How to skip bot from executing a command | discordpy - python

I have a problem. I am building a bot to filter the chat, which has two important commands. "addword" for add a word to list
But here if I want to use the "removeword" command, the bot thinks it's a word in the list and deletes it and it doesn't work properly.

Well, this might not be a perfect answer, but this might work or at least help:
#client.event
async def on_message(message):
if condition: # if this is true, the command will be executed
await client.process_commands(message)
By doing that, we can set the variable condition to whatever you want to, for example:
condition = not message.startswith('!removeword')
The example makes it so that whenever the removeword command is being typed into the chat, it won't response or run the actual command.
Make sure to replace the prefix ! with yours.

Related

Disabling a discord bot for a set time using a command in Discord.py

I've been trying to figure this out for a little while, but given that I'm mostly just slapping other people's code together and trying to troubleshoot what goes wrong, I lack a lot of the knowledge needed to do this.
I'm trying to make a bot that, when someone in the server uses the word "the" in any context (even without the bot's prefix), it corrects them with "da" (this is a running joke, please don't roast me for it lmfao). With what it does, it can be annoying - so I'd like to have people be able to disable it for something like 5 minutes at a time, and have it not send messages. The problem is, I have so little experience with python that I'm basically just guessing here. How would I go about making a command that, when triggered, would keep the bot from sending messages for a set amount of time?
Right now, the way that it's sending messages is by checking if the message contains "the", so would it be possible to have it also check something like if a boolean is true before sending?
Here's the main block of code that's responsible for the sending. I am aware that it's probably suboptimal, and if you're so inclined, feel free to explain to me how I could make it better!
#client.event
async def on_message(message):
if message.author == client.user:
return
if ('the') in message.content:
await message.channel.send('i think you meant da :rolling_eyes:')
Thanks!
(Also, is there any way that I would be able to only have it respond if "the" is by itself, and not in a word? I tried just making it have spaces before and after, but that didn't work if a message started or ended with it. I figured this probably didn't warrant its own post, since I'm probably just stupid lmao)
You can use a global variable to store a value and edit it from different places
correct_the = True
#client.event
async def on_message(message):
global correct_the
if message.author == client.user:
return
words = message.content.lower().split(" ") # make a list of all words
# like this -> ["the", "dogs", "and", "cats"]
if 'the' in words:
if correct_the: # check if it should correct it
await message.channel.send('i think you meant da :rolling_eyes:')
if message.content.startswith("!disable"): # or make this as command if you use commands.Bot
if not correct_the:
print("already disabled")
else:
correct_the = False
await asyncio.sleep(5*60) # sleeps 5min
correct_the = True

Match to the nearest command name in discord.py

I'm trying to create a feature for my discord.py bot that would send command names that are similar to what the user has used as a command when what they have typed in is incorrect. For example, a command called .slap exists. But the user enters .slp or something similar.
I want the bot to respond with the most similar command(s) which in this case is gonna be .slap. I'm a beginner still so I have no idea how to do this. I discovered about a lib called fuzzywuzzy and Levenshtein distance and I have no idea how to use them for my bot.
Any help would be highly appreciated!
Thanks
First of all, fuzzymatching commands and executing what it thinks is right, is not a great thing to add to your bot. It adds a point of failure, which can be pretty frustrating for the user regardless.
However, if you suggest a list of possible commands, it would probably work a lot better.
FuzzyWuzzy is a great tool for this.
The documentations for it are extremely helpful, so I really don't think you would have an issue if you actually read them.
My 2 cents for implementing would be (in pythonian pesudocode)
# user had input an invalid command
invalid_command = #userinput
command_list = [#list of your commands]
fuzzy_ratios = []
for command in command_list:
ratio = fuzzywuzzy.ratio(invalid_command, command)
fuzzy_ratios.append(ratio)
max_ratio_index = fuzzy_ratios.index(max(fuzzy_ratios))
fuzzy_matched = command_list[max_ratio_index]
return f"did you mean {fuzzy_matched}?"
Please try to implement and think why you need to implement it.
You need to actually try to implement yourself, or you will never learn.
You can try this:
disables = []
#client.command()
#commands.has_permissions(administrator=True)
async def disable(ctx, command):
command = client.get_command(command)
if not f"{command}: {ctx.guild.id}" in disables:
disables.append(f"{command}: {ctx.guild.id}")
await ctx.send(f"Disabled **{command}** for this server.")
else:
await ctx.send('This command is already disabled')
#client.command()
#commands.has_permissions(administrator=True)
async def enable(ctx, command):
command = client.get_command(command)
if f"{command}: {ctx.guild.id}\n" in disables:
await ctx.send(f"Enabled **{command}** for this server.")
else:
await ctx.send('This command is already enabled')
Now you have to add:
if "COMMAND: {ctx.guild.id}" in disables:
return
Between async def command(ctx) and your code for this command.
Warning: This is really bad way to do this. You can try to save a disables list to a json file. If you need help message me - Special unit#5323
Something you could use is aliases. Aliases are shortcuts for commands, here's an example:
#client.command(aliases=["slp","spla","spal","slpa","sap","salp"])
async def slap(ctx):
#Do whatever slap does
to create an alias you add aliases=[""] and start adding aliases. Aliases will invoke as commands. If I did .spla or whatever alias you added, it will still do what .slap does. Hope this helped!

discord py - message.mentions "else" makes nothing

I want to get the user that was mentioned in a message and send him a private message. That's working without problems, but now I want to add a message for the case, that the mentioned member is not on the same server.
I searched a lot and try now for over 3 hours to find a solution.
Showcase of the problem: https://youtu.be/PYZMVXYtxpE
Heres my code:
#bot.event
async def on_message(message):
if len(message.mentions) == 1:
membe1 = message.mentions[0].id
membe2 = bot.get_user(membe1)
guild = bot.get_guild(message.author.guild.id)
if guild.get_member(membe1) is not None:
await membe2.send(content=f"you was mentioned in the server chat")
else:
embed2 = discord.Embed(title=f"ยป :warning: | PING not possible", description=f"not possible")
await message.channel.send(content=f"{message.author.mention}", embed=embed)
await message.delete()
return
The first part is working without problems, but at the "else" part, does the bot nothing. He still posts the message with the "invalid" ping in the chat and just ignores it. What can I do to fix that?
There is an error of design in what you are trying to do.
In Discord, you are not able to mention a user if he is not on that same server, so what you are checking will never work at all, currently your code is pretty much checking if the mentioned user exists, which will always happen unless he leaves the guild at the same time the command is executed.
Say for example, to make your command work you want to mention the user user123, who is in your server, you do the following:
#user123 blablabla
And that works because Discord internal cache can find user123 in your server and it is mentioned, which means that clicking on "#user123" will show us a target with his avatar, his roles or whatsoever.
But if you try to do the same for an invalid user, let's say notuser321:
#notuser321 blablabla
This is not a mention, take for example that you know who notuser321 is but he is in the same server as the bot is. Discord cannot retrieve this user from the cache and it is not considered a mention, just a single string, so not a single part of your code will be triggered, because len(message.mentions) will be 0.
Something that you could try would be using regular expressions to find an attempt to tag within message.content. An example would be something like this:
import re
message = "I love #user1 and #user2"
mention_attempt = re.findall(r'[#]\S*', message) # ['#user1', '#user2']

Capturing user input as a string in Discord.py rewrite and returning said input in a message

I'm trying to capture a users input, what they say in a message, and have it returned to them in a message from the bot. More specifically, when they run a command, it'll return what ever text they have entered after that.
So far, I'm here:
async def on_message(message):
if message.content.startswith["=ok"]:
await client.send_message(message.channel, message.content[6:])
...unfortunately, I believe this was valid for the previous version of Discord.py before the rewrite. Essentially I want someone to be able to run the command =pressf and have the bot return the message "Everyone, lets pay respects to (string)!" An event probably isn't the best way to go about this but I'm stumped.
I've been struggling to find a specific answer online for my issue so I greatly appreciate anyone who could point me in the proper direction. Thanks!
I would recommend using the newer Commands Extension, it is much simpler to implement what you are wanting. See this bit specifically for passing everything a user types after the command into a variable.
There is an official example I would recommend looking at here: https://github.com/Rapptz/discord.py/blob/master/examples/basic_bot.py
You should use commands instead of on_message event. Here is a simple command:
#client.command()
async def test(ctx):
await ctx.send('A Simple Command')
ctx parameter is the parameter that all commands must have. So, when you type =test, it will send to that channel A Simple Command.
If we come to what you try to do, you can use more parameters than ctx. Here is how you can do it:
#client.command()
async def pressf(ctx, *, mess):
await ctx.send(mess)
In this code, you have 1 more parameter called mess and also there's a *. That means mess parameter includes every message after =pressf. So when a user type =pressf Hello, it will send the channel Hello.

How do I grab user input with my Discord bot in Python?

I would like to grab user input from the user when they enter a certain command and store the input into a variable (but not the command) so that I can do things with it.
As an example, when the user types "!id 500", I want the bot to type "500" in the channel. I have tried just using message.content but it doesn't work properly because the bot spams it indefinitely, plus it shows the command as well.
#client.event
async def on_message(message):
if message.content.startswith("!id"):
await client.send_message(message.channel, message.content)
Sorry if this is a silly question, but any help would mean a lot.
If you want the bot to just send the message of the user without the command part ("!id") you'll have to specify which part of the string you want to send back. Since strings are really just lists of characters you can specify what part of the string you want by asking for an index.
For example:
"This is an example"[1]
returns "h".
In your case you just want to get rid of the beginning part of the string which can be done like so:
#client.event
async def on_message(message):
if message.content.startswith("!id"):
await client.send_message(message.channel, message.content[3:])
this works because it sends the string back starting with the 4th index place (indexes start at 0 so really [3] is starting at the fourth value)
This also applies if you just want to save the user's message as a variable as you can just do this:
userInput = message.content[3:]
You read more about string manipulation at the python docs.
I would use commands extension - https://github.com/Rapptz/discord.py/blob/async/examples/basic_bot.py
Then make a command like,
#bot.command(pass_context=True)
async def id(ctx, number : int):
await bot.say(number)
The reason your bot spams the text is because your bot is saying the command, which it follow. You need to block your bot from counting your output as a command. You could block it by:
if message.author.bot: return.
This will return None if the author is a bot. Or, you could just block your bot's own id. You won't need to do this if you actually get your command to work correctly, but you should still add it. Second of all, the way I separate the command and arguments is
cmd = message.content.split()[0].lower()[1:]
args = message.content.split()[1:]
With these variables, you could do
#client.event
async def on_message(message):
if message.content.startswith('!'):
if message.author.bot: return # Blocks bots from using commands.
cmd = message.content.split()[0].lower()[1:]
args = message.content.split()[1:]
if command == "id":
await client.send_message(message.channel, ' '.join(args)

Categories