modified: Dockerfile

modified:   app.py
	modified:   bot.py
	new file:   templates/admin_giveaways.html
	new file:   templates/edit_giveaway.html
	new file:   templates/user_giveaways.html
This commit is contained in:
SimolZimol
2024-09-12 14:18:25 +02:00
parent 64466944b8
commit c3cc98cde5
6 changed files with 497 additions and 3 deletions

View File

@@ -30,6 +30,12 @@ ENV ASKMULTUS_ENABLED=$ASKMULTUS_ENABLED
ENV DISCORD_CLIENT_ID=$DISCORD_CLIENT_ID ENV DISCORD_CLIENT_ID=$DISCORD_CLIENT_ID
ENV DISCORD_CLIENT_SECRET=$DISCORD_CLIENT_SECRET ENV DISCORD_CLIENT_SECRET=$DISCORD_CLIENT_SECRET
ENV DISCORD_REDIRECT_URI=$DISCORD_REDIRECT_URI 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 # Startbefehl für das Webpanel
CMD ["python", "app.py"] CMD ["python", "app.py"]

110
app.py
View File

@@ -2,7 +2,7 @@ __version__ = "dev-0.4.6"
__all__ = ["Discordbot-chatai-webpanel (Discord)"] __all__ = ["Discordbot-chatai-webpanel (Discord)"]
__author__ = "SimolZimol" __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 from requests_oauthlib import OAuth2Session
import os import os
import subprocess import subprocess
@@ -393,5 +393,113 @@ def download_logs():
return send_file(LOG_FILE_PATH, as_attachment=True) return send_file(LOG_FILE_PATH, as_attachment=True)
return redirect(url_for("landing_page")) 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/<int:giveaway_id>", 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/<int:giveaway_id>", 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__": if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000, debug=True) app.run(host="0.0.0.0", port=5000, debug=True)

178
bot.py
View File

