Add lunch.py
This commit is contained in:
		
							parent
							
								
									e4ef7499e8
								
							
						
					
					
						commit
						a2849d5c41
					
				
					 1 changed files with 112 additions and 0 deletions
				
			
		
							
								
								
									
										112
									
								
								lunch.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								lunch.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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()
 | 
			
		||||
		Loading…
	
	Add table
		
		Reference in a new issue