Compare commits

..

No commits in common. "a93181bcd85d1c0c3df16d81ec095eeb373d10bd" and "abb1f16129daf8ee8c757b36ff743de1e727d360" have entirely different histories.

3 changed files with 20 additions and 128 deletions

1
.envrc
View File

@ -1 +0,0 @@
use_nix

View File

@ -1,10 +0,0 @@
{ pkgs? import <nixpkgs> {}, ... }:
let
pythonEnv = pkgs.poetry2nix.mkPoetryEnv {
projectDir = ./.;
};
in pkgs.mkShell {
buildInputs = [ pythonEnv ];
PYTHONPATH = ".";
}

View File

@ -1,17 +1,15 @@
import ast
import asyncio
import datetime
import io
import itertools
import operator as op
import random
import re
import traceback
import urllib
from collections import Counter, defaultdict
from collections import defaultdict, Counter
from dataclasses import dataclass, field
from functools import partial
import math
from itertools import groupby
from math import log
from operator import attrgetter, itemgetter
from time import time
from typing import List, Set, Union
@ -21,27 +19,25 @@ import discord
import yaml
from discord import Guild, Member
from discord.ext import commands
from discord.ext.commands import (BadArgument, Cog, command, Command, CommandError, Context, Group, group, is_owner,
MemberConverter, RoleConverter)
from discord.ext.commands import (
Cog,
command,
Context,
Command,
CommandError,
Group,
group,
MemberConverter,
BadArgument,
RoleConverter,
)
from discord.utils import get
from src.constants import *
from src.core import CustomBot
from src.errors import TfjmError
from src.utils import has_role, send_and_bin, start_time
from src.utils import has_role, start_time, send_and_bin
# supported operators
OPS = {
ast.Add: op.add, ast.Sub: op.sub, ast.Mult: op.mul,
ast.FloorDiv: op.floordiv, ast.Mod: op.mod,
ast.Div: op.truediv, ast.Pow: op.pow, ast.BitXor: op.xor,
ast.USub: op.neg, "abs": abs, "π": math.pi, "τ": math.tau,
"i": 1j,
}
for name in dir(math):
if not name.startswith("_"):
OPS[name] = getattr(math, name)
@dataclass
class Joke(yaml.YAMLObject):
@ -194,96 +190,6 @@ class MiscCog(Cog, name="Divers"):
f"iel sera un membre influent du CNO ?"
)
@command(name="calc", aliases=["="])
async def calc_cmd(self, ctx, *args):
"""Effectue un calcul simple"""
with_tb = has_role(ctx.author, Role.DEV)
embed = self._calc(ctx.message.content, with_tb)
resp = await ctx.send(embed=embed)
def check(before, after):
return after.id == ctx.message.id
while True:
try:
before, after = await self.bot.wait_for(
"message_edit", check=check, timeout=600
)
except asyncio.TimeoutError:
break
embed = self._calc(after.content, with_tb)
await resp.edit(embed=embed)
# Remove the "You may edit your message"
embed.set_footer()
try:
await resp.edit(embed=embed)
except discord.NotFound:
pass
def _calc(self, query: str, with_tb=False):
for prefix in ("! ", "!", "calc", "="):
if query.startswith(prefix):
query = query[len(prefix):]
query = re.sub(r"\b((\d)+(\.\d+)?)(?P<name>[a-zA-Z]+)\b", r"\1*\4", query)
query = query.strip().strip("`")
ex = None
result = 42
try:
result = self._eval(ast.parse(query, mode='eval').body)
except Exception as e:
ex = e
if isinstance(result, complex):
if abs(result.imag) < 1e-12:
result = result.real
else:
r, i = result.real, result.imag
r = r if abs(int(r) - r) > 1e-12 else int(r)
i = i if abs(int(i) - i) > 1e-12 else int(i)
if not r:
result = f"{i if i != 1 else ''}i"
else:
result = f"{r}{i if i != 1 else '':+}i"
if isinstance(result, float):
result = round(result, 12)
embed = discord.Embed(title=discord.utils.escape_markdown(query), color=EMBED_COLOR)
# embed.add_field(name="Entrée", value=f"`{query}`", inline=False)
embed.add_field(name="Valeur", value=f"`{result}`", inline=False)
if ex and with_tb:
embed.add_field(name="Erreur", value=f"{ex.__class__.__name__}: {ex}", inline=False)
trace = io.StringIO()
traceback.print_exception(type(ex), ex, ex.__traceback__, file=trace)
trace.seek(0)
embed.add_field(name="Traceback", value=f"```\n{trace.read()}```")
embed.set_footer(text="You may edit your message")
return embed
def _eval(self, node):
if isinstance(node, ast.Num): # <number>
return node.n
elif isinstance(node, ast.BinOp): # <left> <operator> <right>
return OPS[type(node.op)](self._eval(node.left), self._eval(node.right))
elif isinstance(node, ast.UnaryOp): # <operator> <operand> e.g., -1
return OPS[type(node.op)](self._eval(node.operand))
elif isinstance(node, ast.Call):
if isinstance(node.func, ast.Name):
return OPS[node.func.id](*(self._eval(n) for n in node.args), **{k.arg: self._eval(k.value) for k in node.keywords})
elif isinstance(node, ast.Name):
return OPS[node.id]
fields = ", ".join(
f"{k}={getattr(node, k).__class__.__name__}" for k in node._fields
)
raise TypeError(f"Type de noeud non supporté: {node.__class__.__name__}({fields})")
# ----------------- Hugs ---------------- #
@command(aliases=["<3", "❤️", ":heart:", Emoji.RAINBOW_HEART])
@ -618,15 +524,14 @@ class MiscCog(Cog, name="Divers"):
yaml.safe_dump_all(jokes, f)
@group(name="joke", invoke_without_command=True, case_insensitive=True)
async def joke(self, ctx: Context, id=None):
async def joke(self, ctx: Context):
"""Fait discretement une blague aléatoire."""
m: discord.Message = ctx.message
await m.delete()
jokes = self.load_jokes()
if id is not None:
id = int(id)
if False:
joke_id = id
jokes = sorted(
jokes, key=lambda j: len(j.likes) - len(j.dislikes), reverse=True
@ -707,8 +612,7 @@ class MiscCog(Cog, name="Divers"):
self.save_jokes(jokes)
@joke.command(name="top", hidden=True)
@commands.has_any_role(*Role.ORGAS)
@joke.command(name="top", hidden=True, enabled=False)
async def best_jokes(self, ctx: Context):
"""Affiche le palmares des blagues."""
@ -724,9 +628,8 @@ class MiscCog(Cog, name="Divers"):
if joke.file:
text += " - image non inclue - "
name = who.display_name if who else "Inconnu"
embed.add_field(
name=f"{i} - {name} - {len(joke.likes)} :heart: {len(joke.dislikes)} :broken_heart:", value=text, inline=False
name=f"{i} - {who.display_name} - {len(joke.likes)}", value=text
)
await ctx.send(embed=embed)