"""SendBlue iMessage wrapper: send + signature helpers."""
import hmac
import hashlib
import json
import os
import urllib.request
import urllib.error
from pathlib import Path
SEND_URL = "https://api.sendblue.co/api/send-message"
_ENV_FILE = Path(__file__).resolve().parent.parent / "content-os" / "config" / ".env"
def _load_env():
if not _ENV_FILE.exists():
return
for line in _ENV_FILE.read_text().splitlines():
line = line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
k, v = line.split("=", 1)
v = v.strip().strip('"').strip("'")
if not os.environ.get(k.strip()):
os.environ[k.strip()] = v
_load_env()
def _keys():
kid = os.environ.get("SENDBLUE_API_KEY_ID", "")
sec = os.environ.get("SENDBLUE_API_SECRET_KEY", "")
if not kid or not sec:
raise RuntimeError("SENDBLUE_API_KEY_ID / SENDBLUE_API_SECRET_KEY not set")
return kid, sec
def send(number, content, from_number=None, send_style=None, status_callback=None, media_url=None):
"""Send an iMessage. number is E.164 (+15551234567). Returns parsed JSON response."""
kid, sec = _keys()
body = {"number": number}
if content:
body["content"] = content
if from_number or os.environ.get("SENDBLUE_FROM_NUMBER"):
body["from_number"] = from_number or os.environ["SENDBLUE_FROM_NUMBER"]
if send_style:
body["send_style"] = send_style
if status_callback:
body["status_callback"] = status_callback
if media_url:
body["media_url"] = media_url
req = urllib.request.Request(
SEND_URL,
data=json.dumps(body).encode(),
headers={
"sb-api-key-id": kid,
"sb-api-secret-key": sec,
"content-type": "application/json",
},
)
try:
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read())
except urllib.error.HTTPError as e:
return {"error": f"HTTP {e.code}", "body": e.read().decode("utf-8", "replace")}
def verify_webhook(raw_body, header_sig, secret=None):
"""HMAC-SHA256 verification. Returns True/False."""
secret = secret or os.environ.get("SENDBLUE_WEBHOOK_SECRET", "")
if not secret or not header_sig:
return False
digest = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(digest, header_sig)
def authorized(number):
"""Is this E.164 number allowed to text Chairman?"""
allow = os.environ.get("SENDBLUE_AUTHORIZED_NUMBERS", "").split(",")
allow = [a.strip() for a in allow if a.strip()]
return number in allow
if __name__ == "__main__":
import sys
if len(sys.argv) >= 3 and sys.argv[1] == "send":
number, *msg = sys.argv[2:]
print(json.dumps(send(number, " ".join(msg) or "test ping from Chairman"), indent=2))
else:
print("usage: python3 sendblue.py send +15551234567 your message here")