Initial commit: Lunch Notifier source from server
This commit is contained in:
commit
b568287528
9 changed files with 878 additions and 0 deletions
101
scraper.py
Normal file
101
scraper.py
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
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()
|
||||
Loading…
Add table
Add a link
Reference in a new issue