From a2849d5c41583da84c15c9f3959ca760f111e162 Mon Sep 17 00:00:00 2001
From: Clarth <clarth@admin@claytonia.net>
Date: Thu, 10 Apr 2025 09:12:36 -0400
Subject: [PATCH] Add lunch.py

---
 lunch.py | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 112 insertions(+)
 create mode 100644 lunch.py

diff --git a/lunch.py b/lunch.py
new file mode 100644
index 0000000..fd45952
--- /dev/null
+++ b/lunch.py
@@ -0,0 +1,112 @@
+import re
+import json
+import os
+from datetime import datetime, timedelta
+from PyPDF2 import PdfReader
+import requests
+
+# === CONFIG ===
+PDF_FILE = "menu.pdf"
+BOT_TOKEN = "TOKEN"
+CHAT_ID = "CHATID"  # or use the channel's numeric ID
+
+# === HELPERS ===
+def extract_text_from_pdf(path):
+    reader = PdfReader(path)
+    return "\n".join(page.extract_text() for page in reader.pages)
+
+def extract_month_year(text):
+    match = re.search(r"Lunch\s+(\w+)\s+(\d{4})", text)
+    if match:
+        return match.group(1), int(match.group(2))
+    raise ValueError("Could not find month and year in PDF")
+
+def month_name_to_number(name):
+    return datetime.strptime(name[:3], "%b").month
+
+def find_menu_items(text):
+    # Match number-day + content, even if day markers are inline (e.g., "29) ... 30)")
+    pattern = r"(\d{1,2}\))\s*(.*?)(?=(?:\n?\s*\d{1,2}\))|\Z)"
+    matches = re.findall(pattern, text, re.DOTALL)
+
+    entries = []
+    for day_marker, content in matches:
+        day = day_marker.strip(")").strip()
+        cleaned = re.sub(r"\s+", " ", content).strip()
+        entries.append((day, cleaned))
+    return entries
+
+def build_menu_mapping(text, year, month):
+    items = find_menu_items(text)
+    menu_by_date = {}
+
+    # Get all weekdays in the month
+    current = datetime(year, month, 1)
+    weekdays = []
+    while current.month == month:
+        if current.weekday() < 5:  # Mon–Fri
+            weekdays.append(current)
+        current += timedelta(days=1)
+
+    # Match each menu item to weekday, assuming school days only
+    for (day_str, content) in items:
+        try:
+            day = int(day_str)
+            date = datetime(year, month, day)
+            if date.weekday() >= 5:
+                continue  # Skip weekends
+            date_key = date.strftime("%Y-%m-%d")
+            cleaned = re.sub(r"\s+", " ", content).strip()
+            menu_by_date[date_key] = cleaned
+        except ValueError:
+            continue
+
+    return menu_by_date
+
+def load_or_parse_menu():
+    # Extract month/year
+    text = extract_text_from_pdf(PDF_FILE)
+    #print(text[:2000])  # show the first 2000 characters
+    #exit()
+    month_name, year = extract_month_year(text)
+    month = month_name_to_number(month_name)
+
+    # JSON cache
+    json_file = f"menu_{year}_{month:02d}.json"
+    if os.path.exists(json_file):
+        with open(json_file) as f:
+            return json.load(f)
+
+    # Parse and save
+    menu_data = build_menu_mapping(text, year, month)
+    with open(json_file, "w") as f:
+        json.dump(menu_data, f, indent=2)
+    return menu_data
+
+def send_to_telegram(text):
+    url = f"https://api.telegram.org/bot{BOT_TOKEN}/sendMessage"
+    payload = {"chat_id": CHAT_ID, "text": text}
+    response = requests.post(url, data=payload)
+    return response.status_code == 200
+
+def main():
+    today = datetime.now().strftime("%Y-%m-%d")
+    menu = load_or_parse_menu()
+
+    if today in menu:
+        lunch = menu[today]
+
+        if "Early Dismissal" in lunch:
+            message = f"⚠️ Early Dismissal Today ({today}):\n\n{lunch}"
+        elif "No School" in lunch:
+            message = f"❌ No School Today ({today}):\n\n{lunch}"
+        elif "No lunch" in lunch:
+            message = f"⚠️ No Lunch Today ({today}):\n\n{lunch}"
+        else:
+            message = f"📅 Today's Lunch Menu ({today}):\n\n{lunch}"
+
+        send_to_telegram(message)
+    else:
+        print(f"No menu for {today}. Might be a weekend or no school.")
+if __name__ == "__main__":
+    main()