main.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. import os
  2. from dotenv import load_dotenv
  3. import discord
  4. from discord.ext import commands
  5. from discord.commands import Option
  6. from discord.commands import slash_command
  7. from datetime import datetime, time
  8. import configparser
  9. import mysql.connector
  10. import asyncio
  11. import json
  12. from flask import Flask, request, jsonify
  13. from pathlib import Path
  14. intents = discord.Intents.default()
  15. intents.message_content = True
  16. intents.members = True
  17. intents.guilds = True
  18. intents.reactions = True
  19. client = discord.Client(intents=intents)
  20. #---------------------------------#
  21. #Load .env file
  22. load_dotenv()
  23. token = os.getenv("TOKEN")
  24. if token is None:
  25. raise ValueError("TOKEN not found in .env file")
  26. debug_guilds_up = []
  27. server_token = os.getenv("SERVER").split(",")
  28. for i in range(len(server_token)):
  29. debug_guilds_up.append(int(server_token[i]))
  30. dbhost = os.getenv("HOST")
  31. if dbhost is None:
  32. raise ValueError("HOST not found in .env file")
  33. dbname = os.getenv("NAME")
  34. if dbname is None:
  35. raise ValueError("NAME not found in .env file")
  36. dbpsswd = os.getenv("PASSWORD")
  37. if dbpsswd is None:
  38. raise ValueError("PASSWORD not found in .env file")
  39. dbdb = os.getenv("DATABASE")
  40. if dbdb is None:
  41. raise ValueError("DATABASE not found in .env file")
  42. API_KEY = os.getenv("API_KEY")
  43. if API_KEY is None:
  44. raise ValueError("API_KEY not found in .env file")
  45. #---------------------------------#
  46. #ConfigParser
  47. config = configparser.RawConfigParser()
  48. configFilePath = r'config.cfg'
  49. config.read_file(open(configFilePath))
  50. label_rules = config.get('Reactionroles Rules', 'label_rules')
  51. roles_rules = config.get('Reactionroles Rules', 'rules_roles').split(",")
  52. roles_rules = [role.strip() for role in roles_rules if role.strip()]
  53. channel_status_log = config.get('Logs', 'status_log')
  54. channel_mod_log = config.get('Logs', 'mod_log')
  55. team_role_id = config.get('Team Roles', 'team_role_id')
  56. #---------------------------------#
  57. #Database initialization
  58. conn = mysql.connector.connect(
  59. host=dbhost,
  60. user=dbname,
  61. password=dbpsswd,
  62. charset='utf8mb4',
  63. collation='utf8mb4_unicode_ci'
  64. )
  65. cursor = conn.cursor()
  66. conn.database = dbdb
  67. cursor.execute("""
  68. CREATE TABLE IF NOT EXISTS User (
  69. userid BIGINT UNIQUE PRIMARY KEY,
  70. discordname VARCHAR(100),
  71. rolesnumber INT,
  72. Roles TEXT
  73. )
  74. """)
  75. cursor.execute("""
  76. CREATE TABLE IF NOT EXISTS Team (
  77. userid BIGINT UNIQUE PRIMARY KEY,
  78. discordname VARCHAR(100),
  79. Roles TEXT,
  80. Permissions TEXT
  81. )
  82. """)
  83. cursor.execute("""
  84. CREATE TABLE IF NOT EXISTS Warns (
  85. id INT AUTO_INCREMENT PRIMARY KEY,
  86. userid BIGINT,
  87. username VARCHAR(100),
  88. moderatorname VARCHAR(100),
  89. reason VARCHAR(250),
  90. date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  91. )
  92. """)
  93. cursor.execute("""
  94. CREATE TABLE IF NOT EXISTS Bans (
  95. id INT AUTO_INCREMENT PRIMARY KEY,
  96. userid BIGINT,
  97. username VARCHAR(100),
  98. moderatorname VARCHAR(100),
  99. reason VARCHAR(250),
  100. date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  101. )
  102. """)
  103. cursor.execute("""
  104. CREATE TABLE IF NOT EXISTS Unbans (
  105. id INT AUTO_INCREMENT PRIMARY KEY,
  106. userid BIGINT,
  107. username VARCHAR(100),
  108. moderatorname VARCHAR(100),
  109. reason VARCHAR(250),
  110. date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  111. )
  112. """
  113. )
  114. cursor.execute("""
  115. CREATE TABLE IF NOT EXISTS Kick (
  116. id INT AUTO_INCREMENT PRIMARY KEY,
  117. userid BIGINT,
  118. username VARCHAR(100),
  119. moderatorname VARCHAR(100),
  120. reason VARCHAR(250),
  121. date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  122. )
  123. """)
  124. #---------------------------------#
  125. #Initialize Bot
  126. bot = commands.Bot(
  127. command_prefix=commands.when_mentioned_or("!"),
  128. description="VicePD Bot",
  129. intents=intents,
  130. debug_guilds=debug_guilds_up if debug_guilds_up else None
  131. )
  132. #Loading Cogs
  133. def load_extensions():
  134. cogs_dir = "./cogs"
  135. if not os.path.exists(cogs_dir):
  136. print(f"Cogs directory '{cogs_dir}' not found!")
  137. return
  138. for filename in os.listdir(cogs_dir):
  139. if filename.endswith(".py"):
  140. cog_list = os.path.splitext(filename)[0]
  141. try:
  142. bot.load_extension(f"cogs.{cog_list}")
  143. print(f"Loaded cog: {cog_list}")
  144. except Exception as e:
  145. print(f"Failed to load cog {cog_list}: {e}")
  146. class Admin(commands.Cog):
  147. def __init__(self, bot):
  148. self.bot = bot
  149. #---------------------------------#
  150. #Print in Log if error occurs
  151. @bot.event
  152. async def on_application_command_error(ctx, error):
  153. print(f"[!] Error in command {ctx.command}: {error}")
  154. if ctx.guild is None:
  155. return
  156. channel = discord.utils.get(ctx.guild.channels, id=int(channel_status_log))
  157. if channel:
  158. await channel.send(f"Error occurred: {str(error)}")
  159. #---------------------------------#
  160. #Bot Online Console
  161. @bot.event
  162. async def on_ready():
  163. print("------------------------")
  164. print(f"{bot.user} is online")
  165. print("------------------------")
  166. if bot.guilds:
  167. channel = discord.utils.get(bot.guilds[0].channels, id=int(channel_status_log))
  168. if channel:
  169. await channel.send(f"{bot.user} is online")
  170. bot.add_view(PersistentRoleView()) #loading reactionrole memory
  171. print("Registrierte Slash-Commands:")
  172. command_list = "\n".join([f"- /{command.name}" for command in bot.pending_application_commands])
  173. for command in bot.pending_application_commands:
  174. print(f" - {command.name}")
  175. if channel and command_list:
  176. await channel.send(f"Registered Slash-Commands:\n{command_list}")
  177. bot.loop.create_task(update_users_periodically())
  178. #---------------------------------------------------------------------------------------#
  179. #DONT Touch anything above this line, unless you know what you are doing!#
  180. #---------------------------------------------------------------------------------------#
  181. #_________________________________#
  182. #BAN SYSTEM
  183. #---------------------------------#
  184. ##Ban
  185. @bot.slash_command(name="ban", description="Ban a user from this Server")
  186. async def ban(
  187. ctx,
  188. user: Option(discord.User, description = "Select User", required=True), # type: ignore
  189. reason: Option(str, description = "Reason for the ban", default="No reason provided") # type: ignore
  190. ):
  191. if not ctx.author.guild_permissions.ban_members:
  192. await ctx.respond("Error: You don't have the permission to ban Members!", ephemeral=True)
  193. return
  194. if user == bot.user:
  195. await ctx.respond("Error: I can't ban myself!", ephemeral=True)
  196. return
  197. if user == ctx.author:
  198. await ctx.respond("Error: You can't ban yourself!", ephemeral=True)
  199. return
  200. channel= discord.utils.get(ctx.guild.channels, id = int(channel_mod_log))
  201. embed = discord.Embed(
  202. title=f"Ban of **{user.name}**",
  203. description=f"User {user.mention} has been banned from the Server",
  204. color=discord.Color.red()
  205. )
  206. time = discord.utils.format_dt(datetime.now(), "f")
  207. embed.add_field(name="Ban Date", value=time, inline=False)
  208. embed.add_field(name="Moderator", value=f"{ctx.author}", inline=False)
  209. embed.add_field(name="Reason", value=reason, inline=False)
  210. embed.add_field(name="User ID", value=user.id)
  211. embed.set_thumbnail(url=user.display_avatar.url)
  212. embed.set_author(name="VicePD", icon_url="https://i.imgur.com/6QteFrg.png")
  213. embed.set_footer(text="VicePD - Bot | Made by BaumSplitter41")
  214. embed_dm = discord.Embed(
  215. title=f"You have been banned from {ctx.guild.name}",
  216. description=f"Reason: {reason}\n\nIf you believe this was a mistake, please contact the moderators.",
  217. color=discord.Color.red()
  218. )
  219. embed_dm.add_field(name="Ban Date", value=time, inline=False)
  220. embed_dm.set_author(name="VicePD", icon_url="https://i.imgur.com/6QteFrg.png")
  221. embed_dm.set_footer(text="VicePD - Bot | Made by BaumSplitter41")
  222. try:
  223. await user.send(embed=embed_dm)
  224. await ctx.guild.ban(user, reason=reason)
  225. await ctx.respond(f"User {user.mention} has been banned from this Server!", ephemeral=True)
  226. await channel.send(embed=embed)
  227. cursor.execute(
  228. "INSERT INTO Bans (userid, username, moderatorname, reason) VALUES (%s, %s, %s, %s)",
  229. (user.id, str(user), str(ctx.author), reason)
  230. )
  231. conn.commit()
  232. except discord.Forbidden:
  233. await ctx.respond("Error: I don't have permission to ban this user.", ephemeral=True)
  234. except discord.HTTPException as e:
  235. await ctx.respond(f"Error: Could not ban User {user.mention}. Reason: {e}", ephemeral=True)
  236. except Exception as e:
  237. await ctx.respond(f"Unexpected error: {e}", ephemeral=True)
  238. #---------------------------------#
  239. #Unban
  240. @bot.slash_command(name="unban", description="Unban a user from this Server")
  241. async def unban(
  242. ctx,
  243. user: Option(discord.User, description = "Insert User ID", required=True), # type: ignore
  244. reason: Option(str, description = "Reason for the unbanning", default="No reason provided") # type: ignore
  245. ):
  246. if not ctx.author.guild_permissions.ban_members:
  247. await ctx.respond("Error: You don't have the permission to unban Members!", ephemeral=True)
  248. return
  249. if user == bot.user:
  250. await ctx.respond("Error: I can't unban myself!", ephemeral=True)
  251. return
  252. if user == ctx.author:
  253. await ctx.respond("Error: You can't unban yourself!", ephemeral=True)
  254. return
  255. if user in ctx.guild.members:
  256. await ctx.respond("Error: This user is not banned!", ephemeral=True)
  257. return
  258. channel= discord.utils.get(ctx.guild.channels, id = int(channel_mod_log))
  259. embed = discord.Embed(
  260. title=f"Unban of **{user.name}**",
  261. description=f"User {user.mention} was unbanned from this server.",
  262. color=discord.Color.green()
  263. )
  264. time = discord.utils.format_dt(datetime.now(), "f")
  265. embed.add_field(name="Unban Date", value=time, inline=False)
  266. embed.add_field(name="Moderator", value=f"{ctx.author}", inline=False)
  267. embed.add_field(name="Reason", value=reason, inline=False)
  268. embed.add_field(name="User ID", value=user.id)
  269. embed.set_thumbnail(url=user.display_avatar.url)
  270. embed.set_author(name="VicePD", icon_url="https://i.imgur.com/6QteFrg.png")
  271. embed.set_footer(text="VicePD - Bot | Made by BaumSplitter41")
  272. try:
  273. await ctx.guild.unban(user, reason=reason)
  274. await ctx.respond(f"User {user.mention} is now unbanned!", ephemeral=True)
  275. await channel.send(embed=embed)
  276. cursor.execute(
  277. "INSERT INTO Unbans (userid, username, moderatorname, reason) VALUES (%s, %s, %s, %s)",
  278. (user.id, str(user), str(ctx.author), reason)
  279. )
  280. conn.commit()
  281. except discord.Forbidden:
  282. await ctx.respond("Error: I don't have permission to unban this user.", ephemeral=True)
  283. except discord.HTTPException as e:
  284. await ctx.respond(f"Error: Could not unban User {user.mention}. Reason: {e}", ephemeral=True)
  285. except Exception as e:
  286. await ctx.respond(f"Unexpected error: {e}", ephemeral=True)
  287. #---------------------------------#
  288. #_________________________________#
  289. #---------------------------------#
  290. #Kick
  291. @bot.slash_command(name="kick", description="Kick a user from this Server")
  292. async def kick(
  293. ctx,
  294. user: Option(discord.User, description = "Select User", required=True), # type: ignore
  295. reason: Option(str, description = "Reason for the ban", default="No reason provided") # type: ignore
  296. ):
  297. if not ctx.author.guild_permissions.kick_members:
  298. await ctx.respond("Error: You don't have the permission to kick Members!", ephemeral=True)
  299. return
  300. if user == bot.user:
  301. await ctx.respond("Error: I can't kick myself!", ephemeral=True)
  302. return
  303. if user == ctx.author:
  304. await ctx.respond("Error: You can't kick yourself!", ephemeral=True)
  305. return
  306. channel= discord.utils.get(ctx.guild.channels, id = int(channel_mod_log))
  307. embed = discord.Embed(
  308. title=f"Kick of **{user.name}**",
  309. description=f"User {user.mention} has been kicked from the Server",
  310. color=discord.Color.red()
  311. )
  312. time = discord.utils.format_dt(datetime.now(), "f")
  313. embed.add_field(name="Kick Date", value=time, inline=False)
  314. embed.add_field(name="Moderator", value=f"{ctx.author}", inline=False)
  315. embed.add_field(name="Reason", value=reason, inline=False)
  316. embed.add_field(name="User ID", value=user.id)
  317. embed.set_thumbnail(url=user.display_avatar.url)
  318. embed.set_author(name="VicePD", icon_url="https://i.imgur.com/6QteFrg.png")
  319. embed.set_footer(text="VicePD - Bot | Made by BaumSplitter41")
  320. #DM to user
  321. embed_dm = discord.Embed(
  322. title=f"You have been kicked from {ctx.guild.name}",
  323. description=f"Reason: {reason}\n\nIf you believe this was a mistake, please contact the moderators.",
  324. color=discord.Color.red()
  325. )
  326. embed_dm.add_field(name="Kick Date", value=time, inline=False)
  327. embed_dm.set_author(name="VicePD", icon_url="https://i.imgur.com/6QteFrg.png")
  328. embed_dm.set_footer(text="VicePD - Bot | Made by BaumSplitter41")
  329. try:
  330. await user.send(embed=embed_dm)
  331. await ctx.guild.kick(user, reason=reason)
  332. await ctx.respond(f"User {user.mention} has been kicked from this Server!", ephemeral=True)
  333. cursor.execute(
  334. "INSERT INTO Kick (userid, username, moderatorname, reason) VALUES (%s, %s, %s, %s)",
  335. (int(user.id), str(user), str(ctx.author), reason)
  336. )
  337. conn.commit()
  338. await channel.send(embed=embed)
  339. except discord.Forbidden:
  340. await ctx.respond("Error: I don't have permission to kick this user.", ephemeral=True)
  341. except discord.HTTPException as e:
  342. await ctx.respond(f"Error: Could not kick User {user.mention}. Reason: {e}", ephemeral=True)
  343. except Exception as e:
  344. await ctx.respond(f"Unexpected error: {e}", ephemeral=True)
  345. #---------------------------------#
  346. #---------------------------------#
  347. #Warn
  348. @bot.slash_command(name="warn", description="Warn a user from this Server")
  349. async def warn(
  350. ctx,
  351. user: Option(discord.User, required=True), # type: ignore
  352. reason: Option(str, default="No reason provided") # type: ignore
  353. ):
  354. await ctx.defer(ephemeral=True)
  355. if not ctx.author.guild_permissions.kick_members:
  356. await ctx.followup.send("No permission.", ephemeral=True)
  357. return
  358. if user in (bot.user, ctx.author):
  359. await ctx.followup.send("Invalid target.", ephemeral=True)
  360. return
  361. channel= discord.utils.get(ctx.guild.channels, id = int(channel_mod_log))
  362. embed = discord.Embed(
  363. title=f"Warn of **{user.name}**",
  364. description=f"User {user.mention} has been warned.",
  365. color=discord.Color.red()
  366. )
  367. time = discord.utils.format_dt(datetime.now(), "f")
  368. embed.add_field(name="Warn Date", value=time, inline=False)
  369. embed.add_field(name="Moderator", value=f"{ctx.author}", inline=False)
  370. embed.add_field(name="Reason", value=reason, inline=False)
  371. embed.add_field(name="User ID", value=user.id)
  372. embed.set_thumbnail(url=user.display_avatar.url)
  373. embed.set_author(name="VicePD", icon_url="https://i.imgur.com/6QteFrg.png")
  374. embed.set_footer(text="VicePD - Bot | Made by BaumSplitter41")
  375. #DM to user
  376. embed_dm = discord.Embed(
  377. title=f"You have been warned on {ctx.guild.name}",
  378. description=f"Reason: {reason}\n\nIf you believe this was a mistake, please contact the moderators.",
  379. color=discord.Color.red()
  380. )
  381. embed_dm.add_field(name="Warn Date", value=time, inline=False)
  382. embed_dm.set_author(name="VicePD", icon_url="https://i.imgur.com/6QteFrg.png")
  383. embed_dm.set_footer(text="VicePD - Bot | Made by BaumSplitter41")
  384. try:
  385. await user.send(embed=embed_dm)
  386. except discord.Forbidden:
  387. await ctx.respond("Error: I can't send a DM to this user. The user was warned without a information.", ephemeral=True)
  388. pass # User has DMs closed or blocked the bot
  389. cursor.execute(
  390. "INSERT INTO Warns (userid, username, moderatorname, reason) VALUES (%s, %s, %s, %s)",
  391. (user.id, str(user), str(ctx.author), reason)
  392. )
  393. conn.commit()
  394. await channel.send(embed=embed)
  395. await ctx.followup.send(
  396. f"User {user.mention} has been warned for: {reason}",
  397. ephemeral=True
  398. )
  399. #---------------------------------#
  400. #Modinfo
  401. @bot.slash_command(name="modinfo", description="Shows the moderative history of a user from this Server")
  402. async def modinfo(
  403. ctx,
  404. user: Option(discord.User, required=True) # type: ignore
  405. ):
  406. await ctx.defer(ephemeral=False)
  407. if not ctx.author.guild_permissions.kick_members:
  408. await ctx.followup.send("No permission.", ephemeral=True)
  409. return
  410. embed = discord.Embed(
  411. title=f"__Moderation History for {user.name}__",
  412. color=discord.Color.orange()
  413. )
  414. # Collect all events with timestamps
  415. events = []
  416. cursor.execute("SELECT moderatorname, reason, date FROM Warns WHERE userid = %s", (user.id,))
  417. for moderatorname, reason, date in cursor.fetchall():
  418. events.append(("Warned", moderatorname, reason, date))
  419. cursor.execute("SELECT moderatorname, reason, date FROM Kick WHERE userid = %s", (user.id,))
  420. for moderatorname, reason, date in cursor.fetchall():
  421. events.append(("Kicked", moderatorname, reason, date))
  422. cursor.execute("SELECT moderatorname, reason, date FROM Bans WHERE userid = %s", (user.id,))
  423. for moderatorname, reason, date in cursor.fetchall():
  424. events.append(("Banned", moderatorname, reason, date))
  425. cursor.execute("SELECT moderatorname, reason, date FROM Unbans WHERE userid = %s", (user.id,))
  426. for moderatorname, reason, date in cursor.fetchall():
  427. events.append(("Unbanned", moderatorname, reason, date))
  428. if not events:
  429. await ctx.followup.send(f"User `{user.name}` has no moderation history.", ephemeral=True)
  430. return
  431. # Sort chronologically: oldest -> newest
  432. events.sort(key=lambda e: e[3])
  433. # Add fields in chronological order
  434. for action, moderatorname, reason, date in events:
  435. embed.add_field(
  436. name=f"{action} by {moderatorname} on {date.strftime('%Y-%m-%d %H:%M:%S')}",
  437. value=f"Reason: {reason}",
  438. inline=False
  439. )
  440. embed.set_thumbnail(url=user.display_avatar.url)
  441. embed.set_author(name="VicePD", icon_url="https://i.imgur.com/6QteFrg.png")
  442. embed.set_footer(text="VicePD - Bot | Made by BaumSplitter41")
  443. await ctx.followup.send(embed=embed, ephemeral=False)
  444. #_________________________________#
  445. ## Reaction role system
  446. #---------------------------------#
  447. #reaction role verfiy
  448. class PersistentRoleView(discord.ui.View):
  449. def __init__(self):
  450. super().__init__(timeout=None)
  451. @discord.ui.button(
  452. label=label_rules,
  453. style=discord.ButtonStyle.success,
  454. emoji="✅",
  455. custom_id="persistent_view:role_verify"
  456. )
  457. async def verify_callback(self, button: discord.ui.Button, interaction: discord.Interaction):
  458. role_objs = []
  459. for role_id in roles_rules:
  460. try:
  461. role_obj = interaction.guild.get_role(int(role_id))
  462. if role_obj:
  463. role_objs.append(role_obj)
  464. except Exception:
  465. continue
  466. if not role_objs:
  467. await interaction.response.send_message("Error: No valid roles found", ephemeral=True)
  468. return
  469. removed_roles = []
  470. added_roles = []
  471. for role in role_objs:
  472. if role in interaction.user.roles:
  473. await interaction.user.remove_roles(role)
  474. removed_roles.append(role.name)
  475. else:
  476. await interaction.user.add_roles(role)
  477. added_roles.append(role.name)
  478. msg = ""
  479. if removed_roles:
  480. msg += f"Folgende Rollen wurden entfernt: {', '.join(removed_roles)}.\n"
  481. if added_roles:
  482. msg += f"Du hast folgende Rollen erhalten: {', '.join(added_roles)}."
  483. if msg == "":
  484. msg = "Keine Rollen wurden geändert."
  485. await interaction.response.send_message(msg, ephemeral=True)
  486. #Setup the reaction role message
  487. @bot.slash_command(name="verify_message", description="Send the reactionrole message | This is for setup only!")
  488. async def setup_rr(
  489. ctx: discord.ApplicationContext,
  490. channel: discord.TextChannel,
  491. ):
  492. if not ctx.author.guild_permissions.administrator:
  493. await ctx.respond("You dont have the permissions to do that..", ephemeral=True)
  494. return
  495. json_path = Path(__file__).resolve().parent.joinpath("json_files", "verify_text.json")
  496. if not json_path.exists():
  497. await ctx.respond("The .json file is missing.")
  498. return
  499. try:
  500. with json_path.open("r", encoding="utf-8") as f:
  501. json_data = json.load(f)
  502. except json.JSONDecodeError:
  503. await ctx.respond("The .json file is not valid JSON.")
  504. return
  505. if isinstance(json_data, dict):
  506. entries = [json_data]
  507. elif isinstance(json_data, list):
  508. entries = json_data
  509. else:
  510. await ctx.respond("The .json file has an unexpected structure.")
  511. return
  512. if not entries or not isinstance(entries[0], dict):
  513. await ctx.respond("The .json file has an unexpected structure.")
  514. return
  515. if not entries:
  516. await ctx.respond("The .json file is empty.")
  517. return
  518. entry = entries[0]
  519. jstitle = entry.get("title", "Verify")
  520. jsdesc = entry.get("desc", "No description provided.")
  521. embed = discord.Embed(
  522. title=jstitle,
  523. description=jsdesc,
  524. color=discord.Color.red()
  525. )
  526. embed.set_image(url="https://i.imgur.com/FoF791J.png")
  527. try:
  528. await channel.send(embed=embed, view=PersistentRoleView())
  529. await ctx.respond(f"Message was succesfully sent in {channel.mention}!", ephemeral=True)
  530. except discord.Forbidden:
  531. await ctx.respond("I dont have permissions to write in this channel", ephemeral=True)
  532. #---------------------------------#
  533. #_________________________________#
  534. #--------------------------------#
  535. #Get all Users in Database periodically
  536. async def update_users_periodically():
  537. await bot.wait_until_ready()
  538. while not bot.is_closed():
  539. try:
  540. for guild in bot.guilds:
  541. batch_count = 0
  542. async for member in guild.fetch_members(limit=None):
  543. role_ids_string = ",".join([str(role.id) for role in member.roles])
  544. cursor.execute(
  545. """INSERT INTO User (userid, discordname, rolesnumber, roles)
  546. VALUES (%s, %s, %s, %s)
  547. ON DUPLICATE KEY UPDATE discordname=%s, rolesnumber=%s, roles=%s""",
  548. (member.id, str(member), len(member.roles), role_ids_string,
  549. str(member), len(member.roles), role_ids_string)
  550. )
  551. batch_count += 1
  552. if batch_count >= 100:
  553. conn.commit()
  554. batch_count = 0
  555. if batch_count > 0:
  556. conn.commit()
  557. if team_role_id:
  558. for guild in bot.guilds:
  559. team_role = guild.get_role(int(team_role_id))
  560. if team_role is None:
  561. continue
  562. batch_count = 0
  563. async for member in guild.fetch_members(limit=None):
  564. if team_role in member.roles:
  565. role_ids_string = ",".join([str(role.id) for role in member.roles])
  566. cursor.execute(
  567. """INSERT INTO Team (userid, discordname, Roles)
  568. VALUES (%s, %s, %s)
  569. ON DUPLICATE KEY UPDATE discordname=%s, Roles=%s""",
  570. (member.id, str(member), role_ids_string,
  571. str(member), role_ids_string)
  572. )
  573. batch_count += 1
  574. if batch_count >= 100:
  575. conn.commit()
  576. batch_count = 0
  577. if batch_count > 0:
  578. conn.commit()
  579. except Exception as e:
  580. print(f"[!] Fehler beim Update der User: {e}")
  581. await asyncio.sleep(60) # Update every minute
  582. #_________________________________#
  583. #---------------------------------#
  584. #Run function
  585. load_extensions()
  586. bot.run(token)
  587. #---------------------------------#