diff --git a/config/Base.py b/config/Base.py index 863eb96..958d9aa 100644 --- a/config/Base.py +++ b/config/Base.py @@ -1,6 +1,5 @@ from __future__ import annotations -from enum import Enum from typing import Dict, Any, Optional @@ -74,6 +73,9 @@ class Config: Do not override""" self._load() + def __getattr__(self, item): + return self.config.get(item) + def __getitem__(self, item): return self.config.get(item) diff --git a/main.py b/main.py index fa60028..09e12d3 100644 --- a/main.py +++ b/main.py @@ -1,16 +1,10 @@ #!/usr/bin/python3 import asyncio -import concurrent import importlib import json import logging import logging.config import os -import signal -import socket -import traceback -from concurrent.futures.process import ProcessPoolExecutor -from concurrent.futures.thread import ThreadPoolExecutor from typing import Dict import discord @@ -310,6 +304,7 @@ class LBI(discord.Client): initialized_class.dispatch("load") if module not in self.config["modules"]: self.config["modules"].append(module) + self.config.save() return 0 @modules_edit diff --git a/modules/errors/__init__.py b/modules/errors/__init__.py index c65bfd2..daa0870 100644 --- a/modules/errors/__init__.py +++ b/modules/errors/__init__.py @@ -1,11 +1,8 @@ import asyncio -import time - -import datetime +import collections import random import traceback -import collections import discord from discord import Message @@ -32,11 +29,13 @@ class MainClass(BaseClassPython): self.config.init({"dev_chan": [], "memes": [""], "icon": ""}) self.errorsDeque = None - async def on_ready(self): + async def on_load(self): if self.objects.save_exists('errorsDeque'): self.errorsDeque = self.objects.load_object('errorsDeque') else: self.errorsDeque = collections.deque() + + async def on_ready(self): for i in range(len(self.errorsDeque)): try: msg_id = self.errorsDeque.popleft() @@ -73,20 +72,20 @@ class MainClass(BaseClassPython): title="[Erreur] Aïe :/", description="```python\n{0}```".format(traceback.format_exc()), color=self.color) - embed.set_image(url=random.choice(self.config["memes"])) + embed.set_image(url=random.choice(self.config.memes)) message_list = None # Send message to dev channels - for chanid in self.config["dev_chan"]: + for chanid in self.config.dev_chan: try: await self.client.get_channel(chanid).send( - embed=embed.set_footer(text="Ce message ne s'autodétruira pas.", icon_url=self.config["icon"])) + embed=embed.set_footer(text="Ce message ne s'autodétruira pas.", icon_url=self.config.icon)) except BaseException as e: raise e # Send message to current channel if exists if channel is not None: message = await channel.send(embed=embed.set_footer(text="Ce message va s'autodétruire dans une minute", - icon_url=self.config["icon"])) + icon_url=self.config.icon)) msg_id = {"channel_id": message.channel.id, "msg_id": message.id} self.errorsDeque.append(msg_id) # Save message in errorsDeque now to keep them if a reboot happend during next 60 seconds diff --git a/modules/perdu/__init__.py b/modules/perdu/__init__.py index e69de29..e923c22 100644 --- a/modules/perdu/__init__.py +++ b/modules/perdu/__init__.py @@ -0,0 +1,113 @@ +import datetime + +import discord + +import utils.emojis +from modules.base import BaseClassPython + + +class MainClass(BaseClassPython): + name = "Perdu" + help = { + "description": "Module donnant les statistiques sur les perdants", + "commands": { + "`{prefix}{command}`": "Donne le classement des perdants de la semaine", + "`{prefix}{command} all`": "Donne le classement des perdants depuis toujours", + "`{prefix}{command} `": "Donne le classement des perdants sur la durée spécifiée", + "`{prefix}{command} stats [@mention]`": "Donne les statistiques d'un perdant", + } + } + help_active = True + command_text = "perdu" + color = 0xff6ba6 + + def __init__(self, client): + super().__init__(client) + self.config.init({"channel": 0, "lost_role": 0, "min_delta": datetime.timedelta(minutes=30).total_seconds()}) + + async def on_load(self): + if self.objects.save_exists('history'): + self.history = self.objects.load_object('history') + else: + self.history = {} + + async def on_message(self, message: discord.Message): + # Fill history + if message.channel.id == self.config.channel: + if message.author.id not in self.history.keys(): + # Add new user if not found + self.history.update( + {message.author.id: ([(message.created_at, datetime.timedelta(seconds=0)), ])} + ) + else: + # Update user and precompute timedelta + delta = message.created_at - self.history[message.author.id][-1][0] + if delta.total_seconds() >= self.config.min_delta: + self.history[message.author.id].append((message.created_at, delta)) + self.objects.save_object("history", self.history) + await self.parse_command(message) + + async def fill_history(self): + self.history = {} + async for message in self.client.get_channel(self.config.channel).history(limit=None): + if message.author.id not in self.history.keys(): + # Add new user if not found + self.history.update({message.author.id: ([(message.created_at, datetime.timedelta(seconds=0)), ])}) + else: + # Update user and precompute timedelta + delta = self.history[message.author.id][-1][0] - message.created_at + if delta.total_seconds() >= self.config.min_delta: + self.history[message.author.id].append((message.created_at, delta)) + self.objects.save_object("history", self.history) + + def get_top(self, top=10, since=datetime.datetime(year=1, month=1, day=1)): + """Return [(userid, [(date, delta), (date,delta), ...]), ... ]""" + # Extract only messages after until + messages = [] + for user in self.history.keys(): + if self.history[user][-1][0] > since: + messages.append((user, [message for message in self.history[user] if message[0] > since])) + messages.sort(key=lambda x: len(x[1]), reverse=True) + # Extract top-ten + messages = messages[:min(top, len(messages))] + return messages + + async def com_fill(self, message: discord.Message, args, kwargs): + if await self.auth(message.author): + async with message.channel.typing(): + await self.fill_history() + await message.channel.send("Fait.") + + async def com_all(self, message: discord.Message, args, kwargs): + # Get all stats + top = self.get_top() + embed_description = "\n".join( + f"{utils.emojis.write_with_number(i)} : <@{top[i][0]}> a **perdu {len(top[i][1])} fois** depuis la" + f" création du salon à en moyenne **{sum(list(zip(*top[i][1]))[1], datetime.timedelta(0)) / len(top[i][1])} heures d'intervalle.**" + for i in range(len(top)) + )[:2000] + await message.channel.send(embed=discord.Embed(title="G-Perdu - Tableau des scores", + description=embed_description, + color=self.color)) + + async def com_stats(self, message: discord.Message, args, kwargs): + pass + + async def command(self, message, args, kwargs): + if message.mentions: + await self.com_stats(message, args, kwargs) + since = datetime.datetime.now() - datetime.timedelta(days=7) + if args[0]: + try: + since = datetime.datetime.now() - datetime.timedelta(days=float(args[0])) + except ValueError: + pass + top = self.get_top(10, since) + embed_description = "\n".join( + f"{utils.emojis.write_with_number(i)} : <@{top[i][0]}> a **perdu {len(top[i][1])} fois** depuis la" + f" création du salon à en moyenne **{sum(list(zip(*top[i][1]))[1], datetime.timedelta(0)) / len(top[i][1])} heures d'intervalle.**" + for i in range(len(top)) + )[:2000] + await message.channel.send(embed=discord.Embed(title="G-Perdu - Tableau des scores", + description=embed_description, + color=self.color)) diff --git a/modules/rtfgd/__init__.py b/modules/rtfgd/__init__.py new file mode 100644 index 0000000..fdadcd1 --- /dev/null +++ b/modules/rtfgd/__init__.py @@ -0,0 +1,29 @@ +import random + +import discord + +from modules.base import BaseClassPython + + +class MainClass(BaseClassPython): + name = "rtfgd" + help = { + "description": "Read the fucking google doc", + "commands": { + "{prefix}{command} ": "Demande gentilment de lire le google doc" + } + } + help_active = True + command_text = "rtfgd" + + color = 0xdb1348 + + def __init__(self, client): + super().__init__(client) + self.config.init({"memes": []}) + + async def command(self, message, args, kwargs): + await message.channel.send( + " ".join(member.mention for member in message.mentions), + embed=discord.Embed(title="Read da fu**ing GOOGLE DOCS ! (╯°□°)╯︵ ┻━┻", + color=self.color).set_image(url=random.choice(self.config.memes))) diff --git a/utils/__init__.py b/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/utils/emojis.py b/utils/emojis.py new file mode 100644 index 0000000..9267051 --- /dev/null +++ b/utils/emojis.py @@ -0,0 +1,12 @@ +NUMBERS = ["1⃣", "2⃣", "3⃣", "4⃣", "5⃣", "6⃣", "7⃣", "8⃣", "9⃣", "🔟"] + + +def write_with_number(i): + raw = str(i) + s = "" + for c in str(i): + if raw == ".": + s += "." + else: + s += NUMBERS[int(c)] + return s