Files
presnax/main.py
Thies Mueller 032941ae0a initial commit
2025-09-24 00:03:38 +02:00

175 lines
5.3 KiB
Python

import time
import smtplib
import yaml
import requests
import csv
import qrcode
import io
from email.message import EmailMessage
from flask import Flask, request, jsonify, abort
from jinja2 import Template
from functools import wraps
from datetime import datetime
app = Flask(__name__)
with open("config.yaml", "r") as f:
config = yaml.safe_load(f)
MAIL_CONFIG = config["mails"]
MEALS = config["meals"]
TYPES = config["types"]
PRETIX = config["pretix"]
AUTH_TOKEN = config.get("auth", {}).get("token")
with open("template.txt", "r") as f:
MAIL_TEMPLATE = Template(f.read())
def require_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
token = request.headers.get("Authorization")
if not token or token != f"Bearer {AUTH_TOKEN}":
abort(401, description="Unauthorized: Invalid or missing token")
return f(*args, **kwargs)
return decorated
def send_email(to_email, subject, body, attachment_bytes, filename):
print(f"[DEBUG] Sending email to {to_email} with attachment {filename}")
msg = EmailMessage()
msg["From"] = MAIL_CONFIG["sender"]
msg["To"] = to_email
msg["Subject"] = subject
msg.set_content(body)
msg.add_attachment(attachment_bytes, maintype="application", subtype="pdf", filename=filename)
server = smtplib.SMTP(MAIL_CONFIG["server"], MAIL_CONFIG["port"])
if MAIL_CONFIG.get("starttls"):
server.starttls()
server.login(MAIL_CONFIG["user"], MAIL_CONFIG["password"])
server.send_message(msg)
server.quit()
print("[DEBUG] Email sent successfully")
def get_meal_times(meal_key):
if meal_key.endswith("mittag"):
return "11:30 - 13:30"
elif meal_key.endswith("abend"):
return "17:30 - 19:30"
return ""
def log_printed(email, meal_key):
location = email.split("@")[0]
now = datetime.now()
date_str = now.strftime("%Y-%m-%d")
time_str = now.strftime("%H:%M:%S")
with open("printed.csv", "a", newline="") as csvfile:
writer = csv.writer(csvfile, delimiter=";")
writer.writerow([date_str, time_str, meal_key, location])
print(f"[DEBUG] Logged printed PDF: {location} - {meal_key}")
def generate_qr(secret):
qr = qrcode.QRCode(box_size=10, border=4)
qr.add_data(secret)
qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white")
buf = io.BytesIO()
img.save(buf, format="PNG")
buf.seek(0)
return buf.getvalue()
@app.route("/order", methods=["POST"])
@require_auth
def order():
data = request.get_json()
print(f"[DEBUG] Incoming request JSON: {data}")
email = data.get("email")
typ = data.get("type")
meal_key = data.get("meal")
if not email or not typ or not meal_key:
return jsonify({"error": "Missing field"}), 400
meal_info = MEALS.get(meal_key)
if not meal_info:
return jsonify({"error": "Meal not found in config"}), 400
position = {
"positionid": 1,
"item": TYPES.get(typ),
"variation": None,
"price": "0",
"attendee_email": None,
"addon_to": None,
"subevent": meal_info["subevent"]
}
pretix_body = {
"email": "pretixfood@td00.de",
"locale": "en",
"sales_channel": "web",
"payment_provider": "manual",
"positions": [position]
}
url = f"{PRETIX['host']}/api/v1/organizers/{PRETIX['organizer']}/events/{PRETIX['event']}/orders/"
headers = {"Authorization": f"Token {PRETIX['token']}"}
print(f"[DEBUG] Sending POST to Pretix: {url} with body {pretix_body}")
resp = requests.post(url, json=pretix_body, headers=headers)
print(f"[DEBUG] Pretix response status: {resp.status_code}")
print(f"[DEBUG] Pretix response text: {resp.text}")
try:
resp_json = resp.json()
print(f"[DEBUG] Pretix response JSON: {resp_json}")
except ValueError:
print("[DEBUG] Pretix returned no JSON")
return jsonify({"error": "Pretix returned no JSON", "status_code": resp.status_code, "text": resp.text}), 502
if "positions" in resp_json and "item" in resp_json["positions"][0] and isinstance(resp_json["positions"][0]["item"], list):
if isinstance(resp_json["positions"][0]["item"][0], str):
print("[DEBUG] Not enough quota available")
return "Essen ist bereits alle", 418
try:
secret = resp_json["positions"][0]["secret"]
print(f"[DEBUG] Secret: {secret}")
except (KeyError, IndexError):
return jsonify({"error": "Secret not found in Pretix response", "resp_json": resp_json}), 500
qr_bytes = generate_qr(secret)
meal_times = get_meal_times(meal_key)
mail_body = MAIL_TEMPLATE.render(
meal_name=meal_info["name"],
meal_name_en=meal_info["name_en"],
meal_date=meal_info["date"],
meal_times=meal_times
)
if email.endswith("@printme.local"):
log_printed(email, meal_key)
response = app.response_class(
response=qr_bytes,
status=200,
mimetype='image/png'
)
response.headers["Content-Disposition"] = f"inline; filename=ticket.png"
return response
send_email(email, "Dein Engelessen / Your Angel Meal", mail_body, qr_bytes, "ticket.png")
return "Token gesendet", 201
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000, debug=True)