0
votes

I am working on an advanced Discord Bot. A couple of functionalities work through cron jobs. A new feature I am working on requires the bot to get a collection of users that reacted to a specific message with a specific emoji. Based on that the users will get a temporal role (which most likely possesses the same kind of issue since the documentation for it is identical to the current issue).

I have every data required in order to pull the specific message and possibly it's contents, I however don't know how to access it through cron.

I have the discord server ID, discord channel ID, discord message ID and the emoji snowflake. So theoretically I should be able to access all its contents through the API. However, I noticed that most functionalities are through cached data, and only when an event happens.

A similar cron job that it does is sending a daily overview to a specific channel where it is enabled. client.channels.get([channel id]).send([formatted data]);

With this functionality, I would however need to get a message and either a collection of all the users that reacted with (ideally) the emoji snowflake.

It has to be through the cron, using a discord command for this is a no go as automation is the key. It should also work without any cached data (where the real issue is). Once again, I have all the data required to pull the message and find the emoji based on snowflake, I just don't know how to do it through cron. The bot also has all the required permissions on the servers that it operates on.

Any pointers or solutions would be appreciated.

The current code in the cronjob:

    (async () => {
        // walk through channels in DB
        var channels = await query([query]);
        for (var i = 0; i < channels.length; i++) {
            var serv_channel_id = channels[i].server_channel_id;
            var disc_channel_id = channels[i].discord_channel_id;
            var disc_server_id = channels[i].discord_server_id;
            
            // walk through messages in DB
            var messages = await query([query]);
            for (var j = 0; j < messages.length; j++) {
                var serv_message_id = messages[i].server_message_id;
                var disc_message_id = messages[i].discord_message_id;

                // walk through reactions in DB
                var reactions = await query([query]);
                for (var k = 0; k < reactions.legnth; k++) {
                    var serv_reaction_id = reactions[i].server_react_id;
                    var r_to_give = reactions[i].role_to_give;

                    // get discord list of users that reacted with emoji
                    // check per user if they have the role, if they dont then assign role
                }
            }
        }
    })();

Working is currently more important than efficiency. I have left out the queries for obvious reasons and they are not necessary information for this question.

1

1 Answers

0
votes

Through raw events I was able to solve this issue.

My old code had been completely removed and therefor can be ignored as reference material.

Instead I delved into an area of the API that I have not seen before; Raw Events.

If you want to know more about it I highly suggest reading into it starting here: https://anidiots.guide/coding-guides/raw-events

The basic code used in order to reach what I wanted

client.on('raw', packet => {
    (async () => {
        // We don't want this to run on unrelated packets
        if (!['MESSAGE_REACTION_ADD', 'MESSAGE_REACTION_REMOVE'].includes(packet.t)) return;

        // Grab the channel to check the message from
        const channel = client.channels.get(packet.d.channel_id);

        // make sure channel id is in DB otherwise no need to listen
        const check_channel = await query([query]);
        if (!Array.isArray(check_channel) || !check_channel.length) return;

        // make sure the message is in the DB otherwise no need to listen
        const check_message = await query([query]);
        if (!Array.isArray(check_message) || !check_message.length) return;

        channel.fetchMessage(packet.d.message_id).then(message => {
            (async () => {
                // Emojis can have identifiers of name:id format, so we have to account for that case as well
                const emoji = packet.d.emoji.id ? `${packet.d.emoji.name}:${packet.d.emoji.id}` : packet.d.emoji.name;

                // make sure emoji id is in db
                const check_reaction = await query([query]);
                if (!Array.isArray(check_reaction) || !check_reaction.length) return;

                // add and track user
                if (packet.t === 'MESSAGE_REACTION_ADD') {
                    await query([query]);
                }

                // remove user from tracking
                if (packet.t === 'MESSAGE_REACTION_REMOVE') {
                    await query([query]);
                }
            })();
        });
    })();
});

The code is not perfect or clean but it serves as a basic start for those stuck on a similar issue. For my particular issue this was the solution.