feat(watchlist): the ClubLog expedition enrichment — phase 2 lands
clublog.org/watch.php, per entry: the DXpedition flag, OQRS, LiveStream, the log's QSO total and the last-24h rate — the fields the schema has carried since phase 1. Refreshed on DXHunter's own cadence (hourly for expeditions, six-hourly for the rest), two at a time with a breath between requests: the application API key is shared by every install, so a hundred-entry list must read as a trickle at ClubLog's end. Nothing to configure — OpsLog's own key, already used for cty and Most Wanted, serves. A starred pattern is asked about by its base (ClubLog has no log for VK9*). The card gains the 24h rate beside the QSO total and the Live link to the expedition's stream.
This commit is contained in:
@@ -7,7 +7,9 @@ package main
|
||||
// worked-today answer contest entries are judged by).
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -234,3 +236,58 @@ func (a *App) watchSpot(dxCall, band, mode, country, comment string, freqHz int6
|
||||
"visual": true,
|
||||
})
|
||||
}
|
||||
|
||||
// startWatchlistClubLog begins the expedition enrichment: every entry's
|
||||
// ClubLog block (expedition flag, OQRS, LiveStream, QSO totals and 24 h rate)
|
||||
// is refreshed on a rolling schedule — hourly for expeditions, six-hourly for
|
||||
// the rest, DXHunter's own cadence. OpsLog's application API key is used, so
|
||||
// there is nothing to configure.
|
||||
//
|
||||
// Two at a time with a breath between requests: the key is shared by every
|
||||
// OpsLog install, and a hundred-entry watchlist must read as a trickle at
|
||||
// ClubLog's end, not a burst.
|
||||
func (a *App) startWatchlistClubLog() {
|
||||
if a.watchlist == nil {
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
client := &http.Client{Timeout: 30 * time.Second}
|
||||
// Let the app finish starting before the first network pass.
|
||||
time.Sleep(15 * time.Second)
|
||||
for {
|
||||
stale := a.watchlist.StaleEntries(1*time.Hour, 6*time.Hour)
|
||||
changed := false
|
||||
for _, call := range stale {
|
||||
// The pattern's BASE is what ClubLog knows: VK9* has no log.
|
||||
base := strings.TrimSuffix(call, "*")
|
||||
if base == "" {
|
||||
continue
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
d, err := watchlist.FetchWatch(ctx, client, clublogAppAPIKey, base)
|
||||
cancel()
|
||||
if err != nil {
|
||||
applog.Printf("watchlist clublog: %s: %v", base, err)
|
||||
continue
|
||||
}
|
||||
if a.watchlist.ApplyClubLog(call, d) {
|
||||
changed = true
|
||||
if d.IsExpedition {
|
||||
applog.Printf("watchlist clublog: %s is a DXpedition (%d QSOs, %d/24h, OQRS=%v)",
|
||||
base, func() int {
|
||||
if d.ClubLogInfo != nil {
|
||||
return d.ClubLogInfo.TotalQSOs
|
||||
}
|
||||
return 0
|
||||
}(), d.QSOs24h(), d.HasOQRS)
|
||||
}
|
||||
}
|
||||
time.Sleep(400 * time.Millisecond)
|
||||
}
|
||||
if changed && a.ctx != nil {
|
||||
wruntime.EventsEmit(a.ctx, "watchlist:changed")
|
||||
}
|
||||
time.Sleep(10 * time.Minute)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user