chore: release v021.4
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user