From 83074a743b7f042b50944d6de662a23179e2df4a Mon Sep 17 00:00:00 2001 From: osmarks Date: Sat, 17 Jul 2021 22:09:17 +0100 Subject: [PATCH] general changes, fix webhook rate limit incursions --- src/commands.py | 13 +++++++------ src/eventbus.py | 1 + src/telephone.py | 18 ++++++++++++++---- src/tio.py | 2 +- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/commands.py b/src/commands.py index e380af1..984bbdd 100644 --- a/src/commands.py +++ b/src/commands.py @@ -4,6 +4,7 @@ import random from numpy.random import default_rng import re import aiohttp +import subprocess import discord.ext.commands as commands import tio @@ -11,7 +12,7 @@ import util cleaner = commands.clean_content() def clean(ctx, text): - return cleaner.convert(self, ctx, text) + return cleaner.convert(ctx, text) class GeneralCommands(commands.Cog): def __init__(self, bot): @@ -21,7 +22,7 @@ class GeneralCommands(commands.Cog): @commands.command(help="Gives you a random fortune as generated by `fortune`.") async def fortune(self, ctx): proc = await asyncio.create_subprocess_exec("fortune", stdout=subprocess.PIPE) - stdout = (await proc.communicate()).decode("utf-8") + stdout = (await proc.communicate())[0].decode("utf-8") await ctx.send(stdout) @commands.command(help="Generates an apioform type.") @@ -78,12 +79,12 @@ class GeneralCommands(commands.Cog): @commands.command(rest_is_raw=True, help="Execute provided code (in a codeblock) using TIO.run.") async def exec(self, ctx, *, arg): - match = re.match(EXEC_REGEX, arg, flags=re.DOTALL) + match = re.match(GeneralCommands.EXEC_REGEX, arg, flags=re.DOTALL) if match == None: await ctx.send(embed=util.error_embed("Invalid format. Expected a codeblock.")) return flags_raw = match.group(1) - flags = exec_flag_parser.parse_args(flags_raw.split()) + flags = GeneralCommands.exec_flag_parser.parse_args(flags_raw.split()) lang = flags.language or match.group(2) if not lang: await ctx.send(embed=util.error_embed("No language specified. Use the -L flag or add a language to your codeblock.")) @@ -137,7 +138,7 @@ AutoBotRobot is operated by gollark/osmarks. rolls = [ random.randint(1, x) for _ in range(n) ] await ctx.send(f"{sum(rolls)} ({' '.join(map(str, sorted(rolls)))})") - def weight(thing): + def weight(self, thing): lthing = thing.lower() weight = 1.0 if lthing == "c": weight *= 0.3 @@ -166,7 +167,7 @@ AutoBotRobot is operated by gollark/osmarks. return # because of python weirdness, using sum() on the bare map iterator consumes it, which means we have to actually make a list - weights = list(map(weight, choices)) + weights = list(map(self.weight, choices)) if samples == 1: return await ctx.send(random.choices(choices, weights=weights, k=1)[0]) diff --git a/src/eventbus.py b/src/eventbus.py index aa33aac..4f35bdf 100644 --- a/src/eventbus.py +++ b/src/eventbus.py @@ -44,6 +44,7 @@ def find_all_destinations(source): visited.add(current) return visited +# 5 messages per 5 seconds from each input channel RATE = 10.0 PER = 5000000.0 # µs diff --git a/src/telephone.py b/src/telephone.py index c7de6c9..a539c16 100644 --- a/src/telephone.py +++ b/src/telephone.py @@ -69,6 +69,14 @@ class Telephone(commands.Cog): self.webhooks = {} self.bot = bot self.unlisten = eventbus.add_listener("discord", self.on_bridge_message) + self.webhook_queue = asyncio.Queue(50) + self.webhook_queue_handler_task = asyncio.create_task(self.send_webhooks()) + + async def send_webhooks(self): + while True: + webhook, content, username, avatar_url = await self.webhook_queue.get() + wh_obj = discord.Webhook.from_url(webhook, adapter=discord.AsyncWebhookAdapter(self.bot.http._HTTPClient__session)) + await wh_obj.send(content=content, username=username, avatar_url=avatar_url, allowed_mentions=discord.AllowedMentions(everyone=False, roles=False, users=False)) async def initial_load_webhooks(self): rows = await self.bot.database.execute_fetchall("SELECT * FROM discord_webhooks") @@ -81,10 +89,11 @@ class Telephone(commands.Cog): if channel: webhook = self.webhooks.get(channel_id) if webhook: - wh_obj = discord.Webhook.from_url(webhook, adapter=discord.AsyncWebhookAdapter(self.bot.http._HTTPClient__session)) - await wh_obj.send( - content=render_formatting(channel, msg.message)[:2000], username=msg.author.name, avatar_url=msg.author.avatar_url, - allowed_mentions=discord.AllowedMentions(everyone=False, roles=False, users=False)) + try: + self.webhook_queue.put_nowait((webhook, render_formatting(channel, msg.message)[:2000], msg.author.name, msg.author.avatar_url)) + except asyncio.QueueFull: + text = f"<{msg.author.name}> {render_formatting(channel, msg.message)}" + await channel.send(text[:2000], allowed_mentions=discord.AllowedMentions(everyone=False, roles=False, users=False)) else: text = f"<{msg.author.name}> {render_formatting(channel, msg.message)}" await channel.send(text[:2000], allowed_mentions=discord.AllowedMentions(everyone=False, roles=False, users=False)) @@ -102,6 +111,7 @@ class Telephone(commands.Cog): def cog_unload(self): self.unlisten() + self.webhook_queue_handler_task.cancel() # ++tel commands diff --git a/src/tio.py b/src/tio.py index 20fa172..9769ba7 100644 --- a/src/tio.py +++ b/src/tio.py @@ -16,7 +16,7 @@ async def run(http_session, lang, code): real_lang = aliases.get(lang, lang) req = pytio.TioRequest(real_lang, code) res = await (await http_session.post("https://tio.run/cgi-bin/run/api/", data=req.as_deflated_bytes(), timeout=65)).text() - split = list(filter(lambda x: x != "\n" and x != "", content.split(content[:16]))) + split = list(filter(lambda x: x != "\n" and x != "", res.split(res[:16]))) if len(split) == 1: return False, real_lang, split[0], None else: