diff --git a/Dockerfile b/Dockerfile index 56d46bd..ef61ec8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,6 +30,12 @@ ENV ASKMULTUS_ENABLED=$ASKMULTUS_ENABLED ENV DISCORD_CLIENT_ID=$DISCORD_CLIENT_ID ENV DISCORD_CLIENT_SECRET=$DISCORD_CLIENT_SECRET ENV DISCORD_REDIRECT_URI=$DISCORD_REDIRECT_URI +ENV GIVEAWAY_DB_HOST=$GIVEAWAY_DB_HOST +ENV GIVEAWAY_DB_PORT=$GIVEAWAY_DB_PORT +ENV GIVEAWAY_DB_USER=$GIVEAWAY_DB_USER +ENV GIVEAWAY_DB_PASSWORD=$GIVEAWAY_DB_PASSWORD +ENV GIVEAWAY_DB_DATABASE=$GIVEAWAY_DB_DATABASE +ENV GIVEAWAY_WEBSITE_URL=$GIVEAWAY_WEBSITE_URL # Startbefehl für das Webpanel CMD ["python", "app.py"] diff --git a/app.py b/app.py index 1c14524..a7a21cb 100644 --- a/app.py +++ b/app.py @@ -2,7 +2,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 +from flask import Flask, render_template, redirect, url_for, request, session, jsonify, send_file, flash from requests_oauthlib import OAuth2Session import os import subprocess @@ -393,5 +393,113 @@ def download_logs(): return send_file(LOG_FILE_PATH, as_attachment=True) return redirect(url_for("landing_page")) +@app.route("/admin/giveaways", methods=["GET", "POST"]) +def admin_giveaways(): + """Zeigt eine Liste aller Giveaways an und ermöglicht das Bearbeiten und Sortieren.""" + if is_admin(): + connection = get_db_connection() + cursor = connection.cursor(dictionary=True) + + # Sortierung nach bestimmten Feldern + sort_field = request.args.get("sort", "id") # Standardmäßig nach 'id' sortieren + order = request.args.get("order", "asc") # Standardmäßig aufsteigend sortieren + + # Holen aller Giveaways aus der Datenbank + cursor.execute(f"SELECT * FROM giveaways ORDER BY {sort_field} {order}") + giveaways = cursor.fetchall() + + cursor.close() + connection.close() + + return render_template("admin_giveaways.html", giveaways=giveaways, sort_field=sort_field, order=order) + return redirect(url_for("login")) + +@app.route("/admin/giveaways/edit/", methods=["GET", "POST"]) +def edit_giveaway(giveaway_id): + """Bearbeitet ein spezifisches Giveaway.""" + if is_admin(): + connection = get_db_connection() + cursor = connection.cursor(dictionary=True) + + if request.method == "POST": + platform = request.form.get("platform") + name = request.form.get("name") + game_key = request.form.get("game_key") + winner_dc_id = request.form.get("winner_dc_id") + aktiv = bool(request.form.get("aktiv")) + + # Update der Giveaways-Daten + cursor.execute(""" + UPDATE giveaways + SET platform = %s, name = %s, game_key = %s, winner_dc_id = %s, aktiv = %s + WHERE id = %s + """, (platform, name, game_key, winner_dc_id, aktiv, giveaway_id)) + connection.commit() + + flash("Giveaway updated successfully!", "success") + return redirect(url_for("admin_giveaways")) + + # Daten des spezifischen Giveaways laden + cursor.execute("SELECT * FROM giveaways WHERE id = %s", (giveaway_id,)) + giveaway = cursor.fetchone() + + cursor.close() + connection.close() + + return render_template("edit_giveaway.html", giveaway=giveaway) + return redirect(url_for("login")) + +@app.route("/user/giveaways", methods=["GET"]) +def user_giveaways(): + """Zeigt dem Benutzer die Giveaways, die er gewonnen 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) + + # Suche nach Giveaways, bei denen der eingeloggte Benutzer der Gewinner ist + cursor.execute(""" + SELECT * FROM giveaways WHERE winner_dc_id = %s AND aktiv = TRUE + """, (user_id,)) + won_giveaways = cursor.fetchall() + + cursor.close() + connection.close() + + return render_template("user_giveaways.html", user_info=user_info, giveaways=won_giveaways) + + return redirect(url_for("login")) + +@app.route("/user/giveaway/redeem/", methods=["POST"]) +def redeem_giveaway(giveaway_id): + """Erlaubt dem Benutzer, seinen Giveaway-Preis abzuholen.""" + if "discord_user" in session: + user_info = session["discord_user"] + user_id = user_info["id"] + + connection = get_db_connection() + cursor = connection.cursor(dictionary=True) + + # Überprüfe, ob der eingeloggte Benutzer der Gewinner ist + cursor.execute("SELECT * FROM giveaways WHERE id = %s AND winner_dc_id = %s AND aktiv = TRUE", (giveaway_id, user_id)) + giveaway = cursor.fetchone() + + if giveaway: + # Setze das Giveaway auf inaktiv, damit es nicht erneut eingelöst werden kann + cursor.execute("UPDATE giveaways SET aktiv = FALSE WHERE id = %s", (giveaway_id,)) + connection.commit() + flash("You have successfully redeemed your prize!", "success") + else: + flash("You are not the winner of this giveaway or the giveaway is no longer active.", "danger") + + cursor.close() + connection.close() + + return redirect(url_for("user_giveaways")) + + return redirect(url_for("login")) + if __name__ == "__main__": app.run(host="0.0.0.0", port=5000, debug=True) diff --git a/bot.py b/bot.py index d85bbc1..57bf22d 100644 --- a/bot.py +++ b/bot.py @@ -3,21 +3,24 @@ __all__ = ["Discordbot-chatai (Discord)"] __author__ = "SimolZimol" import discord +import uuid import os, sys from openai import OpenAI -from discord.ext import commands +from discord.ext import commands, tasks +from discord.ui import Button, View import requests import asyncio import base64 import mysql.connector import json import logging -from datetime import datetime +from datetime import datetime, timedelta import concurrent.futures from gtts import gTTS import shutil from bs4 import BeautifulSoup from dotenv import load_dotenv +import random load_dotenv() @@ -30,11 +33,49 @@ OPENAI_BASE_URL = os.getenv("OPENAI_BASE_URL") OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") OWNER_ID = int(os.getenv("OWNER_ID")) +GIVEAWAY_DB_HOST = os.getenv("GIVEAWAY_DB_HOST") +GIVEAWAY_DB_PORT = os.getenv("GIVEAWAY_DB_PORT") +GIVEAWAY_DB_USER = os.getenv("GIVEAWAY_DB_USER") +GIVEAWAY_DB_PASSWORD = os.getenv("GIVEAWAY_DB_PASSWORD") +GIVEAWAY_DB_DATABASE = os.getenv("GIVEAWAY_DB_DATABASE") +GIVEAWAY_WEBSITE_URL = os.getenv("GIVEAWAY_WEBSITE_URL") + features = { "askmultus": bool(int(os.getenv("ASKMULTUS_ENABLED", 0))), "vision": bool(int(os.getenv("VISION_ENABLED", 0))) } +def connect_to_giveaway_db(): + return mysql.connector.connect( + host=GIVEAWAY_DB_HOST, + port=GIVEAWAY_DB_PORT, + user=GIVEAWAY_DB_USER, + password=GIVEAWAY_DB_PASSWORD, + database=GIVEAWAY_DB_DATABASE + ) + +def create_giveaway_table(): + connection = connect_to_giveaway_db() + cursor = connection.cursor() + create_table_query = """ + CREATE TABLE IF NOT EXISTS giveaways ( + id INT AUTO_INCREMENT PRIMARY KEY, + platform VARCHAR(255), + name VARCHAR(255), + uuid CHAR(36) NOT NULL UNIQUE, + game_key VARCHAR(255), + winner_dc_id BIGINT, + aktiv BOOLEAN DEFAULT TRUE + ); + """ + cursor.execute(create_table_query) + connection.commit() + cursor.close() + connection.close() + +create_giveaway_table() + +giveaways = {} # Erstelle einen Ordner für die Logs, wenn er noch nicht existiert LOGS_DIR = "logs" @@ -241,6 +282,139 @@ def load_user_data(user_id): #----------------------------------------------------------------------------------------------------------- +def save_giveaway_to_db(platform, name, prize_uuid, game_key, winner_dc_id=None): + connection = connect_to_giveaway_db() + cursor = connection.cursor() + insert_query = """ + INSERT INTO giveaways (platform, name, uuid, game_key, winner_dc_id, aktiv) + VALUES (%s, %s, %s, %s, %s, %s) + """ + data = (platform, name, str(prize_uuid), game_key, winner_dc_id, True) + cursor.execute(insert_query, data) + connection.commit() + cursor.close() + connection.close() + +def update_winner_in_db(prize_uuid, winner_dc_id): + connection = connect_to_giveaway_db() + cursor = connection.cursor() + update_query = """ + UPDATE giveaways SET winner_dc_id = %s, aktiv = FALSE WHERE uuid = %s + """ + data = (winner_dc_id, str(prize_uuid)) + cursor.execute(update_query, data) + connection.commit() + cursor.close() + connection.close() + +class Giveaway: + def __init__(self, ctx, platform, prize, num_winners, title, subtitle, duration, end_time): + self.ctx = ctx + self.platform = platform + self.prize = prize + self.num_winners = num_winners + self.title = title + self.subtitle = subtitle + self.duration = duration + self.end_time = end_time + self.participants = [] + self.prize_uuid = uuid.uuid4() # Generiert eine eindeutige UUID + self.game_key = f"KEY-{uuid.uuid4()}" # Simulierter Game-Key, der ersetzt werden kann + + # Speichern des Giveaways in der Datenbank + save_giveaway_to_db(self.platform, self.title, self.prize_uuid, self.game_key) + + def add_participant(self, user): + if user not in self.participants: + self.participants.append(user) + return True + return False + + def is_finished(self): + return datetime.now() >= self.end_time + + def pick_winners(self): + return random.sample(self.participants, min(self.num_winners, len(self.participants))) + +@client.hybrid_command() +async def startgiveaway(ctx, platform: str, prize: str, num_winners: int, title: str, subtitle: str, duration: str): + """Erstellt ein Giveaway. Nur für Mods und höher verfügbar.""" + user_data = load_user_data(ctx.author.id) + if user_data["permission"] < 5: + await ctx.send("Du hast keine Berechtigung, um ein Giveaway zu erstellen.") + return + + if duration.endswith("m"): + minutes = int(duration[:-1]) + end_time = datetime.now() + timedelta(minutes=minutes) + elif duration.endswith("d"): + days = int(duration[:-1]) + end_time = datetime.now() + timedelta(days=days) + else: + await ctx.send("Ungültige Dauer. Bitte benutze 'm' für Minuten oder 'd' für Tage.") + return + + # Neues Giveaway erstellen + giveaway = Giveaway(ctx, platform, prize, num_winners, title, subtitle, duration, end_time) + giveaway_id = len(giveaways) + 1 + giveaways[giveaway_id] = giveaway + + button = Button(label="Teilnehmen", style=discord.ButtonStyle.green, custom_id=f"giveaway_{giveaway_id}") + view = View() + view.add_item(button) + + embed = discord.Embed( + title=title, + description=f"{subtitle}\n\nPreis: {prize}\nPlattform: {platform}\nAnzahl der Gewinner: {num_winners}\nEndet in: {duration}", + color=0x00ff00 + ) + embed.set_footer(text=f"Giveaway endet am {end_time.strftime('%Y-%m-%d %H:%M:%S')}") + await ctx.send(embed=embed, view=view) + + check_giveaway.start(giveaway_id) + +@tasks.loop(minutes=1) +async def check_giveaway(giveaway_id): + """Überprüft alle 1 Minute, ob das Giveaway beendet ist.""" + giveaway = giveaways.get(giveaway_id) + + if giveaway and giveaway.is_finished(): + check_giveaway.stop() + + winners = giveaway.pick_winners() + if winners: + winner_mentions = ", ".join([winner.mention for winner in winners]) + await giveaway.ctx.send(f"🎉 Glückwunsch an die Gewinner des Giveaways '{giveaway.title}'! Die Gewinner sind: {winner_mentions}") + + # Jeden Gewinner benachrichtigen und zur Webseite schicken + for winner in winners: + # Gewinner in der Datenbank speichern + update_winner_in_db(giveaway.prize_uuid, winner.id) + # Nachricht an den Gewinner senden + await winner.send(f"🎁 Congratulations! You won the giveaway '{giveaway.title}'!\n" + f"Please claim your prize using the following link: {GIVEAWAY_WEBSITE_URL}{giveaway.prize_uuid}") + else: + await giveaway.ctx.send(f"Das Giveaway '{giveaway.title}' wurde beendet, aber es gab keine Teilnehmer.") + + del giveaways[giveaway_id] + +@client.event +async def on_interaction(interaction): + """Bearbeitet die Teilnahme an einem Giveaway.""" + if interaction.data["custom_id"].startswith("giveaway_"): + giveaway_id = int(interaction.data["custom_id"].split("_")[1]) + giveaway = giveaways.get(giveaway_id) + + if giveaway: + if giveaway.is_finished(): + await interaction.response.send_message("Dieses Giveaway ist bereits beendet.", ephemeral=True) + else: + added = giveaway.add_participant(interaction.user) + if added: + await interaction.response.send_message("Du hast erfolgreich am Giveaway teilgenommen!", ephemeral=True) + else: + await interaction.response.send_message("Du nimmst bereits am Giveaway teil.", ephemeral=True) + def read_introduction(): try: with open("introduction.txt", "r", encoding="utf-8") as file: diff --git a/templates/admin_giveaways.html b/templates/admin_giveaways.html new file mode 100644 index 0000000..1f4e6f0 --- /dev/null +++ b/templates/admin_giveaways.html @@ -0,0 +1,74 @@ + + + + + + + Admin - Giveaways + + + + + + + +
+

