Add files via upload
This commit is contained in:
parent
ea467f1057
commit
e9d25d0f40
9 changed files with 2083 additions and 0 deletions
10
Dockerfile
Normal file
10
Dockerfile
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
FROM zinobe/python3-ffmpeg7.4:latest
|
||||||
|
|
||||||
|
WORKDIR /srv/dev-disk-by-label-Disques/appdata/ravaBot
|
||||||
|
|
||||||
|
COPY requirements.txt ./
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
CMD [ "python", "-u", "./main.py" ]
|
78
cogs/meme.py
Normal file
78
cogs/meme.py
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
import discord
|
||||||
|
from discord.ext import commands
|
||||||
|
|
||||||
|
import praw
|
||||||
|
import random
|
||||||
|
import urllib.request as request
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
class Meme(commands.Cog):
|
||||||
|
|
||||||
|
def __init__(self, bot):
|
||||||
|
self.bot = bot
|
||||||
|
|
||||||
|
def JSONEncoder(self, o):
|
||||||
|
if isinstance(o, datetime.datetime):
|
||||||
|
return o.isoformat()
|
||||||
|
|
||||||
|
@commands.command(name='memes', aliases=['meme'])
|
||||||
|
async def memes_(self, ctx, *, args=""):
|
||||||
|
users=json.load(open('data/users.json', 'r'))
|
||||||
|
try:
|
||||||
|
dernier_message_temps = users[str(571348123855880192)]['dernier_message_XP_pics']
|
||||||
|
dernier_message_temps = datetime.datetime.strptime(dernier_message_temps, '%Y-%m-%dT%H:%M:%S.%f')
|
||||||
|
created_at = datetime.datetime.now()
|
||||||
|
ecart = created_at-dernier_message_temps #caclul l'écart
|
||||||
|
except:
|
||||||
|
users[str(571348123855880192)] = {}
|
||||||
|
dernier_message_temps = users[str(571348123855880192)]['experience']=-1
|
||||||
|
client = commands.Bot(command_prefix=".")
|
||||||
|
ravaBot = await client.fetch_user(571348123855880192)
|
||||||
|
dernier_message_temps = users[str(571348123855880192)]['nom_usuel']=f"{ravaBot.name}#{ravaBot.discriminator}"
|
||||||
|
ecart = datetime.timedelta(seconds=6)
|
||||||
|
if ecart.seconds >= 5:
|
||||||
|
users[str(571348123855880192)]['dernier_message_XP_pics'] = datetime.datetime.now()
|
||||||
|
json.dump(users, open('data/users.json', 'w'), default=self.JSONEncoder, indent=4, sort_keys=True)
|
||||||
|
try:
|
||||||
|
reddit = praw.Reddit(client_id='TON ID CLIENT', client_secret='TON CLIENT SECRET', user_agent='disreddit /u/xxxxxx, http://localhost:8080')
|
||||||
|
|
||||||
|
if args == "ctsurenft": # si user demande meme 'ctsurenft'
|
||||||
|
subredditchoix = 'Meme de qualité'
|
||||||
|
image_meme = 'https://twitter.com/i/status/1181338160741191682'
|
||||||
|
return await ctx.send(f"**{subredditchoix}**: {image_meme}") #en attendant que discord fix les vidéos dans les embed
|
||||||
|
|
||||||
|
elif args != "": # si il y a un arg différent d'un meme
|
||||||
|
subredditchoix = args
|
||||||
|
|
||||||
|
else: # si il n'y a pas d'arguments
|
||||||
|
subredditchoix = random.choice(['memes','anime_irl','Animemes','BikiniBottomTwitter','dankmemes','DeepFriedMemes',
|
||||||
|
'educationalmemes','funny','marvelmemes','me_irl','meme','MemeEconomy','Memes_Of_The_Dank','MinecraftMemes',
|
||||||
|
'PewdiepieSubmissions','physicsmemes','reactiongifs','wholesomememes','blackpeopletwitter','metal_me_irl','bee_irl','coaxedintoasnafu','195',
|
||||||
|
'shittyadviceanimals','meirl','2meirl4meirl','AdviceAnimals','weirdmemes'])
|
||||||
|
|
||||||
|
memes_submissions = reddit.subreddit(subredditchoix).hot()
|
||||||
|
post_to_pick = random.randint(1, 10)
|
||||||
|
for i in range(0, post_to_pick): # i pas important
|
||||||
|
submission = next(x for x in memes_submissions if not x.stickied)
|
||||||
|
|
||||||
|
image_meme = submission.url
|
||||||
|
subredditchoix = f"r/{subredditchoix}"
|
||||||
|
|
||||||
|
embed = discord.Embed(title=f"{subredditchoix} pour {ctx.author.name}", colour=discord.Colour.green())
|
||||||
|
embed.set_footer(text=f"Memes from reddit | Développé par des ravaG.")
|
||||||
|
embed.set_image(url=image_meme)
|
||||||
|
return await ctx.send(embed=embed)
|
||||||
|
|
||||||
|
except Exception as error:
|
||||||
|
print(f"args: {args}, subreddit: {subredditchoix}, error: {error}")
|
||||||
|
return await ctx.send(f"Ce subreddit est interdit, mis en quarantaine ou n'existe pas. ({subredditchoix})")
|
||||||
|
else:
|
||||||
|
t = 5-ecart.seconds
|
||||||
|
await ctx.send(f"Tu dois encore attendre {t} seconde{'s' if t>1 else ''} avant de lancer cette commande.", delete_after=2)
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bot):
|
||||||
|
bot.add_cog(Meme(bot))
|
434
cogs/music.py
Normal file
434
cogs/music.py
Normal file
|
@ -0,0 +1,434 @@
|
||||||
|
import discord
|
||||||
|
from discord.ext import commands
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import itertools
|
||||||
|
import sys
|
||||||
|
import traceback
|
||||||
|
from async_timeout import timeout
|
||||||
|
from functools import partial
|
||||||
|
from youtube_dl import YoutubeDL
|
||||||
|
import lyricsgenius
|
||||||
|
|
||||||
|
genius = lyricsgenius.Genius("TON TOKEN GENIUS")
|
||||||
|
|
||||||
|
ytdlopts = {
|
||||||
|
'format': 'bestaudio/best',
|
||||||
|
'outtmpl': 'downloads/%(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' # Les adresses ipv6 posent parfois des problèmes
|
||||||
|
}
|
||||||
|
|
||||||
|
ffmpegopts = {
|
||||||
|
'before_options': '-nostdin',
|
||||||
|
'options': '-vn'
|
||||||
|
}
|
||||||
|
|
||||||
|
ytdl = YoutubeDL(ytdlopts)
|
||||||
|
|
||||||
|
class VoiceConnectionError(commands.CommandError):
|
||||||
|
"""Classe d'exception personnalisée pour les erreurs de connexion."""
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidVoiceChannel(VoiceConnectionError):
|
||||||
|
"""Exception pour les cas de canaux vocaux non valables."""
|
||||||
|
|
||||||
|
|
||||||
|
class YTDLSource(discord.PCMVolumeTransformer):
|
||||||
|
|
||||||
|
def __init__(self, source, *, data, requester):
|
||||||
|
super().__init__(source)
|
||||||
|
self.requester = requester
|
||||||
|
|
||||||
|
self.title = data.get('title')
|
||||||
|
self.web_url = data.get('webpage_url')
|
||||||
|
|
||||||
|
# YTDL info dicts (data) ont d'autres informations utiles que vous pourriez vouloir
|
||||||
|
# https://github.com/rg3/youtube-dl/blob/master/README.md
|
||||||
|
|
||||||
|
def __getitem__(self, item: str):
|
||||||
|
"""Nous permet d'accéder à des attributs similaires à un dict.
|
||||||
|
Cette fonction n'est utile que lorsque vous n'êtes pas en train de télécharger.
|
||||||
|
"""
|
||||||
|
return self.__getattribute__(item)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def create_source(cls, ctx, search: str, *, loop, download=True):
|
||||||
|
loop = loop or asyncio.get_event_loop()
|
||||||
|
|
||||||
|
to_run = partial(ytdl.extract_info, url=search, download=download)
|
||||||
|
data = await loop.run_in_executor(None, to_run)
|
||||||
|
|
||||||
|
if 'entries' in data:
|
||||||
|
# prendre le premier élément d'une liste de lecture
|
||||||
|
data = data['entries'][0]
|
||||||
|
|
||||||
|
await ctx.send(f'```ini\n[{data["title"]} ajouté à la queue.]\n```')
|
||||||
|
|
||||||
|
if download:
|
||||||
|
source = ytdl.prepare_filename(data)
|
||||||
|
else:
|
||||||
|
return {'webpage_url': data['webpage_url'], 'requester': ctx.author, 'title': data['title']}
|
||||||
|
|
||||||
|
return cls(discord.FFmpegPCMAudio(source), data=data, requester=ctx.author)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def regather_stream(cls, data, *, loop):
|
||||||
|
"""Utilisé pour préparer un flux, au lieu de le télécharger.
|
||||||
|
Depuis l'expiration des liens de streaming Youtube."""
|
||||||
|
loop = loop or asyncio.get_event_loop()
|
||||||
|
requester = data['requester']
|
||||||
|
|
||||||
|
to_run = partial(ytdl.extract_info, url=data['webpage_url'], download=True)
|
||||||
|
data = await loop.run_in_executor(None, to_run)
|
||||||
|
|
||||||
|
return cls(discord.FFmpegPCMAudio(data['url']), data=data, requester=requester)
|
||||||
|
|
||||||
|
class MusicPlayer:
|
||||||
|
"""Une classe qui est attribuée à chaque guilde à l'aide du bot pour la musique.
|
||||||
|
Cette classe met en place une file d'attente et une boucle, ce qui permet aux différentes guildes d'écouter différentes listes de lecture
|
||||||
|
simultanément.
|
||||||
|
Lorsque le bot se déconnecte de la Voix, son instance est détruite.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = ('bot', '_guild', '_channel', '_cog', 'queue', 'next', 'current', 'np', 'volume')
|
||||||
|
|
||||||
|
def __init__(self, ctx):
|
||||||
|
self.bot = ctx.bot
|
||||||
|
self._guild = ctx.guild
|
||||||
|
self._channel = ctx.channel
|
||||||
|
self._cog = ctx.cog
|
||||||
|
|
||||||
|
self.queue = asyncio.Queue()
|
||||||
|
self.next = asyncio.Event()
|
||||||
|
|
||||||
|
self.np = None # Message en cours de lecture
|
||||||
|
self.volume = .4 # Volume défini initalement (.5 = 50%)
|
||||||
|
self.current = None
|
||||||
|
|
||||||
|
ctx.bot.loop.create_task(self.player_loop())
|
||||||
|
|
||||||
|
async def player_loop(self):
|
||||||
|
"""Player loop principale"""
|
||||||
|
await self.bot.wait_until_ready()
|
||||||
|
|
||||||
|
while not self.bot.is_closed():
|
||||||
|
self.next.clear()
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Attendez la prochaine chanson. Si nous annulons le lecteur et le déconnecter...
|
||||||
|
async with timeout(300): # 5 minutes...
|
||||||
|
source = await self.queue.get()
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
return self.destroy(self._guild)
|
||||||
|
|
||||||
|
if not isinstance(source, YTDLSource):
|
||||||
|
# La source était probablement un flux (non téléchargé)
|
||||||
|
# Nous devrions donc nous regather pour éviter l'expiration des flux
|
||||||
|
try:
|
||||||
|
source = await YTDLSource.regather_stream(source, loop=self.bot.loop)
|
||||||
|
except Exception as e:
|
||||||
|
await self._channel.send(f'Il y a eu une erreur dans le traitement de votre chanson.\n'
|
||||||
|
f'```css\n[{e}]\n```')
|
||||||
|
continue
|
||||||
|
|
||||||
|
source.volume = self.volume
|
||||||
|
self.current = source
|
||||||
|
|
||||||
|
self._guild.voice_client.play(source, after=lambda _: self.bot.loop.call_soon_threadsafe(self.next.set))
|
||||||
|
self.np = await self._channel.send(f'**Joue :** `{source.title}` demandé par '
|
||||||
|
f'`{source.requester}`')
|
||||||
|
await self.next.wait()
|
||||||
|
|
||||||
|
# Veillez à ce que le processus FFmpeg soit clean.
|
||||||
|
source.cleanup()
|
||||||
|
self.current = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Nous ne jouons plus cette chanson...
|
||||||
|
await self.np.delete()
|
||||||
|
except discord.HTTPException:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def destroy(self, guild):
|
||||||
|
"""Déconnecte et nettoie le lecteur."""
|
||||||
|
return self.bot.loop.create_task(self._cog.cleanup(guild))
|
||||||
|
|
||||||
|
|
||||||
|
class Music(commands.Cog):
|
||||||
|
"""Commandes liées à la musique."""
|
||||||
|
|
||||||
|
__slots__ = ('bot', 'players')
|
||||||
|
|
||||||
|
def __init__(self, bot):
|
||||||
|
self.bot = bot
|
||||||
|
self.players = {}
|
||||||
|
|
||||||
|
async def cleanup(self, guild):
|
||||||
|
try:
|
||||||
|
await guild.voice_client.disconnect()
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
del self.players[guild.id]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def __local_check(self, ctx):
|
||||||
|
"""Un contrôle local qui s'applique à tous les commandements de ce cog."""
|
||||||
|
if not ctx.guild:
|
||||||
|
raise commands.NoPrivateMessage
|
||||||
|
return True
|
||||||
|
|
||||||
|
async def __error(self, ctx, error):
|
||||||
|
"""Un gestionnaire d'erreur local pour toutes les erreurs découlant des commandes de ce rouage."""
|
||||||
|
if isinstance(error, commands.NoPrivateMessage):
|
||||||
|
try:
|
||||||
|
return await ctx.send('Cette commande ne peut pas être utilisée dans les messages privés.')
|
||||||
|
except discord.HTTPException:
|
||||||
|
pass
|
||||||
|
elif isinstance(error, InvalidVoiceChannel):
|
||||||
|
await ctx.send('Erreur de connexion au canal vocal. '
|
||||||
|
'Veuillez vous assurer que vous êtes dans un channel valide ou alors en spécifier un.')
|
||||||
|
|
||||||
|
print('Ignorer l''exception dans la commannde {}:'.format(ctx.command), file=sys.stderr)
|
||||||
|
traceback.print_exception(type(error), error, error.__traceback__, file=sys.stderr)
|
||||||
|
|
||||||
|
def get_player(self, ctx):
|
||||||
|
"""Récupérer le joueur du serveur, ou en générer un."""
|
||||||
|
try:
|
||||||
|
player = self.players[ctx.guild.id]
|
||||||
|
except KeyError:
|
||||||
|
player = MusicPlayer(ctx)
|
||||||
|
self.players[ctx.guild.id] = player
|
||||||
|
|
||||||
|
return player
|
||||||
|
|
||||||
|
@commands.command(name='connect', aliases=['join'])
|
||||||
|
async def connect_(self, ctx, *, channel: discord.VoiceChannel=None):
|
||||||
|
"""Se connecte au vocal.
|
||||||
|
Paramètres
|
||||||
|
------------
|
||||||
|
channel: discord.VoiceChannel [Optionnel]
|
||||||
|
Le channel auquel il faut se connecter. Si un channel n'est pas spécifié, une tentative de rejoindre le canal vocal dans lequel vous êtes
|
||||||
|
sera faite.
|
||||||
|
Cette commande gère également le déplacement du bot vers différents channel.
|
||||||
|
"""
|
||||||
|
if not channel:
|
||||||
|
try:
|
||||||
|
channel = ctx.author.voice.channel
|
||||||
|
except AttributeError:
|
||||||
|
return await ctx.send('Pas de channel à rejoindre. Veuillez soit spécifier un channel valide, soit en rejoindre un.')
|
||||||
|
|
||||||
|
vc = ctx.voice_client
|
||||||
|
|
||||||
|
if vc:
|
||||||
|
if vc.channel.id == channel.id:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await vc.move_to(channel)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
return await ctx.send(f'Move vers le channel : <{channel}> a expiré.')
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
await channel.connect()
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
return await ctx.send(f'Connexion au channel : <{channel}> a expiré.')
|
||||||
|
|
||||||
|
await ctx.send(f'Connexion à : **{channel}**')
|
||||||
|
|
||||||
|
@commands.command(name='play', aliases=['p'])
|
||||||
|
async def play_(self, ctx, *, search: str):
|
||||||
|
"""Demandez une chanson et ajoutez-la à la liste d'attente.
|
||||||
|
Cette commande tente de rejoindre un canal vocal valide si le bot n'en fait pas déjà partie.
|
||||||
|
Utilise YTDL pour rechercher et récupérer automatiquement une chanson.
|
||||||
|
Paramètres
|
||||||
|
------------
|
||||||
|
search: str [Required]
|
||||||
|
La chanson à rechercher et à récupérer en utilisant YTDL. Il peut s'agir d'une simple recherche, d'une ID ou d'une URL.
|
||||||
|
"""
|
||||||
|
await ctx.trigger_typing()
|
||||||
|
|
||||||
|
vc = ctx.voice_client
|
||||||
|
|
||||||
|
if not vc:
|
||||||
|
await ctx.invoke(self.connect_)
|
||||||
|
|
||||||
|
player = self.get_player(ctx)
|
||||||
|
|
||||||
|
# Si le téléchargement est sur False, la source sera un dict qui sera utilisé plus tard pour reconstituer le flux.
|
||||||
|
# Si le téléchargement est sur True, la source sera un discord.FFmpegPCMAudio avec un VolumeTransformer.
|
||||||
|
source = await YTDLSource.create_source(ctx, search, loop=self.bot.loop, download=True)
|
||||||
|
|
||||||
|
await player.queue.put(source)
|
||||||
|
|
||||||
|
@commands.command(name='pause')
|
||||||
|
async def pause_(self, ctx):
|
||||||
|
"""Met en pause la chanson en cours de lecture."""
|
||||||
|
vc = ctx.voice_client
|
||||||
|
|
||||||
|
if not vc or not vc.is_playing():
|
||||||
|
return await ctx.send('Je ne joue rien en ce moment !')
|
||||||
|
elif vc.is_paused():
|
||||||
|
return
|
||||||
|
|
||||||
|
vc.pause()
|
||||||
|
await ctx.send(f'**`{ctx.author}`**: Pause de la chanson !')
|
||||||
|
|
||||||
|
@commands.command(name='resume')
|
||||||
|
async def resume_(self, ctx):
|
||||||
|
"""Reprend la chanson actuellement en pause."""
|
||||||
|
vc = ctx.voice_client
|
||||||
|
|
||||||
|
if not vc or not vc.is_connected():
|
||||||
|
return await ctx.send('Je ne joue rien en ce moment !')
|
||||||
|
elif not vc.is_paused():
|
||||||
|
return
|
||||||
|
|
||||||
|
vc.resume()
|
||||||
|
await ctx.send(f'**`{ctx.author}`**: Reprenez la chanson !')
|
||||||
|
|
||||||
|
@commands.command(name='skip', aliases=['s'])
|
||||||
|
async def skip_(self, ctx):
|
||||||
|
"""Skip la chanson."""
|
||||||
|
vc = ctx.voice_client
|
||||||
|
|
||||||
|
if not vc or not vc.is_connected():
|
||||||
|
return await ctx.send('Je ne joue rien en ce moment !')
|
||||||
|
|
||||||
|
if vc.is_paused():
|
||||||
|
pass
|
||||||
|
elif not vc.is_playing():
|
||||||
|
return
|
||||||
|
|
||||||
|
vc.stop()
|
||||||
|
await ctx.send(f'**`{ctx.author}`**: Skip la chanson !')
|
||||||
|
|
||||||
|
@commands.command(name='queue', aliases=['q'])
|
||||||
|
async def queue_info(self, ctx):
|
||||||
|
"""Affiche la playlist de musiques à venir."""
|
||||||
|
vc = ctx.voice_client
|
||||||
|
|
||||||
|
if not vc or not vc.is_connected():
|
||||||
|
return await ctx.send('Je ne suis pas connecté au channel vocal actuellement !')
|
||||||
|
|
||||||
|
player = self.get_player(ctx)
|
||||||
|
if player.queue.empty():
|
||||||
|
return await ctx.send('Il n''y a actuellement plus de chansons en attente.')
|
||||||
|
|
||||||
|
# Saisissez jusqu'à 5 entrées dans la file d'attente...
|
||||||
|
upcoming = list(itertools.islice(player.queue._queue, 0, 5))
|
||||||
|
|
||||||
|
fmt = '\n'.join(f'**`{_["title"]}`**' for _ in upcoming)
|
||||||
|
embed = discord.Embed(title=f"Prochainement - {len(upcoming)} restant{'s' if len(upcoming)>1 else ''}", description=fmt)
|
||||||
|
|
||||||
|
await ctx.send(embed=embed)
|
||||||
|
|
||||||
|
@commands.command(name='now_playing', aliases=['np'])
|
||||||
|
async def now_playing_(self, ctx):
|
||||||
|
"""Affiche des informations sur la chanson en cours de lecture."""
|
||||||
|
vc = ctx.voice_client
|
||||||
|
|
||||||
|
if not vc or not vc.is_connected():
|
||||||
|
return await ctx.send('Je ne suis pas connecté au channel vocal actuellement !')
|
||||||
|
|
||||||
|
player = self.get_player(ctx)
|
||||||
|
if not player.current:
|
||||||
|
return await ctx.send('Je ne joue rien en ce moment !')
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Supprimez notre message "now_playing" précédent.
|
||||||
|
await player.np.delete()
|
||||||
|
except discord.HTTPException:
|
||||||
|
pass
|
||||||
|
|
||||||
|
player.np = await ctx.send(f'**Joue :** `{vc.source.title}` '
|
||||||
|
f'demandé par `{vc.source.requester}`')
|
||||||
|
|
||||||
|
@commands.command(name='volume', aliases=['vol'])
|
||||||
|
async def change_volume(self, ctx, *, vol: float):
|
||||||
|
"""Changez le volume du lecteur.
|
||||||
|
Paramètres
|
||||||
|
------------
|
||||||
|
volume: float or int [Required]
|
||||||
|
Le volume à régler en pourcentage du lecteur. Celui-ci doit être compris entre 1 et 100.
|
||||||
|
"""
|
||||||
|
vc = ctx.voice_client
|
||||||
|
|
||||||
|
if not vc or not vc.is_connected():
|
||||||
|
return await ctx.send('Je ne suis pas connecté au channel vocal actuellement !')
|
||||||
|
|
||||||
|
if not 0 < vol < 101:
|
||||||
|
return await ctx.send('Veuillez saisir une valeur comprise entre 1 et 100.')
|
||||||
|
|
||||||
|
player = self.get_player(ctx)
|
||||||
|
|
||||||
|
if vc.source:
|
||||||
|
vc.source.volume = vol / 100
|
||||||
|
|
||||||
|
player.volume = vol / 100
|
||||||
|
await ctx.send(f'**`{ctx.author}`**: Volume réglé sur **{vol}%**')
|
||||||
|
|
||||||
|
@commands.command(name='disconnect', aliases=['dc','stop'])
|
||||||
|
async def disconnect_(self, ctx):
|
||||||
|
"""Arrêtez la chanson en cours de lecture et détruisez le lecteur.
|
||||||
|
!Avertissement!
|
||||||
|
Cela détruira le joueur affecté au serveur, en supprimant également les chansons et les paramètres en attente (c'est généralement ce qu'on veut faire).
|
||||||
|
"""
|
||||||
|
vc = ctx.voice_client
|
||||||
|
|
||||||
|
if not vc or not vc.is_connected():
|
||||||
|
return await ctx.send('Je ne joue rien en ce moment !')
|
||||||
|
|
||||||
|
await self.cleanup(ctx.guild)
|
||||||
|
await ctx.send(f'Déconnexion.')
|
||||||
|
|
||||||
|
@commands.command(name='lyrics', aliases=['l', 'lyric']) #caractere vide: \u200b
|
||||||
|
async def lyrics_(self, ctx, *, song: str=None):
|
||||||
|
vc=ctx.voice_client
|
||||||
|
player=self.get_player(ctx)
|
||||||
|
if song or player.current:
|
||||||
|
if not song:
|
||||||
|
song=f"{vc.source.title}"
|
||||||
|
await ctx.send(f":mag: Cherche les paroles pour `{song}`")
|
||||||
|
song=genius.search_song(song)
|
||||||
|
couleur_embed=0xD3D3D3
|
||||||
|
try:
|
||||||
|
paroles=str(song.lyrics)
|
||||||
|
except:
|
||||||
|
return await ctx.send(f"Pas de résultats trouvés pour : `{vc.source.title}`")
|
||||||
|
lignetotal=""
|
||||||
|
premierembed=True
|
||||||
|
if len(paroles)>7500:
|
||||||
|
return await ctx.send("Désolé, les paroles sont trop longues pour être affichés.")
|
||||||
|
for ligne in paroles.split("\n"):
|
||||||
|
if len(f"{lignetotal}\n{ligne}")<1024:
|
||||||
|
lignetotal=f"{lignetotal}\n{ligne}"
|
||||||
|
else:
|
||||||
|
if premierembed==True:
|
||||||
|
premierembed=False
|
||||||
|
embed=discord.Embed(title=f'Paroles de {(str(song).split(":"))[0].replace("by", "par")}.', description=lignetotal, color=couleur_embed)
|
||||||
|
else:
|
||||||
|
embed=discord.Embed(description=lignetotal, color=couleur_embed)
|
||||||
|
await ctx.send(embed=embed)
|
||||||
|
lignetotal=f"{ligne}"
|
||||||
|
if premierembed==True:
|
||||||
|
premierembed=False
|
||||||
|
embed=discord.Embed(description=lignetotal, color=couleur_embed)
|
||||||
|
else:
|
||||||
|
embed=discord.Embed(description=lignetotal, color=couleur_embed)
|
||||||
|
embed.set_footer(icon_url=ctx.author.avatar_url,text=f"Demandé par {ctx.author} | Lyrics de RapGenius")
|
||||||
|
return await ctx.send(embed=embed)
|
||||||
|
else:
|
||||||
|
await ctx.send("Aucune musique demandé... `.lyrics <song>`")
|
||||||
|
|
||||||
|
def setup(bot):
|
||||||
|
bot.add_cog(Music(bot))
|
59
cogs/nsfw.py
Normal file
59
cogs/nsfw.py
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
import discord
|
||||||
|
from discord.ext import commands
|
||||||
|
|
||||||
|
import random
|
||||||
|
import requests
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
from googleapiclient.discovery import build
|
||||||
|
|
||||||
|
class Nsfw(commands.Cog):
|
||||||
|
|
||||||
|
# Init
|
||||||
|
|
||||||
|
def __init__(self, bot):
|
||||||
|
self.bot = bot
|
||||||
|
self.players = {}
|
||||||
|
|
||||||
|
# Research
|
||||||
|
|
||||||
|
def _get_lewd_image(self, what):
|
||||||
|
api_url = f"http://api.o{what}.ru/noise/"
|
||||||
|
|
||||||
|
r = requests.get(api_url)
|
||||||
|
response = r.json()
|
||||||
|
preview = response[0]['preview']
|
||||||
|
r.close()
|
||||||
|
|
||||||
|
image_url = f"http://media.o{what}.ru/{preview}"
|
||||||
|
return image_url
|
||||||
|
|
||||||
|
# Commands
|
||||||
|
|
||||||
|
@commands.command(aliases=['sexes','nude','nudes'])
|
||||||
|
async def sexe(self, ctx, *, choice_of_nsfw=None):
|
||||||
|
liste_hot=['butts', 'boobs']
|
||||||
|
if choice_of_nsfw in liste_hot:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
choice_of_nsfw = random.choice(liste_hot)
|
||||||
|
if ctx.channel.is_nsfw():
|
||||||
|
lewd_image = self._get_lewd_image(choice_of_nsfw)
|
||||||
|
#await ctx.send(lewd_image)
|
||||||
|
embed=discord.Embed(title=f"{choice_of_nsfw.capitalize()} pour {ctx.author.name}", colour=discord.Colour.purple())
|
||||||
|
embed.set_footer(text=f"Développé par des ravaG.")
|
||||||
|
embed.set_image(url=lewd_image)
|
||||||
|
await ctx.send(embed=embed)
|
||||||
|
else:
|
||||||
|
nsfw_channel = self.bot.get_channel(594713819167588387)
|
||||||
|
await ctx.send(f"Désolé mais je n'envois ce genre de message seulement dans {nsfw_channel.mention} !", delete_after=2)
|
||||||
|
|
||||||
|
# En cas d'erreur
|
||||||
|
|
||||||
|
@sexe.error
|
||||||
|
async def sexe_error(self, ctx, error):
|
||||||
|
await ctx.send("Une erreur est survenu lors du traitement de votre commande, veuillez réessayez !", delete_after=2)
|
||||||
|
|
||||||
|
def setup(bot):
|
||||||
|
bot.add_cog(Nsfw(bot))
|
3
data/users.json
Normal file
3
data/users.json
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
20
db.py
Normal file
20
db.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import psycopg2
|
||||||
|
|
||||||
|
conn_DB=psycopg2.connect("dbname='NOM DE TA BASE DE DONNEE' user='PSEUDO DE TA BASE DE DONNEE' host='IP DE TA BASE DE DONNEE' password='MOT DE PASSE DE TA BASE DE DONNEE'")
|
||||||
|
|
||||||
|
cur = conn_DB.cursor()
|
||||||
|
|
||||||
|
cur.execute("""SELECT id_user, nom_usuel, dernier_message_XP, experience, dernier_message_meme, position FROM users""")
|
||||||
|
|
||||||
|
rows = cur.fetchall()
|
||||||
|
|
||||||
|
for row in rows:
|
||||||
|
print("ID = {} ".format(row[0]))
|
||||||
|
print("NOM USUEL = {}".format(row[1]))
|
||||||
|
print("DERNIER MESSAGE XP = {}".format(row[2]))
|
||||||
|
print("XP = {}".format(row[3]))
|
||||||
|
print("DERNIER MESSAGE MEME = {}".format(row[4]))
|
||||||
|
print("POSITION = {}".format(row[5]))
|
||||||
|
print("\n")
|
||||||
|
|
||||||
|
#input("Press enter for quit...")
|
BIN
files/It was this folder, rip.png
Normal file
BIN
files/It was this folder, rip.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 170 KiB |
10
requirements.txt
Normal file
10
requirements.txt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
git+https://github.com/Rapptz/discord.py
|
||||||
|
async-timeout>=3.0.1
|
||||||
|
riotwatcher>=2.7.1
|
||||||
|
psycopg2-binary>=2.8.4
|
||||||
|
lyricsgenius>=1.7.0
|
||||||
|
google-auth-httplib2>=0.0.3
|
||||||
|
praw>=6.4.0
|
||||||
|
google-api-python-client>=1.7.11
|
||||||
|
youtube-dl>=2020.3.24
|
||||||
|
PyNaCl>=1.3.0
|
Reference in a new issue