From bdb6e252f55c3a4d3eba42f6d5aa4cfb11616072 Mon Sep 17 00:00:00 2001 From: Mike Madeja Date: Mon, 23 Mar 2026 21:58:49 -0500 Subject: [PATCH 1/3] update various things --- PiHoleShell/Public/Actions.ps1 | 12 ++--- PiHoleShell/Public/Authentication.ps1 | 7 +-- PiHoleShell/Public/Config.ps1 | 2 +- PiHoleShell/Public/DnsControl.ps1 | 5 +- PiHoleShell/Public/FTLInformation.ps1 | 4 +- PiHoleShell/Public/GroupManagement.ps1 | 42 ++++++++++++---- PiHoleShell/Public/ListManagement.ps1 | 69 ++++++++++++++++++++++---- PiHoleShell/Public/Metrics.ps1 | 3 +- 8 files changed, 106 insertions(+), 38 deletions(-) diff --git a/PiHoleShell/Public/Actions.ps1 b/PiHoleShell/Public/Actions.ps1 index 518eb26..50b53c6 100644 --- a/PiHoleShell/Public/Actions.ps1 +++ b/PiHoleShell/Public/Actions.ps1 @@ -1,11 +1,11 @@ function Update-PiHoleActionsGravity { <# .SYNOPSIS -https://ftl.pi-hole.net/master/docs/#post-/action/gravity +Update Pi-hole's adlists by running pihole -g. The output of the process is streamed with chunked encoding. Use the optional color query parameter to include ANSI color escape codes in the output. #> #Work In Progress - [CmdletBinding(SupportsShouldProcess = $true)] + [CmdletBinding(SupportsShouldProcess = $true, HelpUri = 'https://ftl.pi-hole.net/master/docs/#post-/action/gravity')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] param ( [Parameter(Mandatory = $true)] @@ -59,7 +59,7 @@ https://ftl.pi-hole.net/master/docs/#post-/action/gravity function Invoke-PiHoleFlushNetwork { <# .SYNOPSIS -https://ftl.pi-hole.net/master/docs/#post-/action/flush/network +Flushes the network table. This includes removing both all known devices and their associated addresses. .DESCRIPTION Flushes the Pi-hole log file (/var/log/pihole/pihole.log). @@ -79,7 +79,7 @@ This will dump the response instead of the formatted object .EXAMPLE Invoke-PiHoleFlushNetwork -PiHoleServer "http://pihole.domain.com:8080" -Password "fjdsjfldsjfkldjslafjskdl" #> - [CmdletBinding()] + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#post-/action/flush/network')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Flushes PiHole logs')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] param ( @@ -127,7 +127,7 @@ Invoke-PiHoleFlushNetwork -PiHoleServer "http://pihole.domain.com:8080" -Passwor function Restart-PiHoleDnsService { <# .SYNOPSIS -https://dns3.local:8489/api/docs/#post-/action/restartdns +Restarts the pihole-FTL service .DESCRIPTION Restarts the Pi-hole DNS resolver (FTL). @@ -147,7 +147,7 @@ This will dump the response instead of the formatted object .EXAMPLE Invoke-PiHoleRestartDns -PiHoleServer "http://pihole.domain.com:8080" -Password "fjdsjfldsjfkldjslafjskdl" #> - [CmdletBinding()] + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#post-/action/restartdns')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Restarts PiHole DNS')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] param ( diff --git a/PiHoleShell/Public/Authentication.ps1 b/PiHoleShell/Public/Authentication.ps1 index a8e4d8a..aaff949 100644 --- a/PiHoleShell/Public/Authentication.ps1 +++ b/PiHoleShell/Public/Authentication.ps1 @@ -32,7 +32,7 @@ function Request-PiHoleAuth { function Get-PiHoleCurrentAuthSession { <# .SYNOPSIS -https://ftl.pi-hole.net/master/docs/#get-/auth +List of all current sessions including their validity and further information about the client such as the IP address and user agent. .PARAMETER PiHoleServer The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" @@ -49,7 +49,7 @@ This will dump the response instead of the formatted object .EXAMPLE Get-PiHoleCurrentAuthSession -PiHoleServer "http://pihole.domain.com:8080" -Password "fjdsjfldsjfkldjslafjskdl" #> - [CmdletBinding()] + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#get-/auth/sessions')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] param ( [Parameter(Mandatory = $true)] @@ -118,7 +118,7 @@ Get-PiHoleCurrentAuthSession -PiHoleServer "http://pihole.domain.com:8080" -Pass function Remove-PiHoleAuthSession { <# .SYNOPSIS -https://ftl.pi-hole.net/master/docs/#get-/auth +Using this endpoint, a session can be deleted by its ID. .PARAMETER PiHoleServer The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" @@ -134,6 +134,7 @@ Get-PiHoleCurrentAuthSession -PiHoleServer "http://pihole.domain.com:8080" -Pass #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Does not change state')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#delete-/auth/session/-id-')] param ( [Parameter(Mandatory = $true)] [System.URI]$PiHoleServer, diff --git a/PiHoleShell/Public/Config.ps1 b/PiHoleShell/Public/Config.ps1 index a938f07..5a2ace8 100644 --- a/PiHoleShell/Public/Config.ps1 +++ b/PiHoleShell/Public/Config.ps1 @@ -1,7 +1,7 @@ function Get-PiHoleConfig { <# .SYNOPSIS -https://TODO +https://ftl.pi-hole.net/master/docs/#get-/config #> #Work In Progress diff --git a/PiHoleShell/Public/DnsControl.ps1 b/PiHoleShell/Public/DnsControl.ps1 index e45c7fb..ab59f11 100644 --- a/PiHoleShell/Public/DnsControl.ps1 +++ b/PiHoleShell/Public/DnsControl.ps1 @@ -1,7 +1,7 @@ function Get-PiHoleDnsBlockingStatus { <# .SYNOPSIS -Get current blocking status +https://ftl.pi-hole.net/master/docs/#get-/config .PARAMETER PiHoleServer The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" @@ -53,7 +53,6 @@ Get-PiHoleDnsBlockingStatus -PiHoleServer "http://pihole.domain.com:8080" -Passw $ObjectFinal += $Object Write-Output $ObjectFinal } - } catch { @@ -71,7 +70,7 @@ Get-PiHoleDnsBlockingStatus -PiHoleServer "http://pihole.domain.com:8080" -Passw function Set-PiHoleDnsBlocking { <# .SYNOPSIS -https://ftl.pi-hole.net/development-v6/docs/#post-/dns/blocking +https://ftl.pi-hole.net/master/docs/#get-/dns/blocking .PARAMETER PiHoleServer The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" diff --git a/PiHoleShell/Public/FTLInformation.ps1 b/PiHoleShell/Public/FTLInformation.ps1 index ad14d80..8ce5c63 100644 --- a/PiHoleShell/Public/FTLInformation.ps1 +++ b/PiHoleShell/Public/FTLInformation.ps1 @@ -76,7 +76,7 @@ This API hook returns a collection of host infos. #> #Work In Progress - [CmdletBinding()] + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#get-/info/host')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] param ( [Parameter(Mandatory = $true)] @@ -141,7 +141,7 @@ Get info about logs for webserver #> #Work In Progress - [CmdletBinding()] + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#get-/logs/webserver')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] param ( [Parameter(Mandatory = $true)] diff --git a/PiHoleShell/Public/GroupManagement.ps1 b/PiHoleShell/Public/GroupManagement.ps1 index a874595..2848868 100644 --- a/PiHoleShell/Public/GroupManagement.ps1 +++ b/PiHoleShell/Public/GroupManagement.ps1 @@ -1,11 +1,10 @@ function Get-PiHoleGroup { <# .SYNOPSIS -https://TODO +Get groups #> - #Work In Progress - [CmdletBinding()] + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#get-/groups/-name-')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] param ( [Parameter(Mandatory = $true)] @@ -87,11 +86,10 @@ https://TODO function New-PiHoleGroup { <# .SYNOPSIS -https://TODO +Creates a new group in the groups object. #> - #Work In Progress - [CmdletBinding()] + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#post-/groups')] [Diagnostics.CodeAnalysis.SuppressMessage("PSUseShouldProcessForStateChangingFunctions", "", Justification = "Ignoring for now")] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] param ( @@ -169,12 +167,24 @@ https://TODO function Update-PiHoleGroup { <# .SYNOPSIS -https://TODO +Items may be updated by replacing them. + +.PARAMETER PiHoleServer +The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" + +.PARAMETER Password +The API Password you generated from your PiHole server + +.PARAMETER IgnoreSsl +Set to $true to skip SSL certificate validation + +.PARAMETER RawOutput +This will dump the response instead of the formatted object #> - #Work In Progress [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] [Diagnostics.CodeAnalysis.SuppressMessage("PSUseShouldProcessForStateChangingFunctions", "", Justification = "Ignoring for now")] + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#put-/groups/-name-')] param ( [Parameter(Mandatory = $true)] [System.URI]$PiHoleServer, @@ -274,11 +284,23 @@ https://TODO function Remove-PiHoleGroup { <# .SYNOPSIS -https://TODO +Delete group + +.PARAMETER PiHoleServer +The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" + +.PARAMETER Password +The API Password you generated from your PiHole server + +.PARAMETER IgnoreSsl +Set to $true to skip SSL certificate validation + +.PARAMETER RawOutput +This will dump the response instead of the formatted object #> #Work In Progress - [CmdletBinding()] + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#delete-/groups/-name-')] [Diagnostics.CodeAnalysis.SuppressMessage("PSUseShouldProcessForStateChangingFunctions", "", Justification = "Ignoring for now")] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] param ( diff --git a/PiHoleShell/Public/ListManagement.ps1 b/PiHoleShell/Public/ListManagement.ps1 index c50efce..7ed7747 100644 --- a/PiHoleShell/Public/ListManagement.ps1 +++ b/PiHoleShell/Public/ListManagement.ps1 @@ -1,11 +1,23 @@ function Get-PiHoleList { <# .SYNOPSIS -https://TODO +Get lists + +.PARAMETER PiHoleServer +The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" + +.PARAMETER Password +The API Password you generated from your PiHole server + +.PARAMETER IgnoreSsl +Set to $true to skip SSL certificate validation + +.PARAMETER RawOutput +This will dump the response instead of the formatted object #> #Work In Progress - [CmdletBinding()] + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#get-/lists/-list-')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] param ( [Parameter(Mandatory = $true)] @@ -89,11 +101,23 @@ https://TODO function Search-PiHoleListDomain { <# .SYNOPSIS -https://TODO +Search domains in Pi-hole's lists + +.PARAMETER PiHoleServer +The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" + +.PARAMETER Password +The API Password you generated from your PiHole server + +.PARAMETER IgnoreSsl +Set to $true to skip SSL certificate validation + +.PARAMETER RawOutput +This will dump the response instead of the formatted object #> #Work In Progress - [CmdletBinding()] + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#get-/search/-domain-')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] param ( [Parameter(Mandatory = $true)] @@ -154,11 +178,23 @@ https://TODO function Add-PiHoleList { <# .SYNOPSIS -https://TODO +Add new list + +.PARAMETER PiHoleServer +The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" + +.PARAMETER Password +The API Password you generated from your PiHole server + +.PARAMETER IgnoreSsl +Set to $true to skip SSL certificate validation + +.PARAMETER RawOutput +This will dump the response instead of the formatted object #> #Work In Progress - [CmdletBinding()] + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#post-/lists')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] param ( [Parameter(Mandatory = $true)] @@ -274,11 +310,23 @@ https://TODO function Remove-PiHoleList { <# .SYNOPSIS -https://TODO +Deletes multiple lists in the lists object. + +.PARAMETER PiHoleServer +The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" + +.PARAMETER Password +The API Password you generated from your PiHole server + +.PARAMETER IgnoreSsl +Set to $true to skip SSL certificate validation + +.PARAMETER RawOutput +This will dump the response instead of the formatted objec #> #Work In Progress (NEED TO FINISH) - [CmdletBinding(SupportsShouldProcess = $true)] + [CmdletBinding(SupportsShouldProcess = $true, HelpUri = 'https://ftl.pi-hole.net/master/docs/#post-/lists-batchDelete')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] param ( [Parameter(Mandatory = $true)] @@ -328,8 +376,8 @@ https://TODO else { $ObjectFinal = @() $Object = $null + foreach ($Item in $Response.lists) { - $Object = [PSCustomObject]@{ Address = $Item.address Comment = $Item.comment @@ -348,11 +396,10 @@ https://TODO if ($Object) { $ObjectFinal += $Object } - } + Write-Output $ObjectFinal } - } } diff --git a/PiHoleShell/Public/Metrics.ps1 b/PiHoleShell/Public/Metrics.ps1 index de2119c..3cce171 100644 --- a/PiHoleShell/Public/Metrics.ps1 +++ b/PiHoleShell/Public/Metrics.ps1 @@ -1,7 +1,6 @@ function Get-PiHoleStatsRecentBlocked { <# .SYNOPSIS -Get most recently blocked domain Request most recently blocked domain .PARAMETER PiHoleServer @@ -19,7 +18,7 @@ This will dump the response instead of the formatted object .EXAMPLE Get-PiHoleStatsRecentBlocked -PiHoleServer "http://pihole.domain.com:8080" -Password "fjdsjfldsjfkldjslafjskdl" -MaxResult 20 #> - [CmdletBinding()] + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#get-/stats/recent_blocked')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] param ( [Parameter(Mandatory = $true)] From 9eaee49ab6c14da607dc6036d867ffd3d0893ecf Mon Sep 17 00:00:00 2001 From: Mike Madeja Date: Mon, 23 Mar 2026 22:23:43 -0500 Subject: [PATCH 2/3] updated --- PiHoleShell/PiHoleShell.psm1 | 24 +- PiHoleShell/Public/Actions.ps1 | 193 -------- .../Actions/Invoke-PiHoleFlushNetwork.ps1 | 67 +++ .../Actions/Restart-PiHoleDnsService.ps1 | 67 +++ .../Actions/Update-PiHoleActionsGravity.ps1 | 57 +++ .../Get-PiHoleCurrentAuthSession.ps1} | 92 ---- .../Remove-PiHoleAuthSession.ps1 | 60 +++ .../Authentication/Request-PiHoleAuth.ps1 | 30 ++ .../Get-PiHoleConfig.ps1} | 0 .../Get-PiHoleDnsBlockingStatus.ps1 | 68 +++ .../Set-PiHoleDnsBlocking.ps1} | 69 --- .../Get-PiHoleInfoHost.ps1} | 60 --- .../FTLInformation/Get-PiHoleLogWebserver.ps1 | 60 +++ PiHoleShell/Public/GroupManagement.ps1 | 363 --------------- .../GroupManagement/Get-PiHoleGroup.ps1 | 84 ++++ .../GroupManagement/New-PiHoleGroup.ps1 | 80 ++++ .../GroupManagement/Remove-PiHoleGroup.ps1 | 80 ++++ .../GroupManagement/Update-PiHoleGroup.ps1 | 116 +++++ PiHoleShell/Public/ListManagement.ps1 | 416 ------------------ .../Public/ListManagement/Add-PiHoleList.ps1 | 131 ++++++ .../Public/ListManagement/Get-PiHoleList.ps1 | 99 +++++ .../ListManagement/Remove-PiHoleList.ps1 | 107 +++++ .../Search-PiHoleListDomain.ps1 | 76 ++++ PiHoleShell/Public/Metrics.ps1 | 392 ----------------- .../Metrics/Get-PiHoleStatsQueryType.ps1 | 54 +++ .../Metrics/Get-PiHoleStatsRecentBlocked.ps1 | 73 +++ .../Public/Metrics/Get-PiHoleStatsSummary.ps1 | 124 ++++++ .../Metrics/Get-PiHoleStatsTopClient.ps1 | 87 ++++ .../Metrics/Get-PiHoleStatsTopDomain.ps1 | 51 +++ .../{Padd.ps1 => Padd/Get-PiHolePadd.ps1} | 0 .../Get-PiHoleTeleporterDownload.ps1} | 0 31 files changed, 1583 insertions(+), 1597 deletions(-) delete mode 100644 PiHoleShell/Public/Actions.ps1 create mode 100644 PiHoleShell/Public/Actions/Invoke-PiHoleFlushNetwork.ps1 create mode 100644 PiHoleShell/Public/Actions/Restart-PiHoleDnsService.ps1 create mode 100644 PiHoleShell/Public/Actions/Update-PiHoleActionsGravity.ps1 rename PiHoleShell/Public/{Authentication.ps1 => Authentication/Get-PiHoleCurrentAuthSession.ps1} (51%) create mode 100644 PiHoleShell/Public/Authentication/Remove-PiHoleAuthSession.ps1 create mode 100644 PiHoleShell/Public/Authentication/Request-PiHoleAuth.ps1 rename PiHoleShell/Public/{Config.ps1 => Config/Get-PiHoleConfig.ps1} (100%) create mode 100644 PiHoleShell/Public/DnsControl/Get-PiHoleDnsBlockingStatus.ps1 rename PiHoleShell/Public/{DnsControl.ps1 => DnsControl/Set-PiHoleDnsBlocking.ps1} (57%) rename PiHoleShell/Public/{FTLInformation.ps1 => FTLInformation/Get-PiHoleInfoHost.ps1} (72%) create mode 100644 PiHoleShell/Public/FTLInformation/Get-PiHoleLogWebserver.ps1 delete mode 100644 PiHoleShell/Public/GroupManagement.ps1 create mode 100644 PiHoleShell/Public/GroupManagement/Get-PiHoleGroup.ps1 create mode 100644 PiHoleShell/Public/GroupManagement/New-PiHoleGroup.ps1 create mode 100644 PiHoleShell/Public/GroupManagement/Remove-PiHoleGroup.ps1 create mode 100644 PiHoleShell/Public/GroupManagement/Update-PiHoleGroup.ps1 delete mode 100644 PiHoleShell/Public/ListManagement.ps1 create mode 100644 PiHoleShell/Public/ListManagement/Add-PiHoleList.ps1 create mode 100644 PiHoleShell/Public/ListManagement/Get-PiHoleList.ps1 create mode 100644 PiHoleShell/Public/ListManagement/Remove-PiHoleList.ps1 create mode 100644 PiHoleShell/Public/ListManagement/Search-PiHoleListDomain.ps1 delete mode 100644 PiHoleShell/Public/Metrics.ps1 create mode 100644 PiHoleShell/Public/Metrics/Get-PiHoleStatsQueryType.ps1 create mode 100644 PiHoleShell/Public/Metrics/Get-PiHoleStatsRecentBlocked.ps1 create mode 100644 PiHoleShell/Public/Metrics/Get-PiHoleStatsSummary.ps1 create mode 100644 PiHoleShell/Public/Metrics/Get-PiHoleStatsTopClient.ps1 create mode 100644 PiHoleShell/Public/Metrics/Get-PiHoleStatsTopDomain.ps1 rename PiHoleShell/Public/{Padd.ps1 => Padd/Get-PiHolePadd.ps1} (100%) rename PiHoleShell/Public/{Teleporter.ps1 => Teleporter/Get-PiHoleTeleporterDownload.ps1} (100%) diff --git a/PiHoleShell/PiHoleShell.psm1 b/PiHoleShell/PiHoleShell.psm1 index 0a5b5d4..9555bf6 100644 --- a/PiHoleShell/PiHoleShell.psm1 +++ b/PiHoleShell/PiHoleShell.psm1 @@ -3,8 +3,8 @@ if ($PSVersionTable.PSEdition -ne 'Core') { } # Get all .ps1 files in the 'Public' directory and dot-source them -$PublicFunctions = Get-ChildItem -Path (Join-Path $PSScriptRoot 'Public') -Filter '*.ps1' -File -$PrivateFunctions = Get-ChildItem -Path (Join-Path $PSScriptRoot 'Private') -Filter '*.ps1' -File +$PublicFunctions = Get-ChildItem -Verbose -Path (Join-Path $PSScriptRoot 'Public') -Filter '*.ps1' -File -Recurse +$PrivateFunctions = Get-ChildItem -Path (Join-Path $PSScriptRoot 'Private') -Filter '*.ps1' -File -Recurse foreach ($File in $PublicFunctions) { . $File.FullName @@ -15,22 +15,22 @@ foreach ($File in $PrivateFunctions) { } Export-ModuleMember -Function @( - #Actions.ps1 - 'Update-PiHoleActionsGravity', 'Invoke-PiHoleFlushNetwork' ` - #Authentication.ps1 + #Actions + 'Update-PiHoleActionsGravity', 'Invoke-PiHoleFlushNetwork', 'Restart-PiHoleDnsService' ` + #Authentication 'Remove-PiHoleCurrentAuthSession' , 'Get-PiHoleCurrentAuthSession', 'Remove-PiHoleAuthSession', ` - #GroupManagement.ps1 + #GroupManagement 'Get-PiHoleGroup', 'New-PiHoleGroup', 'Update-PiHoleGroup', 'Remove-PiHoleGroup', ` - #DnsControl.ps1 + #DnsControl 'Get-PiHoleDnsBlockingStatus', 'Set-PiHoleDnsBlocking', ` - #Config.ps1 + #Config 'Get-PiHoleConfig', 'Get-PiHoleCurrentAuthSession', 'Remove-PiHoleAuthSession', ` - #Padd.ps1 + #Padd 'Get-PiHolePadd', ` - #Metrics.ps1 + #Metrics 'Get-PiHoleStatsRecentBlocked', 'Get-PiHoleStatsQueryType', 'Get-PiHoleStatsTopDomain', 'Get-PiHoleStatsSummary', 'Get-PiHoleStatsTopClient' ` - #ListManagement.ps1 + #ListManagement 'Get-PiHoleList', 'Search-PiHoleListDomain', 'Add-PiHoleList', 'Remove-PiHoleList', ` - #FTLInformation.ps1 + #FTLInformation 'Get-PiHoleInfoMessage', 'Get-PiHoleInfoHost' ) \ No newline at end of file diff --git a/PiHoleShell/Public/Actions.ps1 b/PiHoleShell/Public/Actions.ps1 deleted file mode 100644 index 50b53c6..0000000 --- a/PiHoleShell/Public/Actions.ps1 +++ /dev/null @@ -1,193 +0,0 @@ -function Update-PiHoleActionsGravity { - <# -.SYNOPSIS -Update Pi-hole's adlists by running pihole -g. The output of the process is streamed with chunked encoding. Use the optional color query parameter to include ANSI color escape codes in the output. - - #> - #Work In Progress - [CmdletBinding(SupportsShouldProcess = $true, HelpUri = 'https://ftl.pi-hole.net/master/docs/#post-/action/gravity')] - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] - param ( - [Parameter(Mandatory = $true)] - [System.URI]$PiHoleServer, - [Parameter(Mandatory = $true)] - [string]$Password, - [bool]$IgnoreSsl = $false, - [bool]$RawOutput = $false - ) - try { - $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl - - $Params = @{ - Headers = @{sid = $($Sid) } - Uri = "$($PiHoleServer.OriginalString)/api/action/gravity" - Method = "Post" - SkipCertificateCheck = $IgnoreSsl - ContentType = "application/json" - } - - if ($PSCmdlet.ShouldProcess("Pi-Hole server at $PiHoleServer", "Update gravity actions")) { - $Response = Invoke-RestMethod @Params - } - - if ($RawOutput) { - Write-Output $Response - } - - else { - $ObjectFinal = @() - $Object = $null - if ($Object) { - $ObjectFinal += $Object - } - Write-Output $ObjectFinal - } - } - - catch { - Write-Error -Message $_.Exception.Message - break - } - - finally { - if ($Sid) { - Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl - } - } -} - -function Invoke-PiHoleFlushNetwork { - <# -.SYNOPSIS -Flushes the network table. This includes removing both all known devices and their associated addresses. - -.DESCRIPTION -Flushes the Pi-hole log file (/var/log/pihole/pihole.log). - -.PARAMETER PiHoleServer -The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" - -.PARAMETER Password -The API Password you generated from your PiHole server - -.PARAMETER IgnoreSsl -Set to $true to skip SSL certificate validation - -.PARAMETER RawOutput -This will dump the response instead of the formatted object - -.EXAMPLE -Invoke-PiHoleFlushNetwork -PiHoleServer "http://pihole.domain.com:8080" -Password "fjdsjfldsjfkldjslafjskdl" - #> - [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#post-/action/flush/network')] - [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Flushes PiHole logs')] - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] - param ( - $PiHoleServer, - $Password, - [bool]$IgnoreSsl = $false, - [bool]$RawOutput = $false - ) - - try { - $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl - - $Params = @{ - Headers = @{sid = $($Sid) } - Uri = "$PiHoleServer/api/action/flush/logs" - Method = "Post" - ContentType = "application/json" - SkipCertificateCheck = $IgnoreSsl - } - - $Response = Invoke-RestMethod @Params - - if ($RawOutput) { - Write-Output $Response - } - else { - $Object = [PSCustomObject]@{ - Status = "Flushed" - } - Write-Output $Object - } - } - - catch { - Write-Error -Message $_.Exception.Message - } - - finally { - if ($Sid) { - Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl - } - } -} - -function Restart-PiHoleDnsService { - <# -.SYNOPSIS -Restarts the pihole-FTL service - -.DESCRIPTION -Restarts the Pi-hole DNS resolver (FTL). - -.PARAMETER PiHoleServer -The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" - -.PARAMETER Password -The API Password you generated from your PiHole server - -.PARAMETER IgnoreSsl -Set to $true to skip SSL certificate validation - -.PARAMETER RawOutput -This will dump the response instead of the formatted object - -.EXAMPLE -Invoke-PiHoleRestartDns -PiHoleServer "http://pihole.domain.com:8080" -Password "fjdsjfldsjfkldjslafjskdl" - #> - [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#post-/action/restartdns')] - [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Restarts PiHole DNS')] - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] - param ( - $PiHoleServer, - $Password, - [bool]$IgnoreSsl = $false, - [bool]$RawOutput = $false - ) - - try { - $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl - - $Params = @{ - Headers = @{sid = $($Sid) } - Uri = "$PiHoleServer/api/action/restartdns" - Method = "Post" - ContentType = "application/json" - SkipCertificateCheck = $IgnoreSsl - } - - $Response = Invoke-RestMethod @Params - - if ($RawOutput) { - Write-Output $Response - } - else { - $Object = [PSCustomObject]@{ - Status = "Restarted" - } - Write-Output $Object - } - } - - catch { - Write-Error -Message $_.Exception.Message - } - - finally { - if ($Sid) { - Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl - } - } -} \ No newline at end of file diff --git a/PiHoleShell/Public/Actions/Invoke-PiHoleFlushNetwork.ps1 b/PiHoleShell/Public/Actions/Invoke-PiHoleFlushNetwork.ps1 new file mode 100644 index 0000000..87c0847 --- /dev/null +++ b/PiHoleShell/Public/Actions/Invoke-PiHoleFlushNetwork.ps1 @@ -0,0 +1,67 @@ +function Invoke-PiHoleFlushNetwork { + <# +.SYNOPSIS +Flushes the network table. This includes removing both all known devices and their associated addresses. + +.DESCRIPTION +Flushes the Pi-hole log file (/var/log/pihole/pihole.log). + +.PARAMETER PiHoleServer +The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" + +.PARAMETER Password +The API Password you generated from your PiHole server + +.PARAMETER IgnoreSsl +Set to $true to skip SSL certificate validation + +.PARAMETER RawOutput +This will dump the response instead of the formatted object + +.EXAMPLE +Invoke-PiHoleFlushNetwork -PiHoleServer "http://pihole.domain.com:8080" -Password "fjdsjfldsjfkldjslafjskdl" + #> + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#post-/action/flush/network')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Flushes PiHole logs')] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + param ( + $PiHoleServer, + $Password, + [bool]$IgnoreSsl = $false, + [bool]$RawOutput = $false + ) + + try { + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$PiHoleServer/api/action/flush/logs" + Method = "Post" + ContentType = "application/json" + SkipCertificateCheck = $IgnoreSsl + } + + $Response = Invoke-RestMethod @Params + + if ($RawOutput) { + Write-Output $Response + } + else { + $Object = [PSCustomObject]@{ + Status = "Flushed" + } + Write-Output $Object + } + } + + catch { + Write-Error -Message $_.Exception.Message + } + + finally { + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } + } +} \ No newline at end of file diff --git a/PiHoleShell/Public/Actions/Restart-PiHoleDnsService.ps1 b/PiHoleShell/Public/Actions/Restart-PiHoleDnsService.ps1 new file mode 100644 index 0000000..7ee1e4a --- /dev/null +++ b/PiHoleShell/Public/Actions/Restart-PiHoleDnsService.ps1 @@ -0,0 +1,67 @@ +function Restart-PiHoleDnsService { + <# +.SYNOPSIS +Restarts the pihole-FTL service + +.DESCRIPTION +Restarts the Pi-hole DNS resolver (FTL). + +.PARAMETER PiHoleServer +The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" + +.PARAMETER Password +The API Password you generated from your PiHole server + +.PARAMETER IgnoreSsl +Set to $true to skip SSL certificate validation + +.PARAMETER RawOutput +This will dump the response instead of the formatted object + +.EXAMPLE +Invoke-PiHoleRestartDns -PiHoleServer "http://pihole.domain.com:8080" -Password "fjdsjfldsjfkldjslafjskdl" + #> + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#post-/action/restartdns')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Restarts PiHole DNS')] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + param ( + $PiHoleServer, + $Password, + [bool]$IgnoreSsl = $false, + [bool]$RawOutput = $false + ) + + try { + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$PiHoleServer/api/action/restartdns" + Method = "Post" + ContentType = "application/json" + SkipCertificateCheck = $IgnoreSsl + } + + $Response = Invoke-RestMethod @Params + + if ($RawOutput) { + Write-Output $Response + } + else { + $Object = [PSCustomObject]@{ + Status = "Restarted" + } + Write-Output $Object + } + } + + catch { + Write-Error -Message $_.Exception.Message + } + + finally { + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } + } +} \ No newline at end of file diff --git a/PiHoleShell/Public/Actions/Update-PiHoleActionsGravity.ps1 b/PiHoleShell/Public/Actions/Update-PiHoleActionsGravity.ps1 new file mode 100644 index 0000000..8d392db --- /dev/null +++ b/PiHoleShell/Public/Actions/Update-PiHoleActionsGravity.ps1 @@ -0,0 +1,57 @@ +function Update-PiHoleActionsGravity { + <# +.SYNOPSIS +Update Pi-hole's adlists by running pihole -g. The output of the process is streamed with chunked encoding. Use the optional color query parameter to include ANSI color escape codes in the output. + + #> + #Work In Progress + [CmdletBinding(SupportsShouldProcess = $true, HelpUri = 'https://ftl.pi-hole.net/master/docs/#post-/action/gravity')] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + param ( + [Parameter(Mandatory = $true)] + [System.URI]$PiHoleServer, + [Parameter(Mandatory = $true)] + [string]$Password, + [bool]$IgnoreSsl = $false, + [bool]$RawOutput = $false + ) + try { + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$($PiHoleServer.OriginalString)/api/action/gravity" + Method = "Post" + SkipCertificateCheck = $IgnoreSsl + ContentType = "application/json" + } + + if ($PSCmdlet.ShouldProcess("Pi-Hole server at $PiHoleServer", "Update gravity actions")) { + $Response = Invoke-RestMethod @Params + } + + if ($RawOutput) { + Write-Output $Response + } + + else { + $ObjectFinal = @() + $Object = $null + if ($Object) { + $ObjectFinal += $Object + } + Write-Output $ObjectFinal + } + } + + catch { + Write-Error -Message $_.Exception.Message + break + } + + finally { + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } + } +} \ No newline at end of file diff --git a/PiHoleShell/Public/Authentication.ps1 b/PiHoleShell/Public/Authentication/Get-PiHoleCurrentAuthSession.ps1 similarity index 51% rename from PiHoleShell/Public/Authentication.ps1 rename to PiHoleShell/Public/Authentication/Get-PiHoleCurrentAuthSession.ps1 index aaff949..2ae3603 100644 --- a/PiHoleShell/Public/Authentication.ps1 +++ b/PiHoleShell/Public/Authentication/Get-PiHoleCurrentAuthSession.ps1 @@ -1,34 +1,3 @@ -function Request-PiHoleAuth { - #INTERNAL FUNCTION - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] - param ( - [CmdletBinding()] - [System.URI]$PiHoleServer, - [string]$Password, - [bool]$IgnoreSsl = $false - ) - - try { - $Params = @{ - Uri = "$($PiHoleServer.OriginalString)/api/auth" - Method = "Post" - ContentType = "application/json" - SkipCertificateCheck = $IgnoreSsl - Body = @{password = $Password } | ConvertTo-Json - } - - $Response = Invoke-RestMethod @Params -Verbose: $false - Write-Verbose -Message "Request-PiHoleAuth Successful!" - - Write-Output $Response.session.sid - } - - catch { - Write-Error -Message $_.Exception.Message - break - } -} - function Get-PiHoleCurrentAuthSession { <# .SYNOPSIS @@ -113,65 +82,4 @@ Get-PiHoleCurrentAuthSession -PiHoleServer "http://pihole.domain.com:8080" -Pass Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid } } -} - -function Remove-PiHoleAuthSession { - <# -.SYNOPSIS -Using this endpoint, a session can be deleted by its ID. - -.PARAMETER PiHoleServer -The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" - -.PARAMETER Password -The API Password you generated from your PiHole server - -.PARAMETER IgnoreSsl -Ignore SSL when interacting with the PiHole API - -.EXAMPLE -Get-PiHoleCurrentAuthSession -PiHoleServer "http://pihole.domain.com:8080" -Password "fjdsjfldsjfkldjslafjskdl" - #> - [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Does not change state')] - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] - [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#delete-/auth/session/-id-')] - param ( - [Parameter(Mandatory = $true)] - [System.URI]$PiHoleServer, - [Parameter(Mandatory = $true)] - [string]$Password, - [bool]$IgnoreSsl = $false, - [int]$Id - ) - - try { - $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl - $Params = @{ - Headers = @{sid = $($Sid) } - Uri = "$($PiHoleServer.OriginalString)/api/auth/session/$Id" - Method = "Delete" - SkipCertificateCheck = $IgnoreSsl - ContentType = "application/json" - } - - Invoke-RestMethod @Params - - $ObjectFinal = @() - $Object = [PSCustomObject]@{ - Id = $Id - Status = "Removed" - } - $ObjectFinal = $Object - Write-Output $ObjectFinal - } - - catch { - Write-Error -Message $_.Exception.Message - } - - finally { - if ($Sid) { - Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl - } - } } \ No newline at end of file diff --git a/PiHoleShell/Public/Authentication/Remove-PiHoleAuthSession.ps1 b/PiHoleShell/Public/Authentication/Remove-PiHoleAuthSession.ps1 new file mode 100644 index 0000000..c448ad7 --- /dev/null +++ b/PiHoleShell/Public/Authentication/Remove-PiHoleAuthSession.ps1 @@ -0,0 +1,60 @@ +function Remove-PiHoleAuthSession { + <# +.SYNOPSIS +Using this endpoint, a session can be deleted by its ID. + +.PARAMETER PiHoleServer +The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" + +.PARAMETER Password +The API Password you generated from your PiHole server + +.PARAMETER IgnoreSsl +Ignore SSL when interacting with the PiHole API + +.EXAMPLE +Get-PiHoleCurrentAuthSession -PiHoleServer "http://pihole.domain.com:8080" -Password "fjdsjfldsjfkldjslafjskdl" + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Does not change state')] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#delete-/auth/session/-id-')] + param ( + [Parameter(Mandatory = $true)] + [System.URI]$PiHoleServer, + [Parameter(Mandatory = $true)] + [string]$Password, + [bool]$IgnoreSsl = $false, + [int]$Id + ) + + try { + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$($PiHoleServer.OriginalString)/api/auth/session/$Id" + Method = "Delete" + SkipCertificateCheck = $IgnoreSsl + ContentType = "application/json" + } + + Invoke-RestMethod @Params + + $ObjectFinal = @() + $Object = [PSCustomObject]@{ + Id = $Id + Status = "Removed" + } + $ObjectFinal = $Object + Write-Output $ObjectFinal + } + + catch { + Write-Error -Message $_.Exception.Message + } + + finally { + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } + } +} \ No newline at end of file diff --git a/PiHoleShell/Public/Authentication/Request-PiHoleAuth.ps1 b/PiHoleShell/Public/Authentication/Request-PiHoleAuth.ps1 new file mode 100644 index 0000000..aaec1a4 --- /dev/null +++ b/PiHoleShell/Public/Authentication/Request-PiHoleAuth.ps1 @@ -0,0 +1,30 @@ +function Request-PiHoleAuth { + #INTERNAL FUNCTION + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + param ( + [CmdletBinding()] + [System.URI]$PiHoleServer, + [string]$Password, + [bool]$IgnoreSsl = $false + ) + + try { + $Params = @{ + Uri = "$($PiHoleServer.OriginalString)/api/auth" + Method = "Post" + ContentType = "application/json" + SkipCertificateCheck = $IgnoreSsl + Body = @{password = $Password } | ConvertTo-Json + } + + $Response = Invoke-RestMethod @Params -Verbose: $false + Write-Verbose -Message "Request-PiHoleAuth Successful!" + + Write-Output $Response.session.sid + } + + catch { + Write-Error -Message $_.Exception.Message + break + } +} \ No newline at end of file diff --git a/PiHoleShell/Public/Config.ps1 b/PiHoleShell/Public/Config/Get-PiHoleConfig.ps1 similarity index 100% rename from PiHoleShell/Public/Config.ps1 rename to PiHoleShell/Public/Config/Get-PiHoleConfig.ps1 diff --git a/PiHoleShell/Public/DnsControl/Get-PiHoleDnsBlockingStatus.ps1 b/PiHoleShell/Public/DnsControl/Get-PiHoleDnsBlockingStatus.ps1 new file mode 100644 index 0000000..e27a504 --- /dev/null +++ b/PiHoleShell/Public/DnsControl/Get-PiHoleDnsBlockingStatus.ps1 @@ -0,0 +1,68 @@ +function Get-PiHoleDnsBlockingStatus { + <# +.SYNOPSIS +https://ftl.pi-hole.net/master/docs/#get-/config + +.PARAMETER PiHoleServer +The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" + +.PARAMETER Password +The API Password you generated from your PiHole server + +.PARAMETER IgnoreSsl +Ignore SSL when interacting with the PiHole API + +.PARAMETER RawOutput +This will dump the response instead of the formatted object + +.EXAMPLE +Get-PiHoleDnsBlockingStatus -PiHoleServer "http://pihole.domain.com:8080" -Password "fjdsjfldsjfkldjslafjskdl" + #> + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + param ( + [Parameter(Mandatory = $true)] + [System.URI]$PiHoleServer, + [Parameter(Mandatory = $true)] + [string]$Password, + [bool]$IgnoreSsl = $false, + [bool]$RawOutput = $false + ) + try { + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$($PiHoleServer.OriginalString)/api/dns/blocking" + Method = "Get" + ContentType = "application/json" + SkipCertificateCheck = $IgnoreSsl + } + + $Data = Invoke-RestMethod @Params + + if ($RawOutput) { + Write-Output $Data + } + else { + $ObjectFinal = @() + $Object = [PSCustomObject]@{ + Blocking = $Data.blocking + Timer = (Format-PiHoleSecond -TimeInSeconds $Data.timer).TimeInSeconds + } + + $ObjectFinal += $Object + Write-Output $ObjectFinal + } + } + + catch { + Write-Error -Message $_.Exception.Message + break + } + + finally { + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } + } +} \ No newline at end of file diff --git a/PiHoleShell/Public/DnsControl.ps1 b/PiHoleShell/Public/DnsControl/Set-PiHoleDnsBlocking.ps1 similarity index 57% rename from PiHoleShell/Public/DnsControl.ps1 rename to PiHoleShell/Public/DnsControl/Set-PiHoleDnsBlocking.ps1 index ab59f11..ab64125 100644 --- a/PiHoleShell/Public/DnsControl.ps1 +++ b/PiHoleShell/Public/DnsControl/Set-PiHoleDnsBlocking.ps1 @@ -1,72 +1,3 @@ -function Get-PiHoleDnsBlockingStatus { - <# -.SYNOPSIS -https://ftl.pi-hole.net/master/docs/#get-/config - -.PARAMETER PiHoleServer -The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" - -.PARAMETER Password -The API Password you generated from your PiHole server - -.PARAMETER IgnoreSsl -Ignore SSL when interacting with the PiHole API - -.PARAMETER RawOutput -This will dump the response instead of the formatted object - -.EXAMPLE -Get-PiHoleDnsBlockingStatus -PiHoleServer "http://pihole.domain.com:8080" -Password "fjdsjfldsjfkldjslafjskdl" - #> - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] - param ( - [Parameter(Mandatory = $true)] - [System.URI]$PiHoleServer, - [Parameter(Mandatory = $true)] - [string]$Password, - [bool]$IgnoreSsl = $false, - [bool]$RawOutput = $false - ) - try { - $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl - - $Params = @{ - Headers = @{sid = $($Sid) } - Uri = "$($PiHoleServer.OriginalString)/api/dns/blocking" - Method = "Get" - ContentType = "application/json" - SkipCertificateCheck = $IgnoreSsl - } - - $Data = Invoke-RestMethod @Params - - if ($RawOutput) { - Write-Output $Data - } - else { - $ObjectFinal = @() - $Object = [PSCustomObject]@{ - Blocking = $Data.blocking - Timer = (Format-PiHoleSecond -TimeInSeconds $Data.timer).TimeInSeconds - } - - $ObjectFinal += $Object - Write-Output $ObjectFinal - } - } - - catch { - Write-Error -Message $_.Exception.Message - break - } - - finally { - if ($Sid) { - Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl - } - } -} - function Set-PiHoleDnsBlocking { <# .SYNOPSIS diff --git a/PiHoleShell/Public/FTLInformation.ps1 b/PiHoleShell/Public/FTLInformation/Get-PiHoleInfoHost.ps1 similarity index 72% rename from PiHoleShell/Public/FTLInformation.ps1 rename to PiHoleShell/Public/FTLInformation/Get-PiHoleInfoHost.ps1 index 8ce5c63..e425290 100644 --- a/PiHoleShell/Public/FTLInformation.ps1 +++ b/PiHoleShell/Public/FTLInformation/Get-PiHoleInfoHost.ps1 @@ -127,66 +127,6 @@ This API hook returns a collection of host infos. break } - finally { - if ($Sid) { - Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl - } - } -} - -function Get-PiHoleLogWebserver { - <# -.SYNOPSIS -Get info about logs for webserver - - #> - #Work In Progress - [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#get-/logs/webserver')] - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] - param ( - [Parameter(Mandatory = $true)] - [System.URI]$PiHoleServer, - [Parameter(Mandatory = $true)] - [string]$Password, - [int]$NextID, - [bool]$IgnoreSsl = $false, - [bool]$RawOutput = $false - ) - try { - $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl - - if ($NextID) { - $Uri = "$($PiHoleServer.OriginalString)/api/logs/webserver?nextId=$NextId" - - } - else { - $Uri = "$($PiHoleServer.OriginalString)/api/logs/webserver" - } - - $Params = @{ - Headers = @{sid = $($Sid) } - Uri = $Uri - Method = "Get" - SkipCertificateCheck = $IgnoreSsl - ContentType = "application/json" - } - - $Response = Invoke-RestMethod @Params - - if ($RawOutput) { - Write-Output $Response - } - - else { - #$ObjectFinal = @() - } - } - - catch { - Write-Error -Message $_.Exception.Message - break - } - finally { if ($Sid) { Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl diff --git a/PiHoleShell/Public/FTLInformation/Get-PiHoleLogWebserver.ps1 b/PiHoleShell/Public/FTLInformation/Get-PiHoleLogWebserver.ps1 new file mode 100644 index 0000000..16ab4df --- /dev/null +++ b/PiHoleShell/Public/FTLInformation/Get-PiHoleLogWebserver.ps1 @@ -0,0 +1,60 @@ + +function Get-PiHoleLogWebserver { + <# +.SYNOPSIS +Get info about logs for webserver + + #> + #Work In Progress + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#get-/logs/webserver')] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + param ( + [Parameter(Mandatory = $true)] + [System.URI]$PiHoleServer, + [Parameter(Mandatory = $true)] + [string]$Password, + [int]$NextID, + [bool]$IgnoreSsl = $false, + [bool]$RawOutput = $false + ) + try { + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + + if ($NextID) { + $Uri = "$($PiHoleServer.OriginalString)/api/logs/webserver?nextId=$NextId" + + } + else { + $Uri = "$($PiHoleServer.OriginalString)/api/logs/webserver" + } + + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = $Uri + Method = "Get" + SkipCertificateCheck = $IgnoreSsl + ContentType = "application/json" + } + + $Response = Invoke-RestMethod @Params + + if ($RawOutput) { + Write-Output $Response + } + + else { + #$ObjectFinal = @() + } + } + + catch { + Write-Error -Message $_.Exception.Message + break + } + + finally { + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } + } +} \ No newline at end of file diff --git a/PiHoleShell/Public/GroupManagement.ps1 b/PiHoleShell/Public/GroupManagement.ps1 deleted file mode 100644 index 2848868..0000000 --- a/PiHoleShell/Public/GroupManagement.ps1 +++ /dev/null @@ -1,363 +0,0 @@ -function Get-PiHoleGroup { - <# -.SYNOPSIS -Get groups - - #> - [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#get-/groups/-name-')] - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] - param ( - [Parameter(Mandatory = $true)] - [System.URI]$PiHoleServer, - [Parameter(Mandatory = $true)] - $Password, - $GroupName = $null, - [bool]$IgnoreSsl = $false, - [bool]$RawOutput = $false - ) - try { - $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl - - $Params = @{ - Headers = @{sid = $($Sid) } - Uri = "$($PiHoleServer.OriginalString)/api/groups" - Method = "Get" - SkipCertificateCheck = $IgnoreSsl - ContentType = "application/json" - } - - $Response = Invoke-RestMethod @Params - - if ($RawOutput) { - Write-Output $Response - } - - else { - $ObjectFinal = @() - foreach ($Item in $Response.Groups) { - $Object = $null - $Object = [PSCustomObject]@{ - Name = $Item.name - Comment = $Item.comment - Enabled = $Item.enabled - Id = $Item.id - DateAdded = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_added).LocalTime - DateModified = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_modified).LocalTime - - } - Write-Verbose -Message "Name - $($Item.name)" - Write-Verbose -Message "Comment - $($Item.comment)" - Write-Verbose -Message "Enabled - $($Item.enabled)" - Write-Verbose -Message "Id - $($Item.id)" - Write-Verbose -Message "Date Added - $($Item.date_added)" - Write-Verbose -Message "Date Date Modified - $(($Item.date_modified))" - $ObjectFinal += $Object - } - - if ($GroupName) { - $GroupNameObject = $ObjectFinal | Where-Object { $_.Name -eq $GroupName } - if ($GroupNameObject) { - Write-Output $GroupNameObject - } - else { - Write-Warning "Did not find $GroupName on $PiHoleServer" - } - } - - else { - Write-Output $ObjectFinal - } - - } - } - - catch { - Write-Error -Message $_.Exception.Message - break - } - - finally { - if ($Sid) { - Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl - } - } -} - -function New-PiHoleGroup { - <# -.SYNOPSIS -Creates a new group in the groups object. - - #> - [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#post-/groups')] - [Diagnostics.CodeAnalysis.SuppressMessage("PSUseShouldProcessForStateChangingFunctions", "", Justification = "Ignoring for now")] - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] - param ( - [Parameter(Mandatory = $true)] - [System.URI]$PiHoleServer, - [Parameter(Mandatory = $true)] - [string]$Password, - [Parameter(Mandatory = $true)] - [string]$GroupName, - [string]$Comment = $null, - [bool]$Enabled = $true, - [bool]$IgnoreSsl = $false, - [bool]$RawOutput = $false - - ) - try { - $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl - - $GetGroupName = Get-PiHoleGroup -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl -GroupName $GroupName - - if ($GetGroupName) { - Write-Warning -Message "Group $GroupName already exists" - } - - else { - $Body = @{ - comment = $Comment - enabled = $Enabled - name = $GroupName - } - - $Params = @{ - Headers = @{sid = $($Sid) } - Uri = "$($PiHoleServer.OriginalString)/api/groups" - Method = "Post" - SkipCertificateCheck = $IgnoreSsl - ContentType = "application/json" - Body = $Body | ConvertTo-Json -Depth 10 - } - - $Response = Invoke-RestMethod @Params - - if ($RawOutput) { - Write-Output $Response - } - - else { - $ObjectFinal = @() - $Object = [PSCustomObject]@{ - Name = $GroupName - Comment = $Comment - Enabled = $Enabled - } - Write-Verbose -Message "Name - $($Object.GroupName)" - Write-Verbose -Message "Comment - $($Object.Comment)" - Write-Verbose -Message "Enabled - $($Object.Enabled)" - $ObjectFinal = $Object - } - Write-Output $ObjectFinal - } - } - - catch { - Write-Error -Message $_.Exception.Message - break - } - - finally { - if ($Sid) { - Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl - } - } -} - -function Update-PiHoleGroup { - <# -.SYNOPSIS -Items may be updated by replacing them. - -.PARAMETER PiHoleServer -The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" - -.PARAMETER Password -The API Password you generated from your PiHole server - -.PARAMETER IgnoreSsl -Set to $true to skip SSL certificate validation - -.PARAMETER RawOutput -This will dump the response instead of the formatted object - - #> - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] - [Diagnostics.CodeAnalysis.SuppressMessage("PSUseShouldProcessForStateChangingFunctions", "", Justification = "Ignoring for now")] - [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#put-/groups/-name-')] - param ( - [Parameter(Mandatory = $true)] - [System.URI]$PiHoleServer, - [Parameter(Mandatory = $true)] - [string]$Password, - [Parameter(Mandatory = $true)] - [string]$GroupName, - [string]$Comment = $null, - [bool]$Enabled, - [bool]$IgnoreSsl = $false, - [bool]$RawOutput = $false - - ) - #Enabled is weird here.. look into it - try { - $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl - - $Body = @{ - name = $GroupName - } - - $GetGroupName = Get-PiHoleGroup -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl -GroupName $GroupName - - if ($Comment -eq $null -and $Enabled -eq $null) { - Write-Warning -Message "failed" - throw -Message "To update $GroupName, you must either use the Comment and/or Enabled parameter" - } - - if ($Comment) { - $Body += @{ - comment = $Comment - } - } - if ($Enabled -ne $null) { - $Body += @{ - enabled = $Enabled - } - } - else { - switch ($GetGroupStatus) { - "True" { - $true - } - "False" { - $false - } - } - - $Body += @{ - enabled = $GetGroupStatus - } - } - - $Params = @{ - Headers = @{sid = $($Sid) } - Uri = "$($PiHoleServer.OriginalString)/api/groups/$GroupName" - Method = "Put" - SkipCertificateCheck = $IgnoreSsl - ContentType = "application/json" - Body = $Body | ConvertTo-Json -Depth 10 - } - - if ($GetGroupName) { - $Response = Invoke-RestMethod @Params - if ($RawOutput) { - Write-Output $Response - } - else { - $ObjectFinal = @() - $Object = [PSCustomObject]@{ - Name = $GroupName - Comment = $Comment - Enabled = $Enabled - } - Write-Verbose -Message "Name - $($Object.GroupName)" - Write-Verbose -Message "Comment - $($Object.Comment)" - Write-Verbose -Message "Enabled - $($Object.Enabled)" - $ObjectFinal = $Object - } - Write-Output $ObjectFinal - - } - } - - catch { - Write-Error -Message $_.Exception.Message - break - } - - finally { - if ($Sid) { - Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl - } - } -} - -function Remove-PiHoleGroup { - <# -.SYNOPSIS -Delete group - -.PARAMETER PiHoleServer -The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" - -.PARAMETER Password -The API Password you generated from your PiHole server - -.PARAMETER IgnoreSsl -Set to $true to skip SSL certificate validation - -.PARAMETER RawOutput -This will dump the response instead of the formatted object - - #> - #Work In Progress - [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#delete-/groups/-name-')] - [Diagnostics.CodeAnalysis.SuppressMessage("PSUseShouldProcessForStateChangingFunctions", "", Justification = "Ignoring for now")] - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] - param ( - [Parameter(Mandatory = $true)] - [System.URI]$PiHoleServer, - [Parameter(Mandatory = $true)] - [string]$Password, - [Parameter(Mandatory = $true)] - [string]$GroupName, - [bool]$IgnoreSsl = $false, - [bool]$RawOutput = $false - - ) - try { - $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl - - $Body = @{ - name = $GroupName - } - - $Params = @{ - Headers = @{sid = $($Sid) } - Uri = "$($PiHoleServer.OriginalString)/api/groups/$GroupName" - Method = "Delete" - SkipCertificateCheck = $IgnoreSsl - ContentType = "application/json" - Body = $Body | ConvertTo-Json -Depth 10 - } - $GetGroupName = Get-PiHoleGroup -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl -GroupName $GroupName - - if ($GetGroupName) { - $Response = Invoke-RestMethod @Params - - if ($RawOutput) { - Write-Output $Response - } - else { - $ObjectFinal = @() - $Object = [PSCustomObject]@{ - Name = $GroupName - Status = "Deleted" - } - $ObjectFinal = $Object - } - Write-Verbose -Message "Deleted $($Object.GroupName)" - Write-Output $ObjectFinal - } - } - - catch { - Write-Error -Message $_.Exception.Message - break - } - - finally { - if ($Sid) { - Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl - } - } -} \ No newline at end of file diff --git a/PiHoleShell/Public/GroupManagement/Get-PiHoleGroup.ps1 b/PiHoleShell/Public/GroupManagement/Get-PiHoleGroup.ps1 new file mode 100644 index 0000000..5bd952c --- /dev/null +++ b/PiHoleShell/Public/GroupManagement/Get-PiHoleGroup.ps1 @@ -0,0 +1,84 @@ +function Get-PiHoleGroup { + <# +.SYNOPSIS +Get groups + + #> + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#get-/groups/-name-')] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + param ( + [Parameter(Mandatory = $true)] + [System.URI]$PiHoleServer, + [Parameter(Mandatory = $true)] + $Password, + $GroupName = $null, + [bool]$IgnoreSsl = $false, + [bool]$RawOutput = $false + ) + try { + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$($PiHoleServer.OriginalString)/api/groups" + Method = "Get" + SkipCertificateCheck = $IgnoreSsl + ContentType = "application/json" + } + + $Response = Invoke-RestMethod @Params + + if ($RawOutput) { + Write-Output $Response + } + + else { + $ObjectFinal = @() + foreach ($Item in $Response.Groups) { + $Object = $null + $Object = [PSCustomObject]@{ + Name = $Item.name + Comment = $Item.comment + Enabled = $Item.enabled + Id = $Item.id + DateAdded = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_added).LocalTime + DateModified = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_modified).LocalTime + + } + Write-Verbose -Message "Name - $($Item.name)" + Write-Verbose -Message "Comment - $($Item.comment)" + Write-Verbose -Message "Enabled - $($Item.enabled)" + Write-Verbose -Message "Id - $($Item.id)" + Write-Verbose -Message "Date Added - $($Item.date_added)" + Write-Verbose -Message "Date Date Modified - $(($Item.date_modified))" + $ObjectFinal += $Object + } + + if ($GroupName) { + $GroupNameObject = $ObjectFinal | Where-Object { $_.Name -eq $GroupName } + if ($GroupNameObject) { + Write-Output $GroupNameObject + } + else { + Write-Warning "Did not find $GroupName on $PiHoleServer" + } + } + + else { + Write-Output $ObjectFinal + } + + } + } + + catch { + Write-Error -Message $_.Exception.Message + break + } + + finally { + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } + } +} \ No newline at end of file diff --git a/PiHoleShell/Public/GroupManagement/New-PiHoleGroup.ps1 b/PiHoleShell/Public/GroupManagement/New-PiHoleGroup.ps1 new file mode 100644 index 0000000..50458e0 --- /dev/null +++ b/PiHoleShell/Public/GroupManagement/New-PiHoleGroup.ps1 @@ -0,0 +1,80 @@ +function New-PiHoleGroup { + <# +.SYNOPSIS +Creates a new group in the groups object. + + #> + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#post-/groups')] + [Diagnostics.CodeAnalysis.SuppressMessage("PSUseShouldProcessForStateChangingFunctions", "", Justification = "Ignoring for now")] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + param ( + [Parameter(Mandatory = $true)] + [System.URI]$PiHoleServer, + [Parameter(Mandatory = $true)] + [string]$Password, + [Parameter(Mandatory = $true)] + [string]$GroupName, + [string]$Comment = $null, + [bool]$Enabled = $true, + [bool]$IgnoreSsl = $false, + [bool]$RawOutput = $false + + ) + try { + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + + $GetGroupName = Get-PiHoleGroup -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl -GroupName $GroupName + + if ($GetGroupName) { + Write-Warning -Message "Group $GroupName already exists" + } + + else { + $Body = @{ + comment = $Comment + enabled = $Enabled + name = $GroupName + } + + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$($PiHoleServer.OriginalString)/api/groups" + Method = "Post" + SkipCertificateCheck = $IgnoreSsl + ContentType = "application/json" + Body = $Body | ConvertTo-Json -Depth 10 + } + + $Response = Invoke-RestMethod @Params + + if ($RawOutput) { + Write-Output $Response + } + + else { + $ObjectFinal = @() + $Object = [PSCustomObject]@{ + Name = $GroupName + Comment = $Comment + Enabled = $Enabled + } + Write-Verbose -Message "Name - $($Object.GroupName)" + Write-Verbose -Message "Comment - $($Object.Comment)" + Write-Verbose -Message "Enabled - $($Object.Enabled)" + $ObjectFinal = $Object + } + Write-Output $ObjectFinal + } + } + + catch { + Write-Error -Message $_.Exception.Message + break + } + + finally { + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } + } +} \ No newline at end of file diff --git a/PiHoleShell/Public/GroupManagement/Remove-PiHoleGroup.ps1 b/PiHoleShell/Public/GroupManagement/Remove-PiHoleGroup.ps1 new file mode 100644 index 0000000..4af5500 --- /dev/null +++ b/PiHoleShell/Public/GroupManagement/Remove-PiHoleGroup.ps1 @@ -0,0 +1,80 @@ +function Remove-PiHoleGroup { + <# +.SYNOPSIS +Delete group + +.PARAMETER PiHoleServer +The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" + +.PARAMETER Password +The API Password you generated from your PiHole server + +.PARAMETER IgnoreSsl +Set to $true to skip SSL certificate validation + +.PARAMETER RawOutput +This will dump the response instead of the formatted object + + #> + #Work In Progress + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#delete-/groups/-name-')] + [Diagnostics.CodeAnalysis.SuppressMessage("PSUseShouldProcessForStateChangingFunctions", "", Justification = "Ignoring for now")] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + param ( + [Parameter(Mandatory = $true)] + [System.URI]$PiHoleServer, + [Parameter(Mandatory = $true)] + [string]$Password, + [Parameter(Mandatory = $true)] + [string]$GroupName, + [bool]$IgnoreSsl = $false, + [bool]$RawOutput = $false + + ) + try { + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + + $Body = @{ + name = $GroupName + } + + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$($PiHoleServer.OriginalString)/api/groups/$GroupName" + Method = "Delete" + SkipCertificateCheck = $IgnoreSsl + ContentType = "application/json" + Body = $Body | ConvertTo-Json -Depth 10 + } + $GetGroupName = Get-PiHoleGroup -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl -GroupName $GroupName + + if ($GetGroupName) { + $Response = Invoke-RestMethod @Params + + if ($RawOutput) { + Write-Output $Response + } + else { + $ObjectFinal = @() + $Object = [PSCustomObject]@{ + Name = $GroupName + Status = "Deleted" + } + $ObjectFinal = $Object + } + Write-Verbose -Message "Deleted $($Object.GroupName)" + Write-Output $ObjectFinal + } + } + + catch { + Write-Error -Message $_.Exception.Message + break + } + + finally { + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } + } +} \ No newline at end of file diff --git a/PiHoleShell/Public/GroupManagement/Update-PiHoleGroup.ps1 b/PiHoleShell/Public/GroupManagement/Update-PiHoleGroup.ps1 new file mode 100644 index 0000000..f0d9878 --- /dev/null +++ b/PiHoleShell/Public/GroupManagement/Update-PiHoleGroup.ps1 @@ -0,0 +1,116 @@ +function Update-PiHoleGroup { + <# +.SYNOPSIS +Items may be updated by replacing them. + +.PARAMETER PiHoleServer +The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" + +.PARAMETER Password +The API Password you generated from your PiHole server + +.PARAMETER IgnoreSsl +Set to $true to skip SSL certificate validation + +.PARAMETER RawOutput +This will dump the response instead of the formatted object + + #> + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + [Diagnostics.CodeAnalysis.SuppressMessage("PSUseShouldProcessForStateChangingFunctions", "", Justification = "Ignoring for now")] + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#put-/groups/-name-')] + param ( + [Parameter(Mandatory = $true)] + [System.URI]$PiHoleServer, + [Parameter(Mandatory = $true)] + [string]$Password, + [Parameter(Mandatory = $true)] + [string]$GroupName, + [string]$Comment = $null, + [bool]$Enabled, + [bool]$IgnoreSsl = $false, + [bool]$RawOutput = $false + + ) + #Enabled is weird here.. look into it + try { + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + + $Body = @{ + name = $GroupName + } + + $GetGroupName = Get-PiHoleGroup -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl -GroupName $GroupName + + if ($Comment -eq $null -and $Enabled -eq $null) { + Write-Warning -Message "failed" + throw -Message "To update $GroupName, you must either use the Comment and/or Enabled parameter" + } + + if ($Comment) { + $Body += @{ + comment = $Comment + } + } + if ($Enabled -ne $null) { + $Body += @{ + enabled = $Enabled + } + } + else { + switch ($GetGroupStatus) { + "True" { + $true + } + "False" { + $false + } + } + + $Body += @{ + enabled = $GetGroupStatus + } + } + + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$($PiHoleServer.OriginalString)/api/groups/$GroupName" + Method = "Put" + SkipCertificateCheck = $IgnoreSsl + ContentType = "application/json" + Body = $Body | ConvertTo-Json -Depth 10 + } + + if ($GetGroupName) { + $Response = Invoke-RestMethod @Params + if ($RawOutput) { + Write-Output $Response + } + else { + $ObjectFinal = @() + $Object = [PSCustomObject]@{ + Name = $GroupName + Comment = $Comment + Enabled = $Enabled + } + Write-Verbose -Message "Name - $($Object.GroupName)" + Write-Verbose -Message "Comment - $($Object.Comment)" + Write-Verbose -Message "Enabled - $($Object.Enabled)" + $ObjectFinal = $Object + } + Write-Output $ObjectFinal + + } + } + + catch { + Write-Error -Message $_.Exception.Message + break + } + + finally { + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } + } +} \ No newline at end of file diff --git a/PiHoleShell/Public/ListManagement.ps1 b/PiHoleShell/Public/ListManagement.ps1 deleted file mode 100644 index 7ed7747..0000000 --- a/PiHoleShell/Public/ListManagement.ps1 +++ /dev/null @@ -1,416 +0,0 @@ -function Get-PiHoleList { - <# -.SYNOPSIS -Get lists - -.PARAMETER PiHoleServer -The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" - -.PARAMETER Password -The API Password you generated from your PiHole server - -.PARAMETER IgnoreSsl -Set to $true to skip SSL certificate validation - -.PARAMETER RawOutput -This will dump the response instead of the formatted object - - #> - #Work In Progress - [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#get-/lists/-list-')] - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] - param ( - [Parameter(Mandatory = $true)] - [System.URI]$PiHoleServer, - [Parameter(Mandatory = $true)] - [string]$Password, - [System.URI]$List = $null, - [bool]$IgnoreSsl = $false, - [bool]$RawOutput = $false - ) - try { - $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl - - $Groups = Get-PiHoleGroup -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl - - $Params = @{ - Headers = @{sid = $($Sid) } - Uri = "$($PiHoleServer.OriginalString)/api/lists/$List" - Method = "Get" - SkipCertificateCheck = $IgnoreSsl - ContentType = "application/json" - } - - $Response = Invoke-RestMethod @Params - - if ($RawOutput) { - Write-Output $Response - } - - else { - $ObjectFinal = @() - foreach ($Item in $Response.lists) { - $GroupNames = [System.Collections.ArrayList]@() - foreach ($Group in $Item.groups) { - $GroupNames += ($Groups | Where-Object { $_.Id -eq $Group }).Name - } - - $Object = $null - if ($Item.date_updated -eq 0) { - $DateUpdated = $null - } - else { - $DateUpdated = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_modified).LocalTime - } - $Object = [PSCustomObject]@{ - Address = $Item.address - Comment = $Item.comment - Groups = $GroupNames - Enabled = $Item.enabled - Id = $Item.id - DateAdded = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_added).LocalTime - DateModified = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_modified).LocalTime - Type = $Item.type - DateUpdated = $DateUpdated - Number = $Item.number - InvalidDomains = $Item.invalid_domains - AbpEntries = $Item.abp_entries - Status = $Item.status - } - if ($Object) { - $ObjectFinal += $Object - } - - } - Write-Output $ObjectFinal - } - } - - catch { - Write-Error -Message $_.Exception.Message - break - } - - finally { - if ($Sid) { - Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl - } - } -} - -function Search-PiHoleListDomain { - <# -.SYNOPSIS -Search domains in Pi-hole's lists - -.PARAMETER PiHoleServer -The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" - -.PARAMETER Password -The API Password you generated from your PiHole server - -.PARAMETER IgnoreSsl -Set to $true to skip SSL certificate validation - -.PARAMETER RawOutput -This will dump the response instead of the formatted object - - #> - #Work In Progress - [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#get-/search/-domain-')] - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] - param ( - [Parameter(Mandatory = $true)] - [System.URI]$PiHoleServer, - [Parameter(Mandatory = $true)] - [string]$Password, - [Parameter(Mandatory = $true)] - [System.URI]$Domain, - [bool]$PartialMatch = $false, - [int]$MaxResults = 20, - [bool]$IgnoreSsl = $false, - [bool]$RawOutput = $false - ) - try { - $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl - - $Body = @{ - n = $MaxResults - partial = $PartialMatch - name = $GroupName - } - - $Params = @{ - Headers = @{sid = $($Sid) } - Uri = "$($PiHoleServer.OriginalString)/api/search/$Domain" - Method = "Get" - SkipCertificateCheck = $IgnoreSsl - Body = $Body - ContentType = "application/json" - } - - $Response = Invoke-RestMethod @Params - - if ($RawOutput) { - Write-Output $Response - } - - else { - $ObjectFinal = @() - foreach ($Item in $Response.lists) { - } - Write-Output $ObjectFinal - } - } - - catch { - Write-Error -Message $_.Exception.Message - break - } - - finally { - if ($Sid) { - Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl - } - } -} - -function Add-PiHoleList { - <# -.SYNOPSIS -Add new list - -.PARAMETER PiHoleServer -The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" - -.PARAMETER Password -The API Password you generated from your PiHole server - -.PARAMETER IgnoreSsl -Set to $true to skip SSL certificate validation - -.PARAMETER RawOutput -This will dump the response instead of the formatted object - - #> - #Work In Progress - [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#post-/lists')] - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] - param ( - [Parameter(Mandatory = $true)] - [System.URI]$PiHoleServer, - [Parameter(Mandatory = $true)] - [string]$Password, - [bool]$IgnoreSsl = $false, - [System.Uri]$Address, - [Parameter(Mandatory = $true)] - [ValidateSet("Allow", "Block")] - [string]$Type, - [string]$Comment = $null, - [string[]]$Group = "Default", - [bool]$Enabled = $true, - [bool]$RawOutput = $false - ) - try { - $FindMatchingList = Get-PiHoleList -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl | Where-Object { $_.Address -eq $Address } - - if ($FindMatchingList) { - throw "List $Address already exists on $PiHoleServer! Please use Update-PiHoleList to update the list" - } - - $AllGroups = Get-PiHoleGroup -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl - $AllGroupsNames = @() - $AllGroupsIds = @() - foreach ($GroupItem in $Group) { - - $FoundGroup = $AllGroups | Where-Object { $_.Name -eq $GroupItem } - if ($FoundGroup) { - $AllGroupsNames += $FoundGroup.Name - $AllGroupsIds += $FoundGroup.Id - Write-Verbose -Message "Found Group $($FoundGroup.Name) with $($FoundGroup.Id)" - } - else { - throw "Cannot find $GroupItem on $PiHoleServer! Please use Get-PiHoleGroup to list all groups" - } - } - - $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl - - $Body = @{ - address = $Address - type = $Type - groups = [Object[]]($AllGroupsIds) - comment = $Comment - enabled = $Enabled - } - - $Params = @{ - Headers = @{sid = $($Sid) } - Uri = "$($PiHoleServer.OriginalString)/api/lists" - Method = "Post" - SkipCertificateCheck = $IgnoreSsl - Body = $Body | ConvertTo-Json -Depth 10 - ContentType = "application/json" - } - - $Response = Invoke-RestMethod @Params - - if ($Item.date_updated -eq 0) { - $DateUpdated = $null - } - else { - $DateUpdated = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_modified).LocalTime - } - - if ($RawOutput) { - Write-Output $Response - } - - else { - $ObjectFinal = @() - $Object = $null - foreach ($Item in $Response.lists) { - - $Object = [PSCustomObject]@{ - Address = $Item.address - Comment = $Item.comment - Groups = $AllGroupsNames - Enabled = $Item.enabled - Id = $Item.id - DateAdded = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_added).LocalTime - DateModified = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_modified).LocalTime - Type = $Item.type.SubString(0, 1).ToUpper() + $Item.type.SubString(1).ToLower() - DateUpdated = $DateUpdated - Number = $Item.number - InvalidDomains = $Item.invalid_domains - AbpEntries = $Item.abp_entries - Status = $Item.status - } - if ($Object) { - $ObjectFinal += $Object - } - - } - Write-Output $ObjectFinal - } - } - - catch { - Write-Error -Message $_.Exception.Message - break - } - - finally { - if ($Sid) { - Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl - } - } -} - -function Remove-PiHoleList { - <# -.SYNOPSIS -Deletes multiple lists in the lists object. - -.PARAMETER PiHoleServer -The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" - -.PARAMETER Password -The API Password you generated from your PiHole server - -.PARAMETER IgnoreSsl -Set to $true to skip SSL certificate validation - -.PARAMETER RawOutput -This will dump the response instead of the formatted objec - - #> - #Work In Progress (NEED TO FINISH) - [CmdletBinding(SupportsShouldProcess = $true, HelpUri = 'https://ftl.pi-hole.net/master/docs/#post-/lists-batchDelete')] - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] - param ( - [Parameter(Mandatory = $true)] - [System.URI]$PiHoleServer, - [Parameter(Mandatory = $true)] - [string]$Password, - [bool]$IgnoreSsl = $false, - [System.Uri]$Address, - [string]$Type, - [bool]$RawOutput = $false - ) - try { - $Target = "Pi-Hole list $Address of type $Type" - if ($PSCmdlet.ShouldProcess($Target, "Remove list")) { - $FindMatchingList = Get-PiHoleList -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl | Where-Object { $_.Address -eq $Address } - - if ($FindMatchingList) { - - } - - $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl - - $Body = @( - @{ - item = $Address - type = $Type.ToLower() - } - ) - - #For some reason this needs to be here to make it an array - $Body = , $Body - $Params = @{ - Headers = @{sid = $($Sid) } - Uri = "$($PiHoleServer.OriginalString)/api/lists:batchDelete" - Method = "Post" - SkipCertificateCheck = $IgnoreSsl - Body = $Body | ConvertTo-Json -Depth 10 -Compress - ContentType = "application/json" - } - - $Response = Invoke-RestMethod @Params - - if ($RawOutput) { - Write-Output $Response - } - - else { - $ObjectFinal = @() - $Object = $null - - foreach ($Item in $Response.lists) { - $Object = [PSCustomObject]@{ - Address = $Item.address - Comment = $Item.comment - Groups = $AllGroupsNames - Enabled = $Item.enabled - Id = $Item.id - DateAdded = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_added).LocalTime - DateModified = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_modified).LocalTime - Type = $Item.type.SubString(0, 1).ToUpper() + $Item.type.SubString(1).ToLower() - DateUpdated = $DateUpdated - Number = $Item.number - InvalidDomains = $Item.invalid_domains - AbpEntries = $Item.abp_entries - Status = $Item.status - } - if ($Object) { - $ObjectFinal += $Object - } - } - - Write-Output $ObjectFinal - } - } - } - - catch { - Write-Error -Message $_.Exception.Message - break - } - - finally { - if ($Sid) { - Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl - } - } -} \ No newline at end of file diff --git a/PiHoleShell/Public/ListManagement/Add-PiHoleList.ps1 b/PiHoleShell/Public/ListManagement/Add-PiHoleList.ps1 new file mode 100644 index 0000000..af8acc5 --- /dev/null +++ b/PiHoleShell/Public/ListManagement/Add-PiHoleList.ps1 @@ -0,0 +1,131 @@ +function Add-PiHoleList { + <# +.SYNOPSIS +Add new list + +.PARAMETER PiHoleServer +The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" + +.PARAMETER Password +The API Password you generated from your PiHole server + +.PARAMETER IgnoreSsl +Set to $true to skip SSL certificate validation + +.PARAMETER RawOutput +This will dump the response instead of the formatted object + + #> + #Work In Progress + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#post-/lists')] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + param ( + [Parameter(Mandatory = $true)] + [System.URI]$PiHoleServer, + [Parameter(Mandatory = $true)] + [string]$Password, + [bool]$IgnoreSsl = $false, + [System.Uri]$Address, + [Parameter(Mandatory = $true)] + [ValidateSet("Allow", "Block")] + [string]$Type, + [string]$Comment = $null, + [string[]]$Group = "Default", + [bool]$Enabled = $true, + [bool]$RawOutput = $false + ) + try { + $FindMatchingList = Get-PiHoleList -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl | Where-Object { $_.Address -eq $Address } + + if ($FindMatchingList) { + throw "List $Address already exists on $PiHoleServer! Please use Update-PiHoleList to update the list" + } + + $AllGroups = Get-PiHoleGroup -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + $AllGroupsNames = @() + $AllGroupsIds = @() + foreach ($GroupItem in $Group) { + + $FoundGroup = $AllGroups | Where-Object { $_.Name -eq $GroupItem } + if ($FoundGroup) { + $AllGroupsNames += $FoundGroup.Name + $AllGroupsIds += $FoundGroup.Id + Write-Verbose -Message "Found Group $($FoundGroup.Name) with $($FoundGroup.Id)" + } + else { + throw "Cannot find $GroupItem on $PiHoleServer! Please use Get-PiHoleGroup to list all groups" + } + } + + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + + $Body = @{ + address = $Address + type = $Type + groups = [Object[]]($AllGroupsIds) + comment = $Comment + enabled = $Enabled + } + + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$($PiHoleServer.OriginalString)/api/lists" + Method = "Post" + SkipCertificateCheck = $IgnoreSsl + Body = $Body | ConvertTo-Json -Depth 10 + ContentType = "application/json" + } + + $Response = Invoke-RestMethod @Params + + if ($Item.date_updated -eq 0) { + $DateUpdated = $null + } + else { + $DateUpdated = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_modified).LocalTime + } + + if ($RawOutput) { + Write-Output $Response + } + + else { + $ObjectFinal = @() + $Object = $null + foreach ($Item in $Response.lists) { + + $Object = [PSCustomObject]@{ + Address = $Item.address + Comment = $Item.comment + Groups = $AllGroupsNames + Enabled = $Item.enabled + Id = $Item.id + DateAdded = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_added).LocalTime + DateModified = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_modified).LocalTime + Type = $Item.type.SubString(0, 1).ToUpper() + $Item.type.SubString(1).ToLower() + DateUpdated = $DateUpdated + Number = $Item.number + InvalidDomains = $Item.invalid_domains + AbpEntries = $Item.abp_entries + Status = $Item.status + } + if ($Object) { + $ObjectFinal += $Object + } + + } + Write-Output $ObjectFinal + } + } + + catch { + Write-Error -Message $_.Exception.Message + break + } + + finally { + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } + } +} \ No newline at end of file diff --git a/PiHoleShell/Public/ListManagement/Get-PiHoleList.ps1 b/PiHoleShell/Public/ListManagement/Get-PiHoleList.ps1 new file mode 100644 index 0000000..5539fda --- /dev/null +++ b/PiHoleShell/Public/ListManagement/Get-PiHoleList.ps1 @@ -0,0 +1,99 @@ +function Get-PiHoleList { + <# +.SYNOPSIS +Get lists + +.PARAMETER PiHoleServer +The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" + +.PARAMETER Password +The API Password you generated from your PiHole server + +.PARAMETER IgnoreSsl +Set to $true to skip SSL certificate validation + +.PARAMETER RawOutput +This will dump the response instead of the formatted object + + #> + #Work In Progress + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#get-/lists/-list-')] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + param ( + [Parameter(Mandatory = $true)] + [System.URI]$PiHoleServer, + [Parameter(Mandatory = $true)] + [string]$Password, + [System.URI]$List = $null, + [bool]$IgnoreSsl = $false, + [bool]$RawOutput = $false + ) + try { + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + + $Groups = Get-PiHoleGroup -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$($PiHoleServer.OriginalString)/api/lists/$List" + Method = "Get" + SkipCertificateCheck = $IgnoreSsl + ContentType = "application/json" + } + + $Response = Invoke-RestMethod @Params + + if ($RawOutput) { + Write-Output $Response + } + + else { + $ObjectFinal = @() + foreach ($Item in $Response.lists) { + $GroupNames = [System.Collections.ArrayList]@() + foreach ($Group in $Item.groups) { + $GroupNames += ($Groups | Where-Object { $_.Id -eq $Group }).Name + } + + $Object = $null + if ($Item.date_updated -eq 0) { + $DateUpdated = $null + } + else { + $DateUpdated = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_modified).LocalTime + } + $Object = [PSCustomObject]@{ + Address = $Item.address + Comment = $Item.comment + Groups = $GroupNames + Enabled = $Item.enabled + Id = $Item.id + DateAdded = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_added).LocalTime + DateModified = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_modified).LocalTime + Type = $Item.type + DateUpdated = $DateUpdated + Number = $Item.number + InvalidDomains = $Item.invalid_domains + AbpEntries = $Item.abp_entries + Status = $Item.status + } + if ($Object) { + $ObjectFinal += $Object + } + + } + Write-Output $ObjectFinal + } + } + + catch { + Write-Error -Message $_.Exception.Message + break + } + + finally { + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } + } +} \ No newline at end of file diff --git a/PiHoleShell/Public/ListManagement/Remove-PiHoleList.ps1 b/PiHoleShell/Public/ListManagement/Remove-PiHoleList.ps1 new file mode 100644 index 0000000..e2fda10 --- /dev/null +++ b/PiHoleShell/Public/ListManagement/Remove-PiHoleList.ps1 @@ -0,0 +1,107 @@ +function Remove-PiHoleList { + <# +.SYNOPSIS +Deletes multiple lists in the lists object. + +.PARAMETER PiHoleServer +The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" + +.PARAMETER Password +The API Password you generated from your PiHole server + +.PARAMETER IgnoreSsl +Set to $true to skip SSL certificate validation + +.PARAMETER RawOutput +This will dump the response instead of the formatted objec + + #> + #Work In Progress (NEED TO FINISH) + [CmdletBinding(SupportsShouldProcess = $true, HelpUri = 'https://ftl.pi-hole.net/master/docs/#post-/lists-batchDelete')] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + param ( + [Parameter(Mandatory = $true)] + [System.URI]$PiHoleServer, + [Parameter(Mandatory = $true)] + [string]$Password, + [bool]$IgnoreSsl = $false, + [System.Uri]$Address, + [string]$Type, + [bool]$RawOutput = $false + ) + try { + $Target = "Pi-Hole list $Address of type $Type" + if ($PSCmdlet.ShouldProcess($Target, "Remove list")) { + $FindMatchingList = Get-PiHoleList -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl | Where-Object { $_.Address -eq $Address } + + if ($FindMatchingList) { + + } + + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + + $Body = @( + @{ + item = $Address + type = $Type.ToLower() + } + ) + + #For some reason this needs to be here to make it an array + $Body = , $Body + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$($PiHoleServer.OriginalString)/api/lists:batchDelete" + Method = "Post" + SkipCertificateCheck = $IgnoreSsl + Body = $Body | ConvertTo-Json -Depth 10 -Compress + ContentType = "application/json" + } + + $Response = Invoke-RestMethod @Params + + if ($RawOutput) { + Write-Output $Response + } + + else { + $ObjectFinal = @() + $Object = $null + + foreach ($Item in $Response.lists) { + $Object = [PSCustomObject]@{ + Address = $Item.address + Comment = $Item.comment + Groups = $AllGroupsNames + Enabled = $Item.enabled + Id = $Item.id + DateAdded = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_added).LocalTime + DateModified = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_modified).LocalTime + Type = $Item.type.SubString(0, 1).ToUpper() + $Item.type.SubString(1).ToLower() + DateUpdated = $DateUpdated + Number = $Item.number + InvalidDomains = $Item.invalid_domains + AbpEntries = $Item.abp_entries + Status = $Item.status + } + if ($Object) { + $ObjectFinal += $Object + } + } + + Write-Output $ObjectFinal + } + } + } + + catch { + Write-Error -Message $_.Exception.Message + break + } + + finally { + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } + } +} \ No newline at end of file diff --git a/PiHoleShell/Public/ListManagement/Search-PiHoleListDomain.ps1 b/PiHoleShell/Public/ListManagement/Search-PiHoleListDomain.ps1 new file mode 100644 index 0000000..dad94f5 --- /dev/null +++ b/PiHoleShell/Public/ListManagement/Search-PiHoleListDomain.ps1 @@ -0,0 +1,76 @@ +function Search-PiHoleListDomain { + <# +.SYNOPSIS +Search domains in Pi-hole's lists + +.PARAMETER PiHoleServer +The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" + +.PARAMETER Password +The API Password you generated from your PiHole server + +.PARAMETER IgnoreSsl +Set to $true to skip SSL certificate validation + +.PARAMETER RawOutput +This will dump the response instead of the formatted object + + #> + #Work In Progress + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#get-/search/-domain-')] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + param ( + [Parameter(Mandatory = $true)] + [System.URI]$PiHoleServer, + [Parameter(Mandatory = $true)] + [string]$Password, + [Parameter(Mandatory = $true)] + [System.URI]$Domain, + [bool]$PartialMatch = $false, + [int]$MaxResults = 20, + [bool]$IgnoreSsl = $false, + [bool]$RawOutput = $false + ) + try { + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + + $Body = @{ + n = $MaxResults + partial = $PartialMatch + name = $GroupName + } + + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$($PiHoleServer.OriginalString)/api/search/$Domain" + Method = "Get" + SkipCertificateCheck = $IgnoreSsl + Body = $Body + ContentType = "application/json" + } + + $Response = Invoke-RestMethod @Params + + if ($RawOutput) { + Write-Output $Response + } + + else { + $ObjectFinal = @() + foreach ($Item in $Response.lists) { + } + Write-Output $ObjectFinal + } + } + + catch { + Write-Error -Message $_.Exception.Message + break + } + + finally { + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } + } +} \ No newline at end of file diff --git a/PiHoleShell/Public/Metrics.ps1 b/PiHoleShell/Public/Metrics.ps1 deleted file mode 100644 index 3cce171..0000000 --- a/PiHoleShell/Public/Metrics.ps1 +++ /dev/null @@ -1,392 +0,0 @@ -function Get-PiHoleStatsRecentBlocked { - <# -.SYNOPSIS -Request most recently blocked domain - -.PARAMETER PiHoleServer -The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" - -.PARAMETER Password -The API Password you generated from your PiHole server - -.PARAMETER MaxResult -How many results should be returned - -.PARAMETER RawOutput -This will dump the response instead of the formatted object - -.EXAMPLE -Get-PiHoleStatsRecentBlocked -PiHoleServer "http://pihole.domain.com:8080" -Password "fjdsjfldsjfkldjslafjskdl" -MaxResult 20 - #> - [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#get-/stats/recent_blocked')] - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] - param ( - [Parameter(Mandatory = $true)] - [System.URI]$PiHoleServer, - [Parameter(Mandatory = $true)] - [string]$Password, - [int]$MaxResult = 1, - [bool]$IgnoreSsl = $false, - [bool]$RawOutput - ) - try { - $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl - Write-Verbose -Message "MaxResults - $MaxResult" - $Params = @{ - Headers = @{sid = $($Sid) } - Uri = "$($PiHoleServer.OriginalString)/api/stats/recent_blocked?count=$MaxResult" - Method = "Get" - SkipCertificateCheck = $IgnoreSsl - ContentType = "application/json" - } - - $Response = Invoke-RestMethod @Params - - if ($RawOutput) { - Write-Output $Response - } - else { - $ObjectFinal = @() - foreach ($Item in $Response.blocked) { - $Object = $null - $Object = [PSCustomObject]@{ - Blocked = $Item - } - Write-Verbose -Message "Blocked - $Item" - $ObjectFinal += $Object - } - Write-Output $ObjectFinal - } - } - - catch { - Write-Error -Message $_.Exception.Message - break - } - - finally { - if ($Sid) { - Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl - } - } -} - -function Get-PiHoleStatsQueryType { - <# -.SYNOPSIS -https://TODOFINDNEWAPILINK - #> - [CmdletBinding()] - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] - param ( - [Parameter(Mandatory = $true)] - [System.URI]$PiHoleServer, - [Parameter(Mandatory = $true)] - [string]$Password, - [bool]$IgnoreSsl = $false, - [bool]$RawOutput = $false - ) - - $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl - Write-Verbose -Message "MaxResults - $MaxResult" - $Params = @{ - Headers = @{sid = $($Sid) } - Uri = "$($PiHoleServer.OriginalString)/api/stats/query_types" - Method = "Get" - SkipCertificateCheck = $IgnoreSsl - ContentType = "application/json" - } - - $Response = Invoke-RestMethod @Params - - if ($RawOutput) { - Write-Output $Response - } - else { - $Object = [PSCustomObject]@{ - A = $Response.types.A - AAAA = $Response.types.AAAA - ANY = $Response.types.ANY - SRV = $Response.types.SRV - SOA = $Response.types.SOA - PTR = $Response.types.PTR - TXT = $Response.types.TXT - NAPTR = $Response.types.NAPTR - MX = $Response.types.MX - DS = $Response.types.DS - RRSIG = $Response.types.RRSIG - DNSKEY = $Response.types.DNSKEY - NS = $Response.types.NS - SVCB = $Response.types.SVCB - HTTPS = $Response.types.HTTPS - OTHER = $Response.types.OTHER - } - $ObjectFinal += $Object - Write-Output $ObjectFinal - } -} - -function Get-PiHoleStatsTopDomain { - <# -.SYNOPSIS -https://TODOFINDNEWAPILINK - #> - [CmdletBinding()] - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] - param ( - [Parameter(Mandatory = $true)] - [System.URI]$PiHoleServer, - [Parameter(Mandatory = $true)] - [string]$Password, - [int]$MaxResult = 10, - [bool]$Blocked = $false, - [bool]$IgnoreSsl = $false, - [bool]$RawOutput = $false - ) - - $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl - - switch ($Blocked) { - $false { - $Blocked = "false" - } - $true { - $Blocked = "true" - } - Default { - throw "ERROR" - } - } - Write-Verbose "Blocked: $Blocked" - - $Params = @{ - Headers = @{sid = $($Sid) } - Uri = "$($PiHoleServer.OriginalString)/api/stats/top_domains?blocked=$Blocked&count=$MaxResult" - Method = "Get" - SkipCertificateCheck = $IgnoreSsl - ContentType = "application/json" - } - - $Response = Invoke-RestMethod @Params - - if ($RawOutput) { - Write-Output $Response - } - - if ($Sid) { - Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl - } -} - -function Get-PiHoleStatsTopClient { - <# -.SYNOPSIS -Get top clients -Request the top clients (by query count) - -.PARAMETER PiHoleServer -The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" - -.PARAMETER Password -The API Password you generated from your PiHole server - -.PARAMETER MaxResult -How many results should be returned - -.PARAMETER Blocked -If true, returns top clients by blocked queries instead of total queries - -.PARAMETER RawOutput -This will dump the response instead of the formatted object - -.EXAMPLE -Get-PiHoleStatsTopClient -PiHoleServer "http://pihole.domain.com:8080" -Password "fjdsjfldsjfkldjslafjskdl" -MaxResult 10 - #> - [CmdletBinding()] - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] - param ( - [Parameter(Mandatory = $true)] - [System.URI]$PiHoleServer, - [Parameter(Mandatory = $true)] - [string]$Password, - [int]$MaxResult = 10, - [bool]$Blocked = $false, - [bool]$IgnoreSsl = $false, - [bool]$RawOutput = $false - ) - try { - $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl - - switch ($Blocked) { - $false { $BlockedParam = "false" } - $true { $BlockedParam = "true" } - Default { throw "ERROR" } - } - Write-Verbose "Blocked: $BlockedParam" - Write-Verbose "MaxResult: $MaxResult" - - $Params = @{ - Headers = @{sid = $($Sid) } - Uri = "$($PiHoleServer.OriginalString)/api/stats/top_clients?blocked=$BlockedParam&count=$MaxResult" - Method = "Get" - SkipCertificateCheck = $IgnoreSsl - ContentType = "application/json" - } - - $Response = Invoke-RestMethod @Params - - if ($RawOutput) { - Write-Output $Response - } - else { - $ObjectFinal = @() - foreach ($Item in $Response.clients) { - $Object = $null - $Object = [PSCustomObject]@{ - IP = $Item.ip - Name = $Item.name - Count = $Item.count - } - Write-Verbose -Message "Client - $($Item.ip) ($($Item.name)): $($Item.count)" - $ObjectFinal += $Object - } - Write-Output $ObjectFinal - } - } - - catch { - Write-Error -Message $_.Exception.Message - break - } - - finally { - if ($Sid) { - Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl - } - } -} - -function Get-PiHoleStatsSummary { - <# -.SYNOPSIS -Get overview of Pi-hole activity -Request various query, system, and FTL properties - -.PARAMETER PiHoleServer -The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" - -.PARAMETER Password -The API Password you generated from your PiHole server - - -This will dump the response instead of the formatted object - -.PARAMETER RawOutput -This will dump the response instead of the formatted object - -.EXAMPLE -Get-PiHoleStatsSummary -PiHoleServer "http://pihole.domain.com:8080" -Password "fjdsjfldsjfkldjslafjskdl" - #> - [CmdletBinding()] - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] - param ( - [Parameter(Mandatory = $true)] - [System.URI]$PiHoleServer, - [Parameter(Mandatory = $true)] - [string]$Password, - [bool]$IgnoreSsl = $false, - [bool]$RawOutput - ) - try { - $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl - - $Params = @{ - Headers = @{sid = $($Sid) } - Uri = "$($PiHoleServer.OriginalString)/api/stats/summary" - Method = "Get" - SkipCertificateCheck = $IgnoreSsl - ContentType = "application/json" - } - - $Response = Invoke-RestMethod @Params - - if ($RawOutput) { - Write-Output $Response - } - else { - $Object = [PSCustomObject]@{ - Total = $Response.queries.total - Blocked = $Response.queries.blocked - PercentBlocked = $Response.queries.percent_blocked - Types = [PSCustomObject]@{ - A = $Response.queries.types.A - AAAA = $Response.queries.types.AAAA - ANY = $Response.queries.types.ANY - SRV = $Response.queries.types.SRV - SOA = $Response.queries.types.SOA - PTR = $Response.queries.types.PTR - TXT = $Response.queries.types.TXT - NAPTR = $Response.queries.types.NAPTR - MX = $Response.queries.types.MX - DS = $Response.queries.types.DS - RRSIG = $Response.queries.types.RRSIG - DNSKEY = $Response.queries.types.DNSKEY - NS = $Response.queries.types.NS - SVCB = $Response.queries.types.SVCB - HTTPS = $Response.queries.types.HTTPS - OTHER = $Response.queries.types.OTHER - } - Status = [PSCustomObject]@{ - Unknown = $Response.queries.status.UNKNOWN - Gravity = $Response.queries.status.GRAVITY - Forwarded = $Response.queries.status.FORWARDED - Cache = $Response.queries.status.CACHE - Regex = $Response.queries.status.REGEX - DenyList = $Response.queries.status.DENYLIST - ExternalBlockedIp = $Response.queries.status.EXTERNAL_BLOCKED_IP - ExternalBlockedNull = $Response.queries.status.EXTERNAL_BLOCKED_NULL - ExternalBlockedNxra = $Response.queries.status.EXTERNAL_BLOCKED_NXRA - GravityCname = $Response.queries.status.GRAVITY_CNAME - RegexCname = $Response.queries.status.REGEX_CNAME - DenyListCname = $Response.queries.status.DENYLIST_CNAME - Retired = $Response.queries.status.RETRIED - RetiredDnssec = $Response.queries.status.RETRIED_DNSSEC - InProgress = $Response.queries.status.IN_PROGRESS - Dbbusy = $Response.queries.status.DBBUSY - SpecialDomain = $Response.queries.status.SPECIAL_DOMAIN - CacheStale = $Response.queries.status.CACHE_STALE - ExternalBlockedEde15 = $Response.queries.status.EXTERNAL_BLOCKED_EDE15 - } - Replies = [PSCustomObject]@{ - Unknown = $Response.queries.replies.UNKNOWN - Nodata = $Response.queries.replies.NODATA - Nxdomain = $Response.queries.replies.NXDOMAIN - Cname = $Response.queries.replies.CNAME - Ip = $Response.queries.replies.IP - Domain = $Response.queries.replies.DOMAIN - Rrname = $Response.queries.replies.RRNAME - ServFail = $Response.queries.replies.SERVFAIL - Refused = $Response.queries.replies.REFUSED - Notimp = $Response.queries.replies.NOTIMP - Other = $Response.queries.replies.OTHER - Dnssec = $Response.queries.replies.DNSSEC - None = $Response.queries.replies.NONE - Blob = $Response.queries.replies.BLOB - } - } - $ObjectFinal += $Object - Write-Output $ObjectFinal - } - } - - catch { - Write-Error -Message $_.Exception.Message - break - } - - finally { - if ($Sid) { - Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl - } - } -} \ No newline at end of file diff --git a/PiHoleShell/Public/Metrics/Get-PiHoleStatsQueryType.ps1 b/PiHoleShell/Public/Metrics/Get-PiHoleStatsQueryType.ps1 new file mode 100644 index 0000000..2cc78e7 --- /dev/null +++ b/PiHoleShell/Public/Metrics/Get-PiHoleStatsQueryType.ps1 @@ -0,0 +1,54 @@ +function Get-PiHoleStatsQueryType { + <# +.SYNOPSIS +https://TODOFINDNEWAPILINK + #> + [CmdletBinding()] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + param ( + [Parameter(Mandatory = $true)] + [System.URI]$PiHoleServer, + [Parameter(Mandatory = $true)] + [string]$Password, + [bool]$IgnoreSsl = $false, + [bool]$RawOutput = $false + ) + + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + Write-Verbose -Message "MaxResults - $MaxResult" + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$($PiHoleServer.OriginalString)/api/stats/query_types" + Method = "Get" + SkipCertificateCheck = $IgnoreSsl + ContentType = "application/json" + } + + $Response = Invoke-RestMethod @Params + + if ($RawOutput) { + Write-Output $Response + } + else { + $Object = [PSCustomObject]@{ + A = $Response.types.A + AAAA = $Response.types.AAAA + ANY = $Response.types.ANY + SRV = $Response.types.SRV + SOA = $Response.types.SOA + PTR = $Response.types.PTR + TXT = $Response.types.TXT + NAPTR = $Response.types.NAPTR + MX = $Response.types.MX + DS = $Response.types.DS + RRSIG = $Response.types.RRSIG + DNSKEY = $Response.types.DNSKEY + NS = $Response.types.NS + SVCB = $Response.types.SVCB + HTTPS = $Response.types.HTTPS + OTHER = $Response.types.OTHER + } + $ObjectFinal += $Object + Write-Output $ObjectFinal + } +} \ No newline at end of file diff --git a/PiHoleShell/Public/Metrics/Get-PiHoleStatsRecentBlocked.ps1 b/PiHoleShell/Public/Metrics/Get-PiHoleStatsRecentBlocked.ps1 new file mode 100644 index 0000000..b390fcd --- /dev/null +++ b/PiHoleShell/Public/Metrics/Get-PiHoleStatsRecentBlocked.ps1 @@ -0,0 +1,73 @@ +function Get-PiHoleStatsRecentBlocked { + <# +.SYNOPSIS +Request most recently blocked domain + +.PARAMETER PiHoleServer +The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" + +.PARAMETER Password +The API Password you generated from your PiHole server + +.PARAMETER MaxResult +How many results should be returned + +.PARAMETER RawOutput +This will dump the response instead of the formatted object + +.EXAMPLE +Get-PiHoleStatsRecentBlocked -PiHoleServer "http://pihole.domain.com:8080" -Password "fjdsjfldsjfkldjslafjskdl" -MaxResult 20 + #> + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#get-/stats/recent_blocked')] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + param ( + [Parameter(Mandatory = $true)] + [System.URI]$PiHoleServer, + [Parameter(Mandatory = $true)] + [string]$Password, + [int]$MaxResult = 1, + [bool]$IgnoreSsl = $false, + [bool]$RawOutput + ) + try { + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + Write-Verbose -Message "MaxResults - $MaxResult" + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$($PiHoleServer.OriginalString)/api/stats/recent_blocked?count=$MaxResult" + Method = "Get" + SkipCertificateCheck = $IgnoreSsl + ContentType = "application/json" + } + + $Response = Invoke-RestMethod @Params + + if ($RawOutput) { + Write-Output $Response + } + else { + $ObjectFinal = @() + foreach ($Item in $Response.blocked) { + $Object = $null + $Object = [PSCustomObject]@{ + Blocked = $Item + } + Write-Verbose -Message "Blocked - $Item" + $ObjectFinal += $Object + } + Write-Output $ObjectFinal + } + } + + catch { + Write-Error -Message $_.Exception.Message + break + } + + finally { + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } + } +} + diff --git a/PiHoleShell/Public/Metrics/Get-PiHoleStatsSummary.ps1 b/PiHoleShell/Public/Metrics/Get-PiHoleStatsSummary.ps1 new file mode 100644 index 0000000..17c8274 --- /dev/null +++ b/PiHoleShell/Public/Metrics/Get-PiHoleStatsSummary.ps1 @@ -0,0 +1,124 @@ +function Get-PiHoleStatsSummary { + <# +.SYNOPSIS +Get overview of Pi-hole activity +Request various query, system, and FTL properties + +.PARAMETER PiHoleServer +The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" + +.PARAMETER Password +The API Password you generated from your PiHole server + + +This will dump the response instead of the formatted object + +.PARAMETER RawOutput +This will dump the response instead of the formatted object + +.EXAMPLE +Get-PiHoleStatsSummary -PiHoleServer "http://pihole.domain.com:8080" -Password "fjdsjfldsjfkldjslafjskdl" + #> + [CmdletBinding()] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + param ( + [Parameter(Mandatory = $true)] + [System.URI]$PiHoleServer, + [Parameter(Mandatory = $true)] + [string]$Password, + [bool]$IgnoreSsl = $false, + [bool]$RawOutput + ) + try { + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$($PiHoleServer.OriginalString)/api/stats/summary" + Method = "Get" + SkipCertificateCheck = $IgnoreSsl + ContentType = "application/json" + } + + $Response = Invoke-RestMethod @Params + + if ($RawOutput) { + Write-Output $Response + } + else { + $Object = [PSCustomObject]@{ + Total = $Response.queries.total + Blocked = $Response.queries.blocked + PercentBlocked = $Response.queries.percent_blocked + Types = [PSCustomObject]@{ + A = $Response.queries.types.A + AAAA = $Response.queries.types.AAAA + ANY = $Response.queries.types.ANY + SRV = $Response.queries.types.SRV + SOA = $Response.queries.types.SOA + PTR = $Response.queries.types.PTR + TXT = $Response.queries.types.TXT + NAPTR = $Response.queries.types.NAPTR + MX = $Response.queries.types.MX + DS = $Response.queries.types.DS + RRSIG = $Response.queries.types.RRSIG + DNSKEY = $Response.queries.types.DNSKEY + NS = $Response.queries.types.NS + SVCB = $Response.queries.types.SVCB + HTTPS = $Response.queries.types.HTTPS + OTHER = $Response.queries.types.OTHER + } + Status = [PSCustomObject]@{ + Unknown = $Response.queries.status.UNKNOWN + Gravity = $Response.queries.status.GRAVITY + Forwarded = $Response.queries.status.FORWARDED + Cache = $Response.queries.status.CACHE + Regex = $Response.queries.status.REGEX + DenyList = $Response.queries.status.DENYLIST + ExternalBlockedIp = $Response.queries.status.EXTERNAL_BLOCKED_IP + ExternalBlockedNull = $Response.queries.status.EXTERNAL_BLOCKED_NULL + ExternalBlockedNxra = $Response.queries.status.EXTERNAL_BLOCKED_NXRA + GravityCname = $Response.queries.status.GRAVITY_CNAME + RegexCname = $Response.queries.status.REGEX_CNAME + DenyListCname = $Response.queries.status.DENYLIST_CNAME + Retired = $Response.queries.status.RETRIED + RetiredDnssec = $Response.queries.status.RETRIED_DNSSEC + InProgress = $Response.queries.status.IN_PROGRESS + Dbbusy = $Response.queries.status.DBBUSY + SpecialDomain = $Response.queries.status.SPECIAL_DOMAIN + CacheStale = $Response.queries.status.CACHE_STALE + ExternalBlockedEde15 = $Response.queries.status.EXTERNAL_BLOCKED_EDE15 + } + Replies = [PSCustomObject]@{ + Unknown = $Response.queries.replies.UNKNOWN + Nodata = $Response.queries.replies.NODATA + Nxdomain = $Response.queries.replies.NXDOMAIN + Cname = $Response.queries.replies.CNAME + Ip = $Response.queries.replies.IP + Domain = $Response.queries.replies.DOMAIN + Rrname = $Response.queries.replies.RRNAME + ServFail = $Response.queries.replies.SERVFAIL + Refused = $Response.queries.replies.REFUSED + Notimp = $Response.queries.replies.NOTIMP + Other = $Response.queries.replies.OTHER + Dnssec = $Response.queries.replies.DNSSEC + None = $Response.queries.replies.NONE + Blob = $Response.queries.replies.BLOB + } + } + $ObjectFinal += $Object + Write-Output $ObjectFinal + } + } + + catch { + Write-Error -Message $_.Exception.Message + break + } + + finally { + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } + } +} \ No newline at end of file diff --git a/PiHoleShell/Public/Metrics/Get-PiHoleStatsTopClient.ps1 b/PiHoleShell/Public/Metrics/Get-PiHoleStatsTopClient.ps1 new file mode 100644 index 0000000..eba3963 --- /dev/null +++ b/PiHoleShell/Public/Metrics/Get-PiHoleStatsTopClient.ps1 @@ -0,0 +1,87 @@ +function Get-PiHoleStatsTopClient { + <# +.SYNOPSIS +Get top clients +Request the top clients (by query count) + +.PARAMETER PiHoleServer +The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" + +.PARAMETER Password +The API Password you generated from your PiHole server + +.PARAMETER MaxResult +How many results should be returned + +.PARAMETER Blocked +If true, returns top clients by blocked queries instead of total queries + +.PARAMETER RawOutput +This will dump the response instead of the formatted object + +.EXAMPLE +Get-PiHoleStatsTopClient -PiHoleServer "http://pihole.domain.com:8080" -Password "fjdsjfldsjfkldjslafjskdl" -MaxResult 10 + #> + [CmdletBinding()] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + param ( + [Parameter(Mandatory = $true)] + [System.URI]$PiHoleServer, + [Parameter(Mandatory = $true)] + [string]$Password, + [int]$MaxResult = 10, + [bool]$Blocked = $false, + [bool]$IgnoreSsl = $false, + [bool]$RawOutput = $false + ) + try { + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + + switch ($Blocked) { + $false { $BlockedParam = "false" } + $true { $BlockedParam = "true" } + Default { throw "ERROR" } + } + Write-Verbose "Blocked: $BlockedParam" + Write-Verbose "MaxResult: $MaxResult" + + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$($PiHoleServer.OriginalString)/api/stats/top_clients?blocked=$BlockedParam&count=$MaxResult" + Method = "Get" + SkipCertificateCheck = $IgnoreSsl + ContentType = "application/json" + } + + $Response = Invoke-RestMethod @Params + + if ($RawOutput) { + Write-Output $Response + } + else { + $ObjectFinal = @() + foreach ($Item in $Response.clients) { + $Object = $null + $Object = [PSCustomObject]@{ + IP = $Item.ip + Name = $Item.name + Count = $Item.count + } + Write-Verbose -Message "Client - $($Item.ip) ($($Item.name)): $($Item.count)" + $ObjectFinal += $Object + } + Write-Output $ObjectFinal + } + } + + catch { + Write-Error -Message $_.Exception.Message + break + } + + finally { + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } + } +} \ No newline at end of file diff --git a/PiHoleShell/Public/Metrics/Get-PiHoleStatsTopDomain.ps1 b/PiHoleShell/Public/Metrics/Get-PiHoleStatsTopDomain.ps1 new file mode 100644 index 0000000..17b78c8 --- /dev/null +++ b/PiHoleShell/Public/Metrics/Get-PiHoleStatsTopDomain.ps1 @@ -0,0 +1,51 @@ +function Get-PiHoleStatsTopDomain { + <# +.SYNOPSIS +https://TODOFINDNEWAPILINK + #> + [CmdletBinding()] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + param ( + [Parameter(Mandatory = $true)] + [System.URI]$PiHoleServer, + [Parameter(Mandatory = $true)] + [string]$Password, + [int]$MaxResult = 10, + [bool]$Blocked = $false, + [bool]$IgnoreSsl = $false, + [bool]$RawOutput = $false + ) + + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + + switch ($Blocked) { + $false { + $Blocked = "false" + } + $true { + $Blocked = "true" + } + Default { + throw "ERROR" + } + } + Write-Verbose "Blocked: $Blocked" + + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$($PiHoleServer.OriginalString)/api/stats/top_domains?blocked=$Blocked&count=$MaxResult" + Method = "Get" + SkipCertificateCheck = $IgnoreSsl + ContentType = "application/json" + } + + $Response = Invoke-RestMethod @Params + + if ($RawOutput) { + Write-Output $Response + } + + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } +} \ No newline at end of file diff --git a/PiHoleShell/Public/Padd.ps1 b/PiHoleShell/Public/Padd/Get-PiHolePadd.ps1 similarity index 100% rename from PiHoleShell/Public/Padd.ps1 rename to PiHoleShell/Public/Padd/Get-PiHolePadd.ps1 diff --git a/PiHoleShell/Public/Teleporter.ps1 b/PiHoleShell/Public/Teleporter/Get-PiHoleTeleporterDownload.ps1 similarity index 100% rename from PiHoleShell/Public/Teleporter.ps1 rename to PiHoleShell/Public/Teleporter/Get-PiHoleTeleporterDownload.ps1 From 21d310d6831b3b95cbd096f7543b1c901160f78e Mon Sep 17 00:00:00 2001 From: Mike Madeja Date: Mon, 23 Mar 2026 22:47:08 -0500 Subject: [PATCH 3/3] cont --- .gitignore | 1 + PiHoleShell/PiHoleShell.psm1 | 2 +- .../FTLInformation/Get-PiHoleInfoHost.ps1 | 70 ------------------- .../FTLInformation/Get-PiHoleInfoMessage.ps1 | 69 ++++++++++++++++++ PiHoleShell/Public/Padd/Get-PiHolePadd.ps1 | 4 +- 5 files changed, 73 insertions(+), 73 deletions(-) create mode 100644 .gitignore create mode 100644 PiHoleShell/Public/FTLInformation/Get-PiHoleInfoMessage.ps1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d669de9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +notes.txt \ No newline at end of file diff --git a/PiHoleShell/PiHoleShell.psm1 b/PiHoleShell/PiHoleShell.psm1 index 9555bf6..efb4717 100644 --- a/PiHoleShell/PiHoleShell.psm1 +++ b/PiHoleShell/PiHoleShell.psm1 @@ -24,7 +24,7 @@ Export-ModuleMember -Function @( #DnsControl 'Get-PiHoleDnsBlockingStatus', 'Set-PiHoleDnsBlocking', ` #Config - 'Get-PiHoleConfig', 'Get-PiHoleCurrentAuthSession', 'Remove-PiHoleAuthSession', ` + 'Get-PiHoleConfig', ` #Padd 'Get-PiHolePadd', ` #Metrics diff --git a/PiHoleShell/Public/FTLInformation/Get-PiHoleInfoHost.ps1 b/PiHoleShell/Public/FTLInformation/Get-PiHoleInfoHost.ps1 index e425290..6ea7d84 100644 --- a/PiHoleShell/Public/FTLInformation/Get-PiHoleInfoHost.ps1 +++ b/PiHoleShell/Public/FTLInformation/Get-PiHoleInfoHost.ps1 @@ -1,73 +1,3 @@ -function Get-PiHoleInfoMessage { - <# -.SYNOPSIS -Get Pi-hole diagnosis messages -Request Pi-hole diagnosis messages - #> - [CmdletBinding()] - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] - param ( - [Parameter(Mandatory = $true)] - [System.URI]$PiHoleServer, - [Parameter(Mandatory = $true)] - [string]$Password, - [bool]$IgnoreSsl = $false, - [bool]$RawOutput = $false - ) - try { - $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl - - $Params = @{ - Headers = @{sid = $($Sid) } - Uri = "$($PiHoleServer.OriginalString)/api/info/messages" - Method = "Get" - SkipCertificateCheck = $IgnoreSsl - ContentType = "application/json" - } - - $Response = Invoke-RestMethod @Params - - if ($RawOutput) { - Write-Output $Response - } - - else { - $ObjectFinal = @() - foreach ($Item in $Response.messages) { - $Object = $null - $Object = [PSCustomObject]@{ - Id = $Item.id - Timestamp = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.timestamp).LocalTime - Type = $Item.type - Plain = $Item.plain - Html = $Item.html - - } - - Write-Verbose -Message "Name - $($Object.Id)" - Write-Verbose -Message "Timestamp - $($Object.Timestamp)" - Write-Verbose -Message "Type - $($Object.Type)" - Write-Verbose -Message "Plain - $($Object.Plain)" - Write-Verbose -Message "Html - $($Object.Html)" - $ObjectFinal += $Object - } - - Write-Output $ObjectFinal - } - } - - catch { - Write-Error -Message $_.Exception.Message - break - } - - finally { - if ($Sid) { - Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl - } - } -} - function Get-PiHoleInfoHost { <# .SYNOPSIS diff --git a/PiHoleShell/Public/FTLInformation/Get-PiHoleInfoMessage.ps1 b/PiHoleShell/Public/FTLInformation/Get-PiHoleInfoMessage.ps1 new file mode 100644 index 0000000..fcd4f28 --- /dev/null +++ b/PiHoleShell/Public/FTLInformation/Get-PiHoleInfoMessage.ps1 @@ -0,0 +1,69 @@ +function Get-PiHoleInfoMessage { + <# +.SYNOPSIS +Get Pi-hole diagnosis messages +Request Pi-hole diagnosis messages + #> + [CmdletBinding()] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + param ( + [Parameter(Mandatory = $true)] + [System.URI]$PiHoleServer, + [Parameter(Mandatory = $true)] + [string]$Password, + [bool]$IgnoreSsl = $false, + [bool]$RawOutput = $false + ) + try { + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$($PiHoleServer.OriginalString)/api/info/messages" + Method = "Get" + SkipCertificateCheck = $IgnoreSsl + ContentType = "application/json" + } + + $Response = Invoke-RestMethod @Params + + if ($RawOutput) { + Write-Output $Response + } + + else { + $ObjectFinal = @() + foreach ($Item in $Response.messages) { + $Object = $null + $Object = [PSCustomObject]@{ + Id = $Item.id + Timestamp = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.timestamp).LocalTime + Type = $Item.type + Plain = $Item.plain + Html = $Item.html + + } + + Write-Verbose -Message "Name - $($Object.Id)" + Write-Verbose -Message "Timestamp - $($Object.Timestamp)" + Write-Verbose -Message "Type - $($Object.Type)" + Write-Verbose -Message "Plain - $($Object.Plain)" + Write-Verbose -Message "Html - $($Object.Html)" + $ObjectFinal += $Object + } + + Write-Output $ObjectFinal + } + } + + catch { + Write-Error -Message $_.Exception.Message + break + } + + finally { + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } + } +} \ No newline at end of file diff --git a/PiHoleShell/Public/Padd/Get-PiHolePadd.ps1 b/PiHoleShell/Public/Padd/Get-PiHolePadd.ps1 index 7dc47a3..65f1d42 100644 --- a/PiHoleShell/Public/Padd/Get-PiHolePadd.ps1 +++ b/PiHoleShell/Public/Padd/Get-PiHolePadd.ps1 @@ -78,8 +78,8 @@ https://TODO } $Object = [PSCustomObject]@{ - CpuPercent = $Response."%cpu" - MemoryPercent = $Response."%mem" + CpuPercent = [math]::Round([double]$Response."%cpu", 2) + MemoryPercent = [math]::Round([double]$Response."%mem", 2) ActiveClients = $Response.active_clients Blocking = $Response.blocking Cache = $Cache