@@ -3,21 +3,24 @@ __all__ = ["Discordbot-chatai (Discord)"]
__author__ = "SimolZimol" __author__ = "SimolZimol"
import discord import discord
import uuid
import os, sys import os, sys
from openai import OpenAI from openai import OpenAI
from discord.ext import commands from discord.ext import commands, tasks
from discord.ui import Button, View
import requests import requests
import asyncio import asyncio
import base64 import base64
import mysql.connector import mysql.connector
import json import json
import logging import logging
from datetime import datetime from datetime import datetime, timedelta
import concurrent.futures import concurrent.futures
from gtts import gTTS from gtts import gTTS
import shutil import shutil
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from dotenv import load_dotenv from dotenv import load_dotenv
import random
load_dotenv() load_dotenv()
@@ -30,11 +33,49 @@ OPENAI_BASE_URL = os.getenv("OPENAI_BASE_URL")
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
OWNER_ID = int(os.getenv("OWNER_ID")) 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 = { features = {
"askmultus": bool(int(os.getenv("ASKMULTUS_ENABLED", 0))), "askmultus": bool(int(os.getenv("ASKMULTUS_ENABLED", 0))),
"vision": bool(int(os.getenv("VISION_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 # Erstelle einen Ordner für die Logs, wenn er noch nicht existiert
LOGS_DIR = "logs" 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(): def read_introduction():
try: try:
with open("introduction.txt", "r", encoding="utf-8") as file: with open("introduction.txt", "r", encoding="utf-8") as file:

View File

@@ -0,0 +1,74 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin - Giveaways</title>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
<style>
th a {
color: inherit;
text-decoration: none;
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="#">Multus Bot - Admin Giveaways</a>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link" href="{{ url_for('admin_dashboard') }}">Admin Dashboard</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('logout') }}">Logout</a>
</li>
</ul>
</div>
</nav>
<div class="container mt-5">
<h1 class="text-center">Giveaways Management</h1>
<table class="table table-bordered table-hover mt-4">
<thead class="thead-dark">
<tr>
<th><a href="{{ url_for('admin_giveaways', sort='id', order='asc' if sort_field == 'id' and order == 'desc' else 'desc') }}">ID</a></th>
<th><a href="{{ url_for('admin_giveaways', sort='platform', order='asc' if sort_field == 'platform' and order == 'desc' else 'desc') }}">Platform</a></th>
<th><a href="{{ url_for('admin_giveaways', sort='name', order='asc' if sort_field == 'name' and order == 'desc' else 'desc') }}">Name</a></th>
<th>Game Key</th>
<th>Winner Discord ID</th>
<th>Active</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for giveaway in giveaways %}
<tr>
<td>{{ giveaway.id }}</td>
<td>{{ giveaway.platform }}</td>
<td>{{ giveaway.name }}</td>
<td>{{ giveaway.game_key }}</td>
<td>{{ giveaway.winner_dc_id or 'Not Assigned' }}</td>
<td>
{% if giveaway.aktiv %}
<span class="badge badge-success">Active</span>
{% else %}
<span class="badge badge-danger">Inactive</span>
{% endif %}
</td>
<td>
<a href="{{ url_for('edit_giveaway', giveaway_id=giveaway.id) }}" class="btn btn-primary btn-sm">Edit</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.2/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@@ -0,0 +1,57 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Edit Giveaway</title>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="#">Multus Bot - Edit Giveaway</a>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link" href="{{ url_for('admin_giveaways') }}">Back to Giveaways</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('logout') }}">Logout</a>
</li>
</ul>
</div>
</nav>
<div class="container mt-5">
<h1 class="text-center">Edit Giveaway: {{ giveaway.name }}</h1>
<form method="POST">
<div class="form-group">
<label for="platform">Platform</label>
<input type="text" class="form-control" id="platform" name="platform" value="{{ giveaway.platform }}">
</div>
<div class="form-group">
<label for="name">Giveaway Name</label>
<input type="text" class="form-control" id="name" name="name" value="{{ giveaway.name }}">
</div>
<div class="form-group">
<label for="game_key">Game Key</label>
<input type="text" class="form-control" id="game_key" name="game_key" value="{{ giveaway.game_key }}">
</div>
<div class="form-group">
<label for="winner_dc_id">Winner Discord ID</label>
<input type="number" class="form-control" id="winner_dc_id" name="winner_dc_id" value="{{ giveaway.winner_dc_id }}">
</div>
<div class="form-group form-check">
<input type="checkbox" class="form-check-input" id="aktiv" name="aktiv" {% if giveaway.aktiv %}checked{% endif %}>
<label class="form-check-label" for="aktiv">Active</label>
</div>
<button type="submit" class="btn btn-primary">Save Changes</button>
</form>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.2/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@@ -0,0 +1,75 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Giveaways</title>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
<style>
.container {
margin-top: 50px;
}
</style>
</head>
<body>
<!-- Navbar -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="#">Multus Bot - My Giveaways</a>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link" href="{{ url_for('user_dashboard') }}">User Dashboard</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('logout') }}">Logout</a>
</li>
</ul>
</div>
</nav>
<!-- Giveaways List -->
<div class="container">
<h1 class="text-center">Giveaways You've Won</h1>
<div class="row mt-5">
<div class="col-md-12">
{% if giveaways %}
<table class="table table-bordered">
<thead class="thead-dark">
<tr>
<th>ID</th>
<th>Platform</th>
<th>Name</th>
<th>Game Key</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for giveaway in giveaways %}
<tr>
<td>{{ giveaway.id }}</td>
<td>{{ giveaway.platform }}</td>
<td>{{ giveaway.name }}</td>
<td>{{ giveaway.game_key }}</td>
<td>
<form method="POST" action="{{ url_for('redeem_giveaway', giveaway_id=giveaway.id) }}">
<button type="submit" class="btn btn-success">Redeem Prize</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p class="text-center">You have not won any giveaways yet.</p>
{% endif %}
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.2/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>