1 Commits

Author SHA1 Message Date
will 6227d59eae Track altbody in change-detection so existing campaigns actually re-sync
CI / test (push) Successful in 10s
Campaign/parseCampaign never fetched altbody, so campaignUnchanged()
compared everything except it -- a campaign synced before v0.1.3
(altbody always null) whose content otherwise hasn't changed would be
judged unchanged forever and never get updated with the new altbody,
even though every subsequent sync now intends to send one.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 22:13:13 -04:00
3 changed files with 11 additions and 2 deletions
+4
View File
@@ -217,6 +217,10 @@ func attachmentFilename(slug, relPath string, content []byte) string {
func campaignUnchanged(existing *listmonk.Campaign, input listmonk.CampaignInput) bool {
return existing.Subject == input.Subject &&
existing.Body == input.Body &&
// altbody always mirrors body (see CampaignInput.payload) -- comparing
// it here is what catches a campaign synced before that started, whose
// stored altbody is still null even though its body hasn't changed.
existing.AltBody == input.Body &&
existing.FromEmail == input.FromEmail &&
existing.TemplateID == input.TemplateID &&
existing.Type == input.Type &&
+4 -2
View File
@@ -31,6 +31,7 @@ type fakeCampaign struct {
Status string
Subject string
Body string
AltBody string
FromEmail string
TemplateID int
Type string
@@ -138,7 +139,7 @@ func (c fakeCampaign) toJSON() map[string]any {
}
return map[string]any{
"id": c.ID, "name": c.Name, "status": c.Status, "subject": c.Subject,
"body": c.Body, "from_email": c.FromEmail, "template_id": c.TemplateID,
"body": c.Body, "altbody": c.AltBody, "from_email": c.FromEmail, "template_id": c.TemplateID,
"type": c.Type, "tags": c.Tags, "lists": lists, "media": media,
}
}
@@ -155,7 +156,7 @@ func (f *fakeListmonk) createCampaign(w http.ResponseWriter, r *http.Request) {
body := decodeBody(r)
c := fakeCampaign{
ID: f.id(), Name: str(body["name"]), Status: "draft",
Subject: str(body["subject"]), Body: str(body["body"]),
Subject: str(body["subject"]), Body: str(body["body"]), AltBody: str(body["altbody"]),
FromEmail: str(body["from_email"]), TemplateID: toInt(body["template_id"]),
Type: str(body["type"]), Tags: toStrings(body["tags"]),
ListIDs: toInts(body["lists"]), MediaIDs: toInts(body["media"]),
@@ -171,6 +172,7 @@ func (f *fakeListmonk) updateCampaign(w http.ResponseWriter, r *http.Request) {
if f.campaigns[i].ID == id {
f.campaigns[i].Subject = str(body["subject"])
f.campaigns[i].Body = str(body["body"])
f.campaigns[i].AltBody = str(body["altbody"])
f.campaigns[i].FromEmail = str(body["from_email"])
f.campaigns[i].TemplateID = toInt(body["template_id"])
f.campaigns[i].Type = str(body["type"])
+3
View File
@@ -289,6 +289,7 @@ type Campaign struct {
Status string
Subject string
Body string
AltBody string
FromEmail string
TemplateID int
Type string
@@ -381,6 +382,7 @@ func parseCampaign(data []byte) (*Campaign, error) {
Status string `json:"status"`
Subject string `json:"subject"`
Body string `json:"body"`
AltBody string `json:"altbody"`
FromEmail string `json:"from_email"`
TemplateID int `json:"template_id"`
Type string `json:"type"`
@@ -409,6 +411,7 @@ func parseCampaign(data []byte) (*Campaign, error) {
Status: parsed.Status,
Subject: parsed.Subject,
Body: parsed.Body,
AltBody: parsed.AltBody,
FromEmail: parsed.FromEmail,
TemplateID: parsed.TemplateID,
Type: parsed.Type,