Files
scriptkiddie/speiseplan.py
2026-03-01 06:41:26 +01:00

219 lines
6.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import os
import json
import requests
import hashlib
import datetime
import random
# -------------------------
# KONFIG
# -------------------------
WEBHOOK_URL = "https://discord.com/api/webhooks/1440463711645990912/g__qrs1k7gpeHO9xMY0TahIYjVoA0NNTl0mGcn2us80NeTb9hly_lDI41trpuc4oumH3"
BASE_URL = "https://das-schmeckt-mir.ruhr/images/pdf/speise_knapp/{kw:02d}_KW_Speiseplan{year}_Knapp.jpg"
SAVE_DIR = "/opt/speiseplan-bot/plans"
HASH_FILE = "/opt/speiseplan-bot/last_hashes.json"
DELAY_FILE = "/opt/speiseplan-bot/delay.json"
MESSAGES = [
"🍽️ Herr B., ein weiterer Speiseplan für die Woche {found_kw} ist in das Bominhaus eingeschlagen.",
"🥘 Speiseplan für Woche {found_kw}. Hoffentlich ist da kein Döner dabei.",
"🍛 Boah, guck mal hier! Speiseplan für {found_kw}!",
"😋 Der {found_kw}. Speiseplan existiert und wir haben ihn.",
"🍲 Isch hab' gar nichts gemacht! Ich habe nur den {found_kw}. Speiseplan hochgeladen...",
"💀 Wer diese Nachricht über den {found_kw}. Speiseplan liest, der schuldet Kevin einen Döner.",
"💕 Speiseplan gefunden und hochgeladen. Woche {found_kw}.",
"🤓 Wusstet ihr schon, dass das Essen in der KW {found_kw} schlechter ist als dieses Script?"
]
# -------------------------
# LOGGING
# -------------------------
def log_info(msg):
print(f"\033[94m[{datetime.datetime.now().strftime('%H:%M:%S')}] {msg}\033[0m")
def log_success(msg):
print(f"\033[92m[{datetime.datetime.now().strftime('%H:%M:%S')}] {msg}\033[0m")
def log_warn(msg):
print(f"\033[93m[{datetime.datetime.now().strftime('%H:%M:%S')}] {msg}\033[0m")
def log_error(msg):
print(f"\033[91m[{datetime.datetime.now().strftime('%H:%M:%S')}] {msg}\033[0m")
# -------------------------
# HILFSFUNKTIONEN
# -------------------------
def load_json(path, default):
if not os.path.exists(path):
return default
try:
with open(path, "r") as f:
return json.load(f)
except:
log_warn(f"JSON-Datei beschädigt: {path}. Benutze Default.")
return default
def save_json(path, data):
with open(path, "w") as f:
json.dump(data, f, indent=2)
def hash_bytes(data):
return hashlib.sha256(data).hexdigest()
def cleanup_old_plans(current_kw, current_year):
log_info("Aufräumen alter Pläne beginnt…")
files = os.listdir(SAVE_DIR)
cutoff = current_kw - 2
for file in files:
if not file.startswith("Speiseplan_KW"):
continue
parts = file.replace("Speiseplan_KW", "").replace(".jpg", "").split("_")
kw_old = int(parts[0])
year_old = int(parts[1])
if year_old < current_year or (year_old == current_year and kw_old <= cutoff):
log_warn(f"Lösche alten Plan: {file}")
os.remove(os.path.join(SAVE_DIR, file))
log_success("Aufräumen abgeschlossen.")
def fetch_plan(kw, year):
url = BASE_URL.format(kw=kw, year=year)
log_info(f"Prüfe URL: {url}")
try:
r = requests.get(url)
# Wenn kein Bild → direkt ignorieren
content_type = r.headers.get("Content-Type", "")
if r.status_code == 200 and content_type.startswith("image"):
log_success(f"Echter Speiseplan gefunden → KW {kw}")
return r.content
# DEBUG: ausgeben, was der Server wirklich liefert
log_warn(f"Kein gültiges Bild für KW {kw} (Status={r.status_code}, Type={content_type})")
return None
except Exception as e:
log_error(f"Fehler beim Abruf von KW {kw}: {e}")
return None
def record_delay(today, found_kw):
delay = load_json(DELAY_FILE, {"active": False, "start": None, "days": 0})
current_kw = today.isocalendar().week
if found_kw == current_kw:
if delay["active"]:
log_warn(f"Verzögerung beendet nach {delay['days']} Tagen.")
delay = {"active": False, "start": None, "days": 0}
save_json(DELAY_FILE, delay)
return
if found_kw < current_kw:
if not delay["active"]:
delay["active"] = True
delay["start"] = today.isoformat()
delay["days"] = 0
log_warn(f"Verzögerung gestartet! KW {found_kw} statt {current_kw}")
else:
start = datetime.date.fromisoformat(delay["start"])
delay["days"] = (today - start).days
log_warn(f"Verzögerung läuft: {delay['days']} Tage")
save_json(DELAY_FILE, delay)
# -------------------------
# MAIN
# -------------------------
def main():
os.makedirs(SAVE_DIR, exist_ok=True)
today = datetime.date.today()
year = today.year
kw_current = today.isocalendar().week
kw_next = kw_current + 1
year_next = year + 1 if kw_next > 52 else year
if kw_next > 52:
kw_next = 1
log_info(f"Starte Speiseplan-Check für KW {kw_current} + KW {kw_next}")
hashes = load_json(HASH_FILE, {})
found_data = None
found_kw = None
found_year = None
for kw_try, year_try in [(kw_current, year), (kw_next, year_next)]:
data = fetch_plan(kw_try, year_try)
if data:
key = f"{kw_try}-{year_try}"
new_hash = hash_bytes(data)
if hashes.get(key) == new_hash:
log_warn(f"Plan KW {kw_try} bereits bekannt überspringe.")
continue
found_data = data
found_kw = kw_try
found_year = year_try
hashes[key] = new_hash
break
if not found_data:
log_warn("Kein neuer Plan gefunden.")
record_delay(today, -1)
return
record_delay(today, found_kw)
filename = f"Speiseplan_KW{found_kw}_{found_year}.jpg"
file_path = os.path.join(SAVE_DIR, filename)
with open(file_path, "wb") as f:
f.write(found_data)
log_success(f"Plan gespeichert: {file_path}")
# Nachricht formatieren
message = random.choice(MESSAGES).format(found_kw=found_kw)
with open(file_path, "rb") as f:
requests.post(
WEBHOOK_URL,
data={"content": message},
files={"file": (filename, f, "image/jpeg")}
)
log_success("Webhook erfolgreich gesendet!")
save_json(HASH_FILE, hashes)
cleanup_old_plans(kw_current, year)
log_success("Speiseplan-Bot abgeschlossen.")
if __name__ == "__main__":
main()