"""Add savings comparison table to scheduled Listmonk campaigns."""
import json
import subprocess
API_USER = "api"
API_PASS = "6X1rKPea61N4rZ1S65Hx5zvqzbCj30F6nvEe9oVGH_Y"
LISTMONK = "http://localhost:9100"
# HTML savings table for email (inline styles, email-safe)
SAVINGS_TABLE = """
|
What you're paying now vs. what you could be paying
|
|
US Carrier (FCC Section 214)
| 214 filing + attorney | $7K-$17K |
| USF contributions (36.6%) | $12K+/yr |
| CALEA compliance | $50K-$500K+ |
| STIR/SHAKEN | $3K-$5K/yr |
| State PUC registrations | $2K-$5K/yr |
| 499-A filing + RMD | $1.5K/yr |
| Customer surcharges | +15-40% |
|
Year 1: $58K-$525K+ | Ongoing: $23K+/yr
|
|
Canadian Carrier (CRTC Registration)
| CRTC registration | $3,899 |
| USF contributions | $0 |
| CALEA equivalent | $0 |
| STIR/SHAKEN | $0 |
| Provincial registration | $0 |
| Annual maintenance | $349/yr |
| Customer surcharges | $0 |
|
Year 1: $3,899 | Ongoing: $349/yr
|
|
|
Save $55,000 - $525,000+ in Year 1
Then ~$23,000/yr ongoing • Same +1 country code • Zero customer surcharges
|
|
"""
def api_get(path):
r = subprocess.run(["curl", "-s", "-u", f"{API_USER}:{API_PASS}", f"{LISTMONK}{path}"],
capture_output=True, text=True, timeout=10)
return json.loads(r.stdout)
def api_put(path, data):
r = subprocess.run(["curl", "-s", "-X", "PUT", "-u", f"{API_USER}:{API_PASS}",
"-H", "Content-Type: application/json", "-d", json.dumps(data),
f"{LISTMONK}{path}"], capture_output=True, text=True, timeout=10)
return json.loads(r.stdout) if r.stdout else {}
# Campaigns to update with new subject lines emphasizing savings
# Only update scheduled (not yet sent) campaigns
SUBJECT_UPDATES = {
9: "Your competitors are saving $23K/yr in regulatory costs. Here's how.",
10: "$58K-$525K in Year 1 compliance costs — or $3,899. The math.",
11: "CALEA alone costs $50K-$500K. Canadian carriers pay $0.",
12: "Last email: $55K\u2013$525K in savings \u2014 start at ~$975 with 4 payments",
15: "The $55,000+ reason 503 US carriers also registered in Canada",
16: "\"We don't need this\" — until the FCC sends the letter",
17: "No USF. No CALEA. No state PUCs. No 499-A. Here's the setup.",
18: "Last email: save $55K+ in Year 1. Start at ~$975/mo \u2014 4 easy payments.",
22: "For counsel: $58K-$525K in avoided compliance costs for your carrier clients",
23: "Referral arrangement: $300 per carrier setup, zero liability for your firm",
}
CAMPAIGNS = [9, 10, 11, 12, 15, 16, 17, 18, 22, 23]
for cid in CAMPAIGNS:
d = api_get(f"/api/campaigns/{cid}")
data = d["data"]
body = data["body"]
name = data["name"]
if "What you're paying now" in body:
print(f" SKIP {cid:3d} | {name[:55]} | already has savings table")
continue
# Insert the savings table after the CTA button
# Find the CTA button (the red button link) and insert after it
cta_markers = [
'border-radius:4px;text-decoration:none', # CTA button style
'background:#e63f2a', # CTA button background
]
inserted = False
for marker in cta_markers:
if marker in body:
# Find the end of the CTA button row ( after the button)
idx = body.index(marker)
# Find the next after the button
close_idx = body.find("", idx)
if close_idx > 0:
close_idx += len("")
body = body[:close_idx] + SAVINGS_TABLE + body[close_idx:]
inserted = True
break
if not inserted:
# Fallback: insert before the chat block or footer
for fallback in ["We're online", "We are online", "style=\"display:block;margin:0 auto 10px;width:70px"]:
if fallback in body:
fb_idx = body.index(fallback)
tr_start = body[:fb_idx].rfind("| 0:
body = body[:tr_start] + SAVINGS_TABLE + body[tr_start:]
inserted = True
break
if not inserted:
print(f" FAIL {cid:3d} | {name[:55]} | no insertion point found")
continue
lists = [l["id"] for l in data.get("lists", [])]
new_subject = SUBJECT_UPDATES.get(cid, data["subject"])
old_subject = data["subject"]
result = api_put(f"/api/campaigns/{cid}", {
"name": data["name"],
"subject": new_subject,
"body": body,
"lists": lists,
"content_type": data.get("content_type", "richtext"),
"type": data.get("type", "regular"),
})
if "data" in result:
subj_changed = " | subject updated" if new_subject != old_subject else ""
print(f" OK {cid:3d} | {name[:55]} | +savings table{subj_changed}")
if new_subject != old_subject:
print(f" Old: {old_subject}")
print(f" New: {new_subject}")
else:
print(f" FAIL {cid:3d} | {name[:55]} | API error")
print("\nDone")
|