Discord Bots: Detecting a message within another command - python

On my discord bot (python) I am trying to detect or rather to check a sent message within a command: if someone types the command $start the command should check in a while loop which messages are being sent after the $start command. If the sent message is "join", the user who sent the message should be added to a list. I was trying to detect and save messages in a variable via the on_message() function but it doesnt seem to work and I dont think that my code makes that much sense, but I dont know how to properly implement it.
import discord
from discord.ext import commands
client = commands.Bot(command_prefix = "$")
#client.event
async def on_ready():
print("started")
sentMsg = ""
users = []
#client.event
async def on_message(msg):
if msg.author == client.user:
return
else:
sentMsg = msg.content
print(sentMsg)
#client.command()
async def start(ctx):
print(sentMsg)
await ctx.send("starting ...")
users.append(ctx.author)
while True:
if sentMsg == "join":
ctx.send("Joined!")
sentMsg = ""
client.run(*token*)
I put the sentMsg varibale to the Watch-section in VS-Code and it always says "not available" although it prints the right values. Also when hovering over it in on_message() it says: "sentMsg" is not accessed Pylance.
Can anyone improve my code or does anyone have a better idea to implement this?
I'd appreciate anyone's help

instead of using an on_message event, you can make the bot detect messages using client.wait_for!
for example:
#client.command()
async def start(ctx):
await ctx.send("starting ...")
try:
message = await client.wait_for('message', timeout=10, check=lambda m: m.author == ctx.author and m.channel == ctx.channel and ctx.content == "join") # You can set the timeout to 'None'
# if you don't want it to timeout (then you can also remove the 'asyncio.TimeoutError' except case
# (remember you have to have at least 1 except after a 'try'))
# if you want the bot to cancel this if the message content is not 'join',
# take the last statement from the check and put it here with an if
# what you want to do after "join" message
except asyncio.TimeoutError:
await ctx.send('You failed to respond in time!')
return

Related

Trying to send a message if a value is set to true discord.py

I'm trying to make my bot send a message in a channel when it starts up, I'm not getting any errors but its not sending a message in the channel. (Yes it has permissions, I thought it was that at first)
startupmessage = True
channelid = 781433663032131607
async def on_ready():
if startupmessage == True:
await client.get_channel(channelid).send('bot online')
I tried reversing it and putting the if statement first but I got errors saying invalid syntax.
It doesn't work because tou didn't register the event.
startupmessage = True
channelid = 781433663032131607
#client.event
async def on_ready():
if startupmessage == True:
await client.get_channel(channelid).send('bot online')
This should be fine.

How do I make my discord bot reading dms in Python?

I have got a discord bot and it works fine, I've just got one problem: If the bot sends a DM to someone due to some command, I want it to receive the answer to that DM. I don't get it working for DMs. I've tried some stuff I've found on the internet but nothing was even close to working. Any help would be much appreciated :)
Here's what I've tried (I'm sorry I can't give you that much)
#bot.event
async def on_private_message(ctx):
if ctx.channel.id == ctx.author.dm_channel.id:
# here I've tried using ctx.content in several ways but there was no ctx.content...
on_private_message is not a discord event, we just use on_message and check if it is a dm.
#bot.event()
async def on_message(message):
if message.guild is None:
#this is a dm message
However, I see that your problem is accepting an answer from a user in private message, this can be done with wait_for.
#bot.command()
async def something(ctx):
await ctx.author.send('hello there')
await ctx.author.send("you have 30 seconds to reply")
msg = bot.wait_for('message', check = lambda x: x.author == ctx.author and x.channel == ctx.author.dm_channel, timeout=30)
# do stuff with msg
References:
dm_channel
refer to my previous answer for info on wait_for
Ok, so as per your question it says that, you want to receive the answer of dms, in order to receive answer, you might have asked a question, so I will explain using an example, so suppose you run a command !question, the bot will dm you or whoever runs the command, a question whose answer needs to be checked. For that I would recommend the use of bot.wait_for():-
bot.command()
async def question(ctx):
channel = await ctx.author.create_dm()
def check(m):
return m.author == ctx.author and m.channel == channel
try:
await ctx.author.send("") #your question inside ""
msg = await bot.wait_for('message', timeout=100.0, check=check)
message_content = msg.content
print(message_content) #you can do anything with the content of the message
except:
await ctx.author.send("You did not answer in given time")

Send a message based on a user reaction discord.py

