Compare commits

..

20 commits
main ... dev

Author SHA1 Message Date
f27fd93e78
spaces 2022-06-13 23:04:12 +02:00
8ce59cc541
Add some emojis/role reaction + template function which is adding reaction to a message without context 2022-06-13 23:03:56 +02:00
05b9e359c7
Add some emojis 2022-06-02 19:51:47 +02:00
a0eef4bfe5 party games command output now only visible by the user since it workflow changed 2021-12-05 04:15:53 +01:00
4234730041 correct message 2021-11-14 12:47:44 +01:00
90e5d6a1e9 Update Java instructions 2021-11-14 01:23:31 +01:00
ecd00568fe upstream lavalink 2021-11-14 01:21:52 +01:00
036cb69518 Upstream Lavalink 2021-11-14 01:17:19 +01:00
7f98ae2793 adding original link to the message but without embeding it 2021-11-08 21:21:08 +01:00
e78a5f371d Update discord together from 1.1.1 to 1.2.1 2021-11-02 12:37:43 +01:00
c3e11519c4 Update Lavalink main branch 2021-11-01 22:44:37 +01:00
ce7ad42bb9 Add mirror and fast clone method 2021-11-01 22:37:52 +01:00
7d30eae1f2 Fix issue wrong message when vol == 0 2021-10-11 13:30:01 +02:00
8c35af16ff fix typo 2021-09-22 20:08:06 +02:00
ef1816be20 Adding Feature in the list 2021-09-20 11:17:55 +02:00
abd62d7c6d check if DM are closed and don't stop at first error 2021-09-20 11:14:51 +02:00
dac6ed6112 remove debug print 2021-09-20 11:12:09 +02:00
1b7b4d0507 Addition of a recap of the ToDo's every Saturday at 9am 2021-09-20 11:07:45 +02:00
be47cc43b0 fix error when adding reaction in DM channel 2021-09-20 11:06:59 +02:00
f9c02e6c95 bump to 1.7 2021-09-20 09:12:02 +02:00
12 changed files with 164 additions and 38 deletions

View file

