async def on_member_join(self, member): general = neko.find( lambda c: c.name == 'general', member.guild.channels ) if general: await general.send( f'Welcome to {member.guild}, {member.mention}!' )
async def on_member_remove(self, member): general = neko.find( lambda c: c.name == 'general', member.guild.channels ) if general: await general.send( f'Oh no! {member.display_name} just left \N{CRYING CAT FACE}...' )
async def on_member_ban(self, guild, user): general = neko.find( lambda c: c.name == 'general', guild.channels ) if general: await general.send( f'{user.display_name} just got bent.\n' 'https://giphy.com/gifs/H99r2HtnYs492' )
async def reset_cooldown(self, ctx, *, command): command = neko.find(lambda c: c.qualified_name == command or command in c.qualified_aliases, ctx.bot.walk_commands()) if command: command._buckets._cooldown.reset() command._buckets._cache.clear() await ctx.send('Cooldown reset.', delete_after=10) else: await ctx.send('Couldn\'t find that command.')
async def on_message(self, msg): """ When we get a message, we check if certain Discord-app binds are at the start. If there is, we reply with that bind. It is as close as I can get to actually supporting the binds that you can use on desktop, on mobile. """ if not msg.guild or msg.author.bot: return guild = msg.guild.id chan = msg.channel.id timeout_k = str(guild) + str(chan) timeout_v = self.bind_cooldown_buckets.get(timeout_k) # If the user id was mapped under that identity in the # buckets, then we are on timeout, so don't bother doing # anything else. if timeout_v == msg.author.id: return async def callback(): if msg.author.id == self.bot.owner_id: # Owner privileges, kek. return # Insert into the dict self.bind_cooldown_buckets[timeout_k] = msg.author.id # Cooldown for 30s. await asyncio.sleep(30) # Remove from the dict # Specify None to prevent KeyError if it was already # removed somehow. self.bind_cooldown_buckets.pop(timeout_k, None) # Attempt to find the bind (this returns a tuple or None if not found) bind = neko.find(lambda r: r.match(msg.content), binds) if not bind: return else: bind = binds[bind] # Ensure the future, but don't bother waiting. asyncio.ensure_future(callback()) await msg.channel.send(bind)
async def on_error(cls, cog, ctx: commands.Context, error): """Handles any errors that may occur in a command.""" ctx.bot.last_error = (type(error), error, error.__traceback__) try: # For specific types of error, just react. reacts = { commands.CheckFailure: '\N{NO ENTRY SIGN}', commands.MissingRequiredArgument: '\N{THOUGHT BALLOON}', commands.CommandOnCooldown: '\N{ALARM CLOCK}', commands.DisabledCommand: '\N{MOBILE PHONE OFF}', discord.ClientException: '\N{COLLISION SYMBOL}', } reaction = neko.find(lambda e: issubclass(type(error), e), reacts) reaction = reacts[reaction] if not issubclass(type(error), discord.NotFound): await ctx.message.add_reaction(reaction) else: pass # ?? You cant react to something you cant react to. except KeyError: # If we haven't specified a reaction, we instead do something # meaningful. error = error.__cause__ if error.__cause__ else error if not isinstance(error, NotImplementedError): if isinstance(error, Warning): title = f'\N{WARNING SIGN} {error}' else: title = '\N{SQUARED SOS} Oh crap...' description = strings.capitalise(excuses.get_excuse()) else: title = ('\N{NO PEDESTRIANS} ' 'Road under construction. Follow diversion.') description = ('Seems this feature isn\'t finished! Hassle ' 'Espy to get on it. ') embed = book.Page( title=title, description=description, colour=0xffbf00 if isinstance(error, Warning) else 0xff0000) if isinstance(error, NekoCommandError): pass elif not isinstance(error, Warning): # We only show info like the cog name, etc if we are not a # neko command error. Likewise, we only dump a traceback if the # latter holds. error_description = strings.pascal_to_space( type(error).__name__) cog = strings.pascal_to_space(getattr(cog, 'name', str(cog))) error_str = str(error).strip() if error_str: error_description += f' in {cog}: {str(error)}' else: error_description += f' in {cog}.' embed.set_footer(text=error_description) traceback.print_exception(type(error), error, error.__traceback__) resp = await ctx.send(embed=embed) await asyncio.sleep(10) if isinstance(error, NekoCommandError): await resp.delete() return elif isinstance(error, Warning): await resp.edit(content='_Warnings were generated._') else: await resp.edit(content='_**Errors** were generated._') async def del_in_10(): await asyncio.sleep(10 * 60) try: await resp.delete() finally: return asyncio.ensure_future(del_in_10)