I would like my discord bot to respond with a certain message back within a server based on the reaction given by the user: either 👍 or 👎.
I am not too familiar with discord.py and the docs I have read are slightly confusing, I followed a youtube tutorial and made edits. I get to see the reaction printed in the console, however I get the error message:
Instance of 'Bot' has no 'channel' member
Here is my code:
import os
import datetime
import discord
from discord.ext import commands
from dotenv import load_dotenv
load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')
client = commands.Bot(command_prefix = '!')
#client.event
async def on_ready():
print('Bot is logged in.')
#client.command(name='feedback', help='Ask person for feedback')
async def roll(ctx):
await ctx.send('Are you enjoying this bot? \n :thumbsup: :-1: ')
#client.event
async def on_raw_reaction_add(reaction, user):
print(reaction.emoji)
channel = reaction.message.channel
await client.channel.send_message(channel, reaction.emoji)
if reaction.emoji == ':thumbsup:':
await client.channel.send_message(channel, 'Thank you for your feedback')
elif reaction.emoji == ':-1:':
await client.channel.send_message(channel, 'Sorry you feel that way')
client.run(TOKEN)
All help greatly appreciated
Instead of using the on_raw_reaction_add event, it's better in this case to use a wait_for command event. This would mean the event can only be triggered once and only when the command was invoked. However with your current event, this allows anyone to react to a message with that emoji and the bot would respond.
By using client.wait_for("reaction_add"), this would allow you to control when a user can react to the emoji. You can also add checks, this means only the user would be able to use the reactions on the message the bot sends. Other parameters can be passed, but it's up to you how you want to style it.
In the example below shows, the user can invoke the command, then is asked to react with a thumbs up or thumbs down. The bot already adds these reactions, so the user would only need to react. The wait_for attribute would wait for the user to either react with the specified emojis and your command would send a message.
Here is the example applied in your code.
#client.command(name='feedback', help='Ask person for feedback')
async def roll(ctx):
message = await ctx.send('Are you enjoying this bot? \n :thumbsup: :-1: ')
thumb_up = '👍'
thumb_down = '👎'
await message.add_reaction(thumb_up)
await message.add_reaction(thumb_down)
def check(reaction, user):
return user == ctx.author and str(
reaction.emoji) in [thumb_up, thumb_down]
member = ctx.author
while True:
try:
reaction, user = await client.wait_for("reaction_add", timeout=10.0, check=check)
if str(reaction.emoji) == thumb_up:
await ctx.send('Thank you for your feedback')
if str(reaction.emoji) == thumb_down:
await ctx.send('Sorry you feel that way')
You are also getting the error, Instance of 'Bot' has no 'channel' member because you are using an event which limits attributes from the "Bot". However using this within a command allows you to use ctx.send

how to allow specific messages discord bot python in specific channels

So I want to make my bot allow specific messages, like "/verify" in a specifc channel, if someone sent a message other than "verify" the bot should delete the message, however only in a specific channel, I'm new to all of that but I made this code and it's not working
async def verify(ctx):
user = ctx.message.author
role = 'Member' #change the role here
try:
await user.add_roles(discord.utils.get(user.guild.roles, name=role))
await ctx.send('Welcome to our server! :white_check_mark:', delete_after=1)
except Exception as e:
await ctx.send('Cannot assign role. Error: ' + str(e))
if not msg.content == '/verify':
await client.delete_message(msg)
await ctx.message.delete()
any help would be much appreciated.
You can just write a simple check right at the beginning of the function.
For example,
#bot.command()
async def verify(ctx):
if ctx.channel.name != "verify":
return
# rest of the code
Also, you have not defined msg in your code. So that'll also raise an error
You have to specify what exactly your "msg" is that you want to delete.
So instead of msg.delete it should be enough to instead write:
if ctx.message.content == "verify":
await ctx.message.delete
Because the ctx/context is where you get the information about what kind of message it is, which channel it was posted in and so on.

How to receive and send message to specific channel in Discord.py?

Yesterday I was working on something simple where a bot on command of !name Barty would print back Hello Barty
#bot.command()
async def name(ctx, args):
await ctx.send("hello {}".format(args)
However the problem I am facing at this moment is that the bot would response to any channel where I do use the !name XXXX and what I am trying to do is that I want only to react to given specific channel in discord.
I tried to do:
#bot.event
async def on_message(message):
if message.channel.id == 1234567:
#bot.command()
async def name(ctx, args):
await ctx.send("hello {}".format(args)
but that was completely not working and I am out of ideas and here I am.
How can I send command to a given specific channel and get back response from there?
Move the define code out of the IF statement:
#bot.command()
async def name(ctx, args):
await ctx.send("hello {}".format(args)
When you've done that, you should be able to do;
if (message.channel.id == 'channel id'):
await message.channel.send('message goes here')
else:
# handle your else here, such as null, or log it to ur terminal
Could also check out the docs: https://discordpy.readthedocs.io
Once you make the command, make the IF statement inside of that.
message.channel.id now needs to be an integer, not a string so you don't need to use ''
if (message.channel.id == 1234567):
await message.channel.send('message goes here')
else:
# handle your else here, such as null, or log in to ur terminal

Categories

Resources