:spakles: eval keeps locals
This commit is contained in:
parent
6d1560ceaa
commit
924abea6c8
|
@ -1,8 +1,11 @@
|
|||
import asyncio
|
||||
import re
|
||||
import traceback
|
||||
from contextlib import redirect_stdout
|
||||
from io import StringIO
|
||||
from pprint import pprint
|
||||
from textwrap import indent
|
||||
from typing import Union
|
||||
|
||||
import discord
|
||||
from discord import TextChannel, PermissionOverwrite, Message, ChannelType
|
||||
|
@ -35,13 +38,14 @@ COGS_SHORTCUTS = {
|
|||
}
|
||||
|
||||
RE_QUERY = re.compile(
|
||||
r"^! ?e(val)? (`{1,3}py(thon)?\n)?(?P<query>.*?)\n?(`{1,3})?\n?$", re.DOTALL
|
||||
r"^! ?e(val)?[ \n]+(`{1,3}(py(thon)?\n)?)?(?P<query>.*?)\n?(`{1,3})?\n?$", re.DOTALL
|
||||
)
|
||||
|
||||
|
||||
class DevCog(Cog, name="Dev tools"):
|
||||
def __init__(self, bot: CustomBot):
|
||||
self.bot = bot
|
||||
self.eval_locals = {}
|
||||
|
||||
@command(name="interrupt")
|
||||
@has_role(Role.DEV)
|
||||
|
@ -225,57 +229,99 @@ class DevCog(Cog, name="Dev tools"):
|
|||
await channel.delete_messages(to_delete)
|
||||
await ctx.message.delete()
|
||||
|
||||
def eval(self, msg: Message) -> discord.Embed:
|
||||
async def eval(self, msg: Message) -> discord.Embed:
|
||||
guild: discord.Guild = msg.guild
|
||||
roles = guild.roles
|
||||
members = guild.members
|
||||
hugs_cog = self.bot.get_cog("Divers")
|
||||
hugs = hugs_cog.hugs
|
||||
channel: TextChannel = msg.channel
|
||||
send = lambda text: asyncio.create_task(channel.send(text))
|
||||
|
||||
query = re.match(RE_QUERY, msg.content).group("query")
|
||||
|
||||
if not query:
|
||||
raise TfjmError("No query found.")
|
||||
|
||||
if "\n" in query:
|
||||
if any(word in query for word in ("=", "return", "await", ":", "\n")):
|
||||
lines = query.splitlines()
|
||||
if "return" not in lines[-1] and "=" not in lines[-1]:
|
||||
if (
|
||||
"return" not in lines[-1]
|
||||
and "=" not in lines[-1]
|
||||
and not lines[-1].startswith(" ")
|
||||
):
|
||||
lines[-1] = f"return {lines[-1]}"
|
||||
query = "\n ".join(lines)
|
||||
query = f"def q():\n {query}\nresp = q()"
|
||||
query = "\n".join(lines)
|
||||
full_query = f"""async def query():
|
||||
try:
|
||||
{indent(query, " " * 8)}
|
||||
finally:
|
||||
self.eval_locals.update(locals())
|
||||
"""
|
||||
else:
|
||||
full_query = query
|
||||
|
||||
globs = {**globals(), **locals(), **self.eval_locals}
|
||||
stdout = StringIO()
|
||||
|
||||
try:
|
||||
if "\n" in query:
|
||||
q = compile(query, filename="query.py", mode="exec")
|
||||
globs = {**globals(), **locals()}
|
||||
locs = {}
|
||||
exec(query, globs, locs)
|
||||
resp = locs["resp"]
|
||||
else:
|
||||
resp = eval(query, globals(), locals())
|
||||
with redirect_stdout(stdout):
|
||||
if "\n" in full_query:
|
||||
locs = {}
|
||||
exec(full_query, globs, locs)
|
||||
resp = await locs["query"]()
|
||||
else:
|
||||
resp = eval(query, globs)
|
||||
except Exception as e:
|
||||
tb = StringIO()
|
||||
traceback.print_tb(e.__traceback__, file=tb)
|
||||
tb.seek(0)
|
||||
|
||||
embed = discord.Embed(title=str(e), color=discord.Colour.red())
|
||||
embed.add_field(name="Query", value=f"```py\n{query}\n```", inline=False)
|
||||
embed.add_field(
|
||||
name="Traceback", value=f"```py\n{tb.read()}```", inline=False
|
||||
name="Query", value=f"```py\n{full_query}\n```", inline=False
|
||||
)
|
||||
embed.add_field(
|
||||
name="Traceback", value=self.to_field_value(tb), inline=False
|
||||
)
|
||||
else:
|
||||
out = StringIO()
|
||||
pprint(resp, out)
|
||||
out.seek(0)
|
||||
|
||||
embed = discord.Embed(title="Result", color=discord.Colour.green())
|
||||
embed.add_field(name="Query", value=f"```py\n{query}```", inline=False)
|
||||
embed.add_field(name="Value", value=f"```py\n{out.read()}```", inline=False)
|
||||
embed.add_field(name="Query", value=f"```py\n{full_query}```", inline=False)
|
||||
|
||||
value = self.to_field_value(out)
|
||||
if resp is not None and value:
|
||||
embed.add_field(name="Value", value=value, inline=False)
|
||||
|
||||
stdout = self.to_field_value(stdout)
|
||||
if stdout:
|
||||
embed.add_field(name="Standard output", value=stdout, inline=False)
|
||||
|
||||
embed.set_footer(text="You may edit your message.")
|
||||
return embed
|
||||
|
||||
def to_field_value(self, string: Union[str, StringIO]):
|
||||
if isinstance(string, StringIO):
|
||||
string.seek(0)
|
||||
string = string.read()
|
||||
|
||||
if not string:
|
||||
return
|
||||
|
||||
if len(string) > 1000:
|
||||
string = string[:500] + "\n...\n" + string[-500:]
|
||||
|
||||
return f"```py\n{string}```"
|
||||
|
||||
@command(name="eval", aliases=["e"])
|
||||
@is_owner()
|
||||
async def eval_cmd(self, ctx: Context):
|
||||
""""""
|
||||
embed = self.eval(ctx.message)
|
||||
"""(dev) Evalue l'entrée."""
|
||||
|
||||
self.eval_locals["ctx"] = ctx
|
||||
|
||||
embed = await self.eval(ctx.message)
|
||||
resp = await ctx.send(embed=embed)
|
||||
|
||||
def check(before, after):
|
||||
|
@ -289,7 +335,7 @@ class DevCog(Cog, name="Dev tools"):
|
|||
except asyncio.TimeoutError:
|
||||
break
|
||||
|
||||
embed = self.eval(after)
|
||||
embed = await self.eval(after)
|
||||
await resp.edit(embed=embed)
|
||||
|
||||
# Remove the "You may edit your message"
|
||||
|
|
|
@ -8,6 +8,7 @@ import urllib
|
|||
from collections import defaultdict, Counter
|
||||
from dataclasses import dataclass, field
|
||||
from functools import partial
|
||||
from itertools import groupby
|
||||
from math import log
|
||||
from operator import attrgetter, itemgetter
|
||||
from time import time
|
||||
|
@ -177,7 +178,7 @@ class MiscCog(Cog, name="Divers"):
|
|||
|
||||
@command(name="fan", aliases=["join", "adhere"], hidden=True)
|
||||
async def fan_club_cmd(self, ctx: Context, who: Member):
|
||||
"""Permet de rejoindre le fan-club d'Ananas ou Citron Vert."""
|
||||
"""Permet de rejoindre un fan club existant."""
|
||||
role_id = FAN_CLUBS.get(who.id, None)
|
||||
role = get(ctx.guild.roles, id=role_id)
|
||||
|
||||
|
@ -362,10 +363,6 @@ class MiscCog(Cog, name="Divers"):
|
|||
diffs[m.id].add(h.hugger)
|
||||
|
||||
for m, d in diffs.items():
|
||||
if m == self.bot.user.id:
|
||||
print(everyone_diff)
|
||||
print(d)
|
||||
print(everyone_diff.union(d))
|
||||
stats[m] += len(everyone_diff.union(d)) * 42 + everyone_hugs
|
||||
|
||||
top = sorted(list(stats.items()), key=itemgetter(1), reverse=True)
|
||||
|
@ -392,10 +389,7 @@ class MiscCog(Cog, name="Divers"):
|
|||
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
async def send_hugs_stats_for(self, ctx: Context, who: Member):
|
||||
embed = discord.Embed(
|
||||
title=f"Câlins de {who.display_name}", color=discord.Colour.magenta()
|
||||
)
|
||||
async def send_hugs_stats_for(self, ctx: Context, who: discord.Member):
|
||||
|
||||
given = self.hugs_given(ctx, who.id)
|
||||
received = self.hugs_received(ctx, who.id)
|
||||
|
@ -410,6 +404,26 @@ class MiscCog(Cog, name="Divers"):
|
|||
"Morceaux": (len(cut), 30),
|
||||
}
|
||||
|
||||
most_given = Counter(h.hugged for h in given).most_common(1)
|
||||
most_received = Counter(h.hugger for h in received).most_common(1)
|
||||
most_given = most_given[0] if most_given else (0, 0)
|
||||
most_received = most_received[0] if most_received else (0, 0)
|
||||
|
||||
embed = discord.Embed(
|
||||
title=f"Câlins de {who.display_name}",
|
||||
color=discord.Colour.magenta(),
|
||||
description=(
|
||||
f"On peut dire que {who.mention} est très câlin·e, avec un score de "
|
||||
f"{self.score_for(ctx, who.id)}. Iel a beaucoup câliné "
|
||||
f"{self.name_for(ctx, most_given[0])} "
|
||||
f"*({most_given[1]} :heart:)* et "
|
||||
f"s'est beaucoup fait câliner par {self.name_for(ctx, most_received[0])} "
|
||||
f"*({most_received[1]} :heart:)* !"
|
||||
),
|
||||
)
|
||||
user: discord.User = self.bot.get_user(who.id)
|
||||
embed.set_thumbnail(url=user.avatar_url)
|
||||
|
||||
for f, (v, h_factor) in infos.items():
|
||||
heart = self.heart_for_stat(v * h_factor)
|
||||
if f == "Morceaux":
|
||||
|
@ -454,7 +468,13 @@ class MiscCog(Cog, name="Divers"):
|
|||
if memb is not None:
|
||||
name = memb.mention
|
||||
else:
|
||||
name = ctx.guild.get_role(member_or_role_id).mention
|
||||
role = ctx.guild.get_role(member_or_role_id)
|
||||
if role is None:
|
||||
name = getattr(
|
||||
self.bot.get_user(member_or_role_id), "mention", "Personne"
|
||||
)
|
||||
else:
|
||||
name = role.name
|
||||
|
||||
return name
|
||||
|
||||
|
|
|
@ -510,7 +510,7 @@ class TirageCog(Cog, name="Tirages"):
|
|||
@commands.command(name="dice-all", aliases=["da"])
|
||||
@commands.has_role(Role.DEV)
|
||||
async def dice_all_cmd(self, ctx, *teams):
|
||||
"""(dev) Lance un dé pour chaque equipe afin de tester les tirages."""
|
||||
"""(dev) Lance un dé pour chaque equipe en entrée."""
|
||||
channel = ctx.channel.id
|
||||
if channel in self.tirages:
|
||||
for t in teams:
|
||||
|
|
|
@ -12,6 +12,7 @@ __all__ = [
|
|||
"TEAMS_CHANNEL_CATEGORY",
|
||||
"DIEGO",
|
||||
"ANANAS",
|
||||
"YOHANN",
|
||||
"FAN_CLUBS",
|
||||
"BOT",
|
||||
"TOURNOIS",
|
||||
|
|
Loading…
Reference in New Issue