checker-blacklist/checker/collect.go
Pierre-Olivier Mercier ce59a976d5
All checks were successful
continuous-integration/drone/tag Build is passing
continuous-integration/drone/push Build is passing
Expose one rule per source with rule-scoped options
Each registered Source now becomes its own CheckRule (name = source ID)
implementing CheckRuleWithOptions, so the host can toggle blacklists
individually and the per-source option fields show up under the rule
that owns them instead of one flat global option list.

Collect honours the host's per-rule enable map (via the SDK's
RuleEnabled context helper) and skips the network call for disabled
sources entirely, not just their evaluation.
2026-05-19 22:12:31 +08:00

62 lines
1.6 KiB
Go

package checker
import (
"context"
"strings"
"sync"
"time"
sdk "git.happydns.org/checker-sdk-go/checker"
"golang.org/x/net/publicsuffix"
)
// Collect fans out the registered sources concurrently and folds their
// results into a single observation. Adding a new source means
// implementing the Source interface in its own file and calling
// Register(...) from init(); Collect needs no changes.
func (p *blacklistProvider) Collect(ctx context.Context, opts sdk.CheckerOptions) (any, error) {
domain := normalizeDomain(stringOpt(opts, "domain_name"))
if domain == "" {
// Standalone /check form posts "domain"; happyDomain auto-fills
// "domain_name". Accept both so the path stays uniform.
domain = normalizeDomain(stringOpt(opts, "domain"))
}
registered, _ := publicsuffix.EffectiveTLDPlusOne(domain)
if registered == "" {
registered = domain
}
data := &BlacklistData{
Domain: domain,
RegisteredDomain: registered,
CollectedAt: time.Now(),
}
sources := Sources()
per := make([][]SourceResult, len(sources))
var wg sync.WaitGroup
for i, s := range sources {
// The host disables a source by disabling its rule (rule name == source ID).
// Skip the network call entirely; Evaluate is short-circuited host-side.
if !sdk.RuleEnabled(ctx, s.ID()) {
continue
}
wg.Add(1)
go func(i int, s Source) {
defer wg.Done()
per[i] = s.Query(ctx, domain, registered, opts)
}(i, s)
}
wg.Wait()
for _, batch := range per {
data.Results = append(data.Results, batch...)
}
return data, nil
}
func normalizeDomain(s string) string {
return strings.ToLower(strings.TrimSuffix(strings.TrimSpace(s), "."))
}