def __init__(self, client, lang, logger, db, cursor): self.client = client self.lang = lang self.logger = logger self.db = db self.cursor = cursor self.edit = EditLocale(db, cursor) self.util = Util(client, db, cursor)
class Locale(commands.Cog, name='Reminder'): def __init__(self, client, lang, logger, db, cursor): self.client = client self.lang = lang self.logger = logger self.db = db self.cursor = cursor self.edit = EditLocale(db, cursor) self.hand = Handler(client, lang, logger, db, cursor) @commands.command(name="update", usage="[arg]", help="Updates the meta data (date and time) of the event." "Per default all users which are slotted for the event, are" "messaged the changed time and date. If the arg '--supress' is given," "this is not the case.", brief="Updates the internal meta data (date and time) of the event.") @has_role(cfg["role"]) @commands.cooldown(1, 0.5, commands.BucketType.channel) @commands.guild_only() async def update(self, ctx, args=""): def getAllUser(): sql = "SELECT User FROM Slot WHERE Event = %s AND User IS NOT NULL;" self.cursor.execute(sql, [ctx.message.channel.id]) return [channel.guild.get_member(int(x[0])) for x in self.cursor.fetchall() if x[0].isnumeric()] channel = ctx.message.channel time = "" if (before := self.edit.getEvent(channel.id)) is not None: try: date = [int(x) for x in channel.name.split("-")[:3]] date = dt.date(*date) except ValueError: await ctx.message.delete() await channel.send(ctx.message.author.mention + " " + self.lang["update"]["command"]["date_error"].format(channel.name), delete_after=5) return async for msg in channel.history(limit=10, oldest_first=True): if content := re.findall(r"Eventstart:.*$", msg.content.replace("*", ""), re.MULTILINE): if msg.author == ctx.message.author: time = re.sub("[^0-9]", "", content[0]) break if time == "" or date == "": await ctx.message.delete() await channel.send(ctx.message.author.mention + " " + self.lang["update"]["command"]["error"].format(channel.name), delete_after=5) return else: if not (0 < int(time) < 2400): await channel.send(ctx.message.author.mention + " " + self.lang["update"]["command"]["time_error"].format(channel.name), delete_after=5) return time = time[:2] + ':' + time[2:] + ":00" self.edit.updateNotify(channel.id, str(before[0]) + " " + str(before[1]), str(date) + " " + str(time)) if self.edit.updateEvent(channel.id, channel.name, date, time): await channel.send(ctx.message.author.mention + " " + self.lang["update"]["command"]["success"].format(channel.name), delete_after=5) if args != "--suppress": for user in getAllUser(): await user.send(self.lang["update"]["command"]["broadcast"].format(channel.id, time)) else: await channel.send(ctx.message.author.mention + " " + self.lang["update"]["command"]["error"].format(channel.name), delete_after=5)
def __init__(self, db, cursor): self.db = db self.cursor = cursor self.notify = EditLocale(db, cursor)
class Handler(commands.Cog): def __init__(self, client, lang, logger, db, cursor): self.client = client self.lang = lang self.logger = logger self.db = db self.cursor = cursor self.edit = EditLocale(db, cursor) self.util = Util(client, db, cursor) async def notify(self, event, user_id, delay): """ Calculates datetime for notification Args: event(string): ID of an event user_id(string): User ID delay(int): delay in sec. """ await asyncio.sleep(delay) user = self.client.get_user(int(user_id)) if user: sql = "SELECT Time FROM Notify WHERE Event = %s AND User = %s" self.cursor.execute(sql, [event, user_id]) result = self.cursor.fetchall() if not result: return now = dt.datetime.now() delta = (result[0][0] - now).total_seconds() if abs(delta) > 1200: return sql = "SELECT Name, Time FROM Event WHERE ID = %s;" self.cursor.execute(sql, [event]) result = self.cursor.fetchone() guild = self.client.get_guild(int(cfg['guild'])) nickname = guild.get_member(int(user_id)).display_name try: await user.send(self.lang["notify_global"]["noti"].format( nickname, str(result[0]), str(result[1]))) except discord.errors.Forbidden: log = "User: "******"\t" log += "Channel:" + str(event).ljust(20) + "\t" log += "Command: " + "Notify: discord.errors.Forbidden".ljust( 20) + "\t" self.logger.log(log) @commands.Cog.listener() async def on_ready(self): sql = "SELECT n.User, n.Time, n.Event FROM Notify n, User u \ WHERE n.User = u.ID AND u.Notify AND n.Enabled AND n.Time >= CURDATE();" self.cursor.execute(sql) result = self.cursor.fetchall() for elem in result: now = dt.datetime.now() delta = (elem[1] - now).total_seconds() if delta > 0: asyncio.create_task(self.notify(elem[2], elem[0], delta)) @commands.Cog.listener() async def on_guild_channel_update(self, before, after): if before.name != after.name: if (event := self.edit.getEvent(after.id)) is not None: author = self.util.get_channel_author(after) try: date = [int(x) for x in after.name.split("-")[:3]] date = dt.date(*date) except ValueError: await author.send( self.lang["update"]["auto"]["date_error"].format( after.name)) return self.edit.updateNotify(after.id, str(event[0]) + " " + str(event[1]), str(date) + " " + str(event[1])) if self.edit.updateEvent(after.id, after.name, date): await author.send( self.lang["update"]["auto"]["success"].format( after.name)) else: await author.send( self.lang["update"]["auto"]["error"].format(after.name) ) return
class EditList: def __init__(self, db, cursor): self.db = db self.cursor = cursor self.notify = EditLocale(db, cursor) def slotEvent(self, channel, user_id, num, user_displayname=None, force=False): """ Slots a given user in the given slot Args: channel (channel): Server channel user_id (int): User ID num (string): Number of the slot user_displayname (string): User nickname (optional) force (bool): If true, accept duplicates (optional) Returns: (bool): if successful """ sql = "SELECT User FROM Slot, Event WHERE Event.ID = Slot.Event and Event = %s and Number = %s and (NOT Event.Locked OR %s);" var = [channel.id, num, force] self.cursor.execute(sql, var) slot = self.cursor.fetchone() if slot is None or slot[0] is not None: return False sql = "SELECT ID, Nickname FROM User WHERE ID = %s;" self.cursor.execute(sql, [user_id]) result = self.cursor.fetchone() if (not force) and (result is None): sql = "INSERT INTO User (ID, Nickname) VALUES (%s, %s);" var = [str(user_id), user_displayname] self.cursor.execute(sql, var) self.db.commit() elif not force and (result is not None) and result[1] != user_displayname: sql = "UPDATE User SET Nickname= %s WHERE ID = %s;" var = [str(user_displayname), str(user_id)] self.cursor.execute(sql, var) self.db.commit() if not force: sql = "UPDATE Slot SET User = NULL WHERE STRCMP(User, %s) = 0 AND Event = %s;" var = [str(user_id), str(channel.id)] self.cursor.execute(sql, var) self.db.commit() self.notify.create(channel.id, user_id) try: sql = "UPDATE Slot SET User = %s WHERE Number = %s and Event = %s;" var = [user_id, num, channel.id] self.cursor.execute(sql, var) self.db.commit() except mysql.connector.errors.DatabaseError: return False return True def unslotEvent(self, channel, user_id="", slot=""): """ Unslots a user or clears an slot from an Event Args: channel (channel): Server channel user_id (string): User ID slot (string) ; Slotnumber Returns: (bool): if successful """ type = ['Number', 'User'][int(slot == "")] arg = [slot, user_id][int(slot == "")] sql = f"SELECT Number FROM Slot WHERE STRCMP({type} , %s) = 0 and Event = %s;" var = [arg, channel.id] self.cursor.execute(sql, var) result = self.cursor.fetchone() if result: sql = f"UPDATE Slot SET User = NULL WHERE STRCMP({type}, %s) = 0 and Event = %s;" var = [arg, channel.id] self.cursor.execute(sql, var) self.db.commit() self.notify.toggle(channel.id, user_id, True) return result[0] else: return False def addSlot(self, channel, slot, group, desc): """ Adds a slot to a given event Args: channel (channel): Server channel slot (int): Slot-Number group (string): Group-Number (counting form 0) or Group-Name desc (string): Name Returns: (bool): if successful """ sql = "SELECT Description FROM Slot WHERE Event = %s and Number = %s;" var = [channel.id, slot] self.cursor.execute(sql, var) result = self.cursor.fetchone() # Pushes Reserve Slots if result and (result[0] == "Reserve" and not desc == "Reserve"): sql = "SELECT Number FROM Slot WHERE Event = %s and Description = %s" self.cursor.execute(sql, [channel.id, 'Reserve']) result = self.cursor.fetchall() new = [(int(x[0]) + 10, channel.id, x[0]) for x in result] sql = "UPDATE Slot SET Number = %s WHERE Event=%s and Number = %s" self.cursor.executemany(sql, new) self.db.commit() elif result: return False if group.isdigit(): sql = "SELECT Number FROM SlotGroup WHERE Event = %s AND Number = %s;" self.cursor.execute(sql, [channel.id, group]) if self.cursor.fetchall() is None: return False else: sql = "SELECT Number FROM SlotGroup WHERE Event = %s and Name = %s;" var = [channel.id, group] self.cursor.execute(sql, var) group = self.cursor.fetchone()[0] if not group: return False sql = "INSERT INTO Slot (Event, Number, Description, GroupNumber) VALUES (%s, %s, %s, %s);" var = [channel.id, slot, desc, group] self.cursor.execute(sql, var) self.db.commit() length = len(str(slot)) + len(desc) + 15 sql = "UPDATE SlotGroup SET Length = Length + %s WHERE Number = %s and Event = %s;" var = [length, group, channel.id] self.cursor.execute(sql, var) self.db.commit() return True def delSlot(self, channel, slot): """ Deletes a given slot Args: channel (channel): Server channel slot (string): Slot-Number Returns: (bool): if successful """ sql = "SELECT Description, GroupNumber FROM Slot WHERE Event = %s and Number = %s;" var = [channel.id, slot] self.cursor.execute(sql, var) desc = self.cursor.fetchone() if not desc: return False length = len(str(slot)) + len(desc[0]) + 15 sql = "DELETE FROM Slot WHERE Event = %s AND Number = %s;" self.cursor.execute(sql, [channel.id, slot]) self.db.commit() sql = "UPDATE SlotGroup SET Length = Length - %s WHERE Number = %s AND Event = %s" var = [length, desc[1], channel.id] self.cursor.execute(sql, var) self.db.commit() return True def editSlot(self, channel, slot, desc): """ Edits a slot name Args: channel (channel): Server channel slot (string): Slot-Number desc (string): Name Returns: (bool): if successful """ sql = "SELECT Description, GroupNumber FROM Slot WHERE Event = %s and Number = %s;" var = [channel.id, slot] self.cursor.execute(sql, var) old_desc = self.cursor.fetchone() if not old_desc: return False sql = "UPDATE Slot SET Description = %s WHERE Number = %s AND Event = %s;" var = [desc, slot, channel.id] self.cursor.execute(sql, var) self.db.commit() length = len(desc) - len(old_desc[0]) sql = "UPDATE SlotGroup SET Length = Length + %s WHERE Event = %s AND Number = %s;" var = [length, channel.id, old_desc[1]] self.cursor.execute(sql, var) self.db.commit() return True def addGroup(self, channel, number, name=""): """ Adds a slot-group to a given event Args: channel (channel): Server channel number (int): Group-Number (counting from 0) name (string): Group-Name (optional) Returns: (bool): if successful """ sql = "SELECT Name, Number FROM SlotGroup WHERE Event = %s and Number = %s;" var = [channel.id, int(number)] self.cursor.execute(sql, var) result = self.cursor.fetchone() if result and result[0] == "Reserve": sql = "UPDATE SlotGroup SET Number = %s WHERE Event = %s and Name = %s" var = [int(number) + 1, channel.id, 'Reserve'] self.cursor.execute(sql, var) self.db.commit() elif result: return False sql = "INSERT INTO SlotGroup (Number, Event, Name, Struct, Length) VALUES (%s, %s, %s, '\n', %s);" length = len(name) + 1 var = [number, channel.id, name, length] self.cursor.execute(sql, var) self.db.commit() return True def delGroup(self, channel, group): """ Deletes a slot from a given event Args: channel (channel): Server channel group (string): Group-Number (counting form 0) or Group-Name Returns: (bool): if successful """ if group.isdigit(): sql = "SELECT Number FROM SlotGroup WHERE Event = %s AND Number = %s;" self.cursor.execute(sql, [channel.id, group]) if self.cursor.fetchone() is None: return False else: sql = "SELECT Number FROM SlotGroup WHERE Event = %s AND Name = %s;" var = [channel.id, group] self.cursor.execute(sql, var) if not group: return False group = self.cursor.fetchone()[0] sql = "DELETE FROM Slot WHERE GroupNumber = %s AND Event = %s;" self.cursor.execute(sql, [group, channel.id]) self.db.commit() sql = "DELETE FROM SlotGroup WHERE Number = %s AND Event = %s;" self.cursor.execute(sql, [group, channel.id]) self.db.commit() return True def toggleLock(self, channel): """ Toggles the lock on an event Args: channel (channel): Server channel Returns: (bool): if successful """ sql = "UPDATE Event SET Locked = NOT Locked WHERE ID = %s;" self.cursor.execute(sql, [channel.id]) self.db.commit() return self.cursor.rowcount == 1