feat: implemented HRDLog upload

This commit is contained in:
2026-06-18 14:27:33 +02:00
parent e8eedcc1dc
commit cdd71b17c8
11 changed files with 333 additions and 8 deletions
+52 -1
View File
@@ -190,6 +190,11 @@ const (
keyExtClublogAutoUpload = "extsvc.clublog.auto_upload"
keyExtClublogUploadMode = "extsvc.clublog.upload_mode"
keyExtHRDLogCallsign = "extsvc.hrdlog.callsign"
keyExtHRDLogCode = "extsvc.hrdlog.code" // HRDLog account upload code
keyExtHRDLogAutoUpload = "extsvc.hrdlog.auto_upload"
keyExtHRDLogUploadMode = "extsvc.hrdlog.upload_mode"
keyExtPotaToken = "extsvc.pota.token" // pota.app session token for hunter-log sync
keyExtLoTWTQSLPath = "extsvc.lotw.tqsl_path"
@@ -4867,7 +4872,8 @@ func (a *App) loadExternalServices() extsvc.ExternalServices {
keyExtLoTWTQSLPath, keyExtLoTWStationLoc, keyExtLoTWForceCall, keyExtLoTWKeyPassword,
keyExtLoTWUploadFlag, keyExtLoTWUploadFlags, keyExtLoTWWriteLog,
keyExtLoTWAutoUpload, keyExtLoTWUploadMode,
keyExtLoTWUsername, keyExtLoTWWebPassword)
keyExtLoTWUsername, keyExtLoTWWebPassword,
keyExtHRDLogCallsign, keyExtHRDLogCode, keyExtHRDLogAutoUpload, keyExtHRDLogUploadMode)
if err != nil {
return out
}
@@ -4912,6 +4918,18 @@ func (a *App) loadExternalServices() extsvc.ExternalServices {
if out.LoTW.TQSLPath == "" {
out.LoTW.TQSLPath = extsvc.DefaultTQSLPath()
}
out.HRDLog = extsvc.ServiceConfig{
Callsign: m[keyExtHRDLogCallsign],
Code: m[keyExtHRDLogCode],
AutoUpload: m[keyExtHRDLogAutoUpload] == "1",
UploadMode: extsvc.UploadMode(m[keyExtHRDLogUploadMode]),
}
// Default the HRDLog callsign to the active profile's call when unset.
if out.HRDLog.Callsign == "" && a.profiles != nil {
if p, perr := a.profiles.Active(a.ctx); perr == nil {
out.HRDLog.Callsign = p.Callsign
}
}
return out
}
@@ -4959,6 +4977,11 @@ func (a *App) SaveExternalServices(cfg extsvc.ExternalServices) error {
if cfg.LoTW.WriteLog {
ltWriteLog = "1"
}
hlMode := modeOf(cfg.HRDLog.UploadMode)
hlAuto := "0"
if cfg.HRDLog.AutoUpload {
hlAuto = "1"
}
scope := a.profileScope() // write under the active profile's prefix
for k, v := range map[string]string{
keyExtQRZAPIKey: strings.TrimSpace(cfg.QRZ.APIKey),
@@ -4983,6 +5006,11 @@ func (a *App) SaveExternalServices(cfg extsvc.ExternalServices) error {
keyExtLoTWUploadMode: ltMode,
keyExtLoTWUsername: strings.TrimSpace(cfg.LoTW.Username),
keyExtLoTWWebPassword: cfg.LoTW.Password,
keyExtHRDLogCallsign: strings.ToUpper(strings.TrimSpace(cfg.HRDLog.Callsign)),
keyExtHRDLogCode: strings.TrimSpace(cfg.HRDLog.Code),
keyExtHRDLogAutoUpload: hlAuto,
keyExtHRDLogUploadMode: hlMode,
} {
if err := a.settings.Set(a.ctx, scope+k, v); err != nil {
return err
@@ -5011,6 +5039,11 @@ func (a *App) TestClublogUpload() (string, error) {
return extsvc.TestClublog(a.ctx, a.loadExternalServices().Clublog)
}
// TestHRDLogUpload validates that the HRDLog credentials are complete.
func (a *App) TestHRDLogUpload() (string, error) {
return extsvc.TestHRDLog(a.ctx, nil, a.loadExternalServices().HRDLog)
}
// ── QSL Manager (manual upload) ────────────────────────────────────────
// uploadColumnFor maps a service id to its QSO sent-status column.
@@ -5022,6 +5055,8 @@ func uploadColumnFor(service string) string {
return "clublog_qso_upload_status"
case extsvc.ServiceLoTW:
return "lotw_sent"
case extsvc.ServiceHRDLog:
return "hrdlog_qso_upload_status"
}
return ""
}
@@ -5160,6 +5195,8 @@ func (a *App) runManualUpload(svc extsvc.Service, ids []int64, cfg extsvc.Extern
switch svc {
case extsvc.ServiceQRZ:
res, err = extsvc.UploadQRZ(ctx, nil, cfg.QRZ.APIKey, rec)
case extsvc.ServiceHRDLog:
res, err = extsvc.UploadHRDLog(ctx, nil, cfg.HRDLog.Callsign, cfg.HRDLog.Code, rec)
default:
res, err = extsvc.UploadClublog(ctx, nil, cfg.Clublog, rec)
}
@@ -5731,6 +5768,8 @@ func (a *App) uploadOwnerCall(svc extsvc.Service) string {
owner = cfg.QRZ.ForceStationCallsign
case extsvc.ServiceClublog:
owner = cfg.Clublog.Callsign
case extsvc.ServiceHRDLog:
owner = cfg.HRDLog.Callsign
}
owner = strings.ToUpper(strings.TrimSpace(owner))
if owner == "" && a.profiles != nil {
@@ -5821,6 +5860,12 @@ func (a *App) extShouldUpload(svc extsvc.Service, id int64) bool {
return false
}
return true
case extsvc.ServiceHRDLog:
if strings.EqualFold(q.HRDLogUploadStatus, "Y") {
applog.Printf("extsvc: QSO %d not eligible for hrdlog — HRDLogUploadStatus already %q (set Confirmations default to N to upload)", id, q.HRDLogUploadStatus)
return false
}
return true
case extsvc.ServiceLoTW:
for _, f := range a.loadExternalServices().LoTW.UploadFlags {
if strings.EqualFold(q.LOTWSent, f) {
@@ -5855,6 +5900,12 @@ func (a *App) markExtUploaded(svc extsvc.Service, id int64, logID string) {
applog.Printf("extsvc: mark lotw uploaded %d: %v", id, err)
}
}
case extsvc.ServiceHRDLog:
if a.qso != nil {
if err := a.qso.MarkHRDLogUploaded(a.ctx, id, date); err != nil {
applog.Printf("extsvc: mark hrdlog uploaded %d: %v", id, err)
}
}
}
if a.ctx != nil {
wruntime.EventsEmit(a.ctx, "extsvc:uploaded", map[string]any{