new-site/scripts/workers/create_compliance_campaign.py
justin f8cd37ac8c Initial commit — Performance West telecom compliance platform
Includes: API (Express/TypeScript), Astro site, Python workers,
document generators, FCC compliance tools, Canada CRTC formation,
Ansible infrastructure, and deployment scripts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-27 06:54:22 -05:00

270 lines
14 KiB
Python

#!/usr/bin/env python3
"""
create_compliance_campaign.py — Create the FCC Compliance Alert campaign
for Listmonk list 6 (FCC Carriers - Compliance Alert).
Uses the same HTML email helpers as create_campaigns.py.
Run: python3 scripts/workers/create_compliance_campaign.py
"""
import requests
import sys
LISTMONK_URL = "https://lists.performancewest.net"
AUTH = ("api", "6X1rKPea61N4rZ1S65Hx5zvqzbCj30F6nvEe9oVGH_Y")
COMPLIANCE_CHECK_URL = "https://performancewest.net/tools/fcc-compliance-check"
ORDER_URL = "https://performancewest.net/order/fcc-compliance"
PHONE = "1-888-411-0383"
EMAIL_ADDR = "info@performancewest.net"
CONTACT = (
f'Email <a href="mailto:{EMAIL_ADDR}" style="color:#e63f2a;text-decoration:none;">{EMAIL_ADDR}</a> '
f'or call <a href="tel:+18884110383" style="color:#e63f2a;text-decoration:none;">{PHONE}</a>'
)
# ── HTML helpers (same as create_campaigns.py) ─────────────────────────
def hdr(eyebrow, headline, sub=None):
s = f'<p style="margin:8px 0 0;font-family:Arial,sans-serif;font-size:13px;color:#a0b4cc;line-height:1.5;">{sub}</p>' if sub else ''
return (
'<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="background:#1a2744;padding:0;">'
'<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding:18px 40px 14px;">'
'<table cellpadding="0" cellspacing="0" border="0"><tr>'
'<td style="vertical-align:middle;padding-right:12px;"><img src="https://performancewest.net/images/logo.png" width="90" alt="Performance West" style="display:block;width:90px;height:auto;"></td>'
'<td style="vertical-align:middle;border-left:1px solid #2d4e78;padding-left:12px;"><span style="color:#8fa8d0;font-family:Arial,sans-serif;font-size:11px;letter-spacing:1.5px;text-transform:uppercase;">Telecom Compliance</span></td>'
'</tr></table></td></tr></table>'
'<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="background:#e63f2a;height:3px;font-size:0;line-height:0;">&nbsp;</td></tr></table>'
'<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding:28px 40px 32px;">'
f'<p style="margin:0 0 8px;font-family:Arial,sans-serif;font-size:11px;color:#e63f2a;letter-spacing:2px;text-transform:uppercase;font-weight:600;">{eyebrow}</p>'
f'<h1 style="margin:0;font-family:Arial,sans-serif;font-size:24px;font-weight:700;color:#ffffff;line-height:1.3;">{headline}</h1>{s}'
'</td></tr></table></td></tr></table>'
)
def alert_bar():
return (
'<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr>'
'<td style="background:#fef2f2;padding:14px 40px;border-bottom:2px solid #fca5a5;">'
'<p style="margin:0;font-family:Arial,sans-serif;font-size:14px;color:#991b1b;font-weight:700;text-align:center;">'
'\U0001F6A8 ACTION REQUIRED &mdash; Your FCC filings appear to be past due'
'</p></td></tr></table>'
)
def P(t):
return f'<p style="margin:0 0 16px;font-family:Arial,sans-serif;font-size:15px;color:#2d3748;line-height:1.7;">{t}</p>'
def PS(t):
return f'<p style="margin:0 0 16px;font-family:Arial,sans-serif;font-size:14px;color:#6b7280;line-height:1.7;">{t}</p>'
def H2(t):
return f'<h2 style="margin:24px 0 10px;font-family:Arial,sans-serif;font-size:17px;font-weight:700;color:#1a2744;">{t}</h2>'
def UL(*items):
return (
'<ul style="margin:0 0 16px;padding-left:22px;font-family:Arial,sans-serif;font-size:15px;color:#2d3748;line-height:1.7;">'
+ "".join(f'<li style="margin-bottom:8px;">{i}</li>' for i in items)
+ '</ul>'
)
def cta(text, url):
return (
'<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td align="center">'
'<table cellpadding="0" cellspacing="0" border="0" style="margin:28px auto;"><tr>'
f'<td style="background:#e63f2a;border-radius:4px;"><a href="{url}" style="display:inline-block;padding:14px 36px;font-family:Arial,sans-serif;font-size:15px;font-weight:700;color:#ffffff;text-decoration:none;">{text}</a></td>'
'</tr></table></td></tr></table>'
)
def warning_box(text):
return (
'<table width="100%" cellpadding="0" cellspacing="0" border="0" style="margin:20px 0;"><tr>'
'<td style="border-left:4px solid #dc2626;padding:14px 20px;background:#fef2f2;border-radius:0 6px 6px 0;">'
f'<p style="margin:0;font-family:Arial,sans-serif;font-size:14px;color:#991b1b;line-height:1.6;">{text}</p>'
'</td></tr></table>'
)
def info_box(text):
return (
'<table width="100%" cellpadding="0" cellspacing="0" border="0" style="margin:20px 0;"><tr>'
'<td style="border-left:4px solid #2563eb;padding:14px 20px;background:#eff6ff;border-radius:0 6px 6px 0;">'
f'<p style="margin:0;font-family:Arial,sans-serif;font-size:14px;color:#1e40af;line-height:1.6;">{text}</p>'
'</td></tr></table>'
)
def ftr():
return (
'<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr>'
'<td style="background:#f4f5f7;padding:20px 40px;border-top:1px solid #e8ecf0;text-align:center;">'
'<img src="https://performancewest.net/images/logo.png" width="70" alt="Performance West" style="display:block;margin:0 auto 10px;width:70px;height:auto;opacity:0.5;">'
'<p style="margin:0 0 6px;font-family:Arial,sans-serif;font-size:12px;color:#9ca3af;">'
'Performance West Inc. &nbsp;&middot;&nbsp; <a href="https://performancewest.net" style="color:#9ca3af;">performancewest.net</a></p>'
'<p style="margin:0;font-family:Arial,sans-serif;font-size:11px;color:#b0b7c3;line-height:1.6;">'
'<a href="{{ UnsubscribeURL }}" style="color:#b0b7c3;">Unsubscribe</a></p>'
'</td></tr></table>'
)
def assemble(hdr_html, bar_html, body_html, ftr_html):
inner = (
hdr_html + bar_html
+ f'<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding:32px 40px;background:#ffffff;" class="body-pad">{body_html}</td></tr></table>'
+ ftr_html
)
return (
'<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><style>'
'@media only screen and (max-width:600px){.wrap{width:100%!important;border-radius:0!important;}.body-pad{padding:24px 20px!important;}h1{font-size:20px!important;}}'
'body,table,td,p,a{-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;}table{border-collapse:collapse!important;}img{border:0;outline:none;text-decoration:none;}'
'</style></head><body style="margin:0;padding:0;background:#eef0f3;">'
'<table width="100%" cellpadding="0" cellspacing="0" border="0" style="background:#eef0f3;padding:20px 0;"><tr><td align="center">'
'<table width="620" cellpadding="0" cellspacing="0" border="0" class="wrap" style="width:620px;max-width:620px;background:#ffffff;border-radius:8px;overflow:hidden;box-shadow:0 2px 8px rgba(0,0,0,0.08);">'
f'<tr><td>{inner}</td></tr></table></td></tr></table></body></html>'
)
# ═══════════════════════════════════════════════════════════════════════
# Campaign body
# ═══════════════════════════════════════════════════════════════════════
body = (
P("{{ .Subscriber.Attribs.company }},")
+ warning_box(
"\U0001F6A8 <strong>Our records indicate your carrier appears to have one or more "
"FCC compliance filings that are past due.</strong> "
"Failure to maintain current filings can result in forfeitures, red-light "
"status on your FRN, and disruption to your ability to do business."
)
+ P(
"The FCC has been <strong>aggressively enforcing</strong> filing deadlines "
"in 2025\u20132026. Carriers with overdue filings face:"
)
+ UL(
"<strong>Robocall Mitigation Database (RMD)</strong> \u2014 failure to "
"recertify by March 1 can lead to removal from the RMD, which means "
"downstream carriers are <strong>required to block your traffic "
"within 30 days</strong> of the FCC\u2019s removal order",
"<strong>CPNI Annual Certification</strong> \u2014 overdue certifications "
"under 47 CFR \u00A7 64.2009 carry forfeitures up to <strong>$500,000 "
"per violation</strong>",
"<strong>Form 499-A</strong> \u2014 late filers face retroactive USF "
"contributions plus interest, and USAC will place a <strong>red-light "
"hold</strong> on your FRN until the filing is current",
"<strong>BDC (Broadband Data Collection)</strong> \u2014 carriers who "
"provide broadband or retail voice must file semi-annually; non-filers "
"face enforcement action",
)
+ H2("Check your compliance status \u2014 free, instant.")
+ P(
"We built a free compliance check tool that scans your FRN against "
"FCC databases and tells you exactly which filings are current and "
"which need attention. No login required \u2014 just enter your FRN."
)
+ '<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td align="center">'
+ '<table cellpadding="0" cellspacing="0" border="0" style="margin:28px auto;"><tr>'
+ f'<td style="background:#059669;border-radius:4px;"><a href="{COMPLIANCE_CHECK_URL}" style="display:inline-block;padding:14px 36px;font-family:Arial,sans-serif;font-size:15px;font-weight:700;color:#ffffff;text-decoration:none;">Check My FCC Compliance for FREE \u2192</a></td>'
+ '</tr></table></td></tr></table>'
+ H2("We handle the filings for you.")
+ P(
"Performance West specializes in FCC regulatory compliance. We file "
"499-A, CPNI certifications, RMD registrations, STIR/SHAKEN, BDC, "
"and CALEA plans for carriers across the US. Fixed pricing, no hourly "
"billing, and we handle everything from document preparation to portal "
"submission."
)
+ info_box(
"<strong>Bundle discount:</strong> Order 2 or more compliance services "
"and save 15% automatically. Most carriers need at least 499-A + CPNI + RMD."
)
+ UL(
"Form 499-A filing \u2014 <strong>$499</strong>",
"CPNI Annual Certification \u2014 <strong>$149</strong> \u2014 includes CPNI deployment guide so you know how to properly deploy customer verification \u2014 \u23F0 <em>same-day service available</em>",
"RMD Registration / Recertification \u2014 <strong>$219</strong> + $100 FCC filing fee \u2014 \u23F0 <em>same-day service available</em>",
"New Carrier Onboarding Bundle (everything) \u2014 <strong>$1,799</strong>",
)
+ '<table width="100%" cellpadding="0" cellspacing="0" border="0" style="margin:16px 0 24px;"><tr>'
+ '<td style="background:#fefce8;border:1px solid #fde68a;border-radius:8px;padding:16px 20px;text-align:center;">'
+ '<table cellpadding="0" cellspacing="0" border="0" style="margin:0 auto;"><tr>'
+ '<td style="vertical-align:middle;padding-right:12px;font-size:36px;">&#x23F1;</td>'
+ '<td style="vertical-align:middle;">'
+ '<p style="margin:0;font-family:Arial,sans-serif;font-size:15px;font-weight:700;color:#92400e;">Same-Day Filing Available</p>'
+ '<p style="margin:4px 0 0;font-family:Arial,sans-serif;font-size:13px;color:#a16207;">CPNI and RMD filings can be completed and submitted the same day you order. '
+ 'Get back into compliance before the end of business today.</p>'
+ '</td></tr></table></td></tr></table>'
+ cta("View All Compliance Services \u2192", "https://performancewest.net/services/telecom")
+ H2("Flexible payment options.")
+ P(
"We accept <strong>credit/debit cards</strong>, <strong>ACH bank transfer</strong> (no fee), "
"<strong>PayPal</strong>, <strong>Klarna</strong> (pay in 4 installments), "
"and <strong>cryptocurrency</strong> (BTC, ETH, USDC, and more). "
"Pay however works best for your business."
)
+ P(
"All compliance filing fees are <strong>tax deductible</strong> as "
"ordinary business expenses under IRC \u00A7 162."
)
+ PS(f"Questions? {CONTACT} \u2014 we\u2019re happy to review your filing status at no cost.")
+ P("\u2014 Performance West Compliance Team")
)
# ═══════════════════════════════════════════════════════════════════════
# Create the campaign
# ═══════════════════════════════════════════════════════════════════════
def create_campaign():
s = requests.Session()
s.auth = AUTH
campaign_html = assemble(
hdr(
"FCC Compliance Alert",
"Your FCC filings appear to be past due.",
"Immediate action recommended to avoid enforcement",
),
alert_bar(),
body,
ftr(),
)
r = s.post(f"{LISTMONK_URL}/api/campaigns", json={
"name": "COMPLIANCE ALERT \u2014 FCC filings past due",
"subject": "\U0001F6A8 ACTION REQUIRED \u2014 PAST DUE: Your FCC compliance filings need immediate attention",
"lists": [6], # FCC Carriers - Compliance Alert
"type": "regular",
"content_type": "html",
"body": campaign_html,
"status": "draft",
"headers": [{"key": "Reply-To", "value": "info@performancewest.net"}],
}, timeout=30)
if not r.ok:
print(f"ERROR {r.status_code}: {r.text[:200]}", file=sys.stderr)
return None
cid = r.json().get("data", {}).get("id", "?")
print(f"Campaign created: [{cid}] COMPLIANCE ALERT")
print(f"Subject: \U0001F6A8 ACTION REQUIRED \u2014 PAST DUE: Your FCC compliance filings need immediate attention")
print(f"List: 6 (FCC Carriers - Compliance Alert)")
print(f"Status: draft (review in Listmonk before sending)")
return cid
if __name__ == "__main__":
create_campaign()