Reputation: 21
A server owner on discord asked me to Add a custom currency system to my bot for him (the bot is only on this server). To encourage activity we did not go with the dailies system and instead my idea was to have a message pop up every 7min with an image and users have to add a "Reaction" to the image. To make it easy and control the inputs i want to add a reaction to my image so users can just click the reaction and it will add the amount.
With all that context out of the way, here is the problem as a background task. I have no clue how to pass context to the reaction!
async def my_background_task():
await bot.wait_until_ready()
counter = 0
channel = discord.Object(id='446782521070321664')
while not bot.is_closed:
counter += 1
with open('vbuck.png', 'rb') as f:
await bot.send_file(channel, f) #sends a png of a vbuck
await bot.add_reaction(discord.message,'<:vbuck:441740047897591809>') #This is the Reaction part
await asyncio.sleep(420) # task runs every 7 min seconds
bot.loop.create_task(my_background_task())
If you could give me advice that would be great and if you are feeling extra generous Code + explanation would be appreciated I am learning python from this project.
Upvotes: 2
Views: 5354
Reputation: 60974
You need to save the Message
object that send_file
returns (the message that was sent). Then you can use that Message
object in Client.wait_for_reaction
to wait for a reaction.
async def task():
await bot.wait_until_ready()
channel = discord.Object(id='446782521070321664')
vbuck = discord.utils.get(bot.get_all_emojis(), name='vbuck')
check = lambda reaction, user: user != bot.user
while not bot.is_closed:
msg = await bot.send_file(channel, 'vbuck.png') #sends a png of a vbuck
await bot.add_reaction(msg, vbuck)
for _ in range(7*60):
res = await bot.wait_for_reaction(message=msg, emoji=vbuck, check=check, timeout=1)
if res:
# res.user reacted to the message
Upvotes: 1
Reputation: 1187
If I understood the question correctly, you want to actually wait for users to react to the file you posted and then award them on that reaction. I'm gonna assume you are using discord.py version 1.0 or higher.
The background task itself can not, as far as I know, be handed any context - because it isn't invoked like a comment in a specific context. However, the API (https://discordpy.readthedocs.io/en/rewrite/api.html#discord.on_reaction_add) states that there is a listener to reactions on messages, which means you can simply use
@bot.event
async def on_reaction_add(reaction, user):
#here do some checks on reaction.message and to check that it is actually
#the correct message being reacted too and avoid multiple reactions of one user.
The API will also tell you what kind of checks you can do on the message. You could give the message a certain signature when you let the bot post it (a timestamp like time.time()
seems good enough) and then access reaction.message.content
and compare it to the current time. To do that, I would modify your background task to something like this:
async def my_background_task():
await bot.wait_until_ready()
counter = 0
channel = bot.get_channel(id='446782521070321664')
while not bot.is_closed:
counter += 1
mess = "maybe a timestamp"
e = discord.Embed()
e.set_image(url = "some cool image maybe randomly chosen, please no vbucks")
await channel.send(mess, embed = e) #sends a message with embed picture
await asyncio.sleep(420) # task runs every 7 min
the message content will then simply be message
.
Hope this helps.
Upvotes: 0