I want to send a list of users who reacted to my message but the list always shows empty - discord

I searched it up and saw someone do it like this but it always returns an empty list
#bot.command()
async def spinthewheel(ctx,msg:discord.Message=None):
guild=ctx.guild
if msg==None:
em=discord.Embed(title="SPIN THE WHEEL!!", description="React to this message with ⚡ to enter!",color=discord.Color.from_str('#ff00ff'))
msg=await ctx.send(embed=em)
await msg.add_reaction('⚡')
else:
await msg.add_reaction('⚡')
await ctx.send("Reaction has been added",delete_after=10)
await asyncio.sleep(5)
users = list()
for reaction in msg.reactions:
if reaction.emoji == '⚡':
async for user in reaction.users():
if user != bot.user:
users.append(user.name)
user_list="\n".join(user.name for user in users)
await ctx.send(f"users: {user_list}")
I tried using this one too but same results
users = [user async for user in reaction.users()]
Can you pls tell me how to fix this? Thanks <3

The issue is that msg.reactions is empty - this is because it's the message representation at the time it was created and hasn't been updated since with the reaction information. This is easily fixable with a:
msg = await msg.fetch()
This will fetch the message anew from the channel. Just put it after your asyncio.sleep and before you loop over the reactions.

Related

I cannot understand how to use this code in discord.py

It regards user imput, so like I was commissioned to do a prompt but I've never done this so like this is what i found online
playerChoice = await bot.wait_for('message', check=check(ctx.author), timeout=30)
I get some of it, but I don't get the 'message' part and the 'check = check'.
Here's my full code
#client.command()
async def event(ctx):
await ctx.send("Prompt will continue in DMs.")
embed = discord.Embed(title="Event Prompt", description="Please specify the type of event.")
embed.set_footer("Prompt will expire in ## seconds")
await ctx.author.send(embed=embed)
eventType = await bot.wait_for('message', check=check(ctx.author), timeout=30) # I want it to send the event type.
await ctx.send(eventType)
I'd like an explaination and a possible way to improve that and make it work. Thanks in advance
https://discordpy.readthedocs.io/en/stable/api.html?highlight=wait_for#discord.Client.wait_for
#client.event
async def on_message(message):
if message.content.startswith('$greet'):
channel = message.channel
await channel.send('Say hello!')
def check(m):
return m.content == 'hello' and m.channel == channel
msg = await client.wait_for('message', check=check)
await channel.send('Hello {.author}!'.format(msg))
await client.wait_for('message', check=check)
message refers to the event. You could have also do it for the event reaction_add, voice_state_update, etc.
So this means you are waiting for a message. The check defines what you are waiting for exactly. It is a method and returns a True or False.
In my case I am waiting for a message event which is posted in the same channel and has the message content "hello".
If you didn't have such check it would pick up a message that might have been send by a different author, in a different channel, in a different guild.

I want a discord bot send a dm to somebody by their id

if (message.content === "!test"){
client.users.cache.get('id').send('message');
console.log("message sent")
}
This method doesn't work and I wasn't able to find any other methods that worked
Is there a spelling mistake or this method is outdated?
I've actually encountered this error myself once. There are two problems you might be facing here:
The user isn't cached by discord.js yet
There isn't a DMChannel open for that user yet
To solve the first one, you have to fetch the user before doing anything with it. Remember this is a Promise, so you'll have to either await for it to complete or use .then(...).
const user = await client.users.fetch('id')
Once you've fetched your user by their ID, you can then create a DMChannel which, again, returns a promise.
const dmChannel = await user.createDM()
You can then use your channel like you normally would
dmChannel.send('Hello!')
Try to create a variable like this:
var user = client.users.cache.find(user => user.id === 'USER-ID')
And then do this:
user.send('your message')

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")

Wait for Message on_member_join using checks (discord.py) | SOLVED

I want to wait for a private message that was sent only by the member. I am trying to use the check parameter for the client.wait_for() method but I can not seem to get it. I tried putting the check as the response.author but will not work since I just assigned response. Also I am executing this when a member joins using on_member_join which takes in a member argument (like this async def on_member_join(member). Anyone know how to properly do this? Any answers would be greatly appreciated!
Here is the code for this:
await member.send('What is your student number? ')
response = await client.wait_for('message')
student_number = response.content
When adding a check function to wait_for, that check function will get the received message as an argument. This means that it will check every single message the bot gets, pass all of them to your check function, and wait until one of them makes the check return True.
#client.event()
async def on_member_join(member):
def check(message):
return message.author.id == member.id and message.guild is None
await member.send('What is your student number?')
response = await client.wait_for('message', check=check)
student_number = response.content
Note how my example also makes sure the guild is None, as you explicitly mentioned waiting for a private message.

Trouble with bot.wait_for() Discord.py

So modern documentation on the bot.wait_for() coroutine is not super detailed, and I'm having trouble getting it to work with reactions. Would appreciate feedback.
Python 3 with Discord.py
## Test Role Add
#kelutralBot.command(name='testreaction')
async def testReaction(ctx):
member = ctx.message.author
message = await ctx.send("This is a test message.")
emojis = ['\u2642','\u2640','\u2716']
for emoji in emojis:
await message.add_reaction(emoji)
def check(reaction, user):
return user == message.author and str(reaction.emoji) == '\u2642'
try:
reaction, user = await kelutral.wait_for('reaction_add', timeout=60.0, check=check)
except asyncio.TimeoutError:
await ctx.send("Window has passed to self-assign pronouns. Please DM a mod if you would still like to do so.")
else:
print(reaction)
male = get(member.guild.roles, name="He/Him")
await member.add_roles(male)
print("Assigned " + member.name + " He/Him pronouns.")
Two things were wrong.
First, don't use Client and Bot in the same command. Bot is sufficient for both.
Second, Unicode Emoji for Discord are treated as '\U000#####', which was the biggest problem.
Once we solved that, everything worked as intended.
The problem here is that you are checking if the person who sent the reaction is the author of the message that contains the message, which is only satisfied by the bot that reacted. Also consider using a role ID instead (server settings > roles > left click role > right click role > copy ID). You also want to be consistent with kelutral or kelutral Bot throughout the command.
#kelutralBot.command(name='testreaction')
async def testReaction(ctx):
member = ctx.message.author
message = await ctx.send("This is a test message.")
emojis = ['\u2642','\u2640','\u2716']
for emoji in emojis:
await message.add_reaction(emoji)
def check(reaction, user):
return user == member and str(reaction.emoji) == '\u2642' # check against the member who sent the command, not the author of the message
try:
reaction, user = await kelutralBot.wait_for('reaction_add', timeout=60.0, check=check)
except asyncio.TimeoutError:
await ctx.send("Window has passed to self-assign pronouns. Please DM a mod if you would still like to do so.")
else:
print(reaction)
male = ctx.message.guild.get_role(ROLE_ID_GOES_HERE) # put your role ID here #
await member.add_roles(male)
print(f"Assigned {member.name} He/Him pronouns.")
Keep in mind your code only works for the "male" role, you have to implement a different check function to use it for everything.

Resources