101 lines
2.9 KiB
Python
101 lines
2.9 KiB
Python
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()
|