modified: app.py

modified:   templates/global_admin_dashboard.html
	modified:   templates/user_dashboard.html
	modified:   templates/user_landing_page.html
This commit is contained in:
SimolZimol
2024-10-25 13:56:32 +02:00
parent f3a8eebc44
commit c917f30e4f
4 changed files with 190 additions and 68 deletions

252
app.py
View File

@@ -1,3 +1,7 @@
__version__ = "dev-0.4.6"
__all__ = ["Discordbot-chatai-webpanel (Discord)"]
__author__ = "SimolZimol"
from flask import Flask, render_template, redirect, url_for, request, session, jsonify, send_file, flash, g from flask import Flask, render_template, redirect, url_for, request, session, jsonify, send_file, flash, g
from requests_oauthlib import OAuth2Session from requests_oauthlib import OAuth2Session
import os import os
@@ -11,9 +15,11 @@ app = Flask(__name__)
app.secret_key = os.getenv("FLASK_SECRET_KEY") app.secret_key = os.getenv("FLASK_SECRET_KEY")
LOG_FILE_PATH = os.path.join("logs", f"{datetime.now().strftime('%Y-%m-%d')}.log") LOG_FILE_PATH = os.path.join("logs", f"{datetime.now().strftime('%Y-%m-%d')}.log")
app.config["SESSION_TYPE"] = "filesystem" app.config["SESSION_TYPE"] = "filesystem" # Oder 'redis' für Redis-basierte Speicherung
Session(app) Session(app)
print(f"Session Type: {app.config['SESSION_TYPE']}")
# Verwende Umgebungsvariablen für die Datenbankverbindung
DB_HOST = os.getenv("DB_HOST") DB_HOST = os.getenv("DB_HOST")
DB_PORT = os.getenv("DB_PORT") DB_PORT = os.getenv("DB_PORT")
DB_USER = os.getenv("DB_USER") DB_USER = os.getenv("DB_USER")
@@ -28,25 +34,36 @@ DISCORD_TOKEN_URL = "https://discord.com/api/oauth2/token"
DISCORD_API_URL = "https://discord.com/api/users/@me" DISCORD_API_URL = "https://discord.com/api/users/@me"
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1' os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
# Speichern der Prozess-ID
bot_process = None bot_process = None
def bot_status(): def bot_status():
"""Überprüft, ob der Bot läuft."""
global bot_process global bot_process
return bot_process is not None and bot_process.poll() is None if bot_process is None:
return False
return bot_process.poll() is None # None bedeutet, dass der Prozess noch läuft
def start_bot(): def start_bot():
"""Startet den Bot."""
global bot_process global bot_process
if not bot_status(): if not bot_status():
bot_process = subprocess.Popen(["python", "bot.py"], cwd=os.path.dirname(os.path.abspath(__file__))) bot_process = subprocess.Popen(["python", "bot.py"], cwd=os.path.dirname(os.path.abspath(__file__)))
else:
print("Bot läuft bereits.")
def stop_bot(): def stop_bot():
"""Stoppt den Bot."""
global bot_process global bot_process
if bot_process and bot_status(): if bot_process and bot_status():
bot_process.terminate() bot_process.terminate()
bot_process.wait() bot_process.wait() # Warten, bis der Prozess beendet ist
bot_process = None bot_process = None
else:
print("Bot läuft nicht.")
def get_db_connection(): def get_db_connection():
"""Stellt eine Verbindung zur MySQL-Datenbank her."""
return mysql.connector.connect( return mysql.connector.connect(
host=DB_HOST, host=DB_HOST,
port=DB_PORT, port=DB_PORT,
@@ -73,48 +90,93 @@ def make_discord_session(token=None, state=None):
token_updater=token_updater token_updater=token_updater
) )
def is_bot_admin():
"""Überprüft, ob der Benutzer globale Admin-Rechte hat."""
if "discord_user" in session:
user_info = session["discord_user"]
user_id = user_info["id"]
connection = get_db_connection()
cursor = connection.cursor(dictionary=True)
cursor.execute("SELECT global_permission FROM bot_data WHERE user_id = %s", (user_id,))
user_data = cursor.fetchone()
cursor.close()
connection.close()
return user_data and user_data["global_permission"] >= 8
return False
def is_server_admin(guild_id):
"""Überprüft, ob der Benutzer Admin-Rechte auf einem bestimmten Server (Guild) hat."""
if "discord_user" in session:
user_info = session["discord_user"]
user_id = user_info["id"]
connection = get_db_connection()
cursor = connection.cursor(dictionary=True)
cursor.execute("SELECT permission FROM user_data WHERE user_id = %s AND guild_id = %s", (user_id, guild_id))
user_data = cursor.fetchone()
cursor.close()
connection.close()
return user_data and user_data["permission"] >= 8
return False
@app.route("/")
def landing_page():
"""Landing Page"""
return render_template("landing.html")
@app.route("/about")
def about():
"""Öffentliche Über-uns-Seite"""
return render_template("about.html")
@app.route("/contact")
def contact():
"""Öffentliche Kontaktseite"""
return render_template("contact.html")
@app.route("/faq")
def faq():
"""Öffentliche FAQ-Seite"""
return render_template("faq.html")
@app.route("/help")
def help_page():
"""Öffentliche Hilfeseite"""
return render_template("help.html")
@app.route("/login")
def login():
"""Startet den Discord-OAuth2-Flow."""
discord = make_discord_session()
authorization_url, state = discord.authorization_url(DISCORD_OAUTH2_URL)
session['oauth_state'] = state
return redirect(authorization_url)
@app.before_request @app.before_request
def load_user_data(): def load_user_data():
"""Lädt Benutzerdaten vor jeder Anfrage für geschützte Routen."""
if "discord_user" in session: if "discord_user" in session:
g.user_info = session["discord_user"] g.user_info = session["discord_user"]
g.is_admin = session.get("is_admin", False) g.is_admin = session.get("is_admin", False)
g.guilds = session.get("discord_guilds", []) g.guilds = session.get("discord_guilds", [])
g.bot_running = bot_status() g.bot_running = bot_status() # Lädt den Bot-Status in g
else: else:
# Falls der Benutzer nicht eingeloggt ist, keine Daten setzen
g.user_info = None g.user_info = None
g.is_admin = False g.is_admin = False
g.guilds = [] g.guilds = []
g.bot_running = False g.bot_running = False
@app.route("/")
def landing_page():
return render_template("landing.html")
@app.route("/about")
def about():
return render_template("about.html")
@app.route("/contact")
def contact():
return render_template("contact.html")
@app.route("/faq")
def faq():
return render_template("faq.html")
@app.route("/help")
def help_page():
return render_template("help.html")
@app.route("/login")
def login():
discord = make_discord_session()
authorization_url, state = discord.authorization_url(DISCORD_OAUTH2_URL)
session['oauth_state'] = state
return redirect(authorization_url)
@app.route("/callback") @app.route("/callback")
def callback(): def callback():
"""Verarbeitet den OAuth2-Rückruf von Discord."""
try: try:
discord = make_discord_session(state=session.get("oauth_state")) discord = make_discord_session(state=session.get("oauth_state"))
token = discord.fetch_token( token = discord.fetch_token(
@@ -122,100 +184,160 @@ def callback():
client_secret=DISCORD_CLIENT_SECRET, client_secret=DISCORD_CLIENT_SECRET,
authorization_response=request.url, authorization_response=request.url,
) )
session['oauth_token'] = token session['oauth_token'] = token
# Abrufen der Benutzerinformationen von Discord
user_info = discord.get(DISCORD_API_URL).json() user_info = discord.get(DISCORD_API_URL).json()
session['discord_user'] = user_info session['discord_user'] = user_info
# Hole die Gilden (Server), auf denen der Benutzer ist
guilds_response = discord.get('https://discord.com/api/users/@me/guilds') guilds_response = discord.get('https://discord.com/api/users/@me/guilds')
if guilds_response.status_code != 200: if guilds_response.status_code != 200:
flash("Fehler beim Abrufen der Gilden.", "danger") flash("Fehler beim Abrufen der Gilden.", "danger")
return redirect(url_for("landing_page")) return redirect(url_for("landing_page"))
session['discord_guilds'] = guilds_response.json() guilds = guilds_response.json()
session['discord_guilds'] = guilds # Speichere die Gilden in der Session
# Prüfe die Admin-Berechtigungen in der bot_data Tabelle
connection = get_db_connection() connection = get_db_connection()
cursor = connection.cursor(dictionary=True) cursor = connection.cursor(dictionary=True)
cursor.execute("SELECT global_permission FROM bot_data WHERE user_id = %s", (user_info["id"],)) cursor.execute("SELECT global_permission FROM bot_data WHERE user_id = %s", (user_info["id"],))
bot_admin_data = cursor.fetchone() bot_admin_data = cursor.fetchone()
# Speichere Admin-Rechte in der Session
session['is_admin'] = bool(bot_admin_data and bot_admin_data['global_permission'] >= 8) session['is_admin'] = bool(bot_admin_data and bot_admin_data['global_permission'] >= 8)
cursor.close() cursor.close()
connection.close() connection.close()
# Leite zur User-Landing-Page weiter
return redirect(url_for("user_landing_page")) return redirect(url_for("user_landing_page"))
except Exception as e: except Exception as e:
print(f"Error in OAuth2 callback: {e}") print(f"Error in OAuth2 callback: {e}")
flash("Ein Fehler ist beim Authentifizierungsprozess aufgetreten.", "danger") flash("Ein Fehler ist beim Authentifizierungsprozess aufgetreten.", "danger")
return redirect(url_for("landing_page")) return redirect(url_for("landing_page"))
@app.route("/user_server_data/<int:guild_id>")
def user_server_data(guild_id):
"""Zeigt die serverbezogenen Nutzerdaten für den ausgewählten Server an."""
if "discord_user" in session:
user_info = session["discord_user"]
user_id = user_info["id"]
@app.route("/user_landing_page")
def user_landing_page():
if g.user_info:
return render_template("user_landing_page.html")
return redirect(url_for("landing_page"))
@app.route("/global_admin_dashboard")
def global_admin_dashboard():
if g.is_admin:
return render_template("global_admin_dashboard.html")
return redirect(url_for("user_landing_page"))
@app.route("/user_dashboard/<int:guild_id>")
def user_dashboard(guild_id):
if g.user_info:
connection = get_db_connection() connection = get_db_connection()
cursor = connection.cursor(dictionary=True) cursor = connection.cursor(dictionary=True)
cursor.execute("SELECT * FROM user_data WHERE user_id = %s AND guild_id = %s", (g.user_info["id"], guild_id))
g.user_data = cursor.fetchone() # Hole die serverbezogenen Nutzerdaten
cursor.execute("SELECT * FROM user_data WHERE user_id = %s AND guild_id = %s", (user_id, guild_id))
user_data = cursor.fetchone()
cursor.close() cursor.close()
connection.close() connection.close()
if g.user_data: if user_data:
g.guild_id = guild_id return render_template("user_server_data.html", user_info=user_info, user_data=user_data, guild_id=guild_id)
return render_template("user_dashboard.html") else:
flash("Keine Daten für diesen Server gefunden.", "warning")
return redirect(url_for("user_landing_page"))
return redirect(url_for("landing_page")) return redirect(url_for("landing_page"))
@app.route("/server_admin_dashboard/<int:guild_id>") @app.route("/server_admin_dashboard/<int:guild_id>")
def server_admin_dashboard(guild_id): def server_admin_dashboard(guild_id):
"""Serverbasiertes Admin-Dashboard für server-spezifische Admin-Rechte"""
if g.user_info: if g.user_info:
user_id = g.user_info["id"]
# Überprüfe, ob der Benutzer Admin-Rechte auf dem spezifischen Server hat
connection = get_db_connection() connection = get_db_connection()
cursor = connection.cursor(dictionary=True) cursor = connection.cursor(dictionary=True)
cursor.execute("SELECT permission FROM user_data WHERE user_id = %s AND guild_id = %s", (g.user_info["id"], guild_id))
cursor.execute("SELECT permission FROM user_data WHERE user_id = %s AND guild_id = %s", (user_id, guild_id))
user_data = cursor.fetchone() user_data = cursor.fetchone()
cursor.execute("SELECT name FROM guilds WHERE guild_id = %s", (guild_id,)) cursor.execute("SELECT name FROM guilds WHERE guild_id = %s", (guild_id,)) # Nehme an, du speicherst Guild-Infos
guild_name = cursor.fetchone()["name"] guild_name = cursor.fetchone()["name"]
cursor.close() cursor.close()
connection.close() connection.close()
if user_data and user_data['permission'] >= 8: if user_data and user_data['permission'] >= 8:
g.guild_id = guild_id # Benutzer ist Admin auf diesem Server
g.guild_name = guild_name return render_template("server_admin_dashboard.html", guild_id=guild_id, guild_name=guild_name)
return render_template("server_admin_dashboard.html")
return redirect(url_for("user_landing_page")) return redirect(url_for("user_landing_page"))
@app.route("/server_giveaways/<int:guild_id>") @app.route("/user_dashboard/<int:guild_id>")
def server_giveaways(guild_id): def user_dashboard(guild_id):
"""Serverbasiertes User-Dashboard"""
if g.user_info: if g.user_info:
user_id = g.user_info["id"]
# Hole die serverbezogenen Nutzerdaten
connection = get_db_connection() connection = get_db_connection()
cursor = connection.cursor(dictionary=True) cursor = connection.cursor(dictionary=True)
cursor.execute("SELECT permission FROM user_data WHERE user_id = %s AND guild_id = %s", (g.user_info["id"], guild_id))
cursor.execute("SELECT * FROM user_data WHERE user_id = %s AND guild_id = %s", (user_id, guild_id))
user_data = cursor.fetchone()
cursor.close()
connection.close()
if user_data:
return render_template("user_dashboard.html", user_info=g.user_info, user_data=user_data, guild_id=guild_id)
return redirect(url_for("landing_page"))
@app.route("/server_giveaways/<int:guild_id>")
def server_giveaways(guild_id):
"""Serverbasiertes Giveaway-Management"""
if g.user_info:
user_id = g.user_info["id"]
# Überprüfe, ob der Benutzer Admin-Rechte auf diesem Server hat
connection = get_db_connection()
cursor = connection.cursor(dictionary=True)
cursor.execute("SELECT permission FROM user_data WHERE user_id = %s AND guild_id = %s", (user_id, guild_id))
user_data = cursor.fetchone() user_data = cursor.fetchone()
if user_data and user_data['permission'] >= 8: if user_data and user_data['permission'] >= 8:
# Hole die Giveaways für diesen Server
cursor.execute("SELECT * FROM giveaway_data WHERE guild_id = %s", (guild_id,)) cursor.execute("SELECT * FROM giveaway_data WHERE guild_id = %s", (guild_id,))
g.giveaways = cursor.fetchall() giveaways = cursor.fetchall()
g.guild_id = guild_id
cursor.close() cursor.close()
connection.close() connection.close()
return render_template("server_giveaways.html")
return render_template("server_giveaways.html", giveaways=giveaways, guild_id=guild_id)
return redirect(url_for("user_landing_page"))
@app.route("/user_landing_page")
def user_landing_page():
"""Zeigt die globale Benutzerdaten und die Liste der Server an."""
if g.user_info and "discord_guilds" in session:
guilds = session["discord_guilds"]
return render_template("user_landing_page.html", user_info=g.user_info, guilds=guilds)
return redirect(url_for("landing_page"))
@app.route("/global_admin_dashboard")
def global_admin_dashboard():
"""Globales Admin-Dashboard nur für globale Admins"""
if g.is_admin:
bot_running = bot_status() # Funktion, die den Status des Bots prüft
return render_template("global_admin_dashboard.html", user_info=g.user_info, bot_running=bot_running)
return redirect(url_for("user_landing_page")) return redirect(url_for("user_landing_page"))
@app.route("/logout") @app.route("/logout")
def logout(): def logout():
"""Meldet den Benutzer ab."""
session.clear() session.clear()
return redirect(url_for("landing_page")) return redirect(url_for("landing_page"))

