Switch to using custom type for pihole's top blocked domains

This commit is contained in:
Svilen Markov 2024-09-30 00:24:44 +01:00
parent 28167403a4
commit 672547cd07

View File

@ -1,6 +1,7 @@
package feed package feed
import ( import (
"encoding/json"
"errors" "errors"
"log/slog" "log/slog"
"net/http" "net/http"
@ -14,19 +15,28 @@ type piholeStatsResponse struct {
BlockedQueries int `json:"ads_blocked_today"` BlockedQueries int `json:"ads_blocked_today"`
BlockedSeries map[int64]int `json:"ads_over_time"` BlockedSeries map[int64]int `json:"ads_over_time"`
BlockedPercentage float64 `json:"ads_percentage_today"` BlockedPercentage float64 `json:"ads_percentage_today"`
TopBlockedDomains map[string]int `json:"top_ads"` TopBlockedDomains piholeTopBlockedDomains `json:"top_ads"`
DomainsBlocked int `json:"domains_being_blocked"` DomainsBlocked int `json:"domains_being_blocked"`
} }
// If user has some level of privacy enabled on Pihole, `json:"top_ads"` is an empty array // If user has some level of privacy enabled on Pihole, `json:"top_ads"` is an empty array
// Use alternate struct without that field to avoid error when unmarshalling // Use custom unmarshal behavior to avoid not getting the rest of the valid data when unmarshalling
type piholeStatsResponsePrivate struct { type piholeTopBlockedDomains map[string]int
TotalQueries int `json:"dns_queries_today"`
QueriesSeries map[int64]int `json:"domains_over_time"` func (p *piholeTopBlockedDomains) UnmarshalJSON(data []byte) error {
BlockedQueries int `json:"ads_blocked_today"` // NOTE: do not change to piholeTopBlockedDomains type here or it will cause a stack overflow
BlockedSeries map[int64]int `json:"ads_over_time"` // because of the UnmarshalJSON method getting called recursively
BlockedPercentage float64 `json:"ads_percentage_today"` temp := make(map[string]int)
DomainsBlocked int `json:"domains_being_blocked"`
err := json.Unmarshal(data, &temp)
if err != nil {
*p = make(piholeTopBlockedDomains)
} else {
*p = temp
}
return nil
} }
func FetchPiholeStats(instanceURL, token string) (*DNSStats, error) { func FetchPiholeStats(instanceURL, token string) (*DNSStats, error) {
@ -45,24 +55,10 @@ func FetchPiholeStats(instanceURL, token string) (*DNSStats, error) {
responseJson, err := decodeJsonFromRequest[piholeStatsResponse](defaultClient, request) responseJson, err := decodeJsonFromRequest[piholeStatsResponse](defaultClient, request)
if err != nil {
// Refer to piholeStatsResponsePrivate above
responseJsonPriv, err :=
decodeJsonFromRequest[piholeStatsResponsePrivate](defaultClient, request)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Copy the results back to responseJson, leaving the TopBlockedDomains field empty
responseJson.TotalQueries = responseJsonPriv.TotalQueries
responseJson.QueriesSeries = responseJsonPriv.QueriesSeries
responseJson.BlockedQueries = responseJsonPriv.BlockedQueries
responseJson.BlockedSeries = responseJsonPriv.BlockedSeries
responseJson.BlockedPercentage = responseJsonPriv.BlockedPercentage
responseJson.TopBlockedDomains = make(map[string]int)
responseJson.DomainsBlocked = responseJsonPriv.DomainsBlocked
}
stats := &DNSStats{ stats := &DNSStats{
TotalQueries: responseJson.TotalQueries, TotalQueries: responseJson.TotalQueries,
BlockedQueries: responseJson.BlockedQueries, BlockedQueries: responseJson.BlockedQueries,