How to set up a discord bot that replies upon mention to messages which contain certain words without prefix command? - discord

I'm trying to create a simple discord bot that replies with mention to messages that contain certain words.
Also, I want the bot to respond only when it gets mentioned and without a prefix.
This was my try, but the bot didn't reply at all to the messages.
import discord
from discord.ext import commands
client = commands.Bot(command_prefix='')
#client.event
async def on_message(message):
if client.user.mentioned_in(message){
if message.content == "Hi"{
await message.channel.send(f"Hello {message.author.mention}")
}
if message.content == "How are you?"{
await message.channel.send(f"I'm good {message.author.mention}")
}
}
client.run("TOKEN")

message.content contains the entirety of the message text so when you do #mybot Hi, the message.content will be something like: <#MY_BOT_ID> hi. Your code is checking that the message.content is exactly equals to either Hi or How are you? and that is not going to be the case.
You could use Python's in operator to check for certain text:
#client.event
async def on_message(message):
if client.user.mentioned_in(message):
# making the text lowercase here to make it easier to compare
message_content = message.content.lower()
if "hi" in message_content:
await message.channel.send(f"Hello {message.author.mention}")
if "how are you?" in message_content:
await message.channel.send(f"I'm good {message.author.mention}")
client.run("TOKEN")
Though, this isn't perfect. The bot will also respond to anything with the characters hi in. You could split the content of the messages by word and check that or you could use regular expressions. See this post for more info.
Additionally, your python code had some {} brackets - which is invalid syntax for if statements - I've corrected that in my example. Consider looking up python syntax.

Related

how to add reaction to a specifc user?

I've been working on this piece of code:
#client.event
async def lol(message,ctx):
if ctx.author.id == <user_id>:
await message.add_reaction('❤️')
else:
return
I am pretty sure that it is developed correctly, yet I am not getting the desired results.
I am pretty sure that if you check the console, an HTTP error would have been encountered. That's because you directly pasted the emoji in the function parameter. You have to add its unicode value. In your case:
await message.add_reaction(u'\u2764')
You are using an event decorator rather than a command, unless you were trying to detect if the user reacted, but its still completely off. What it looks like, the command that is called will send a message and the bot will react to it.
#client.command()
async def lol(ctx):
message = await ctx.send(f"{ctx.author.mention}, lol")
await message.add_reaction('😂')
If you then want to detect if the user had reacted to the emoji, you can use a event, but an on_reaction_add:
#client.event
async def on_reaction_add(reaction, user):
if reaction.emoji == '😂':
await user.send("Lol")

Adding reaction if message contains certain content

I wanted to ask how do I make my bot react to a message if it contains something, for example:
if the message contains "Hi" the bot will react with :wave:.
so how do I do this? any help is appreciated, I am new to the forum so sorry if I made any mistakes. :)
You should try this
#client.event
async def on_message(message):
if 'Hi' in message.content.split():
await message.add_reaction("👋")
It will probably work
if you use cogs :
#commands.Cog.listener()
async def on_message(self,message):
if 'Hi' in message.content.split():
await message.add_reaction("👋")

Saving message content to a list discord.py

I'm trying to create a playlist which the bot can send but I can't figure it out, here's the code I've tried although it only takes the text to trigger the command and I can't access the list anywhere.
Code:
#client.event
async def on_message(message):
if message.content == "=playlist":
playlist = message.content
await message.channel.send(playlist)
Any ideas?
I don't understand what the problem is, by the looks of it, when a users message is =playlist, your code will send all the contents of that message essentially back to them. Is that not what you want?

discord.py bot repeating messages

hi i am trying to make a discord.py bot so i can have a gif chat channel but when someone types a message in that channel then my bot starts repeating his message, pls help if u know.
my code:
#client.event
async def on_message(message):
with open("gif_chater.json", "r+") as file:
data=json.load(file)
if str(message.channel.id) in data:
if message.content.startswith("https://tenor.com/"):
print("wOw")
if not message.content.startswith("https://tenor.com/") and not message.author.id == "760083241133932544":
await message.channel.send("lol pls use gifs in this channel : )")
await message.delete()
exit
The on_message event
The issue is that the bot is constantly responding to itself, and it's because the on_message event triggers not just when users send a message but also when the bot sends a message. As such, once it tells the user that they must only post tenor gifs, it reacts to its own message and goes into an infinite loop, posting and deleting its responses.
Preventing the bot from responding to itself
To prevent the bot from responding to it's own messages, you should add a check at the start of the event like in the discord.py docs:
#client.event
async def on_message(message):
if message.author == client.user:
return
...
Also, the ID check at the end
The last condition in your code before it decides to send a message is checking the ID of the messenger (not message.author.id == "760083241133932544"). I don't know whether it's meant to avoid deleting you or the bot's messages but regardless, the check itself is bugged. message.author.id returns an integer but is then being compared to a string, and due to the conflicting types, will always return False.
To fix it, change your ID to an integer by removing the quotes: not message.author.id == 760083241133932544. As well, you should use the not-equals operator != instead of not to improve readability: message.author.id != 760083241133932544.
Also, since you already checked if the message starts with the website link, you can use an elif statement instead of rechecking the condition, since else/elif guarantees that the previous condition was false (aka, that the message didn't start with the website link):
if message.content.startswith("https://tenor.com/"):
print("wOw")
elif message.author.id != 760083241133932544:
await message.channel.send("lol pls use gifs in this channel : )")
await message.delete()
Fixes combined
With the new changes, your function could look something like this:
#client.event
async def on_message(message):
# Don't respond to the bot's own messages
if message.author == client.user:
return
with open("gif_chater.json") as file:
data = json.load(file)
if str(message.channel.id) in data:
if message.content.startswith("https://tenor.com/"):
print("wOw")
elif message.author.id != 760083241133932544:
await message.channel.send("lol pls use gifs in this channel : )")
await message.delete()

Discord Py bot spams channel when looping through a dictionary

import asyncio
import random
import discord
memes = {
'r/dank_memes': {'imgur_url':'https://imgur.com/r/dankmemes/', 'trigger': 'get dank', 'memes':['get dank meme', 'sample meme']},
'r/cats': {'imgur_url':'https://imgur.com/r/cats/', 'trigger': 'meow', 'memes':['cat meme', 'i love cats']},
}
#client.event
async def on_message(message):
message.content = message.content.lower()
for name, trigger in memes.items():
if trigger['trigger'] in message.content:
#print(random.choice(memes[name]['memes'])) # This works fine
await client.send_message(message.channel, random.choice(memes[name]['memes']))
I am making a discord bot that posts random memes I scraped online when a certain keyword is said in my channel.
My problem is that when I type "get dank" in discord the bot will spam a bunch of memes:
get dank meme
get dank meme
dank 2
get dank meme
But when I type "meow" or whatever the last value is in the memes dictionary then it works fine and only sends one image.
I have figured out that this has something to do the await from asyncio because when I use print() it only sends its once to the console. It appears the await is required though because the script won't do anything without it. Using break in the for loop doesn't help either.
Is there a way to make the loop stop once it found a keyword or to only have it send one image and using the await.
The problem could be that one of your sample memes, get dank meme, contains the trigger itself. A new on_message picks it up, and responds with a new meme, which can again contain the trigger, and so on. That doesn't happen with print because print does not transmit to the channel and therefore cannot trigger meme responses.
To fix this, either be careful to avoid triggers in your meme responses, or include code that ignores triggers coming from the bot itself.

Resources