Discord bot reading reactions

Em Ae picture Em Ae · Aug 8, 2018 · Viewed 9.1k times · Source

I need to implement some of the feature and one of the feature is implementing polls type feature. Can't use public discord bots due to some policies so we have to implement something on my own. Did some research yesterday and was able to make basic bot using python3 and commands api from discord.ext. Now what i need to figure out is:

  1. Read reactions added by a user to a message?
  2. Create a message with reactions (like bots which create reaction polls?)
  3. Pin a message?
  4. I believe from ctx i can get user tags (admin etc). Is there a better way to do so?

Couldn't find anything helpful on Commands reference page or probably i am looking at wrong documentation. any help would be appreciated.

thanks


Updated: Thanks guys. now i am stuck at how to add emoji, here is my code

poll_emojis = {0: ':zero:', 1: ':one:', 2: ':two:', 3: ':three:', 4: ':four:'}

@client.event
async def on_message(message):
    if message.author == client.user:
        return

    if message.content.startswith('$create_poll'):

        poll_content = message.content.split('"')
        poll_text = poll_content[1]
        poll_options = []
        poll_option_text = ''
        count = 0
        for poll_option in poll_content[2:]:
            if poll_option.strip() != '':
                poll_options.append(poll_option)
                poll_option_text += '{0}: {1}\t'.format(poll_emojis[count], poll_option)
                count += 1

        posted_message = await message.channel.send('**{0}**\n{1}'.format(poll_text, poll_option_text))

        count = 0
        for poll_option in poll_options:
            await posted_message.add_reaction(Emoji(poll_emojis[count]))
            count += 1

Answer

Patrick Haugh picture Patrick Haugh · Aug 8, 2018

As an aside, given you're starting this project, and are already using the rewrite documentation, make sure you're using the rewrite version. There are some questions on here about how to make sure, and how to get it if you're not, but it's better documented and easier to use. My answers below assume you are using

  1. Message.reactions is a list of Reactions. You could get a mapping of reactions to their counts with

    {react.emoji: react.count for react in message.reactions}
    
  2. You could react to the message immediately after posting it:

    @bot.command()
    async def poll(ctx, *, text):
        message = await ctx.send(text)
        for emoji in ('👍', '👎'):
            await message.add_reaction(emoji)
    
  3. You can use Message.pin: await message.pin()

I'm not sure what you mean by "user tags". Do you mean roles?

I would write your command as

@bot.command()
async def create_poll(ctx, text, *emojis: discord.Emoji):
    msg = await ctx.send(text)
    for emoji in emojis:
        await msg.add_reaction(emoji)

Note that this will only work for custom emoji, the ones you have added to your own server (This is because discord.py treats unicode emoji and custom emoji differently.) This would accept commands like

!create_poll "Vote in the Primary!" :obamaemoji: :hillaryemoji:

assuming those two emoji were on the server you send the command in.

With the new commands.Greedy converter, I would rewrite the above command like so:

@bot.command()
async def create_poll(ctx, emojis: Greedy[Emoji], *, text):
    msg = await ctx.send(text)
    for emoji in emojis:
        await msg.add_reaction(emoji)

So invocation would be a little more natural, without the quotes:

!create_poll :obamaemoji: :hillaryemoji: Vote in the Primary!