This commit is contained in:
Mael GRAMAIN 2018-11-18 03:05:22 +01:00
parent 12b8f79093
commit a690049e7e
198 changed files with 2557 additions and 884 deletions

39
README Normal file
View File

@ -0,0 +1,39 @@
TuxBot, un bot discord écrit en Python.
Ici ce trouve le code source du bot provenant du serveur Discord [Aide GNU/Linux-Fr"](https://discord.gg/79943dJ "Rejoindre le serveur"), il à été créé spécialement pour ce discord, si vous souhaitez l'utiliser il vous faudra modifier ``params.json`` et ``cogs/utils/checks.py`` ;)
### Pré-requis
Il vous faut :
- Un ordinateur sous **GNU/Linux** avec une connexion à internet;
- Python3.5 ou + ;
- Installer ``requirements.txt`` (avec ``pip install -r requirements.txt`` par ex)
### Installation
Une fois les pré-requis installés et ``params.json`` édité, placez vous dans le repertoire de tuxbot et lancez ``bot.py`` avec python3 (ex: ``python3 bot.py``)
## Démarrage
Placez vous dans le repertoire de tuxbot et exécutez ``bot.py`` avec python3 (ex: ``python3 bot.py``)
## Fabriqué avec
* [PyCharm](https://www.jetbrains.com/pycharm/) - Editeur de texte payant :3
* [discord.py](https://github.com/Rapptz/discord.py) - API Python pour discord
## Versions
Liste des versions : [Cliquer pour afficher](https://github.com/outout14/tuxbot-bot/tags)
## Auteurs
* **Maël** _alias_ [@outout14](https://github.com/outout14)
* **Romain** _alias_ [Romain le malchanceux](https://github.com/Rom194)
## License
Ce projet est sous licence ``Creative Commons BY-NC-SA 4.0`` - voir le fichier [LICENSE.md](LICENSE.md) pour plus d'informations
## Support on Beerpay
Hey dude! Help me out for a couple of :beers:!

205
bot.py
View File

@ -1,149 +1,120 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
__author__ = "Maël / Outout"
__author__ = ["Romain", "Maël / Outout"]
__licence__ = "WTFPL Licence 2.0"
from discord.ext import commands
import discord
from cogs.utils import checks
import datetime, re
import json, asyncio
import datetime
import json
import copy
import logging
from logging.handlers import RotatingFileHandler
import traceback
import sys
from collections import Counter
import os
import aiohttp
description = """
Je suis TuxBot, le bot qui vit de l'OpenSource ! ;)
"""
import config
import cogs.utils.cli_colors as colors
l_extensions = [
'cogs.basics',
#'cogs.test',
'cogs.admin',
'cogs.funs',
'cogs.utility',
'cogs.search',
'cogs.ci'
'cogs.admin',
# 'cogs.afk',
'cogs.basics',
'cogs.ci',
'cogs.cog_manager',
'cogs.filter_messages',
'cogs.funs',
'cogs.passport',
'cogs.role',
'cogs.search',
'cogs.send_logs',
'cogs.sondage',
'cogs.utility'
]
# DISCORD LOGGER #
discord_logger = logging.getLogger('discord')
discord_logger.setLevel(logging.CRITICAL)
log = logging.getLogger()
log.setLevel(logging.INFO)
handler = logging.FileHandler(filename='logs/discord.log', encoding='utf-8', mode='w')
log.addHandler(handler)
help_attrs = dict(hidden=True, in_help=True, name="DONOTUSE")
# CREDENTIALS #
try:
def load_credentials():
with open('params.json') as f:
return json.load(f)
except:
print("Le fichier de paramètre est introuvable, veuillez le créer et le configurer.")
class TuxBot(commands.Bot):
def __init__ (self):
self.config = config
super().__init__(command_prefix=self.config.prefix[0],
description=self.config.description,
pm_help=None,
help_attrs=help_attrs)
credentials = load_credentials()
prefix = credentials.get("prefix", ["."])
bot = commands.Bot(command_prefix=prefix, description=description, pm_help=None, help_attrs=help_attrs)
self.client_id = self.config.client_id
self.session = aiohttp.ClientSession(loop=self.loop)
self._events = []
@bot.event
async def on_command_error(error, ctx):
if isinstance(error, commands.NoPrivateMessage):
await bot.send_message(ctx.message.author, 'Cette commande ne peut pas être utilisée en message privée.')
elif isinstance(error, commands.DisabledCommand):
await bot.send_message(ctx.message.author, 'Désoler mais cette commande est désactivé, elle ne peut donc pas être utilisée.')
elif isinstance(error, commands.CommandInvokeError):
print('In {0.command.qualified_name}:'.format(ctx), file=sys.stderr)
traceback.print_tb(error.original.__traceback__)
print('{0.__class__.__name__}: {0}'.format(error.original), file=sys.stderr)
@bot.event
async def on_ready():
print('---------------------')
print('CONNECTÉ :')
print(""" Nom d\'utilisateur : {0.name}#{0.discriminator}
ID : {0.id}""".format(bot.user))
print('Merci d\'utiliser TuxBot')
print('---------------------')
await bot.change_presence(game=discord.Game(name=credentials.get("game", "Manger des pommes | .help")), status=discord.Status("dnd"), afk=False)
if bot.client_id == None:
bot.client_id = bot.user.id
if not hasattr(bot, 'uptime'):
bot.uptime = datetime.datetime.utcnow()
self.add_command(self.do)
@bot.event
async def on_resumed():
print('resumed...')
for extension in l_extensions:
try:
self.load_extension(extension)
print(f"{colors.text_colors.GREEN}\"{extension}\" chargé !{colors.ENDC}")
except Exception as e:
print(f"{colors.text_colors.RED}Impossible de charger l'extension {extension}\n{type(e).__name__}: {e}{colors.ENDC}", file=sys.stderr)
@bot.event
async def on_message(message):
if message.author.bot:
return
async def on_command_error(self, ctx, error):
if isinstance(error, commands.NoPrivateMessage):
await ctx.author.send('Cette commande ne peut pas être utilisee en message privee.')
elif isinstance(error, commands.DisabledCommand):
await ctx.author.send('Desoler mais cette commande est desactive, elle ne peut donc pas être utilisée.')
elif isinstance(error, commands.CommandInvokeError):
print(f'In {ctx.command.qualified_name}:', file=sys.stderr)
traceback.print_tb(error.original.__traceback__)
print(f'{error.original.__class__.__name__}: {error.original}', file=sys.stderr)
try:
await bot.process_commands(message)
except Exception as e:
print('Erreur rencontré : \n {}: {} \n \n'.format(type(e).__name__, e))
async def on_ready(self):
if not hasattr(self, 'uptime'):
self.uptime = datetime.datetime.utcnow()
@bot.command(pass_context=True, hidden=True)
@checks.is_owner()
async def do(ctx, times : int, *, command):
"""Repeats a command a specified number of times."""
msg = copy.copy(ctx.message)
msg.content = command
for i in range(times):
await bot.process_commands(msg)
log_channel_id = self.get_channel(int(self.config.log_channel_id))
@bot.command(pass_context=True)
async def github(ctx):
"""Pour voir mon code"""
text = "How tu veux voir mon repos Github pour me disséquer ? Pas de soucis ! Je suis un Bot, je ne ressens pas la douleur !\n https://github.com/outout14/tuxbot-bot"
em = discord.Embed(title='Repos TuxBot-Bot', description=text, colour=0xE9D460)
em.set_author(name='Outout', icon_url="https://avatars0.githubusercontent.com/u/14958554?v=3&s=400")
await ctx.send(embed=em)
print('\n\n---------------------')
print('CONNECTÉ :')
print(f'Nom d\'utilisateur: {self.user} {colors.text_style.DIM}(ID: {self.user.id}){colors.ENDC}')
print(f'Channel de log: {log_channel_id} {colors.text_style.DIM}(ID: {log_channel_id.id}){colors.ENDC}')
print(f'Prefix: {self.config.prefix[0]}')
print('Merci d\'utiliser TuxBot')
print('---------------------\n\n')
async def on_command_error(self, ctx, error):
if isinstance(error, commands.NoPrivateMessage):
await ctx.author.send('Cette commande ne peut pas être utilisée en message privée.')
elif isinstance(error, commands.DisabledCommand):
await ctx.author.send('Désoler mais cette commande est désactivé, elle ne peut donc pas être utilisée.')
elif isinstance(error, commands.CommandInvokeError):
print(f'In {ctx.command.qualified_name}:', file=sys.stderr)
traceback.print_tb(error.original.__traceback__)
print(f'{error.original.__class__.__name__}: {error.original}', file=sys.stderr)
await self.change_presence(status=discord.Status.dnd, activity=discord.Game(name=self.config.game))
async def on_resumed():
print('resumed...')
async def on_message(self, message):
if message.author.bot:
return
try:
await self.process_commands(message)
except Exception as e:
print(f'{colors.text_colors.RED}Erreur rencontré : \n {type(e).__name__}: {e}{colors.ENDC} \n \n')
def run(self):
super().run(self.config.token, reconnect=True)
@checks.has_permissions(administrator=True)
@commands.command(pass_context=True, hidden=True)
async def do(ctx, times: int, *, command):
"""Repeats a command a specified number of times."""
msg = copy.copy(ctx.message)
msg.content = command
for i in range(times):
await bot.process_commands(msg)
## LOAD ##
if __name__ == '__main__':
try:
credentials = load_credentials()
token = credentials.get('token')
if token is None:
print("/!\ Le token est manquant dans le fichier params.json...")
bot.client_id = credentials.get('client_id', None)
except:
print("Impossible de démarer TuxBot dû à une erreur inconnue.")
for extension in l_extensions:
try:
bot.load_extension(extension)
except Exception as e:
print('Impossible de charger l\'extension {}\n{}: {}'.format(extension, type(e).__name__, e))
try:
bot.run(token)
except:
print("Une erreur est survenue avec votre Token, merci de le vérifier.")
handlers = log.handlers[:]
for hdlr in handlers:
hdlr.close()
log.removeHandler(hdlr)
if os.path.exists('config.py') is not True:
print(f"{colors.text_colors.RED}Veuillez créer le fichier config.py{colors.ENDC}"); exit()
tuxbot = TuxBot()
tuxbot.run()

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,105 +1,336 @@
from discord.ext import commands
import discord
import aiohttp
import asyncio
import time
import discord
from .utils import checks
from .utils.checks import get_user
import json
import random
import datetime
import requests
class Admin:
"""Commandes secrètes d'administration."""
"""Commandes secrètes d'administration."""
def __init__(self, bot):
self.bot = bot
@checks.is_owner()
@commands.command(name='unload_cog', hidden=True)
async def _unload(self, ctx, module: str):
"""Unloads a module."""
try:
self.bot.unload_extension("cogs."+module)
except Exception as e:
await ctx.send('\N{PISTOL}')
await ctx.send('{}: {}'.format(type(e).__name__, e))
else:
await ctx.send('\N{OK HAND SIGN}')
print("cog : " + str(module) + " activé")
def __init__(self, bot):
self.bot = bot
"""--------------------------------------------------------------------------------------------------------------------------"""
"""--------------------------------------------------------------------------------------------------------------------------"""
@checks.is_owner()
@commands.command(name='load_cog', hidden=True)
async def _load(self, ctx, module: str):
"""Unloads a module."""
try:
self.bot.load_extension("cogs."+module)
except Exception as e:
await ctx.send('\N{PISTOL}')
await ctx.send('{}: {}'.format(type(e).__name__, e))
else:
await ctx.send('\N{OK HAND SIGN}')
print("cog : " + str(module) + " desactivé")
@checks.has_permissions(administrator=True)
@commands.command(pass_context=True)
async def ban(self, ctx, user, *, reason=""):
"""Ban user"""
user = get_user(ctx.message, user)
if user:
try:
await user.ban(reason=reason)
return_msg = "`{}` a été banni\n".format(user.mention)
if reason:
return_msg += "raison : `{}`".format(reason)
return_msg += "."
await ctx.send(return_msg)
except discord.Forbidden:
await ctx.send('Impossible de bannir cet user, probleme de permission.')
else:
return await ctx.send('Impossible de trouver l\'user.')
"""--------------------------------------------------------------------------------------------------------------------------"""
"""--------------------------------------------------------------------------------------------------------------------------"""
@checks.is_owner()
@commands.command(name='reload_cog', hidden=True)
async def _reload(self, ctx, *, module: str):
"""Reloads a module."""
try:
self.bot.unload_extension("cogs."+module)
self.bot.load_extension("cogs."+module)
await ctx.send("Je te reload ca")
except Exception as e: #TODO : A virer dans l'event on_error
await ctx.send(':( Erreur :')
await ctx.send('{}: {}'.format(type(e).__name__, e))
else:
await ctx.send('\N{OK HAND SIGN}')
print("cog : " + str(module) + " relancé")
@checks.has_permissions(administrator=True)
@commands.command(pass_context=True)
async def kick(self, ctx, user, *, reason=""):
"""Kick a user"""
user = get_user(ctx.message, user)
if user:
try:
await user.kick(reason=reason)
return_msg = "`{}` a été kické\n".format(user.mention)
if reason:
return_msg += "raison : `{}`".format(reason)
return_msg += "."
await ctx.send(return_msg)
except discord.Forbidden:
await ctx.send('Impossible de kicker cet user, probleme de permission.')
else:
return await ctx.send('Impossible de trouver l\'user.')
"""--------------------------------------------------------------------------------------------------------------------------"""
"""--------------------------------------------------------------------------------------------------------------------------"""
@checks.is_owner()
@commands.command(name='clear', pass_context=True, hidden=True)
async def _clear(self, ctx, number: int):
@checks.has_permissions(administrator=True)
@commands.command(name='clear', pass_context=True)
async def _clear(self, ctx, number: int, silent: str = True):
"""Clear <number> of message(s)"""
try:
await ctx.message.delete()
except:
print("Impossible de supprimer le message \"" + str(ctx.message.content) + "\"")
if number < 1000:
async for message in ctx.message.channel.history(limit=number):
try:
await message.delete()
except Exception as e: #TODO : A virer dans l'event on_error
if silent is not True:
await ctx.send(':sob: Une erreur est survenue : \n {}: {}'.format(type(e).__name__, e))
if silent is not True:
await ctx.send("Hop voila j'ai viré des messages! Hello World")
print(str(number)+" messages ont été supprimés")
else:
await ctx.send('Trop de messages, entre un nombre < 1000')
await ctx.message.delete()
if number < 1000:
async for message in ctx.message.channel.history(limit=number):
try:
await message.delete()
except Exception as e: #TODO : A virer dans l'event on_error
await ctx.send(':sob: Une erreur est survenue : \n {}: {}'.format(type(e).__name__, e))
await ctx.send("Hop voila j'ai viré des messages! Hello World")
print(str(number)+" messages ont été supprimés")
else:
await ctx.send('Trop de messages, entre un nombre < 1000')
"""--------------------------------------------------------------------------------------------------------------------------"""
"""--------------------------------------------------------------------------------------------------------------------------"""
@checks.has_permissions(administrator=True)
@commands.command(name='say', pass_context=True)
async def _say(self, ctx, *, tosay:str):
"""Say a message in the current channel"""
try:
try:
await ctx.message.delete()
except:
print("Impossible de supprimer le message \"" + str(ctx.message.content) + "\"")
await ctx.send(tosay)
except Exception as e: #TODO : A virer dans l'event on_error
await ctx.send(':sob: Une erreur est survenue : \n {}: {}'.format(type(e).__name__, e))
@checks.is_owner()
@commands.command(name='say', pass_context=True, hidden=True)
async def _say(self, ctx, *direuh:str):
try:
dire = ctx.message.content.split("say ")
await ctx.message.delete()
await ctx.send(dire[1])
except Exception as e: #TODO : A virer dans l'event on_error
await ctx.send(':sob: Une erreur est survenue : \n {}: {}'.format(type(e).__name__, e))
"""--------------------------------------------------------------------------------------------------------------------------"""
"""--------------------------------------------------------------------------------------------------------------------------"""
@checks.has_permissions(administrator=True)
@commands.command(name='sayto', pass_context=True)
async def _sayto(self, ctx, id:int, *, tosay:str):
"""Say a message in the <id> channel"""
try:
chan = self.bot.get_channel(id)
try:
await ctx.message.delete()
except:
print("Impossible de supprimer le message \"" + str(ctx.message.content) + "\"")
try:
await chan.send(tosay)
except Exception as e:
print("Impossible d'envoyer le message dans " + str(id))
except Exception as e: #TODO : A virer dans l'event on_error
await ctx.send(':sob: Une erreur est survenue : \n {}: {}'.format(type(e).__name__, e))
@checks.is_owner()
@commands.command(pass_context=True, hidden=True)
async def _clearterm(self, ctx):
clear = "\n" * 100
print(clear)
await ctx.send(":ok_hand: It's good")
"""--------------------------------------------------------------------------------------------------------------------------"""
"""--------------------------------------------------------------------------------------------------------------------------"""
@checks.has_permissions(administrator=True)
@commands.command(name='sayto_dm', pass_context=True)
async def _sayto_dm(self, ctx, id:int, *, tosay:str):
"""Say a message to the <id> user"""
try:
user = self.bot.get_user(id)
try:
await ctx.message.delete()
except:
print("Impossible de supprimer le message \"" + str(ctx.message.content) + "\"")
try:
await user.send(tosay)
except Exception as e:
print("Impossible d'envoyer le message dans " + str(id))
except Exception as e: #TODO : A virer dans l'event on_error
await ctx.send(':sob: Une erreur est survenue : \n {}: {}'.format(type(e).__name__, e))
"""--------------------------------------------------------------------------------------------------------------------------"""
@checks.has_permissions(administrator=True)
@commands.command(name='editsay', pass_context=True)
async def _editsay(self, ctx, id:int, *, new_content:str):
"""Edit a bot's message"""
try:
try:
await ctx.message.delete()
except:
print("Impossible de supprimer le message \"" + str(ctx.message.content) + "\"")
toedit = await ctx.channel.get_message(id)
except discord.errors.NotFound:
await ctx.send("Impossible de trouver le message avec l'id `{}` sur ce salon".format(id))
return
try:
await toedit.edit(content=str(new_content))
except discord.errors.Forbidden:
await ctx.send("J'ai po les perms pour editer mes messages :(")
"""--------------------------------------------------------------------------------------------------------------------------"""
@checks.has_permissions(administrator=True)
@commands.command(name='addreaction', pass_context=True)
async def _addreaction(self, ctx, id:int, reaction:str):
"""Add reactions to a message"""
try:
try:
await ctx.message.delete()
except:
print("Impossible de supprimer le message \"" + str(ctx.message.content) + "\"")
toadd = await ctx.channel.get_message(id)
except discord.errors.NotFound:
await ctx.send("Impossible de trouver le message avec l'id `{}` sur ce salon".format(id))
return
try:
await toadd.add_reaction(reaction)
except discord.errors.Forbidden:
await ctx.send("J'ai po les perms pour ajouter des réactions :(")
"""--------------------------------------------------------------------------------------------------------------------------"""
@checks.has_permissions(administrator=True)
@commands.command(name='delete', pass_context=True)
async def _delete(self, ctx, id:int):
"""Delete message in current channel"""
try:
try:
await ctx.message.delete()
except:
print("Impossible de supprimer le message \"" + str(ctx.message.content) + "\"")
todelete = await ctx.channel.get_message(id)
except discord.errors.NotFound:
await ctx.send("Impossible de trouver le message avec l'id `{}` sur ce salon".format(id))
return
try:
await todelete.delete()
except discord.errors.Forbidden:
await ctx.send("J'ai po les perms pour supprimer des messages :(")
"""--------------------------------------------------------------------------------------------------------------------------"""
@checks.has_permissions(administrator=True)
@commands.command(name='deletefrom', pass_context=True)
async def _deletefrom(self, ctx, chan_id:int, *, message_id:str):
"""Delete message in <chan_id> channel"""
try:
chan = self.bot.get_channel(chan_id)
try:
await ctx.message.delete()
except:
print("Impossible de supprimer le message \"" + str(ctx.message.content) + "\"")
todelete = await chan.get_message(message_id)
except discord.errors.NotFound:
await ctx.send("Impossible de trouver le message avec l'id `{}` sur le salon".format(id))
return
try:
await todelete.delete()
except discord.errors.Forbidden:
await ctx.send("J'ai po les perms pour supprimer le message :(")
"""--------------------------------------------------------------------------------------------------------------------------"""
@checks.has_permissions(administrator=True)
@commands.command(name='embed', pass_context=True)
async def _embed(self, ctx, *, msg: str = "help"):
"""Send an embed"""
if msg != "help":
ptext = title = description = image = thumbnail = color = footer = author = None
timestamp = discord.Embed.Empty
embed_values = msg.split('|')
for i in embed_values:
if i.strip().lower().startswith('ptext='):
ptext = i.strip()[6:].strip()
elif i.strip().lower().startswith('title='):
title = i.strip()[6:].strip()
elif i.strip().lower().startswith('description='):
description = i.strip()[12:].strip()
elif i.strip().lower().startswith('desc='):
description = i.strip()[5:].strip()
elif i.strip().lower().startswith('image='):
image = i.strip()[6:].strip()
elif i.strip().lower().startswith('thumbnail='):
thumbnail = i.strip()[10:].strip()
elif i.strip().lower().startswith('colour='):
color = i.strip()[7:].strip()
elif i.strip().lower().startswith('color='):
color = i.strip()[6:].strip()
elif i.strip().lower().startswith('footer='):
footer = i.strip()[7:].strip()
elif i.strip().lower().startswith('author='):
author = i.strip()[7:].strip()
elif i.strip().lower().startswith('timestamp'):
timestamp = ctx.message.created_at
else:
if description is None and not i.strip().lower().startswith('field='):
description = i.strip()
if color:
if color.startswith('#'):
color = color[1:]
if not color.startswith('0x'):
color = '0x' + color
if ptext is title is description is image is thumbnail is color is footer is author is None and 'field=' not in msg:
try:
await ctx.message.delete()
except:
print("Impossible de supprimer le message \"" + str(ctx.message.content) + "\"")
return await ctx.send(content=None,
embed=discord.Embed(description=msg))
if color:
em = discord.Embed(timestamp=timestamp, title=title, description=description, color=int(color, 16))
else:
em = discord.Embed(timestamp=timestamp, title=title, description=description)
for i in embed_values:
if i.strip().lower().startswith('field='):
field_inline = True
field = i.strip().lstrip('field=')
field_name, field_value = field.split('value=')
if 'inline=' in field_value:
field_value, field_inline = field_value.split('inline=')
if 'false' in field_inline.lower() or 'no' in field_inline.lower():
field_inline = False
field_name = field_name.strip().lstrip('name=')
em.add_field(name=field_name, value=field_value.strip(), inline=field_inline)
if author:
if 'icon=' in author:
text, icon = author.split('icon=')
if 'url=' in icon:
em.set_author(name=text.strip()[5:], icon_url=icon.split('url=')[0].strip(), url=icon.split('url=')[1].strip())
else:
em.set_author(name=text.strip()[5:], icon_url=icon)
else:
if 'url=' in author:
em.set_author(name=author.split('url=')[0].strip()[5:], url=author.split('url=')[1].strip())
else:
em.set_author(name=author)
if image:
em.set_image(url=image)
if thumbnail:
em.set_thumbnail(url=thumbnail)
if footer:
if 'icon=' in footer:
text, icon = footer.split('icon=')
em.set_footer(text=text.strip()[5:], icon_url=icon)
else:
em.set_footer(text=footer)
try:
await ctx.message.delete()
except:
print("Impossible de supprimer le message \"" + str(ctx.message.content) + "\"")
await ctx.send(content=ptext, embed=em)
else:
embed=discord.Embed(title="Aide sur l'utilisation de la commande .embed:")
embed.add_field(name="Titre:", value="title=<le titre>", inline=True)
embed.add_field(name="Description:", value="description=<la description>", inline=True)
embed.add_field(name="Couleur:", value="color=<couleur en hexa>", inline=True)
embed.add_field(name="Image:", value="image=<url de l'image (en https)>", inline=True)
embed.add_field(name="Thumbnail:", value="thumbnail=<url de l'image>", inline=True)
embed.add_field(name="Auteur:", value="author=<nom de l'auteur>", inline=True)
embed.add_field(name="Icon", value="icon=<url de l'image>", inline=True)
embed.add_field(name="Footer", value="footer=<le footer>", inline=True)
embed.set_footer(text="Exemple: .embed title=Un titre | description=Une description | color=3AB35E | field=name=test value=test")
await ctx.send(embed=embed)
"""--------------------------------------------------------------------------------------------------------------------------"""
def setup(bot):
bot.add_cog(Admin(bot))
bot.add_cog(Admin(bot))

78
cogs/afk.py Executable file
View File

@ -0,0 +1,78 @@
from discord.ext import commands
import random
class AFK:
"""Commandes utilitaires."""
def __init__(self, bot):
self.bot = bot
"""---------------------------------------------------------------------"""
@commands.command(pass_context=True)
async def afk(self, ctx):
user = ctx.message.author
try:
await user.edit(nick="[AFK] "+str(user.name))
author = ctx.message.author
channel = await author.create_dm()
await channel.send("Ton pseudo a prit le prefix `[AFK]` pour "
"monter que tu es absent,")
await channel.send("tu auras juste a mettre un message pour que "
"je signale ton retour parmis nous et que je "
"retire le prefix `[AFK]` de ton pseudo 😉")
except KeyError:
print('')
author = ctx.message.author
channel = await author.create_dm()
await channel.send("Tu auras juste a mettre un message pour que "
"je signale ton retour parmis nous 😉")
msgs = ["s'absente de discord quelques instants",
"se casse de son pc",
"va sortir son chien",
"reviens bientôt",
"va nourrir son cochon",
"va manger des cookies",
"va manger de la poutine",
"va faire caca",
"va faire pipi"]
msg = random.choice(msgs)
await ctx.send("**{}** {}...".format(ctx.message.author.mention, msg))
"""---------------------------------------------------------------------"""
async def on_message(message):
ni = str(message.author.nick)
if ni:
ni2 = ni.split(" ")
if "[AFK]" in ni2:
user = message.author
await user.edit(nick=None)
msgs = ["a réssuscité",
"est de nouveau parmi nous",
"a fini de faire caca",
"a fini d'uriner",
"n'est plus mort",
"est de nouveau sur son PC",
"a fini de manger sa poutine",
"a fini de danser",
"s'est réveillé",
"est de retour dans ce monde cruel"]
msg = random.choice(msgs)
await message.channel.send("**{}** {} !".format(
message.author.mention, msg))
def setup(bot):
bot.add_cog(AFK(bot))

View File

@ -1,56 +1,67 @@
from discord.ext import commands
from random import choice, shuffle
import aiohttp
import asyncio
import time
import discord
import platform, socket
import os
import platform
import socket
import wikipedia, bs4
class General:
"""Commandes générales."""
def __init__(self, bot):
self.bot = bot
@commands.command()
async def ping(self, ctx):
t1 = time.perf_counter()
await ctx.trigger_typing()
t2 = time.perf_counter()
result = round((t2-t1)*1000)
if int(result) >=200:
em = discord.Embed(title="Ping : " + str(result) + "ms", description="... c'est quoi ce ping !", colour=0xFF1111)
await ctx.send(embed=em)
elif int(result) > 100 and int(result) < 200:
em = discord.Embed(title="Ping : " + str(result) + "ms", description="Ca va, ça peut aller, mais j'ai l'impression d'avoir 40 ans !", colour=0xFFA500)
await ctx.send(embed=em)
elif int(result) <= 100:
em = discord.Embed(title="Ping : " + str(result) + "ms", description="Wow c'te vitesse de réaction, je m'épate moi-même !",colour=0x11FF11)
await ctx.send(embed=em)
##INFO##
@commands.command()
async def info(self, ctx):
"""Affiches des informations sur le bot"""
text = open('texts/info.md').read()
os_info = str(platform.system()) + " / " + str(platform.release())
em = discord.Embed(title='Informations sur TuxBot', description=text.format(os_info, platform.python_version(), socket.gethostname(), discord.__version__), colour=0x89C4F9)
em.set_footer(text=os.getcwd() + "/bot.py")
await ctx.send(embed=em)
import subprocess
## HELP PLZ ##
@commands.command()
async def help(self, ctx):
"""Affiches l'aide du bot"""
text = open('texts/help.md').read()
em = discord.Embed(title='Commandes de TuxBot', description=text, colour=0x89C4F9)
await ctx.send(embed=em)
class Basics:
"""Commandes générales."""
def __init__(self, bot):
self.bot = bot
@commands.command()
async def ping(self, ctx):
ping_res = str(subprocess.Popen(["/bin/ping", "-c1", "discordapp.com"], stdout=subprocess.PIPE).stdout.read())
formated_res = [item for item in ping_res.split() if 'time=' in item]
result = str(formated_res[0])[5:]
if float(result) >= 200:
em = discord.Embed(title="Ping : " + str(result) + "ms",
description="... c'est quoi ce ping !",
colour=0xFF1111)
await ctx.send(embed=em)
elif float(result) > 100 < 200:
em = discord.Embed(title="Ping : " + str(result) + "ms",
description="Ca va, ça peut aller, mais j'ai "
"l'impression d'avoir 40 ans !",
colour=0xFFA500)
await ctx.send(embed=em)
else:
em = discord.Embed(title="Ping : " + str(result) + "ms",
description="Wow c'te vitesse de réaction, "
"je m'épate moi-même !",
colour=0x11FF11)
await ctx.send(embed=em)
"""--------------------------------------------------------------------------------------------------------------------------"""
@commands.command()
async def info(self, ctx):
"""Affiches des informations sur le bot"""
text = open('texts/info.md').read()
os_info = str(platform.system()) + " / " + str(platform.release())
em = discord.Embed(title='Informations sur TuxBot',
description=text.format(os_info,
platform.python_version(),
socket.gethostname(),
discord.__version__),
colour=0x89C4F9)
em.set_footer(text="/home/****/bot.py")
await ctx.send(embed=em)
"""--------------------------------------------------------------------------------------------------------------------------"""
@commands.command()
async def help(self, ctx):
"""Affiches l'aide du bot"""
text = open('texts/help.md').read()
em = discord.Embed(title='Commandes de TuxBot', description=text,
colour=0x89C4F9)
await ctx.send(embed=em)
def setup(bot):
bot.add_cog(General(bot))
bot.add_cog(Basics(bot))

View File

@ -1,188 +1,249 @@
from discord.ext import commands
from random import choice, shuffle
import aiohttp
import asyncio
import discord
import platform, socket
import os
import sqlite3
import time
import datetime, pytz
from .utils import checks
from .utils import db
from .utils.checks import get_user, check_date
from datetime import date
import calendar
import datetime
#### SQL #####
conn = sqlite3.connect('tuxbot.db') #Connexion SQL
import pymysql
import requests
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS users(
id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,
userid TEXT,
username TEXT,
os TEXT,
config TEXT,
useravatar TEXT,
userbirth TEXT,
pays TEXT,
cidate TEXT,
cibureau TEXT
)
""")# Creation table Utilisateur si premiere fois
conn.commit()
class Identity:
"""Commandes des cartes d'identité ."""
"""Commandes des cartes d'identité ."""
def __init__(self, bot):
self.bot = bot
def __init__(self, bot):
self.bot = bot
@commands.group(name="ci", no_pm=True, pass_context=True)
async def _ci(self, ctx):
"""Cartes d'identité"""
if ctx.invoked_subcommand is None:
text = open('texts/ci-info.md').read()
em = discord.Embed(title='Commandes de carte d\'identité de TuxBot', description=text, colour=0x89C4F9)
await ctx.send(embed=em)
self.conn = db.connect_to_db(self)
self.cursor = self.conn.cursor()
@_ci.command(pass_context=True, name="show")
async def ci_test(self, ctx, args : discord.Member):
self.cursor.execute("""SHOW TABLES LIKE 'users'""")
result = self.cursor.fetchone()
def isexist(var):
if not var:
return "Non renseigné."
else:
return var
if not result:
# Creation table Utilisateur si premiere fois
sql = "CREATE TABLE users ( `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, userid TEXT null, username TEXT null, os TEXT null, config TEXT null, useravatar TEXT null, userbirth TEXT null, pays TEXT null, cidate TEXT null, cibureau TEXT null);"
self.cursor.execute(sql)
cursor.execute("""SELECT userid, username, useravatar, userbirth, cidate, cibureau, os, config, pays, id FROM users WHERE userid=?""",(args.id,))
result = cursor.fetchone()
@commands.group(name="ci", no_pm=True, pass_context=True)
async def _ci(self, ctx):
"""Cartes d'identité"""
if ctx.invoked_subcommand is None:
text = open('texts/ci-info.md').read()
em = discord.Embed(title='Commandes de carte d\'identité de TuxBot', description=text, colour=0x89C4F9)
await ctx.send(embed=em)
if not result:
await ctx.send(ctx.message.author.mention + "> :x: Désolé mais {} est sans papier !".format(args.mention))
@_ci.command(pass_context=True, name="show")
async def ci_show(self, ctx, args: str = None):
self.conn = db.connect_to_db(self)
self.cursor = self.conn.cursor()
else:
try:
userbirth = result[3].split(" ")
cidate = result[4].split(" ")
embed=discord.Embed(title="Carte d'identité | Communisme Linuxien")
embed.set_author(name=result[1], icon_url=result[2])
embed.set_thumbnail(url = result[2])
embed.add_field(name="Nom :", value=result[1], inline=True)
embed.add_field(name="Système d'exploitation :", value=isexist(result[6]), inline=True)
embed.add_field(name="Configuration Système : ", value=isexist(result[7]), inline=True)
embed.add_field(name="Date de naissance : ", value=userbirth[0], inline=True)
embed.add_field(name="Pays : ", value=isexist(result[8]), inline=True)
embed.add_field(name="Profil sur le web : ", value="https://tuxbot.outout.tech/user-{}".format(result[9]), inline=True)
embed.set_footer(text="Enregistré dans le bureau {} le {}.".format(result[5], cidate[0]))
await ctx.send(embed=embed)
except:
await ctx.send(ctx.message.author.mention + "> :x: Désolé mais la carte d'identité de {0} est trop longue de ce fait je ne peux te l'envoyer, essaye de l'aléger, {0} :wink: !".format(args.mention))
if args == None:
user = get_user(ctx.message, ctx.message.author.name)
else:
user = get_user(ctx.message, args)
@_ci.command(pass_context=True, name="register")
async def ci_register(self, ctx):
cursor.execute("""SELECT id, userid FROM users WHERE userid=?""", (ctx.message.author.id,))
existansw = cursor.fetchone()
if existansw != None:
await ctx.send("Mais tu as déja une carte d'identité ! u_u")
else:
date = datetime.datetime.now()
if user:
self.cursor.execute("""SELECT userid, username, useravatar, userbirth, cidate, cibureau, os, config, pays, id FROM users WHERE userid=%s""",(str(user.id)))
result = self.cursor.fetchone()
nd = str(date.day)
nd += "-"
nd += str(date.month)
nd += "-"
nd += str(date.year)
def isexist(var):
if not var:
return "Non renseigné."
else:
return var
cursor.execute("""INSERT INTO users(userid, username, useravatar, userbirth, cidate, cibureau) VALUES(?, ?, ?, ?, ?, ?)""", (ctx.message.author.id, ctx.message.author.name, ctx.message.author.avatar_url, ctx.message.author.created_at, nd, str(ctx.message.guild.name)))
conn.commit()
await ctx.send(":clap: Bievenue à toi {} dans le communisme {} ! Fait ``.ci`` pour plus d'informations !".format(ctx.message.author.name, str(ctx.message.guild.name)))
if not result:
await ctx.send(f"{ctx.message.author.mention}> :x: Désolé mais {user.mention} est sans papier !")
else:
try:
user_birth = datetime.datetime.fromisoformat(result[3])
user_birth_day = check_date(str(user_birth.day))
user_birth_month = check_date(str(user_birth.month))
@_ci.command(pass_context=True, name="delete")
async def ci_delete(self, ctx):
cursor.execute("""SELECT id, userid FROM users WHERE userid=?""", (ctx.message.author.id,))
existansw = cursor.fetchone()
if existansw != None:
cursor.execute("""DELETE FROM users WHERE userid =?""", (ctx.message.author.id,))
await ctx.send("Tu es maintenant sans papiers !")
else:
await ctx.send("Déja enregistre ta carte d'identité avant de la supprimer u_u (après c'est pas logique...)")
formated_user_birth = str(user_birth_day) + "/" + str(user_birth_month) + "/" + str(user_birth.year)
@_ci.command(pass_context=True, name="update")
async def ci_image(self, ctx):
try:
cursor.execute("""SELECT id, userid FROM users WHERE userid=?""", (ctx.message.author.id,))
existansw = cursor.fetchone()
try: ## a virer une fois le patch appliqué pour tout le monde
cidate = datetime.datetime.fromisoformat(result[4])
cidate_day = check_date(str(cidate.day)) ## a garder
cidate_month = check_date(str(cidate.month)) ## a garder
if existansw != None:
cursor.execute("""UPDATE users SET useravatar = ?, username = ?, cibureau = ? WHERE userid = ?""", (ctx.message.author.avatar_url, ctx.message.author.name, str(ctx.message.guild), ctx.message.author.id))
conn.commit()
await ctx.send(ctx.message.author.mention + "> Tu viens, en quelques sortes, de renaitre !")
else:
await ctx.send(ctx.message.author.mention + "> :x: Veuillez enregistrer votre carte d'identité pour commencer !")
formated_cidate = str(cidate_day) + "/" + str(cidate_month) + "/" + str(cidate.year) ## a garder
except ValueError: ## a virer une fois le patch appliqué pour tout le monde
formated_cidate = str(result[4]).replace('-', '/') ## a virer une fois le patch appliqué pour tout le monde
await ctx.send(f"{user.mention} vous êtes prié(e) de faire la commande `.ci update` afin de regler un probleme de date coté bdd") ## a virer une fois le patch appliqué pour tout le monde
except Exception as e: #TODO : A virer dans l'event on_error
await ctx.send(':( Erreur veuillez contacter votre administrateur :')
await ctx.send('{}: {}'.format(type(e).__name__, e))
embed=discord.Embed(title="Carte d'identité | Communisme Linuxien")
embed.set_author(name=result[1], icon_url=result[2])
embed.set_thumbnail(url = result[2])
embed.add_field(name="Nom :", value=result[1], inline=True)
embed.add_field(name="Système d'exploitation :", value=isexist(result[6]), inline=True)
embed.add_field(name="Configuration Système : ", value=isexist(result[7]), inline=True)
embed.add_field(name="Date de naissance sur discord : ", value=formated_user_birth, inline=True)
embed.add_field(name="Pays : ", value=isexist(result[8]), inline=True)
embed.add_field(name="Profil sur le web : ", value=f"https://tuxbot.outout.xyz/user-{result[9]}", inline=True)
embed.set_footer(text=f"Enregistré dans le bureau {result[5]} le {formated_cidate}.")
await ctx.send(embed=embed)
except Exception as e:
await ctx.send(f"{ctx.message.author.mention}> :x: Désolé mais la carte d'identité de {user.mention} est trop longue de ce fait je ne peux te l'envoyer, essaye de l'aléger, {user.mention} :wink: !")
await ctx.send(f':sob: Une erreur est survenue : \n {type(e).__name__}: {e}')
else:
return await ctx.send('Impossible de trouver l\'user.')
@_ci.command(pass_context=True, name="setconfig")
async def ci_setconfig(self, ctx, args_):
try:
args = ctx.message.content.split("setconfig ")
args = args[1]
cursor.execute("""SELECT id, userid FROM users WHERE userid=?""", (ctx.message.author.id,))
existansw = cursor.fetchone()
@_ci.command(pass_context=True, name="register")
async def ci_register(self, ctx):
self.conn = db.connect_to_db(self)
self.cursor = self.conn.cursor()
if existansw != None:
cursor.execute("""UPDATE users SET config = ? WHERE userid = ?""", (args, ctx.message.author.id))
conn.commit()
await ctx.send(ctx.message.author.mention + "> :ok_hand: Carte d'identité mise à jour !")
else:
await ctx.send(ctx.message.author.mention + "> :x: Veuillez enregistrer votre carte d'identité pour commencer !")
except:
await ctx.send(ctx.message.author.mention + "> :x: Il manque un paramètre !")
self.cursor.execute("""SELECT id, userid FROM users WHERE userid=%s""", (str(ctx.message.author.id)))
result = self.cursor.fetchone()
@_ci.command(pass_context=True, name="setos")
async def ci_setos(self, ctx, args_):
try:
args = ctx.message.content.split("setos ")
args = args[1]
cursor.execute("""SELECT id, userid FROM users WHERE userid=?""", (ctx.message.author.id,))
existansw = cursor.fetchone()
if result:
await ctx.send("Mais tu as déja une carte d'identité ! u_u")
else:
now = datetime.datetime.now()
if existansw != None:
cursor.execute("""UPDATE users SET os = ? WHERE userid = ?""", (args, ctx.message.author.id))
conn.commit()
await ctx.send(ctx.message.author.mention + "> :ok_hand: Carte d'identité mise à jour !")
else:
await ctx.send(ctx.message.author.mention + "> :x: Veuillez enregistrer votre carte d'identité pour commencer !")
except:
await ctx.send(ctx.message.author.mention + "> :x: Il manque un paramètre !")
self.cursor.execute("""INSERT INTO users(userid, username, useravatar, userbirth, cidate, cibureau) VALUES(%s, %s, %s, %s, %s, %s)""", (str(ctx.message.author.id), str(ctx.message.author), str(ctx.message.author.avatar_url_as(format="jpg", size=512)), str(ctx.message.author.created_at), now, str(ctx.message.guild.name)))
self.conn.commit()
await ctx.send(f":clap: Bievenue à toi {ctx.message.author.name} dans le communisme {ctx.message.guild.name} ! Fait ``.ci`` pour plus d'informations !")
@_ci.command(pass_context=True, name="setcountry")
async def ci_setcountry(self, ctx, args):
cursor.execute("""SELECT id, userid FROM users WHERE userid=?""", (ctx.message.author.id,))
existansw = cursor.fetchone()
@_ci.command(pass_context=True, name="delete")
async def ci_delete(self, ctx):
self.conn = db.connect_to_db(self)
self.cursor = self.conn.cursor()
if existansw != None:
cursor.execute("""UPDATE users SET pays = ? WHERE userid = ?""", (args, ctx.message.author.id))
conn.commit()
await ctx.send(ctx.message.author.mention + "> :ok_hand: Carte d'identité mise à jour !")
else:
await ctx.send(ctx.message.author.mention + "> :x: Veuillez enregistrer votre carte d'identité pour commencer !")
self.cursor.execute("""SELECT id, userid FROM users WHERE userid=%s""", (str(ctx.message.author.id)))
result = self.cursor.fetchone()
@_ci.command(pass_context=True, name="list")
async def ci_list(self, ctx):
cursor.execute("""SELECT id, username FROM users""")
rows = cursor.fetchall()
msg = ""
try:
for row in rows:
msg = msg + '{0} : {1} \n'.format(row[0], row[1])
await ctx.send(msg)
except:
await ctx.send(":x: Pas d'entrés")
if result:
self.cursor.execute("""DELETE FROM users WHERE userid =%s""", (str(ctx.message.author.id)))
self.conn.commit()
await ctx.send("Tu es maintenant sans papiers !")
else:
await ctx.send("Déja enregistre ta carte d'identité avant de la supprimer u_u (après c'est pas logique...)")
@_ci.command(pass_context=True, name="update")
async def ci_update(self, ctx):
self.conn = db.connect_to_db(self)
self.cursor = self.conn.cursor()
try:
self.cursor.execute("""SELECT id, userid FROM users WHERE userid=%s""", (str(ctx.message.author.id)))
result = self.cursor.fetchone()
if result:
self.cursor.execute("""SELECT cidate FROM users WHERE userid=%s""",(str(ctx.message.author.id)))
old_ci_date = self.cursor.fetchone()
try:
new_ci_date = datetime.datetime.fromisoformat(old_ci_date[0])
except ValueError:
old_ci_date = datetime.datetime.strptime(old_ci_date[0].replace('/', '-'), '%d-%m-%Y')
old_ci_date_day = check_date(str(old_ci_date.day))
old_ci_date_month = check_date(str(old_ci_date.month))
new_ci_date = f"{str(old_ci_date.year)}-{str(old_ci_date_month)}-{str(old_ci_date_day)} 00:00:00.000000"
await ctx.send("succes update")
self.cursor.execute("""UPDATE users SET cidate = %s WHERE userid = %s""", (str(new_ci_date), str(ctx.message.author.id)))
self.conn.commit()
self.cursor.execute("""UPDATE users SET useravatar = %s, username = %s, cibureau = %s WHERE userid = %s""", (str(ctx.message.author.avatar_url_as(format="jpg", size=512)), str(ctx.message.author), str(ctx.message.guild), str(ctx.message.author.id)))
self.conn.commit()
await ctx.send(f"{ctx.message.author.mention}> Tu viens, en quelques sortes, de renaitre !")
else:
await ctx.send(f"{ctx.message.author.mention}> :x: Veuillez enregistrer votre carte d'identité pour commencer !")
except Exception as e: #TODO : A virer dans l'event on_error
await ctx.send(':( Erreur veuillez contacter votre administrateur :')
await ctx.send(f'{type(e).__name__}: {e}')
@_ci.command(pass_context=True, name="setconfig")
async def ci_setconfig(self, ctx, *, conf: str = None):
self.conn = db.connect_to_db(self)
self.cursor = self.conn.cursor()
if conf:
self.cursor.execute("""SELECT id, userid FROM users WHERE userid=%s""", (str(ctx.message.author.id)))
result = self.cursor.fetchone()
if result:
self.cursor.execute("""UPDATE users SET config = %s WHERE userid = %s""", (str(conf), str(ctx.message.author.id)))
self.conn.commit()
await ctx.send(f"{ctx.message.author.mention}> :ok_hand: Carte d'identité mise à jour !")
else:
await ctx.send(f"{ctx.message.author.mention}> :x: Veuillez enregistrer votre carte d'identité pour commencer !")
else:
await ctx.send(f"{ctx.message.author.mention}> :x: Il manque un paramètre !")
@_ci.command(pass_context=True, name="setos")
async def ci_setos(self, ctx, *, conf: str = None):
self.conn = db.connect_to_db(self)
self.cursor = self.conn.cursor()
if conf:
self.cursor.execute("""SELECT id, userid FROM users WHERE userid=%s""", (str(ctx.message.author.id)))
result = self.cursor.fetchone()
if result:
self.cursor.execute("""UPDATE users SET os = %s WHERE userid = %s""", (str(conf), str(ctx.message.author.id)))
self.conn.commit()
await ctx.send(f"{ctx.message.author.mention}> :ok_hand: Carte d'identité mise à jour !")
else:
await ctx.send(f"{ctx.message.author.mention}> :x: Veuillez enregistrer votre carte d'identité pour commencer !")
else:
await ctx.send(f"{ctx.message.author.mention}> :x: Il manque un paramètre !")
@_ci.command(pass_context=True, name="setcountry")
async def ci_setcountry(self, ctx, *, country: str = None):
self.conn = db.connect_to_db(self)
self.cursor = self.conn.cursor()
if country:
self.cursor.execute("""SELECT id, userid FROM users WHERE userid=%s""", (str(ctx.message.author.id)))
result = self.cursor.fetchone()
if result:
self.cursor.execute("""UPDATE users SET pays = %s WHERE userid = %s""", (str(country), str(ctx.message.author.id)))
self.conn.commit()
await ctx.send(f"{ctx.message.author.mention}> :ok_hand: Carte d'identité mise à jour !")
else:
await ctx.send(f"{ctx.message.author.mention}> :x: Veuillez enregistrer votre carte d'identité pour commencer !")
else:
await ctx.send(f"{ctx.message.author.mention}> :x: Il manque un paramètre !")
@checks.has_permissions(administrator=True)
@_ci.command(pass_context=True, name="list")
async def ci_list(self, ctx):
self.conn = db.connect_to_db(self)
self.cursor = self.conn.cursor()
self.cursor.execute("""SELECT id, username FROM users""")
rows = self.cursor.fetchall()
msg = ""
try:
for row in rows:
row_id = row[0]
row_name = row[1].encode('utf-8')
msg += f"{str(row_id)} : {str(row_name)} \n"
post = requests.post("https://hastebin.com/documents", data=msg)
await ctx.send(f"{ctx.message.author.mention} liste posté avec succès sur :\nhttps://hastebin.com/{post.json()['key']}.txt")
with open('ci_list.txt', 'w', encoding='utf-8') as fp:
for row in rows:
row_id = row[0]
row_name = row[1]
fp.write(f"{str(row_id)} : {str(row_name)} \n")
except Exception as e:
await ctx.send(f':sob: Une erreur est survenue : \n {type(e).__name__}: {e}')
def setup(bot):
bot.add_cog(Identity(bot))
bot.add_cog(Identity(bot))

110
cogs/cog_manager.py Executable file
View File

@ -0,0 +1,110 @@
from discord.ext import commands
import discord
from .utils import checks
from .utils.paginator import HelpPaginator
class CogManager:
"""Gestionnaire des cogs"""
def __init__(self, bot):
self.bot = bot
"""--------------------------------------------------------------------------------------------------------------------------"""
@checks.has_permissions(administrator=True)
@commands.group(name="cogs", no_pm=True, pass_context=True, case_insensitive=True)
async def _cogs(self, ctx):
"""show help about 'cogs' command"""
if ctx.invoked_subcommand is None:
text = "Tuxbot - Commandes cogs\n-> .cogs <load/unload/reload/info> *{cog}* : <load/unload/reload/info> *{cog}*\n-> .cogs <null/!(load/unload/reload)>: affiche cette aide"
em = discord.Embed(title='Tuxbot - Commandes cogs', description=text, colour=0x89C4F9)
await ctx.send(embed=em)
"""--------------------------------------------------------------------------------------------------------------------------"""
@_cogs.command(name="load", pass_context=True)
async def cogs_load(self, ctx, cog: str = ""):
"""load a cog"""
if cog != "":
try:
self.bot.load_extension(cog)
await ctx.send('\N{OK HAND SIGN}')
print("cog : " + str(cog) + " chargé")
except Exception as e:
await ctx.send('\N{PISTOL}')
await ctx.send(f'{type(e).__name__}: {e}')
else:
text = "Tuxbot - Commandes cogs\n-> .cogs <load/unload/reload/info> *{cog}* : <load/unload/reload/info> *{cog}*\n-> .cogs <null/!(load/unload/reload)>: affiche cette aide"
em = discord.Embed(title='Tuxbot - Commandes cogs', description=text, colour=0x89C4F9)
await ctx.send(embed=em)
"""--------------------------------------------------------------------------------------------------------------------------"""
@_cogs.command(name="unload", pass_context=True)
async def cogs_unload(self, ctx, cog: str = ""):
"""unload a cog"""
if cog != "":
try:
self.bot.unload_extension(cog)
await ctx.send('\N{OK HAND SIGN}')
print("cog : " + str(cog) + " déchargé")
except Exception as e:
await ctx.send('\N{PISTOL}')
await ctx.send(f'{type(e).__name__}: {e}')
else:
text = "Tuxbot - Commandes cogs\n-> .cogs <load/unload/reload/info> *{cog}* : <load/unload/reload/info> *{cog}*\n-> .cogs <null/!(load/unload/reload)>: affiche cette aide"
em = discord.Embed(title='Tuxbot - Commandes cogs', description=text, colour=0x89C4F9)
await ctx.send(embed=em)
"""--------------------------------------------------------------------------------------------------------------------------"""
@_cogs.command(name="reload", pass_context=True)
async def cogs_reload(self, ctx, cog: str = ""):
"""reload a cog"""
if cog != "":
try:
self.bot.unload_extension(cog)
self.bot.load_extension(cog)
await ctx.send('\N{OK HAND SIGN}')
print("cog : " + str(cog) + " rechargé")
except Exception as e:
await ctx.send('\N{PISTOL}')
await ctx.send(f'{type(e).__name__}: {e}')
else:
text = "Tuxbot - Commandes cogs\n-> .cogs <load/unload/reload/info> *{cog}* : <load/unload/reload/info> *{cog}*\n-> .cogs <null/!(load/unload/reload)>: affiche cette aide"
em = discord.Embed(title='Tuxbot - Commandes cogs', description=text, colour=0x89C4F9)
await ctx.send(embed=em)
"""--------------------------------------------------------------------------------------------------------------------------"""
@_cogs.command(name="info", pass_context=True)
async def cogs_info(self, ctx, cog: str = ""):
"""show info about a cog"""
if cog != "":
try:
entity = self.bot.get_cog(cog)
if entity is None:
clean = cog.replace('@', '@\u200b')
await ctx.send(f'Command or category "{clean}" not found.')
else:
p = await HelpPaginator.from_cog(ctx, entity)
await p.paginate()
except Exception as e:
await ctx.send('\N{PISTOL}')
await ctx.send(f'{type(e).__name__}: {e}')
else:
text = "Tuxbot - Commandes cogs\n-> .cogs <load/unload/reload/info> *{cog}* : <load/unload/reload/info> *{cog}*\n-> .cogs <null/!(load/unload/reload)>: affiche cette aide"
em = discord.Embed(title='Tuxbot - Commandes cogs', description=text, colour=0x89C4F9)
await ctx.send(embed=em)
def setup(bot):
bot.add_cog(CogManager(bot))

24
cogs/dev.py Normal file
View File

@ -0,0 +1,24 @@
from discord.ext import commands
import discord
class Dev:
"""Gestionnaire des cogs"""
def __init__(self, bot):
self.bot = bot
"""--------------------------------------------------------------------------------------------------------------------------"""
@commands.command(name="test", no_pm=True, pass_context=True, case_insensitive=True)
async def _test(self, ctx):
"""show help about 'cogs' command"""
if ctx.invoked_subcommand is None:
text = "<:python:334346615366221825>"
em = discord.Embed(title='Some test', description=text, colour=0x89C4F9)
await ctx.send(embed=em)
def setup(bot):
bot.add_cog(Dev(bot))

52
cogs/filter_messages.py Executable file
View File

@ -0,0 +1,52 @@
from discord.ext import commands
import discord
import asyncio
import discord
import re
class FilterMessages:
"""Flitre des messages"""
def __init__(self, bot):
self.bot = bot
async def on_message(self, message):
no_pub_guild = [280805240977227776, 303633056944881686, 274247231534792704]
lien_channel = [280805783795662848, 508794201509593088]
sondage_channel = [394146769107419146, 477147964393914388]
if message.author.bot \
or str(message.author.id) in self.bot.config.authorized_id \
or message.channel.permissions_for(message.author).administrator is True:
return
discord_invite_regex = re.compile(r"(discord\.(gg|io|me|li)|discordapp\.com\/invite)\/[0-9A-Za-z]*", re.IGNORECASE)
invalid_link_regex = re.compile(r"^(\[[^\]]+\]|<\:[a-z0-9]+\:[0-9]+>) .+ https?:\/\/\S*$", re.IGNORECASE)
try:
if message.guild.id in no_pub_guild: ## discord invitation send by a non-admin and a non-authorized_id
if isinstance(discord_invite_regex.search(message.content), re.Match):
author = self.bot.get_user(message.author.id)
await message.delete()
await author.send("La pub pour les serveurs discord n'est pas autorisée ici")
if message.channel.id in lien_channel \
and not isinstance(invalid_link_regex.search(message.content), re.Match): ## link send without pattern
author = self.bot.get_user(message.author.id)
await message.delete()
await author.send("Votre message `" + content + "` a été supprimé du channel `liens` car il ne respecte pas la structure définie. Pour partager un lien veuillez suivre la structure suivante : ` [Sujet] Descirption http(s)://....`")
await author.send("Si vous voulez commenter ou discuter à propos d'un lien, veuillez le faire dans le channel `#discussion-des-liens`.")
if message.channel.id in sondage_channel: ## a non-sondage send by a non-admin
prefix_lenght = len(await self.bot.get_prefix(message))
command = (message.content.split()[0])[prefix_lenght:]
if command != "sondage":
await message.delete()
except AttributeError:
pass
def setup(bot):
bot.add_cog(FilterMessages(bot))

View File

@ -1,133 +1,188 @@
from discord.ext import commands
from random import choice, shuffle
import aiohttp
import asyncio
import discord
import urllib.request, json
import urllib.request
import json
import random
import requests
class Funs:
"""Commandes funs."""
"""Commandes funs."""
def __init__(self, bot):
self.bot = bot
def __init__(self, bot):
self.bot = bot
"""--------------------------------------------------------------------------------------------------------------------------"""
@commands.command()
async def avatar(self, ctx, user: discord.Member = None):
"""Récuperer l'avatar de ..."""
if user == None:
user = ctx.message.author
embed = discord.Embed(title="Avatar de : " + user.name,
url=user.avatar_url_as(format="png"),
description=f"[Voir en plus grand]({user.avatar_url_as(format='png')})")
embed.set_thumbnail(url=user.user.avatar_url_as(format="png"))
await ctx.send(embed=embed)
"""--------------------------------------------------------------------------------------------------------------------------"""
@commands.command(pass_context=True)
async def poke(self, ctx, user: discord.Member):
"""Poke quelqu'un"""
await ctx.send(":clap: Hey {0} tu t'es fait poker par {1} !".format(
user.mention, ctx.message.author.name))
await ctx.message.delete()
"""--------------------------------------------------------------------------------------------------------------------------"""
@commands.command()
async def btcprice(self, ctx):
"""Le prix du BTC"""
loading = await ctx.send("_réfléchis..._")
try:
url = urllib.request.urlopen("https://blockchain.info/fr/ticker")
btc = json.loads(url.read().decode())
except KeyError:
btc = 1
if btc == 1:
await loading.edit(content="Impossible d'accèder à l'API blockchain.info, "
"veuillez réessayer ultérieurment ! :c")
else:
frbtc = str(btc["EUR"]["last"]).replace(".", ",")
usbtc = str(btc["USD"]["last"]).replace(".", ",")
await loading.edit(content="Un bitcoin est égal à : {0}$US soit {1}€.".format(usbtc, frbtc))
"""--------------------------------------------------------------------------------------------------------------------------"""
@commands.command()
async def joke(self, ctx, number:str = 0):
"""Print a random joke in a json file"""
with open('texts/jokes.json') as js:
jk = json.load(js)
try:
if int(number) <= 15 and int(number) > 0:
clef = str(number)
else:
clef = str(random.randint(1,15))
except:
clef = str(random.randint(1,15))
joke = jk["{}".format(clef)]
@commands.command()
async def avatar(self, ctx, user : discord.Member):
"""Récuperer l'avatar de ..."""
embed = discord.Embed(title="Avatar de : " + user.name, url=user.avatar_url, description="[Voir en plus grand]({})".format(user.avatar_url))
embed.set_thumbnail(url=user.avatar_url)
await ctx.send(embed=embed)
embed = discord.Embed(title="Blague _{}_ : ".format(clef), description=joke['content'], colour=0x03C9A9)
embed.set_footer(text="Par " + joke['author'])
embed.set_thumbnail(url='https://outout.tech/tuxbot/blobjoy.png')
await ctx.send(embed=embed)
@commands.command(pass_context=True)
async def poke(self, ctx, user : discord.Member):
"""Poke quelqu'un"""
await ctx.send(":clap: Hey {0} tu t'es fait poker par {1} !".format(user.mention, ctx.message.author.name))
await ctx.message.delete()
"""--------------------------------------------------------------------------------------------------------------------------"""
@commands.command()
async def btcprice(self, ctx):
"""Le prix du BTC"""
loading = await ctx.send("_réfléchis..._")
try:
with urllib.request.urlopen("http://api.coindesk.com/v1/bpi/currentprice/EUR.json") as url:
data = json.loads(url.read().decode())
btc = data['bpi']['EUR']['rate']
btc = btc.split(".")
except:
btc = 1
@commands.command()
async def ethylotest(self, ctx):
"""Ethylotest simulator 2018"""
results_poulet = ["Désolé mais mon ethylotest est sous Windows Vista, "
"merci de patienter...",
"_(ethylotest)_ : Une erreur est survenue. Windows "
"cherche une solution à se problème.",
"Mais j'l'ai foutu où ce p\\*\\*\\* d'ethylotest de m\\*\\*\\* "
"bordel fait ch\\*\\*\\*",
"C'est pas possible z'avez cassé l'ethylotest !"]
results_client = ["D'accord, il n'y a pas de problème à cela je suis "
"complètement clean",
"Bien sur si c'est votre devoir !", "Suce bi\\*e !",
"J'ai l'air d'être bourré ?",
"_laissez moi prendre un bonbon à la menthe..._"]
if btc == 1:
await ctx.send("Impossible d'accèder à l'API coindesk.com, veuillez réessayer ultérieurment !")
else:
await loading.edit(content="Un bitcoin est égal à : " + btc[0] + "")
result_p = random.choice(results_poulet)
result_c = random.choice(results_client)
@commands.command()
async def joke(self, ctx):
"""Print a random joke in a json file"""
with open('texts/jokes.json') as js:
jk = json.load(js)
await ctx.send(":oncoming_police_car: Bonjour bonjour, contrôle "
"d'alcoolémie !")
await asyncio.sleep(0.5)
await ctx.send(":man: " + result_c)
await asyncio.sleep(1)
await ctx.send(":police_car: " + result_p)
clef = str(random.randint(1,13))
joke = jk["{}".format(clef)]
"""--------------------------------------------------------------------------------------------------------------------------"""
embed = discord.Embed(title="Blague _{}_ : ".format(clef), description=joke['content'], colour=0x03C9A9)
embed.set_footer(text="Par " + joke['author'])
embed.set_thumbnail(url='https://outout.tech/tuxbot/blobjoy.png')
await ctx.send(embed=embed)
@commands.command()
async def coin(self, ctx):
"""Coin flip simulator 2025"""
starts_msg = ["Je lance la pièce !", "C'est parti !", "C'est une pièce"
" d'un cent faut"
" pas la perdre",
"C'est une pièce d'un euro faut pas la perdre",
"Je lance !"]
results_coin = ["{0} pile", "{0} face", "{1} Heu c'est quoi pile c'est"
" quoi face enfaite ?",
"{1} Oh shit, je crois que je l'ai perdue",
"{1} Et bim je te vol ta pièce !",
"{0} Oh une erreur d'impression il n'y a ni pile ni"
" face !"]
@commands.command()
async def ethylotest(self, ctx):
"""Ethylotest simulator 2018"""
results_poulet = ["Désolé mais mon ethylotest est sous Windows Vista, merci de patienter...", "_(ethylotest)_ ``Une erreur est survenue. Windows cherche une solution à se problème...``", "Mais j'l'ai foutu où ce p*** d'ethylotest de m*** bordel fait ch*** tab***", "C'est pas possible z'avez cassé l'ethylotest !"]
results_client = ["D'accord, il n'y a pas de problème à cela je suis complètement clean", "Bien sur si c'est votre devoir !", "Suce bi** !", "J'ai l'air d'être bourré ?", "_laissez moi prendre un bonbon à la menthe..._"]
start = random.choice(starts_msg)
result = random.choice(results_coin)
result_p = random.choice(results_poulet)
result_c = random.choice(results_client)
await ctx.send(start)
await asyncio.sleep(0.6)
await ctx.send(result.format(":moneybag: Et la pièce retombe sur ...",
":robot:"))
await ctx.send(":oncoming_police_car: Bonjour bonjour, controle d'alcoolémie !")
await asyncio.sleep(0.5)
await ctx.send(":man: " + result_c)
await asyncio.sleep(1)
await ctx.send(":police_car: " + result_p)
"""--------------------------------------------------------------------------------------------------------------------------"""
@commands.command()
async def coin(self, ctx):
"""Coin flip simulator 2025"""
starts_msg = ["Je lance la pièce !", "C'est parti !", "C'est une pièce d'un cent faut pas la perdre", "C'est une pièce d'un euro faut pas la perdre", "Je lance !"]
results_coin = ["{0} pile", "{0} face", "{1} Heu c'est quoi pile c'est quoi face enfaite ?", "{1} Oh shit, je crois que je l'ai perdue", "{1} Et bim je te vol ta pièce !", "{0} Oh une erreur d'impression il n'y a ni pile ni face !"]
@commands.command()
async def pokemon(self, ctx):
"""Random pokemon fight"""
with open('texts/pokemons.json') as js:
jk = json.load(js)
start = random.choice(starts_msg)
result = random.choice(results_coin)
poke1 = jk[random.randint(1, 150)]
poke2 = jk[random.randint(1, 150)]
await ctx.send(start)
await asyncio.sleep(0.6)
await ctx.send(result.format(":moneybag: Et la pièce retombe sur ...", ":robot:"))
try:
if poke1['MaxHP'] > poke2['MaxHP']:
winer = poke1
else:
winer = poke2
except KeyError:
winer = poke1
@commands.command()
async def pokemon(self, ctx):
"""Random pokemon fight"""
with open('texts/pokemons.json') as js:
jk = json.load(js)
await ctx.send(":flag_white: **Le combat commence !**")
await asyncio.sleep(1)
await ctx.send(":loudspeaker: Les concurants sont {} contre {} ! Bonne"
" chance à eux !".format(poke1["Name"], poke2["Name"]))
await asyncio.sleep(0.5)
await ctx.send(":boom: {} commence et utilise {}".format(
poke1["Name"], poke1["Fast Attack(s)"][0]["Name"]))
await asyncio.sleep(1)
await ctx.send(":dash: {} réplique avec {}".format(
poke2["Name"], poke2["Fast Attack(s)"][0]["Name"]))
await asyncio.sleep(1.2)
await ctx.send("_le combat continue de se dérouler..._")
await asyncio.sleep(1.5)
await ctx.send(":trophy: Le gagnant est **{}** !".format(
winer["Name"]))
poke1 = jk[random.randint(1, 150)]
poke2 = jk[random.randint(1, 150)]
try:
if poke1['MaxHP'] > poke2['MaxHP']:
winer = poke1
else:
winer = poke2
except:
winer = poke1
await ctx.send(":flag_white: **Le combat commence !**")
await asyncio.sleep(1)
await ctx.send(":loudspeaker: Les concurants sont {} contre {} ! Bonne chance à eux !".format(poke1["Name"], poke2["Name"]))
await asyncio.sleep(0.5)
await ctx.send(":boom: {} commence et utilise {}".format(poke1["Name"], poke1["Fast Attack(s)"][0]["Name"]))
await asyncio.sleep(1)
await ctx.send(":dash: {} réplique avec {}".format(poke2["Name"], poke2["Fast Attack(s)"][0]["Name"]))
await asyncio.sleep(1.2)
await ctx.send("_le combat continue de se dérouler..._")
await asyncio.sleep(1.5)
await ctx.send(":trophy: Le gagnant est **{}** !".format(winer["Name"]))
@commands.command()
async def randomcat(self, ctx):
"""Display a random cat"""
r = requests.get('http://random.cat/meow.php')
cat = str(r.json()['file'])
embed = discord.Embed(title="Meow", description="[Voir le chat plus grand]({})".format(cat), colour=0x03C9A9)
embed.set_thumbnail(url=cat)
embed.set_author(name="Random.cat", url='https://random.cat/', icon_url='http://outout.tech/tuxbot/nyancat2.gif')
await ctx.send(embed=embed)
"""--------------------------------------------------------------------------------------------------------------------------"""
@commands.command()
async def randomcat(self, ctx):
"""Display a random cat"""
r = requests.get('http://aws.random.cat/meow')
cat = str(r.json()['file'])
embed = discord.Embed(title="Meow",
description="[Voir le chat plus grand]({})".
format(cat), colour=0x03C9A9)
embed.set_thumbnail(url=cat)
embed.set_author(name="Random.cat", url='https://random.cat/')
await ctx.send(embed=embed)
def setup(bot):
bot.add_cog(Funs(bot))
bot.add_cog(Funs(bot))

222
cogs/passport.py Executable file
View File

@ -0,0 +1,222 @@
from discord.ext import commands
import discord
from PIL import Image
from PIL import ImageOps
from .utils import checks
from .utils import db
from .utils.passport_generator import generate_passport
from .utils.checks import get_user, check_date
import asyncio, aiohttp, io, time, imghdr, os, shutil, json, textwrap, re, math, datetime
class Passport:
"""Commandes des passeports ."""
def __init__(self, bot):
self.bot = bot
self.conn = db.connect_to_db(self)
self.cursor = self.conn.cursor()
self.cursor.execute("""SHOW TABLES LIKE 'passport'""")
result = self.cursor.fetchone()
if not result:
# Creation table Passport si premiere fois
sql = "CREATE TABLE passport ( `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, userid TEXT null, os TEXT null, config TEXT null, languages TEXT null, pays TEXT null, passportdate TEXT null, theme CHAR(5) DEFAULT 'dark');"
self.cursor.execute(sql)
@commands.group(pass_context=True)
async def passeport(self, ctx):
"""Passeport"""
if ctx.invoked_subcommand is None:
text = open('texts/passport-info.md').read()
em = discord.Embed(title='Commandes de carte de passeport de TuxBot', description=text, colour=0x89C4F9)
await ctx.send(embed=em)
@passeport.command(pass_context=True)
async def show(self, ctx, user: str = None):
self.conn = db.connect_to_db(self)
self.cursor = self.conn.cursor()
if user == None:
user = get_user(ctx.message, ctx.message.author.name)
else:
user = get_user(ctx.message, user)
wait_message = await ctx.send(f"Je vais chercher le passeport de {user.name} dans les archives, je vous prie de bien vouloir patienter...")
card = await generate_passport(self, user)
s = 'data/users/cards/{0}.png'.format(user.id)
card.save(s, 'png')
with open('data/users/cards/{0}.png'.format(user.id), 'rb') as g:
await ctx.message.channel.send(file=discord.File(g))
await wait_message.delete()
@passeport.command(name="config", pass_context=True)
async def passeport_config(self, ctx):
self.conn = db.connect_to_db(self)
self.cursor = self.conn.cursor()
await ctx.send('Un message privé vous a été envoyé pour configurer votre passeport.')
questions = ["Système(s) d'exploitation :", "Configuration Système :", "Langages de programmation préférés :", "Pays :"]
answers = {}
user_dm = await ctx.author.create_dm()
try:
await user_dm.send("Salut ! Je vais vous posez quelques questions afin de configurer votre passeport, si vous ne voulez pas répondre à une question, envoyez `skip` pour passer à la question suivante.")
except discord.HTTPException:
await ctx.send(f"{str(ctx.message.author.mention)}> il m'est impossible de vous envoyer les messages nécessaire a la configuration de votre passeport :sob:")
return
for x, question in enumerate(questions):
await user_dm.send(question)
def check(m):
return m.channel.id == user_dm.id and m.author.id == user_dm.recipient.id
answer = await self.bot.wait_for('message', check=check)
if answer.content.lower() == 'skip':
answers[x] = 'n/a'
else:
answers[x] = answer.content
try:
self.cursor.execute("""SELECT id, userid FROM passport WHERE userid = %s""", str(user_dm.recipient.id))
result = self.cursor.fetchone()
if result:
self.cursor.execute("""UPDATE passport SET os = %s, config = %s, languages = %s, pays = %s WHERE userid = %s""", (str(answers[0]), str(answers[1]), str(answers[2]), str(answers[3]), str(ctx.message.author.id)))
self.conn.commit()
else:
now = datetime.datetime.now()
self.cursor.execute("""INSERT INTO passport(userid, os, config, languages, pays, passportdate, theme) VALUES(%s, %s, %s, %s, %s, %s, %s)""", (str(ctx.message.author.id), str(answers[0]), str(answers[1]), str(answers[2]), str(answers[3]), now, "dark"))
self.conn.commit()
await user_dm.send('Configuration de votre passeport terminée avec succès, vous pouvez désormais la voir en faisant `.passeport show`.')
except Exception as e:
await user_dm.send(f':sob: Une erreur est survenue : \n {type(e).__name__}: {e}')
@passeport.command(name="background", pass_context=True)
async def passeport_background(self, ctx, *, url=""):
try:
background = ctx.message.attachments[0].url
except:
if url != "":
background = url
else:
em = discord.Embed(title='Une erreur est survenue', description="Image ou URL introuvable.", colour=0xDC3546)
await ctx.send(embed=em)
return
user = ctx.message.author
try:
async with aiohttp.ClientSession() as session:
async with session.get(background) as r:
image = await r.content.read()
except:
em = discord.Embed(title='Une erreur est survenue', description="Image ou URL introuvable.", colour=0xDC3546)
await ctx.send(embed=em)
return
with open(f"data/users/backgrounds/{str(user.id)}.png",'wb') as f:
f.write(image)
isImage = imghdr.what(f"data/users/backgrounds/{str(user.id)}.png")
if isImage == 'png' or isImage == 'jpeg' or isImage == 'jpg' or isImage == 'gif':
f.close()
em = discord.Embed(title='Configuration terminée', description="Fond d'écran enregistré et configuré avec succes", colour=0x28a745)
await ctx.send(embed=em)
else:
f.close()
os.remove(f"data/users/backgrounds/{str(user.id)}.png")
em = discord.Embed(title='Une erreur est survenue', description="Est-ce bien une image que vous avez envoyé ? :thinking:", colour=0xDC3546)
await ctx.send(embed=em)
@passeport.command(name="theme", aliases=["thème"], pass_context=True)
async def passeport_theme(self, ctx, theme: str = ""):
self.conn = db.connect_to_db(self)
self.cursor = self.conn.cursor()
possible_theme = ["dark", "light", "preview"]
if theme.lower() in possible_theme:
if theme.lower() == "dark":
self.cursor.execute("""UPDATE passport SET theme = %s WHERE userid = %s""", ("dark", str(ctx.message.author.id)))
self.conn.commit()
em = discord.Embed(title='Configuration terminée', description="Thème enregistré avec succes", colour=0x28a745)
await ctx.send(embed=em)
elif theme.lower() == "light":
self.cursor.execute("""UPDATE passport SET theme = %s WHERE userid = %s""", ("light", str(ctx.message.author.id)))
self.conn.commit()
em = discord.Embed(title='Configuration terminée', description="Thème enregistré avec succes", colour=0x28a745)
await ctx.send(embed=em)
else:
wait_message = await ctx.send(f"Laissez moi juste le temps de superposer les 2 passeports, je vous prie de bien vouloir patienter...")
cardbg = Image.new('RGBA', (1600, 500), (0, 0, 0, 255))
card_dark = await generate_passport(self, ctx.author, "dark")
card_dark.save(f'data/tmp/{ctx.author.id}_dark.png', 'png')
card_light = await generate_passport(self, ctx.author, "light")
card_light.save(f'data/tmp/{ctx.author.id}_light.png', 'png')
saved_card_dark = Image.open(f'data/tmp/{ctx.author.id}_dark.png')
saved_card_light = Image.open(f'data/tmp/{ctx.author.id}_light.png')
saved_card_dark = ImageOps.fit(saved_card_dark, (800, 500))
saved_card_light = ImageOps.fit(saved_card_light, (800, 500))
cardbg.paste(saved_card_dark, (0, 0))
cardbg.paste(saved_card_light, (800, 0))
cardbg.save(f'data/tmp/{ctx.author.id}.png', 'png')
with open(f'data/tmp/{ctx.author.id}.png', 'rb') as g:
await ctx.send(file=discord.File(g))
await wait_message.delete()
await ctx.send(f"Et voila {ctx.author.mention} ! à gauche votre passeport avec le thème \"dark\" et à droite avec le thème \"light\" :wink:")
shutil.rmtree("data/tmp")
os.mkdir("data/tmp")
else:
em = discord.Embed(title='Une erreur est survenue', description="Les choix possible pour cette commande sont : `dark`, `light`, `preview`", colour=0xDC3546)
await ctx.send(embed=em)
@passeport.command(name="delete", pass_context=True)
async def passeport_delete(self, ctx):
self.conn = db.connect_to_db(self)
self.cursor = self.conn.cursor()
self.cursor.execute("""SELECT id, userid FROM passport WHERE userid = %s""", str(ctx.author.id))
result = self.cursor.fetchone()
if result:
def check(m):
return m.author.id == ctx.author.id and \
m.channel.id == ctx.channel.id
await ctx.send(f"{str(ctx.message.author.mention)}> envoyez `CONFIRMER` afin de supprimer vos données conformément à l'article 17 du `règlement général sur la protection des données` sur le `Droit à l'effacement`")
response = await self.bot.wait_for('message', check=check, timeout=10.0 * 60.0)
if response.content == "CONFIRMER":
os.remove(f"data/users/backgrounds/{str(ctx.author.id)}.png")
self.cursor.execute("""DELETE FROM passport WHERE userid =%s""", (str(ctx.message.author.id)))
self.conn.commit()
em = discord.Embed(title='Suppression confirmée', description="Vos données ont été supprimées avec succès", colour=0x28a745)
await ctx.send(embed=em)
else:
await ctx.send("Déja configure ton passeport avant de la supprimer u_u (après c'est pas logique...)")
def setup(bot):
bot.add_cog(Passport(bot))

127
cogs/role.py Executable file
View File

@ -0,0 +1,127 @@
from discord.ext import commands
import discord
class Role:
"""Commandes role."""
def __init__(self, bot):
self.bot = bot
self.ARCH_ROLE = 393077257826205706
self.DEBIAN_ROLE = 393077933209550859
self.RHEL_ROLE = 393078333245751296
self.ANDROID_ROLE = 393087862972612627
self.BSD_ROLE = 401791543708745738
@commands.group(name="role", no_pm=True, pass_context=True, case_insensitive=True)
async def _role(self, ctx):
"""Affiche l'aide sur la commande role"""
if ctx.message.guild.id != 280805240977227776:
return
if ctx.invoked_subcommand is None:
text = open('texts/roles.md').read()
em = discord.Embed(title='Gestionnaires de rôles', description=text,colour=0x89C4F9)
await ctx.send(embed=em)
"""--------------------------------------------------------------------------------------------------------------------------"""
@_role.command(name="arch", aliases=["archlinux", "arch_linux"], pass_context=True)
async def role_arch(self, ctx):
"""Ajoute/retire le role 'Arch user'"""
roles = ctx.message.author.roles
role_id = []
for role in roles:
role_id.append(role.id)
user = ctx.message.author
if self.ARCH_ROLE in role_id:
await user.remove_roles(discord.Object(id=self.ARCH_ROLE))
await ctx.send(ctx.message.author.mention + " > Pourquoi tu viens de supprimer Arch Linux, c'était trop compliqué pour toi ? <:sad:343723037331292170>")
else:
await user.add_roles(discord.Object(id=self.ARCH_ROLE))
await ctx.send(ctx.message.author.mention + " > How un ArchLinuxien, c'est bon les ``yaourt`` ? <:hap:354275645574086656>")
"""--------------------------------------------------------------------------------------------------------------------------"""
@_role.command(name="debian", pass_context=True)
async def role_debian(self, ctx):
"""Ajoute/retire le role 'debian user'"""
roles = ctx.message.author.roles
role_id = []
for role in roles:
role_id.append(role.id)
user = ctx.message.author
if self.DEBIAN_ROLE in role_id:
await user.remove_roles(discord.Object(id=self.DEBIAN_ROLE))
await ctx.send(ctx.message.author.mention + " > Adieu ! Tu verras, APT te manquera ! ")
else:
await user.add_roles(discord.Object(id=self.DEBIAN_ROLE))
await ctx.send(ctx.message.author.mention + " > Un utilisateur de Debian, encore et encore ! <:stuck_out_tongue:343723077412323339>")
"""--------------------------------------------------------------------------------------------------------------------------"""
@_role.command(name="rhel", pass_context=True)
async def role_rhel(self, ctx):
"""Ajoute/retire le role 'rhel user'"""
roles = ctx.message.author.roles
role_id = []
for role in roles:
role_id.append(role.id)
user = ctx.message.author
if self.RHEL_ROLE in role_id:
await user.remove_roles(discord.Object(id=self.RHEL_ROLE))
await ctx.send(ctx.message.author.mention + " > Pourquoi tu t'en vas, il sont déjà assez seul là-bas <:sad:343723037331292170>")
else:
await user.add_roles(discord.Object(id=self.RHEL_ROLE))
await ctx.send(ctx.message.author.mention + " > Mais, voila quelqu'un qui porte des chapeaux ! <:hap:354275645574086656>")
"""--------------------------------------------------------------------------------------------------------------------------"""
@_role.command(name="android", pass_context=True)
async def role_android(self, ctx):
"""Ajoute/retire le role 'android user'"""
roles = ctx.message.author.roles
role_id = []
for role in roles:
role_id.append(role.id)
user = ctx.message.author
if self.ANDROID_ROLE in role_id:
await user.remove_roles(discord.Object(id=self.ANDROID_ROLE))
await ctx.send(ctx.message.author.mention + " > How, me dit pas que tu as compris que les Android's allaient exterminer le monde ? <:trollface:375327667160875008>")
else:
await user.add_roles(discord.Object(id=self.ANDROID_ROLE))
await ctx.send(ctx.message.author.mention + " > Hey, un utilisateur d'Android, prêt à continuer l'extermination de WP et iOS ? <:stuck_out_tongue:343723077412323339>")
"""--------------------------------------------------------------------------------------------------------------------------"""
@_role.command(name="bsd", pass_context=True)
async def role_bsd(self, ctx):
"""Ajoute/retire le role 'BSD user'"""
roles = ctx.message.author.roles
role_id = []
for role in roles:
role_id.append(role.id)
user = ctx.message.author
if self.BSD_ROLE in role_id:
await user.remove_roles(discord.Object(id=self.BSD_ROLE))
await ctx.send(ctx.message.author.mention + " > Ohhhh fait gaffe ou le démon va te piquer")
else:
await user.add_roles(discord.Object(id=self.BSD_ROLE))
await ctx.send(ctx.message.author.mention + " > Quelqu'un sous BSD ! Au moins il a pas besoin de mettre GNU devant son OS à chaque fois :d")
"""--------------------------------------------------------------------------------------------------------------------------"""
@_role.command(name="staff", pass_context=True, hidden=True)
async def role_staff(self, ctx):
"""Easter egg"""
user = ctx.message.author
await ctx.send(ctx.message.author.mention + " > Vous n'avez pas le rôle staff, tu crois quoi :joy:")
def setup(bot):
bot.add_cog(Role(bot))

View File

@ -1,128 +1,157 @@
from discord.ext import commands
import aiohttp
import asyncio
import discord
import urllib.request, json
import wikipedia, bs4
import asyncio
import urllib.request
import wikipedia
wikipedia.set_lang("fr")
class Search:
"""Commandes de WWW."""
"""Commandes de WWW."""
def __init__(self, bot):
self.bot = bot
def __init__(self, bot):
self.bot = bot
@commands.group(name="search", no_pm=True, pass_context=True)
async def _search(self, ctx):
"""Rechercher sur le world wide web"""
if ctx.invoked_subcommand is None:
text = open('texts/search.md').read()
em = discord.Embed(title='Commandes de search TuxBot', description=text, colour=0x89C4F9)
await ctx.send(embed=em)
@commands.group(name="search", no_pm=True, pass_context=True)
async def _search(self, ctx):
"""Rechercher sur le world wide web"""
if ctx.invoked_subcommand is None:
text = open('texts/search.md').read()
em = discord.Embed(title='Commandes de search TuxBot',
description=text,
colour=0x89C4F9)
await ctx.send(embed=em)
@_search.command(pass_context=True, name="docubuntu")
async def search_docubuntu(self, ctx, args):
attends = await ctx.send("_Je te cherche ça {} !_".format(
ctx.message.author.mention))
html = urllib.request.urlopen("https://doc.ubuntu-fr.org/" +
args).read()
if "avez suivi un lien" in str(html):
await attends.edit(content=":sob: Nooooon ! Cette page n'existe "
"pas, mais tu peux toujours la créer : "
"https://doc.ubuntu-fr.org/" + args)
else:
await attends.delete()
embed = discord.Embed(description="Voila j'ai trouvé ! Voici la "
"page ramenant à votre recherche,"
" toujours aussi bien rédigée "
":wink: : https://doc.ubuntu-fr."
"org/" + args,
url='http://doc.ubuntu-fr.org/')
embed.set_author(name="DocUbuntu-Fr",
url='http://doc.ubuntu-fr.org/',
icon_url='https://tuxbot.outout.xyz/data/ubuntu.png')
embed.set_thumbnail(url='https://tuxbot.outout.xyz/data/ubuntu.png')
embed.set_footer(text="Merci à ceux qui ont pris le temps d'écrire "
"cette documentation")
await ctx.send(embed=embed)
@_search.command(pass_context=True, name="docarch")
async def search_docarch(self, ctx, args):
attends = await ctx.send("_Je te cherche ça {} !_".format(
ctx.message.author.mention))
html = urllib.request.urlopen("https://wiki.archlinux.org/index.php/" +
args).read()
if "There is currently no text in this page" in str(html):
await attends.edit(content=":sob: Nooooon ! Cette page n'existe "
"pas.")
else:
await attends.delete()
embed = discord.Embed(description="Voila j'ai trouvé ! Voici la "
"page ramenant à votre recherche,"
" toujours aussi bien rédigée "
":wink: : https://wiki.archlinux."
"org/index.php/" + args,
url='https://wiki.archlinux.org/index.php/')
embed.set_author(name="Doc ArchLinux",
url='https://wiki.archlinux.org/index.php/',
icon_url='https://tuxbot.outout.xyz/data/arch.png')
embed.set_thumbnail(url='https://tuxbot.outout.xyz/data/arch.png')
embed.set_footer(text="Merci à ceux qui ont pris le temps d'écrire "
"cette documentation")
await ctx.send(embed=embed)
@_search.command(pass_context=True, name="wikipedia")
async def search_wikipedia(self, ctx: commands.Context, args):
"""Fait une recherche sur wikipd"""
@_search.command(pass_context=True, name="docubuntu")
async def search_docubuntu(self, ctx, args):
attends = await ctx.send("_Je te cherche ça {} !_".format(ctx.message.author.mention))
html = urllib.request.urlopen("https://doc.ubuntu-fr.org/" + args).read()
if "avez suivi un lien" in str(html):
await attends.edit(content=":sob: Nooooon ! Cette page n'existe pas, mais tu peux toujours la créer : https://doc.ubuntu-fr.org/"+ args)
else:
await attends.delete()
embed = discord.Embed(description="Voila j'ai trouvé ! Voici la page ramenant à votre recherche, toujours aussi bien rédigée :wink: : https://doc.ubuntu-fr.org/" + args, url='http://doc.ubuntu-fr.org/')
embed.set_author(name="DocUbuntu-Fr", url='http://doc.ubuntu-fr.org/', icon_url='http://outout.tech/tuxbot/ubuntu.png')
embed.set_thumbnail(url='http://outout.tech/tuxbot/ubuntu.png')
embed.set_footer(text="Merci à ceux qui ont pris le temps d'écrire cette documentation")
await ctx.send(embed=embed)
wait = await ctx.send("_Je cherche..._")
results = wikipedia.search(args)
nbmr = 0
mmssgg = ""
@_search.command(pass_context=True, name="aur")
async def search_aur(self, ctx, args):
attends = await ctx.send("_Je te cherche ça {} !_".format(ctx.message.author.mention))
erreur = 0
try:
html = urllib.request.urlopen("https://aur.archlinux.org/packages/" + args).read()
except:
erreur = 1
for value in results:
nbmr = nbmr + 1
mmssgg = mmssgg + "**{}**: {} \n".format(str(nbmr), value)
if erreur == 1:
await attends.delete()
embed = discord.Embed(description=":sob: Je n'ai pas trouvé le packet mais j'ai lancé une petite recherche, tu y trouveras peut être ton bonheur ? https://aur.archlinux.org/packages/?K=" + args,url='https://aur.archlinux.org/')
embed.set_author(name="Aur.archlinux", url='https://aur.archlinux.org/', icon_url='http://outout.tech/tuxbot/arch.png')
embed.set_thumbnail(url='http://outout.tech/tuxbot/arch.png')
embed.set_footer(text="Pff même pas trouvé !")
await ctx.send(embed=embed)
em = discord.Embed(title='Résultats de : ' + args,
description = mmssgg,
colour=0x4ECDC4)
em.set_thumbnail(url="https://upload.wikimedia.org/wikipedia/commons/"
"2/26/Paullusmagnus-logo_%28large%29.png")
await wait.delete()
else:
await attends.delete()
embed = discord.Embed(description="Et voila, j'ai trouvé la page sur le packet : https://aur.archlinux.org/packages/{0} ! \n Ca te dit un petit ``pacaur -S {0}`` ?".format(args), url='https://aur.archlinux.org/')
embed.set_author(name="Aur.archlinux", url='https://aur.archlinux.org/', icon_url='http://outout.tech/tuxbot/arch.png')
embed.set_thumbnail(url='http://outout.tech/tuxbot/arch.png')
embed.set_footer(text="C'est vrai que pacman et pacaur sont mieux qu'APT ^^")
await ctx.send(embed=embed)
sending = ["1⃣", "2⃣", "3⃣", "4⃣", "5⃣", "6⃣", "7⃣", "8⃣", "9⃣", "🔟"]
def check(reaction, user):
return user == ctx.author and reaction.emoji in sending and \
reaction.message.id == msg.id
@_search.command(pass_context=True, name="wikipedia")
async def search_wikipedia(self, ctx: commands.Context, args):
"""Fait une recherche sur wikipd"""
async def waiter(future: asyncio.Future):
reaction, user = await self.bot.wait_for('reaction_add',
check=check)
future.set_result(reaction.emoji)
wait = await ctx.send("_Je cherche..._")
results = wikipedia.search(args)
nbmr = 0
mmssgg = ""
emoji = asyncio.Future()
self.bot.loop.create_task(waiter(emoji))
for value in results:
nbmr = nbmr + 1
mmssgg = mmssgg + "**{}**: {} \n".format(str(nbmr), value)
msg = await ctx.send(embed=em)
for e in sending:
await msg.add_reaction(e)
if emoji.done():
break
em = discord.Embed(title='Résultats de : ' + args, description = mmssgg, colour=0x4ECDC4)
em.set_thumbnail(url = "https://upload.wikimedia.org/wikipedia/commons/2/26/Paullusmagnus-logo_%28large%29.png")
await wait.delete()
while not emoji.done():
await asyncio.sleep(0.1)
sending = ["1⃣", "2⃣", "3⃣", "4⃣", "5⃣", "6⃣", "7⃣", "8⃣", "9⃣", "🔟"]
sPage = int(sending.index(emoji.result()))
def check(reaction, user):
return user == ctx.author and reaction.emoji in sending and reaction.message.id == msg.id
args_ = results[sPage]
async def waiter(future: asyncio.Future):
reaction, user = await self.bot.wait_for('reaction_add', check=check)
future.set_result(reaction.emoji)
emoji = asyncio.Future()
self.bot.loop.create_task(waiter(emoji))
msg = await ctx.send(embed=em)
for e in sending:
await msg.add_reaction(e)
if emoji.done():
break
while not emoji.done():
await asyncio.sleep(0.1)
sPage = int(sending.index(emoji.result()))
args_ = results[sPage]
try:
await msg.delete()
await ctx.trigger_typing()
wait = await ctx.send(ctx.message.author.mention + " ah ok sympa cette recherche, je l'effectue de suite !")
wp = wikipedia.page(args_)
wp_contenu = wp.summary[:200] + "..."
em = discord.Embed(title='Wikipedia : ' + wp.title, description = "{} \n_Lien_ : {} ".format(wp_contenu, wp.url), colour=0x9B59B6)
em.set_author(name="Wikipedia", url='http://wikipedia.org', icon_url='https://upload.wikimedia.org/wikipedia/commons/2/26/Paullusmagnus-logo_%28large%29.png')
em.set_thumbnail(url = "https://upload.wikimedia.org/wikipedia/commons/2/26/Paullusmagnus-logo_%28large%29.png")
em.set_footer(text="Merci à eux de nous fournir une encyclopédie libre !")
await wait.delete()
await ctx.send(embed=em)
except wikipedia.exceptions.PageError: #TODO : A virer dans l'event on_error
await ctx.send(":open_mouth: Une **erreur interne** est survenue, si cela ce reproduit contactez votre administrateur ou faites une Issue sur ``github`` !")
try:
await msg.delete()
await ctx.trigger_typing()
wait = await ctx.send(ctx.message.author.mention +
" ah ok sympa cette recherche, je l'effectue de suite !")
wp = wikipedia.page(args_)
wp_contenu = wp.summary[:200] + "..."
em = discord.Embed(title='Wikipedia : ' + wp.title,
description = "{} \n_Lien_ : {} ".format(
wp_contenu, wp.url),
colour=0x9B59B6)
em.set_author(name="Wikipedia",
url='http://wikipedia.org',
icon_url='https://upload.wikimedia.org/wikipedia/'
'commons/2/26/Paullusmagnus-logo_%28large'
'%29.png')
em.set_thumbnail(url = "https://upload.wikimedia.org/wikipedia/"
"commons/2/26/Paullusmagnus-logo_%28large"
"%29.png")
em.set_footer(text="Merci à eux de nous fournir une encyclopédie "
"libre !")
await wait.delete()
await ctx.send(embed=em)
except wikipedia.exceptions.PageError:
# TODO : A virer dans l'event on_error
await ctx.send(":open_mouth: Une **erreur interne** est survenue,"
" si cela ce reproduit contactez votre"
" administrateur ou faites une Issue sur"
" ``github`` !")
def setup(bot):
bot.add_cog(Search(bot))
bot.add_cog(Search(bot))

80
cogs/send_logs.py Executable file
View File

@ -0,0 +1,80 @@
from discord.ext import commands
import discord
import datetime, socket
class SendLogs:
"""Send logs to a specific channel"""
def __init__(self, bot):
self.bot = bot
self.log_channel = None
self.main_server_id = int(self.bot.config.main_server_id)
async def on_resumed(self):
em = discord.Embed(title="Et hop je me reconnecte à l'api 😃", colour=0x5cb85c)
em.timestamp = datetime.datetime.utcnow()
await self.log_channel.send(embed=em)
async def on_ready(self):
self.log_channel = self.bot.get_channel(int(self.bot.config.log_channel_id))
em = discord.Embed(title="Je suis opérationnel 😃", description=f"*Instance lancée sur {socket.gethostname()}*", colour=0x5cb85c)
em.timestamp = datetime.datetime.utcnow()
await self.log_channel.send(embed=em)
"""--------------------------------------------------------------------------------------------------------------------------"""
async def on_guild_join(self, guild: discord.Guild):
em = discord.Embed(title=f"On m'a ajouté à : {str(guild.name)} 😃", colour=0x51A351)
em.timestamp = datetime.datetime.utcnow()
await self.log_channel.send(embed=em)
async def on_guild_remove(self, guild: discord.Guild):
em = discord.Embed(title=f"On m'a viré de : {str(guild.name)} 😦", colour=0xBD362F)
em.timestamp = datetime.datetime.utcnow()
await self.log_channel.send(embed=em)
"""--------------------------------------------------------------------------------------------------------------------------"""
async def on_member_join(self, member):
if member.guild.id == self.main_server_id:
em = discord.Embed(title=f"{str(member)} *`({str(member.id)})`* nous a rejoint 😃", colour=0x51A351)
em.set_footer(text="Compte crée le " + str(member.created_at), )
em.timestamp = datetime.datetime.utcnow()
await self.log_channel.send(embed=em)
async def on_member_remove(self, member):
if member.guild.id == self.main_server_id:
em = discord.Embed(title=f"{str(member)} *`({str(member.id)})`* nous a quitter 😦", colour=0xBD362F)
em.timestamp = datetime.datetime.utcnow()
await self.log_channel.send(embed=em)
"""--------------------------------------------------------------------------------------------------------------------------"""
async def on_message_delete(self, message):
if message.guild.id == self.main_server_id and not message.author.bot:
async def is_a_command(message):
prefix_lenght = len(await self.bot.get_prefix(message))
command = (message.content.split()[0])[prefix_lenght:]
if command == '':
command = "not_a_command"
return self.bot.get_command(str(command))
if await is_a_command(message) is None:
em = discord.Embed(title=f"Message supprimé dans : {str(message.channel.name)}", colour=0xBD362F)
em.add_field(name=f"{str(message.author)} *`({str(message.author.id)})`* a supprimé :", value=str(message.content))
em.timestamp = datetime.datetime.utcnow()
await self.log_channel.send(embed=em)
async def on_message_edit(self, before, after):
if before.guild.id == self.main_server_id and not before.author.bot:
em = discord.Embed(title="Message edité dans : " + str(before.channel.name), colour=0x0088CC)
em.add_field(name=f"{str(before.author)} *`({str(before.author.id)})`* a edité :", value=str(before.content))
em.add_field(name="Pour remplacer par :", value=str(after.content))
em.timestamp = datetime.datetime.utcnow()
await self.log_channel.send(embed=em)
def setup(bot):
bot.add_cog(SendLogs(bot))

109
cogs/sondage.py Executable file
View File

@ -0,0 +1,109 @@
from discord.ext import commands
import discord
import random
import asyncio
import datetime
class Sondage:
"""Commandes sondage."""
def __init__(self, bot):
self.bot = bot
@commands.command(pass_context=True)
async def sondage(self, ctx, *, msg="help"):
if msg != "help":
await ctx.message.delete()
options = msg.split(" | ")
time = [x for x in options if x.startswith("time=")]
if time:
time = time[0]
if time:
options.remove(time)
if len(options) <= 1:
raise commands.errors.MissingRequiredArgument
if len(options) >= 21:
return await ctx.send(ctx.message.author.mention + "> :octagonal_sign: Vous ne pouvez pas mettre plus de 20 réponses !")
if time:
time = int(time.strip("time="))
else:
time = 0
emoji = ['1⃣',
'2⃣',
'3⃣',
'4⃣',
'5⃣',
'6⃣',
'7⃣',
'8⃣',
'9⃣',
'🔟',
'0⃣',
'🇦',
'🇧',
'🇨',
'🇩',
'🇪',
'🇫',
'🇬',
'🇭',
'🇮'
]
to_react = []
confirmation_msg = "**{}?**:\n\n".format(options[0].rstrip("?"))
for idx, option in enumerate(options[1:]):
confirmation_msg += "{} - {}\n".format(emoji[idx], option)
to_react.append(emoji[idx])
confirmation_msg += "*Sondage proposé par* " + \
str(ctx.message.author.mention)
if time == 0:
confirmation_msg += ""
else:
confirmation_msg += "\n\nVous avez {} secondes pour voter!".\
format(time)
poll_msg = await ctx.send(confirmation_msg)
for emote in to_react:
await poll_msg.add_reaction(emote)
if time != 0:
await asyncio.sleep(time)
if time != 0:
async for message in ctx.message.channel.history():
if message.id == poll_msg.id:
poll_msg = message
results = {}
for reaction in poll_msg.reactions:
if reaction.emoji in to_react:
results[reaction.emoji] = reaction.count - 1
end_msg = "Le sondage est términé. Les résultats sont:\n\n"
for result in results:
end_msg += "{} {} - {} votes\n".\
format(result,
options[emoji.index(result)+1],
results[result])
top_result = max(results, key=lambda key: results[key])
if len([x for x in results
if results[x] == results[top_result]]) > 1:
top_results = []
for key, value in results.items():
if value == results[top_result]:
top_results.append(options[emoji.index(key)+1])
end_msg += "\nLes gagnants sont : {}".\
format(", ".join(top_results))
else:
top_result = options[emoji.index(top_result)+1]
end_msg += "\n\"{}\" est le gagnant!".format(top_result)
await ctx.send(end_msg)
else:
await ctx.message.delete()
text = open('texts/rpoll.md').read()
em = discord.Embed(title='Aide sur le sondage',
description=text,
colour=0xEEEEEE)
await ctx.send(embed=em)
def setup(bot):
bot.add_cog(Sondage(bot))

View File

@ -1,242 +1,284 @@
from discord.ext import commands
from random import choice, shuffle
import random
import aiohttp
import asyncio
import time
import discord
import urllib.request, json
import random
import json
import datetime, pytz
from datetime import date
import calendar
import requests
import urllib
class Utility:
"""Commandes utilitaires."""
"""Commandes utilitaires."""
def __init__(self, bot):
self.bot = bot
def __init__(self, bot):
self.bot = bot
@commands.command()
async def clock(self, ctx, args):
"""Display hour in a country"""
args = args.upper()
then = datetime.datetime.now(pytz.utc)
form = '%H heures %M'
try:
argument = args[1]
if args == "MONTREAL":
utc = then.astimezone(pytz.timezone('America/Montreal'))
site = "http://ville.montreal.qc.ca/"
img = "https://upload.wikimedia.org/wikipedia/commons/e/e0/Rentier_fws_1.jpg"
country = "au Canada, Québec"
description = "Montréal est la deuxième ville la plus peuplée du Canada. Elle se situe dans la région du Québec"
elif args == "VANCOUVER":
utc = then.astimezone(pytz.timezone('America/Vancouver'))
site = "http://vancouver.ca/"
img = "https://upload.wikimedia.org/wikipedia/commons/f/fe/Dock_Vancouver.JPG"
country = "au Canada"
description = "Vancouver, officiellement City of Vancouver, est une cité portuaire au Canada"
elif args == "NEW-YORK" or args == "N-Y":
utc = then.astimezone(pytz.timezone('America/New_York'))
site = "http://www1.nyc.gov/"
img = "https://upload.wikimedia.org/wikipedia/commons/e/e3/NewYork_LibertyStatue.jpg"
country = "aux U.S.A."
description = "New York, est la plus grande ville des États-Unis en termes d'habitants et l'une des plus importantes du continent américain. "
elif args == "LOSANGELES" or args == "L-A" or args == "LA" or args == "LACITY":
utc = then.astimezone(pytz.timezone('America/Los_Angeles'))
site = "https://www.lacity.org/"
img = "https://upload.wikimedia.org/wikipedia/commons/thumb/5/57/LA_Skyline_Mountains2.jpg/800px-LA_Skyline_Mountains2.jpg"
country = "aux U.S.A."
description = "Los Angeles est la deuxième ville la plus peuplée des États-Unis après New York. Elle est située dans le sud de l'État de Californie, sur la côte pacifique."
elif args == "PARIS":
utc = then.astimezone(pytz.timezone('Europe/Paris'))
site = "http://www.paris.fr/"
img = "https://upload.wikimedia.org/wikipedia/commons/a/af/Tour_eiffel_at_sunrise_from_the_trocadero.jpg"
country = "en France"
description = "Paris est la capitale de la France. Elle se situe au cœur d'un vaste bassin sédimentaire aux sols fertiles et au climat tempéré, le bassin parisien."
elif args == "BERLIN":
utc = then.astimezone(pytz.timezone('Europe/Berlin'))
site = "http://www.berlin.de/"
img = "https://upload.wikimedia.org/wikipedia/commons/9/91/Eduard_Gaertner_Schlossfreiheit.jpg"
country = "en Allemagne"
description = "Berlin est la capitale et la plus grande ville d'Allemagne. Située dans le nord-est du pays, elle compte environ 3,5 millions d'habitants. "
elif args == "BERN" or args == "ZURICH" or args == "BERNE":
utc = then.astimezone(pytz.timezone('Europe/Zurich'))
site = "http://www.berne.ch/"
img = "https://upload.wikimedia.org/wikipedia/commons/d/db/Justitia_Statue_02.jpg"
country = "en Suisse"
description = "Berne est la cinquième plus grande ville de Suisse et la capitale du canton homonyme. Depuis 1848, Berne est la « ville fédérale »."
elif args == "TOKYO":
utc = then.astimezone(pytz.timezone('Asia/Tokyo'))
site = "http://www.gotokyo.org/"
img = "https://upload.wikimedia.org/wikipedia/commons/3/37/TaroTokyo20110213-TokyoTower-01.jpg"
country = "au Japon"
description = "Tokyo, anciennement Edo, officiellement la préfecture métropolitaine de Tokyo, est la capitale du Japon."
elif args == "MOSCOU":
utc = then.astimezone(pytz.timezone('Europe/Moscow'))
site = "https://www.mos.ru/"
img = "https://upload.wikimedia.org/wikipedia/commons/f/f7/Andreyevsky_Zal.jpg"
country = "en Russie"
description = "Moscou est la capitale de la Fédération de Russie et la plus grande ville d'Europe. Moscou est situé sur la rivière Moskova. "
try:
if args == "LIST":
text = open('texts/clocks.md').read()
em = discord.Embed(title='Liste des Horloges', description=text, colour=0xEEEEEE)
await ctx.send(embed=em)
else:
tt = utc.strftime(form)
em = discord.Embed(title='Heure à ' + args.title(), description="A [{}]({}) {}, Il est **{}** ! \n {} \n _source des images et du texte : [Wikimedia foundation](http://commons.wikimedia.org/)_".format(str(args), site, str(country), str(tt), str(description)), colour=0xEEEEEE)
em.set_thumbnail(url = img)
await ctx.send(embed=em)
except UnboundLocalError:
await ctx.send("[**Erreur**] Ville inconnue, faites ``.clock list`` pour obtenir la liste des villes")
except IndexError:
await ctx.send("[**Erreur**] Ville inconnue, faites ``.clock list`` pour obtenir la liste des villes")
@commands.group(name="clock", pass_context=True, case_insensitive=True)
async def clock(self, ctx):
"""Display hour in a country"""
"""--------------------------------------------------------------------------------------------------------------------------"""
if ctx.invoked_subcommand is None:
text = open('texts/clocks.md').read()
em = discord.Embed(title='Liste des Horloges', description=text, colour=0xEEEEEE)
await ctx.send(embed=em)
@commands.command()
async def ytdiscover(self, ctx):
"""Random youtube channel"""
with open('texts/ytb.json') as js:
ytb = json.load(js)
@clock.command(name="montréal", aliases=["mtl", "montreal"], pass_context=True)
async def clock_montreal(self, ctx):
then = datetime.datetime.now(pytz.utc)
clef = str(random.randint(0,12))
chaine = ytb["{}".format(clef)]
utc = then.astimezone(pytz.timezone('America/Montreal'))
site = "http://ville.montreal.qc.ca/"
img = "https://upload.wikimedia.org/wikipedia/commons/e/e0/Rentier_fws_1.jpg"
country = "au Canada, Québec"
description = "Montréal est la deuxième ville la plus peuplée du Canada. Elle se situe dans la région du Québec"
embed = discord.Embed(title=chaine['name'], url=chaine['url'],
description="**{}**, {} \n[Je veux voir ça]({})".format(chaine['name'], chaine['desc'], chaine['url']))
embed.set_thumbnail(url='https://outout.tech/tuxbot/yt.png')
await ctx.send(embed=embed)
form = '%H heures %M'
tt = utc.strftime(form)
"""--------------------------------------------------------------------------------------------------------------------------"""
em = discord.Embed(title='Heure à Montréal', description=f"A [Montréal]({site}) {country}, Il est **{str(tt)}** ! \n {description} \n _source des images et du texte : [Wikimedia foundation](http://commons.wikimedia.org/)_", colour=0xEEEEEE)
em.set_thumbnail(url = img)
await ctx.send(embed=em)
@commands.command(pass_context=True)
async def afk(self, ctx):
"""Away from keyboard"""
msgs = ["s'absente de discord quelques instants", "se casse de son pc", "va sortir son chien", "reviens bientôt", "va nourrir son cochon", "va manger des cookies", "va manger de la poutine", "va faire caca", "va faire pipi"]
msg = random.choice(msgs)
@clock.command(name="vancouver", pass_context=True)
async def clock_vancouver(self, ctx):
then = datetime.datetime.now(pytz.utc)
await ctx.send("**{}** {}...".format(ctx.message.author.mention, msg))
utc = then.astimezone(pytz.timezone('America/Vancouver'))
site = "http://vancouver.ca/"
img = "https://upload.wikimedia.org/wikipedia/commons/f/fe/Dock_Vancouver.JPG"
country = "au Canada"
description = "Vancouver, officiellement City of Vancouver, est une cité portuaire au Canada"
"""--------------------------------------------------------------------------------------------------------------------------"""
form = '%H heures %M'
tt = utc.strftime(form)
@commands.command(pass_context=True)
async def back(self, ctx):
"""I'm back !"""
msgs = ["a réssuscité", "est de nouveau parmi nous", "a fini de faire caca", "a fini d'urine", "n'est plus mort", "est de nouveau sur son PC", "a fini de manger sa poutine", "a fini de danser", "s'est réveillé", "est de retour dans ce monde cruel"]
msg = random.choice(msgs)
em = discord.Embed(title='Heure à Vancouver', description=f"A [Vancouver]({site}) {country}, Il est **{str(tt)}** ! \n {description} \n _source des images et du texte : [Wikimedia foundation](http://commons.wikimedia.org/)_", colour=0xEEEEEE)
em.set_thumbnail(url = img)
await ctx.send(embed=em)
await ctx.send("**{}** {} !".format(ctx.message.author.mention, msg))
@clock.command(name="new-york",aliases=["ny", "n-y", "new york"], pass_context=True)
async def clock_new_york(self, ctx):
then = datetime.datetime.now(pytz.utc)
"""--------------------------------------------------------------------------------------------------------------------------"""
utc = then.astimezone(pytz.timezone('America/New_York'))
site = "http://www1.nyc.gov/"
img = "https://upload.wikimedia.org/wikipedia/commons/e/e3/NewYork_LibertyStatue.jpg"
country = "aux U.S.A."
description = "New York, est la plus grande ville des États-Unis en termes d'habitants et l'une des plus importantes du continent américain. "
@commands.command(pass_context=True)
async def sondage(self, ctx, *, msg):
"""Create a poll using reactions. >help rpoll for more information.
>rpoll <question> | <answer> | <answer> - Create a poll. You may use as many answers as you want, placing a pipe | symbol in between them.
Example:
>rpoll What is your favorite anime? | Steins;Gate | Naruto | Attack on Titan | Shrek
You can also use the "time" flag to set the amount of time in seconds the poll will last for.
Example:
>rpoll What time is it? | HAMMER TIME! | SHOWTIME! | time=10
"""
await ctx.message.delete()
options = msg.split(" | ")
time = [x for x in options if x.startswith("time=")]
if time:
time = time[0]
if time:
options.remove(time)
if len(options) <= 1:
raise commands.errors.MissingRequiredArgument
if len(options) >= 11:
return await ctx.send("Vous ne pouvez mettre que 9 options de réponse ou moins.")
if time:
time = int(time.strip("time="))
else:
time = 0
emoji = ['1⃣', '2⃣', '3⃣', '4⃣', '5⃣', '6⃣', '7⃣', '8⃣', '9⃣']
to_react = []
confirmation_msg = "**{}?**:\n\n".format(options[0].rstrip("?"))
for idx, option in enumerate(options[1:]):
confirmation_msg += "{} - {}\n".format(emoji[idx], option)
to_react.append(emoji[idx])
confirmation_msg += "*Sondage proposé par* "+str(ctx.message.author.mention)
if time == 0:
confirmation_msg += ""
else:
confirmation_msg += "\n\nVous avez {} secondes pour voter!".format(time)
poll_msg = await ctx.send(confirmation_msg)
for emote in to_react:
await poll_msg.add_reaction(emote)
form = '%H heures %M'
tt = utc.strftime(form)
if time != 0:
await asyncio.sleep(time)
em = discord.Embed(title='Heure à New York', description=f"A [str(New York]({site}) {country}, Il est **{str(tt)}** ! \n {description} \n _source des images et du texte : [Wikimedia foundation](http://commons.wikimedia.org/)_", colour=0xEEEEEE)
em.set_thumbnail(url = img)
await ctx.send(embed=em)
@clock.command(name="la", aliases=["los-angeles", "losangeles", "l-a", "los angeles"], pass_context=True)
async def clock_la(self, ctx):
then = datetime.datetime.now(pytz.utc)
if time != 0:
async for message in ctx.message.channel.history():
if message.id == poll_msg.id:
poll_msg = message
results = {}
for reaction in poll_msg.reactions:
if reaction.emoji in to_react:
results[reaction.emoji] = reaction.count - 1
end_msg = "Le sondage est términé. Les résultats sont:\n\n"
for result in results:
end_msg += "{} {} - {} votes\n".format(result, options[emoji.index(result)+1], results[result])
top_result = max(results, key=lambda key: results[key])
if len([x for x in results if results[x] == results[top_result]]) > 1:
top_results = []
for key, value in results.items():
if value == results[top_result]:
top_results.append(options[emoji.index(key)+1])
end_msg += "\nLes gagnants sont : {}".format(", ".join(top_results))
else:
top_result = options[emoji.index(top_result)+1]
end_msg += "\n\"{}\" est le gagnant!".format(top_result)
await ctx.send(end_msg)
utc = then.astimezone(pytz.timezone('America/Los_Angeles'))
site = "https://www.lacity.org/"
img = "https://upload.wikimedia.org/wikipedia/commons/thumb/5/57/LA_Skyline_Mountains2.jpg/800px-LA_Skyline_Mountains2.jpg"
country = "aux U.S.A."
description = "Los Angeles est la deuxième ville la plus peuplée des États-Unis après New York. Elle est située dans le sud de l'État de Californie, sur la côte pacifique."
"""--------------------------------------------------------------------------------------------------------------------------"""
form = '%H heures %M'
tt = utc.strftime(form)
@commands.command(pass_context=True)
async def sondage_aide(self, ctx):
await ctx.message.delete()
em = discord.Embed(title='Heure à Los Angeles', description=f"A [Los Angeles]({site}) {country}, Il est **{str(tt)}** ! \n {description} \n _source des images et du texte : [Wikimedia foundation](http://commons.wikimedia.org/)_", colour=0xEEEEEE)
em.set_thumbnail(url = img)
await ctx.send(embed=em)
@clock.command(name="paris", aliases=["baguette"],pass_context=True)
async def clock_paris(self, ctx):
then = datetime.datetime.now(pytz.utc)
text = open('texts/rpoll.md').read()
em = discord.Embed(title='Aide sur le sondage', description=text, colour=0xEEEEEE)
await ctx.send(embed=em)
utc = then.astimezone(pytz.timezone('Europe/Paris'))
site = "http://www.paris.fr/"
img = "https://upload.wikimedia.org/wikipedia/commons/a/af/Tour_eiffel_at_sunrise_from_the_trocadero.jpg"
country = "en France"
description = "Paris est la capitale de la France. Elle se situe au cœur d'un vaste bassin sédimentaire aux sols fertiles et au climat tempéré, le bassin parisien."
"""--------------------------------------------------------------------------------------------------------------------------"""
form = '%H heures %M'
tt = utc.strftime(form)
@commands.command(name='hastebin', pass_context=True)
async def _hastebin(self, ctx, *, data):
"""Poster sur Hastebin."""
await ctx.message.delete()
em = discord.Embed(title='Heure à Paris', description=f"A [Paris]({site}) {country}, Il est **{str(tt)}** ! \n {description} \n _source des images et du texte : [Wikimedia foundation](http://commons.wikimedia.org/)_", colour=0xEEEEEE)
em.set_thumbnail(url = img)
await ctx.send(embed=em)
@clock.command(name="berlin", pass_context=True)
async def clock_berlin(self, ctx):
then = datetime.datetime.now(pytz.utc)
post = requests.post("https://hastebin.com/documents", data=data)
utc = then.astimezone(pytz.timezone('Europe/Berlin'))
site = "http://www.berlin.de/"
img = "https://upload.wikimedia.org/wikipedia/commons/9/91/Eduard_Gaertner_Schlossfreiheit.jpg"
country = "en Allemagne"
description = "Berlin est la capitale et la plus grande ville d'Allemagne. Située dans le nord-est du pays, elle compte environ 3,5 millions d'habitants. "
try:
await ctx.send(str(ctx.message.author.mention)+" message posté avec succes sur :\nhttps://hastebin.com/{}.txt".format(post.json()["key"]))
except json.JSONDecodeError:
await ctx.send("Impossible de poster ce message. L'API doit etre HS.")
form = '%H heures %M'
tt = utc.strftime(form)
@commands.command(name='test', pass_context=True)
async def test(self, ctx):
em = discord.Embed(title='Heure à Berlin', description=f"A [Berlin]({site}) {country}, Il est **{str(tt)}** ! \n {description} \n _source des images et du texte : [Wikimedia foundation](http://commons.wikimedia.org/)_", colour=0xEEEEEE)
em.set_thumbnail(url = img)
await ctx.send(embed=em)
@clock.command(name="berne", aliases=["zurich", "bern"], pass_context=True)
async def clock_berne(self, ctx):
then = datetime.datetime.now(pytz.utc)
date = datetime.datetime.now()
utc = then.astimezone(pytz.timezone('Europe/Zurich'))
site = "http://www.berne.ch/"
img = "https://upload.wikimedia.org/wikipedia/commons/d/db/Justitia_Statue_02.jpg"
country = "en Suisse"
description = "Berne est la cinquième plus grande ville de Suisse et la capitale du canton homonyme. Depuis 1848, Berne est la « ville fédérale »."
nd = str(date.day)
nd += "-"
nd += str(date.month)
nd += "-"
nd += str(date.year)
form = '%H heures %M'
tt = utc.strftime(form)
await ctx.send(nd)
em = discord.Embed(title='Heure à Berne', description=f"A [Berne]({site}) {country}, Il est **{str(tt)}** ! \n {description} \n _source des images et du texte : [Wikimedia foundation](http://commons.wikimedia.org/)_", colour=0xEEEEEE)
em.set_thumbnail(url = img)
await ctx.send(embed=em)
@clock.command(name="tokyo", pass_context=True)
async def clock_tokyo(self, ctx):
then = datetime.datetime.now(pytz.utc)
utc = then.astimezone(pytz.timezone('Asia/Tokyo'))
site = "http://www.gotokyo.org/"
img = "https://upload.wikimedia.org/wikipedia/commons/3/37/TaroTokyo20110213-TokyoTower-01.jpg"
country = "au Japon"
description = "Tokyo, anciennement Edo, officiellement la préfecture métropolitaine de Tokyo, est la capitale du Japon."
form = '%H heures %M'
tt = utc.strftime(form)
em = discord.Embed(title='Heure à Tokyo', description=f"A [Tokyo]({site}) {country}, Il est **{str(tt)}** ! \n {description} \n _source des images et du texte : [Wikimedia foundation](http://commons.wikimedia.org/)_", colour=0xEEEEEE)
em.set_thumbnail(url = img)
await ctx.send(embed=em)
@clock.command(name="moscou", aliases=["moscow", "moskova"], pass_context=True)
async def clock_moscou(self, ctx):
then = datetime.datetime.now(pytz.utc)
utc = then.astimezone(pytz.timezone('Europe/Moscow'))
site = "https://www.mos.ru/"
img = "https://upload.wikimedia.org/wikipedia/commons/f/f7/Andreyevsky_Zal.jpg"
country = "en Russie"
description = "Moscou est la capitale de la Fédération de Russie et la plus grande ville d'Europe. Moscou est situé sur la rivière Moskova. "
form = '%H heures %M'
tt = utc.strftime(form)
em = discord.Embed(title='Heure à Moscou', description=f"A [Moscou]({site}) {country}, Il est **{str(tt)}** ! \n {description} \n _source des images et du texte : [Wikimedia foundation](http://commons.wikimedia.org/)_", colour=0xEEEEEE)
em.set_thumbnail(url = img)
await ctx.send(embed=em)
"""--------------------------------------------------------------------------------------------------------------------------"""
@commands.command()
async def ytdiscover(self, ctx):
"""Random youtube channel"""
with open('texts/ytb.json') as js:
ytb = json.load(js)
clef = str(random.randint(0,12))
chaine = ytb["{}".format(clef)]
embed = discord.Embed(title=chaine['name'],
url=chaine['url'],
description=f"**{chaine['name']}**, {chaine['desc']} \n[Je veux voir ça]({chaine['url']})")
embed.set_thumbnail(url='https://outout.tech/tuxbot/yt.png')
await ctx.send(embed=embed)
"""--------------------------------------------------------------------------------------------------------------------------"""
@commands.command(name='hastebin', pass_context=True)
async def _hastebin(self, ctx, *, data):
"""Poster sur Hastebin."""
await ctx.message.delete()
post = requests.post("https://hastebin.com/documents", data=data)
try:
await ctx.send(f"{ctx.message.author.mention} message posté avec succès sur :\nhttps://hastebin.com/{post.json()['key']}.txt")
except json.JSONDecodeError:
await ctx.send("Impossible de poster ce message. L'API doit être HS.")
"""---------------------------------------------------------------------"""
@commands.command(name='iplocalise', pass_context=True)
async def _iplocalise(self, ctx, ipaddress):
"""Recup headers."""
if ipaddress.startswith("http://"):
ipaddress = ipaddress.split("http://")[1]
if ipaddress.startswith("https://"):
ipaddress = ipaddress.split("https://")[1]
iploading = await ctx.send("_réfléchis..._")
ipapi = urllib.request.urlopen("http://ip-api.com/json/" + ipaddress)
ipinfo = json.loads(ipapi.read().decode())
if ipinfo["status"] != "fail":
await iploading.edit(content="L'adresse IP ``{query}`` appartient à ``{org}`` et se situe à ``{city}``, dans ``{regionName}``, ``{country}``.".format(**ipinfo))
else:
await iploading.edit(content=f"Erreur, impossible d'avoir des informations sur l'adresse IP {ipinfo['query']}")
"""--------------------------------------------------------------------------------------------------------------------------"""
@commands.command(name='getheaders', pass_context=True)
async def _getheaders(self, ctx, *, adresse):
"""Recuperer les HEADERS :d"""
print("Loaded")
if adresse.startswith("http://") != True and adresse.startswith("https://") != True:
adresse = "http://" + adresse
if len(adresse) > 200:
await ctx.send("{0} Essaye d'entrer une adresse de moins de 200 caractères plutôt.".format(ctx.author.mention))
elif adresse.startswith("http://") or adresse.startswith("https://") or adresse.startswith("ftp://"):
try:
get = urllib.request.urlopen(adresse, timeout = 1)
embed = discord.Embed(title="Entêtes de {0}".format(adresse), color=0xd75858)
embed.add_field(name="Code Réponse", value=get.getcode(), inline = True)
embed.set_thumbnail(url="https://http.cat/{}".format(str(get.getcode())))
if get.getheader('location'):
embed.add_field(name="Redirection vers", value=get.getheader('location'), inline=True)
if get.getheader('server'):
embed.add_field(name="Serveur", value=get.getheader('server'), inline=True)
if get.getheader('content-type'):
embed.add_field(name="Type de contenu", value = get.getheader('content-type'), inline = True)
if get.getheader('x-content-type-options'):
embed.add_field(name="x-content-type", value= get.getheader('x-content-type-options'), inline=True)
if get.getheader('x-frame-options'):
embed.add_field(name="x-frame-options", value= get.getheader('x-frame-options'), inline=True)
if get.getheader('cache-control'):
embed.add_field(name="Controle du cache", value = get.getheader('cache-control'), inline = True)
await ctx.send(embed=embed)
except urllib.error.HTTPError as e:
embed = discord.Embed(title="Entêtes de {0}".format(adresse), color=0xd75858)
embed.add_field(name="Code Réponse", value=e.getcode(), inline = True)
embed.set_thumbnail(url="https://http.cat/{}".format(str(e.getcode())))
await ctx.send(embed=embed)
print('''An error occurred: {} The response code was {}'''.format(e, e.getcode()))
except urllib.error.URLError as e:
print("ERROR @ getheaders @ urlerror : {} - adress {}".format(e, adresse))
await ctx.send('[CONTACTER ADMIN] URLError: {}'.format(e.reason))
except Exception as e:
print("ERROR @ getheaders @ Exception : {} - adress {}".format(e, adresse))
await ctx.send("{0} Impossible d'accèder à {1}, es-tu sur que l'adresse {1} est correcte et que le serveur est allumé ?".format(ctx.author.mention, adresse))
else:
await ctx.send("{0} Merci de faire commencer {1} par ``https://``, ``http://`` ou ``ftp://``.".format(ctx.message.author.mention, adresse))
"""--------------------------------------------------------------------------------------------------------------------------"""
@commands.command(name='github', pass_context=True)
async def _github(ctx):
"""Pour voir mon code"""
text = "How tu veux voir mon repos Github pour me disséquer ? Pas de soucis ! Je suis un Bot, je ne ressens pas la douleur !\n https://github.com/outout14/tuxbot-bot"
em = discord.Embed(title='Repos TuxBot-Bot', description=text, colour=0xE9D460)
em.set_author(name='Outout', icon_url="https://avatars0.githubusercontent.com/u/14958554?v=3&s=400")
await ctx.send(embed=em)
def setup(bot):
bot.add_cog(Utility(bot))
bot.add_cog(Utility(bot))

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,75 +1,101 @@
# -*- coding: utf-8 -*-
import discord.utils
from discord.ext import commands
def is_owner_check(message): # OUTOUT id RICK id L4P1N id GIGA id FLAYOR id ROMAIN id
owner = str(message.author.id) in ['171685542553976832', '163697401935298560', '88644904112128000', '92619860521005056', '273757386127441920', '269156684155453451'] ###ID's modo & admin
rights = str(message.author.top_role.name).upper() in ['ADMIN', 'ADMINISTRATEURS', 'ADMINISTRATEUR', 'MODO', 'MODÉRATEUR', 'MODÉRATEURS', 'MODERATEUR', 'MODERATEURS']
if rights == True or owner == True:
return True # Owner of the bot
else:
return False
def is_owner_check(message):
return str(message.author.id) in ['171685542553976832', '269156684155453451']
def is_owner(warn=True):
def check(ctx, warn):
owner = is_owner_check(ctx.message)
if not owner and warn:
print(ctx.message.author.name + " à essayer d'executer " + ctx.message.content)
return owner
def check(ctx, warn):
owner = is_owner_check(ctx.message)
if not owner and warn:
print(ctx.message.author.name + " à essayer d'executer " + ctx.message.content + " sur le serveur " + ctx.message.guild.name)
return owner
owner = commands.check(lambda ctx: check(ctx, warn))
return owner
owner = commands.check(lambda ctx: check(ctx, warn))
return owner
def check_permissions(ctx, perms):
msg = ctx.message
if is_owner_check(msg):
return True
"""--------------------------------------------------------------------------------------------------------------------------"""
ch = msg.channel
author = msg.author
resolved = ch.permissions_for(author)
return all(getattr(resolved, name, None) == value for name, value in perms.items())
async def check_permissions(ctx, perms, *, check=all):
is_owner = await ctx.bot.is_owner(ctx.author)
if is_owner or is_owner_check(ctx.message) == True:
return True
resolved = ctx.channel.permissions_for(ctx.author)
return check(getattr(resolved, name, None) == value for name, value in perms.items())
def role_or_permissions(ctx, check, **perms):
if check_permissions(ctx, perms):
return True
def has_permissions(*, check=all, **perms):
async def pred(ctx):
return await check_permissions(ctx, perms, check=check)
return commands.check(pred)
ch = ctx.message.channel
author = ctx.message.author
if ch.is_private:
return False # can't have roles in PMs
async def check_guild_permissions(ctx, perms, *, check=all):
is_owner = await ctx.bot.is_owner(ctx.author)
if is_owner:
return True
role = discord.utils.find(check, author.roles)
return role is not None
if ctx.guild is None:
return False
resolved = ctx.author.guild_permissions
return check(getattr(resolved, name, None) == value for name, value in perms.items())
def admin_or_permissions(**perms):
def predicate(ctx):
return role_or_permissions(ctx, lambda r: r.name == 'Bot Admin', **perms)
def has_guild_permissions(*, check=all, **perms):
async def pred(ctx):
return await check_guild_permissions(ctx, perms, check=check)
return commands.check(pred)
return commands.check(predicate)
def is_in_servers(*server_ids):
def predicate(ctx):
server = ctx.message.server
if server is None:
return False
return server.id in server_ids
return commands.check(predicate)
def embed_perms(message):
try:
check = message.author.permissions_in(message.channel).embed_links
except:
check = True
return check
# These do not take channel overrides into account
def is_mod():
async def pred(ctx):
return await check_guild_permissions(ctx, {'manage_guild': True})
return commands.check(pred)
async def pred(ctx):
return await check_guild_permissions(ctx, {'manage_guild': True})
return commands.check(pred)
def is_admin():
async def pred(ctx):
return await check_guild_permissions(ctx, {'administrator': True})
return commands.check(pred)
def mod_or_permissions(**perms):
perms['manage_guild'] = True
async def predicate(ctx):
return await check_guild_permissions(ctx, perms, check=any)
return commands.check(predicate)
def admin_or_permissions(**perms):
perms['administrator'] = True
async def predicate(ctx):
return await check_guild_permissions(ctx, perms, check=any)
return commands.check(predicate)
def is_in_guilds(*guild_ids):
def predicate(ctx):
guild = ctx.guild
if guild is None:
return False
return guild.id in guild_ids
return commands.check(predicate)
def is_lounge_cpp():
return is_in_guilds(145079846832308224)
def get_user(message, user):
try:
member = message.mentions[0]
except:
member = message.guild.get_member_named(user)
if not member:
try:
member = message.guild.get_member(int(user))
except ValueError:
pass
if not member:
return None
return member
def check_date(date: str):
if len(date) == 1:
return f"0{date}"
else:
return date

43
cogs/utils/cli_colors.py Normal file
View File

@ -0,0 +1,43 @@
class text_colors:
BLACK = '\033[30m'
RED = '\033[31m'
GREEN = '\033[32m'
YELLOW = '\033[33m'
BLUE = '\033[34m'
MAGENTA = '\033[35m'
CYAN = '\033[36m'
LIGHT_GRAY = '\033[37m'
DARK_GRAY = '\033[90m'
LIGHT_RED = '\033[91m'
LIGHT_GREEN = '\033[92m'
LIGHT_YELLOW = '\033[93m'
LIGHT_BLUE = '\033[94m'
LIGHT_MAGENTA = '\033[95m'
LIGHT_CYAN = '\033[96m'
WHITE = '\033[97m'
class bg_colors:
BLACK = '\033[40m'
RED = '\033[41m'
GREEN = '\033[42m'
YELLOW = '\033[43m'
BLUE = '\033[44m'
MAGENTA = '\033[45m'
CYAN = '\033[46m'
LIGHT_GRAY = '\033[47m'
DARK_GRAY = '\033[100m'
LIGHT_RED = '\033[101m'
LIGHT_GREEN = '\033[102m'
LIGHT_YELLOW = '\033[103m'
LIGHT_BLUE = '\033[104m'
LIGHT_MAGENTA = '\033[105m'
LIGHT_CYAN = '\033[106m'
WHITE = '\033[107m'
class text_style:
BOLD = '\033[1m'
DIM = '\033[2m'
UNDERLINE = '\033[4m'
BLINK = '\033[5m'
ENDC = '\033[0m'

24
cogs/utils/db.py Executable file
View File

@ -0,0 +1,24 @@
import pymysql
def connect_to_db(self):
mysqlHost = self.bot.config.mysql["host"]
mysqlUser = self.bot.config.mysql["username"]
mysqlPass = self.bot.config.mysql["password"]
mysqlDB = self.bot.config.mysql["dbname"]
try:
return pymysql.connect(host=mysqlHost, user=mysqlUser, passwd=mysqlPass, db=mysqlDB, charset='utf8')
except KeyError:
print("Rest in peperoni, Impossible de se connecter a la base de données.")
print(str(KeyError))
return
def reconnect_to_db(self):
if not self.conn:
mysqlHost = self.bot.config.mysql["host"]
mysqlUser = self.bot.config.mysql["username"]
mysqlPass = self.bot.config.mysql["password"]
mysqlDB = self.bot.config.mysql["dbname"]
return pymysql.connect(host=mysqlHost, user=mysqlUser, passwd=mysqlPass, db=mysqlDB, charset='utf8')
return self.conn

View File

@ -0,0 +1,245 @@
from PIL import Image
from PIL import ImageOps
from PIL import ImageDraw
from PIL import ImageFont
from .checks import check_date
import aiohttp, imghdr, textwrap, math, datetime
async def generate_passport(self, user, theme: str = None):
name = user.name
userid = user.id
avatar = user.avatar_url
def_avatar = user.default_avatar_url
created = datetime.datetime.fromisoformat(str(user.created_at))
nick = user.display_name
discr = user.discriminator
roles = user.roles
top_role_color = str(user.top_role.color)[1:]
user_color = tuple(int(top_role_color[i:i+2], 16) for i in (0, 2 ,4))
user_color += (255,)
color = {
"dark": {
"background": 39,
"question": 220,
"answer": 150
},
"light": {
"background": 216,
"question": 35,
"answer": 61
}
}
user_birth_day = check_date(str(created.day))
user_birth_month = check_date(str(created.month))
formated_user_birth = str(user_birth_day) + "/" + str(user_birth_month) + "/" + str(created.year)
formated_passportdate = "n/a"
roleImages = {}
def draw_underlined_text(draw, pos, text, font, **options):
twidth, theight = draw.textsize(text, font=font)
lx, ly = pos[0], pos[1] + theight
draw.text(pos, text, font=font, **options)
draw.line((lx, ly, lx + twidth, ly), **options)
def break_line(draw, pos, text, font, **options):
lines = text.split("\n")
current_y = pos[1]
for line in lines:
twidth, theight = draw.textsize(line, font=font)
lx, ly = pos[0], current_y
if textwrap.fill(line, 60) == line:
draw.text((lx, ly), textwrap.fill(line, 60), font=font, **options)
current_y += math.floor(theight)
else:
draw.text((lx, ly), textwrap.fill(line, 60), font=font, **options)
current_y += math.floor(theight*2)
for x, role in enumerate(roles):
try:
roleImages[role.name] = Image.open(f"data/images/roles/small/{role.name.lower().replace(' user', '')}.png")
except Exception as e:
next
if avatar == '':
async with aiohttp.ClientSession() as session:
async with session.get(def_avatar) as r:
image = await r.content.read()
else:
async with aiohttp.ClientSession() as session:
async with session.get(avatar) as r:
image = await r.content.read()
with open('data/users/avatars/{}.png'.format(user.id), 'wb') as f:
f.write(image)
checked = False
while checked == False:
checks = 0
isImage = imghdr.what('data/users/avatars/{}.png'.format(user.id))
if checks > 4:
checked = True
if isImage != 'None':
checked = True
else:
checks += 1
av = Image.open('data/users/avatars/{}.png'.format(user.id))
userAvatar = av.resize((128, 128), resample=Image.BILINEAR).convert('RGBA')
maxsize = ( 800, 500)
try:
bg = Image.open('data/users/backgrounds/{0}.png'.format(user.id))
bg_width, bg_height = bg.size
bg = ImageOps.fit(bg,maxsize)
except:
bg = Image.open('data/images/background_default.png')
fontFace = 'data/fonts/{}'.format(self.bot.config.fonts['normal'])
fontFace_bold = 'data/fonts/{}'.format(self.bot.config.fonts['bold'])
fontSize = 18
fontSizeVeryTiny = 16
descSizeQuestion = 10
descSizeAnswer = 10
headerSize = 32
headerSizeTiny = 24
headerSizeVeryTiny = 16
header_font = ImageFont.truetype(fontFace_bold, headerSize)
header_font_tiny = ImageFont.truetype(fontFace_bold, headerSizeTiny)
header_font_very_tiny = ImageFont.truetype(fontFace_bold, headerSizeVeryTiny)
font = ImageFont.truetype(fontFace, fontSize)
font_very_tiny = ImageFont.truetype(fontFace, fontSizeVeryTiny)
desc_font_question = ImageFont.truetype(fontFace_bold, descSizeQuestion)
desc_font_answer = ImageFont.truetype(fontFace, descSizeAnswer)
font_bold = font = ImageFont.truetype(fontFace_bold, fontSize)
answers = None
self.cursor.execute("SELECT os, config, languages, pays, passportdate, theme FROM passport WHERE userid=%s", str(user.id))
answers = self.cursor.fetchone()
if not theme:
if answers:
theme = str(answers[5])
else:
theme = "dark"
cardbg = Image.new('RGBA', (800, 500), (0, 0, 0, 255))
d = ImageDraw.Draw(cardbg)
d.rectangle([(0, 0), 800, 500], fill=(255, 255, 255, 255))
cardbg.paste(bg, (0, 0))
cardfg = Image.new('RGBA', (800, 500), (255, 255, 255, 0))
dd = ImageDraw.Draw(cardfg)
# Info Box Top
dd.rectangle([(60, 60), (600, 191)], fill=(color[theme]["background"], color[theme]["background"], color[theme]["background"], 200))
dd.rectangle([(60, 60), (600, 134)], fill=(color[theme]["background"], color[theme]["background"], color[theme]["background"], 255))
# Avatar box
if user_color == (0, 0, 0, 255):
user_color = (color[theme]["background"], color[theme]["background"], color[theme]["background"], 255)
dd.rectangle([(609, 60), (740, 191)], fill=user_color)
cardfg.paste(userAvatar, (611, 62))
# Profile Information
if textwrap.fill(nick, 25) != nick:
dd.text((70, 70), nick, fill=(color[theme]["question"], color[theme]["question"], color[theme]["question"], 220), font=header_font_very_tiny)
dd.text((70, 106), '@' + name + '#' + discr, fill=(color[theme]["answer"], color[theme]["answer"], color[theme]["answer"], 225), font=font_very_tiny)
elif textwrap.fill(nick, 15) != nick:
dd.text((70, 70), nick, fill=(color[theme]["question"], color[theme]["question"], color[theme]["question"], 220), font=header_font_tiny)
dd.text((70, 106), '@' + name + '#' + discr, fill=(color[theme]["answer"], color[theme]["answer"], color[theme]["answer"], 225), font=font)
else:
dd.text((70, 64), nick, fill=(color[theme]["question"], color[theme]["question"], color[theme]["question"], 220), font=header_font)
dd.text((70, 106), '@' + name + '#' + discr, fill=(color[theme]["answer"], color[theme]["answer"], color[theme]["answer"], 225), font=font)
draw_underlined_text(dd, (380, 75), "Date de parution sur discord :", fill=(color[theme]["question"], color[theme]["question"], color[theme]["question"], 220), font=desc_font_question)
dd.text((542, 75), formated_user_birth, fill=(color[theme]["answer"], color[theme]["answer"], color[theme]["answer"], 225), font=desc_font_answer)
# Roles
for idy, ii in enumerate(roleImages):
startx = int((270 - (30 * len(roleImages))) / 2)
cardfg.paste(roleImages[ii], (197 + startx + (30 * idy),152), roleImages[ii])
#Info Box Bottom
dd.rectangle([(60, 200), (740, 450)], fill=(color[theme]["background"], color[theme]["background"], color[theme]["background"], 200))
if answers:
passportdate = datetime.datetime.fromisoformat(answers[4])
passportdate_day = check_date(str(passportdate.day))
passportdate_month = check_date(str(passportdate.month))
formated_passportdate = str(passportdate_day) + "/" + str(passportdate_month) + "/" + str(passportdate.year)
draw_underlined_text(dd, (80, 220), "Système(s) d'exploitation :", desc_font_question, fill=(color[theme]["question"], color[theme]["question"], color[theme]["question"], 255))
break_line(
dd,
(80, 240),
answers[0],
fill=(color[theme]["answer"], color[theme]["answer"], color[theme]["answer"], 255),
font=desc_font_answer
)
draw_underlined_text(dd, (80, 300), "Langages de programmation préférés :", desc_font_question, fill=(color[theme]["question"], color[theme]["question"], color[theme]["question"], 255))
break_line(
dd,
(80, 320),
answers[2],
fill=(color[theme]["answer"], color[theme]["answer"], color[theme]["answer"], 255),
font=desc_font_answer
)
draw_underlined_text(dd, (80, 380), "Pays :", desc_font_question, fill=(color[theme]["question"], color[theme]["question"], color[theme]["question"], 255))
break_line(
dd,
(80, 400),
answers[3],
fill=(color[theme]["answer"], color[theme]["answer"], color[theme]["answer"], 255),
font=desc_font_answer
)
dd.line((400, 220, 400, 430), fill=(color[theme]["answer"], color[theme]["answer"], color[theme]["answer"], 255))
draw_underlined_text(dd, (410, 220), "Configuration Système :", desc_font_question, fill=(color[theme]["question"], color[theme]["question"], color[theme]["question"], 255))
break_line(
dd,
(410, 240),
answers[1],
fill=(color[theme]["answer"], color[theme]["answer"], color[theme]["answer"], 255),
font=desc_font_answer
)
else:
dd.text(
(370, 300),
"Non renseigné.",
fill=(color[theme]["question"], color[theme]["question"], color[theme]["question"], 255),
font=desc_font_question
)
draw_underlined_text(dd, (380, 100), "Date de création du passeport :", fill=(color[theme]["question"], color[theme]["question"], color[theme]["question"], 220), font=desc_font_question)
dd.text((542, 100), formated_passportdate, fill=(color[theme]["answer"], color[theme]["answer"], color[theme]["answer"], 225), font=desc_font_answer)
card = Image.new('RGBA', (800, 500), (255, 255, 255, 255))
card = Image.alpha_composite(card, cardbg)
card = Image.alpha_composite(card, cardfg)
return card

26
config.py Executable file
View File

@ -0,0 +1,26 @@
token = "INSERT_TOKEN_HERE"
client_id = "INSERT_CLIENT_ID_HERE"
log_channel_id = "INSERT_LOG_CHANNEL_HERE"
main_server_id = "INSERT_MAIN_CHANNEL_ID_HERE"
game = "PLAYING_GAME_HERE"
prefix = ["."]
description = """
Je suis TuxBot, le bot qui vit de l'OpenSource ! ;)
"""
mysql = {
"host": "localhost",
"username": "msqlusername",
"password": "msqlpasswd",
"dbname": "mysqldb"
}
authorized_id = ['admin ids here']
## Passport settings
fonts = {
"normal": "NotoSansCJK-Regular.ttc",
"bold": "NotoSansCJK-Bold.ttc"
}

BIN
data/fonts/NotoSansCJK-Bold.ttc Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 627 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1012 B

BIN
data/images/roles/antergos.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
data/images/roles/arch.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 763 B

BIN
data/images/roles/bsd.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 845 B

BIN
data/images/roles/debian.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
data/images/roles/elementary.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
data/images/roles/fedora.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 962 B

BIN
data/images/roles/gentoo.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
data/images/roles/linuxmint.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
data/images/roles/manjaro.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

BIN
data/images/roles/opensuse.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
data/images/roles/rhel.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
data/images/roles/small/arch.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
data/images/roles/small/bsd.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
data/images/roles/small/macos.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
data/images/roles/small/mint.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
data/images/roles/small/other.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 917 B

BIN
data/images/roles/small/rhel.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
data/images/roles/small/void.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

BIN
data/images/roles/ubuntu.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
data/images/roles/void.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 B

Some files were not shown because too many files have changed in this diff Show More