import os import sys import logging import smtplib from datetime import datetime from email.message import EmailMessage import requests logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s") log = logging.getLogger(__name__) SCHOOL_SLUG = "kyrene-de-la-mariposa" MENU_TYPE = "lunch" API_BASE = "https://kyrene.api.nutrislice.com/menu/api/weeks/school" def get_lunch_menu(date_str: str | None = None) -> tuple[list[str], str]: if date_str is None: date_str = datetime.now().strftime("%Y-%m-%d") dt = datetime.strptime(date_str, "%Y-%m-%d") url = f"{API_BASE}/{SCHOOL_SLUG}/menu-type/{MENU_TYPE}/{dt.year}/{dt.month:02d}/{dt.day:02d}/" log.info(f"Fetching {url}") resp = requests.get( url, headers={"Accept": "application/json", "User-Agent": "Mozilla/5.0"}, timeout=20, ) resp.raise_for_status() data = resp.json() items = [] for day in data.get("days", []): if day.get("date") != date_str: continue for entry in day.get("menu_items", []): if entry.get("is_section_title") or entry.get("is_station_header"): continue food = entry.get("food") if food and food.get("name"): items.append(food["name"].strip()) return items, date_str def send_sms(message: str, phone: str) -> None: gmail_user = os.environ["GMAIL_USER"] gmail_pass = os.environ["GMAIL_APP_PASSWORD"] gateway = os.environ.get("CARRIER_GATEWAY", "vtext.com") to_addr = f"{phone}@{gateway}" msg = EmailMessage() msg["From"] = gmail_user msg["To"] = to_addr msg.set_content(message) log.info(f"Sending email-to-SMS → {to_addr}") with smtplib.SMTP("smtp.gmail.com", 587) as smtp: smtp.starttls() smtp.login(gmail_user, gmail_pass) smtp.send_message(msg) log.info("Sent.") def main(): phone = os.environ.get("PHONE_NUMBER", "").strip() if not phone: log.error("PHONE_NUMBER environment variable is not set.") sys.exit(1) try: items, date_str = get_lunch_menu() if items: body = "\n".join(f"• {i}" for i in items) message = f"Mariposa Lunch {date_str}:\n{body}" else: message = ( f"No lunch menu posted for {date_str} " f"(Kyrene de la Mariposa — may be a break or holiday)." ) except Exception as e: log.exception("Failed to fetch menu") message = f"Error fetching Mariposa lunch menu: {e}" # SMS via email has a ~160 char limit per message segment; keep it short if len(message) > 1400: message = message[:1397] + "..." log.info(f"Message:\n{message}") try: send_sms(message, phone) except Exception as e: log.error(f"Failed to send SMS: {e}") sys.exit(1) if __name__ == "__main__": main()