Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion PiHoleShell/PiHoleShell.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Export-ModuleMember -Function @(
#Padd
'Get-PiHolePadd', `
#Metrics
'Get-PiHoleStatsRecentBlocked', 'Get-PiHoleStatsQueryType', 'Get-PiHoleStatsTopDomain', 'Get-PiHoleStatsSummary', 'Get-PiHoleStatsTopClient' `
'Get-PiHoleStatsRecentBlocked', 'Get-PiHoleStatsQueryType', 'Get-PiHoleStatsTopDomain', 'Get-PiHoleStatsSummary', 'Get-PiHoleStatsTopClient', 'Get-PiHoleStatsQuerySuggestions' `
#ListManagement
'Get-PiHoleList', 'Search-PiHoleListDomain', 'Add-PiHoleList', 'Remove-PiHoleList', `
#FTLInformation
Expand Down
77 changes: 77 additions & 0 deletions PiHoleShell/Public/Metrics/Get-PiHoleStatsQuerySuggestions.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
function Get-PiHoleStatsQuerySuggestions {
<#
.SYNOPSIS
Get query filter suggestions

.DESCRIPTION
Returns suggested values seen in recent queries for each filter accepted by the queries
endpoint: domain, client IP, client name, upstream, query type, status, reply, and DNSSEC status.

.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
Get-PiHoleStatsQuerySuggestions -PiHoleServer "http://pihole.domain.com:8080" -Password "fjdsjfldsjfkldjslafjskdl"
#>
[CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#get-/queries/suggestions')]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification = "Suggestions is plural because the API returns multiple categories of suggested filter values")]
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/queries/suggestions"
Method = "Get"
SkipCertificateCheck = $IgnoreSsl
ContentType = "application/json"
}

$Response = Invoke-RestMethod @Params

if ($RawOutput) {
Write-Output $Response
}
else {
$Object = [PSCustomObject]@{
Domain = $Response.suggestions.domain
ClientIp = $Response.suggestions.client_ip
ClientName = $Response.suggestions.client_name
Upstream = $Response.suggestions.upstream
Type = $Response.suggestions.type
Status = $Response.suggestions.status
Reply = $Response.suggestions.reply
Dnssec = $Response.suggestions.dnssec
}
Write-Output $Object
}
}

catch {
Write-Error -Message $_.Exception.Message
}

finally {
if ($Sid) {
Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl
}
}
}
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ Functions marked 🚧 are still under active development — signatures and outp

| Function | Description |
|---|---|
| `Get-PiHoleStatsQuerySuggestions` | Get query filter suggestions |
| `Get-PiHoleStatsQueryType` | _No description yet_ |
| `Get-PiHoleStatsRecentBlocked` | Request most recently blocked domain |
| `Get-PiHoleStatsSummary` | Get overview of Pi-hole activity Request various query, system, and FTL properties |
Expand Down
47 changes: 47 additions & 0 deletions tests/Get-PiHoleStatsQuerySuggestions.Integration.Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Requires -Module Pester
#
# Integration tests that call a REAL Pi-hole server. Configure tests/IntegrationConfig.local.ps1
# (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically
# if that file is missing.

# Config availability must be known at discovery time so the -Skip parameter on each It block
# (evaluated during discovery, before BeforeAll runs) sees the correct value.
$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1')

Describe 'Get-PiHoleStatsQuerySuggestions (Integration)' -Tag 'Integration' {
BeforeAll {
Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force

# Recomputed here (not read from the discovery-time $script:ConfigAvailable above) because
# Pester runs discovery and run in separate scopes, so BeforeAll cannot see that value.
$configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1'
if (Test-Path $configPath) {
. $configPath
$script:PiHoleServer = $PiHoleServer
$script:PiHoleToken = $PiHoleToken
$script:PiHoleIgnoreSsl = $PiHoleIgnoreSsl
}
}

It 'returns filter suggestions as a formatted object' -Skip:(-not $script:ConfigAvailable) {
$result = Get-PiHoleStatsQuerySuggestions -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl

$result | Should -Not -BeNullOrEmpty
$result.Type | Should -Not -BeNullOrEmpty
$result.Status | Should -Not -BeNullOrEmpty
$result.Reply | Should -Not -BeNullOrEmpty
$result.Dnssec | Should -Not -BeNullOrEmpty
}

It 'returns the raw API response when RawOutput is set' -Skip:(-not $script:ConfigAvailable) {
$result = Get-PiHoleStatsQuerySuggestions -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -RawOutput $true

$result.suggestions | Should -Not -BeNullOrEmpty
}

It 'errors when given a bad password' -Skip:(-not $script:ConfigAvailable) {
$result = Get-PiHoleStatsQuerySuggestions -PiHoleServer $script:PiHoleServer -Password 'definitely-not-the-real-token' -IgnoreSsl $script:PiHoleIgnoreSsl -ErrorVariable errOut -ErrorAction SilentlyContinue

$errOut | Should -Not -BeNullOrEmpty
}
}
Loading