Repo erstellen!
This commit is contained in:
28
push-updates.ps1
Normal file
28
push-updates.ps1
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
param(
|
||||||
|
[string]$RepoPath = "C:\Users\Kevkus\Desktop\Obsidian\Allgemeine D&D Notizen\DND Zeug"
|
||||||
|
)
|
||||||
|
|
||||||
|
Set-StrictMode -Version Latest
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
# Datum/Time für Commit-Message (lokal, ISO-ish)
|
||||||
|
$stamp = Get-Date -Format "yyyy-MM-dd HH:mm"
|
||||||
|
|
||||||
|
Set-Location $RepoPath
|
||||||
|
|
||||||
|
# Add alles
|
||||||
|
git add -A | Out-Null
|
||||||
|
|
||||||
|
# Prüfen ob überhaupt Änderungen da sind
|
||||||
|
$changes = git status --porcelain
|
||||||
|
if ([string]::IsNullOrWhiteSpace($changes)) {
|
||||||
|
Write-Host "Keine Änderungen – nichts zu committen/pushen."
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Commit + Push
|
||||||
|
$msg = "Automatischer Push von $stamp"
|
||||||
|
git commit -m $msg | Out-Null
|
||||||
|
git push | Out-Null
|
||||||
|
|
||||||
|
Write-Host "OK: $msg"
|
||||||
218
speiseplan.py
Normal file
218
speiseplan.py
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
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()
|
||||||
Reference in New Issue
Block a user