-1

I want to make it so that when a command is activated, a bot will send a message in a channel specifying a certain emoji. The message it sends will delete if, either 15 seconds have passed, or someone reacted with the correct emoji. The correct emoji is a custom emoji. The bot will also react to the message with the emoji as soon as it is sent so users can just click on the reaction.

If nobody reacts in time, the message will just delete. But if somebody reacts, then the message will delete and the bot will send a new message in the same channel shouting out who reacted to the message first. What I need help with is how to make the bot detect who reacted to a message and how to make it react to its own message as soon as the message is sent.

buttonmsg = await channel.send("**Button: :greenbutton:**", delete_after=float(15))
            emoji = get(message.server.emojis, name="custom_emoji")
            reaction = await client.wait_for_reaction(emoji, buttonmsg)
            redeemedby = #user that reacted with the correct emoji first
            await channel.send(f"Button redeemed by {redeemedby}")
            await adminchannel.send(f"**Button redeemed by {redeemedby}**")

How would I do this?

Edit: New Code

global buttonExpected
global buttonUserId
global buttonMsgId
global buttonStage
buttonExpected = "none"
buttonUserId = 0
buttonMsgId = 0
buttonStage = 0

@client.event
async def on_raw_reaction_add(payload):
    global buttonExpected
    global buttonUserId
    global buttonMsgId
    global buttonStage
    print("Reaction detected")
    print(f"payload.user_id: {str(payload.user_id)}")
    print(f"payload.message_id: {str(payload.message_id)}")
    print(f"payload.emoji.name: {str(payload.emoji.name)}")
    print(f"payload.emoji.id: {str(payload.emoji.id)}")
    guild = discord.utils.find(lambda g: g.id == payload.guild_id, client.guilds)

    if payload.emoji.id == 1123299037236433027 and payload.message_id == buttonMsgId and buttonExpected == "green":
      print("Green Button Detected")
      buttonUserId = payload.user_id
      buttonStage = 2

# In the on_message event:

if floodfrightbuttons_button == "normal":
  global buttonStage
  global buttonUserId
  global buttonMsgId
  global buttonExpected
  buttonStage = 1
  buttonmsg = await floodfrightbuttons_channel.send("**Button:** <:greenbutton:1123299037236433027>")
  buttonExpected = "green"
  buttonMsgId = buttonmsg.id
  def reaction_ready():
    if buttonStage == 2:
      return True
    return False
  wait(lambda: reaction_ready(), timeout_seconds=floodfrightbuttons_deletetime, waiting_for="reaction")
  print("Reaction received")
  await floodfrightbuttons_channel.send(f"Button redeemed by <@{buttonUserId}>")
  await floodfrightbuttons_bothubchannel.send(f"Button redeemed by <@{buttonUserId}>")

New Code Output:

Traceback (most recent call last):
File " /home/runner/Bot-Yozy/venv/lib/pytho n3.8/site-packages/discord/client.py", line 441, in run_event
await coro( *args, **kwargs)
File "main.py", , line 589, in on _message
print( "Reaction received" )
File "/home/runner/Bot-Yozy/venv/lib/pytho n3.8/site-packages/waiting/__ init__•py":
•Tin
e 18, in wait
for × in iterwait(result=result, *args,
**kwargs) :
File "/home/runner/Bot-Yozy/venv/lib/pytho n3.8/site-packages/waiting/ init_ _•py", lin e 56, in iterwait
raise TimeoutExpired(timeout_seconds, wa iting_for)
waiting. exceptions.TimeoutExpired: Timeout o f 12 seconds expired waiting for reaction
2023-06-29 14:44:20,192 - discord.client - I
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Yozy Opto
  • 23
  • 5

2 Answers2

0

You could go by creating another bot event like this:

@bot.event
async def on_raw_reaction_add(payload):
    # Check if the bot's message was reacted to with the custom emoji
    if payload.emoji.name == "custom_emoji" and payload.user_id != bot.user.id:
        channel = bot.get_channel(payload.channel_id)
        message = await channel.fetch_message(payload.message_id)

        # Send a new message mentioning the user who reacted to the bot's message
        await channel.send(f"Button redeemed by <@{payload.user_id}>")

This should solve your problem.

If you have another bot event already running, do not add my @bot.event, simply add everything below.

Hope I could help you!

Oh, and to get the bot to reply to itself, do

message = channel.send("TEXT")
message.reply("You reacted", ephemeral=True)

Ephemeral makes the reply basically only visible to the one who reacted.

Karo
  • 107
  • 8
0

This is easy to achieve through wait_for method, and you don't need to add delete_after in your context.send since wait_for can handle all of it.

buttonmsg = await channel.send("**Button: :greenbutton:**")

# check the emoji that added to bot's message
def check(reaction, user):
  return str(reaction.emoji) == 'custom_emoji'  # replace custom_emoji by your own

try:
  reaction, user = await client.wait_for('reaction_add', timeout=15.0, check=check)
except asyncio.TimeoutError:
  await buttonmsg.delete()
else:  # if check returns True
  await channel.send(f"Button redeemed by {user.name}")  # you can add user.id or whatever in your message
  await adminchannel.send(f"**Button redeemed by {user.name}**")

To get the format of your custom emoji, you could check about this StackOverflow post
P.S: wait_for_reaction is changed to wait_for after migrating to v1.0. I don't know what version you are using but make sure to change it for future usages. Changelog

TimG233
  • 535
  • 2
  • 12
  • It says asyncio is undefined – Yozy Opto Jun 28 '23 at 03:01
  • @YozyOpto then `import asyncio`, it is a built-in now, you don't need to pip install it – TimG233 Jun 28 '23 at 03:10
  • Alr, and how would I get the bot to react to its own message with the same emoji? (So users can just tap the emoji instead of having to add it as a reaction) – Yozy Opto Jun 28 '23 at 15:55
  • Also the code doesn't seem to do anything when I add the reaction anyway – Yozy Opto Jun 28 '23 at 15:58
  • @YozyOpto Does it show any error in the terminal? And can you show me the code snippet of your implementation (for the command) – TimG233 Jun 29 '23 at 00:45
  • Edited the post with them – Yozy Opto Jun 29 '23 at 14:46
  • So do you have an answer? – Yozy Opto Jul 03 '23 at 02:31
  • @YozyOpto I don't suggest using so many global variables in your code, which you could possibly replace them by `bot.var`. Also, I don't think you need to use `on_raw_reaction_add` event to check about this since that's too much. I think my above code should be enough for the job. And if you find out the reaction that you added will not trigger bot's further action, please double check you correctly replace and format `custom_emoji` with your custom emoji – TimG233 Jul 03 '23 at 02:55
  • Your above code wouldn't do anything for me. I felt safer using on_raw_reaction_add because it already successfully detected the reaction and which emoji the reaction was. I'm just having trouble getting it to react based on that. Also what is bot.var? – Yozy Opto Jul 03 '23 at 14:48
  • Tried your code and it didn't work – Yozy Opto Jul 03 '23 at 22:09
  • @YozyOpto you can send me your attempt (code snippet) and then I can see why it doesn't work – TimG233 Jul 04 '23 at 00:56
  • I ended up just doing everything in on_raw_reaction_add and it works – Yozy Opto Jul 04 '23 at 00:57