-1

I'm using the current latest version of Discord.js 12.5.3 and tried several different approaches for different versions.

In the documentation I can see there are two args, first of which is "client" and the second one is simply "data", it's not specified which data it needs so it's a bit weird being the first time building a Discord bot.

I've tried to use the first arg only with this code:

bot.on("message", async (msg) => {
  if (!isCommand(msg) || msg.author.bot) return;

  const guild = new Discord.Guild(bot);
  console.log(guild);

});

Then I get this:

<ref *1> Guild {
  members: GuildMemberManager {
    cacheType: [class Collection extends Collection],
    cache: Collection(0) [Map] {},
    guild: [Circular *1]
  },
  channels: GuildChannelManager {
    cacheType: [class Collection extends Collection],
    cache: Collection(0) [Map] {},
    guild: [Circular *1]
  },
  roles: RoleManager {
    cacheType: [class Collection extends Collection],
    cache: Collection(0) [Map] {},
    guild: [Circular *1]
  },
  presences: PresenceManager {
    cacheType: [class Collection extends Collection],
    cache: Collection(0) [Map] {}
  },
  voiceStates: VoiceStateManager {
    cacheType: [class Collection extends Collection],
    cache: Collection(0) [Map] {},
    guild: [Circular *1]
  },
  deleted: false
}

Then I try console.log(guild.members);

and I get

<ref *1> GuildMemberManager {
  cacheType: [class Collection extends Collection],
  cache: Collection(0) [Map] {},
  guild: <ref *2> Guild {
    members: [Circular *1],
    channels: GuildChannelManager {
      cacheType: [class Collection extends Collection],
      cache: Collection(0) [Map] {},
      guild: [Circular *2]
    },
    roles: RoleManager {
      cacheType: [class Collection extends Collection],
      cache: Collection(0) [Map] {},
      guild: [Circular *2]
    },
    presences: PresenceManager {
      cacheType: [class Collection extends Collection],
      cache: Collection(0) [Map] {}
    },
    voiceStates: VoiceStateManager {
      cacheType: [class Collection extends Collection],
      cache: Collection(0) [Map] {},
      guild: [Circular *2]
    },
    deleted: false
  }
}

in which cache is a Collection(0) [Map] {}

and console.log(guild.members.guild.members);

gives the same output than console.log(guild.members);

All code chunks marked as working are from older versions or not working to me.

I was guessing if I need to login the bot on another place but as long as message reply works... Here's the code for reference:

const Discord = require("discord.js");
const bot = new Discord.Client({ disableMentions: "everyone" });
const dotenv = require("dotenv");
dotenv.config();

bot.login(process.env.token);

// event handlers
bot.once("ready", () => {
  console.log("Ready!");
});

bot.on("message", async (msg) => {
  if (!isCommand(msg) || msg.author.bot) return;

  /* 
  // get guild online member usernames
  
  const guild = new Discord.Guild(bot);
  console.log(guild.members);
   */

  msg.reply(handle(msg.content, msg.author.username));
});

Can you put me in the right direction about how to reach this? Thanks

JoelBonetR
  • 1,551
  • 1
  • 15
  • 21

2 Answers2

0

You can get the current server you're sending the message in from the message itself. message.guild returns the guild the message was sent in.

guild has a members prop that returns a manager of the members belonging to this guild. To get all the members, you can use the fetch() method that returns a promise and resolves to a collection of members. Collections have a map() methods that you can use to create an array of usernames.

Checking if a user is online is a bit trickier. You can check their presence. Its status prop can be online, idle, offline, or dnd. You can filter the array you created above and only return ones where the status is not offline.

Something like this should work:

bot.on('message', async (msg) => {
  if (!isCommand(msg) || msg.author.bot) return;

  let { guild: { members } } = msg;
  let allMembers = await members.fetch();
  let onlineUsers = allMembers.filter((member) => member.presence.status !== 'offline');
  let usernames = onlineUsers.map((member) => member.displayName);

  // array of usernames of users who are not offline
  console.log(usernames);
});
Zsolt Meszaros
  • 21,961
  • 19
  • 54
  • 57
  • Yes it should but for any reason I can't catch at this point, the fetch method throws a timeout with this exact code and with other implementations I've tried so far. \discord.js\src\managers\GuildMemberManager.js:317 reject(new Error('GUILD_MEMBERS_TIMEOUT')); ^ Error [GUILD_MEMBERS_TIMEOUT]: Members didn't arrive in time. – JoelBonetR Jul 25 '21 at 10:25
  • Yep, that's because of the missing `GUILD_MEMBERS` intents. https://stackoverflow.com/questions/64559390/none-of-my-discord-js-guildmember-events-are-emitting-my-user-caches-are-basica/64559391#64559391 – Zsolt Meszaros Jul 25 '21 at 11:03
  • yup that's what I'd find out – JoelBonetR Jul 25 '21 at 11:49
0

SOLVED:

I've found that I need to enable Privileged Gateway Intents in Discord developer portal -> bot.

Then set up the bot like this:

const Discord = require("discord.js");
const bot = new Discord.Client({ disableMentions: "everyone", ws: { Intents: ["GUILD_MEMBERS", "GUILD_PRESENCES"] } });

and finally I'm able to get online guild users that are not bots with this

bot.on("message", async (msg) => {
  if (!isCommand(msg) || msg.author.bot) return;

  let {
    guild: { members },
  } = msg;

  let allMembers = await members.fetch();
  let onlineUsers = allMembers.filter((member) => member.presence.status !== "offline");
  let availableUsers = onlineUsers.filter((member) => !member.user.bot);
  let usernames = availableUsers.map((member) => member.displayName);

  console.log(usernames);

  msg.reply(handle(msg.content, msg.author.username));
});

So it was about permissions and a little tweak. This is not linked or advertised in Discord.js documentation so it was a bit confusing.

JoelBonetR
  • 1,551
  • 1
  • 15
  • 21