master #7

Merged
daniel merged 3 commits from master into dev 2026-03-08 17:20:27 +01:00
8 changed files with 60 additions and 22 deletions
Showing only changes of commit 3936a0b53b - Show all commits

View File

@ -1 +1 @@
{"authenticated":true,"discord_id":"277898241750859776","discord_name":"mrteels","db_id":2,"display_name":"r","discord_avatar_url":"https://cdn.discordapp.com/avatars/277898241750859776/7c3446bb51fafd72b1b4c21124b4994f.png"}
{"authenticated":true,"discord_id":"277898241750859776","discord_name":"mrteels","db_id":2,"display_name":"Stolpernder Meta-Chaser","discord_avatar_url":"https://cdn.discordapp.com/avatars/277898241750859776/7c3446bb51fafd72b1b4c21124b4994f.png"}

View File

@ -11,7 +11,12 @@ def change_display_name(player_id, new_name):
connection.commit()
connection.close()
def generate_silly_name():
adjectives = ["Verwirrter", "Blinder", "Heulender", "Zorniger", "Chaos", "Verzweifelter", "Schreiender", "Stolpernder", "Schwitzender"]
nouns = ["Grot", "Kultist", "Servitor", "Snotling", "Guardmen", "Würfellecker", "Regelvergesser", "Meta-Chaser", "Klebschnüffler"]
adj = random.choice(adjectives)
noun = random.choice(nouns)
return f"{adj} {noun}"
def get_or_create_player(discord_id, discord_name, avatar_url):
@ -25,12 +30,6 @@ def get_or_create_player(discord_id, discord_name, avatar_url):
if player is None:
# Random Silly Name Generator für neue Spieler. Damit sie angeregt werden ihren richtigen Namen einzutragen.
def generate_silly_name():
adjectives = ["Verwirrter", "Blinder", "Heulender", "Zorniger", "Chaos", "Verzweifelter", "Schreiender", "Stolpernder", "Schwitzender"]
nouns = ["Grot", "Kultist", "Servitor", "Snotling", "Guardmen", "Würfellecker", "Regelvergesser", "Meta-Chaser", "Klebschnüffler"]
adj = random.choice(adjectives)
noun = random.choice(nouns)
return f"{adj} {noun}"
silly_name = generate_silly_name()
cursor.execute("INSERT INTO players (discord_id, discord_name, display_name, discord_avatar_url) VALUES (?, ?, ?, ?)", (discord_id, discord_name, silly_name, avatar_url))
@ -456,13 +455,14 @@ def get_leaderboard(system_name):
connection.row_factory = sqlite3.Row
cursor = connection.cursor()
# Wir holen ID, Namen, Discord und MMR, sortiert vom höchsten MMR zum niedrigsten
# WIR HABEN HIER EINE BEDINGUNG HINZUGEFÜGT: AND stat.games_in_system > 0
# Dadurch filtert die Datenbank direkt auf dem Server schon alle "0-Spiele"-Accounts raus.
query = """
SELECT p.id, p.display_name, p.discord_name, stat.mmr
FROM players p
JOIN player_game_statistic stat ON p.id = stat.player_id
JOIN gamesystems sys ON stat.gamesystem_id = sys.id
WHERE sys.name = ?
WHERE sys.name = ? AND stat.games_in_system > 0
ORDER BY stat.mmr DESC
"""

View File

@ -3,6 +3,8 @@ from data import database, data_api
from gui import gui_style
def setup_routes():
@ui.page('/admin')
@ui.page('/admin', dark=True)
def home_page():
gui_style.apply_design()
gui_style.apply_design()
if app.storage.user.get('authenticated', False):
ui.card().classes("w-full")

View File

