Stopping a discord bot from responding to itself - python

I'm really new to coding, and I'm just wondering if I can get some help with a discord bot I've based off of Frost Bot.
The idea is pretty simple, Frost will respond to users, but I've removed the need to mention it to get a response.
I have a twin bot, too, and the idea is to get them to converse, which they do, however it seems that they're trying to respond to what they themselves have said, which causes a backlog of replies to come out.
Here is the bulk of the code, written in Python- if that matters.
#client.event
async def on_ready():
print('Logged in as '+client.user.name+' (ID:'+client.user.id+') | '+str(len(client.servers))+' servers')
await client.change_presence(game=discord.Game(name='chat with me!'))
#client.event
async def on_message(message):
if not message.author.bot == client.user:
await client.send_typing(message.channel)
txt = message.content.replace(message.server.me.mention,'') if message.server else message.content
r = json.loads(requests.post('https://cleverbot.io/1.0/ask', json={'user':user, 'key':key, 'nick':'frost', 'text':txt}).text)
if r['status'] == 'success':
await client.send_message(message.channel, r['response'] )
Any help would seriously be appreciated, as I'm incredibly new to scripting/coding and have spent a few hours already trying to research a solution.

Do a message.author.id == otherBotID: #stuff instead.
If you have more than one other bot to have a conversation with, switch to a NOT operator and place it as your own bot's ID, then check if the message author is a bot.
EDIT
Replace it in if not message.author.bot == client.user:.
Originally, you were checking if the message's author is not a user. And if it was not a user you would do stuff.
But since your own bot is not a user itself, the if statement would pass too when your bot sends a message (and recieves it's own message).
Hence we are placing a if-statement to check if the bot's ID equals to the targeted bot's ID.

Related

If Discord.py Bot gets dm

Dear stackoverflow community.
I want to add a little 'Easter egg' to my discord.py bot. If one gets a DM from a user, he should reply something like "No private messages while at work". Is that somehow possible? Unfortunately, I have no idea how to do this. That's why I can't attach code. Please help me : )
You can have an on_message event, which will fire each time there is any new message which your bot can read. Then you can check if the message is a direct message:
#bot.event # could be client instead of bot for you
async def on_message(message):
if message.author == bot.user: # Don't reply to itself. Could again be client for you
return
if isinstance(message.channel,discord.DMChannel): #If you want this to work in a group channel, you could also check for discord.GroupChannel
await message.channel.send("No private messages while at work")
await bot.process_commands(message)
Also don't forget to add bot.process_commands(message) add the end of on_message so your commands still work. (Could again be client instead of bot for you)
References:
Message.channel

How do you make your bot ignore reply mentions?

In my bot, I have an event for replying to when the bot is mentioned. The issue is, that it replies when u mention the bot through replying to it. How can I fix this? Here's my code:
#commands.Cog.listener()
async def on_message(self, msg):
guild = msg.guild
prefix = get_prefix(self.client, guild)
if msg.author == self.client.user:
return
if msg.mention_everyone:
return
if self.client.user.mentioned_in(msg):
embed = discord.Embed(description=f"The prefix for this server is `{prefix}` <:info:857962218150953000>", color=0x505050)
await msg.channel.send(embed=embed)
Change
if self.client.user.mentioned_in(msg):
to
if msg.guild.me.mention in msg.content:
Why this happens
discord messages use a special field in it's messages to specify if someone is mentioned or not, if a message has someone in that field then the message will ping that someone. mentioned_in works that way so you can figure out if a certain message pings a certain person. when we use the msg.guild.mention part, we manually check for the mention instead of discord telling us if someone was mentioned since discord counts replies as mentions
I've used the following code for similar applications.
Note - Replace 'client' in client.user.id with what you've used like bot.user.id
#client.event
async def on_message(message):
if message.content in [f'<#{client.user.id}', f'<#!{client.user.id}>']:
await message.channel.send("Hey! My prefix is ```,```")
await client.process_commands(message)

Python Discord.py - Bot wont register reactions to messages from before the bot is started

