import asyncio,discord from discord.ext import commands from core.ctx import Ctx from core.limiter import Limiter async def setup(bot): lim=Limiter() async def run(ctx,st,wait,uid): try: if wait>0:await asyncio.sleep(wait) st.tasks.discard(asyncio.current_task()) await bot.invoke(ctx) except asyncio.CancelledError:pass except Exception as e:bot.hook.put(f"dispatch failed for {uid}: {e!r}"[:1900]) async def handler(m): if m.author.bot or not m.content.startswith(await bot.get_prefix(m)):return uid=m.author.id if uid!=bot.user.id and uid not in bot.wl:return ctx=await bot.get_context(m,cls=Ctx) if ctx.command is None:return st,wait,full=lim.admit(uid) if full: n=lim.flush(st) bot.hook.put(f"{m.author} ({uid}) flooded, {n} pending commands dropped") try:await m.add_reaction("\u274c") except Exception:pass try:await m.reply(f"too many pending commands, {n} dropped",mention_author=False) except Exception:pass return ctx.limited=wait>0 where=f"#{getattr(m.channel,'name',None) or 'dm'} ({m.guild.name if m.guild else 'dm'})" bot.hook.put(f"{m.author} ({uid}) ran `{m.content[:200]}` in {where}") lim.track(uid,st,asyncio.create_task(run(ctx,st,wait,uid))) async def on_command_error(ctx,e): if isinstance(e,(commands.CommandNotFound,commands.CheckFailure)):return bot.hook.put(f"error in `{ctx.command}` by {ctx.author.id}: `{e!r}`"[:1900]) try:await ctx.send(f"error: `{e}`"[:1900]) except Exception:pass bot.on_message=handler;bot.on_command_error=on_command_error