Discord.py – User ID from message reaction dump to json file
Question:
I’m looking for a way to store all the user reactions from a message in a json file. I want the users who react with the "✅" to be stored in one json file and the users who react with "❌" to be stored in a separate json file.
This is the portion of the code I’m having trouble with:
for reactions in message.reactions:
if str(reactions) == "✅":
user_list = [user async for user in message.reactions.users() if user != client.user]
for user in user_list:
users = user.id + "n"
with open ("reaction_tick.json", "w") as f:
json.dump(users,f)
return True
for reactions in message.reactions:
if str(reactions) == "❌":
user_list = [user async for user in message.reactions.users() if user != client.user]
for user in user_list:
users = user.id + "n"
with open ("reaction_cross.json", "w") as f:
json.dump(users,f)
return True
How do I gather all the users’ ids and put them into a string then dump that into a json file?
So far, when I run all the code nothing happens and there are no error messages.
Any help would be greatly appreciated.
================================================================
Here is the rest of my code:
@client.event
async def on_member_join(member):
channel = client.get_channel(1003203232824307745)
embed=discord.Embed(title=f'{member.name}#{member.discriminator} has joined the server!', description="Will they stay or will they leave? Place your bets!", color=0xf1c40f, inline=True)
embed.add_field(name='Will they stay longer than 1 hour?', value=f'React stay ✅')
embed.add_field(name='Will they leave before 1 hour is up?', value=f'React leave ❌')
embed.add_field(name='Betting will close in:', value=f'5 minutes', inline=False)
embed.add_field(name='Results will be posted in', value=f'1 hour!', inline=True)
message = await channel.send(embed=embed)
await message.add_reaction('✅')
await message.add_reaction('❌')
time = 3600
id = member.id
while time >= 0:
if time <= 0:
embed.remove_field(index=3)
embed.insert_field_at(index=3, name='Betting complete! Results have been posted!', value=f'Ended at {datetime.datetime.now().strftime("%B %d, %I:%M %p")}', inline=False)
await message.edit(embed=embed)
await membercheck(id, channel)
await reactioncheck(message)
return
elif 1 <= time < 50:
embed.remove_field(index=3)
embed.insert_field_at(index=3, name='Results in:', value=f'{time:.1f} seconds', inline=False)
await message.edit(embed=embed)
time -= 10
await asyncio.sleep(10)
elif 60 == time:
embed.remove_field(index=3)
embed.insert_field_at(index=3, name='Results in:', value=f'{time/60:.1f} minute', inline=False)
await message.edit(embed=embed)
time -= 10
await asyncio.sleep(10)
elif 60 <= time < 3290:
embed.remove_field(index=3)
embed.insert_field_at(index=3, name='Results in:', value=f'{time/60:.1f} minutes', inline=False)
await message.edit(embed=embed)
time -= 10
await asyncio.sleep(10)
elif 3300 == time:
await reactioncheck(message) #This is the function that I was having trouble with above.
embed.remove_field(index=2)
embed.insert_field_at(index=2, name='Betting has closed:', value=f'Ended at {datetime.datetime.now().strftime("%B %d, %I:%M %p")}', inline=False)
await message.edit(embed=embed)
await message.clear_reactions()
time -= 10
await asyncio.sleep(10)
elif 3300 <= time < 3600:
await reactioncheck(message)
embed.remove_field(index=2)
embed.insert_field_at(index=2, name='Betting will close in:', value=f'{time/60 - 55:.1f} minutes', inline=False)
embed.remove_field(index=3)
embed.insert_field_at(index=3, name='Results in:', value=f'{time/60:.1f} minutes', inline=False)
await message.edit(embed=embed)
time -= 10
await asyncio.sleep(10)
async def reactioncheck(message):
rmsg = message #the message with reactions
for reaction in rmsg.reactions:
users = "" #the string to dump
if str(reaction) == "✅":
user_list = [user async for user in reaction.users() if user != client.user]
#it should be reaction.users() and not <message>.reactions.users()
for user in user_list:
users = users + str(user.id) + "n" #converting ID to str and adding instead of overwriting
with open("reaction_tick.json", "w") as f:
json.dump(users, f)
return True
for reaction in rmsg.reactions:
if str(reaction) == "❌":
user_list = [user async for user in reaction.users() if user != client.user]
for user in user_list:
users = users + str(user.id) + "n"
with open("reaction_cross.json", "w") as f:
json.dump(users, f)
return True
I know there are many issues with this and I know I should create other helper functions in order to condense this mess. The general gist of what I’m trying to achieve is that upon a new member joining my server, my bot will send an embed to a designated channel. The embed has a timer that constantly updates until that timer is finished. There are 2 timers on the embed – the first lasts 5 minutes and the second lasts 1 hour. When the first timer finishes, I want my bot to store the names of the people who have reacted to the embed and then clear the reactions from the embed. After the second timer is finished, the embed will send the names of the people who reacted with the ✅ and ❌ emojis. Basically people are betting on whether new members will stay or leave the server within the given hour.
Answers:
You made a silly mistake in the line used to create user_list
. It’s reaction.users()
, not <message>.reactions.users()
. You are trying to call a function users()
of a list
object which does not exist (a list
obviously doesn’t have a .users()
function). In other words, you are trying to use users()
on the wrong object. message.reactions
is a list (it returns a List[Reaction]
). You are trying to run list.users()
, which is invalid.
I’ve corrected the code:
for reaction in message.reactions:
if str(reaction) == "✅":
user_list = [user async for user in reaction.users() if user != client.user]
#it should be reaction.users() and not <message>.reactions.users()
for user in user_list:
users = users + str(user.id) + "n" #converting ID to str and adding instead of overwriting
with open ("reaction_tick.json", "w") as f:
json.dump(users,f)
return True
for reaction in message.reactions:
if str(reaction) == "❌":
user_list = [user async for user in reaction.users() if user != client.user]
for user in user_list:
users = users + str(user.id) + "n"
with open ("reaction_cross.json", "w") as f:
json.dump(users,f)
return True
Note that I’ve replaced reactions
with reaction
in the for
loops (so that I don’t make mistakes). You can correct them back if you want; just make sure you correct them in other places too.
Here is an example of how to use this code:
from discord.ext import commands
import discord.utils
import json
intent = discord.Intents(messages=True, message_content=True, guilds=True)
bot = commands.Bot(command_prefix="", description="", intents=intent)
@bot.event
async def on_ready(): #When the bot comes online
print("It's online.")
@bot.command(name="gr")
async def gr(message, msg):
if msg == "message":
rmsg = None #the message with reactions
async for msg in message.channel.history(limit=200):
if msg.content == "message":
rmsg = msg
for reaction in rmsg.reactions:
users = "" #the string to dump
if str(reaction) == "✅":
user_list = [user async for user in reaction.users() if user != bot.user]
#it should be reaction.users() and not <message>.reactions.users()
for user in user_list:
users = users + str(user.id) + "n" #converting ID to str and adding instead of overwriting
with open("reaction_tick.json", "w") as f:
json.dump(users, f)
return True
for reaction in rmsg.reactions:
if str(reaction) == "❌":
user_list = [user async for user in reaction.users() if user != bot.user]
for user in user_list:
users = users + str(user.id) + "n"
with open("reaction_cross.json", "w") as f:
json.dump(users, f)
return True
bot.run(<token>)
You can send a message on Discord (manually) and react to it with the emojis (for testing). Replace "message"
s with the content
of the message which you sent manually. rmsg
is the message (to which you also reacted manually). users
is the str
ing that’s going to be dumped as a JSON. Also, I’ve replaced users = user.id + "n"
with users = users + str(user.id) + "n"
. Your code overwrites users
every time in the for
loop. Also, you can’t concatenate a str
ing (users
in my case) with an int
eger (user.id
).
Do you not get any errors or exceptions? Because I got many.
I’m looking for a way to store all the user reactions from a message in a json file. I want the users who react with the "✅" to be stored in one json file and the users who react with "❌" to be stored in a separate json file.
This is the portion of the code I’m having trouble with:
for reactions in message.reactions:
if str(reactions) == "✅":
user_list = [user async for user in message.reactions.users() if user != client.user]
for user in user_list:
users = user.id + "n"
with open ("reaction_tick.json", "w") as f:
json.dump(users,f)
return True
for reactions in message.reactions:
if str(reactions) == "❌":
user_list = [user async for user in message.reactions.users() if user != client.user]
for user in user_list:
users = user.id + "n"
with open ("reaction_cross.json", "w") as f:
json.dump(users,f)
return True
How do I gather all the users’ ids and put them into a string then dump that into a json file?
So far, when I run all the code nothing happens and there are no error messages.
Any help would be greatly appreciated.
================================================================
Here is the rest of my code:
@client.event
async def on_member_join(member):
channel = client.get_channel(1003203232824307745)
embed=discord.Embed(title=f'{member.name}#{member.discriminator} has joined the server!', description="Will they stay or will they leave? Place your bets!", color=0xf1c40f, inline=True)
embed.add_field(name='Will they stay longer than 1 hour?', value=f'React stay ✅')
embed.add_field(name='Will they leave before 1 hour is up?', value=f'React leave ❌')
embed.add_field(name='Betting will close in:', value=f'5 minutes', inline=False)
embed.add_field(name='Results will be posted in', value=f'1 hour!', inline=True)
message = await channel.send(embed=embed)
await message.add_reaction('✅')
await message.add_reaction('❌')
time = 3600
id = member.id
while time >= 0:
if time <= 0:
embed.remove_field(index=3)
embed.insert_field_at(index=3, name='Betting complete! Results have been posted!', value=f'Ended at {datetime.datetime.now().strftime("%B %d, %I:%M %p")}', inline=False)
await message.edit(embed=embed)
await membercheck(id, channel)
await reactioncheck(message)
return
elif 1 <= time < 50:
embed.remove_field(index=3)
embed.insert_field_at(index=3, name='Results in:', value=f'{time:.1f} seconds', inline=False)
await message.edit(embed=embed)
time -= 10
await asyncio.sleep(10)
elif 60 == time:
embed.remove_field(index=3)
embed.insert_field_at(index=3, name='Results in:', value=f'{time/60:.1f} minute', inline=False)
await message.edit(embed=embed)
time -= 10
await asyncio.sleep(10)
elif 60 <= time < 3290:
embed.remove_field(index=3)
embed.insert_field_at(index=3, name='Results in:', value=f'{time/60:.1f} minutes', inline=False)
await message.edit(embed=embed)
time -= 10
await asyncio.sleep(10)
elif 3300 == time:
await reactioncheck(message) #This is the function that I was having trouble with above.
embed.remove_field(index=2)
embed.insert_field_at(index=2, name='Betting has closed:', value=f'Ended at {datetime.datetime.now().strftime("%B %d, %I:%M %p")}', inline=False)
await message.edit(embed=embed)
await message.clear_reactions()
time -= 10
await asyncio.sleep(10)
elif 3300 <= time < 3600:
await reactioncheck(message)
embed.remove_field(index=2)
embed.insert_field_at(index=2, name='Betting will close in:', value=f'{time/60 - 55:.1f} minutes', inline=False)
embed.remove_field(index=3)
embed.insert_field_at(index=3, name='Results in:', value=f'{time/60:.1f} minutes', inline=False)
await message.edit(embed=embed)
time -= 10
await asyncio.sleep(10)
async def reactioncheck(message):
rmsg = message #the message with reactions
for reaction in rmsg.reactions:
users = "" #the string to dump
if str(reaction) == "✅":
user_list = [user async for user in reaction.users() if user != client.user]
#it should be reaction.users() and not <message>.reactions.users()
for user in user_list:
users = users + str(user.id) + "n" #converting ID to str and adding instead of overwriting
with open("reaction_tick.json", "w") as f:
json.dump(users, f)
return True
for reaction in rmsg.reactions:
if str(reaction) == "❌":
user_list = [user async for user in reaction.users() if user != client.user]
for user in user_list:
users = users + str(user.id) + "n"
with open("reaction_cross.json", "w") as f:
json.dump(users, f)
return True
I know there are many issues with this and I know I should create other helper functions in order to condense this mess. The general gist of what I’m trying to achieve is that upon a new member joining my server, my bot will send an embed to a designated channel. The embed has a timer that constantly updates until that timer is finished. There are 2 timers on the embed – the first lasts 5 minutes and the second lasts 1 hour. When the first timer finishes, I want my bot to store the names of the people who have reacted to the embed and then clear the reactions from the embed. After the second timer is finished, the embed will send the names of the people who reacted with the ✅ and ❌ emojis. Basically people are betting on whether new members will stay or leave the server within the given hour.
You made a silly mistake in the line used to create user_list
. It’s reaction.users()
, not <message>.reactions.users()
. You are trying to call a function users()
of a list
object which does not exist (a list
obviously doesn’t have a .users()
function). In other words, you are trying to use users()
on the wrong object. message.reactions
is a list (it returns a List[Reaction]
). You are trying to run list.users()
, which is invalid.
I’ve corrected the code:
for reaction in message.reactions:
if str(reaction) == "✅":
user_list = [user async for user in reaction.users() if user != client.user]
#it should be reaction.users() and not <message>.reactions.users()
for user in user_list:
users = users + str(user.id) + "n" #converting ID to str and adding instead of overwriting
with open ("reaction_tick.json", "w") as f:
json.dump(users,f)
return True
for reaction in message.reactions:
if str(reaction) == "❌":
user_list = [user async for user in reaction.users() if user != client.user]
for user in user_list:
users = users + str(user.id) + "n"
with open ("reaction_cross.json", "w") as f:
json.dump(users,f)
return True
Note that I’ve replaced reactions
with reaction
in the for
loops (so that I don’t make mistakes). You can correct them back if you want; just make sure you correct them in other places too.
Here is an example of how to use this code:
from discord.ext import commands
import discord.utils
import json
intent = discord.Intents(messages=True, message_content=True, guilds=True)
bot = commands.Bot(command_prefix="", description="", intents=intent)
@bot.event
async def on_ready(): #When the bot comes online
print("It's online.")
@bot.command(name="gr")
async def gr(message, msg):
if msg == "message":
rmsg = None #the message with reactions
async for msg in message.channel.history(limit=200):
if msg.content == "message":
rmsg = msg
for reaction in rmsg.reactions:
users = "" #the string to dump
if str(reaction) == "✅":
user_list = [user async for user in reaction.users() if user != bot.user]
#it should be reaction.users() and not <message>.reactions.users()
for user in user_list:
users = users + str(user.id) + "n" #converting ID to str and adding instead of overwriting
with open("reaction_tick.json", "w") as f:
json.dump(users, f)
return True
for reaction in rmsg.reactions:
if str(reaction) == "❌":
user_list = [user async for user in reaction.users() if user != bot.user]
for user in user_list:
users = users + str(user.id) + "n"
with open("reaction_cross.json", "w") as f:
json.dump(users, f)
return True
bot.run(<token>)
You can send a message on Discord (manually) and react to it with the emojis (for testing). Replace "message"
s with the content
of the message which you sent manually. rmsg
is the message (to which you also reacted manually). users
is the str
ing that’s going to be dumped as a JSON. Also, I’ve replaced users = user.id + "n"
with users = users + str(user.id) + "n"
. Your code overwrites users
every time in the for
loop. Also, you can’t concatenate a str
ing (users
in my case) with an int
eger (user.id
).
Do you not get any errors or exceptions? Because I got many.