diff --git a/.gitignore b/.gitignore index 3155612..28290b4 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ __pycache__/ *.pyc .env config.py +!cogs/utils/* .DS_Store private.py diff --git a/blacklist.json b/blacklist.json new file mode 100644 index 0000000..918516c --- /dev/null +++ b/blacklist.json @@ -0,0 +1,3 @@ +[ + 589949234308972556 +] \ No newline at end of file diff --git a/bot.py b/bot.py index 0f9486d..545f52b 100755 --- a/bot.py +++ b/bot.py @@ -2,13 +2,16 @@ import datetime import logging import sys import traceback +from collections import deque +from typing import List import aiohttp import discord from discord.ext import commands import config -from cogs.utils.lang import _ +from cogs.utils.config import Config +from cogs.utils.lang import gettext description = """ Je suis TuxBot, le bot qui vit de l'OpenSource ! ;) @@ -18,16 +21,17 @@ log = logging.getLogger(__name__) l_extensions = ( 'cogs.admin', - 'cogs.basaics', + 'cogs.basics', + 'jishaku', ) -async def _prefix_callable(bot, message): - base = [] if config.prefix is None else config.prefix +async def _prefix_callable(bot, message: discord.message) -> List: + extras = [] + if message.guild is not None: + extras = bot.prefixes.get(str(message.guild.id), []) - # if message.guild is not None: - # base.extend(bot.prefixes.get(message.guild.id)) - return commands.when_mentioned_or(base) + return commands.when_mentioned_or(*extras)(bot, message) class TuxBot(commands.AutoShardedBot): @@ -40,40 +44,64 @@ class TuxBot(commands.AutoShardedBot): self.uptime = datetime.datetime.utcnow() self.config = config - self.prefixes = {} + self._prev_events = deque(maxlen=10) self.session = aiohttp.ClientSession(loop=self.loop) + self.prefixes = Config('prefixes.json') + self.blacklist = Config('blacklist.json') + for extension in l_extensions: if extension not in unload: try: self.load_extension(extension) except Exception as e: - print(_("Failed to load extension : ") + extension, + print(gettext("Failed to load extension : ") + extension, file=sys.stderr) - traceback.print_exc() + log.error(gettext("Failed to load extension : ") + + extension, exc_info=e) + + async def on_socket_response(self, msg): + self._prev_events.append(msg) async def on_command_error(self, ctx, error): if isinstance(error, commands.NoPrivateMessage): await ctx.author.send( - _('This command cannot be used in private messages.') + gettext('This command cannot be used in private messages.') ) elif isinstance(error, commands.DisabledCommand): await ctx.author.send( - _('Sorry. This command is disabled and cannot be used.') + gettext('Sorry. This command is disabled and cannot be used.') ) elif isinstance(error, commands.CommandInvokeError): - print(_('In ') + f'{ctx.command.qualified_name}:', file=sys.stderr) + print(gettext('In ') + f'{ctx.command.qualified_name}:', + file=sys.stderr) traceback.print_tb(error.original.__traceback__) print(f'{error.original.__class__.__name__}: {error.original}', file=sys.stderr) elif isinstance(error, commands.ArgumentParsingError): await ctx.send(error) + async def process_commands(self, message): + ctx = await self.get_context(message) + + if ctx.command is None: + return + + await self.invoke(ctx) + + async def on_message(self, message): + if message.author.bot \ + or message.author.id in self.blacklist \ + or message.guild.id in self.blacklist: + return + + await self.process_commands(message) + async def on_ready(self): if not hasattr(self, 'uptime'): self.uptime = datetime.datetime.utcnow() - print(_('Ready:') + f' {self.user} (ID: {self.user.id})') + print(gettext('Ready:') + f' {self.user} (ID: {self.user.id})') await self.change_presence(status=discord.Status.dnd, activity=discord.Game( @@ -90,7 +118,8 @@ class TuxBot(commands.AutoShardedBot): webhook = discord.Webhook.partial(id=logs_webhook.get('id'), token=logs_webhook.get('token'), adapter=discord.AsyncWebhookAdapter( - self.session)) + self.session) + ) return webhook async def close(self): diff --git a/cogs/basics.py b/cogs/basics.py index f61ab16..51b6d92 100755 --- a/cogs/basics.py +++ b/cogs/basics.py @@ -1,6 +1,5 @@ import platform import socket -import subprocess import discord from discord.ext import commands @@ -10,33 +9,14 @@ from discord.http import Route class Basics(commands.Cog): """Commandes générales.""" - def __init__(self, bot): + def __init__(self, bot: discord.ext.commands.AutoShardedBot): 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) + async def ping(self, ctx: discord.ext.commands.context.Context): + delta = await ctx.send(self.bot.latency * 1000) + await ctx.send((delta.created_at-ctx.message.created_at) + .microseconds/1000) """---------------------------------------------------------------------""" @@ -63,7 +43,7 @@ class Basics(commands.Cog): text = open('texts/help.md').read().split("[split]") for txt in text: em = discord.Embed(title='Commandes de TuxBot', description=txt, - colour=0x89C4F9) + colour=0x89C4F9) await ctx.send(embed=em) diff --git a/cogs/utils/config.py b/cogs/utils/config.py new file mode 100644 index 0000000..91fc65e --- /dev/null +++ b/cogs/utils/config.py @@ -0,0 +1,27 @@ +import json + + +class Config: + __slots__ = ('name', '_db') + + def __init__(self, name): + self.name = name + + try: + with open(self.name, 'r') as f: + self._db = json.load(f) + except FileNotFoundError: + self._db = {} + + def __contains__(self, item): + return item in self._db + + def __getitem__(self, item): + return self._db[str(item)] + + def get(self, key, *args): + """Retrieves a config entry.""" + return self._db.get(str(key), *args) + + def all(self) -> dict: + return self._db diff --git a/cogs/utils/lang.py b/cogs/utils/lang.py index db41736..9142680 100644 --- a/cogs/utils/lang.py +++ b/cogs/utils/lang.py @@ -5,4 +5,4 @@ lang = gettext.translation('base', localedir='locales', languages=[config.lang]) lang.install() -_ = lang.gettext +gettext = lang.gettext diff --git a/first_run/initializer.py b/first_run/initializer.py index 7ebd976..f3870f9 100644 --- a/first_run/initializer.py +++ b/first_run/initializer.py @@ -66,7 +66,6 @@ class Config: + '\033[0m\n') self.input('activity', empty=True) - self.input('prefix', empty=True) def save(self): with open('config.py', 'w') as file: diff --git a/first_run/langs.py b/first_run/langs.py index 3048fcd..731084c 100644 --- a/first_run/langs.py +++ b/first_run/langs.py @@ -20,7 +20,6 @@ texts = { 'misc': 'Autre', 'activity': "Joue à ...", - 'prefix': "Prefixe (par defaut : @tuxbot)", 'end': "Configuration terminée, vous pouvez à tout moment la rectifier en modifiant le fichier config.py", @@ -47,7 +46,6 @@ texts = { 'misc': 'Misc', 'activity': "Playing ...", - 'prefix': "Prefix (default is @tuxbot)", 'end': "Configuration completed, you can fix it at any time by modifying the config.py file", diff --git a/launcher.py b/launcher.py index 48f4542..7149b90 100644 --- a/launcher.py +++ b/launcher.py @@ -11,7 +11,7 @@ from cogs.utils.db import Table try: import config - from cogs.utils.lang import _ + from cogs.utils.lang import gettext except ModuleNotFoundError: import first_run @@ -51,8 +51,8 @@ def run_bot(unload): Table.create_pool(config.postgresql, command_timeout=60) ) except socket.gaierror as e: - click.echo(_('Could not set up PostgreSQL...'), file=sys.stderr) - log.exception(_('Could not set up PostgreSQL...')) + click.echo(gettext('Could not set up PostgreSQL...'), file=sys.stderr) + log.exception(gettext('Could not set up PostgreSQL...')) return bot = TuxBot(unload) @@ -63,7 +63,7 @@ def run_bot(unload): @click.group(invoke_without_command=True, options_metavar='[options]') @click.option('-u', '--unload', multiple=True, type=str, - help=_('Launch without loading the module')) + help=gettext('Launch without loading the module')) @click.pass_context def main(ctx, unload): if ctx.invoked_subcommand is None: diff --git a/logs/tuxbot.log b/logs/tuxbot.log deleted file mode 100644 index 72e6060..0000000 --- a/logs/tuxbot.log +++ /dev/null @@ -1,12 +0,0 @@ -[2019-09-08 22:58:46] [INFO ] discord.client: logging in using static token -[2019-09-08 22:58:47] [INFO ] discord.gateway: Shard ID 0 has sent the IDENTIFY payload. -[2019-09-08 22:58:47] [INFO ] discord.gateway: Shard ID 0 has connected to Gateway: ["gateway-prd-main-xfx5",{"micros":31802,"calls":["discord-sessions-prd-1-18",{"micros":26858,"calls":["start_session",{"micros":12548,"calls":["api-prd-main-6rfw",{"micros":8098,"calls":["get_user",{"micros":1942},"add_authorized_ip",{"micros":5},"get_guilds",{"micros":3036},"coros_wait",{"micros":3}]}]},"guilds_connect",{"micros":139,"calls":[]},"presence_connect",{"micros":1,"calls":[]}]}]}] (Session ID: 03fcb2e35ce477c42ae58e20259b5d68). -[2019-09-08 22:58:53] [INFO ] discord.state: Processed a chunk for 463 members in guild ID 280805240977227776. -[2019-09-08 22:58:54] [INFO ] discord.state: Processed a chunk for 807 members in guild ID 331981755177238530. -[2019-09-08 22:58:55] [INFO ] discord.state: Processed a chunk for 1000 members in guild ID 296698073177128962. -[2019-09-08 22:58:55] [INFO ] discord.state: Processed a chunk for 1000 members in guild ID 296698073177128962. -[2019-09-08 22:58:55] [INFO ] discord.state: Processed a chunk for 662 members in guild ID 296698073177128962. -[2019-09-08 23:03:12] [INFO ] discord.client: Cleaning up tasks. -[2019-09-08 23:03:12] [INFO ] discord.client: Cleaning up after 5 tasks. -[2019-09-08 23:03:12] [INFO ] discord.client: All tasks finished cancelling. -[2019-09-08 23:03:12] [INFO ] discord.client: Closing the event loop. diff --git a/prefixes.json b/prefixes.json new file mode 100644 index 0000000..200257f --- /dev/null +++ b/prefixes.json @@ -0,0 +1,5 @@ +{ + "280805240977227776": [ + "." + ] +} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index c94599b..22eaeb7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ discord.py[voice] +jishaku lxml click asyncpg>=0.12.0 \ No newline at end of file