Public/Get-PiHoleDbTopClients.ps1
function Get-PiHoleDbTopClients { <# .SYNOPSIS Retrieves top clients data from the Pi-hole long-term database. .DESCRIPTION This function authenticates to the Pi-hole API using Connect-PiHole, retrieves top clients data from the long-term database, and then disconnects the session using Disconnect-PiHole. .PARAMETER BaseUrl The base URL of the Pi-hole instance (e.g., http://pi.hole). .PARAMETER Credential A PSCredential object containing the Pi-hole password. .PARAMETER From DateTime from when the data should be requested. Accepts DateTime objects or date strings like '5-7-2025 3:34PM'. .PARAMETER Until DateTime until when the data should be requested. Accepts DateTime objects or date strings like '5-7-2025 3:34PM'. .PARAMETER Blocked Switch parameter to return information about blocked queries instead of permitted queries. .PARAMETER Count Number of requested items. Default is 10. .OUTPUTS A PSCustomObject containing the top clients data, total queries, blocked queries, and processing time. .EXAMPLE $cred = Get-Credential $from = Get-Date "2023-01-01 12:00:00" $until = Get-Date "2023-01-02 12:00:00" Get-PiHoleDbTopClients -BaseUrl 'http://pi.hole' -Credential $cred -From $from -Until $until .EXAMPLE # Get top 20 blocked clients using string dates $cred = Get-Credential Get-PiHoleDbTopClients -BaseUrl 'http://pi.hole' -Credential $cred -From '5-7-2025 3:34PM' -Until '5-7-2025 11:59PM' -Blocked -Count 20 .EXAMPLE # Get top 5 permitted clients for the last 24 hours $cred = Get-Credential $until = Get-Date $from = $until.AddDays(-1) Get-PiHoleDbTopClients -BaseUrl 'http://pi.hole' -Credential $cred -From $from -Until $until -Count 5 #> param ( [Parameter(Mandatory = $true)] [string]$BaseUrl, [Parameter(Mandatory = $true)] [System.Management.Automation.PSCredential]$Credential, [Parameter(Mandatory = $true)] [DateTime]$From, [Parameter(Mandatory = $true)] [DateTime]$Until, [Parameter()] [switch]$Blocked, [Parameter()] [int]$Count = 10 ) begin { # Validate BaseUrl uses http if (-not $BaseUrl.StartsWith('http://')) { throw "Error: BaseUrl must use the 'http' scheme." } # Validate DateTime parameters if ($From -gt $Until) { throw "Error: From DateTime cannot be greater than Until DateTime." } # Validate Count parameter if ($Count -lt 1) { throw "Error: Count must be greater than 0." } } process { $sessionData = $null try { Write-Verbose "Starting authentication to Pi-hole at $BaseUrl" # Authenticate and get session data $sessionData = Connect-PiHole -BaseUrl $BaseUrl -Credential $Credential Write-Verbose "Authentication successful. Session ID: $($sessionData.ID), SID: $($sessionData.SID)" # Convert DateTime to Unix timestamps for API call $fromUnix = [DateTimeOffset]::new($From).ToUnixTimeSeconds() $untilUnix = [DateTimeOffset]::new($Until).ToUnixTimeSeconds() Write-Verbose "Converted dates - From: $From ($fromUnix), Until: $Until ($untilUnix)" # Prepare API request to get top clients data $blockedValue = if ($Blocked) { "1" } else { "0" } $url = "$BaseUrl/api/stats/database/top_clients?from=$fromUnix&until=$untilUnix&blocked=$blockedValue&count=$Count" Write-Verbose "Making API request to: $url" $headers = @{ 'X-FTL-SID' = $sessionData.SID } $response = Invoke-RestMethod -Uri $url -Method Get -Headers $headers -ErrorAction Stop Write-Verbose "API request successful. Retrieved $($response.clients.Count) top clients" # Return the response as-is Write-Verbose "Successfully retrieved top clients data" return $response } catch { Write-Error "Error occurred: $($_.Exception.Message)" Write-Verbose "Full error details: $($_ | Out-String)" # Try to disconnect if we have session data if ($sessionData -and $sessionData.ID -and $sessionData.SID) { Write-Verbose "Attempting to disconnect session due to error..." try { Disconnect-PiHole -BaseUrl $BaseUrl -Id $sessionData.ID -SID $sessionData.SID Write-Verbose "Session disconnected successfully" } catch { Write-Warning "Failed to disconnect session: $($_.Exception.Message)" } } throw } finally { # Clean disconnect in finally block if ($sessionData -and $sessionData.ID -and $sessionData.SID) { Write-Verbose "Attempting final session cleanup..." try { Disconnect-PiHole -BaseUrl $BaseUrl -Id $sessionData.ID -SID $sessionData.SID Write-Verbose "Final session cleanup completed successfully" } catch { Write-Warning "Failed to clean up session in finally block: $($_.Exception.Message)" } } } } end { # Nothing to clean up in the end block } } |