main.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  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
  8. import configparser
  9. import mysql.connector
  10. intents = discord.Intents.default()
  11. intents.message_content = True
  12. intents.members = True
  13. intents.guilds = True
  14. intents.reactions = True
  15. client = discord.Client(intents=intents)
  16. #------#
  17. #Load .env file
  18. load_dotenv()
  19. token = os.getenv("TOKEN")
  20. if token is None:
  21. raise ValueError("TOKEN not found in .env file")
  22. debug_guilds_up = []
  23. server_token = os.getenv("SERVER").split(",")
  24. for i in range(len(server_token)):
  25. debug_guilds_up.append(int(server_token[i]))
  26. dbhost = os.getenv("HOST")
  27. if token is None:
  28. raise ValueError("HOST not found in .env file")
  29. dbname = os.getenv("NAME")
  30. if token is None:
  31. raise ValueError("NAME not found in .env file")
  32. dbpsswd = os.getenv("PASSWORD")
  33. if token is None:
  34. raise ValueError("PASSWORD not found in .env file")
  35. dbdb = os.getenv("DATABASE")
  36. if token is None:
  37. raise ValueError("DATABASE not found in .env file")
  38. #------#
  39. #ConfigParser
  40. config = configparser.RawConfigParser()
  41. configFilePath = r'config.cfg'
  42. config.read_file(open(configFilePath))
  43. label_rules = config.get('Reactionroles Rules', 'label_rules')
  44. role_rules = config.get('Reactionroles Rules', 'rules_role')
  45. channel_log = config.get('Logs', 'channel_log')
  46. channel_banlog = config.get('Logs', 'ban_log')
  47. #------#
  48. #SQL initialization
  49. conn = mysql.connector.connect(
  50. host=dbhost,
  51. user=dbname,
  52. password=dbpsswd
  53. )
  54. cursor = conn.cursor()
  55. conn.database = dbdb
  56. cursor.execute("""
  57. CREATE TABLE IF NOT EXISTS User (
  58. id INT AUTO_INCREMENT PRIMARY KEY,
  59. discordid INT,
  60. discordname VARCHAR(100),
  61. roles INT
  62. )
  63. """)
  64. cursor.execute("""
  65. CREATE TABLE IF NOT EXISTS Warns (
  66. id INT AUTO_INCREMENT PRIMARY KEY,
  67. userid INT,
  68. username VARCHAR(100),
  69. moderatorname VARCHAR(100),
  70. reason VARCHAR(250),
  71. date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  72. )
  73. """)
  74. #------#
  75. #Initialize Bot
  76. bot = commands.Bot(
  77. command_prefix=commands.when_mentioned_or("!"),
  78. description="VicePD Bot",
  79. intents=intents,
  80. debug_guilds=debug_guilds_up if debug_guilds_up else None
  81. )
  82. async def load_extensions():
  83. for filename in os.listdir("cogs"):
  84. if filename.endswith(".py"):
  85. bot.load_extension(f"cogs.{filename[:-3]}")
  86. class Admin(commands.Cog):
  87. def __init__(self, bot):
  88. self.bot = bot
  89. #------#
  90. #Print in Log if error occurs
  91. @bot.event
  92. async def on_command_error(ctx, error):
  93. channel = discord.utils.get(bot.guilds[0].channels, id=int(channel_log))
  94. if channel:
  95. await channel.send(f"Error occurred: {str(error)}")
  96. #---------------------------------#
  97. #Bot Online Console
  98. @bot.event
  99. async def on_ready():
  100. print(f"{bot.user} ist online")
  101. if bot.guilds:
  102. channel = discord.utils.get(bot.guilds[0].channels, id=int(channel_log))
  103. if channel:
  104. await channel.send(f"{bot.user} ist online")
  105. await load_extensions()
  106. bot.add_view(PersistentRoleView()) #loading reactionrole memory
  107. #---------------------------------------------------------------------------------------#
  108. #DONT Touch anything above this line, unless you know what you are doing!#
  109. #---------------------------------------------------------------------------------------#
  110. #---------------------------------#
  111. ## Greet
  112. @bot.slash_command(description="Greet a User")
  113. async def greet(ctx, user: str = Option(discord.User, "The user, you want to greet")):
  114. await ctx.respond(f"Hello {user.mention}")
  115. #---------------------------------#
  116. #---------------------------------#
  117. ## Say
  118. @bot.slash_command(description="Let the bot send a message")
  119. async def say(
  120. ctx,
  121. text: str = Option(description="Input the text you want to send"),
  122. channel_input: discord.TextChannel = Option(description="Select the channel,where you want to send the message.")
  123. ):
  124. channel= discord.utils.get(ctx.guild.channels, id = int(channel_input[2:-1]))
  125. await channel.send(text)
  126. await ctx.respond("Message sent", ephemeral=True)
  127. #---------------------------------#
  128. #---------------------------------#
  129. ## Userinfo
  130. @bot.slash_command(name="userinfo", description="Show informations of a user from this server")
  131. async def userinfo(
  132. ctx,
  133. user: str = Option(discord.User, "Select User"),
  134. ):
  135. if user is None:
  136. user = ctx.author
  137. elif user not in ctx.guild.members:
  138. await ctx.respond("The selected user is not a member on this Server!", ephemeral=True)
  139. return
  140. elif user == bot.user:
  141. await ctx.respond(f"This is me - the {bot.user}", ephemeral=True)
  142. return
  143. embed = discord.Embed(
  144. title=f"Information about *{user.name}*",
  145. description=f"Here you see all details about {user.mention}",
  146. color=discord.Color.blue()
  147. )
  148. time = discord.utils.format_dt(user.created_at, "R")
  149. embed.add_field(name="Account creation date", value=time, inline=False)
  150. if len(user.roles) >= 2:
  151. embed.add_field(name="Roles", value=", ".join([role.mention for role in user.roles if role.name != "@everyone"]), inline=False)
  152. else:
  153. embed.add_field(name="Roles", value="User has no roles", inline=False)
  154. embed.add_field(name="Server join date", value=discord.utils.format_dt(user.joined_at, "R"), inline=False)
  155. embed.add_field(name="User ID", value=user.id)
  156. embed.set_thumbnail(url=user.display_avatar.url)
  157. embed.set_author(name="VicePD", icon_url="https://i.imgur.com/6QteFrg.png")
  158. embed.set_footer(text="VicePD - Bot | Made by BaumSplitter41")
  159. await ctx.respond(embed=embed)
  160. #---------------------------------#
  161. #_________________________________#
  162. #BAN SYSTEM
  163. #---------------------------------#
  164. ##Ban
  165. @bot.slash_command(name="ban", description="Ban a user from this Server")
  166. async def ban(
  167. ctx,
  168. user: Option(discord.User, description = "Select User", required=True), # type: ignore
  169. reason: Option(str, description = "Reason for the ban", default="No reason provided") # type: ignore
  170. ):
  171. if not ctx.author.guild_permissions.ban_members:
  172. await ctx.respond("Error: You don't have the permission to ban Members!", ephemeral=True)
  173. return
  174. if user == bot.user:
  175. await ctx.respond("Error: I can't ban myself!", ephemeral=True)
  176. return
  177. if user == ctx.author:
  178. await ctx.respond("Error: You can't ban yourself!", ephemeral=True)
  179. return
  180. channel= discord.utils.get(ctx.guild.channels, id = int(channel_banlog))
  181. embed = discord.Embed(
  182. title=f"Ban of **{user.name}**",
  183. description=f"User {user.mention} has been banned from the Server",
  184. color=discord.Color.red()
  185. )
  186. time = discord.utils.format_dt(datetime.now(), "f")
  187. embed.add_field(name="Ban Date", value=time, inline=False)
  188. embed.add_field(name="Moderator", value=f"{ctx.author}", inline=False)
  189. embed.add_field(name="Reason", value=reason, inline=False)
  190. embed.add_field(name="User ID", value=user.id)
  191. embed.set_thumbnail(url=user.display_avatar.url)
  192. embed.set_author(name="VicePD", icon_url="https://i.imgur.com/6QteFrg.png")
  193. embed.set_footer(text="VicePD - Bot | Made by BaumSplitter41")
  194. try:
  195. await ctx.guild.ban(user, reason=reason)
  196. await ctx.respond(f"User {user.mention} has been banned from this Server!", ephemeral=True)
  197. await channel.send(embed=embed)
  198. except discord.Forbidden:
  199. await ctx.respond("Error: I don't have permission to ban this user.", ephemeral=True)
  200. except discord.HTTPException as e:
  201. await ctx.respond(f"Error: Could not ban User {user.mention}. Reason: {e}", ephemeral=True)
  202. except Exception as e:
  203. await ctx.respond(f"Unexpected error: {e}", ephemeral=True)
  204. #---------------------------------#
  205. #Unban
  206. @bot.slash_command(name="unban", description="Unban a user from this Server")
  207. async def unban(
  208. ctx,
  209. user: Option(discord.User, description = "Insert User ID", required=True), # type: ignore
  210. reason: Option(str, description = "Reason for the unbanning", default="No reason provided") # type: ignore
  211. ):
  212. if not ctx.author.guild_permissions.ban_members:
  213. await ctx.respond("Error: You don't have the permission to unban Members!", ephemeral=True)
  214. return
  215. if user == bot.user:
  216. await ctx.respond("Error: I can't unban myself!", ephemeral=True)
  217. return
  218. if user == ctx.author:
  219. await ctx.respond("Error: You can't unban yourself!", ephemeral=True)
  220. return
  221. if user in ctx.guild.members:
  222. await ctx.respond("Error: This user is not banned!", ephemeral=True)
  223. return
  224. channel= discord.utils.get(ctx.guild.channels, id = int(channel_banlog))
  225. embed = discord.Embed(
  226. title=f"Unban of **{user.name}**",
  227. description=f"User {user.mention} was unbanned from this server.",
  228. color=discord.Color.green()
  229. )
  230. time = discord.utils.format_dt(datetime.now(), "f")
  231. embed.add_field(name="Unban Date", value=time, inline=False)
  232. embed.add_field(name="Moderator", value=f"{ctx.author}", inline=False)
  233. embed.add_field(name="Reason", value=reason, inline=False)
  234. embed.add_field(name="User ID", value=user.id)
  235. embed.set_thumbnail(url=user.display_avatar.url)
  236. embed.set_author(name="VicePD", icon_url="https://i.imgur.com/6QteFrg.png")
  237. embed.set_footer(text="VicePD - Bot | Made by BaumSplitter41")
  238. try:
  239. await ctx.guild.unban(user, reason=reason)
  240. await ctx.respond(f"User {user.mention} is now unbanned!", ephemeral=True)
  241. await channel.send(embed=embed)
  242. except discord.Forbidden:
  243. await ctx.respond("Error: I don't have permission to unban this user.", ephemeral=True)
  244. except discord.HTTPException as e:
  245. await ctx.respond(f"Error: Could not unban User {user.mention}. Reason: {e}", ephemeral=True)
  246. except Exception as e:
  247. await ctx.respond(f"Unexpected error: {e}", ephemeral=True)
  248. #---------------------------------#
  249. #_________________________________#
  250. #---------------------------------#
  251. #Kick
  252. @bot.slash_command(name="kick", description="Kick a user from this Server")
  253. async def kick(
  254. ctx,
  255. user: Option(discord.User, description = "Select User", required=True), # type: ignore
  256. reason: Option(str, description = "Reason for the ban", default="No reason provided") # type: ignore
  257. ):
  258. if not ctx.author.guild_permissions.kick_members:
  259. await ctx.respond("Error: You don't have the permission to kick Members!", ephemeral=True)
  260. return
  261. if user == bot.user:
  262. await ctx.respond("Error: I can't kick myself!", ephemeral=True)
  263. return
  264. if user == ctx.author:
  265. await ctx.respond("Error: You can't kick yourself!", ephemeral=True)
  266. return
  267. try:
  268. await ctx.guild.kick(user, reason=reason)
  269. await ctx.respond(f"User {user.mention} has been kick from this Server!", ephemeral=True)
  270. except discord.Forbidden:
  271. await ctx.respond("Error: I don't have permission to kick this user.", ephemeral=True)
  272. except discord.HTTPException as e:
  273. await ctx.respond(f"Error: Could not kick User {user.mention}. Reason: {e}", ephemeral=True)
  274. except Exception as e:
  275. await ctx.respond(f"Unexpected error: {e}", ephemeral=True)
  276. #---------------------------------#
  277. #---------------------------------#
  278. @bot.slash_command(name="warn", description="Warn a user from this Server")
  279. async def warn(
  280. ctx,
  281. user: Option(discord.User, required=True), # type: ignore
  282. reason: Option(str, default="No reason provided") # type: ignore
  283. ):
  284. await ctx.defer(ephemeral=True)
  285. if not ctx.author.guild_permissions.kick_members:
  286. await ctx.followup.send("No permission.", ephemeral=True)
  287. return
  288. if user in (bot.user, ctx.author):
  289. await ctx.followup.send("Invalid target.", ephemeral=True)
  290. return
  291. cursor.execute(
  292. "INSERT INTO Warns (userid, username, moderatorname, reason) VALUES (%s, %s, %s, %s)",
  293. (user.id, str(user), str(ctx.author), reason)
  294. )
  295. conn.commit()
  296. await ctx.followup.send(
  297. f"User {user.mention} has been warned for: {reason}",
  298. ephemeral=True
  299. )
  300. #_________________________________#
  301. ## Reaction role system
  302. #---------------------------------#
  303. #reaction role verfiy
  304. class PersistentRoleView(discord.ui.View):
  305. def __init__(self):
  306. super().__init__(timeout=None)
  307. @discord.ui.button(
  308. label=label_rules,
  309. style=discord.ButtonStyle.success,
  310. emoji="✅",
  311. custom_id="persistent_view:role_verify"
  312. )
  313. async def verify_callback(self, button: discord.ui.Button, interaction: discord.Interaction):
  314. role = interaction.guild.get_role(int(role_rules))
  315. if role is None:
  316. await interaction.response.send_message("Fehler: Die konfigurierte Rolle wurde nicht gefunden.", ephemeral=True)
  317. return
  318. if role in interaction.user.roles:
  319. await interaction.user.remove_roles(role)
  320. await interaction.response.send_message(f"Rolle **{role.name}** wurde entfernt.", ephemeral=True)
  321. else:
  322. await interaction.user.add_roles(role)
  323. await interaction.response.send_message(f"Du hast die Rolle **{role.name}** erhalten!", ephemeral=True)
  324. @bot.slash_command(name="verify_message", description="Sendet die persistente Reaction-Role Nachricht")
  325. async def setup_rr(
  326. ctx: discord.ApplicationContext,
  327. channel: discord.TextChannel,
  328. title: str,
  329. description: str
  330. ):
  331. if not ctx.author.guild_permissions.administrator:
  332. await ctx.respond("Keine Berechtigung.", ephemeral=True)
  333. return
  334. embed = discord.Embed(
  335. title=title,
  336. description=f"{description}\n\nViel Spass auf dem Server!",
  337. color=discord.Color.red()
  338. )
  339. embed.set_image(url="https://i.imgur.com/FoF791J.png")
  340. try:
  341. await channel.send(embed=embed, view=PersistentRoleView())
  342. await ctx.respond(f"Nachricht erfolgreich in {channel.mention} gesendet!", ephemeral=True)
  343. except discord.Forbidden:
  344. await ctx.respond("Ich darf in diesem Kanal nicht schreiben.", ephemeral=True)
  345. #---------------------------------#
  346. #_________________________________#
  347. #_________________________________#
  348. ## Help System
  349. #---------------------------------#
  350. #How to team
  351. @bot.slash_command(name="how_to_team", description= "Get Infos")
  352. async def how_to_team(
  353. ctx,
  354. ):
  355. server = ctx.guild
  356. embed = discord.Embed(
  357. title=f"__How to join the Team on {server.name}__",
  358. description=f"If you want to join the Serverteam open a ticket in #ticket.",
  359. color=discord.Color.yellow()
  360. )
  361. embed.set_thumbnail(url=server.icon)
  362. embed.set_author(name="VicePD", icon_url="https://i.imgur.com/6QteFrg.png")
  363. embed.set_footer(text="VicePD - Bot | Made by BaumSplitter41")
  364. await ctx.respond(embed=embed, ephemeral=True)
  365. #---------------------------------#
  366. #How to start
  367. @bot.slash_command(name="how_to_start", description= "Get Infos")
  368. async def how_to_start(
  369. ctx,
  370. ):
  371. server = ctx.guild
  372. embed = discord.Embed(
  373. title=f"__How to start__",
  374. description=f"Hallo {ctx.author.mention}, um auf unserem Server spielen zu können, ließ dir zuerst das Regelwerk in in #regelwerk durch. Um einem Department beizutreten wähle in #how-to-start eine Einweisungsrolle aus. Melde dich anschließend für eine Einweisung an. **Wichtig: gehe erst krz vor der Einweisung auf den Server!**",
  375. color=discord.Color.yellow()
  376. )
  377. embed.set_thumbnail(url=server.icon)
  378. embed.set_author(name="VicePD", icon_url="https://i.imgur.com/6QteFrg.png")
  379. embed.set_footer(text="VicePD - Bot | Made by BaumSplitter41")
  380. await ctx.respond(embed=embed, ephemeral=True)
  381. #---------------------------------#
  382. #Help_cache
  383. @bot.slash_command(name="help_cache", description= "Get Infos")
  384. async def help_cache(
  385. ctx,
  386. ):
  387. server = ctx.guild
  388. embed = discord.Embed(
  389. title=f"__How to clear your game cache__",
  390. description=f"Follow the follwing steps to clear your game cache:",
  391. color=discord.Color.yellow()
  392. )
  393. embed.add_field(name="Close Game", value="Close FiveM completely", inline=False)
  394. embed.add_field(name="Press keys", value="Win + R", inline=False)
  395. embed.add_field(name="Go to the folder", value="\Local\FiveM\FiveM.app\data", inline=False)
  396. embed.add_field(name="Delete the folders", value="cache, server-cache, server-cache-priv", inline=False)
  397. embed.add_field(name="Restart Game", value="Restart the game and download the resources again.", inline=False)
  398. embed.set_thumbnail(url=server.icon)
  399. embed.set_author(name="VicePD", icon_url="https://i.imgur.com/6QteFrg.png")
  400. embed.set_footer(text="VicePD - Bot | Made by BaumSplitter41")
  401. await ctx.respond(embed=embed, ephemeral=True)
  402. #---------------------------------#
  403. #_________________________________#
  404. #---------------------------------#
  405. #Run function
  406. bot.run(token)
  407. #---------------------------------#