coreCog.py (8559B)
1 # Import dependencies 2 import discord 3 from discord.ext import commands 4 from datetime import timedelta 5 6 # Import modules 7 from .botUtilities import COLORS, CommandError, CountdownNotFound, isCountdown, loadCountdown, getContextCountdown, addMessage 8 9 10 11 class Core(commands.Cog): 12 def __init__(self, bot, db_connection): 13 self.bot = bot 14 self.db_connection = db_connection 15 16 17 18 @commands.Cog.listener() 19 async def on_message(self, obj): 20 # Parse countdown message 21 with self.db_connection.cursor() as cur: 22 if (await addMessage(cur, obj)): 23 self.db_connection.commit() 24 25 26 27 @commands.command() 28 async def activate(self, ctx): 29 """ 30 Turns a channel into a countdown 31 """ 32 33 with self.db_connection.cursor() as cur: 34 # Check if channel is already a countdown 35 if (isCountdown(cur, ctx.channel.id)): 36 raise CommandError("This channel is already a countdown") 37 38 # Check if channel is a DM 39 if (not isinstance(ctx.channel, discord.channel.TextChannel)): 40 raise CommandError("This command must be run inside a server") 41 42 # Check if user isn't authorized 43 if (not ctx.message.author.guild_permissions.administrator): 44 raise CommandError("You must be an administrator to turn a channel into a countdown") 45 46 # Create countdown 47 cur.execute("CALL createCountdown(%s, %s, %s);", 48 (ctx.channel.id, ctx.channel.guild.id, self.bot.prefix)) 49 50 # Send initial response 51 self.bot.logger.info(f"Activated {self.bot.get_channel(ctx.channel.id)} (ID {ctx.channel.id}) as a countdown") 52 embed = discord.Embed(title=":clock3: Loading Countdown", description="This channel is now a countdown\nPlease wait to start counting", color=COLORS["embed"]) 53 msg = await ctx.send(embed=embed) 54 55 # Load countdown 56 await loadCountdown(self.bot, ctx.channel.id) 57 self.db_connection.commit() 58 59 # Send final response 60 embed = discord.Embed(title=":white_check_mark: Countdown Activated", description="This channel is now a countdown\nYou may start counting!", color=COLORS["embed"]) 61 await msg.edit(embed=embed) 62 63 64 65 @commands.command() 66 async def config(self, ctx, key=None, *args): 67 """ 68 Shows and modifies countdown settings 69 """ 70 71 # Create embed 72 embed = discord.Embed(title=":gear: Countdown Settings", color=COLORS["embed"]) 73 74 # Make sure context is in a server 75 if (not isinstance(ctx.channel, discord.channel.TextChannel)): 76 raise CommandError("This command must be run in a countdown channel or a server with a countdown channel") 77 78 with self.db_connection.cursor() as cur: 79 # Get countdown channel 80 countdown = getContextCountdown(cur, ctx) 81 82 if not countdown: 83 raise CountdownNotFound() 84 85 # Get / set settings 86 if (key is None): 87 embed.description = f"**Countdown Channel:** <#{countdown}>\n" 88 89 cur.execute("SELECT * from getPrefixes(%s);", (countdown,)) 90 prefixes = [x["prefix"] for x in cur.fetchall()] 91 embed.description += f"**Command Prefixes:** `{'`, `'.join(prefixes)}`\n" 92 93 cur.execute("CALL getTimezone(%s, null);", (countdown,)) 94 timezone = cur.fetchone()["_timezone"] 95 if (timezone >= 0): 96 embed.description += f"**Countdown Timezone:** UTC+{timezone:.2f}\n" 97 else: 98 embed.description += f"**Countdown Timezone:** UTC-{abs(timezone):.2f}\n" 99 100 cur.execute("SELECT * FROM getReactions(%s, NULL);", (countdown,)) 101 reactions = cur.fetchall() 102 if (len(reactions) == 0): 103 embed.description += f"**Reactions:** none\n" 104 else: 105 embed.description += f"**Reactions:**\n" 106 for number in reversed(list(set([x["number"] for x in reactions]))): 107 embed.description += f"**-** #{number}: {', '.join([x["value"] for x in reactions if x["number"] == number])}\n" 108 109 embed.description += f"\nUse `{ctx.prefix}help config` to view more information about settings\n" 110 embed.description += f"Use `{ctx.prefix}config <key> <value>` to modify settings\n" 111 elif (not ctx.message.author.guild_permissions.administrator): 112 raise CommandError("You must be an administrator to modify settings") 113 elif (len(args) == 0): 114 raise CommandError("Please provide a value for the setting") 115 elif (key in ["tz", "timezone"]): 116 try: 117 timezone = float(args[0]) 118 except: 119 raise CommandError(f"Invalid timezone: `{args[0]}`") 120 else: 121 cur.execute("CALL setTimezone(%s, %s);", (countdown, timezone)) 122 if (timezone >= 0): 123 embed.description = f"Timezone set to UTC+{timezone:.2f}\n" 124 else: 125 embed.description = f"Timezone set to UTC-{abs(timezone):.2f}\n" 126 elif (key in ["prefix", "prefixes"]): 127 cur.execute("CALL setPrefixes(%s, %s);", (countdown, list(args))) 128 embed.description = f"Prefixes updated" 129 elif (key in ["react"]): 130 try: 131 number = int(args[0]) 132 except: 133 raise CommandError(f"Invalid number: `{args[0]}`") 134 if (number < 0): 135 raise CommandError("Number must be greater than zero") 136 cur.execute("CALL setReactions(%s, %s, %s);", 137 (countdown, number, list(args[1:]))) 138 if (len(args) == 1): 139 embed.description = f"Removed reactions for #{number}" 140 else: 141 embed.description = f"Updated reactions for #{number}" 142 else: 143 raise CommandError(f"Setting not found: `{key}`") 144 145 # Save changes 146 self.db_connection.commit() 147 148 # Send embed 149 await ctx.send(embed=embed) 150 151 152 153 @commands.command() 154 async def deactivate(self, ctx): 155 """ 156 Deactivates a countdown channel 157 """ 158 159 with self.db_connection.cursor() as cur: 160 # Check if channel isn't a countdown 161 if (not isCountdown(cur, ctx.channel.id)): 162 raise CommandError("This channel isn't a countdown") 163 164 # Check if user isn't authorized 165 if (not ctx.author.guild_permissions.administrator): 166 raise CommandError("You must be an administrator to deactivate a countdown channel") 167 168 # Delete countdown 169 cur.execute("CALL deleteCountdown(%s);", 170 (ctx.channel.id,)) 171 self.db_connection.commit() 172 173 # Send response 174 self.bot.logger.info(f"Deactivated {self.bot.get_channel(ctx.channel.id)} (ID {ctx.channel.id}) as a countdown") 175 embed = discord.Embed(title=":octagonal_sign: Countdown Deactivated", description="This channel is no longer a countdown", color=COLORS["embed"]) 176 await ctx.send(embed=embed) 177 178 179 180 @commands.command() 181 async def reload(self, ctx): 182 """ 183 Reloads the countdown cache 184 """ 185 186 with self.db_connection.cursor() as cur: 187 # Check if channel isn't a countdown 188 if (not isCountdown(cur, ctx.channel.id)): 189 raise CommandError("Countdown not found\nThis command must be used in a countdown channel") 190 191 # Send initial response 192 embed = discord.Embed(title=":clock3: Reloading Countdown Cache", description="Please wait to continue counting", color=COLORS["embed"]) 193 msg = await ctx.channel.send(embed=embed) 194 195 # Reload messages 196 await loadCountdown(self.bot, ctx.channel.id) 197 self.db_connection.commit() 198 199 # Send final response 200 self.bot.logger.info(f"Reloaded messages from {self.bot.get_channel(ctx.channel.id)} (ID {ctx.channel.id})") 201 embed = discord.Embed(title=":white_check_mark: Countdown Cache Reloaded", description="Done! You may continue counting!", color=COLORS["embed"]) 202 await msg.edit(embed=embed)