javabotsdiscorddiscord-jda

Discord JDA - Invalid Member List


I am creating a Discord bot and have encountered a strange problem. I need to go through each user on the server and perform a conditional action. But when receiving a list of all Members, it contains only me and the bot itself.

public class Bot extends ListenerAdapter {
    public void onGuildMessageReceived(GuildMessageReceivedEvent Event) {
        String Message = Event.getMessage().getContentRaw();

        if(Message.charAt(0) == Globals.BOT_PREFIX) {
            String[] Args = Message.split("\\s+");

        if(Args[0].equalsIgnoreCase(CommandType.COMMAND_DEV_TEST)) {
            List<Member> MemberList = Event.getGuild().getMembers();
            for(int i = 0; i < MemberList.size(); i++)
                System.out.println(MemberList.get(i));
        }
    }
}

If another person writes, then only me and the bot are still displayed.


Solution

  • I assume you're using a development version of the 4.2.0 release (4.1.1_102 and above)

    In these versions, the new factory methods have been introduced to make people aware of the new discord API design. In the future, bots will be limited to cache members who connected to voice channels by default.

    If all you need is the count of members you can just use Guild#getMemberCount! Otherwise:

    The createDefault/createLight will only cache members connected to voice channels or owners of guilds (on first sight). To cache more members, you will have to enable the GUILD_MEMBERS intent in both the application dashboard for your bot and in JDA.

    enter image description here

    Now you can do something like this:

    JDA api = JDABuilder.createDefault(token)
                        .setMemberCachePolicy(MemberCachePolicy.ALL)
                        .enableIntents(GatewayIntent.GUILD_MEMBERS)
                        .build();
    

    The GUILD_MEMBERS intent is needed because it enables the GUILD_MEMBER_REMOVE dispatch to tell the library to remove a member from the cache when they are kicked/banned/leave.

    This setup will perform lazy loading, which means it will start with only voice members and add more members to the cache once they become active.

    To load all members on startup you have to additionally enable member chunking:

    JDABuilder.createDefault(token)
              .setChunkingFilter(ChunkingFilter.ALL) // enable member chunking for all guilds
              .setMemberCachePolicy(MemberCachePolicy.ALL)
              .enableIntents(GatewayIntent.GUILD_MEMBERS)
              .build();
    

    You can also load them for individual guilds using Guild#loadMembers or Guild#findMembers.

    I recommend to also read this JDA wiki article: Gateway Intents and Member Cache Policy.