This commit is contained in:
MeBeBruno committed 2026-08-09 16:42:33 +02:00
commit 339e0c72ad
3 files changed
+55 -33

No files matched your search

+46 -29
View File
@@ -1,3 +1,6 @@
from gevent import monkey
monkey.patch_all()
import sqlite3 import sqlite3
import string import string
import secrets import secrets
@@ -10,16 +13,17 @@ from passlib.hash import argon2
import pyotp import pyotp
import qrcode import qrcode
import qrcode.image.svg import qrcode.image.svg
from apscheduler.schedulers.background import BackgroundScheduler from apscheduler.schedulers.gevent import GeventScheduler
from apscheduler.triggers.cron import CronTrigger from apscheduler.triggers.cron import CronTrigger
from apscheduler.triggers.date import DateTrigger from apscheduler.triggers.date import DateTrigger
from flask import Flask, request, session, redirect, render_template, url_for, abort, send_from_directory from flask import Flask, request, session, redirect, render_template, url_for, abort, send_from_directory
from flask_socketio import SocketIO, emit, join_room from flask_socketio import SocketIO, emit, join_room
application = Flask(__name__) application = Flask(__name__)
app = application # Fallback-Alias für Gunicorn und Pella
application.secret_key = secrets.token_hex(64) application.secret_key = secrets.token_hex(64)
websocket_manager = SocketIO(application, manage_session=False) websocket_manager = SocketIO(application, manage_session=False, async_mode='gevent')
scheduler_instance = BackgroundScheduler(timezone="Europe/Berlin") scheduler_instance = GeventScheduler(timezone="Europe/Berlin")
european_timezone = zoneinfo.ZoneInfo("Europe/Berlin") european_timezone = zoneinfo.ZoneInfo("Europe/Berlin")
IDENTIFIER_LENGTH = 5 IDENTIFIER_LENGTH = 5
@@ -62,7 +66,7 @@ def initialize_database():
""") """)
connection.execute(""" connection.execute("""
CREATE TABLE IF NOT EXISTS kill_log ( CREATE TABLE IF NOT EXISTS kill_log (
kill_identifier INTEGER PRIMARY KEY AUTOINCREMENT, kill_id INTEGER PRIMARY KEY AUTOINCREMENT,
killer_identifier TEXT, killer_identifier TEXT,
victim_identifier TEXT, victim_identifier TEXT,
victim_previous_target TEXT, victim_previous_target TEXT,
@@ -240,13 +244,13 @@ def process_administrator_action(action_type, form_data):
new_target = victim["target_identifier"] new_target = victim["target_identifier"]
connection.execute("UPDATE player SET is_alive = 0, target_identifier = NULL, pending_attacker_identifier = NULL WHERE player_identifier = ?", (target_identifier,)) connection.execute("UPDATE player SET is_alive = 0, target_identifier = NULL, pending_attacker_identifier = NULL WHERE player_identifier = ?", (target_identifier,))
attacker_identifier = None attacker_id = None
if attacker: if attacker:
attacker_identifier = attacker["player_identifier"] attacker_id = attacker["player_identifier"]
connection.execute("UPDATE player SET target_identifier = ? WHERE player_identifier = ?", (new_target, attacker_identifier)) connection.execute("UPDATE player SET target_identifier = ? WHERE player_identifier = ?", (new_target, attacker_id))
timestamp = datetime.now(european_timezone).isoformat() timestamp = datetime.now(european_timezone).isoformat()
connection.execute("INSERT INTO kill_log (killer_identifier, victim_identifier, victim_previous_target, kill_timestamp) VALUES (?, ?, ?, ?)", (attacker_identifier, target_identifier, new_target, timestamp)) connection.execute("INSERT INTO kill_log (killer_identifier, victim_identifier, victim_previous_target, kill_timestamp) VALUES (?, ?, ?, ?)", (attacker_id, target_identifier, new_target, timestamp))
alive_count_record = connection.execute("SELECT COUNT(*) as alive_count FROM player WHERE is_alive = 1 AND is_approved = 1").fetchone() alive_count_record = connection.execute("SELECT COUNT(*) as alive_count FROM player WHERE is_alive = 1 AND is_approved = 1").fetchone()
if alive_count_record["alive_count"] <= 1: if alive_count_record["alive_count"] <= 1:
@@ -261,50 +265,50 @@ def process_administrator_action(action_type, form_data):
has_game_state_changed = True has_game_state_changed = True
elif action_type == "edit_kill": elif action_type == "edit_kill":
kill_identifier = form_data.get("kill_identifier") kill_id = form_data.get("kill_id")
new_killer_identifier = form_data.get("new_killer_identifier") new_killer_id = form_data.get("new_killer_identifier")
if new_killer_identifier == "": if new_killer_id == "":
new_killer_identifier = None new_killer_id = None
new_timestamp = form_data.get("kill_timestamp") new_timestamp = form_data.get("kill_timestamp")
old_kill = connection.execute("SELECT * FROM kill_log WHERE kill_identifier = ?", (kill_identifier,)).fetchone() old_kill = connection.execute("SELECT * FROM kill_log WHERE kill_id = ?", (kill_id,)).fetchone()
if old_kill: if old_kill:
old_killer_identifier = old_kill["killer_identifier"] old_killer_id = old_kill["killer_identifier"]
if old_killer_identifier != new_killer_identifier: if old_killer_id != new_killer_id:
if old_killer_identifier: if old_killer_id:
connection.execute("UPDATE player SET score = MAX(0, score - 1) WHERE player_identifier = ?", (old_killer_identifier,)) connection.execute("UPDATE player SET score = MAX(0, score - 1) WHERE player_identifier = ?", (old_killer_id,))
if new_killer_identifier: if new_killer_id:
connection.execute("UPDATE player SET score = score + 1 WHERE player_identifier = ?", (new_killer_identifier,)) connection.execute("UPDATE player SET score = score + 1 WHERE player_identifier = ?", (new_killer_id,))
connection.execute("UPDATE kill_log SET killer_identifier = ?, kill_timestamp = ? WHERE kill_identifier = ?", (new_killer_identifier, new_timestamp, kill_identifier)) connection.execute("UPDATE kill_log SET killer_identifier = ?, kill_timestamp = ? WHERE kill_id = ?", (new_killer_id, new_timestamp, kill_id))
connection.commit() connection.commit()
has_game_state_changed = True has_game_state_changed = True
elif action_type == "revoke_kill": elif action_type == "revoke_kill":
kill_identifier = form_data.get("kill_identifier") kill_id = form_data.get("kill_id")
kill_record = connection.execute("SELECT * FROM kill_log WHERE kill_identifier = ?", (kill_identifier,)).fetchone() kill_record = connection.execute("SELECT * FROM kill_log WHERE kill_id = ?", (kill_id,)).fetchone()
if kill_record: if kill_record:
if kill_record["killer_identifier"]: if kill_record["killer_identifier"]:
connection.execute("UPDATE player SET score = MAX(0, score - 1) WHERE player_identifier = ?", (kill_record["killer_identifier"],)) connection.execute("UPDATE player SET score = MAX(0, score - 1) WHERE player_identifier = ?", (kill_record["killer_identifier"],))
victim_identifier = kill_record["victim_identifier"] victim_id = kill_record["victim_identifier"]
target_to_restore = kill_record["victim_previous_target"] target_to_restore = kill_record["victim_previous_target"]
player_pointing_to_target = connection.execute("SELECT player_identifier FROM player WHERE target_identifier = ?", (target_to_restore,)).fetchone() player_pointing_to_target = connection.execute("SELECT player_identifier FROM player WHERE target_identifier = ?", (target_to_restore,)).fetchone()
connection.execute("UPDATE player SET is_alive = 1, target_identifier = ? WHERE player_identifier = ?", (target_to_restore, victim_identifier)) connection.execute("UPDATE player SET is_alive = 1, target_identifier = ? WHERE player_identifier = ?", (target_to_restore, victim_id))
if player_pointing_to_target: if player_pointing_to_target:
connection.execute("UPDATE player SET target_identifier = ? WHERE player_identifier = ?", (victim_identifier, player_pointing_to_target["player_identifier"])) connection.execute("UPDATE player SET target_identifier = ? WHERE player_identifier = ?", (victim_id, player_pointing_to_target["player_identifier"]))
connection.execute("DELETE FROM kill_log WHERE kill_identifier = ?", (kill_identifier,)) connection.execute("DELETE FROM kill_log WHERE kill_id = ?", (kill_id,))
alive_count = connection.execute("SELECT COUNT(*) as alive_count FROM player WHERE is_alive = 1 AND is_approved = 1").fetchone()["alive_count"] alive_count = connection.execute("SELECT COUNT(*) as alive_count FROM player WHERE is_alive = 1 AND is_approved = 1").fetchone()["alive_count"]
if alive_count > 1: if alive_count > 1:
status = connection.execute("SELECT configuration_value FROM game_configuration WHERE configuration_key = 'game_status'").fetchone()["configuration_value"] status = connection.execute("SELECT configuration_value FROM game_configuration WHERE configuration_key = 'game_status'").fetchone()["configuration_value"]
if status == 'finished': if status == 'finished':
connection.execute("UPDATE game_configuration SET configuration_value = 'running' WHERE configuration_key = 'game_status'") connection.execute("UPDATE game_configuration SET configuration_value = 'running' WHERE configuration_key = 'game_status'")
connection.execute("UPDATE player SET score = MAX(0, score - 3) WHERE is_alive = 1 AND is_approved = 1 AND player_identifier != ?", (victim_identifier,)) connection.execute("UPDATE player SET score = MAX(0, score - 3) WHERE is_alive = 1 AND is_approved = 1 AND player_identifier != ?", (victim_id,))
connection.commit() connection.commit()
has_game_state_changed = True has_game_state_changed = True
@@ -362,6 +366,11 @@ def scheduled_action_wrapper(action_type, form_data):
def serve_service_worker(): def serve_service_worker():
return send_from_directory(application.static_folder, "service_worker.js") return send_from_directory(application.static_folder, "service_worker.js")
@application.route("/health")
@application.route("/ping")
def handle_health_check():
return "OK", 200
@application.route("/") @application.route("/")
@require_player_authentication @require_player_authentication
def handle_index(): def handle_index():
@@ -630,7 +639,15 @@ def handle_elimination_rejection():
emit("elimination_rejected", to=attacker_identifier) emit("elimination_rejected", to=attacker_identifier)
connection.close() connection.close()
if __name__ == "__main__": # --- PRODUKTIONS-SETUP (GUNICORN) ---
with application.app_context():
initialize_database() initialize_database()
scheduler_instance.start()
try:
if getattr(scheduler_instance, 'state', 0) == 0:
scheduler_instance.start()
except Exception:
pass
if __name__ == "__main__":
websocket_manager.run(application, host="0.0.0.0", port=5000) websocket_manager.run(application, host="0.0.0.0", port=5000)
+2
View File
@@ -0,0 +1,2 @@
worker_class = "geventwebsocket.gunicorn.workers.GeventWebSocketWorker"
workers = 1
+7 -4
View File
@@ -1,8 +1,11 @@
flask Flask
flask-socketio Flask-SocketIO
APScheduler
passlib passlib
argon2-cffi argon2-cffi
pyotp pyotp
apscheduler
qrcode qrcode
markdown Markdown
gunicorn
gevent
gevent-websocket