diff --git a/src/cogs/reminder.py b/src/cogs/reminder.py new file mode 100644 index 0000000..721452c --- /dev/null +++ b/src/cogs/reminder.py @@ -0,0 +1,202 @@ +import discord +from discord.ext import commands, tasks +from discord_slash import cog_ext +from utils.reminder import Reminder +from utils.core import getURLsInString, getMentionInString, isSlash, mySendHidden, mentionToUser, cleanCodeStringWithMentionAndURLs +from utils.time import stringTempsVersSecondes, nowUTC, intToDatetime, timedeltaToString, timestampScreen + +def setup(client): + client.add_cog(Reminder(client)) + +class Reminder(commands.Cog): + """Commandes relatives aux cours.""" + def __init__(self, client): + self.client = client + + @commands.command(name='reminder', aliases=["remind", "remindme", "rappel"]) + async def _reminder(self, ctx, time, *reminder): + """Met en place un rappel.⁢⁢⁢⁢⁢\n ➡ Syntaxe: {PREFIX}reminder/remind/remindme/rappel [@] [message]""" + _, fromSlash, reminder = isSlash(reminder) + if len(reminder) > 0: + reminder = " ".join(reminder) + else: + reminder = None + + embed = discord.Embed(color = 0xC41B1B) + extrarg = 0 + guildID = ctx.guild.id # can be set to 0 if its a DM message, so it can be see from anywhere + destination = "ici" + if not reminder: + reminder = "Notification" + if time == "help": + seconds = 0 + else: + if time.endswith("@"): + time = time[:-1] + extrarg = 1 + if time.lower().endswith("p"): + time = time[:-1] + extrarg = 2 + guildID = 0 + destination = "en MP" + seconds = stringTempsVersSecondes(time) + if type(seconds) != int: + if fromSlash != True: + await ctx.message.add_reaction(emoji = '❓') + return await mySendHidden(ctx, fromSlash, seconds) + if seconds == 0: + embed.add_field(name="Attention", value= + "Format pour le temps : `d` ou `j` pour jour, `h` pour heure, `m` pour minute, `s` pour seconde (légères variances acceptés aussi). \ + \nMet un `@` accolée aux temps pour mentionner les gens mentionner dans ton message. \ + \nMet un `P` accolée au temps pour que le bot te DM au lieu de t'envoyer un message dans ce salon." + ) + elif seconds > (50 * (86400 * 365.242)): # 50 ans + embed.add_field(name="Attention", value="Tu as spécifié une durée trop longue, la durée maximum étant de 50 ans.") + else: + now = int(nowUTC()) + messageID = None + if fromSlash != True: + messageID = ctx.message.id + reminderID = Reminder().ajoutReminder(messageID, ctx.channel.id, extrarg, reminder, now, now + seconds, ctx.author.id, guildID) + return await mySendHidden(ctx, fromSlash, f"Ton reminder **`{reminderID[0][0]}`** est enrengistré, je te notifie {destination} dans {timedeltaToString(seconds)} (avec 1m de retard maximum).") + await mySendHidden(ctx, fromSlash, embed = embed) + @_reminder.error + async def _reminder_error(self, ctx, error): + if 'time is a required argument that is missing.' in str(error): + await ctx.send("Tu n'as pas spécifié de durée.") + @cog_ext.cog_slash(name="reminder", description = "Met en place un rappel.") + async def __reminder(self, ctx, time, reminder = None): + if reminder == None: + return await self._reminder(ctx, time, True) + else: + return await self._reminder(ctx, time, reminder, True) + + @tasks.loop(minutes = 1) + async def _reminderLoop(self): + """Méthode qui se répète toute les minutes pour vérifier si des rappels n'ont pas expirés, si expirés, les envoient.""" + expiration = Reminder().recuperationExpiration(int(nowUTC())) # on récupères les éléments expirés + for expired in expiration: # on regarde tout les éléments expirés + reminder = expired[2] # message + userID = expired[4] # personne qui a fait le rappel + channel = self.client.get_channel(expired[0]) # salon du message + finalEmbed = discord.Embed(description = cleanCodeStringWithMentionAndURLs(reminder), timestamp = intToDatetime(expired[3]), color = discord.Colour.random()) + if expired[1] == 2: # s'il faut envoyer en DM le message + user = self.client.get_user(userID) + if user == None: # si l'utilisateur n'est pas trouvé + return Reminder().suppressionReminder(expired[5]) # suppression du rappel + channel = await user.create_dm() # envoie en DM + userID = None # plus de mention + sourceMessage = None # plus de message source + elif channel == None: # si le salon n'existe plus + user = self.client.get_user(userID) + if user == None: # si l'utilisateur n'est pas trouvé + return Reminder().suppressionReminder(expired[5]) # suppression du rappel + channel = await user.create_dm() # envoie en DM + userID = None # plus de mention + sourceMessage = None # plus de message source + finalEmbed.add_field(name = "Info", value = "Message envoyé en DM car le salon n'est plus disponible.") + else: + sourceMessage = expired[6] + if sourceMessage != None: # vérification message avec slash command et que si c'est pas en DM + try: + sourceMessage = await channel.fetch_message(sourceMessage) # récupération message + except: + sourceMessage = None # message a été supprimé + if sourceMessage != None: + await sourceMessage.add_reaction(emoji = '✅') # ajout réaction + finalEmbed.set_footer(text=f"Message d'il y a {timedeltaToString(int(nowUTC()) - expired[3])}") + links = "" + findedURLs = getURLsInString(reminder) + for i in range(0, len(findedURLs)): # ajout de field "lien" pour pouvoir cliquer sur les liens facilement + links += f"[Lien {i + 1}]({findedURLs[i]}) · " + if len(findedURLs) > 0: + finalEmbed.add_field(name = f"Lien{'s' if len(findedURLs) > 1 else ''}", value = links[:-3]) + message = "" + if userID != None: # metion de l'utilisateur si le message n'est pas en DM + message = f"<@{userID}>" + if expired[1] == 1: # s'il faut mentionner les personnes dans le message + mentionList = getMentionInString(reminder) + for i in mentionList: + message += f" {i}" + try: + await channel.send(message, embed = finalEmbed) # envoie du rappel + except: # les DM sont fermés + pass + Reminder().suppressionReminder(expired[5]) # suppression du rappel + @_reminderLoop.before_loop + async def __avant_reminderLoop(self): + await self.client.wait_until_ready() + + @commands.command(name='reminderlist', aliases=["remindlist", "rl", "rappeliste"]) + async def _reminderlist(self, ctx, *arg): + """Affiche la liste des rappels d'un utilisateur.⁢⁢⁢⁢⁢\n ➡ Syntaxe: {PREFIX}reminderlist/rl/remindlist/rappeliste [utilisateur]""" + _, fromSlash, arg = isSlash(arg) + utilisateur = ctx.author.id + page = 1 + if len(arg) > 0: + try: + utilisateur = mentionToUser(getMentionInString(arg[0])[0]) + except: + try: + page = int(arg[0]) + except: + return await mySendHidden(ctx, fromSlash, "Veuillez renseigné un utilisateur ou un numéro de page valide.") + + reminders = Reminder().listeReminder(utilisateur, ctx.guild.id) + if fromSlash != True: + await ctx.message.add_reaction(emoji = '✅') + + pageMAX = -(-len(reminders) // 5) + embed = discord.Embed(description = f"**Rappel{'s' if len(reminders) > 1 else ''} de <@{utilisateur}>** • Page {page}/{pageMAX}", color = discord.Colour.random()) + embed.set_thumbnail(url = self.client.get_user(utilisateur).avatar_url_as(size = 64)) + limit = 5 * page + if len(reminders) > 0 and page <= pageMAX: + curseur = limit - 4 + for reminder in reminders[limit - 5:]: + if curseur <= limit: + texte = reminder[0] + if len(texte) > 1024: + texte = f"{texte[:1021]}..." + expiration = reminder[2] - int(nowUTC()) + if expiration > 0: + expiration = f"Expire dans {timedeltaToString(expiration)}" + else: + expiration = f"A déjà expiré." + embed.add_field(value = texte, name = f"#{reminder[3]} • Fais le {timestampScreen(intToDatetime(reminder[1]))}\n{expiration}", inline = False) + curseur += 1 + else: + embed.add_field(name = "\u200b", value = f"L'utilisateur n'a aucun rappel en attente ou page n°{page} vide !") + embed.set_footer(text = "Les rappels qui ont déjà expirés vont apparaître dans quelques instants.\nIls peuvent avoir jusqu'à 1 minute de retard maximum.") + await ctx.send(embed = embed) + @cog_ext.cog_slash(name="reminderlist", description = "Affiche la liste des rappels d'un utilisateur.") + async def __reminderlist(self, ctx, userorpage = None): + if userorpage == None: + return await self._reminderlist(ctx, True) + else: + return await self._reminderlist(ctx, userorpage, True) + + @commands.command(name='reminderdelete', aliases=["reminddelete", "rd"]) + async def _reminderdelete(self, ctx, *id): + """Suppprime un rappel.⁢⁢⁢⁢⁢\n ➡ Syntaxe: {PREFIX}reminderdelete/rd """ + id, fromSlash, _ = isSlash(id) + if id: + try: + id = int(id) + except: + return await mySendHidden(ctx, fromSlash, "L'ID renseigné n'est pas valide.") + else: + return await ctx.send("Veuillez renseigner un ID.") + + verification = Reminder().appartenanceReminder(ctx.author.id, id, ctx.guild.id) + if verification: + Reminder().suppressionReminder(id) + if fromSlash != True: + await ctx.message.add_reaction(emoji = '✅') + return await ctx.send(f"Reminder **#{id}** supprimé !") + else: + if fromSlash != True: + await ctx.message.add_reaction(emoji = '❌') + return await mySendHidden(ctx, fromSlash, "Rappel non trouvé, pas sur le bon serveur ou qui ne vous appartiens pas.") + @cog_ext.cog_slash(name="reminderdelete", description = "Suppprime un rappel.") + async def __reminderdelete(self, ctx, id): + return await self._reminderdelete(ctx, id, True) diff --git a/src/cogs/utils.py b/src/cogs/utils.py index 29e8536..65a54fe 100644 --- a/src/cogs/utils.py +++ b/src/cogs/utils.py @@ -1,11 +1,11 @@ import discord -from discord.ext import commands, tasks +from discord.ext import commands from random import randint, shuffle +from re import findall from discord_slash import cog_ext -from utils.reminder import Reminder -from utils.core import map_list_among_us, getURLsInString, getMentionInString, cleanCodeStringWithMentionAndURLs, cleanUser, userOrNick +from utils.core import map_list_among_us, cleanCodeStringWithMentionAndURLs, cleanUser, userOrNick from utils.core import mySendHidden, mentionToUser, getChangelogs, getActualVersion, isSlash, load, devOrStableChannel -from utils.time import stringTempsVersSecondes, nowUTC, intToDatetime, timedeltaToString, timestampScreen, getAge, ageLayout, nowCustom +from utils.time import nowUTC, intToDatetime, timestampScreen, getAge, ageLayout, nowCustom def setup(client): client.add_cog(Utils(client)) @@ -249,7 +249,7 @@ class Utils(commands.Cog): version = f"`{version}`" if changes[0] == 200: version = f"[{version}]({changes[1]})" - embed.add_field(name = "Version", value = f"{version} ({devOrStableChannel().replace("main", "stable")})") + embed.add_field(name = "Version", value = f"{version} ({devOrStableChannel().replace('main', 'stable')})") embed.set_footer(text = f"Basé sur discord.py {discord.__version__}") try: if fromSlash != True: @@ -447,194 +447,6 @@ class Utils(commands.Cog): args = args[:1] return await self._avis(ctx, args, True) - @commands.command(name='reminder', aliases=["remind", "remindme", "rappel"]) - async def _reminder(self, ctx, time, *reminder): - """Met en place un rappel.⁢⁢⁢⁢⁢\n ➡ Syntaxe: {PREFIX}reminder/remind/remindme/rappel [@] [message]""" - _, fromSlash, reminder = isSlash(reminder) - if len(reminder) > 0: - reminder = " ".join(reminder) - else: - reminder = None - - embed = discord.Embed(color = 0xC41B1B) - extrarg = 0 - guildID = ctx.guild.id # can be set to 0 if its a DM message, so it can be see from anywhere - destination = "ici" - if not reminder: - reminder = "Notification" - if time == "help": - seconds = 0 - else: - if time.endswith("@"): - time = time[:-1] - extrarg = 1 - if time.lower().endswith("p"): - time = time[:-1] - extrarg = 2 - guildID = 0 - destination = "en MP" - seconds = stringTempsVersSecondes(time) - if type(seconds) != int: - if fromSlash != True: - await ctx.message.add_reaction(emoji = '❓') - return await mySendHidden(ctx, fromSlash, seconds) - if seconds == 0: - embed.add_field(name="Attention", value= - "Format pour le temps : `d` ou `j` pour jour, `h` pour heure, `m` pour minute, `s` pour seconde (légères variances acceptés aussi). \ - \nMet un `@` accolée aux temps pour mentionner les gens mentionner dans ton message. \ - \nMet un `P` accolée au temps pour que le bot te DM au lieu de t'envoyer un message dans ce salon." - ) - elif seconds > (50 * (86400 * 365.242)): # 50 ans - embed.add_field(name="Attention", value="Tu as spécifié une durée trop longue, la durée maximum étant de 50 ans.") - else: - now = int(nowUTC()) - messageID = None - if fromSlash != True: - messageID = ctx.message.id - reminderID = Reminder().ajoutReminder(messageID, ctx.channel.id, extrarg, reminder, now, now + seconds, ctx.author.id, guildID) - return await mySendHidden(ctx, fromSlash, f"Ton reminder **`{reminderID[0][0]}`** est enrengistré, je te notifie {destination} dans {timedeltaToString(seconds)} (avec 1m de retard maximum).") - await mySendHidden(ctx, fromSlash, embed = embed) - @_reminder.error - async def _reminder_error(self, ctx, error): - if 'time is a required argument that is missing.' in str(error): - await ctx.send("Tu n'as pas spécifié de durée.") - @cog_ext.cog_slash(name="reminder", description = "Met en place un rappel.") - async def __reminder(self, ctx, time, reminder = None): - if reminder == None: - return await self._reminder(ctx, time, True) - else: - return await self._reminder(ctx, time, reminder, True) - - @tasks.loop(minutes = 1) - async def _reminderLoop(self): - """Méthode qui se répète toute les minutes pour vérifier si des rappels n'ont pas expirés, si expirés, les envoient.""" - expiration = Reminder().recuperationExpiration(int(nowUTC())) # on récupères les éléments expirés - for expired in expiration: # on regarde tout les éléments expirés - reminder = expired[2] # message - userID = expired[4] # personne qui a fait le rappel - channel = self.client.get_channel(expired[0]) # salon du message - finalEmbed = discord.Embed(description = cleanCodeStringWithMentionAndURLs(reminder), timestamp = intToDatetime(expired[3]), color = discord.Colour.random()) - if expired[1] == 2: # s'il faut envoyer en DM le message - user = self.client.get_user(userID) - if user == None: # si l'utilisateur n'est pas trouvé - return Reminder().suppressionReminder(expired[5]) # suppression du rappel - channel = await user.create_dm() # envoie en DM - userID = None # plus de mention - sourceMessage = None # plus de message source - elif channel == None: # si le salon n'existe plus - user = self.client.get_user(userID) - if user == None: # si l'utilisateur n'est pas trouvé - return Reminder().suppressionReminder(expired[5]) # suppression du rappel - channel = await user.create_dm() # envoie en DM - userID = None # plus de mention - sourceMessage = None # plus de message source - finalEmbed.add_field(name = "Info", value = "Message envoyé en DM car le salon n'est plus disponible.") - else: - sourceMessage = expired[6] - if sourceMessage != None: # vérification message avec slash command et que si c'est pas en DM - try: - sourceMessage = await channel.fetch_message(sourceMessage) # récupération message - except: - sourceMessage = None # message a été supprimé - if sourceMessage != None: - await sourceMessage.add_reaction(emoji = '✅') # ajout réaction - finalEmbed.set_footer(text=f"Message d'il y a {timedeltaToString(int(nowUTC()) - expired[3])}") - links = "" - findedURLs = getURLsInString(reminder) - for i in range(0, len(findedURLs)): # ajout de field "lien" pour pouvoir cliquer sur les liens facilement - links += f"[Lien {i + 1}]({findedURLs[i]}) · " - if len(findedURLs) > 0: - finalEmbed.add_field(name = f"Lien{'s' if len(findedURLs) > 1 else ''}", value = links[:-3]) - message = "" - if userID != None: # metion de l'utilisateur si le message n'est pas en DM - message = f"<@{userID}>" - if expired[1] == 1: # s'il faut mentionner les personnes dans le message - mentionList = getMentionInString(reminder) - for i in mentionList: - message += f" {i}" - try: - await channel.send(message, embed = finalEmbed) # envoie du rappel - except: # les DM sont fermés - pass - Reminder().suppressionReminder(expired[5]) # suppression du rappel - @_reminderLoop.before_loop - async def __avant_reminderLoop(self): - await self.client.wait_until_ready() - - @commands.command(name='reminderlist', aliases=["remindlist", "rl", "rappeliste"]) - async def _reminderlist(self, ctx, *arg): - """Affiche la liste des rappels d'un utilisateur.⁢⁢⁢⁢⁢\n ➡ Syntaxe: {PREFIX}reminderlist/rl/remindlist/rappeliste [utilisateur]""" - _, fromSlash, arg = isSlash(arg) - utilisateur = ctx.author.id - page = 1 - if len(arg) > 0: - try: - utilisateur = mentionToUser(getMentionInString(arg[0])[0]) - except: - try: - page = int(arg[0]) - except: - return await mySendHidden(ctx, fromSlash, "Veuillez renseigné un utilisateur ou un numéro de page valide.") - - reminders = Reminder().listeReminder(utilisateur, ctx.guild.id) - if fromSlash != True: - await ctx.message.add_reaction(emoji = '✅') - - pageMAX = -(-len(reminders) // 5) - embed = discord.Embed(description = f"**Rappel{'s' if len(reminders) > 1 else ''} de <@{utilisateur}>** • Page {page}/{pageMAX}", color = discord.Colour.random()) - embed.set_thumbnail(url = self.client.get_user(utilisateur).avatar_url_as(size = 64)) - limit = 5 * page - if len(reminders) > 0 and page <= pageMAX: - curseur = limit - 4 - for reminder in reminders[limit - 5:]: - if curseur <= limit: - texte = reminder[0] - if len(texte) > 1024: - texte = f"{texte[:1021]}..." - expiration = reminder[2] - int(nowUTC()) - if expiration > 0: - expiration = f"Expire dans {timedeltaToString(expiration)}" - else: - expiration = f"A déjà expiré." - embed.add_field(value = texte, name = f"#{reminder[3]} • Fais le {timestampScreen(intToDatetime(reminder[1]))}\n{expiration}", inline = False) - curseur += 1 - else: - embed.add_field(name = "\u200b", value = f"L'utilisateur n'a aucun rappel en attente ou page n°{page} vide !") - embed.set_footer(text = "Les rappels qui ont déjà expirés vont apparaître dans quelques instants.\nIls peuvent avoir jusqu'à 1 minute de retard maximum.") - await ctx.send(embed = embed) - @cog_ext.cog_slash(name="reminderlist", description = "Affiche la liste des rappels d'un utilisateur.") - async def __reminderlist(self, ctx, userorpage = None): - if userorpage == None: - return await self._reminderlist(ctx, True) - else: - return await self._reminderlist(ctx, userorpage, True) - - @commands.command(name='reminderdelete', aliases=["reminddelete", "rd"]) - async def _reminderdelete(self, ctx, *id): - """Suppprime un rappel.⁢⁢⁢⁢⁢\n ➡ Syntaxe: {PREFIX}reminderdelete/rd """ - id, fromSlash, _ = isSlash(id) - if id: - try: - id = int(id) - except: - return await mySendHidden(ctx, fromSlash, "L'ID renseigné n'est pas valide.") - else: - return await ctx.send("Veuillez renseigner un ID.") - - verification = Reminder().appartenanceReminder(ctx.author.id, id, ctx.guild.id) - if verification: - Reminder().suppressionReminder(id) - if fromSlash != True: - await ctx.message.add_reaction(emoji = '✅') - return await ctx.send(f"Reminder **#{id}** supprimé !") - else: - if fromSlash != True: - await ctx.message.add_reaction(emoji = '❌') - return await mySendHidden(ctx, fromSlash, "Rappel non trouvé, pas sur le bon serveur ou qui ne vous appartiens pas.") - @cog_ext.cog_slash(name="reminderdelete", description = "Suppprime un rappel.") - async def __reminderdelete(self, ctx, id): - return await self._reminderdelete(ctx, id, True) - @commands.command(name='changelogs', aliases=["changelog", "changement", "changements"]) async def _changelogs(self, ctx, *version): """Affiche les changements de la dernière version ou d'une version précise.⁢⁢⁢⁢⁢\n ➡ Syntaxe: {PREFIX}changelogs/changelog/changement/changements [version]"""