fix: a test button that cannot fail is worse than no button

TestClublog checked that three fields were non-empty and returned "Ready — CALL
via EMAIL". Nothing was ever sent to Club Log, so a wrong password produced the
identical green message. It now signs in, through getadif.php because that is
the one authenticated endpoint that cannot change anything: a test must never
put a record into someone's log. A future start year keeps it from downloading
130 000 QSOs to prove a password, and a rejected login answers 403 before any
body arrives.

LoTW is two credentials doing two jobs and the button reported only the first.
Uploads go through TQSL signed by the certificate — the website password is
never involved — so a wrong one breaks nothing until the day confirmations are
downloaded, by which time nobody connects the two events. Both are now checked
and, more importantly, reported separately.

Also: the detector still refused 12 and 10 m while the PSK Reporter feed was
already subscribed to them, so those decodes were fetched and thrown away. The
rule was never "HF is out", it is "is an opening here an event" — 20 m being
open is the normal state of the band, 10 m opening is not.
This commit is contained in:
2026-08-11 13:16:09 +02:00
parent 9c33feecfa
commit 0550ecdac3
4 changed files with 108 additions and 11 deletions
+25 -2
View File
@@ -277,10 +277,33 @@ func TestLoTW(cfg ServiceConfig, stationDataPath string) (string, error) {
if err != nil {
return "", fmt.Errorf("lotw: can't read station locations: %w", err)
}
found := ""
for _, l := range locs {
if strings.EqualFold(l.Name, loc) {
return fmt.Sprintf("Ready — TQSL found, location %q (%s)", l.Name, l.Call), nil
found = l.Call
break
}
}
return "", fmt.Errorf("lotw: station location %q not found in TQSL", loc)
if found == "" {
return "", fmt.Errorf("lotw: station location %q not found in TQSL", loc)
}
// LoTW is TWO credentials doing two jobs, and the button used to report only
// the first. Uploading goes through TQSL and is signed by the certificate —
// the website password is never involved, so a wrong one breaks nothing until
// the day confirmations are downloaded and nobody connects the two events.
//
// So the download login is tested separately, and said separately. A future
// "since" date makes LoTW return an empty report rather than the whole
// account: the credentials are what is being checked, not the log.
up := fmt.Sprintf("Ready — TQSL found, location %q (%s)", loc, found)
if strings.TrimSpace(cfg.Username) == "" || cfg.Password == "" {
return up + ". Download login not set — confirmations cannot be fetched.", nil
}
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if _, err := DownloadLoTWConfirmations(ctx, nil, cfg, "2099-01-01", ""); err != nil {
return "", fmt.Errorf("%s — but the DOWNLOAD login failed: %w", up, err)
}
return up + ". Download login accepted.", nil
}