From 4df73337b8366fb68e898634292dd4f888f885dc Mon Sep 17 00:00:00 2001 From: justin Date: Fri, 29 May 2026 14:25:12 -0500 Subject: [PATCH] Add state-targeted campaign creator (CA, OR, NY) Script creates Listmonk campaigns with state-specific content: - California: MCP + CARB + CHP CA Number + insurance - Oregon: Weight-Mile Tax + IRP + ODOT authority - New York: HUT + insurance ($1.5M NYC) + intrastate authority Usage: python3 scripts/create_state_campaigns.py california Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/create_state_campaigns.py | 207 ++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 scripts/create_state_campaigns.py diff --git a/scripts/create_state_campaigns.py b/scripts/create_state_campaigns.py new file mode 100644 index 0000000..34a7e8e --- /dev/null +++ b/scripts/create_state_campaigns.py @@ -0,0 +1,207 @@ +#!/usr/bin/env python3 +"""Create state-targeted email campaigns in Listmonk for trucking compliance.""" +import json +import urllib.request +import base64 +import sys + +AUTH = base64.b64encode(b"api:6X1rKPea61N4rZ1S65Hx5zvqzbCj30F6nvEe9oVGH_Y").decode() +API = "http://localhost:9100/api" + +def api_call(path, data=None, method=None): + headers = {"Content-Type": "application/json", "Authorization": "Basic " + AUTH} + req = urllib.request.Request(API + path, headers=headers) + if data: + req.data = json.dumps(data).encode() + if method: + req.method = method + return json.loads(urllib.request.urlopen(req).read()) + +def find_list(name_contains): + lists = api_call("/lists").get("data", {}).get("results", []) + for l in lists: + if name_contains.lower() in l["name"].lower(): + return l + return None + +# ══════════════════════════════════════════════════════════════════════ +# Campaign templates by state +# ══════════════════════════════════════════════════════════════════════ + +CAMPAIGNS = { + "california": { + "list_search": "California", + "name": "CA Motor Carrier Permit + CARB Compliance Alert", + "subject": "California Motor Carrier Permit — is your MCP current, {{ .Subscriber.Attribs.company }}?", + "state_section": """ +

California-Specific Requirements

+ + + + + + +
Motor Carrier Permit (MCP) — required for all for-hire carriers and CMVs over 10,001 lbs. Annual renewal through CA DMV. Operating without an MCP is a misdemeanor.
CA Number (CHP) — issued by California Highway Patrol. Required before you can get an MCP. Must also have a USDOT number.
CARB Truck & Bus Rule — all diesel vehicles over 14,000 lbs must have a 2010 or newer engine. Non-compliant vehicles face $1,000/day fines.
State Insurance — California requires $750K+ liability for most carriers, up to $5M depending on cargo. Form E/H filing required with CHP.
""", + "services_section": """ + + + + + +
California MCP + CARB Compliance$349
IRP Registration Assistance$199
IFTA Application + Decals$149
State Compliance Bundle$599
""", + "cta_url": "https://performancewest.net/services/trucking/california/", + "cta_text": "View California Compliance Services", + }, + "oregon": { + "list_search": "Oregon", + "name": "Oregon Weight-Mile Tax Compliance Alert", + "subject": "Oregon Weight-Mile Tax — are you registered, {{ .Subscriber.Attribs.company }}?", + "state_section": """ +

Oregon-Specific Requirements

+ + + + + +
Weight-Mile Tax — Oregon has NO diesel fuel tax for trucks. Instead, all vehicles over 26,001 lbs pay a weight-mile tax based on miles driven and weight class. Filed via Oregon Trucking Online.
IRP Registration — interstate carriers must register through ODOT for apportioned plates.
ODOT Certificate of Authority — for-hire intrastate carriers must register with Oregon DOT.
""", + "services_section": """ + + + + + +
Oregon Weight-Mile Tax Setup$199
IRP Registration Assistance$199
IFTA Application + Decals$149
State Compliance Bundle$599
""", + "cta_url": "https://performancewest.net/services/trucking/oregon/", + "cta_text": "View Oregon Compliance Services", + }, + "new-york": { + "list_search": "New York", + "name": "NY Highway Use Tax Compliance Alert", + "subject": "New York Highway Use Tax — is your HUT current, {{ .Subscriber.Attribs.company }}?", + "state_section": """ +

New York-Specific Requirements

+ + + + + +
Highway Use Tax (HUT) — New York requires all vehicles over 18,000 lbs to pay the Highway Use Tax. Quarterly filing via NY Department of Tax and Finance. Lowest weight threshold in the US.
State Insurance — $750K liability required for most carriers. $1.5M minimum for NYC operations.
Intrastate Authority — for-hire intrastate carriers need NY DOT Certificate of Authority.
""", + "services_section": """ + + + + + +
NY Highway Use Tax Registration$199
IRP Registration Assistance$199
Intrastate Operating Authority$249
State Compliance Bundle$599
""", + "cta_url": "https://performancewest.net/services/trucking/new-york/", + "cta_text": "View New York Compliance Services", + }, +} + +def build_email(cfg): + """Build the full email HTML using the general template + state-specific sections.""" + return r""" +
+
+ + + + + + + + + + + +
+
+""" + +def main(): + state = sys.argv[1] if len(sys.argv) > 1 else "california" + if state not in CAMPAIGNS: + print(f"Unknown state: {state}. Available: {', '.join(CAMPAIGNS.keys())}") + sys.exit(1) + + cfg = CAMPAIGNS[state] + + # Find the Listmonk list + lst = find_list(cfg["list_search"]) + if not lst: + print(f"No Listmonk list found containing '{cfg['list_search']}'") + print("Run the flagger with --state-lists first") + sys.exit(1) + + list_id = lst["id"] + print(f"Found list: {lst['name']} (ID {list_id}, {lst.get('subscriber_count', '?')} subscribers)") + + # Build the email + body = build_email(cfg) + + # Create campaign as draft + campaign_data = { + "name": cfg["name"], + "subject": cfg["subject"], + "from_email": "Performance West ", + "content_type": "html", + "body": body, + "lists": [list_id], + "template_id": 1, + "headers": [{"Reply-To": "info@performancewest.net"}], + "tags": ["state-compliance", state, "dot-compliance"], + } + + resp = api_call("/campaigns", campaign_data) + cid = resp.get("data", {}).get("id") + print(f"Campaign {cid} created (draft) — '{cfg['name']}'") + print(f"Review at: http://localhost:9100/campaigns/{cid}") + +if __name__ == "__main__": + main()