First Commit

This commit is contained in:
2025-09-16 15:00:16 +02:00
commit c8980f785f
188 changed files with 43407 additions and 0 deletions
Executable
+363
View File
@@ -0,0 +1,363 @@
import sys
import os
if __package__ is None or __package__ == "":
# Running as __main__ (e.g. python web/app.py)
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
from utils.sql_commands import DatabaseManager
else:
# Imported as a module (e.g. from bot.py)
from utils.sql_commands import DatabaseManager
import os
import requests
from flask import Flask, redirect, url_for, session, request, render_template, flash
from dotenv import load_dotenv
from collections import defaultdict
import datetime
import json
load_dotenv()
app = Flask(__name__)
app.secret_key = os.getenv("SECRET_KEY")
db = DatabaseManager()
# Ensure required environment variables are loaded
DISCORD_CLIENT_ID = os.getenv("DISCORD_CLIENT_ID")
DISCORD_CLIENT_SECRET = os.getenv("DISCORD_CLIENT_SECRET")
DISCORD_REDIRECT_URI = os.getenv("DISCORD_REDIRECT_URI")
DISCORD_API_BASE_URL = "https://discord.com/api"
DISCORD_BOT_TOKEN = os.getenv("TOKEN")
# Check for missing environment variables
if not all([DISCORD_CLIENT_ID, DISCORD_CLIENT_SECRET, DISCORD_REDIRECT_URI]):
raise EnvironmentError("One or more required environment variables are missing.")
# OAuth2 login route
@app.route("/login")
def login():
discord_auth_url = (
f"{DISCORD_API_BASE_URL}/oauth2/authorize"
f"?client_id={DISCORD_CLIENT_ID}&redirect_uri={DISCORD_REDIRECT_URI}"
f"&response_type=code&scope=identify%20guilds%20applications.commands%20bot"
)
return redirect(discord_auth_url)
def can_add_bot(guild):
# Check if the user has permission to manage the bot
permissions = guild.get(
"permissions", 0
) # Ensure permissions are included in the guild data
# Bitwise operation for managing server (assuming manage_server is 0x20)
return (permissions & 0x20) != 0
# OAuth2 callback route
@app.route("/callback")
def callback():
code = request.args.get("code")
if not code:
flash("Authorization code was not provided.")
return redirect(url_for("home"))
data = {
"client_id": DISCORD_CLIENT_ID,
"client_secret": DISCORD_CLIENT_SECRET,
"grant_type": "authorization_code",
"code": code,
"redirect_uri": DISCORD_REDIRECT_URI,
}
headers = {"Content-Type": "application/x-www-form-urlencoded"}
response = requests.post(
f"{DISCORD_API_BASE_URL}/oauth2/token", data=data, headers=headers
)
if response.status_code != 200:
flash("Failed to retrieve access token from Discord.")
return redirect(url_for("home"))
access_token = response.json().get("access_token")
if not access_token:
flash("Access token missing in the response.")
return redirect(url_for("home"))
# Store access token in session for later use
session["access_token"] = access_token
# Fetch user info
user_data = requests.get(
f"{DISCORD_API_BASE_URL}/users/@me",
headers={"Authorization": f"Bearer {access_token}"},
).json()
# Store user information in session
session["user"] = user_data
# Fetch guilds the user is in
guilds_response = requests.get(
f"{DISCORD_API_BASE_URL}/users/@me/guilds",
headers={"Authorization": f"Bearer {access_token}"},
)
if guilds_response.status_code == 200:
guilds = guilds_response.json() # Store guilds in a variable
session["guilds"] = guilds # Store guilds in session
# Fetch member count and permissions for each guild
for guild in guilds:
guild_id = guild["id"]
guild_info_response = requests.get(
f"{DISCORD_API_BASE_URL}/guilds/{guild_id}",
headers={"Authorization": f"Bearer {access_token}"},
)
if guild_info_response.status_code == 200:
guild_info = guild_info_response.json()
guild["approx_member_count"] = guild_info.get("member_count", "N/A")
guild["permissions"] = guild_info.get(
"permissions", 0
) # Store permissions
else:
guild["approx_member_count"] = "N/A" # Fallback if unable to fetch
# Filter guilds where user can add bots
guilds_with_bot_permission = [guild for guild in guilds if can_add_bot(guild)]
session["guilds_with_bot_permission"] = guilds_with_bot_permission
else:
flash("Failed to retrieve guilds from Discord.")
return redirect(url_for("home"))
# Logout route
@app.route("/logout")
def logout():
session.pop("user", None)
session.pop("guilds", None)
session.pop("access_token", None) # Ensure access token is also cleared
session.pop("guilds_with_bot_permission", None)
flash("You have been logged out.")
return redirect(url_for("home"))
@app.route("/main")
def main_page():
return render_template("main.html")
# Update home route to display user info
@app.route("/")
def home():
user = session.get("user")
if not user:
return redirect(
url_for("main_page")
) # Redirect to the main page if not logged in
guilds_with_permission = session.get("guilds_with_bot_permission", [])
user_info = {
"id": user.get("id", "N/A"),
"username": user.get("username", "Unknown"),
"discriminator": user.get("discriminator", "0000"),
"avatar": user.get("avatar", None),
"servers": len(guilds_with_permission),
}
return render_template(
"home.html", user=user_info, stats=user_info, guilds=guilds_with_permission
)
def get_user_balance(user_id):
result = db.fetch_one("SELECT BANK, WALLET FROM economy WHERE ID = %s", (user_id,))
print(result)
bank_balance = result.get("BANK", 0) if result else 0
wallet_balance = result.get("WALLET", 0) if result else 0
return {
"bank": bank_balance,
"wallet": wallet_balance,
}
@app.route("/wallet")
def wallet():
user = session.get("user")
if not user:
flash("You are not logged in.")
return redirect(url_for("login"))
user_balance = get_user_balance(user["id"])
return render_template("wallet.html", user=user, balance=user_balance)
def get_user_transactions(user_id, sort_by="date", order="asc"):
valid_sort_fields = {
"date": "TIME",
"amount": "amount",
}
sort_column = valid_sort_fields.get(sort_by, "TIME")
sort_order = "ASC" if order == "asc" else "DESC"
query = f"SELECT * FROM transactions WHERE USERID = %s ORDER BY {sort_column} {sort_order}"
transactions = db.fetch_all(query, (user_id,))
return transactions if transactions else []
@app.route("/transactions")
def transactions():
user = session.get("user")
if not user:
flash("You are not logged in.")
return redirect(url_for("login"))
sort_by = request.args.get("sort", "date")
order = request.args.get("order", "asc")
user_transactions = get_user_transactions(str(user["id"]), sort_by, order)
daily_totals = defaultdict(float)
for transaction in user_transactions:
time_value = transaction["TIME"]
if isinstance(time_value, str):
try:
time_value = datetime.datetime.fromisoformat(time_value)
except Exception:
try:
time_value = datetime.datetime.strptime(
time_value, "%Y-%m-%d %H:%M:%S"
)
except Exception:
continue # skip if can't parse
date = time_value.date()
amount = transaction["amount"]
daily_totals[date] += float(amount)
dates = list(daily_totals.keys())
totals = list(daily_totals.values())
return render_template(
"transactions.html",
user=user,
transactions=user_transactions,
dates=dates,
totals=totals,
sort_by=sort_by,
order=order,
)
@app.route("/add_command", methods=["GET", "POST"])
def add_command():
user = session.get("user")
if not user:
flash("You are not logged in.")
return redirect(url_for("login"))
if request.method == "POST":
guild_id = request.form.get("guild_id")
command_name = request.form.get("command_name")
response_text = request.form.get("response")
# Save command to the database
db.execute_query(
"INSERT INTO custom_commands (GUILDID, COMMANDNAME, RESPONSE) VALUES (%s, %s, %s)",
(guild_id, command_name, response_text),
)
flash("Custom command created successfully!")
return redirect(url_for("home"))
return render_template("add_command.html")
@app.route("/commands")
def list_commands():
user = session.get("user")
if not user:
flash("You are not logged in.")
return redirect(url_for("login"))
guild_id = request.args.get("guild_id")
commands = []
if guild_id:
commands = db.fetch_all(
"SELECT * FROM custom_commands WHERE GUILDID = %s", (guild_id,)
)
return render_template("list_commands.html", commands=commands)
@app.route("/delete_command/<int:command_id>", methods=["POST"])
def delete_command(command_id):
user = session.get("user")
if not user:
flash("You are not logged in.")
return redirect(url_for("login"))
db.execute_query("DELETE FROM custom_commands WHERE ID = %s", (command_id,))
flash("Custom command deleted successfully!")
return redirect(url_for("list_commands"))
@app.route("/guild/<guild_id>/settings", methods=["GET", "POST"])
def guild_settings(guild_id):
user = session.get("user")
if not user:
flash("You are not logged in.")
return redirect(url_for("login"))
bot_headers = {"Authorization": f"Bot {DISCORD_BOT_TOKEN}"}
guild_info_response = requests.get(
f"{DISCORD_API_BASE_URL}/guilds/{guild_id}?with_counts=true",
headers=bot_headers,
)
if guild_info_response.status_code != 200:
flash("Failed to retrieve guild information (bot may not be in this guild).")
return redirect(url_for("home"))
guild_info = guild_info_response.json()
owner_id = guild_info.get("owner_id", "N/A")
member_count = guild_info.get("approximate_member_count", "N/A")
# Fetch owner's username using the bot token
owner_name = "Unknown"
if owner_id != "N/A":
owner_response = requests.get(
f"{DISCORD_API_BASE_URL}/users/{owner_id}",
headers=bot_headers,
)
if owner_response.status_code == 200:
owner_data = owner_response.json()
owner_name = f"{owner_data.get('username', 'Unknown')}#{owner_data.get('discriminator', '0000')}"
else:
owner_name = owner_id # fallback to ID if fetch fails
json_formatted_str = json.dumps(guild_info, indent=2)
print(json_formatted_str)
return render_template(
"guild_settings.html",
user=user,
guild=guild_info,
owner_name=owner_name,
member_count=member_count,
)
@app.route("/profile")
def profile():
user = session.get("user")
if not user:
flash("Please log in to view your profile.")
return redirect(url_for("login"))
# Example: Fetch more user data if needed
# user_data = db.fetch_one("SELECT ... FROM ... WHERE ID = %s", (user["id"],))
return render_template("profile.html", user=user)
if __name__ == "__main__":
app.run(debug=True, port=5000, host="0.0.0.0")