Search code examples
discorddiscord.js

Discord.js Slash Command: Displaying User Information Issues


I'm working on a Discord bot using Discord.js, and I've created a slash command to display user information. However, I'm facing some issues with the output of this command.

Problem 1: Server Member Since

The "Server Member Since" field is not displaying the correct join date for the user. Instead, it's showing "<t:NaN:R>". How can I fix this issue to correctly display when a user joined the server?

Problem 2: Roles Info

In the "Roles Info" section, I'm trying to display the roles a user has and their highest role. However, it's showing "No roles found" for all users, and "N/A" for the highest role. How can I correctly display the roles a user has and their highest role? I've added some debugging lines to check if the necessary data is available, but I'm not sure where the problem lies. Can someone please help me identify and resolve these issues with my code?

Thank you!

Here's the relevant code:

const { MessageEmbed, MessageActionRow, MessageButton } = require("discord.js");
const { format } = require("date-fns");
const { version } = require("../../package.json");
const pms = require("pretty-ms");

module.exports = {
  category: "Information",
  description: "Shows info based on input!",
  slash: true,

  testonly: true,   
  options: [
    {
      name: "user",
      description: "Shows information about the user mentioned",
      type: "SUB_COMMAND",
      options: [
        {
          name: "target",
          description: "The target user.",
          type: "USER",
          required: true,
        },
      ],
    },
    {
      name: "server",
      description: "Shows information about the server.",
      type: "SUB_COMMAND",
    },
    {
      name: "bot",
      description: "shows information about the bot.",
      type: "SUB_COMMAND",
    },
  ],
  async callback({ interaction, client }) {
    try {
      if (interaction.options.getSubcommand() === "user") {
        const target = interaction.options.getUser('target');

        var main = new MessageActionRow().addComponents(
          new MessageButton()
            .setLabel(`Main info`)
            .setEmoji(`ℹ`)
            .setCustomId(`main`)
            .setDisabled(true)
            .setStyle(`SECONDARY`),
          new MessageButton()
            .setLabel(`Roles info`)
            .setStyle(`DANGER`)
            .setEmoji(`ℹ`)
            .setCustomId(`roles`),
          new MessageButton()
            .setLabel(`Permissions`)
            .setStyle(`SECONDARY`)
            .setEmoji(`ℹ`)
            .setCustomId(`permissions`)
        );

        const Response = new MessageEmbed()
        .setAuthor({
          name: `${target.tag}`,
          iconURL: `${target.displayAvatarURL({ dynamic: true })}`,
        })
        .setThumbnail(`${target.displayAvatarURL({ dynamic: true })}`)
        .setColor("WHITE")
        .addField("UserID", `${target.id}`, false)
        .addField(
          "Server Member Since",
          target.joinedTimestamp ?
            `<t:${parseInt(target.joinedTimestamp / 1000, 10)}:R>` :
            "Not available",
          false
        )
        
        
        .addField(
          "Discord User Since",
          `<t:${parseInt(target.createdTimestamp / 1000)}:R>`,
          false
        );
      
        let presenceStatus = "Offline"; // Default to "Offline" if status is not found
        
        if (target.presence) {
          // Check if target.presence exists
          const status = target.presence.status;
          if (status === "online") {
            presenceStatus = "Online";
          } else if (status === "idle") {
            presenceStatus = "Idle";
          } else if (status === "dnd") {
            presenceStatus = "Do Not Disturb";
          } else {
            presenceStatus = status; // Use the actual status string if it's not recognized
          }
        }
        
        Response.addField(`Presence : `, `**${presenceStatus}**`, false);
        
        const Sm = await interaction.reply({
          embeds: [Response],
          components: [main],
          fetchReply: true,
        });
        
          const collector = Sm.createMessageComponentCollector();
    
          collector.on("collect", async (i) => {
            if (i.user.id === interaction.user.id) {
              if (i.customId === "main") {
                await i.update({
                  embeds: [Response],
                  components: [main],
                });
              }
              if (i.customId === "roles") {
                var role = new MessageActionRow().addComponents(
                  new MessageButton()
                    .setLabel(`Main info`)
                    .setEmoji(`ℹ`)
                    .setCustomId(`main`)
                    .setStyle(`SECONDARY`),
                  new MessageButton()
                    .setLabel(`Roles info`)
                    .setStyle(`DANGER`)
                    .setDisabled(true)
                    .setEmoji(`ℹ`)
                    .setCustomId(`roles`),
                  new MessageButton()
                    .setLabel(`Permissions`)
                    .setStyle(`SECONDARY`)
                    .setEmoji(`ℹ`)
                    .setCustomId(`permissions`)
                );
                const rolee = new MessageEmbed()
                .setAuthor({
                  name: `${target.tag}`,
                  iconURL: `${target.displayAvatarURL({ dynamic: true })}`,
                });
              
                if (target.roles && target.roles.cache.size > 0) {
                  const rolesList = target.roles.cache
                    .filter((role) => role.id !== interaction.guild.id) // Exclude @everyone role
                    .sort((a, b) => b.position - a.position)
                    .map((role) => role.name)
                    .join(", ");
                  rolee.addField("Roles", rolesList, true);
                  rolee.addField("Highest Role", target.roles.highest.toString(), true);
                } else {
                  rolee.addField("Roles", "No roles found.", true);
                  rolee.addField("Highest Role", "N/A", true);
                }
                
                
                rolee.setColor(`RANDOM`)
                  .setThumbnail(
                    `${target.displayAvatarURL({ size: 1024, dynamic: true })}`
                  );
                
                await i.update({
                  embeds: [rolee],
                  components: [role],
                });
                
              }
              if (i.customId === `permissions`) {
                var perms = new MessageActionRow().addComponents(
                  new MessageButton()
                    .setLabel(`Main info`)
                    .setEmoji(`ℹ`)
                    .setCustomId(`main`)
                    .setStyle(`SECONDARY`),
                  new MessageButton()
                    .setLabel(`Roles info`)
                    .setStyle(`DANGER`)
                    .setEmoji(`ℹ`)
                    .setCustomId(`roles`),
                  new MessageButton()
                    .setLabel(`Permissions`)
                    .setStyle(`SECONDARY`)
                    .setDisabled(true)
                    .setEmoji(`ℹ`)
                    .setCustomId(`permissions`)
                );
                var eee2 = new MessageEmbed()
                .setAuthor({
                  name: `${target.tag}`,
                  iconURL: `${target.displayAvatarURL({ dynamic: true })}`,
                });
              
                if (target.permissions) {
                  // Check if target.permissions exists before calling toArray()
                  const formattedPermissions = target.permissions.toArray().map(permission => `\`${permission}\``).join(', ');
                  eee2.addField(
                    `Permissions : `,
                    `${formattedPermissions}`,
                    true
                  );
                } else {
                  eee2.addField(
                    `Permissions : `,
                    "No permissions available", // Handle the case where target.permissions is undefined
                    true
                  );
                }
                
                eee2.setColor(`RANDOM`)
                  .setThumbnail(`${target.displayAvatarURL({ dynamic: true })}`);
                
                await i.update({
                  embeds: [eee2],
                  components: [perms],
                });
                
              }
            } else {
              i.reply({
                content: `These buttons aren't for you!`,
                ephemeral: true,
              });
            }
          });
      } else if (interaction.options.getSubcommand() === "bot") {
        const time = pms(client.uptime, {
          compact: true,
        });
        let botEmbed = new MessageEmbed()
          .setTitle(`Information about ${client.user.tag}`)
          .setAuthor({
            name: `${client.user.tag}`,
            iconURL: `${client.user.displayAvatarURL()}`,
          })
          .addField(`👋 Name of bot:`, `${client.user.tag}`, true)
          .addField(`⚠️ Version:`, `${version}`, true)
          .addField(
            `💯 Account created on:`,
            `${format(client.user.createdAt, "dd/MM/yyyy hh:mm:ss")}`,
            true
          )
          .addField(`🤖 Amount of Guilds:`, `${client.guilds.cache.size}`, true)
          .addField(`⬆️ Uptime of the bot:`, `${time}`, true)
          .setFooter({
            text: `${client.user.tag}`,
            iconURL: client.user.displayAvatarURL(),
          })
          .setColor("RANDOM")
          .setTimestamp();
  
        interaction.reply({
          embeds: [botEmbed],
        });
      } else if (interaction.options.getSubcommand() === "server") {
        let serverEmbed = new MessageEmbed()
          .setTimestamp()
          .setTitle(`**Server Information** for ${interaction.guild.name}`)
          .setColor("RANDOM")
          .setThumbnail(interaction.guild.iconURL())
          .addField(`🎫 Name of server:`, `${interaction.guild.name}`, true)
          .addField(`🆔 ID of server`, `${interaction.guild.id}`, true)
          .addField(`👑 Owner of server`, `<@${interaction.guild.ownerId}>`, true)
          .addField(`👑 Owner ID`, `${interaction.guild.ownerId}`, true)
          .addField(
            `👥 Member total`,
            `${interaction.guild.members.cache.size}`,
            true
          )
          .addField(
            `🤖 Bots:`,
            `${
              interaction.guild.members.cache.filter((member) => member.user.bot)
                .size
            }`,
            true
          )
          .addField(
            `🚶 Real Humans:`,
            `${
              interaction.guild.members.cache.filter((member) => !member.user.bot)
                .size
            }`,
            true
          )
          .addField(`😗 Emojis:`, `${interaction.guild.emojis.cache.size}`, true)
          .addField(
            `👻 Animated Emoji\'s:`,
            `${
              interaction.guild.emojis.cache.filter((emoji) => emoji.animated)
                .size
            }`,
            true
          )
          .addField(
            `🎮 Guild Creation date:`,
            `${format(interaction.guild.createdAt, "dd/MM/yyyy hh:mm:ss")}`,
            true
          )
          .addField(
            `💯 You joined on:`,
            `${format(interaction.member.joinedAt, "dd/MM/yyyy hh:mm:ss")}`,
            true
          )
          .addField(
            `👔 Total Amount of Roles:`,
            `${interaction.guild.roles.cache.size}`,
            true
          )
          .addField(
            `🎉 Boost Tier:`,
            `${interaction.guild.premiumTier.toLowerCase()}`,
            true
          )
          .addField(
            `⛔ Amount of bans:`,
            `${interaction.guild.bans.cache.size}`,
            true
          )
          .addField(`🥇 Member Cap:`, `${interaction.guild.maximumMembers}`, true)
          .setAuthor({
            name: interaction.user.username,
            iconURL: interaction.user.displayAvatarURL(),
          })
          .setFooter({
            text: client.user.tag,
            iconURL: client.user.displayAvatarURL(),
          });
  
        await interaction.reply({
          embeds: [serverEmbed],
        });
      } else {
        await interaction.reply("No sub command was used.");
      }
    } catch (error) {
      // Handle errors here
      console.error(error);
    
      const errorEmbed = new MessageEmbed()
        .setColor("RED")
        .setTitle("An error occurred")
        .setDescription("An error occurred while processing your request.")
        .addField("Error Message", `\`\`\`${error.message}\`\`\``);
    
      // Check if the error has a stack trace
      if (error.stack) {
        const stackLines = error.stack.split("\n");
        // Extract the line number from the second line of the stack trace
        const lineMatch = stackLines[1].match(/:(\d+):\d+/);
        if (lineMatch) {
          const lineNumber = lineMatch[1];
          errorEmbed.addField("Line Number", `\`\`\`${lineNumber}\`\`\``);
        }
        // Add the first two lines of the stack trace to the embed
        errorEmbed.addField("Stack Trace", `\`\`\`${stackLines.slice(0, 2).join("\n")}\`\`\``);
      }
    
      errorEmbed.addField(
        "Instructions",
        "If you encounter this error repeatedly, please take note of the error message and line number and contact the server administrators for assistance."
      );
    
      await interaction.reply({ embeds: [errorEmbed] });
    }
    
    
  },
};

What I've Tried:

I've reviewed the code and made sure that the necessary properties (target.joinedTimestamp, target.roles) are being accessed correctly. However, I'm still encountering these issues.

Expected Outcome:

I expect the "Server Member Since" field to display the user's join date in a readable format, and the "Roles" field to list the user's roles. Additionally, the "Highest Role" field should display the user's highest role.


Solution

  • Solution 1:

    Your target is a User not a GuildMember!

    To get a GuildMember, use .getMember() instead of .getUser().

    const member = interaction.options.getMember('target'); // get a member
    const user = await interaction.client.users.fetch(member.user.id); // fetch a user using the member
    

    Now, use member & parseInt() without a second param and you're good to go!

    .addField(
        "Server Member Since",
        member.joinedTimestamp ?
        `<t:${parseInt(member.joinedTimestamp / 1000)}:R>` :
        "Not available",
        false
    )
    

    Solution 2:

    Change all your target occurrences inside the collector to member to access the RoleManager property.

    This should resolve your issue.