Is there a way to disable @everyone or @here from being used in a say command

Viewed 1372

I have a bot that has a say command and I would like to make this command public to everyone, but a possible risk is they could ping "@everyone" or "@here" via the bot's message.

If anybody has a way to mitigate this and prevent the bot from pinging everyone, please let me know.

My code:

@bot.command()
@commands.has_guild_permissions(administrator=True)
async def say(ctx, *, message=None):
    message = message or "Please say something to use the say command!"
    await ctx.message.delete()
    await ctx.send(message)
3 Answers

You can create this a couple of ways, but one way is to use a commands.check() decorator here:

def not_everyone(ctx):
    return not any(m in ctx.message.content for m in ["@here", "@everyone"])

@bot.command()
@commands.has_guild_permissions(administrator=True)
@commands.check(not_everyone) # Note you don't call the function - just pass it in
async def cmd(ctx):
    # Do stuff

References:

  • Checks in d.py

  • any()

  • Message.content

  • Message.mention_everyone - Could also be used as opposed to checking if @everyone/@here is in the message. It's down to preference. A small note for this attribute however:

    "This does not check if the @everyone or the @here text is in the message itself. Rather this boolean indicates if either the @everyone or the @here text is in the message and it did end up mentioning."

Another option is to use commands.clean_content. This will make "transform @everyone and @here mentions into non-mentions" and transform other mention into how they are displayed but this doesn't appear to have any noticable effects.

Api reference: discord.Message.clean_content

You can also use this with discord commands as a type. Advanced Converters using commands.clean_content

@commands.command()
async def say(self, ctx, message: commands.clean_content):
    ctx.send(message)

You could use regex to look at the string and identify if there's a @everyone or @here. My regex is extremely rusty so I'd advise you investigate that route further.

Another option which doesn't require regex would be to split the string down into a list of its substrings and check if any of those substrings were @here or @everyone.

    @bot.command()
    @commands.has_guild_permissions(administrator=True)
    async def say(ctx, *, message=None):
        message = message or "Please say something to use the say command!"
        message_components = message.split()
        if "@everyone" in message_components or "@here" in message_components:
            await ctx.send("You cannot have @everyone or @here in your message!")
            return

        await ctx.message.delete()
        await ctx.send(message)
Related