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()