revoltchat / revolt.js

Modern Typescript library for interacting with Revolt.
https://revolt.js.org
MIT License
216 stars 54 forks source link

bug: When fetching a member by user id from a server guild: the returned Member does not have a user property. #63

Closed BoQsc closed 1 year ago

BoQsc commented 1 year ago

What happened?

Clarifications

Notice: username and nickname are not the same thing. nickname is related to the server/guild member. username is related to the revolt instance user.

Affected

Edit: Happens with invited bots that are second, third, fourth on the Guild/Server. First invited bot on the server/guild does not have such issue.

I'm trying to get the username of a member on the server/guild.

For fetching a member I use .fetchMember

.user property/accessor is missing when fetching a member from a server using a user id.

Returned member object. (missing user: property/accessor )

    _id: [object Object]
    nickname: boqsc
    avatar: null
    roles: 01GK52Z15W78JM1WQ1NK7MMZCW
    timeout: null
    joined_at: Wed Nov 30 2022 12:52:54 GMT+0200 (Eastern European Standard Time)

Example:

client.on("packet", async (event) => {
    if ((event.type == "MessageReact" || event.type == "MessageUnreact") && (event.user_id != client.user._id)){
        console.log("Red reaction.");

        client.servers.forEach(async (values, keys, objects) => {
            if (values.channel_ids.includes(event.channel_id) ){
                guild = await client.servers.get(values._id);
                guild_member = await guild.fetchMember(event.user_id);
                for (const [key, value] of Object.entries(guild_member)) {
                                  console.log(`    ${key}: ${value}`);
                }

                console.log(`  Guild Name:  ${guild.name}`);

                console.log(`  Guild_Member Id: ${guild_member._id.user}`);
                console.log(`  Guild_Member Nickname: ${guild_member.nickname}`);
                console.log(`  Guild_Member Joined at: ${guild_member.joined_at}`);
                console.log(`  Guild_Member Roles: ${guild_member.roles}`);
                console.log(`  Guild_Member User: ${guild_member.user.username}`);
                for (const [key, value] of Object.entries(guild_member)) {
                                  console.log(`    ${key}: ${value}`);
                }
            }
        });

    }

});

Example output:

Red reaction.
    client: [object Object]
    _id: [object Object]
    nickname: boqsc
    avatar: null
    roles: 01GK52Z15W78JM1WQ1NK7MMZCW
    timeout: null
    joined_at: Wed Nov 30 2022 12:52:54 GMT+0200 (Eastern European Standard Time)
  Guild Name:  Colors Server
  Guild_Member Id: 01GHZS22KV2CPEVGGVC3HSQYFZ
  Guild_Member Nickname: boqsc
  Guild_Member Joined at: Wed Nov 30 2022 12:52:54 GMT+0200 (Eastern European Standard Time)
  Guild_Member Roles: 01GK52Z15W78JM1WQ1NK7MMZCW
(node:454029) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'username' of undefined
    at /root/bot.js:57:59
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
BoQsc commented 1 year ago

As you can see in the example output

(node:454029) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'username' of undefined

username property is undefined.

BoQsc commented 1 year ago

Turns out to be very easy to reproduce. I've tested this example with 4 bots and three separate servers, out of which one was completely new. It happens to be that only the first invited bot is the only one capable of returning. guild_member.user.username and the whole guild_member.user object.

const { Client } = require("revolt.js");
let client = new Client();

console.info(`Welcome to a Basic Reaction Roles Bot.`);
console.info(`Revolt Library version: ${require("revolt.js").LIBRARY_VERSION}!`);
console.info(`_______________________________`);

let chat_message_reply;

client.on("message", async (message) => {

    if (message.content === "lets create reactions") {
        chat_message_reply = await message.channel.sendMessage("Select roles: ");
        try {
            console.log("Adding reactions to the message.");
            await chat_message_reply.react("01GK50B414WGS9M82668EZWMSX");
            await chat_message_reply.react("01GK50BBW5FP8PZSYTHYCJCG3W");
            await chat_message_reply.react("01GK50BH980WRKX5ATEETZMWZK");
            await chat_message_reply.react("01GK50BQA59VF31A04ERDTNPMG");
            await chat_message_reply.react("01GK50BYNR1PY1G479KCBA2QPR");
            console.log("Added reactions to the message sucessfully.");
        } catch (e) {
            if (e.response.status == 403){
                console.log(`An error response from the Revolt Server while trying to react to a message.`);
                console.log(`  ${e.response.status}: ${e.response.statusText}`);
                chat_message_reply.edit({
                    content: `Bot has no **Use Reactions** permission in the  **${message.channel.server.name}** Guild.`

                });

                console.log(`    Please add "Use Reactions" permission to the Bot "${client.user.username}" in the Guild "${message.channel.server.name}". `);

            }
        }

    }

});

client.on("packet", async (event) => {
    if ((event.type == "MessageReact" || event.type == "MessageUnreact") && (event.user_id != client.user._id)){
        console.log("Red reaction.");

        client.servers.forEach(async (values, keys, objects) => {
            if (values.channel_ids.includes(event.channel_id) ){
                guild = await client.servers.get(values._id);
                guild_member = await guild.fetchMember(event.user_id);

                for (const [key, value] of Object.entries(guild_member)) {
                                  console.log(`    ${key}: ${value}`);
                }

                console.log(`  Guild Name:  ${guild.name}`);

                console.log(`  Guild_Member Id: ${guild_member._id.user}`);
                console.log(`  Guild_Member Nickname: ${guild_member.nickname}`);
                console.log(`  Guild_Member Joined at: ${guild_member.joined_at}`);
                console.log(`  Guild_Member Roles: ${guild_member.roles}`);
                console.log(`  Guild_Member User: ${guild_member.user.username}`);
                console.log(`  Guild_Member User: ${guild_member.user}`);
                    //console.log({ members: [guild_member]}); 

            /*
            console.log(await new Promise(function(){

                    return  { 
                                members: [guild_member],
                                users: ["happysuer"]

                        };
            }
                    ));

                    console.log("endreached");*/

            }
        });

    }

});

client.on("ready", async () => {
    client.users.edit({
        status: {
            text: "Listening to you.",
            presence: "Idle",
        },
    });

});

var fs = require('fs');
client.loginBot(fs.readFileSync('./token.txt','utf8'));
BoQsc commented 1 year ago

So yeah, this whole issue seems to be only about invited bots that are second or third or fourth... in the server.

BoQsc commented 1 year ago

Temporary untested workaround for other bot developers: There is a chance that it is possible to do a workaround by fetching all members of the server/guild and selecting the user object.

https://revolt.js.org/classes/maps_Servers.Server.html#fetchMembers

Again, haven't tried that. Might not work as well.

insertish commented 1 year ago

The library is designed around the client so this is sort of intended behavior, users aren't fetched automatically with members. I am working towards figuring this out in the near future.