feat(hamlog): read confirmations back from a HAMLOG.online ADIF

Their agent protocol has no download verb, so the return path is a file
exported from their site. Running that file through the ordinary ADIF
import is the wrong tool and does real damage: it matches on callsign +
UTC minute + band + mode, their export is rebuilt from their own
database and rarely agrees to the minute, and 'update duplicates' then
inserts everything that failed to match -- several hundred copies of
contacts already in the log.

This path matches only. It stamps the confirmation on QSOs it finds,
falls back to the mode-CLASS key for the modes their export renames, and
REPORTS what it could not match instead of adding it: an unmatched
confirmation is a question about the log, not a contact to create.

Also logs and reports how many rows a delete actually removed -- silence
there made a delete that did nothing indistinguishable from one that
worked.
This commit is contained in:
2026-08-23 15:32:41 +02:00
parent 20784c2fb1
commit 803f4dc4ed
10 changed files with 259 additions and 8 deletions
+10 -1
View File
@@ -6508,7 +6508,16 @@ func (a *App) DeleteQSOs(ids []int64) (int64, error) {
}
a.deleteRemoteCopies(ids)
a.syncPublishDeletes(ids)
return a.qso.DeleteMany(a.ctx, ids)
n, err := a.qso.DeleteMany(a.ctx, ids)
// Logged because a delete that does nothing is otherwise indistinguishable
// from a delete that worked: the rows leave the grid either way once it
// reloads, and the only place the truth survives is here.
if err != nil {
applog.Printf("delete: %d QSO(s) requested, FAILED: %v", len(ids), err)
} else {
applog.Printf("delete: %d QSO(s) requested, %d row(s) removed", len(ids), n)
}
return n, err
}
// DuplicateGroup is a set of QSOs the log considers the same contact.