fix: Upload to HRDLog
This commit is contained in:
@@ -6,7 +6,6 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@@ -117,61 +116,9 @@ func UploadHRDLog(ctx context.Context, client *http.Client, callsign, code, adif
|
||||
return UploadResult{OK: false, Message: reason}, fmt.Errorf("hrdlog: upload failed: %s", reason)
|
||||
}
|
||||
|
||||
// UploadHRDLogADIF pushes a WHOLE ADIF document (header + many records) to
|
||||
// HRDLog.net in one NewEntry request — HRDLog parses every <eor> record and
|
||||
// replies "<insert>N" with the number actually inserted (duplicates aren't
|
||||
// counted but aren't errors). Use this for bulk uploads instead of calling
|
||||
// UploadHRDLog once per QSO.
|
||||
func UploadHRDLogADIF(ctx context.Context, client *http.Client, callsign, code, adifDoc string) (UploadResult, error) {
|
||||
callsign = strings.ToUpper(strings.TrimSpace(callsign))
|
||||
code = strings.TrimSpace(code)
|
||||
if callsign == "" {
|
||||
return UploadResult{}, fmt.Errorf("hrdlog: station callsign not set")
|
||||
}
|
||||
if code == "" {
|
||||
return UploadResult{}, fmt.Errorf("hrdlog: upload code not set")
|
||||
}
|
||||
if strings.TrimSpace(adifDoc) == "" {
|
||||
return UploadResult{}, fmt.Errorf("hrdlog: empty adif")
|
||||
}
|
||||
|
||||
body, err := hrdlogPost(ctx, client, callsign, code, adifDoc)
|
||||
if err != nil {
|
||||
return UploadResult{OK: false, Message: body}, err
|
||||
}
|
||||
if reason := authErrHRDLog(body); reason != "" {
|
||||
return UploadResult{OK: false, Message: reason}, fmt.Errorf("hrdlog: %s", reason)
|
||||
}
|
||||
if n, ok := parseHRDLogInsert(body); ok {
|
||||
return UploadResult{OK: true, Message: fmt.Sprintf("%d added", n)}, nil
|
||||
}
|
||||
if strings.Contains(strings.ToLower(body), "<error>") {
|
||||
return UploadResult{OK: false, Message: body}, fmt.Errorf("hrdlog: %s", body)
|
||||
}
|
||||
return UploadResult{OK: true, Message: "uploaded"}, nil
|
||||
}
|
||||
|
||||
// parseHRDLogInsert reads N from "<insert>N" (or "<insert>N</insert>").
|
||||
func parseHRDLogInsert(body string) (int, bool) {
|
||||
b := strings.ToLower(body)
|
||||
i := strings.Index(b, "<insert>")
|
||||
if i < 0 {
|
||||
return 0, false
|
||||
}
|
||||
rest := b[i+len("<insert>"):]
|
||||
j := 0
|
||||
for j < len(rest) && rest[j] >= '0' && rest[j] <= '9' {
|
||||
j++
|
||||
}
|
||||
if j == 0 {
|
||||
return 0, false
|
||||
}
|
||||
n, err := strconv.Atoi(rest[:j])
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
return n, true
|
||||
}
|
||||
// NOTE: HRDLog's NewEntry.aspx inserts ONLY the first record of a multi-record
|
||||
// ADIFData, so there is no batch upload — callers must POST one record per
|
||||
// request (see UploadHRDLog). The bulk uploader in app.go does exactly that.
|
||||
|
||||
// TestHRDLog validates the configured HRDLog credentials with a REAL request:
|
||||
// it posts an empty ADIF so nothing is inserted, then checks for HRDLog's auth
|
||||
|
||||
@@ -625,6 +625,29 @@ func (r *Repo) MarkLoTWUploaded(ctx context.Context, id int64, date string) erro
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarkUploadedBatch sets <statusCol>='Y' and <dateCol>=date on EVERY id in one
|
||||
// UPDATE — used by bulk upload (Club Log / HRDLog) so a 25k-QSO run isn't one
|
||||
// round-trip per QSO on a remote MySQL. statusCol/dateCol come from a fixed
|
||||
// whitelist (not user input), so the column interpolation is safe.
|
||||
func (r *Repo) MarkUploadedBatch(ctx context.Context, statusCol, dateCol, date string, ids []int64) error {
|
||||
if len(ids) == 0 {
|
||||
return nil
|
||||
}
|
||||
ph := strings.TrimSuffix(strings.Repeat("?,", len(ids)), ",")
|
||||
args := make([]any, 0, len(ids)+2)
|
||||
args = append(args, date, db.NowISO())
|
||||
for _, id := range ids {
|
||||
args = append(args, id)
|
||||
}
|
||||
_, err := r.db.ExecContext(ctx,
|
||||
`UPDATE qso SET `+statusCol+` = 'Y', `+dateCol+` = ?, updated_at = ? WHERE id IN (`+ph+`)`,
|
||||
args...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("mark uploaded batch (%d): %w", len(ids), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarkEQSLSent stamps EQSL_QSL_SENT=Y and the sent date after a successful
|
||||
// eQSL e-mail. date is an ADIF YYYYMMDD string.
|
||||
func (r *Repo) MarkEQSLSent(ctx context.Context, id int64, date string) error {
|
||||
|
||||
Reference in New Issue
Block a user