premier commit
This commit is contained in:
commit
15716f8ea9
9 changed files with 1500 additions and 0 deletions
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
UPDATE/
|
||||
.dockerignore
|
||||
Dockerfile
|
||||
setup.py
|
||||
cogs/music_old.py
|
108
cogs/fun.py
Normal file
108
cogs/fun.py
Normal file
|
@ -0,0 +1,108 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
from random import randint, choice
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(Fun(client))
|
||||
|
||||
class Fun(commands.Cog):
|
||||
"""Commandes plutôt fun."""
|
||||
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
|
||||
@commands.command(name='iq')
|
||||
async def _iq(self, ctx, *, user = '0'):
|
||||
"""Calcule ton IQ.\n ➡ Syntaxe: .iq [user]"""
|
||||
if user == '0':
|
||||
user = ctx.author
|
||||
await ctx.message.add_reaction(emoji = '✅')
|
||||
return await ctx.send(f"T'as {randint(randint(-100,0),220)} IQ {user.mention} !")
|
||||
else:
|
||||
try:
|
||||
user2 = user
|
||||
user2 = user2[2:-1]
|
||||
user2 = user2.replace("!","")
|
||||
user2 = int(user2)
|
||||
user2 = self.client.get_user(user2)
|
||||
KassouBot = self.client.get_user(740140888373854269)
|
||||
if user2.id == KassouBot.id:
|
||||
await ctx.message.add_reaction(emoji = '✅')
|
||||
return await ctx.send(f"Bah... pas ouf... j'ai juste 100000 IQ :/")
|
||||
else:
|
||||
await ctx.message.add_reaction(emoji = '✅')
|
||||
message = await ctx.send("...")
|
||||
return await message.edit(content = f"{user2.mention} a {randint(randint(-100,0),220)} IQ !")
|
||||
except:
|
||||
await ctx.message.add_reaction(emoji = '✅')
|
||||
message = await ctx.send("...")
|
||||
return await message.edit(content = f"{user} a {randint(randint(-100,0),220)} IQ !")
|
||||
|
||||
@commands.command(name='love')
|
||||
async def _love(self, ctx, *users: discord.Member):
|
||||
"""Découvre la probabilité que ces deux personnes se mettent en couple.\n ➡ Syntaxe: .love <User1> <User2>"""
|
||||
if len(users) == 2 or len(users) == 1:
|
||||
UneDemande = False
|
||||
if len(users) == 1:
|
||||
U = users
|
||||
users = []
|
||||
users.append(U[0])
|
||||
users.append(ctx.author)
|
||||
UneDemande = True
|
||||
if users[0] == users[1]:
|
||||
await ctx.message.add_reaction(emoji = '✅')
|
||||
return await ctx.send("Je suis sûr que cette personne s'aime ! :angry:")
|
||||
if users[0].nick:
|
||||
user1 = list(users[0].nick)
|
||||
else:
|
||||
user1 = list(users[0].name)
|
||||
if users[1].nick:
|
||||
user2 = list(users[1].nick)
|
||||
else:
|
||||
user2 = list(users[1].name)
|
||||
user1_CALC = self._retirerDoublons([x.lower() for x in user1])
|
||||
user2_CALC = self._retirerDoublons([x.lower() for x in user2])
|
||||
coef_amour = 0
|
||||
if len(user1_CALC) > len(user2_CALC):
|
||||
taille_du_pls_grand = len(user1_CALC)
|
||||
taille_du_ms_grand = len(user2_CALC)
|
||||
else:
|
||||
taille_du_pls_grand = len(user2_CALC)
|
||||
taille_du_ms_grand = len(user1_CALC)
|
||||
coef_amour = round(float(len(list(set(user1_CALC).intersection(user2_CALC))) / taille_du_pls_grand),1) * 100 + ((taille_du_pls_grand-taille_du_ms_grand) * 1.5) * 1.7
|
||||
if coef_amour > 100:
|
||||
coef_amour = 100
|
||||
if UneDemande == True:
|
||||
await ctx.message.add_reaction(emoji = '✅')
|
||||
return await ctx.send(f"Tu as {coef_amour}% de chance de te mettre en couple avec {''.join(user1)}")
|
||||
await ctx.message.add_reaction(emoji = '✅')
|
||||
await ctx.send(f"{''.join(user1)} et {''.join(user2)} ont {coef_amour}% de chance de se mettre en couple !")
|
||||
else:
|
||||
await ctx.message.add_reaction(emoji = '❌')
|
||||
await ctx.send("Erreur! Syntaxe : `.love <User1> [User2]`\n")
|
||||
def _retirerDoublons(self, liste):
|
||||
Newliste = []
|
||||
for element in liste:
|
||||
if element not in Newliste:
|
||||
Newliste.append(element)
|
||||
return Newliste
|
||||
@_love.error
|
||||
async def _love_error(self, ctx, error):
|
||||
await ctx.send(str(error).replace('Member "', "Le membre **").replace('" not found', "** n'as pas été trouvé."))
|
||||
|
||||
@commands.command(name='8ball', aliases=['8b', '8balls'])
|
||||
async def _8ball(self, ctx, *, question):
|
||||
"""Répond à ta question 🔮.\n ➡ Syntaxe: .8ball/8b <question>"""
|
||||
reponses=["c'est sûr.","il en est décidément ainsi.","incontestablement.","oui sans aucun doute.","tu peux t'y fier.","tel que je le vois, oui.","c'est le plus probable.",
|
||||
"cela montre de bonnes perspectives.","certes.","les signes indiquent que oui.","ma réponse est oui.","ta question est trop floue, réessaie.","redemandes plus tard stp.",
|
||||
"je ferais mieux de pas te le dire maintenant...","je ne peux pas le prédire actuellement :/","concentre-toi et redemande.","n'y comptes pas trop.","ma réponse est non.",
|
||||
"mes sources disent que non.", "les perspectives ne sont pas si bonnes...","c'est très douteux."]
|
||||
await ctx.send(f"{ctx.author.mention}, {choice(reponses)}")
|
||||
@_8ball.error
|
||||
async def _8ball_error(self, ctx, error):
|
||||
if str(error) == "question is a required argument that is missing.":
|
||||
await ctx.send("Mauvaise syntaxe : `.8ball/8b/8balls <question>`.")
|
||||
|
||||
@commands.command(name='pileouface', aliases=['pf'])
|
||||
async def _pileouface(self, ctx):
|
||||
return await ctx.send(f"{'Pile' if randint(0,1) == 1 else 'Face'} !")
|
93
cogs/games.py
Normal file
93
cogs/games.py
Normal file
|
@ -0,0 +1,93 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
from random import randint, choice
|
||||
import asyncio
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(Games(client))
|
||||
|
||||
class Games(commands.Cog):
|
||||
"""Commandes relatives aux jeux."""
|
||||
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
self.guessing_game = {}
|
||||
|
||||
@commands.command(name='chifumi', aliases = ["shifumi", "ppc"])
|
||||
async def _chifumi(self, ctx, *, choix):
|
||||
"""Un simple Chifumi contre le bot.\n ➡ Syntaxe: .chifumi/shifumi/ppc <pierre/papier/ciseaux>"""
|
||||
|
||||
choix_jeu = ["Pierre ✊", "Papier 🧻", "Ciseaux ✂"]
|
||||
orditxt = choice(choix_jeu)
|
||||
ordi = choix_jeu.index(orditxt)
|
||||
|
||||
PIERRE = 0
|
||||
PAPIER = 1
|
||||
CISEAUX = 2
|
||||
|
||||
choix = choix.lower()
|
||||
if choix == "pierre":
|
||||
choix = PIERRE
|
||||
if choix == "papier" or choix == "feuille":
|
||||
choix = PAPIER
|
||||
if choix == "ciseaux" or choix == "ciseau":
|
||||
choix = CISEAUX
|
||||
|
||||
description = (f"{choix_jeu[choix][:-1]} VS {choix_jeu[ordi][:-1]}\n\n**"
|
||||
f"{('Égalité !', 'Tu as perdu !', 'Tu as gagné !')[(choix != ordi) + ((choix > ordi and ordi +1 == choix) or (choix < ordi and choix + ordi == 2))]}**")
|
||||
|
||||
embed = discord.Embed(title = f"{choix_jeu[choix][-1:]}VS {choix_jeu[ordi][-1:]}", description = description)
|
||||
embed.set_author(name = ctx.author.name, icon_url = ctx.author.avatar_url)
|
||||
await ctx.send(embed = embed)
|
||||
await ctx.message.add_reaction(emoji = '✅')
|
||||
@_chifumi.error
|
||||
async def _chifumi_error(self, ctx, error):
|
||||
await ctx.send("Mauvaise syntaxe : `.chifumi/shifumi/ppc <pierre/papier/ciseaux>`.")
|
||||
|
||||
|
||||
@commands.command(name='plusoumoins', aliases = ['+ou-', '+-'])
|
||||
async def _plusoumoins(self, ctx):
|
||||
"""Un plus ou moins entre 1 et 100.\n ➡ Syntaxe: .plusoumoins/+ou-/+-"""
|
||||
if str(ctx.author.id) in self.guessing_game:
|
||||
return await ctx.send("Tu es déjà en partie.")
|
||||
guess = 5
|
||||
self.guessing_game[str(ctx.author.id)] = guess
|
||||
number = randint(1,100)
|
||||
message = f"Choisis un nombre entre 1 et 100 {ctx.author.mention}."
|
||||
await ctx.send(message)
|
||||
while self.guessing_game[str(ctx.author.id)] != 0:
|
||||
try:
|
||||
def check(message):
|
||||
if message.author.bot == False:
|
||||
return str(message.author.id) in self.guessing_game
|
||||
msg = await self.client.wait_for('message', check = check, timeout = 30)
|
||||
except asyncio.TimeoutError:
|
||||
del self.guessing_game[str(ctx.author.id)]
|
||||
return await ctx.send(f"Tu as mis trop de temps a répondre {ctx.author.mention}. La réponse était {number}.")
|
||||
if msg.author == ctx.author:
|
||||
if msg.content == "stop":
|
||||
del self.guessing_game[str(ctx.author.id)]
|
||||
return await ctx.send(f"Fin du plus ou moins {ctx.author.mention}. La réponse était {number}.")
|
||||
try:
|
||||
attempt = int(msg.content)
|
||||
if attempt > number:
|
||||
if guess-1 != 0:
|
||||
await ctx.send(f"J'pense que c'est moins {ctx.author.mention}... Il te reste {guess-1} essai{'s' if guess-1>1 else ''}.")
|
||||
guess -= 1
|
||||
self.guessing_game[str(ctx.author.id)] = guess
|
||||
if guess != 0:
|
||||
await ctx.send(message)
|
||||
elif attempt < number:
|
||||
if guess-1 != 0:
|
||||
await ctx.send(f"J'pense que c'est plus {ctx.author.mention}... Il te reste {guess-1} essai{'s' if guess-1>1 else ''}.")
|
||||
guess -=1
|
||||
self.guessing_game[str(ctx.author.id)] = guess
|
||||
if guess != 0:
|
||||
await ctx.send(message)
|
||||
elif attempt == number:
|
||||
del self.guessing_game[str(ctx.author.id)]
|
||||
return await ctx.send(f"Tu as trouvé {ctx.author.mention}, bien joué !")
|
||||
except:
|
||||
await ctx.send(f"Erreur dans la réponse {ctx.author.mention}, merci de n'écrire qu'un nombre. Tapez `stop` pour arrêter le jeu.")
|
||||
del self.guessing_game[str(ctx.author.id)]
|
||||
await ctx.send(f"T'as pas trouvé {ctx.author.mention}... dommage, c'était {number}.")
|
67
cogs/help.py
Normal file
67
cogs/help.py
Normal file
|
@ -0,0 +1,67 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
from random import randint
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(Help(client))
|
||||
|
||||
class Help(commands.Cog):
|
||||
"""Listes des commandes et/ou catégories."""
|
||||
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
self.client.remove_command("help")
|
||||
|
||||
@commands.command(name='help')
|
||||
async def _help(self, ctx, *cog):
|
||||
"""Affiche toutes les commandes du bot.\n ➡ Syntaxe: .help [catégorie]"""
|
||||
if not cog:
|
||||
"""Liste des Cog"""
|
||||
halp=discord.Embed(title = 'Liste des catégories et commandes sans catégorie',
|
||||
description = f'Utilisez `{ctx.prefix}help [catégorie]` pour en savoir plus sur elles et leur commande.',
|
||||
color = randint(0, 0xFFFFFF))
|
||||
for name_cog in self.client.cogs:
|
||||
liste_cmds = ""
|
||||
nb_cmds = 0
|
||||
for cmds in self.client.get_cog(name_cog).get_commands():
|
||||
if not cmds.hidden:
|
||||
liste_cmds += f", `{ctx.prefix}{cmds.name}`"
|
||||
nb_cmds += 1
|
||||
if name_cog != "Help":
|
||||
halp.add_field(name = f'**{name_cog} — {nb_cmds}**', value = liste_cmds[2:], inline = False)
|
||||
cmds_desc = ''
|
||||
for y in self.client.walk_commands():
|
||||
if not y.cog_name and not y.hidden:
|
||||
cmds_desc += (f'{ctx.prefix}{y.name} - {y.help}\n ')
|
||||
|
||||
if len(cmds_desc) > 1:
|
||||
halp.add_field(name = 'Commandes sans catégorie', value = cmds_desc[0:len(cmds_desc)-1], inline = False)
|
||||
await ctx.message.add_reaction(emoji = '✅')
|
||||
await ctx.send(embed = halp)
|
||||
else:
|
||||
"""Avertissement si il y a trop d'arguments dans la variable cog"""
|
||||
if len(cog) > 1:
|
||||
halp = discord.Embed(title = 'Erreur !', description = "Tu as renseigné trop d'arguments !", color = 0xC41B1B)
|
||||
await ctx.send(embed = halp)
|
||||
else:
|
||||
"""Liste des commandes avec cogs."""
|
||||
cog = [item.capitalize() for item in cog]
|
||||
found = False
|
||||
for x in self.client.cogs:
|
||||
for y in cog:
|
||||
if x == y:
|
||||
halp = discord.Embed(title = f'{cog[0]} - Liste des commandes', description = self.client.cogs[cog[0]].__doc__, color = randint(0, 0xFFFFFF))
|
||||
for c in self.client.get_cog(y).get_commands():
|
||||
if not c.hidden:
|
||||
cmds_help = str(c.help).split("\n")
|
||||
del cmds_help[0]
|
||||
backslash = '\n'
|
||||
halp.add_field(name = f"`{ctx.prefix}{c.name}` - {str(c.help).split(backslash)[0]}", value = f"{''.join(cmds_help)}\u200b", inline = False)
|
||||
found = True
|
||||
if not found:
|
||||
"""Rappel si le cog n'existe pas."""
|
||||
await ctx.message.add_reaction(emoji = '❌')
|
||||
halp = discord.Embed(title = 'Erreur !', description = f"Qu'est ce que {cog[0]} ?", color = 0xC41B1B)
|
||||
else:
|
||||
await ctx.message.add_reaction(emoji = '✅')
|
||||
await ctx.send('', embed = halp)
|
139
cogs/internet.py
Normal file
139
cogs/internet.py
Normal file
|
@ -0,0 +1,139 @@
|
|||
import discord, praw, json, requests, datetime
|
||||
from discord.ext import commands
|
||||
from random import randint, choice
|
||||
import time
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(Internet(client))
|
||||
|
||||
class Internet(commands.Cog):
|
||||
"""Commandes relatives à ce qui provient d'internet."""
|
||||
|
||||
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_message(self, message):
|
||||
if message.channel.id == 770805818487865404 or message.channel.id == 772239638240165928: # Le groupe de l'amour ❤❤ -- channel chien/chat
|
||||
chiens = ["dog", "chien", "potichien"]
|
||||
chats = ["kat", "mace", "kater", "katze", "sinta", "minoos", "cat", "qitt", "besseh", "katu", "caun", "kazh",
|
||||
"bisig", "moggy", "kotka", "maow", "gat", "we'sa", "guigna", "kodkod", "mao", "koyangi", "ghjattu", "míw", "pussi",
|
||||
"gato", "gata", "kato", "kass", "domadh", "demmat", "kissa", "chat", "minou", "piscín", "cath", "k'at'a", "muca", "gali",
|
||||
"gatos", "popoki", "kike", "chatul", "chatula", "billa", "kat poes", "macska", "cica", "kutjing", "kucing", "köttur",
|
||||
"gatto", "gattina", "neko", "chma", "pising", "feles", "felix", "kakis", "katé", "qattus", "qattusa", "ngeru", "miz", "felino",
|
||||
"felina", "muur", "katt", "shimii", "billi", "gorbe", "pusa", "kot", "giat", "pisica", "koshka", "pusi", "macka", "mizhu",
|
||||
"kotsur", "bisad", "büsi", "chatz", "paka", "muc", "poonai", "puunay", "kocour", "kocka", "maa-oh", "kedi", "kit", "con mêo",
|
||||
"tchèt", "mouss", "ologbo", "kats", "猫", "кот", "고양이", "poticha", "😼"]
|
||||
if message.content.lower() in chiens:
|
||||
await self._dog(await self.client.get_context(message))
|
||||
if message.content.lower() in chats:
|
||||
await self._cat(await self.client.get_context(message))
|
||||
|
||||
@commands.command(name='memes', aliases = ['meme'])
|
||||
async def _memes(self, ctx, *, args = ""):
|
||||
"""Envois un meme de reddit.\n ➡ Syntaxe: .memes/meme [subreddit]"""
|
||||
try:
|
||||
reddit = praw.Reddit(client_id = 'nHPaCR8L_jlmwQ', client_secret = 'tSCjb4QvdiNyCYKmW35SEWhjV8w', user_agent = 'disreddit /u/mylloon, http://localhost:8080')
|
||||
|
||||
if args != "": # si il y a un arg différent d'un meme
|
||||
subredditchoix = args
|
||||
|
||||
else: # si il n'y a pas d'arguments
|
||||
subredditchoix = choice(['memes', 'anime_irl', 'goodanimemes', 'BikiniclienttomTwitter', 'dankmemes', 'DeepFriedMemes',
|
||||
'educationalmemes', 'funny', 'marvelmemes', 'me_irl', 'meme', 'MemeEconomy', 'Memes_Of_The_Dank', 'MinecraftMemes',
|
||||
'physicsmemes', 'reactiongifs', 'blackpeopletwitter', 'metal_me_irl', 'bee_irl', '195',
|
||||
'shittyadviceanimals', 'meirl', '2meirl4meirl', 'AdviceAnimals', 'weirdmemes'])
|
||||
|
||||
memes_submissions = reddit.subreddit(subredditchoix).hot()
|
||||
post_to_pick = randint(1, 10)
|
||||
for i in range(0, post_to_pick): # i pas important
|
||||
i = i #retire l'erreur sur vscode
|
||||
submission = next(x for x in memes_submissions if not x.stickied)
|
||||
|
||||
image = ["png", "jpg", "jpeg", "bmp", "gif"]
|
||||
if submission.url[-3:] in image:
|
||||
embed = discord.Embed(title = f"r/{subredditchoix} pour {ctx.author.name}", color = randint(0, 0xFFFFFF), description = f"[lien du meme]({submission.url})")
|
||||
embed.set_footer(text = f"Meme de Reddit")
|
||||
embed.set_image(url = submission.url)
|
||||
message = await ctx.send(embed = embed)
|
||||
else:
|
||||
await ctx.send(f"```r/{subredditchoix} pour {ctx.author.name}```\n{submission.url}")
|
||||
message = await ctx.send("```Meme de Reddit```")
|
||||
await ctx.message.add_reaction(emoji = '✅')
|
||||
await message.add_reaction('👍')
|
||||
return await message.add_reaction('👎')
|
||||
|
||||
except Exception as error:
|
||||
print(f"args: {args}, subreddit: {subredditchoix}, error: {error}")
|
||||
await ctx.message.add_reaction(emoji = '❌')
|
||||
return await ctx.send(f"Ce subreddit est interdit, mis en quarantaine ou n'existe pas. ({subredditchoix})")
|
||||
|
||||
def _random_image(self, link):
|
||||
temps_requete = int(round(time.time() * 1000))
|
||||
try:
|
||||
request_data = requests.get(link)
|
||||
except Exception as e:
|
||||
raise Exception(f"Une erreur s'est produite lors de la tentative de demande de l'API {link} : {e}")
|
||||
|
||||
if not request_data.status_code == 200:
|
||||
raise Exception(f"Code HTTP {request_data.status_code} au lieu de HTTP 200 à l'appel de {link} : {request_data.text}")
|
||||
|
||||
try:
|
||||
json_data = json.loads(request_data.text)
|
||||
except Exception as e:
|
||||
raise Exception(f"Erreur lors de la transformation les données de {link} en json : {e}")
|
||||
|
||||
temps_requete = int(round(time.time() * 1000)) - temps_requete
|
||||
return (json_data, temps_requete)
|
||||
|
||||
@commands.command(name='cat', aliases = ['chat'])
|
||||
async def _cat(self, ctx):
|
||||
"""Te montre un magnifique chat\n ➡ Syntaxe: .cat/chat"""
|
||||
|
||||
if ctx.author.nick:
|
||||
name = f"{ctx.author.nick} ({ctx.author.name}#{ctx.author.discriminator})"
|
||||
else:
|
||||
name = f"{ctx.author.name}"
|
||||
embed = discord.Embed(title = f"Poticha pour {name}", colour = randint(0, 0xFFFFFF))
|
||||
cat = self._random_image("http://aws.random.cat/meow")
|
||||
embed.set_image(url = cat[0]['file'])
|
||||
embed.set_footer(text = f"random.cat a pris {cat[1]} ms.")
|
||||
await ctx.message.add_reaction(emoji = '✅')
|
||||
message = await ctx.send(embed=embed)
|
||||
return await message.add_reaction('❤️')
|
||||
|
||||
@commands.command(name='dog', aliases = ['chien'])
|
||||
async def _dog(self, ctx):
|
||||
"""Te montre un magnifique chien\n ➡ Syntaxe: .dog/chien"""
|
||||
|
||||
if ctx.author.nick:
|
||||
name = f"{ctx.author.nick} ({ctx.author.name}#{ctx.author.discriminator})"
|
||||
else:
|
||||
name = f"{ctx.author.name}"
|
||||
embed = discord.Embed(title = f"Potichien pour {name}", colour = randint(0, 0xFFFFFF))
|
||||
dog = self._random_image("https://dog.ceo/api/breeds/image/random")
|
||||
embed.set_image(url = dog[0]['message'])
|
||||
embed.set_footer(text = f"dog.ceo a pris {dog[1]} ms.")
|
||||
await ctx.message.add_reaction(emoji = '✅')
|
||||
message = await ctx.send(embed=embed)
|
||||
return await message.add_reaction('❤️')
|
||||
|
||||
@commands.command(name='sexe', aliases=['sexes', 'nude', 'nudes', 'nsfw'])
|
||||
async def _sexe(self, ctx, *, choice_of_nsfw = None):
|
||||
"""Envois une image coquine. (NSFW)\n ➡ Syntaxe: .sexe/sexes/nude/nudes [butts/boobs]"""
|
||||
liste_hot = ['butts', 'boobs']
|
||||
if choice_of_nsfw in liste_hot:
|
||||
pass
|
||||
else:
|
||||
choice_of_nsfw = choice(liste_hot)
|
||||
if ctx.channel.is_nsfw():
|
||||
embed = discord.Embed(title = f"{choice_of_nsfw.capitalize()} pour {ctx.author.name}", colour = randint(0, 0xFFFFFF))
|
||||
nsfw = self._random_image(f'http://api.o{choice_of_nsfw}.ru/noise/')
|
||||
embed.set_image(url = f"http://media.o{choice_of_nsfw}.ru/{nsfw[0][0]['preview']}")
|
||||
embed.set_footer(text = f"o{choice_of_nsfw}.ru a pris {nsfw[1]} ms.")
|
||||
await ctx.message.add_reaction(emoji = '✅')
|
||||
await ctx.send(embed = embed)
|
||||
else:
|
||||
await ctx.message.add_reaction(emoji = '❌')
|
||||
await ctx.send(f"Désolé mais je n'envois ce genre de message seulement dans les salons NSFW !")
|
565
cogs/music.py
Normal file
565
cogs/music.py
Normal file
|
@ -0,0 +1,565 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Copyright (c) 2019 Valentin B.
|
||||
|
||||
https://gist.github.com/vbe0201/ade9b80f2d3b64643d854938d40a0a2d
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import functools
|
||||
import itertools
|
||||
import math
|
||||
import random
|
||||
|
||||
import discord
|
||||
import youtube_dl
|
||||
from async_timeout import timeout
|
||||
from discord.ext import commands
|
||||
|
||||
from random import randint
|
||||
import lyricsgenius
|
||||
import time
|
||||
|
||||
# Genius API
|
||||
genius = lyricsgenius.Genius("gmAB9NLNoDACxvcf5IjJKVVgbYx3UJ8CZmdQkFOitRfyFewI6qvZFe62x6EUETpK")
|
||||
|
||||
# Silence useless bug reports messages
|
||||
youtube_dl.utils.bug_reports_message = lambda: ''
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(Music(client))
|
||||
|
||||
class VoiceError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class YTDLError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class YTDLSource(discord.PCMVolumeTransformer):
|
||||
YTDL_OPTIONS = {
|
||||
'format': 'bestaudio/best',
|
||||
'extractaudio': True,
|
||||
'audioformat': 'mp3',
|
||||
'outtmpl': '%(extractor)s-%(id)s-%(title)s.%(ext)s',
|
||||
'restrictfilenames': True,
|
||||
'noplaylist': True,
|
||||
'nocheckcertificate': True,
|
||||
'ignoreerrors': False,
|
||||
'logtostderr': False,
|
||||
'quiet': True,
|
||||
'no_warnings': True,
|
||||
'default_search': 'auto',
|
||||
'source_address': '0.0.0.0',
|
||||
}
|
||||
|
||||
FFMPEG_OPTIONS = {
|
||||
'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5',
|
||||
'options': '-vn',
|
||||
}
|
||||
|
||||
ytdl = youtube_dl.YoutubeDL(YTDL_OPTIONS)
|
||||
|
||||
def __init__(self, ctx: commands.Context, source: discord.FFmpegPCMAudio, *, data: dict, volume: float = 0.5):
|
||||
super().__init__(source, volume)
|
||||
|
||||
self.requester = ctx.author
|
||||
self.channel = ctx.channel
|
||||
self.data = data
|
||||
|
||||
self.uploader = data.get('uploader')
|
||||
self.uploader_url = data.get('uploader_url')
|
||||
date = data.get('upload_date')
|
||||
self.upload_date = date[6:8] + '.' + date[4:6] + '.' + date[0:4]
|
||||
self.title = data.get('title')
|
||||
self.thumbnail = data.get('thumbnail')
|
||||
self.description = data.get('description')
|
||||
self.duration = self.parse_duration(int(data.get('duration')))
|
||||
self.tags = data.get('tags')
|
||||
self.url = data.get('webpage_url')
|
||||
self.views = data.get('view_count')
|
||||
self.likes = data.get('like_count')
|
||||
self.dislikes = data.get('dislike_count')
|
||||
self.stream_url = data.get('url')
|
||||
|
||||
def __str__(self):
|
||||
return f"**{self.title}** de **{self.uploader}**"
|
||||
|
||||
@classmethod
|
||||
async def create_source(cls, ctx: commands.Context, search: str, *, loop: asyncio.BaseEventLoop = None):
|
||||
loop = loop or asyncio.get_event_loop()
|
||||
|
||||
partial = functools.partial(cls.ytdl.extract_info, search, download=False, process=False)
|
||||
data = await loop.run_in_executor(None, partial)
|
||||
|
||||
if data is None:
|
||||
raise YTDLError(f"Je n'ai rien trouvé qui corresponde à `{search}`")
|
||||
|
||||
if 'entries' not in data:
|
||||
process_info = data
|
||||
else:
|
||||
process_info = None
|
||||
for entry in data['entries']:
|
||||
if entry:
|
||||
process_info = entry
|
||||
break
|
||||
|
||||
if process_info is None:
|
||||
raise YTDLError(f"Je n'ai rien trouvé qui corresponde à `{search}`")
|
||||
|
||||
webpage_url = process_info['webpage_url']
|
||||
partial = functools.partial(cls.ytdl.extract_info, webpage_url, download=False)
|
||||
processed_info = await loop.run_in_executor(None, partial)
|
||||
|
||||
if processed_info is None:
|
||||
raise YTDLError(f"Impossible d'obtenir `{webpage_url}`")
|
||||
|
||||
if "entries" not in processed_info:
|
||||
info = processed_info
|
||||
else:
|
||||
info = None
|
||||
while info is None:
|
||||
try:
|
||||
info = processed_info['entries'].pop(0)
|
||||
except IndexError:
|
||||
raise YTDLError(f"Aucune correspondances pour `{webpage_url}`")
|
||||
|
||||
return cls(ctx, discord.FFmpegPCMAudio(info['url'], **cls.FFMPEG_OPTIONS), data=info)
|
||||
|
||||
@staticmethod
|
||||
def parse_duration(duration: int):
|
||||
minutes, seconds = divmod(duration, 60)
|
||||
hours, minutes = divmod(minutes, 60)
|
||||
days, hours = divmod(hours, 24)
|
||||
|
||||
duration = []
|
||||
if days > 0:
|
||||
duration.append(f"{days} jours,{'' if days <= 1 else 's'}")
|
||||
if hours > 0:
|
||||
duration.append(f"{hours} H,{'' if hours <= 1 else 's'}")
|
||||
if minutes > 0:
|
||||
duration.append(f"{minutes} min{'' if minutes <= 1 else 's'}")
|
||||
if seconds > 0:
|
||||
duration.append(f"{seconds} sec{'' if seconds <= 1 else 's'}")
|
||||
|
||||
return ' '.join(duration)
|
||||
|
||||
|
||||
class Song:
|
||||
__slots__ = ('source', 'requester')
|
||||
|
||||
def __init__(self, source: YTDLSource):
|
||||
self.source = source
|
||||
self.requester = source.requester
|
||||
|
||||
def create_embed(self):
|
||||
embed = (discord.Embed(title="Joue",
|
||||
description=f"\n[{self.source.title}]({self.source.url})\n",
|
||||
color=randint(0, 0xFFFFFF))
|
||||
.add_field(name="Durée", value=self.source.duration)
|
||||
.add_field(name="Demandé par", value=self.requester.mention)
|
||||
.add_field(name="Chaîne", value=f"[{self.source.uploader}]({self.source.uploader_url})")
|
||||
.set_thumbnail(url=self.source.thumbnail))
|
||||
|
||||
return embed
|
||||
|
||||
def title(self):
|
||||
return self.source.title
|
||||
|
||||
|
||||
class SongQueue(asyncio.Queue):
|
||||
def __getitem__(self, item):
|
||||
if isinstance(item, slice):
|
||||
return list(itertools.islice(self._queue, item.start, item.stop, item.step))
|
||||
else:
|
||||
return self._queue[item]
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._queue.__iter__())
|
||||
|
||||
def __len__(self):
|
||||
return self.qsize()
|
||||
|
||||
def clear(self):
|
||||
self._queue.clear()
|
||||
|
||||
def shuffle(self):
|
||||
random.shuffle(self._queue)
|
||||
|
||||
def remove(self, index: int):
|
||||
del self._queue[index]
|
||||
|
||||
|
||||
class VoiceState:
|
||||
def __init__(self, client: commands.bot, ctx: commands.Context):
|
||||
self.client = client
|
||||
self._ctx = ctx
|
||||
|
||||
self.current = None
|
||||
self.voice = None
|
||||
self.next = asyncio.Event()
|
||||
self.songs = SongQueue()
|
||||
|
||||
self._loop = False
|
||||
self._volume = 1.0
|
||||
|
||||
self.audio_player = client.loop.create_task(self.audio_player_task())
|
||||
|
||||
def __del__(self):
|
||||
self.audio_player.cancel()
|
||||
|
||||
@property
|
||||
def loop(self):
|
||||
return self._loop
|
||||
|
||||
@loop.setter
|
||||
def loop(self, value: bool):
|
||||
self._loop = value
|
||||
|
||||
@property
|
||||
def volume(self):
|
||||
return self._volume
|
||||
|
||||
@volume.setter
|
||||
def volume(self, value: float):
|
||||
self._volume = value
|
||||
|
||||
@property
|
||||
def is_playing(self):
|
||||
return self.voice and self.current
|
||||
|
||||
async def audio_player_task(self):
|
||||
while True:
|
||||
self.next.clear()
|
||||
|
||||
if not self.loop:
|
||||
# Try to get the next song within 3 minutes.
|
||||
# If no song will be added to the queue in time,
|
||||
# the player will disconnect due to performance
|
||||
# reasons.
|
||||
try:
|
||||
async with timeout(180): # 3 minutes
|
||||
self.current = await self.songs.get()
|
||||
except asyncio.TimeoutError:
|
||||
self.client.loop.create_task(self.stop())
|
||||
return
|
||||
|
||||
self.current.source.volume = self._volume
|
||||
self.voice.play(self.current.source, after=self.play_next_song)
|
||||
await self.current.source.channel.send(embed=self.current.create_embed())
|
||||
|
||||
await self.next.wait()
|
||||
|
||||
def play_next_song(self, error=None):
|
||||
if error:
|
||||
raise VoiceError(str(error))
|
||||
|
||||
self.next.set()
|
||||
|
||||
def skip(self):
|
||||
if self.is_playing:
|
||||
self.voice.stop()
|
||||
|
||||
async def stop(self):
|
||||
self.songs.clear()
|
||||
|
||||
if self.voice:
|
||||
await self.voice.disconnect()
|
||||
self.voice = None
|
||||
|
||||
|
||||
class Music(commands.Cog):
|
||||
"""Commandes relatives à la musique - © vbe0201."""
|
||||
def __init__(self, client: commands.bot):
|
||||
self.client = client
|
||||
self.voice_states = {}
|
||||
|
||||
def get_voice_state(self, ctx: commands.Context):
|
||||
state = self.voice_states.get(ctx.guild.id)
|
||||
if not state:
|
||||
state = VoiceState(self.client, ctx)
|
||||
self.voice_states[ctx.guild.id] = state
|
||||
|
||||
return state
|
||||
|
||||
def cog_unload(self):
|
||||
for state in self.voice_states.values():
|
||||
self.client.loop.create_task(state.stop())
|
||||
|
||||
def cog_check(self, ctx: commands.Context):
|
||||
if not ctx.guild:
|
||||
raise commands.NoPrivateMessage("Je ne fais pas de musiques en DM.")
|
||||
|
||||
return True
|
||||
|
||||
async def cog_before_invoke(self, ctx: commands.Context):
|
||||
ctx.voice_state = self.get_voice_state(ctx)
|
||||
|
||||
async def cog_command_error(self, ctx: commands.Context, error: commands.CommandError):
|
||||
await ctx.send(f"Une erreur est survenue : {str(error)}")
|
||||
|
||||
@commands.command(name='join', aliases=['j'], invoke_without_subcommand=True)
|
||||
async def _summon(self, ctx: commands.Context, *, channel: discord.VoiceChannel = None):
|
||||
"""Se connecte au salon vocal.\n ➡ Syntaxe: .connect/join"""
|
||||
|
||||
if not channel and not ctx.author.voice:
|
||||
await ctx.send("Aucun channel à rejoindre. Connecte toi dans un vocal ou donne-moi son id.")
|
||||
raise VoiceError("Vous n'êtes pas connecté à un channel vocal et n'avez spécifié aucun channel à rejoindre.")
|
||||
|
||||
destination = channel or ctx.author.voice.channel
|
||||
await ctx.send(f":thumbsup: **Connecté à __{destination}__**")
|
||||
if ctx.voice_state.voice:
|
||||
await ctx.voice_state.voice.move_to(destination)
|
||||
return
|
||||
|
||||
ctx.voice_state.voice = await destination.connect()
|
||||
|
||||
@commands.command(name='stop', aliases=['disconnect', 'dc'])
|
||||
async def _leave(self, ctx: commands.Context):
|
||||
"""Arrête la chanson en cours de lecture et quitte le salon vocal.\n ➡ Syntaxe: .disconnect/dc/stop"""
|
||||
|
||||
if not ctx.voice_state.voice:
|
||||
embed = discord.Embed(description = "Tape `.play <chanson>` pour jouer quelque chose ou `.join [id]` pour me connecter à un salon vocal.", color = 0xC41B1B)
|
||||
embed.set_author(name = "Je ne suis connecté à aucun vocal.")
|
||||
return await ctx.send(embed = embed)
|
||||
|
||||
await ctx.voice_state.stop()
|
||||
del self.voice_states[ctx.guild.id]
|
||||
await ctx.send("📭 **Déconnecté du salon**")
|
||||
|
||||
@commands.command(name='volume', aliases=['vol'])
|
||||
async def _volume(self, ctx: commands.Context, *, volume: int = False):
|
||||
"""Modifie le volume du bot (entre 1 et 100).\n ➡ Syntaxe: .volume/vol [1;100]"""
|
||||
|
||||
if not ctx.voice_state.is_playing:
|
||||
return await ctx.send("Rien n'est joué pour le moment.")
|
||||
|
||||
if not volume:
|
||||
return await ctx.send(f"Le volume est à **{ctx.voice_state.volume * 100}%**")
|
||||
|
||||
if 0 > volume > 100:
|
||||
return await ctx.send("Le volume doit être compris entre 0 et 100.")
|
||||
|
||||
ctx.voice_state.volume = volume / 100
|
||||
await ctx.send(f"Volume réglé sur **{volume}%**")
|
||||
|
||||
@commands.command(name='now', aliases=['current', 'playing', 'np'])
|
||||
async def _now(self, ctx: commands.Context):
|
||||
"""Affiche des informations sur la chanson en cours de lecture.\n ➡ Syntaxe: .now/current/playing/np"""
|
||||
|
||||
await ctx.send(embed=ctx.voice_state.current.create_embed())
|
||||
|
||||
@commands.command(name='pause')
|
||||
async def _pause(self, ctx: commands.Context):
|
||||
"""Mets en pause de la chanson en cours de lecture."""
|
||||
|
||||
if not ctx.voice_state.is_playing and ctx.voice_state.voice.is_playing():
|
||||
ctx.voice_state.voice.pause()
|
||||
await ctx.message.add_reaction('⏯')
|
||||
await ctx.send(f"**`{ctx.author}`** met en pause la chanson en cours.")
|
||||
else:
|
||||
embed = discord.Embed(description = "Tape `.play <chanson>` pour jouer quelque chose.", color = 0xC41B1B)
|
||||
embed.set_author(name = "Je ne joue rien en ce moment !")
|
||||
return await ctx.send(embed = embed)
|
||||
|
||||
@commands.command(name='resume')
|
||||
async def _resume(self, ctx: commands.Context):
|
||||
"""Reprends la chanson en pause."""
|
||||
|
||||
if not ctx.voice_state.is_playing and ctx.voice_state.voice.is_paused():
|
||||
ctx.voice_state.voice.resume()
|
||||
await ctx.message.add_reaction('⏯')
|
||||
await ctx.send(f"**`{ctx.author}`** relance la chanson.")
|
||||
else:
|
||||
if ctx.voice_state.is_playing:
|
||||
embed = discord.Embed(description = "Tape `.pause` pour mettre en pause la chanson.", color = 0xC41B1B)
|
||||
embed.set_author(name = "Je suis déjà en lecture !")
|
||||
return await ctx.send(embed = embed)
|
||||
else:
|
||||
embed = discord.Embed(description = "Tape `.play <chanson>` pour jouer quelque chose ou `.join [id]` pour me connecter à un salon vocal.", color = 0xC41B1B)
|
||||
embed.set_author(name = "Je ne suis connecté à aucun vocal.")
|
||||
return await ctx.send(embed = embed)
|
||||
|
||||
@commands.command(name='skip', aliases=['s'])
|
||||
async def _skip(self, ctx: commands.Context):
|
||||
"""Passe la chanson.\n ➡ Syntaxe: .skip/s"""
|
||||
|
||||
if not ctx.voice_state.is_playing:
|
||||
embed = discord.Embed(description = "Tape `.play <chanson>` pour jouer quelque chose.", color = 0xC41B1B)
|
||||
embed.set_author(name = "Je ne joue rien en ce moment !")
|
||||
return await ctx.send(embed = embed)
|
||||
|
||||
await ctx.message.add_reaction('⏭')
|
||||
ctx.voice_state.skip()
|
||||
await ctx.send(f"**`{ctx.author}`**: Passe la chanson !")
|
||||
|
||||
@commands.command(name='queue', aliases=['q', 'playlist'])
|
||||
async def _queue(self, ctx: commands.Context, *, page: int = 1):
|
||||
"""Affiche la file d'attente des chansons à venir.\n ➡ Syntaxe: .queue/q/playlist [page]"""
|
||||
|
||||
if len(ctx.voice_state.songs) == 0:
|
||||
embed = discord.Embed(description = "Tape `.play <chanson>` pour jouer quelque chose.", color = 0xC41B1B)
|
||||
embed.set_author(name = "Il n'y a plus de chanson à venir dans la playlist.")
|
||||
return await ctx.send(embed = embed)
|
||||
|
||||
items_per_page = 10
|
||||
pages = math.ceil(len(ctx.voice_state.songs) / items_per_page)
|
||||
|
||||
if page > pages:
|
||||
embed = discord.Embed(description = "Tape `.play <chanson>` pour rajouter encore de la musique.", color = 0xC41B1B)
|
||||
embed.set_author(name = "Il n'y a pas autant de pages")
|
||||
return await ctx.send(embed = embed)
|
||||
|
||||
start = (page - 1) * items_per_page
|
||||
end = start + items_per_page
|
||||
|
||||
queue = ''
|
||||
for i, song in enumerate(ctx.voice_state.songs[start:end], start=start):
|
||||
queue += f"`{i + 1}.` [**{song.source.title}**]({song.source.url})\n"
|
||||
|
||||
embed = (discord.Embed(description=f"**{len(ctx.voice_state.songs)} piste{'s' if len(ctx.voice_state.songs)>1 else ''} :**\n\n{queue}", color = randint(0, 0xFFFFFF))
|
||||
.set_footer(text=f"Page {page}/{pages}"))
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name='shuffle')
|
||||
async def _shuffle(self, ctx: commands.Context):
|
||||
"""Mélange la file d'attente."""
|
||||
|
||||
if len(ctx.voice_state.songs) == 0:
|
||||
embed = discord.Embed(description = "Tape `.play <chanson>` pour jouer quelque chose.", color = 0xC41B1B)
|
||||
embed.set_author(name = "La file est vide.")
|
||||
return await ctx.send(embed = embed)
|
||||
|
||||
ctx.voice_state.songs.shuffle()
|
||||
await ctx.message.add_reaction('✅')
|
||||
|
||||
@commands.command(name='remove')
|
||||
async def _remove(self, ctx: commands.Context, index: int):
|
||||
"""Supprime une chanson de la file d'attente."""
|
||||
|
||||
if len(ctx.voice_state.songs) == 0:
|
||||
return await ctx.send("File vide.")
|
||||
|
||||
ctx.voice_state.songs.remove(index - 1)
|
||||
await ctx.message.add_reaction('✅')
|
||||
await ctx.send("Chanson sélectionnée supprimée de la file d'attente.")
|
||||
|
||||
@commands.command(name='loop', aliases=['repeat'])
|
||||
async def _loop(self, ctx: commands.Context):
|
||||
"""Répète la chanson actuellement en lecture.\n ➡ Syntaxe: .loop/repeat"""
|
||||
|
||||
if not ctx.voice_state.is_playing:
|
||||
embed = discord.Embed(description = "Tape `.play <chanson>` pour jouer quelque chose.", color = 0xC41B1B)
|
||||
embed.set_author(name = "Je ne joue rien en ce moment !")
|
||||
return await ctx.send(embed = embed)
|
||||
|
||||
# Inverse boolean value to loop and unloop.
|
||||
ctx.voice_state.loop = not ctx.voice_state.loop
|
||||
await ctx.message.add_reaction('✅')
|
||||
await ctx.send("La chanson change d'état.")
|
||||
|
||||
@commands.command(name='play', aliases=['p'])
|
||||
async def _play(self, ctx: commands.Context, *, search: str):
|
||||
"""Recherche une chanson sur les sites compatibles avec YoutubeDL si aucun URL n'est donné et l'ajoute à la file d'attente.\n ➡ Syntaxe: .play/p"""
|
||||
|
||||
if not ctx.voice_state.voice:
|
||||
await ctx.invoke(self._summon)
|
||||
|
||||
async with ctx.typing():
|
||||
try:
|
||||
source = await YTDLSource.create_source(ctx, search, loop=self.client.loop)
|
||||
except YTDLError as e:
|
||||
await ctx.send(f"Une erreur s'est produite lors du traitement de cette demande : {str(e)}")
|
||||
else:
|
||||
song = Song(source)
|
||||
|
||||
await ctx.voice_state.songs.put(song)
|
||||
await ctx.send(f"En file d'attente {str(source)}")
|
||||
|
||||
@_summon.before_invoke
|
||||
@_play.before_invoke
|
||||
async def ensure_voice_state(self, ctx: commands.Context):
|
||||
if not ctx.author.voice or not ctx.author.voice.channel:
|
||||
raise commands.CommandError("Vous n'êtes connecté à aucun channel vocal.")
|
||||
|
||||
if ctx.voice_client:
|
||||
if ctx.voice_client.channel != ctx.author.voice.channel:
|
||||
raise commands.CommandError("Le bot est déjà dans un channel vocal.")
|
||||
|
||||
@commands.command(name='lyrics', aliases = ['l', 'lyric'])
|
||||
async def _lyrics(self, ctx, *, song: str = None):
|
||||
"""Affiche les paroles de la musique en cours, ou de la chanson spécifiée.\n ➡ Syntaxe: .lyrics/lyric/l (musique)"""
|
||||
if song or ctx.voice_state.is_playing:
|
||||
if not song:
|
||||
song = f"{ctx.voice_state.current.title()}"
|
||||
if " romanized" in song:
|
||||
message = await ctx.send(f":mag: **Cherche les paroles romanisées de ** `{song.replace(' romanized', '')}`")
|
||||
else:
|
||||
message = await ctx.send(f":mag: **Cherche les paroles de ** `{song}`")
|
||||
temps_requete = int(round(time.time() * 1000))
|
||||
song_genius = genius.search_song(song)
|
||||
couleur_embed = randint(0, 0xFFFFFF)
|
||||
try:
|
||||
paroles = song_genius.lyrics
|
||||
except:
|
||||
await ctx.message.add_reaction(emoji = '❌')
|
||||
return await message.edit(content = f"Pas de résultats trouvés pour `{song}`.")
|
||||
lignetotal = ""
|
||||
premierembed = True
|
||||
if len(paroles) > 7500:
|
||||
await ctx.message.add_reaction(emoji = '❌')
|
||||
return await message.edit(content = f"Désolé, les paroles sont trop longues pour être affichés (lien vers la page des paroles : {song_genius.url}).")
|
||||
title_first_embed = f"Paroles de {song_genius.title} par {song_genius.artist}."
|
||||
desc_first_embed = f"[Lien vers les paroles sur le site]({song_genius.url})"
|
||||
type_de_comptage = "\n\n" if paroles.count("\n\n") > 2 else "\n"
|
||||
for ligne in paroles.split(type_de_comptage):
|
||||
if len(ligne) >= 2048:
|
||||
type_de_comptage = "\n"
|
||||
for ligne in paroles.split(type_de_comptage):
|
||||
if len(f"{lignetotal}{type_de_comptage}{ligne}") < 1900:
|
||||
lignetotal = f"{lignetotal}{type_de_comptage}{self.ligne_formatage(ligne)}"
|
||||
else:
|
||||
if premierembed == True:
|
||||
premierembed = False
|
||||
embed = discord.Embed(title = title_first_embed, description = f"{desc_first_embed}{lignetotal}", color = couleur_embed)
|
||||
embed.set_thumbnail(url = song_genius.song_art_image_url)
|
||||
await message.edit(embed = embed)
|
||||
else:
|
||||
embed = discord.Embed(description = lignetotal, color = couleur_embed)
|
||||
await ctx.send(embed = embed)
|
||||
lignetotal = f"{self.ligne_formatage(ligne)}"
|
||||
|
||||
temps_requete = int(round(time.time() * 1000)) - temps_requete
|
||||
footer_embed = f"Pour {self.user_or_nick(ctx.author)} par Genius en {round(temps_requete / 1000, 2)} s."
|
||||
await ctx.message.add_reaction(emoji = '✅')
|
||||
if premierembed == True:
|
||||
premierembed = False
|
||||
embed = discord.Embed(title = title_first_embed, description = f"{desc_first_embed}{lignetotal}", color = couleur_embed)
|
||||
embed.set_footer(icon_url = ctx.author.avatar_url, text = footer_embed)
|
||||
return await message.edit(embed = embed)
|
||||
else:
|
||||
embed = discord.Embed(description = lignetotal, color = couleur_embed)
|
||||
embed.set_footer(icon_url = ctx.author.avatar_url, text = footer_embed)
|
||||
return await ctx.send(embed = embed)
|
||||
else:
|
||||
await ctx.message.add_reaction(emoji = '❌')
|
||||
await ctx.send("Aucune musique demandé... `.lyrics/l/lyrics <song>`.")
|
||||
def ligne_formatage(self, ligne):
|
||||
liste_balise = [
|
||||
('[Hook', '[Accroche'), ('[Verse', '[Couplet'), ('[Chorus', '[Chœur'),
|
||||
('[Bridge', '[Pont'),('[Pre-Chorus', '[Pré-chœur'), ('[Post-Chorus', '[Post-chœur')
|
||||
]
|
||||
for balises in liste_balise:
|
||||
ligne = ligne.replace(balises[0], balises[1])
|
||||
return ligne
|
||||
def user_or_nick(self, user):
|
||||
if user.nick:
|
||||
return f"{user.nick} ({user.name}#{user.discriminator})"
|
||||
else:
|
||||
return f"{user.name}#{user.discriminator}"
|
||||
|
||||
@commands.command(name='lyricsromanized', aliases = ['lr', 'lyricromanized'], hidden = True)
|
||||
async def _lyricsromanized(self, ctx, *, song: str = None):
|
||||
await ctx.invoke(self.client.get_command("lyrics"), song = f"{song} romanized" if song else song)
|
337
cogs/utils.py
Normal file
337
cogs/utils.py
Normal file
|
@ -0,0 +1,337 @@
|
|||
import discord, pytz, time
|
||||
from discord.ext import commands
|
||||
from random import randint, shuffle
|
||||
from datetime import datetime
|
||||
from pytz import timezone
|
||||
import re
|
||||
import asyncio
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(Utils(client))
|
||||
|
||||
class Utils(commands.Cog):
|
||||
"""Commandes essentielles."""
|
||||
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
|
||||
|
||||
@commands.command(name='ping')
|
||||
async def _ping(self, ctx, *, question = '0'):
|
||||
"""Affiche mon ping.\n ➡ Syntaxe: .ping [help]"""
|
||||
if question == 'help':
|
||||
return await ctx.send(embed = discord.Embed(color = randint(0, 0xFFFFFF), description = ":hourglass: correspond au temps entre deux battements de cœurs (en millisecondes)\n\n:stopwatch: correspond au temps que met le client a calculer le ping (en millisecondes)\n\n:heartbeat: correspond au temps que met le client a réagir au messages (en millisecondes)"))
|
||||
else:
|
||||
now = int(round(time.time() * 1000))
|
||||
ping = now - int(round(ctx.message.created_at.timestamp() * 1000))
|
||||
embed = discord.Embed(description = 'Pinging...')
|
||||
message = await ctx.send(embed = embed)
|
||||
ping2 = int(round(time.time() * 1000)) - now
|
||||
await message.edit(embed = discord.Embed(color = randint(0, 0xFFFFFF), description = f':hourglass: {round(self.client.latency * 1000)}ms\n\n:stopwatch: {ping2}ms\n\n:heartbeat: {ping}ms'))
|
||||
await ctx.message.add_reaction(emoji = '✅')
|
||||
|
||||
@commands.command(name='avatar')
|
||||
async def _avatar(self, ctx, *, user = '0'):
|
||||
"""Affiche ton avatar ou celui que tu mentionnes.\n ➡ Syntaxe: .avatar [user]"""
|
||||
if user == '0':
|
||||
user = ctx.author
|
||||
else:
|
||||
user = self.client.get_user(int(user[2:-1].replace("!","")))
|
||||
await ctx.message.add_reaction(emoji = '✅')
|
||||
embed = discord.Embed(description = f"[lien vers la photo de profil]({user.avatar_url}) de {user.mention}", color = randint(0, 0xFFFFFF))
|
||||
embed.set_author(name = f"Photo de profil de {user.name}")
|
||||
embed.set_image(url = user.avatar_url)
|
||||
await ctx.send(embed = embed)
|
||||
|
||||
@commands.command(name='calc')
|
||||
async def _calc(self, ctx, *, msg):
|
||||
"""Calculatrice.\n ➡ Syntaxe: .calc <calcul>"""
|
||||
equation = msg.replace('^', '**').replace('x', '*').replace('×', '*').replace('÷', '/').replace('≥', '>=').replace('≤', '<=')
|
||||
try:
|
||||
try:
|
||||
if '=' in equation:
|
||||
if '<' in equation:
|
||||
left = eval(equation.split("<=")[0])
|
||||
right = eval(equation.split("<=")[1])
|
||||
answer = str(left <= right)
|
||||
elif '>' in equation:
|
||||
left = eval(equation.split(">=")[0])
|
||||
right = eval(equation.split(">=")[1])
|
||||
answer = str(left >= right)
|
||||
else:
|
||||
left = eval(equation.split("=")[0])
|
||||
right = eval(equation.split("=")[1])
|
||||
answer = str(left == right)
|
||||
else:
|
||||
answer = str(eval(equation))
|
||||
except ZeroDivisionError:
|
||||
return await ctx.send("Tu ne peux pas divisé par 0.")
|
||||
except TypeError:
|
||||
return await ctx.send("Requête de calcul invalide.")
|
||||
if '.' in answer:
|
||||
aftercomma = answer.split(".")[1]
|
||||
if len(aftercomma) > 2:
|
||||
answer = str(round(float(answer),2))
|
||||
equation = f"'{equation}' arrondi à 2"
|
||||
equation = equation.replace('*', '×').replace('/', '÷').replace('>=', '≥').replace('<=', '≤')
|
||||
embed = discord.Embed(color = randint(0, 0xFFFFFF), title = 'Calculatrice')
|
||||
embed.set_footer(text = ctx.author)
|
||||
|
||||
embed.add_field(name = 'Calcul :', value = equation, inline = False)
|
||||
embed.add_field(name = 'Réponse :', value = answer.replace('False', 'Faux').replace('True', 'Vrai'), inline = False)
|
||||
await ctx.message.add_reaction(emoji = '✅')
|
||||
await ctx.send(content = None, embed = embed)
|
||||
@_calc.error
|
||||
async def _calc_error(self, ctx, error):
|
||||
await ctx.send("Tu n'as pas spécifié de calcul.")
|
||||
|
||||
@commands.command(name='syntax')
|
||||
async def _syntax(self, ctx):
|
||||
"""Informations pour bien éditer son texte."""
|
||||
syntaxe = "-----------------------------------------------------\n"
|
||||
syntaxe += discord.utils.escape_markdown("```Js\n")
|
||||
syntaxe += discord.utils.escape_markdown("//code en js (possible de remplacer 'js' par d'autres languages . adaptez le !)\n")
|
||||
syntaxe += discord.utils.escape_markdown('console.log("hi");\n')
|
||||
syntaxe += discord.utils.escape_markdown("```\n")
|
||||
syntaxe += "```Js\n"
|
||||
syntaxe += "//code en js (possible de remplacer 'js' par d'autres languages . adaptez le !)\n"
|
||||
syntaxe += 'console.log("hi");\n'
|
||||
syntaxe += "```\n"
|
||||
syntaxe += "Si ton code est trop long, mets le sur <https://pastebin.com/>\n"
|
||||
syntaxe += "-----------------------------------------------------\n"
|
||||
syntaxe += discord.utils.escape_markdown("`code sur une seule ligne`\n")
|
||||
syntaxe += "`code sur une seule ligne`\n"
|
||||
syntaxe += "-----------------------------------------------------\n"
|
||||
syntaxe += discord.utils.escape_markdown("*texte en italique*\n")
|
||||
syntaxe += "*texte en italique*\n"
|
||||
syntaxe += "-----------------------------------------------------\n"
|
||||
syntaxe += discord.utils.escape_markdown("**text en gras**\n")
|
||||
syntaxe += "**text en gras**\n"
|
||||
syntaxe += "-----------------------------------------------------\n"
|
||||
syntaxe += discord.utils.escape_markdown("<<https://www.youtube.com/watch?v=GhuYKL5NUYg>>\n")
|
||||
syntaxe += "Un lien entre crochet, ça empêche Discord de rajouté son intégration automatique (mais le lien fonctionnera toujours).\n"
|
||||
syntaxe += "-----------------------------------------------------\n"
|
||||
syntaxe += discord.utils.escape_markdown("__texte souligné__\n")
|
||||
syntaxe += "__texte souligné__\n"
|
||||
syntaxe += "-----------------------------------------------------\n"
|
||||
syntaxe += discord.utils.escape_markdown("~~texte barré~~\n")
|
||||
syntaxe += "~~texte barré~~\n"
|
||||
syntaxe += "-----------------------------------------------------\n"
|
||||
syntaxe += discord.utils.escape_markdown("~~__***text en italique-gras-souligné-barré***__~~\n")
|
||||
syntaxe += "~~__***text en italique-gras-souligné-barré***__~~\n"
|
||||
syntaxe += "-----------------------------------------------------\n"
|
||||
syntaxe += discord.utils.escape_markdown("\:joy: <- l'emoji ne va pas fonctionné grâce au \ \n")
|
||||
syntaxe += "\:joy: <- l'emoji ne va pas fonctionné grâce au \ \n"
|
||||
syntaxe += "-----------------------------------------------------\n"
|
||||
syntaxe += discord.utils.escape_markdown("> cette ligne est cité\npas celle là\n")
|
||||
syntaxe += "> cette ligne est cité\npas celle là\n"
|
||||
syntaxe += "-----------------------------------------------------\n"
|
||||
syntaxe += discord.utils.escape_markdown(">>> cette ligne est cité\ncelle là aussi (et elles le seront toutes!)\n")
|
||||
syntaxe += ">>> cette ligne est cité\ncelle là aussi (et elles le seront toutes!)\n"
|
||||
await ctx.message.add_reaction(emoji = '✅')
|
||||
await ctx.send(syntaxe)
|
||||
|
||||
@commands.command(name='memo', aliases = ['note'])
|
||||
async def _memo(self, ctx, *, text):
|
||||
"""T'envoie un petit memo par message privé.\n ➡ Syntaxe: .memo/note <message>"""
|
||||
if len(text) <= 5:
|
||||
await ctx.message.add_reaction(emoji = '❌')
|
||||
return await ctx.send("Ta note doit au moins faire 5 caractères.")
|
||||
elif len(text) >= 2048:
|
||||
await ctx.message.add_reaction(emoji = '❌')
|
||||
return await ctx.send("Ta note doit faire moins de 2048 caractères.")
|
||||
else:
|
||||
await ctx.message.delete()
|
||||
embed = discord.Embed(description = text, color = randint(0, 0xFFFFFF))
|
||||
embed.set_author(name = "Mémo", icon_url = ctx.author.avatar_url)
|
||||
embed.set_footer(text = f'📝 le {datetime.now(pytz.timezone("Europe/Paris")).strftime("%d/%m/%Y à %H:%M:%S")}')
|
||||
await ctx.author.send(embed = embed)
|
||||
return await ctx.send("Tu viens de recevoir ton mémo !", delete_after = 5)
|
||||
@_memo.error
|
||||
async def _note_error(self, ctx, error):
|
||||
if str(error) == "text is a required argument that is missing.":
|
||||
await ctx.send("Vous devez renseigner un message : `.note/memo <message>`.")
|
||||
|
||||
@commands.command(name='infos', aliases = ['info'])
|
||||
async def _infos(self, ctx):
|
||||
"""Donne des infos sur le bot.\n ➡ Syntaxe: .infos/info"""
|
||||
appinfo = await self.client.application_info()
|
||||
|
||||
embed = discord.Embed(color = randint(0, 0xFFFFFF))
|
||||
|
||||
embed.set_author(name = appinfo.name, icon_url = self.client.user.avatar_url)
|
||||
|
||||
total_online = len({m.id for m in self.client.get_all_members() if m.status is discord.Status.online})
|
||||
total_unique = len(self.client.users)
|
||||
|
||||
voice_channels = []
|
||||
text_channels = []
|
||||
for guild in self.client.guilds:
|
||||
voice_channels.extend(guild.voice_channels)
|
||||
text_channels.extend(guild.text_channels)
|
||||
|
||||
text = len(text_channels)
|
||||
voice = len(voice_channels)
|
||||
|
||||
embed.add_field(name = "Dev", value = f"[{appinfo.owner}](https://github.com/Mylloon)")
|
||||
embed.add_field(name = "Serveurs", value = len(self.client.guilds))
|
||||
embed.add_field(name = "Membres", value = f"{total_unique} au total\n{total_online} en ligne")
|
||||
embed.add_field(name = "Channels", value = f"{text} textuelles\n{voice} vocales")
|
||||
embed.set_footer(text = f"Basé sur discord.py {discord.__version__}")
|
||||
await ctx.message.add_reaction(emoji = '✅')
|
||||
await ctx.send(embed = embed)
|
||||
|
||||
def _map_list_among_us(self, map):
|
||||
maps = {}
|
||||
maps["skeld"] = ["skeld", "the skeld", "theskeld"]
|
||||
maps["mira"] = ["mira", "mira hq", "mirahq"]
|
||||
maps["polus"] = ["polus"]
|
||||
if map == "all":
|
||||
return maps["skeld"] + maps["mira"] + maps["polus"]
|
||||
return maps[map]
|
||||
|
||||
@commands.command(name='among', hidden = True)
|
||||
async def _among(self, ctx, *, args = ""):
|
||||
if not args == "":
|
||||
args = args.split()
|
||||
del args[0]
|
||||
args = " ".join(args)
|
||||
if args.lower() in self._map_list_among_us("all"):
|
||||
await ctx.invoke(self.client.get_command("amongus"), map=args)
|
||||
else:
|
||||
await ctx.invoke(self.client.get_command("amongus"))
|
||||
else:
|
||||
await ctx.message.add_reaction(emoji = '❓')
|
||||
|
||||
@commands.command(name='amongus')
|
||||
async def _amongus(self, ctx, *, map = "0"):
|
||||
"""Affiche la carte voulue d'Among Us.\n ➡ Syntaxe: .amongus <carte>"""
|
||||
if map.lower() in self._map_list_among_us("mira"):
|
||||
image = "https://i.imgur.com/6ijrH1h.jpg"
|
||||
embed = discord.Embed(title = f"Map Mira HQ d'Among Us", color = randint(0, 0xFFFFFF), description = f"[lien de l'image]({image})")
|
||||
embed.set_image(url = image)
|
||||
await ctx.send(embed = embed)
|
||||
await ctx.message.add_reaction(emoji = '✅')
|
||||
elif map.lower() in self._map_list_among_us("polus"):
|
||||
image = "https://i.imgur.com/mhFmcw3.jpg"
|
||||
embed = discord.Embed(title = f"Map Polus d'Among Us", color = randint(0, 0xFFFFFF), description = f"[lien de l'image]({image})")
|
||||
embed.set_image(url = image)
|
||||
await ctx.send(embed = embed)
|
||||
await ctx.message.add_reaction(emoji = '✅')
|
||||
elif map.lower() in self._map_list_among_us("skeld"):
|
||||
image = "https://i.imgur.com/OSXI4Zv.jpg"
|
||||
embed = discord.Embed(title = f"Map The Skeld d'Among Us", color = randint(0, 0xFFFFFF), description = f"[lien de l'image]({image})")
|
||||
embed.set_image(url = image)
|
||||
await ctx.send(embed = embed)
|
||||
await ctx.message.add_reaction(emoji = '✅')
|
||||
else:
|
||||
await ctx.send("`.amongus <mira/polus/skeld>`")
|
||||
|
||||
@commands.command(name='whois')
|
||||
async def _whois(self, ctx, *user: discord.Member):
|
||||
"""Affiche les infos sur l'utilisateur.\n ➡ Syntaxe: .whois [user]"""
|
||||
if len(user) <= 1:
|
||||
if user == ():
|
||||
user = [ctx.author]
|
||||
nom = f"{user[0].name}#{user[0].discriminator}"
|
||||
if user[0].nick:
|
||||
nom = f"{user[0].nick} ({user[0].name}#{user[0].discriminator})"
|
||||
embed = discord.Embed(color = randint(0, 0xFFFFFF)).set_author(name = nom, icon_url = user[0].avatar_url)
|
||||
|
||||
embed.add_field(name = "ID", value = user[0].id)
|
||||
|
||||
value = str(user[0].created_at.astimezone(timezone('Europe/Paris')))[:-13].replace('-', '/').split()
|
||||
embed.add_field(name = "Compte créé le", value = f"{value[0][8:]}/{value[0][5:-3]}/{value[0][:4]} à {value[1]}")
|
||||
|
||||
embed.add_field(name = "Âge du compte", value = self._age_layout(self._get_age(user[0].created_at)))
|
||||
|
||||
embed.add_field(name = "Mention", value = user[0].mention)
|
||||
|
||||
value = str(user[0].joined_at.astimezone(timezone('Europe/Paris')))[:-13].replace('-', '/').split()
|
||||
embed.add_field(name = "Serveur rejoint le", value = f"{value[0][8:]}/{value[0][5:-3]}/{value[0][:4]} à {value[1]}")
|
||||
|
||||
embed.add_field(name = "Est sur le serveur depuis", value = self._age_layout(self._get_age(user[0].joined_at)))
|
||||
await ctx.message.add_reaction(emoji = '✅')
|
||||
return await ctx.send(embed = embed)
|
||||
await ctx.send("Tu mentionnes trop d'utilisateurs : `.whois [@Membre]`")
|
||||
def _get_age(self, date):
|
||||
joursRestants = datetime.now() - date
|
||||
years = joursRestants.total_seconds() / (365.242 * 24 * 3600)
|
||||
months = (years - int(years)) * 12
|
||||
days = (months - int(months)) * (365.242 / 12)
|
||||
hours = (days - int(days)) * 24
|
||||
minutes = (hours - int(hours)) * 60
|
||||
seconds = (minutes - int(minutes)) * 60
|
||||
return (int(years), int(months), int(days), int(hours), int(minutes), int(seconds))
|
||||
def _age_layout(self, tuple):
|
||||
time = {}
|
||||
time[0], time[1], time[2], time[3], time[4], time[5] = "an", "mois", "jour", "heure", "minute", "seconde"
|
||||
for i in range(len(tuple)):
|
||||
if tuple[i] > 1 and i != 1:
|
||||
time[i] = time[i] + "s"
|
||||
message = ""
|
||||
if tuple[5] > 0: # pour les secondes
|
||||
affichage = [5] # on affiche que : seconde
|
||||
if tuple[4] > 0:
|
||||
affichage = [4, 5] # on affiche : minute + seconde
|
||||
if tuple[3] > 0:
|
||||
affichage = [3, 4, 5] # on affiche : heure + minute + seconde
|
||||
if tuple[2] > 0:
|
||||
affichage = [2, 3, 4] # on affiche : jour + heure + minute
|
||||
if tuple[1] > 0:
|
||||
affichage = [1, 2, 3] # on affiche : mois + jour + heure
|
||||
if tuple[0] > 0:
|
||||
affichage = [0, 1, 3] # on affiche : an + mois + heure
|
||||
for i in affichage:
|
||||
message = message + f", {tuple[i]} {time[i]}"
|
||||
return message[2:]
|
||||
|
||||
@commands.command(name='sondage')
|
||||
async def _sondage(self, ctx, *args):
|
||||
"""Fais un sondage.\n ➡ Syntaxe: .sondage "<Question>" "<Proposition1>" "<Proposition...>" "<Proposition20>" """
|
||||
args = list(args)
|
||||
if len(args) > 2:
|
||||
question = args[0].replace("<@!", "").replace(">", "").replace("<@", "")
|
||||
for i in re.findall(r'\d+', question):
|
||||
ii = self.user_or_nick(ctx.author.guild.get_member(int(i)))
|
||||
try:
|
||||
question = question.replace(i, ii)
|
||||
except:
|
||||
pass
|
||||
propositions = args[1:]
|
||||
if len(propositions) <= 20:
|
||||
message = ""
|
||||
emojis = {}
|
||||
emojis[0] = ['1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣', '9️⃣', '🔟']
|
||||
emojis[1] = [
|
||||
'🟤', '🔴', '🟠', '🟡', '🟢', '🔵', '🟣', '🔘', '❤', '💜',
|
||||
'🟫', '🟥', '🟧', '🟨', '🟩', '🟦', '🟪', '🔳', '🧡', '💙'
|
||||
]
|
||||
mixable = True
|
||||
if len(propositions) <= 10:
|
||||
emojis_chosen = emojis[randint(0, len(emojis) - 1)]
|
||||
emojis_chosen = emojis_chosen[:10]
|
||||
if len(propositions) <= 8:
|
||||
emojis_chosen = emojis_chosen[:8]
|
||||
else:
|
||||
emojis_chosen = emojis[randint(1, len(emojis) - 1)]
|
||||
if emojis[0][0] in emojis_chosen: # rajouter ici les listes qui ne doivent pas être mélanger
|
||||
mixable = False
|
||||
if mixable:
|
||||
shuffle(emojis_chosen)
|
||||
for i in range(len(args[1:])):
|
||||
message += f"{emojis_chosen[i]} -> {propositions[i]}\n"
|
||||
embed = discord.Embed(title = question, description = message,color = randint(0, 0xFFFFFF)).set_footer(text = self.user_or_nick(ctx.author), icon_url = ctx.author.avatar_url)
|
||||
sondage = await ctx.send(embed = embed)
|
||||
for i in range(len(args[1:])):
|
||||
await sondage.add_reaction(emoji = emojis_chosen[i])
|
||||
return await ctx.message.add_reaction(emoji = '✅')
|
||||
else:
|
||||
return await ctx.send(f"Désolé, mais tu as mis trop de possibilités (maximum : 20)")
|
||||
else:
|
||||
return await ctx.send(f'Désolé, mais il manque des arguments : `.sondage "<Question>" "<Proposition1>" "<Proposition...>" "<Proposition20>"`')
|
||||
def user_or_nick(self, user):
|
||||
if user.nick:
|
||||
return f"{user.nick} ({user.name}#{user.discriminator})"
|
||||
else:
|
||||
return f"{user.name}#{user.discriminator}"
|
180
main.py
Normal file
180
main.py
Normal file
|
@ -0,0 +1,180 @@
|
|||
print("Connexion à Discord...")
|
||||
|
||||
import discord, re, pytz
|
||||
from discord.ext import commands
|
||||
from random import randint, choice
|
||||
from datetime import datetime, timedelta
|
||||
from pytz import timezone
|
||||
from setup import token
|
||||
|
||||
client = commands.Bot(command_prefix = ".", case_insensitive = True, intents = discord.Intents.all())
|
||||
|
||||
@client.event
|
||||
async def on_connect():
|
||||
print(f"Connecté avec le token : {token}.")
|
||||
print("Chargement des extensions & librairie...")
|
||||
client.load_extension("cogs.help")
|
||||
client.load_extension("cogs.utils")
|
||||
client.load_extension("cogs.internet")
|
||||
client.load_extension("cogs.music")
|
||||
client.load_extension("cogs.games")
|
||||
client.load_extension("cogs.fun")
|
||||
|
||||
@client.event
|
||||
async def on_ready():
|
||||
await client.change_presence(status = discord.Status.online, activity = discord.Activity(name = ".help", type = discord.ActivityType.playing))
|
||||
print("Bot prêt.")
|
||||
channel = client.get_channel(742564480050790512)
|
||||
await channel.send("Le bot a bien démarré.")
|
||||
|
||||
@client.event
|
||||
async def on_member_join(member):
|
||||
if member.guild.id == 441208120644075520: # Confrérie du Kassoulait
|
||||
if member.bot == True:
|
||||
role = discord.utils.get(member.guild.roles, name = "Bot")
|
||||
else:
|
||||
role = discord.utils.get(member.guild.roles, name = "Copain")
|
||||
await member.add_roles(role)
|
||||
try:
|
||||
await member.send(f"Coucou **{member.name}** sur {member.guild.name} ! 🥰\n\nTu as le rôle **{role}** 💖!")
|
||||
except:
|
||||
pass
|
||||
channel = client.get_channel(741639570172674120) # salons des arrivées
|
||||
switch = {
|
||||
0: f"Bienvenue, {member.mention}. On espère que tu as apporté de la pizza.",
|
||||
1: f"C'est un plaisir de te voir, {member.mention}.",
|
||||
2: f"{member.mention} vient juste d'arriver !",
|
||||
3: f"{member.mention} vient juste d'atterrir.",
|
||||
4: f"{member.mention} vient de se glisser dans le serveur.",
|
||||
5: f"{member.mention} a bondi dans le serveur.",
|
||||
6: f"Contents de te voir, {member.mention}.",
|
||||
7: f"{member.mention} est arrivé(e).",
|
||||
8: f"Tout le monde, accueillez comme il se doit {member.mention} !",
|
||||
9: f"Youhou, tu as réussi, {member.mention} !",
|
||||
10: f"{member.mention} a rejoint le groupe.",
|
||||
}
|
||||
message = await channel.send("...") # évite d'envoyer une notification
|
||||
await message.edit(content = choice(switch))
|
||||
|
||||
@client.event
|
||||
async def on_member_remove(member):
|
||||
if member.guild.id == 441208120644075520: # Confrérie du Kassoulait
|
||||
channel = client.get_channel(741639570172674120) # salons des arrivées
|
||||
await channel.send(f"{member.mention} vient de quitter le serveur.")
|
||||
|
||||
@client.event
|
||||
async def on_raw_reaction_add(payload):
|
||||
if payload.message_id == 644922358745792512: # Règles de la Confrérie du Kassoulait
|
||||
if payload.emoji.name == '✅':
|
||||
role = discord.utils.get(payload.member.guild.roles, name="règles-acceptés")
|
||||
await payload.member.add_roles(role)
|
||||
|
||||
@client.event
|
||||
async def on_raw_reaction_remove(payload):
|
||||
if payload.message_id == 644922358745792512: # Règles de la Confrérie du Kassoulait
|
||||
if payload.emoji.name == '✅':
|
||||
guild = discord.utils.find(lambda g : g.id == payload.guild_id, client.guilds)
|
||||
member = discord.utils.find(lambda m: m.id == payload.user_id, guild.members)
|
||||
role = discord.utils.get(guild.roles, name="règles-acceptés")
|
||||
await member.remove_roles(role)
|
||||
|
||||
@client.event
|
||||
async def on_command_error(ctx, error):
|
||||
if not ctx.invoked_with.startswith('.'):
|
||||
await ctx.message.add_reaction(emoji = '❓')
|
||||
print(error)
|
||||
|
||||
@client.event
|
||||
async def on_message(message):
|
||||
await client.process_commands(message)
|
||||
|
||||
|
||||
if message.author == client.user:
|
||||
return
|
||||
|
||||
if client.user.mention == message.content.replace("!",""):
|
||||
ctx = await client.get_context(message)
|
||||
prefix = await client.get_prefix(message)
|
||||
await ctx.send(f">>> Coucou !\nMon préfix est `{prefix}` et ma commande d'aide est `{prefix}help`")
|
||||
|
||||
urls = re.findall(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', message.content)
|
||||
for i in range(len(urls)):
|
||||
if urls[i].startswith("https://discordapp.com/channels/") or urls[i].startswith("https://discord.com/channels/") or urls[i].startswith("https://ptb.discordapp.com/"):
|
||||
link = urls[i]
|
||||
linkURL = link
|
||||
if link.startswith("https://discord.com/channels/"):
|
||||
link = f'000{link}'
|
||||
if link.startswith("https://ptb.discordapp.com/"):
|
||||
link = link[4:]
|
||||
if "@me" in urls[i]:
|
||||
return await message.channel.send("Je ne cite pas les messages privés.", delete_after = 5)
|
||||
try:
|
||||
if int(link[32:-38]) == message.guild.id:
|
||||
msgID = await client.get_channel(int(link[51:-19])).fetch_message(int(link[70:]))
|
||||
if len(msgID.content) > 0:
|
||||
embed = discord.Embed(description = msgID.content)
|
||||
else:
|
||||
return # si le message ne contient pas de mots (image? vidéo? intégration?)
|
||||
embed.add_field(name = "Auteur", value = msgID.author.mention, inline=True)
|
||||
embed.add_field(name = "Channel", value = msgID.channel.mention, inline=True)
|
||||
embed.add_field(name = "Message", value = f"[Aller au message]({linkURL})", inline=True)
|
||||
embed.set_author(name = "Citation", icon_url = msgID.author.avatar_url)
|
||||
|
||||
icon_url = message.author.avatar_url
|
||||
|
||||
date_1 = str(msgID.created_at.astimezone(timezone('Europe/Paris')))[:-13].replace('-', '/').split()
|
||||
edit = ""
|
||||
if msgID.edited_at:
|
||||
date_edit = str(msgID.edited_at.astimezone(timezone('Europe/Paris')))[:-13].replace('-', '/').split()
|
||||
edit = f"(Dernier edit : {date_edit[0][8:]}/{date_edit[0][5:-3]}/{date_edit[0][:4]} à {date_edit[1]})"
|
||||
message_1 = f"Date : {date_1[0][8:]}/{date_1[0][5:-3]}/{date_1[0][:4]} à {date_1[1]} {edit}"
|
||||
|
||||
date_2 = str(message.created_at.astimezone(timezone('Europe/Paris')))[:-13].replace('-', '/').split()
|
||||
date_2 = f"{date_2[0][8:]}/{date_2[0][5:-3]}/{date_2[0][:4]} à {date_2[1]}"
|
||||
|
||||
embed.set_footer(icon_url = icon_url, text = f"{message_1}\nCité par {user_or_nick(message.author)} le {date_2}")
|
||||
await message.channel.send(embed = embed)
|
||||
if message.content == linkURL.replace(' ',''):
|
||||
await message.delete()
|
||||
except Exception as e:
|
||||
e = str(e)
|
||||
if not "invalid literal for int() with base 10:" in e or not "404 Not Found (error code: 10008)" in e: # faute de frappe / message supprimé
|
||||
print(e)
|
||||
|
||||
@client.event
|
||||
async def on_message_delete(message):
|
||||
if message.author.guild.id == 441208120644075520: # Confrérie du Kassoulait
|
||||
prefix = await client.get_prefix(message)
|
||||
if not (
|
||||
message.content.startswith(f"{prefix}note") or
|
||||
message.content.startswith(f"{prefix}memo") or
|
||||
len(re.findall(".com/channels/", message.content)) != 0 or
|
||||
client.user.id is message.author.id
|
||||
):
|
||||
user_suppressed = None
|
||||
|
||||
async for entry in message.guild.audit_logs(limit=1):
|
||||
if (datetime.now() - entry.created_at).seconds < 5 and str(entry.action) == 'AuditLogAction.message_delete':
|
||||
user_suppressed = entry.user
|
||||
|
||||
channel = client.get_channel(742588187456831659)
|
||||
embed = discord.Embed(description = f"{message.content}")
|
||||
|
||||
embed.set_author(name = user_or_nick(message.author), icon_url = message.author.avatar_url)
|
||||
|
||||
if not user_suppressed:
|
||||
embed.set_footer(text = f"Channel: #{message.channel.name} | Date : {str(message.created_at.astimezone(timezone('Europe/Paris')))[:-13].replace('-', '/').replace(' ', ' à ')}\nSupprimé le {datetime.now(pytz.timezone('Europe/Paris')).strftime('%d/%m/%Y à %H:%M:%S')}")
|
||||
else:
|
||||
embed.set_footer(icon_url = user_suppressed.avatar_url, text = f"Channel: #{message.channel.name} | Date : {str(message.created_at.astimezone(timezone('Europe/Paris')))[:-13].replace('-', '/').replace(' ', ' à ')}\nSupprimé par {user_or_nick(user_suppressed)} le {datetime.now(pytz.timezone('Europe/Paris')).strftime('%d/%m/%Y à %H:%M:%S')}")
|
||||
|
||||
await channel.send(embed = embed)
|
||||
# ne fonctionne pas quand un message a été supprimé avant que le bot ai démarré
|
||||
# info sur la personne qui a supprimé ne fonctionne pas si il a supprimé un message auparavant (les logs se rajoute a un log deja existant)
|
||||
|
||||
def user_or_nick(user):
|
||||
if user.nick:
|
||||
return f"{user.nick} ({user.name}#{user.discriminator})"
|
||||
else:
|
||||
return f"{user.name}#{user.discriminator}"
|
||||
|
||||
client.run(token)
|
6
requirements.txt
Normal file
6
requirements.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
discord.py[voice]==1.5.1 # discord
|
||||
async-timeout==3.0.1 # discord
|
||||
pytz==2020.4 # timezone
|
||||
praw==7.1.0 # reddit
|
||||
youtube-dl==2020.11.17 # music
|
||||
git+https://github.com/johnwmillr/LyricsGenius.git # lyrics
|
Reference in a new issue