Add files via upload

This commit is contained in:
Mylloon 2020-08-03 19:28:55 +02:00 committed by GitHub
parent ea467f1057
commit e9d25d0f40
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 2083 additions and 0 deletions

10
Dockerfile Normal file
View 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
View 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
View 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
View 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
View file

@ -0,0 +1,3 @@
{
}

20
db.py Normal file
View 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...")

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

1469
main.py Normal file

File diff suppressed because it is too large Load diff

10
requirements.txt Normal file
View 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