feat(qsl): credit line at the foot of the default QSL e-mail
"Designed & sent by OpsLog — https://github.com/GregTroar/OpsLog/releases/latest" now closes the default body, so a fresh install sends it without being asked. Put in the TEMPLATE, not appended at send time. Two consequences, both of them the point: an operator who does not want it deletes the line once and it is gone, and one who has already written their own body never sees it appear — a stored template is returned verbatim and the default is only the fallback. Appending it at send would have made it unremovable, which is not a thing to do to somebody's outgoing mail. The link is the human release page. updateCheckURL sits next to it in update.go and answers JSON, which is the easy mistake here — a correspondent who clicks the credit gets a download page, and a test says so.
This commit is contained in:
+12
-1
@@ -45,9 +45,20 @@ const appQSLCardSentField = "APP_OPSLOG_QSL_SENT"
|
||||
// (please send one). Independent of ADIF qsl_rcvd, like the sent field.
|
||||
const appQSLCardRcvdField = "APP_OPSLOG_QSL_RCVD"
|
||||
|
||||
// qslCredit closes the default QSL e-mail: who made the card, and where the
|
||||
// recipient can get the same program.
|
||||
//
|
||||
// A DEFAULT, not a signature. It lives in the body template like every other
|
||||
// line, so an operator who does not want it deletes it once and it is gone —
|
||||
// and one who has already written their own body never sees it appear, because
|
||||
// a stored template is returned verbatim and the default is only the fallback.
|
||||
// Appending it at send time instead would have made it unremovable, which is
|
||||
// not a thing to do to someone's outgoing mail.
|
||||
const qslCredit = "--\nDesigned & sent by OpsLog — " + releasesPageURL
|
||||
|
||||
const (
|
||||
defaultQSLEmailSubject = "eQSL — {CALL} de {MYCALL}"
|
||||
defaultQSLEmailBody = "Hi,\n\nThank you for our QSO! Please find attached your eQSL card.\n\n{DATE} · {BAND} · {MODE}\n\n73,\n{MYCALL}"
|
||||
defaultQSLEmailBody = "Hi,\n\nThank you for our QSO! Please find attached your eQSL card.\n\n{DATE} · {BAND} · {MODE}\n\n73,\n{MYCALL}\n\n" + qslCredit
|
||||
)
|
||||
|
||||
// qslDir is the root of all designer artifacts: templates/<id>/ and outbox/.
|
||||
|
||||
+4
-2
@@ -4,11 +4,13 @@
|
||||
"date": "",
|
||||
"en": [
|
||||
"Right-click: update the US county of the selected contacts from the ULS database, replacing a county since renamed or abolished.",
|
||||
"A QSO logged from WSJT-X, MSHV or a net now appears in Recent QSOs at once, instead of waiting for a delayed auto-upload to send it."
|
||||
"A QSO logged from WSJT-X, MSHV or a net now appears in Recent QSOs at once, instead of waiting for a delayed auto-upload to send it.",
|
||||
"New installs: the default QSL e-mail ends with a credit line and a link to OpsLog. It is part of the template, so delete it if you'd rather not."
|
||||
],
|
||||
"fr": [
|
||||
"Clic droit : mettre à jour le comté US des contacts sélectionnés depuis la base ULS, pour remplacer un comté renommé ou supprimé.",
|
||||
"Un QSO logué depuis WSJT-X, MSHV ou un net apparaît aussitôt dans les QSO récents, sans attendre l’envoi d’un upload automatique différé."
|
||||
"Un QSO logué depuis WSJT-X, MSHV ou un net apparaît aussitôt dans les QSO récents, sans attendre l’envoi d’un upload automatique différé.",
|
||||
"Nouvelles installations : le mail QSL par défaut se termine par une ligne de crédit et un lien vers OpsLog. Elle fait partie du modèle, supprimable."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// The default QSL e-mail closes with a credit line carrying the download page.
|
||||
//
|
||||
// It is part of the BODY TEMPLATE, deliberately: an operator who does not want
|
||||
// it deletes it once, and one who already wrote their own body never sees it,
|
||||
// because a stored template is returned verbatim and the default is only the
|
||||
// fallback. Appending it at send time would have made it unremovable.
|
||||
func TestQSLCreditIsInTheDefaultBody(t *testing.T) {
|
||||
if !strings.HasSuffix(defaultQSLEmailBody, qslCredit) {
|
||||
t.Errorf("the default QSL e-mail does not end with the credit line:\n%q", defaultQSLEmailBody)
|
||||
}
|
||||
// The body still has to be a usable template — the credit is added to it,
|
||||
// not in place of it.
|
||||
for _, v := range []string{"{DATE}", "{BAND}", "{MODE}", "{MYCALL}"} {
|
||||
if !strings.Contains(defaultQSLEmailBody, v) {
|
||||
t.Errorf("the default QSL e-mail lost %s", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The link must be the page a person can read. updateCheckURL sits beside it and
|
||||
// answers JSON — sending a correspondent there is the easy mistake to make.
|
||||
func TestQSLCreditLinksTheHumanPage(t *testing.T) {
|
||||
if !strings.Contains(qslCredit, releasesPageURL) {
|
||||
t.Errorf("credit %q does not carry the releases page", qslCredit)
|
||||
}
|
||||
if strings.Contains(qslCredit, "api.github.com") {
|
||||
t.Errorf("credit %q points at the update API, which answers JSON to whoever clicks it", qslCredit)
|
||||
}
|
||||
if !strings.Contains(qslCredit, "OpsLog") {
|
||||
t.Errorf("credit %q does not name OpsLog", qslCredit)
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,11 @@ import (
|
||||
// build (the exe lives there; source stays on Gitea). Adjust the repo if needed.
|
||||
const updateCheckURL = "https://api.github.com/repos/GregTroar/OpsLog/releases/latest"
|
||||
|
||||
// releasesPageURL is the same release, for people rather than for the updater:
|
||||
// the API address above answers JSON, so it is not something to put in front of
|
||||
// an operator who followed a link out of a QSL e-mail.
|
||||
const releasesPageURL = "https://github.com/GregTroar/OpsLog/releases/latest"
|
||||
|
||||
// UpdateInfo is the result of the version check.
|
||||
type UpdateInfo struct {
|
||||
Current string `json:"current"` // this build's version (appVersion)
|
||||
|
||||
Reference in New Issue
Block a user