I'm writing a discord bot for a server which I want to detect when someone has reacted to a message. It's working flawlessly for all messages that were sent while the bot is active. Any messages that were sent before the bot came online, however, are not picked up. Almost as if the bot simply isn't monitoring them.
Here is the code I'm using:
#client.event async def on_reaction_add(reaction, user):
#ensures the message is not from itself and it's in the right channel
if reaction.message.author == client.user or reaction.message.channel.name != 'basement-bets':
return
#calls the appropriate function based on the emoji sent by the mod
if reaction.emoji == '👍':
outPut = betting.bet_won(reaction.message.id)
await client.get_channel(channel).send('{0.author.mention}, '.format(reaction.message) + outPut)
print(outPut)
I've searched the API and I'm struggling to see why this is, or how I widen the scope of the bots view, should that be the issue.
All help greatly appreciated.
Edit: To clarify, I mean that once I turn it on and it's online, it won't monitor the messages sent prior to it being on. Even after coming online.
It Isn't Possible To Let The Bot Be Working While It's Offline. However, There Are Solutions.
Perhaps Try To Host Your Bot on Something Like Heroku, It Will Be Online For about 3/4 of the Month if You Use the Free Plan. (If You Have Trouble Getting It Up, Consider Watching a YouTube Tutorial)
If You Want It To Be Online 24/7 However, Then You Probably Will Need to Pay.
Just use the on_raw_reaction_add(payload) it can see every reaction happening but you have a payload in input see the code below to get the user and the reaction (doesn't work in DM's).
#bot.event
async def on_raw_reaction_add(payload):
if payload.guild_id == None: # payload.guild_id is None when it is in DM's (you can't get DM channel by id)
return
message = await bot.get_channel(payload.channel_id).fetch_message(payload.message_id)
reaction = nextcord.utils.get(message.reactions, emoji=payload.emoji.name)
user = payload.member
(code from Monu Yadav)

await client.wait_for isn't working correctly discord.py

