I'm coding a discord bot using JDA and I'm having a tough time trying to figure out a way to show in the bot's activity section the number of online users in a server.
This is my main bot class:
public DiscordBot() throws LoginException {
config = Dotenv.configure().load();
String token = config.get("TOKENDISCORD");
eventListener = new BotEventListener();
eventListener.addOnlineStatusChangeListener(event -> {
int onlineMembers = eventListener.getQuantityOnlineMembers();
});
bot = JDABuilder.createDefault(token,
GatewayIntent.GUILD_MEMBERS,
GatewayIntent.GUILD_MESSAGES,
GatewayIntent.GUILD_PRESENCES,
GatewayIntent.GUILD_VOICE_STATES
)
.setMemberCachePolicy(MemberCachePolicy.ALL)
.disableCache(EnumSet.of(
CacheFlag.CLIENT_STATUS,
CacheFlag.ACTIVITY,
CacheFlag.EMOTE
))
.setChunkingFilter(ChunkingFilter.ALL)
.enableCache(EnumSet.of(
CacheFlag.ONLINE_STATUS
))
.setActivity(Activity.listening(new CustomActivity(eventListener).getName()))
.setMemberCachePolicy(MemberCachePolicy.VOICE)
.addEventListeners(eventListener)
.addEventListeners(new BotCommands())
.enableCache(CacheFlag.VOICE_STATE)
.build();
}
Event listener class:
//Triggering observer whenever a user is online or offline
@Override
public void onUserUpdateOnlineStatus(UserUpdateOnlineStatusEvent event) {
System.out.println("test 1");
onlineStatusEvent = event;
int onlineMembers = getQuantityOnlineMembers();
for (Consumer<Integer> listener : onlineStatusChangeListeners) {
listener.accept(onlineMembers);
}
}
//Evaluating user amount
public int getQuantityOnlineMembers() {
System.out.println("test 2");
if (onlineStatusEvent == null) {
return 0;
}
System.out.println("test 3");
List<Member> members = onlineStatusEvent.getGuild().getMembers();
int onlineMembers = 0;
for (Member member : members) {
if (member.getOnlineStatus() == OnlineStatus.ONLINE) {
onlineMembers++;
System.out.println(onlineMembers);
}
}
return onlineMembers;
}
//And I've created a CustomActivity class to make the code cleaner when calling it from the bot's .setActivity
public class CustomActivity extends ActivityImpl {
private BotEventListener eventListener;
public CustomActivity(BotEventListener eventListener) {
super(null);
this.eventListener = eventListener;
}
@Override
public String getName() {
int onlineMembers = eventListener.getQuantityOnlineMembers();
return "Users online: " + String.valueOf(onlineMembers);
}
}
I've noticed that once the bot starts, it never goes back to update its activity display. Maybe creating a map to the amount of users and updating it forcefully when the observer in onUserUpdateOnlineStatus is triggered.
You should use a scheduler to update the activity in a set interval:
// Build your JDA instance
JDA jda = JDABuilder...build();
// Every 60 seconds (don't update this too quickly)
jda.getGatewayPool().scheduleAtFixedRate(() -> {
int onlineMembers = eventListener.getQuantityOnlineMembers();
jda.getPresence().setActivity(Activity.listening("Users online: " + onlineMembers));
}, 0, 60, TimeUnit.SECONDS);