Giveaways Management

+ + + + + + + + + + + + + + {% for giveaway in giveaways %} + + + + + + + + + + {% endfor %} + +
IDPlatformNameGame KeyWinner Discord IDActiveActions
{{ giveaway.id }}{{ giveaway.platform }}{{ giveaway.name }}{{ giveaway.game_key }}{{ giveaway.winner_dc_id or 'Not Assigned' }} + {% if giveaway.aktiv %} + Active + {% else %} + Inactive + {% endif %} + + Edit +
+
+ + + + + + diff --git a/templates/edit_giveaway.html b/templates/edit_giveaway.html new file mode 100644 index 0000000..3419e8c --- /dev/null +++ b/templates/edit_giveaway.html @@ -0,0 +1,57 @@ + + + + + + + Edit Giveaway + + + + + + +
+

Edit Giveaway: {{ giveaway.name }}

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+ + + + + + diff --git a/templates/user_giveaways.html b/templates/user_giveaways.html new file mode 100644 index 0000000..a6006e7 --- /dev/null +++ b/templates/user_giveaways.html @@ -0,0 +1,75 @@ + + + + + + + My Giveaways + + + + + + + + + +
+

Giveaways You've Won

+
+
+ {% if giveaways %} + + + + + + + + + + + + {% for giveaway in giveaways %} + + + + + + + + {% endfor %} + +
IDPlatformNameGame KeyActions
{{ giveaway.id }}{{ giveaway.platform }}{{ giveaway.name }}{{ giveaway.game_key }} +
+ +
+
+ {% else %} +

You have not won any giveaways yet.

+ {% endif %} +
+
+
+ + + + + +