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. #---------------------------------#