Compare commits
No commits in common. "a93181bcd85d1c0c3df16d81ec095eeb373d10bd" and "abb1f16129daf8ee8c757b36ff743de1e727d360" have entirely different histories.
a93181bcd8
...
abb1f16129
10
shell.nix
10
shell.nix
|
@ -1,10 +0,0 @@
|
||||||
{ pkgs? import <nixpkgs> {}, ... }:
|
|
||||||
let
|
|
||||||
pythonEnv = pkgs.poetry2nix.mkPoetryEnv {
|
|
||||||
projectDir = ./.;
|
|
||||||
};
|
|
||||||
in pkgs.mkShell {
|
|
||||||
buildInputs = [ pythonEnv ];
|
|
||||||
|
|
||||||
PYTHONPATH = ".";
|
|
||||||
}
|
|
137
src/cogs/misc.py
137
src/cogs/misc.py
|
@ -1,17 +1,15 @@
|
||||||
import ast
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import datetime
|
import datetime
|
||||||
import io
|
import io
|
||||||
import itertools
|
import itertools
|
||||||
import operator as op
|
|
||||||
import random
|
import random
|
||||||
import re
|
import re
|
||||||
import traceback
|
|
||||||
import urllib
|
import urllib
|
||||||
from collections import Counter, defaultdict
|
from collections import defaultdict, Counter
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from functools import partial
|
from functools import partial
|
||||||
import math
|
from itertools import groupby
|
||||||
|
from math import log
|
||||||
from operator import attrgetter, itemgetter
|
from operator import attrgetter, itemgetter
|
||||||
from time import time
|
from time import time
|
||||||
from typing import List, Set, Union
|
from typing import List, Set, Union
|
||||||
|
@ -21,27 +19,25 @@ import discord
|
||||||
import yaml
|
import yaml
|
||||||
from discord import Guild, Member
|
from discord import Guild, Member
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from discord.ext.commands import (BadArgument, Cog, command, Command, CommandError, Context, Group, group, is_owner,
|
from discord.ext.commands import (
|
||||||
MemberConverter, RoleConverter)
|
Cog,
|
||||||
|
command,
|
||||||
|
Context,
|
||||||
|
Command,
|
||||||
|
CommandError,
|
||||||
|
Group,
|
||||||
|
group,
|
||||||
|
MemberConverter,
|
||||||
|
BadArgument,
|
||||||
|
RoleConverter,
|
||||||
|
)
|
||||||
from discord.utils import get
|
from discord.utils import get
|
||||||
|
|
||||||
from src.constants import *
|
from src.constants import *
|
||||||
from src.core import CustomBot
|
from src.core import CustomBot
|
||||||
from src.errors import TfjmError
|
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
|
@dataclass
|
||||||
class Joke(yaml.YAMLObject):
|
class Joke(yaml.YAMLObject):
|
||||||
|
@ -194,96 +190,6 @@ class MiscCog(Cog, name="Divers"):
|
||||||
f"iel sera un membre influent du CNO ?"
|
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 ---------------- #
|
# ----------------- Hugs ---------------- #
|
||||||
|
|
||||||
@command(aliases=["<3", "❤️", ":heart:", Emoji.RAINBOW_HEART])
|
@command(aliases=["<3", "❤️", ":heart:", Emoji.RAINBOW_HEART])
|
||||||
|
@ -618,15 +524,14 @@ class MiscCog(Cog, name="Divers"):
|
||||||
yaml.safe_dump_all(jokes, f)
|
yaml.safe_dump_all(jokes, f)
|
||||||
|
|
||||||
@group(name="joke", invoke_without_command=True, case_insensitive=True)
|
@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."""
|
"""Fait discretement une blague aléatoire."""
|
||||||
|
|
||||||
m: discord.Message = ctx.message
|
m: discord.Message = ctx.message
|
||||||
await m.delete()
|
await m.delete()
|
||||||
|
|
||||||
jokes = self.load_jokes()
|
jokes = self.load_jokes()
|
||||||
if id is not None:
|
if False:
|
||||||
id = int(id)
|
|
||||||
joke_id = id
|
joke_id = id
|
||||||
jokes = sorted(
|
jokes = sorted(
|
||||||
jokes, key=lambda j: len(j.likes) - len(j.dislikes), reverse=True
|
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)
|
self.save_jokes(jokes)
|
||||||
|
|
||||||
@joke.command(name="top", hidden=True)
|
@joke.command(name="top", hidden=True, enabled=False)
|
||||||
@commands.has_any_role(*Role.ORGAS)
|
|
||||||
async def best_jokes(self, ctx: Context):
|
async def best_jokes(self, ctx: Context):
|
||||||
"""Affiche le palmares des blagues."""
|
"""Affiche le palmares des blagues."""
|
||||||
|
|
||||||
|
@ -724,9 +628,8 @@ class MiscCog(Cog, name="Divers"):
|
||||||
if joke.file:
|
if joke.file:
|
||||||
text += " - image non inclue - "
|
text += " - image non inclue - "
|
||||||
|
|
||||||
name = who.display_name if who else "Inconnu"
|
|
||||||
embed.add_field(
|
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)
|
await ctx.send(embed=embed)
|
||||||
|
|
Loading…
Reference in New Issue