View File

@@ -24,7 +24,7 @@
</nav> </nav>
<div class="container mt-5"> <div class="container mt-5">
<h1 class="text-center">Welcome, {{ g.user_info.username }} (Admin)</h1> <h1 class="text-center">Welcome, {{ g.user_info['username'] }} (Admin)</h1>
<p class="text-center">Manage global bot settings and controls.</p> <p class="text-center">Manage global bot settings and controls.</p>
<div class="card mt-4"> <div class="card mt-4">

View File

@@ -11,7 +11,7 @@
<body> <body>
{% include 'navigation.html' %} {% include 'navigation.html' %}
<div class="container mt-5"> <div class="container mt-5">
<h1>Welcome, {{ g.user_info.username }}!</h1> <h1>Welcome, {{ g.user_info['username'] }}!</h1>
<p>Your Points: {{ g.user_data['points'] }}</p> <p>Your Points: {{ g.user_data['points'] }}</p>
<p>Level: {{ g.user_data['level'] }}</p> <p>Level: {{ g.user_data['level'] }}</p>
<p>Server ID: {{ g.guild_id }}</p> <p>Server ID: {{ g.guild_id }}</p>

View File

@@ -11,7 +11,7 @@
<body> <body>
{% include 'navigation.html' %} {% include 'navigation.html' %}
<div class="container mt-5"> <div class="container mt-5">
<h1>Welcome, {{ g.user_info.username }}</h1> <h1>Welcome, {{ g.user_info['username'] }}</h1>
<p>Select a server to view your server-specific data.</p> <p>Select a server to view your server-specific data.</p>
<div class="row"> <div class="row">