possible cause #2 is probably what's happening
Why I am using this:
I am trying to get my bot to detect a bot's embed message (to get the in-game currency of a player) using
await client.wait_for
Problem
However, it somehow does not detect the embeds sent by the bot. It still acknowledges it as long as it has plain text sent together with the embed or it sends the plain text on its own. The
#client.event
async def on_message(message):
code will still work if the bot has sent embeds with or without the text.
Possible causes:
1. ❌Already tested and proven not the cause❌ That my bot cannot read messages from bots
2. Possible: That my bot is slower that the bot I am testing with, so once my bot detects a message sent by a user for the bot to react, the bot has already responded with another message, so the bot is still waiting for a non-existent message. I have not found a viable, not time-consuming way to test this
3. Possible: {this question}
Others
All help will be appreciated! Please also point out any errors in my code here and whether I am using the right code to detect embeds and/or messages by bots. I would also appreciate alternative ways of doing my code.
Code
A portion of my current code is:
def pred(m):
return m.author == client.get_user(490707751832649738)
try:
msg = await client.wait_for('message', check=pred, timeout=10.0)
except asyncio.TimeoutError:
await message.channel.send('Looks like Taco-shack is down :/')
else:
await message.channel.send('You said {0.content}, {0.author}.'.format(msg))
Please ignore the indentations. It was fresh copypasta from my code. I modified it from the API https://discordpy.readthedocs.io/en/latest/migrating.html#waiting-for-events
output:
Looks like taco-shack is down which is the output of an asyncio timeout error
P.S. This is my first question after creating my stack overflow account, I realised that there were already so many articles that I could refer to. So I kept searching, but I could only not find the solution to this question. Please ignore my poor formatting!
Edit:
in response to my comments, I shall make it more clear
I have amended my above code because of Eric's help. He commented something that led me to improve my code ;)
Thanks
In response to Patrick's comment (thanks a lot for directing me to the https://stackoverflow.com/help/minimal-reproducible-examrple help page, really appreciate it ;)), here are a few steps you can go to reproduce the code.
Steps to reproduce the problem
Step 1:
Go to the Discord developer portal and create 2 bots, one for sending the embed and the other for this testing thing (one if you have a random bot that can send embeds
Step 2:
Invite the bot(s) to your server
Step 3:
Code the first bot to send an embed once you sent a message inside any channel maybe a simple embed like the one in How can I send an embed via my Discord bot, w/python? and also maybe an else added to it and that else sends some plain text. Remember to use client.run()!
Step 4
Code the second bot like this:
#client.event
async def on_message(message):
def pred(m):
return m.author == client.get_user(490707751832649738)
try:
msg = await client.wait_for('message', check=pred, timeout=10.0)
except asyncio.TimeoutError:
await message.channel.send('Looks like Taco-shack is down :/')
else:
await message.channel.send('You said {0.content}, {0.author}.'.format(msg))
client.run('token')
Step 5:
Run the two bots!
More questions:
I don't seem to understand whats the use of using message.embeds. I am trying to wait for a message to be sent under the on.message to continue the thread after someone types .balance to see the value of their account so that the bot can get the information. However, it does not recognise a message was sent by the bot
Legality/ethicality
The idea of making this bot came because Carl could not send the message ID.
This part is to see how much money the user has left along with whether the person has successfully sent the donation so that false donations do not clutter the channel
This bot is not meant to be a self bot.
and should not be thought as one.
** If and when you find out that this is not legal, please give a 'no' answer or comment that it is not legal (I prefer the latter) **
I can't reproduce this. Here's what I'm doing
#bot.event
async def on_message(message):
if message.author.id == bot.user.id:
print(message.content)
print(message.embeds)
await bot.process_commands(message)
#bot.command()
async def comm(ctx):
msg = await bot.wait_for('message', check=lambda m: m.author.id == bot.user.id)
await ctx.send(f"{msg.content} {msg.embeds}")
#bot.command()
async def send_content(ctx):
await ctx.send("content1")
#bot.command()
async def send_embed(ctx):
embed = Embed(title="Title1")
await ctx.send(embed=embed)
#bot.command()
async def send_both(ctx):
embed = Embed(title="Title2")
await ctx.send("content2", embed=embed)
I only have the one bot, so maybe that's the problem, but by running !comm and then !send_embed, the bot will detect its own embed-only message from wait_for. One thing I do in this code is to compare objects by id instead of by simple equality.
I edited my on_message to detect the response the second it hears the message. Thanks for all your help :) It was the 2nd thing I ruled out

Discord Bot Delete Messages in Specific Channel

TIA for your help and apologies, I'm a newbie so this may be a foolish question. I've searched through and can't find anything specific on how to make a discord bot (in Python) delete messages only within a specific channel. I want all messages sent to a specific channel to be deleted, their contents sent via PM to the user and the user's role changed.
Is there a way to use on_message and specify in an specific channel?
#client.event
async def on_message(message):
user = message.author
if message.content.startswith("Cluebot:"):
await message.delete()
await user.send("Yes?")
await user.remove_roles(get(user.guild.roles, "Investigator"))
The problem I'm having is I'm also using commands which now no longer work because the bot only responds if the message begins with "Cluebot:" Can I have the bot only look for "Cluebot:" in a specific channel?
Is it possible to make this work through a command instead of an event?
Thanks for your help. :)
The problem I'm having is I'm also using commands which now no longer work because the bot only responds if the message begins with "Cluebot:" Can I have the bot only look for "Cluebot:" in a specific channel?
About this problem the clue is:
await bot.process_commands(message)
as docs says Without this coroutine, none of the commands will be triggered.
about the main question you could try using get_channel by ID and then purge it:
eg.
#client.event
async def on_message(message):
purgeChannel = client.get_channel([CHANNEL ID]])
await purgeChannel.purge(limit=1)
you can add check to purge() to check for deleting specific message:
eg.:
def check(message):
return message.author.id == [author's ID]
#client.event
async def on_message(message):
purgeChannel = client.get_channel([CHANNEL ID]])
await purgeChannel.purge(limit=1, check=check)

Categories

Resources