chore: release v021.4

This commit is contained in:
2026-07-27 00:16:17 +02:00
parent aefb984974
commit cb27aa5ebf
13 changed files with 457 additions and 35 deletions
+50 -1
View File
@@ -279,6 +279,14 @@ const (
keyExtEQSLAutoUpload = "extsvc.eqsl.auto_upload"
keyExtEQSLUploadMode = "extsvc.eqsl.upload_mode"
// Cloudlog and its fork Wavelog are self-hosted, so the instance URL is part
// of the configuration (there is no fixed endpoint).
keyExtCloudlogURL = "extsvc.cloudlog.url"
keyExtCloudlogAPIKey = "extsvc.cloudlog.api_key"
keyExtCloudlogStationID = "extsvc.cloudlog.station_id"
keyExtCloudlogAutoUpload = "extsvc.cloudlog.auto_upload"
keyExtCloudlogUploadMode = "extsvc.cloudlog.upload_mode"
keyExtPotaToken = "extsvc.pota.token" // pota.app session token for hunter-log sync
keyExtLoTWTQSLPath = "extsvc.lotw.tqsl_path"
@@ -8512,7 +8520,9 @@ func (a *App) loadExternalServices() extsvc.ExternalServices {
keyExtLoTWAutoUpload, keyExtLoTWUploadMode,
keyExtLoTWUsername, keyExtLoTWWebPassword,
keyExtHRDLogCallsign, keyExtHRDLogCode, keyExtHRDLogAutoUpload, keyExtHRDLogUploadMode,
keyExtEQSLUsername, keyExtEQSLPassword, keyExtEQSLQTHNick, keyExtEQSLAutoUpload, keyExtEQSLUploadMode)
keyExtEQSLUsername, keyExtEQSLPassword, keyExtEQSLQTHNick, keyExtEQSLAutoUpload, keyExtEQSLUploadMode,
keyExtCloudlogURL, keyExtCloudlogAPIKey, keyExtCloudlogStationID,
keyExtCloudlogAutoUpload, keyExtCloudlogUploadMode)
if err != nil {
return out
}
@@ -8582,6 +8592,13 @@ func (a *App) loadExternalServices() extsvc.ExternalServices {
out.EQSL.Username = p.Callsign
}
}
out.Cloudlog = extsvc.ServiceConfig{
URL: m[keyExtCloudlogURL],
APIKey: m[keyExtCloudlogAPIKey],
StationID: m[keyExtCloudlogStationID],
AutoUpload: m[keyExtCloudlogAutoUpload] == "1",
UploadMode: extsvc.UploadMode(m[keyExtCloudlogUploadMode]),
}
return out
}
@@ -8639,6 +8656,17 @@ func (a *App) SaveExternalServices(cfg extsvc.ExternalServices) error {
if cfg.EQSL.AutoUpload {
eqAuto = "1"
}
// Cloudlog has no per-QSO upload-status column in the logbook, so the
// on-close sweep (which selects by that column) cannot apply — force any
// stored on_close back to immediate rather than silently doing nothing.
clgMode := modeOf(cfg.Cloudlog.UploadMode)
if clgMode == string(extsvc.ModeOnClose) {
clgMode = string(extsvc.ModeImmediate)
}
clgAuto := "0"
if cfg.Cloudlog.AutoUpload {
clgAuto = "1"
}
scope := a.profileScope() // write under the active profile's prefix
for k, v := range map[string]string{
keyExtQRZAPIKey: strings.TrimSpace(cfg.QRZ.APIKey),
@@ -8674,6 +8702,12 @@ func (a *App) SaveExternalServices(cfg extsvc.ExternalServices) error {
keyExtEQSLQTHNick: strings.TrimSpace(cfg.EQSL.QTHNickname),
keyExtEQSLAutoUpload: eqAuto,
keyExtEQSLUploadMode: eqMode,
keyExtCloudlogURL: strings.TrimSpace(cfg.Cloudlog.URL),
keyExtCloudlogAPIKey: strings.TrimSpace(cfg.Cloudlog.APIKey),
keyExtCloudlogStationID: strings.TrimSpace(cfg.Cloudlog.StationID),
keyExtCloudlogAutoUpload: clgAuto,
keyExtCloudlogUploadMode: clgMode,
} {
if err := a.settings.Set(a.ctx, scope+k, v); err != nil {
return err
@@ -8712,6 +8746,12 @@ func (a *App) TestEQSLUpload() (string, error) {
return extsvc.TestEQSL(a.ctx, nil, a.loadExternalServices().EQSL)
}
// TestCloudlogUpload checks the Cloudlog/Wavelog URL, API key and station id
// against the user's own instance, without inserting anything.
func (a *App) TestCloudlogUpload() (string, error) {
return extsvc.TestCloudlog(a.ctx, nil, a.loadExternalServices().Cloudlog)
}
// ── QSL Manager (manual upload) ────────────────────────────────────────
// uploadColumnFor maps a service id to its QSO sent-status column.
@@ -9999,6 +10039,12 @@ func (a *App) extShouldUpload(svc extsvc.Service, id int64) bool {
return false
}
return true
case extsvc.ServiceCloudlog:
// No per-QSO status column for Cloudlog: it dedupes server-side (its API
// checks each incoming record against the log), so re-sending is harmless
// and every QSO is eligible. The cost is that a permanently failed upload
// is not remembered — hence no on-close mode and no manual backlog.
return true
case extsvc.ServiceLoTW:
for _, f := range a.loadExternalServices().LoTW.UploadFlags {
if strings.EqualFold(q.LOTWSent, f) {
@@ -10034,6 +10080,9 @@ func (a *App) markExtUploaded(svc extsvc.Service, id int64, logID string) {
err = a.qso.MarkHRDLogUploaded(ctx, id, date)
case extsvc.ServiceEQSL:
err = a.qso.MarkEQSLSent(ctx, id, date)
case extsvc.ServiceCloudlog:
// Nothing to stamp — see extShouldUpload. Still logged and announced so
// the upload is visible in the diagnostic log and the UI.
}
if err != nil {
applog.Printf("extsvc: mark %s uploaded %d failed: %v", svc, id, err)