mirror of
				https://gitlab.com/ddorn/tfjm-discord-bot.git
				synced 2025-11-04 04:22:16 +01:00 
			
		
		
		
	:sparles: safe calc cmd
This commit is contained in:
		
							
								
								
									
										133
									
								
								src/cogs/misc.py
									
									
									
									
									
								
							
							
						
						
									
										133
									
								
								src/cogs/misc.py
									
									
									
									
									
								
							@@ -1,15 +1,17 @@
 | 
				
			|||||||
 | 
					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 defaultdict, Counter
 | 
					from collections import Counter, defaultdict
 | 
				
			||||||
from dataclasses import dataclass, field
 | 
					from dataclasses import dataclass, field
 | 
				
			||||||
from functools import partial
 | 
					from functools import partial
 | 
				
			||||||
from itertools import groupby
 | 
					from math import *
 | 
				
			||||||
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
 | 
				
			||||||
@@ -19,24 +21,24 @@ 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 (
 | 
					from discord.ext.commands import (BadArgument, Cog, command, Command, CommandError, Context, Group, group, is_owner,
 | 
				
			||||||
    Cog,
 | 
					                                  MemberConverter, RoleConverter)
 | 
				
			||||||
    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, start_time, send_and_bin
 | 
					from src.utils import has_role, send_and_bin, start_time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 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, "sin": sin, "cos": cos, "pi": pi, "exp": exp,
 | 
				
			||||||
 | 
					    "log": log, "abs": abs, "sqrt": sqrt, "tau": 2*pi, "π": pi, "τ": 2*pi,
 | 
				
			||||||
 | 
					    "e": e, "i": 1j,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@dataclass
 | 
					@dataclass
 | 
				
			||||||
@@ -190,6 +192,96 @@ 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"(\d)i", r"\1*i", 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])
 | 
				
			||||||
@@ -524,14 +616,15 @@ 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):
 | 
					    async def joke(self, ctx: Context, id=None):
 | 
				
			||||||
        """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 False:
 | 
					        if id is not None:
 | 
				
			||||||
 | 
					            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
 | 
				
			||||||
@@ -613,7 +706,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)
 | 
				
			||||||
    @commands.has_any_role(*Role.ORGA)
 | 
					    @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."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -631,7 +724,7 @@ class MiscCog(Cog, name="Divers"):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            name = who.display_name if who else "Inconnu"
 | 
					            name = who.display_name if who else "Inconnu"
 | 
				
			||||||
            embed.add_field(
 | 
					            embed.add_field(
 | 
				
			||||||
                name=f"{i} - {name} - {len(joke.likes)}", value=text
 | 
					                name=f"{i} - {name} - {len(joke.likes)} :heart: {len(joke.dislikes)} :broken_heart:", value=text, inline=False
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await ctx.send(embed=embed)
 | 
					        await ctx.send(embed=embed)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user