@ -11,8 +11,9 @@ def get_auth_url():
redirect_uri = f"{app_url}/login/discord"
encoded_redirect_uri = urllib.parse.quote(redirect_uri, safe="")
# NEU: scope=identify%20guilds fragt Profilbild UND Server ab
return f"https://discord.com/api/oauth2/authorize?client_id={client_id}&redirect_uri={encoded_redirect_uri}&response_type=code&scope=identify%20guilds"
# NEU: guilds.members.read erlaubt uns, die Rollen des Users in einem bestimmten Server abzufragen
return f"https://discord.com/api/oauth2/authorize?client_id={client_id}&redirect_uri={encoded_redirect_uri}&response_type=code&scope=identify%20guilds.members.read"
def setup_login_routes():
client_id = os.getenv("DISCORD_CLIENT_ID")
@ -20,7 +21,7 @@ def setup_login_routes():
app_url = os.getenv("APP_URL")
redirect_uri = f"{app_url}/login/discord"
@ui.page('/login/discord')
@ui.page('/login/discord', dark=True)
def discord_callback(code: str = None):
if not code:
ui.label('Fehler: Kein Code erhalten.').classes('text-red-500')
@ -39,8 +40,35 @@ def setup_login_routes():
if 'access_token' in token_json:
access_token = token_json['access_token']
user_headers = {'Authorization': f"Bearer {access_token}"}
# 1. Die IDs aus der .env laden (Passe die Namen an, falls sie bei dir anders heißen!)
guild_id = os.getenv("DISCORD_SERVER_ID")
role_diceghosts = os.getenv("DISCORD_SERVER_DICEGHOST_ID")
role_friend = os.getenv("DISCORD_SERVER_FRIEND_ID")
# 2. Prüfen: Ist der Nutzer überhaupt auf unserem Server?
# Wir fragen Discord gezielt nach dem Profil des Nutzers auf DEINEM Server.
member_response = requests.get(f'https://discord.com/api/users/@me/guilds/{guild_id}/member', headers=user_headers)
# Ein HTTP Status-Code 200 bedeutet "OK". Alles andere (z.B. 404 Not Found) bedeutet: Er ist nicht auf dem Server!
if member_response.status_code != 200:
ui.label('Zugriff verweigert: Du bist nicht auf dem Diceghosts Server!').classes('text-red-500 text-xl font-bold p-4')
return # Bricht die Funktion hier ab. Kein Login!
# 3. Prüfen: Hat er die richtige Rolle?
member_json = member_response.json()
# Wir holen die Liste aller Rollen des Nutzers. Wenn er keine hat, nehmen wir eine leere Liste []
user_roles = member_json.get('roles', [])
# Wir prüfen, ob mindestens eine der beiden Rollen-IDs in seiner Liste auftaucht
if role_diceghosts not in user_roles and role_friend not in user_roles:
ui.label('Zugriff verweigert: Du hast nicht die benötigte Rolle (Diceghosts oder Friend)!').classes('text-red-500 text-xl font-bold p-4')
return # Bricht die Funktion hier ab. Kein Login!
# --- AB HIER: ZUGANG GEWÄHRT! ---
# Jetzt laden wir noch seine allgemeinen Discord-Daten (für Name und Profilbild)
user_response = requests.get('https://discord.com/api/users/@me', headers=user_headers)
user_json = user_response.json()
@ -63,8 +91,8 @@ def setup_login_routes():
app.storage.user['discord_name'] = discord_name
app.storage.user['db_id'] = player[0]
app.storage.user['display_name'] = player[2]
app.storage.user['discord_avatar_url'] = player[3] # Bild speichern!
app.storage.user['discord_avatar_url'] = player[3]
ui.navigate.to('/')
else:
ui.label('Fehler beim Login!').classes('text-red-500')
ui.label('Fehler beim Login!').classes('text-red-500')

View File

@ -1,6 +1,8 @@
from nicegui import ui
def apply_design():
ui.add_css('body { background-color: #18181b; }')
# 1. Dark Mode aktivieren
ui.dark_mode(True)

View File

@ -4,7 +4,7 @@ from data import data_api
def setup_routes():
# 1. Die {}-Klammern definieren eine dynamische Variable in der URL
@ui.page('/statistic/{systemname}')
@ui.page('/statistic/{systemname}', dark=True)
def gamesystem_statistic_page(systemname: str): # <--- WICHTIG: Hier fangen wir das Wort aus der URL auf!
# Sicherheitscheck: Ist der User eingeloggt?

View File

@ -4,7 +4,7 @@ from gui import discord_login, gui_style
from match_calculations import calc_match
def setup_routes(admin_discord_id):
@ui.page('/')
@ui.page('/', dark=True)
def home_page():
gui_style.apply_design()
@ -48,7 +48,7 @@ def setup_routes(admin_discord_id):
ui.button(icon='edit', color='primary', on_click=toggle_edit_mode).props('round dense')
# --- ANSICHT 2: Das Eingabefeld (startet unsichtbar!) ---
with ui.row().classes('items-center gap-2') as edit_row:
with ui.row().classes('items-center gap-5') as edit_row:
edit_row.visible = False # Am Anfang verstecken
def save_new_name():
@ -65,8 +65,14 @@ def setup_routes(admin_discord_id):
# Wenn nichts geändert wurde, einfach wieder einklappen
toggle_edit_mode()
def generate_random_silly_name():
silly_name = data_api.generate_silly_name()
name_input.value=silly_name
name_input = ui.input('Neuer Name', value=display_name).on('keydown.enter', save_new_name)
ui.button(icon='save', color='positive', on_click=save_new_name).props('round dense')
ui.button(icon='casino', on_click=generate_random_silly_name).props('round dense')
ui.button(icon='close', color='negative', on_click=toggle_edit_mode).props('round dense')
avatar = app.storage.user.get('avatar_url')

View File

@ -6,7 +6,7 @@ from match_calculations import calc_match
def setup_routes():
# 1. Die {}-Klammern definieren eine dynamische Variable in der URL
@ui.page('/add-match/{systemname}')
@ui.page('/add-match/{systemname}', dark=True)
def match_form_page(systemname: str): # <--- WICHTIG: Hier fangen wir das Wort aus der URL auf!
gui_style.apply_design()