@ -1,7 +1,8 @@
# Bot Discord # Bot Discord
[![Version](https://img.shields.io/badge/version-1.6-green?style=for-the-badge)](https://gitlab.com/ConfrerieDuKassoulait/KassouBot/-/releases) [![Version](https://img.shields.io/badge/version-1.7-green?style=for-the-badge)](https://gitlab.com/ConfrerieDuKassoulait/KassouBot/-/releases)
[![Build](https://img.shields.io/gitlab/pipeline/ConfrerieDuKassoulait/KassouBot/main?style=for-the-badge)](https://gitlab.com/ConfrerieDuKassoulait/KassouBot/container_registry) [![Build](https://img.shields.io/gitlab/pipeline/ConfrerieDuKassoulait/KassouBot/dev?style=for-the-badge)](https://gitlab.com/ConfrerieDuKassoulait/KassouBot/container_registry)
[![Mirror](https://img.shields.io/badge/Mirror-brightgreen?style=for-the-badge)](https://git.kennel.ml/ConfrerieDuKassoulait/KassouBot)
## __Features__ ## __Features__
@ -9,7 +10,7 @@
- Slash commands support (use [Discord Interactions](https://github.com/goverfl0w/discord-interactions)). - Slash commands support (use [Discord Interactions](https://github.com/goverfl0w/discord-interactions)).
- Party games activities support (use [Discord Together](https://github.com/apurv-r/discord-together)). - Party games activities support (use [Discord Together](https://github.com/apurv-r/discord-together)).
- Music support (use [Lavalink](https://github.com/freyacodes/Lavalink) with the [Wavelink](https://github.com/PythonistaGuild/Wavelink) client). - Music support (use [Lavalink](https://github.com/freyacodes/Lavalink) with the [Wavelink](https://github.com/PythonistaGuild/Wavelink) client).
- Reminders and Todos list support. - Reminders and ToDos list support (with a weekly reminder of the ToDos list in DM).
- Poll support. - Poll support.
- Meme from reddit and NSFW pictures support. - Meme from reddit and NSFW pictures support.
- Basics commands and simple games, don't mind on opening an issue if you wan't your idea to be added to the bot. - Basics commands and simple games, don't mind on opening an issue if you wan't your idea to be added to the bot.
@ -77,19 +78,22 @@ To find Genius token, go to [this site](https://genius.com/api-clients), `login
## __Launching locally__ ## __Launching locally__
If you want to run it without Docker, clone the repo and his submodules by doing this command in the git folder: If you want to run it without Docker, clone the repo and his submodules by doing this command in the git folder:
```batch ```batch
git clone git@gitlab.com:ConfrerieDuKassoulait/KassouBot.git --recursive
```
If you already cloned the repo without the `--recursive` arg you can do that in the git folder :
```batch
git submodule update --force --recursive --init --remote git submodule update --force --recursive --init --remote
``` ```
Then create an .env file to store variables in the root folder (there is an example [here](https://gitlab.com/ConfrerieDuKassoulait/KassouBot/-/blob/main/.envexample)). Then create an .env file to store variables in the root folder (there is an example [here](https://gitlab.com/ConfrerieDuKassoulait/KassouBot/-/blob/main/.envexample)).
Install all the requirements by doing `python3 -m pip install -r requirements.txt` (I recommend using virtualenv to not interfere with your system). Install all the requirements by doing `python3 -m pip install -r requirements.txt` (I recommend using virtualenv to not interfere with your system).
If you need to install Java, there is some step to have the same as the [Docker image built for the project](https://gitlab.com/ConfrerieDuKassoulait/lavalink/), on Debian-based distro: If you need to install Java, there is some step to have the same as the [Docker image built for the project](https://gitlab.com/ConfrerieDuKassoulait/lavalink/), on Debian-based distro, I recommand using [SDKMAN](https://sdkman.io/):
```bash ```bash
wget -qO - https://adoptopenjdk.jfrog.io/adoptopenjdk/api/gpg/key/public | sudo apt-key add - curl -s "https://get.sdkman.io" | bash
sudo add-apt-repository --yes https://adoptopenjdk.jfrog.io/adoptopenjdk/deb/ source "$HOME/.sdkman/bin/sdkman-init.sh"
sudo apt update -y sdk install java 17.0.1-tem
sudo apt install adoptopenjdk-16-openj9 -y
``` ```
On Windows just go [to their site](https://adoptopenjdk.net/?variant=openjdk16&jvmVariant=openj9). On Windows just go [to their site](https://adoptium.net/archive.html) and choose the latest version of Temurin 17 (LTS).
Then, simply run `start.bat` if you are on Windows or `start.sh` if on Debian-based distro to launch the bot. Then, simply run `start.bat` if you are on Windows or `start.sh` if on Debian-based distro to launch the bot.

View file

@ -7,4 +7,4 @@ feedparser==6.0.8 # rss feed (news)
discord-py-slash-command==3.0.1 # slash commands discord-py-slash-command==3.0.1 # slash commands
python_dotenv==0.19.0 # using .env file python_dotenv==0.19.0 # using .env file
wavelink==0.9.10 # music | to know the version of lavalink used, see the repo wavelink==0.9.10 # music | to know the version of lavalink used, see the repo
discord-together==1.1.1 # for the party games discord-together==1.2.1 # for the party games

View file

@ -15,20 +15,31 @@ class ConfrerieDuKassoulait(commands.Cog):
def __init__(self, client): def __init__(self, client):
self.client = client self.client = client
self.messageDictAndEmojiToRoles = { self.messageDictAndEmojiToRoles = {
882785207235788800: # {MessageID: {
{ # Emoji(ID): RoleID
882783004706095194: 882616261626970112, # elephant - l1 # }}
882783004697714789: 882616188830629998, # gorilla - l2 882785207235788800: {
882783004416675881: 882616082022670387, # cat - - l3 "🟡": 882616261626970112, # l1
882783005108744202: 882616475918147654, # rabbit - visiteurs "🔵": 882616188830629998, # l2
882783004911624212: 882616714133635093 # dog - alumni "🟣": 882616082022670387, # l3
"🟠": 882616475918147654, # visiteurs
"🟢": 882616714133635093, # alumni
"💛": 882721538770624562, # référent l1
"💙": 882721619041198190, # référent l2
"💜": 882721700465246218 # référent l3
}, },
888001335105036329: 888001335105036329: {
{ "1": 887999417892880474, # étudiant
"1": 887999417892880474, # 1 - étudiant "2": 887999473513549845 # professeur
"2": 887999473513549845, # 2 - professeur },
979497142085357568: {
949037346207170571: 947652446497423382, # cartouche
"🦝": 947650819078099006, # racoon
"🎹": 979493581289042020 # musical_keyboard
} }
} }
@commands.Cog.listener() @commands.Cog.listener()
async def on_member_join(self, member): async def on_member_join(self, member):
"""Triggered when a member join a guild""" """Triggered when a member join a guild"""
@ -133,7 +144,9 @@ class ConfrerieDuKassoulait(commands.Cog):
await payload.member.add_roles(payload.member.guild.get_role(self.messageDictAndEmojiToRoles[payload.message_id][payload.emoji.id])) await payload.member.add_roles(payload.member.guild.get_role(self.messageDictAndEmojiToRoles[payload.message_id][payload.emoji.id]))
except: except:
await payload.member.add_roles(payload.member.guild.get_role(self.messageDictAndEmojiToRoles[payload.message_id][str(payload.emoji)])) await payload.member.add_roles(payload.member.guild.get_role(self.messageDictAndEmojiToRoles[payload.message_id][str(payload.emoji)]))
except KeyError: except KeyError: # mauvais message ou réaction
return
except AttributeError: # reaction en DM
return return
@commands.Cog.listener() @commands.Cog.listener()
@ -148,3 +161,19 @@ class ConfrerieDuKassoulait(commands.Cog):
await member.remove_roles(guild.get_role(self.messageDictAndEmojiToRoles[payload.message_id][str(payload.emoji)])) await member.remove_roles(guild.get_role(self.messageDictAndEmojiToRoles[payload.message_id][str(payload.emoji)]))
except KeyError: except KeyError:
return return
except AttributeError: # reaction en DM
return
""" @commands.command()
async def test(self, _):
# Test command to add some emojis to a message.
channel = self.client.get_channel(882785037236445245)
message = await channel.fetch_message(882785207235788800)
await message.add_reaction("🟡")
await message.add_reaction("🔵")
await message.add_reaction("🟣")
await message.add_reaction("🟠")
await message.add_reaction("🟢")
await message.add_reaction("💛")
await message.add_reaction("💙")
await message.add_reaction("💜") """

View file

@ -210,8 +210,9 @@ class Internet(commands.Cog):
if "tiktok.com" not in url: if "tiktok.com" not in url:
return return
url_embed = url.replace("tiktok.com", "dstn.to") url_embed = url.replace("tiktok.com", "dstn.to")
mergeUrls = f"{url_embed} | <{url}>"
if message.content == url.replace(" ", ""): if message.content == url.replace(" ", ""):
await message.channel.send(f"Tiktok partagé par {message.author.mention}{url.replace('tiktok.com', 'dstn.to')}") await message.channel.send(f"Tiktok partagé par {message.author.mention}{mergeUrls}")
await message.delete() await message.delete()
else: else:
await message.reply(f"{url_embed}", mention_author = False) await message.reply(f"{mergeUrls}", mention_author = False)

View file

@ -711,7 +711,7 @@ class Music(commands.Cog, wavelink.WavelinkMixin):
await addReaction(ctx.message, 2) await addReaction(ctx.message, 2)
return await mySendHidden(ctx, fromSlash, "Seuls le DJ ou les admins peuvent modifier le volume.") return await mySendHidden(ctx, fromSlash, "Seuls le DJ ou les admins peuvent modifier le volume.")
if not vol: if vol == None:
await mySendHidden(ctx, fromSlash, f"Le volume est actuellement réglé à **{player.volume}%**.") await mySendHidden(ctx, fromSlash, f"Le volume est actuellement réglé à **{player.volume}%**.")
if fromSlash != True: if fromSlash != True:
return await addReaction(ctx.message, 0) return await addReaction(ctx.message, 0)

View file

@ -1,8 +1,7 @@
import discord import discord
from discord.ext import commands from discord.ext import commands
import discordTogether
from discord_slash import cog_ext from discord_slash import cog_ext
from discordTogether import DiscordTogether from discord_together import errors as dte
from utils.core import mySendHidden from utils.core import mySendHidden
def setup(client): def setup(client):
@ -13,13 +12,15 @@ class PartyGames(commands.Cog, name="Partygames"):
"""Discord beta "party games" dispo uniquement sur PC.""" """Discord beta "party games" dispo uniquement sur PC."""
def __init__(self, client): def __init__(self, client):
self.client = client self.client = client
self.togetherControl = DiscordTogether(client)
self.appList = { # appNameForDiscord - (AppNameForConsumer, AppImage) self.appList = { # appNameForDiscord - (AppNameForConsumer, AppImage)
"youtube": ("Youtube Together", "https://logo-logos.com/wp-content/uploads/2016/11/YouTube_icon_logo.png"), "youtube": ("Youtube Together", "https://logo-logos.com/wp-content/uploads/2016/11/YouTube_icon_logo.png"),
"poker": ("Poker Night", "https://images.launchbox-app.com/21782afd-4f83-492a-b199-38404d743e57.png"), "poker": ("Poker Night", "https://images.launchbox-app.com/21782afd-4f83-492a-b199-38404d743e57.png"),
"chess": ("Chess in the Park", "https://images.discordapp.net/avatars/716382796108660826/e52b79451f4d00cb04a4aca3099210a7.png?size=512"), "chess": ("Chess in the Park", "https://images.discordapp.net/avatars/716382796108660826/e52b79451f4d00cb04a4aca3099210a7.png?size=512"),
"betrayal": ("Betrayal.io", "https://1.bp.blogspot.com/-uaqT13tY30Q/X_kqsiBJqTI/AAAAAAAADRw/R5ekQuGsO08dlBlgzXZbHktF3ioHmwmPQCLcBGAsYHQ/w1200-h630-p-k-no-nu/icon%2B%25283%2529.png"), "betrayal": ("Betrayal.io", "https://1.bp.blogspot.com/-uaqT13tY30Q/X_kqsiBJqTI/AAAAAAAADRw/R5ekQuGsO08dlBlgzXZbHktF3ioHmwmPQCLcBGAsYHQ/w1200-h630-p-k-no-nu/icon%2B%25283%2529.png"),
"fishing": ("Fishington.io", None) "fishing": ("Fishington.io", None),
"letter-tile": ("Letter Tile", None),
"word-snack": ("Word Snack", "https://image.winudf.com/v2/image/Y29tLmFwbmF4LndvcmRzbmFja19zY3JlZW5fNF8xNTM3NzE5OTkzXzAxNg/screen-4.jpg?fakeurl=1&type=.jpg"),
"doodle-crew": ("Doodle Crew", None)
} }
@commands.command(name='app', hidden = True) @commands.command(name='app', hidden = True)
@ -35,16 +36,16 @@ class PartyGames(commands.Cog, name="Partygames"):
except: except:
pass pass
try: try:
link = await self.togetherControl.create_link(ctx.author.voice.channel.id, app) link = await self.client.togetherControl.create_link(ctx.author.voice.channel.id, app)
except AttributeError: except AttributeError:
return await mySendHidden(ctx, fromSlash, "Vous devez d'abord être dans un salon vocal avant de faire cette commande.") return await mySendHidden(ctx, fromSlash, "Vous devez d'abord être dans un salon vocal avant de faire cette commande.")
except discordTogether.errors.InvalidActivityChoice: except dte.InvalidArgument:
return await mySendHidden(ctx, fromSlash, "Cette application n'est pas reconnu par Discord.") return await mySendHidden(ctx, fromSlash, "Cette application n'est pas reconnu par Discord.")
embed = discord.Embed(title = "Party Games", description = f"[Lancer *{appName}*]({link}) !") embed = discord.Embed(title = "Party Games", description = f"[Lancer *{appName}*]({link}) !")
if appImage: if appImage:
embed.set_thumbnail(url = appImage) embed.set_thumbnail(url = appImage)
embed.set_footer(text = "Ne fonctionne que sur PC pour le moment.") embed.set_footer(text = "Ne fonctionne que sur PC pour le moment.")
return await ctx.send(embed = embed) return await mySendHidden(ctx, fromSlash, embed = embed)
@commands.command(name='youtube') @commands.command(name='youtube')
@ -91,3 +92,30 @@ class PartyGames(commands.Cog, name="Partygames"):
async def __fishing(self, ctx): async def __fishing(self, ctx):
"""Slash command""" """Slash command"""
return await self._fishing(ctx, True) return await self._fishing(ctx, True)
@commands.command(name='letter-tile')
async def _letterTile(self, ctx, fromSlash = None):
"""Créer une instance "Letter Tile"."""
return await self._linkCreator(ctx, "letter-tile", fromSlash)
@cog_ext.cog_slash(name="letter-tile", description = "Créer une instance \"Letter Tile\".")
async def __letterTile(self, ctx):
"""Slash command"""
return await self._letterTile(ctx, True)
@commands.command(name='word-snack')
async def _wordSnack(self, ctx, fromSlash = None):
"""Créer une instance "Word Snack"."""
return await self._linkCreator(ctx, "word-snack", fromSlash)
@cog_ext.cog_slash(name="word-snack", description = "Créer une instance \"Word Snack\".")
async def __wordSnack(self, ctx):
"""Slash command"""
return await self._wordSnack(ctx, True)
@commands.command(name='doodle-crew')
async def _doodleCrew(self, ctx, fromSlash = None):
"""Créer une instance "Doodle Crew"."""
return await self._linkCreator(ctx, "doodle-crew", fromSlash)
@cog_ext.cog_slash(name="doodle-crew", description = "Créer une instance \"Doodle Crew\".")
async def __doodleCrew(self, ctx):
"""Slash command"""
return await self._doodleCrew(ctx, True)

View file

@ -1,9 +1,9 @@
from discord.ext import commands from discord.ext import commands, tasks
from discord_slash import cog_ext from discord_slash import cog_ext
from utils.todo import ToDo, embedListeToDo from utils.todo import ToDo, embedListeToDo
from utils.core import getMentionInString, isSlash, mySendHidden from utils.core import getMentionInString, isSlash, mySendHidden
from utils.core import addReaction, mentionToUser from utils.core import addReaction, mentionToUser
from utils.time import nowUTC from utils.time import nowUTC, timeBeforeNextSaturdayAtNineHours
def setup(client): def setup(client):
"""Adding Cog to bot""" """Adding Cog to bot"""
@ -13,8 +13,46 @@ class ToDoDiscord(commands.Cog, name="Todo"):
"""Commandes relatives aux To Do.""" """Commandes relatives aux To Do."""
def __init__(self, client): def __init__(self, client):
self.client = client self.client = client
self._todoLoop.start()
ToDo().creationTable() ToDo().creationTable()
@tasks.loop(minutes = 1) # ce temps est ignoré
async def _todoLoop(self):
"""Méthode qui se répète toute les samedis pour envoyer un récapitulatif des Todos."""
if self._todoLoop.current_loop in (0, 2): # ignore des boucles non voulue (#1 se lance au démarrage et #3 au changement de l'intervalle)
return
elif self._todoLoop.current_loop == 1: # premier vrai lancement
self._todoLoop.change_interval(hours = 168) # prochain lancement dans 1 semaine
todos = []
listIDs = []
for todo in ToDo().listAll():
if todo[0] in listIDs:
pass
else:
todos.append(todo)
listIDs.append(todo[0])
for todo in todos:
user = self.client.get_user(todo[0])
if user == None: # si l'utilisateur n'est pas trouvé
pass # on ignore l'utilisateur
channel = await user.create_dm() # envoie en DM
embed, pageMAX = await embedListeToDo(user, 1)
try:
message = await channel.send("Récapitulatif hebdomadaire de vos To Do's", embed = embed)
except: # Les DM sont fermés
pass # on ignore l'envoie du récap
if pageMAX > 1:
for emoji in ["⬅️", "➡️"]:
await message.add_reaction(emoji)
else:
await message.add_reaction("🔄")
@_todoLoop.before_loop
async def __avant_todoLoop(self):
"""Wait to start the loop until the whole bot is ready"""
await self.client.wait_until_ready()
self._todoLoop.change_interval(seconds = timeBeforeNextSaturdayAtNineHours())
@commands.command(name='todo') @commands.command(name='todo')
async def _todo(self, ctx, *todo): async def _todo(self, ctx, *todo):
"""Met en place un To Do.\n ➡ Syntaxe: {PREFIX}todo <message>""" """Met en place un To Do.\n ➡ Syntaxe: {PREFIX}todo <message>"""
@ -36,7 +74,7 @@ class ToDoDiscord(commands.Cog, name="Todo"):
todoID = ToDo().ajout(messageID, todo, now, ctx.author.id) todoID = ToDo().ajout(messageID, todo, now, ctx.author.id)
if fromSlash != True: if fromSlash != True:
await addReaction(ctx.message, 0) await addReaction(ctx.message, 0)
return await mySendHidden(ctx, fromSlash, f"To Do **`#{todoID[0][0]}`** enrengistré !") return await mySendHidden(ctx, fromSlash, f"To Do **`#{todoID[0][0]}`** enregistré !")
@cog_ext.cog_slash(name="todo", description = "Met en place un To Do.") @cog_ext.cog_slash(name="todo", description = "Met en place un To Do.")
async def __todo(self, ctx, todo): async def __todo(self, ctx, todo):
"""Slash command""" """Slash command"""

@ -1 +1 @@
Subproject commit 570730f3ae83dab0c4a8c61dde1c9094957c6ad4 Subproject commit e05be4c3fa886268cef3d19bec568c28999e03ea

View file

@ -6,6 +6,7 @@ from discord_slash import SlashCommand
from discord.ext import commands from discord.ext import commands
from utils.core import load, addReaction from utils.core import load, addReaction
from utils.page import listReaction from utils.page import listReaction
from discord_together import DiscordTogether
keys = load(["PREFIX", "TOKEN_DISCORD", "DEACTIVATE"]) keys = load(["PREFIX", "TOKEN_DISCORD", "DEACTIVATE"])
customPrefix = keys["PREFIX"] customPrefix = keys["PREFIX"]
@ -48,6 +49,7 @@ async def on_ready(update_changePresence = False):
"""Triggered when the bot is ready to operate""" """Triggered when the bot is ready to operate"""
await client.change_presence(status = discord.Status.online, activity = discord.Activity(name = f"{customPrefix}help · {len(client.guilds)} serveur{'s' if len(client.guilds) > 1 else ''}", type = discord.ActivityType.playing)) await client.change_presence(status = discord.Status.online, activity = discord.Activity(name = f"{customPrefix}help · {len(client.guilds)} serveur{'s' if len(client.guilds) > 1 else ''}", type = discord.ActivityType.playing))
if update_changePresence == False: if update_changePresence == False:
client.togetherControl = await DiscordTogether(keys["TOKEN_DISCORD"])
print("Bot prêt.") print("Bot prêt.")
@client.event @client.event

View file

@ -9,8 +9,12 @@ async def listReaction(client, payload):
""" """
if payload.emoji.name in ["⬅️", "🔄", "➡️"]: if payload.emoji.name in ["⬅️", "🔄", "➡️"]:
if payload.event_type == "REACTION_ADD": if payload.event_type == "REACTION_ADD":
if payload.member.bot == True: # vérifie que c'est pas un bot qui a réagit if payload.member: # check car pas de member en DM
return False, False if payload.member.bot == True: # vérifie que c'est pas un bot qui a réagit
return False, False
else:
if client.get_user(payload.user_id).bot == True: # vérifie que c'est pas un bot qui a réagit
return False, False
channel = client.get_channel(payload.channel_id) channel = client.get_channel(payload.channel_id)
message = await channel.fetch_message(payload.message_id) message = await channel.fetch_message(payload.message_id)
if message.author.id != client.user.id or len(message.embeds) == 0: # vérification message du bot + au moins 1 embed if message.author.id != client.user.id or len(message.embeds) == 0: # vérification message du bot + au moins 1 embed

View file

@ -129,3 +129,16 @@ def ageLayout(tuple):
for i in affichage: for i in affichage:
message = message + f", {tuple[i]} {time[i]}" message = message + f", {tuple[i]} {time[i]}"
return message[2:] return message[2:]
def timeBeforeNextSaturdayAtNineHours() -> int:
"""Envoie le nombre de secondes qu'il y a avant le prochain Samedi à 9h"""
date = datetime.today()
now = date
# prochain 9h
while date.hour != 9:
date = date + timedelta(hours = 1)
# prochain samedi
while date.strftime("%A") != "Saturday":
date = date + timedelta(days = 1)
delta = date - now
return int(delta.total_seconds())

View file

@ -47,6 +47,13 @@ class ToDo(Database):
""" """
return self.affichageResultat(self.requete(requete, userID)) return self.affichageResultat(self.requete(requete, userID))
def listAll(self):
"""Retourne la liste de tout les To Do."""
requete = """
SELECT user_id, id, todo_str, creation_int FROM todo
"""
return self.affichageResultat(self.requete(requete))
def appartenance(self, userID: int, id: int): def appartenance(self, userID: int, id: int):
"""Vérifie qu'un To Do appartiens à un utilisateur. Renvois False si le To Do n'existe pas.""" """Vérifie qu'un To Do appartiens à un utilisateur. Renvois False si le To Do n'existe pas."""
requete = """ requete = """