Discord jda bot || UserUpdateActivitiesEvent does not trigger - java

I tried tracking if people on the bots guild change activities (like starting to play a game)
After reading the javadoc I found out:
GatewayIntent.GUILD_PRESENCES
CacheFlag.ACTIVITY
MemberCachePolicy.ONLINE (therefore GatewayIntent.GUILD_MEMBERS)
must be active.
so thats my Main:
JDABuilder builder = JDABuilder.createDefault(token);
builder.enableIntents(GatewayIntent.GUILD_PRESENCES);
builder.enableIntents(GatewayIntent.GUILD_MEMBERS);
builder.enableCache(CacheFlag.ACTIVITY);
builder.setMemberCachePolicy(MemberCachePolicy.ONLINE);
builder.setChunkingFilter(ChunkingFilter.ALL);
this.jda = builder.build();
jda.addEventListener( new ActivityListener(jda));
And this my Listener:
public class ActivityListener extends ListenerAdapter {
private final JDA jda;
public ActivityListener(JDA jda) {
this.jda = jda;
}
#Override
public void onUserUpdateActivities(#NotNull UserUpdateActivitiesEvent event) {
super.onUserUpdateActivities(event);
System.out.println(event.getUser().getAsTag() + " " + event.getUser().getIdLong());
}
}
Sadly when I or someone else starts a game or smt else it never triggers.
Edit:
I used jda.getUserCache(); to check if the caching worked and I am i the cache, but it still doesn't work.

The members for the associated users have to be cached before the event fires. Since you use lazy loading this might take a while to happen since members are added to cache through messages or voice states.
You can use setChunkingFilter(ChunkingFilter.ALL) to eagerly load all members on startup.
There was a bug which caused these events to not fire which has been fixed in 4.2.1_264.

the UserUpdateActivitiesEvent requires the GuildPresence intent to be enabled. You enabled it in your code, but it has to also be enabled on the discord api website at https://discord.com/developers/applications -> Your Application -> Bot -> Enable Presence Intent

Related

onGuildMemberJoin Does not work / is not being called

`public class VerificationSystem extends ListenerAdapter {
#Override
public void onGuildMemberJoin(GuildMemberJoinEvent event) {
System.out.println("WORKS!");
String memberName = event.getMember().getEffectiveName();
Member member = event.getMember();
event.getGuild().addRoleToMember(member,event.getGuild().getRoleById("1034143551568752682")).queue(); //Grants the new member "Unverified" role
TextChannel textChannel = event.getGuild().createTextChannel("Verification for: " + memberName).complete(); // Creates new verification channel
textChannel.getManager().getChannel().upsertPermissionOverride(event.getMember()).setAllowed(Permission.VIEW_CHANNEL).queue(); // Grants the new member view permissions to the channel
textChannel.getManager().getChannel().upsertPermissionOverride(event.getGuild().getRoleById("1034143551568752682")).setDenied(Permission.VIEW_CHANNEL).queue(); // Revokes the view permission for #everyone
}`
The event register:
JDA jda = JDABuilder.createDefault(token)
.setActivity(Activity.playing("Football Manager"))
.addEventListeners(new VerificationSystem())
.build().awaitReady();
For some reason this method does not work. It is correctly registered, and it does not work whenever someone joins the server. Please help, this is killing me!!
Since one of updates Discord added such thing as "Intents". Now all developers have to specify what kind of data their bots need.
To accept events of members' joining you need to use intent "GUILD_MEMBERS". Note that this intent is priveleged, what means you can use it easily until your bot reaches 100 servers, then you must get verification from Discord.
To enable intents in bot visit Developers portal
To enable intents in JDA use enableIntents method in builder.
JDA jda = JDABuilder.createDefault(token)
.setActivity(Activity.playing("Football Manager"))
.addEventListeners(new VerificationSystem())
// Enables GUILD_MEMBERS intent
.enableIntents(GatewayIntent.GUILD_MEMBERS)
.build().awaitReady();

How to send a DM to someone WITH response in JDA

I am coding a feedback feature in my Discord Bot, when someone leaves, they should be DMed a message asking why they left.
event.getUser().openPrivateChannel()
.flatMap(channel -> channel.sendMessage("Hello, we are sorry you're leaving "+event.getGuild().getName()+", if you don't mind, please tell us why you left or leave any other feedback here, it'll help us improve the server and improve experience for you if you re-join again in the future.\n\nThank you ❤."))
.queue();
The code above is responsible for sending it, I tried to create a state machine in a private channel but it didn't work:
import bot.Main;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.MessageChannel;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
public class Feedback extends ListenerAdapter {
private final long channelId, authorId;
public Feedback(MessageChannel channel, User author) {
this.channelId = channel.getIdLong();
this.authorId = author.getIdLong();
}
#Override
public void onMessageReceived(MessageReceivedEvent event) {
if (event.getAuthor().isBot()) return;
if (event.getAuthor().getIdLong() != authorId) return;
if (event.getChannel().getIdLong() != channelId) return;
MessageChannel channel = event.getChannel();
String content = event.getMessage().getContentRaw();
event.getChannel().sendMessage("Thanks for your feedback!").queue();
EmbedBuilder feedback = new EmbedBuilder();
feedback.setTitle("Automated System Operations - Leaving Feedback");
feedback.addField("Feedback", content, false);
feedback.setColor(0xC90004);
feedback.setAuthor(event.getAuthor().getAsTag()+" - "+event.getAuthor().getId(), "https://support.discord.com/hc/en-us/articles/209572128-How-do-I-log-out-", event.getAuthor().getAvatarUrl());
feedback.setImage("https://media.discordapp.net/attachments/894913784823566428/896323821336948736/unknown.png?width=384&height=192");
Main.jda.getGuildById("894913620868202506").getTextChannelById("896322509874540545").sendMessage(feedback.build()).queue();
}
}
I got this event state-machine channel but I don't know how to addListener to it in DMs.
Any help is accepted <3
You can add the state machine event listener with JDA#addEventListener:
event.getUser().openPrivateChannel().flatMap(channel -> {
event.getJDA().addEventListener(new Feedback(channel, event.getUser()));
return channel.sendMessage("hello");
}).queue();
I would recommend to remove your event listener after you received that response with event.getJDA().removeEventListener(this);
You never have to guess how to use a library - that's what documentation is for. Any library worth its salt has documentation listing every single class, method, and the property you need to worry about.
A quick google search for "discord-jda docs" takes us to the JavaDoc: https://ci.dv8tion.net/job/JDA/javadoc/index.html
You want to send a message to a user, right? So let's use the search bar and find User. First result under Types is net.dv8tion.jda.API.entities.User. We're now at https://ci.dv8tion.net/job/JDA/javadoc/net/dv8tion/jda/api/entities/User.html
If you want to know how to do something with a user, we look at the Methods every User has. Two catch my eye right away: User.hasPrivateChannel() and User.openPrivateChannel(). We'll click the second one since it looks relevant.
Lo and behold, the docs have example usage! I'll quote it below:
// Send message without response handling
public void sendMessage(User user, String content) {
user.openPrivateChannel()
.flatMap(channel -> channel.sendMessage(content))
.queue();
}
This seems pretty straightforward. So the basic usage you're looking for (assuming event is a MessageReceivedEvent) is this:
event.getAuthor().openPrivateChannel().flatMap(channel -> channel.sendMessage("hello")).queue();

I'm trying to make a simple Discord Bot, but it doesn't work

I'm trying to make a simple Discord Bot within a Minecraft Mod, and it doesn't work. I do have to say that I am new to coding discord bots in java, as I am more based to javascript.
Here is what I made:
DiscordBot.java
public class DiscordBot
{
public JDA jda;
private String token = "----";
public static DiscordBot instance = new DiscordBot();
#SuppressWarnings("deprecation")
public void startDiscordBot() throws LoginException
{
jda = new JDABuilder()
.setToken(token)
.setStatus(OnlineStatus.DO_NOT_DISTURB)
.addEventListeners(new DiscordEventListener())
.build();
}
}
DiscordEventListener.java
public class DiscordEventListener extends ListenerAdapter
{
#Override
public void onMessageReceived(MessageReceivedEvent event)
{
if(event.getMessage().getContentRaw().equals("-login"))
{
EmbedBuilder eb1 = new EmbedBuilder();
EmbedBuilder eb2 = new EmbedBuilder();
event.getAuthor().openPrivateChannel().queue(channel -> {
eb2.setColor(Color.MAGENTA);
eb2.setTitle(placeholder-text);
eb2.setDescription(placeholder-text);
channel.sendMessage(eb2.build());
});
The DiscordEventListener takes "-login" and responds with the rest of the code, but the problem is, while the bot does go online, it doesn't do anything when I send -login in the discord server, nor dms. Also no errors occur on launch neither on the event. Also, I have a depricated version of JDA (4.2.1) because I don't understand how to use the new one.
I tried multiple little things but they showed 0 results, so I don't know what is wrong here.
(Also yes, I have initialised the DiscordBot class in the Main one, so I don't think that is the problem)
#dan1st figured it out, I forgot to add .queue(); to the end of channel.sendMessage, so thanks to them.

JDA. GuildMemberJoin/LeaveEvent

I have written the following methods and they both are not working. Anyone know why and how to fix it?
PS: The bot has admin perms.
public class GuildMemberJoin extends ListenerAdapter {
public void onGuildMemberJoin(GuildMemberJoinEvent event) {
EmbedBuilder join = new EmbedBuilder();
join.setColor(Color.getHSBColor(227, 74, 64));
join.setTitle("SERVER UPDATE");
join.setDescription(event.getMember().getAsMention() + " has now joined The server!");
event.getGuild().getDefaultChannel().sendMessage(join.build()).queue();
}
public class GuildMemberLeave extends ListenerAdapter {
public void onGuildMemberLeave(GuildMemberLeaveEvent event) {
EmbedBuilder join = new EmbedBuilder();
TextChannel spamChannel = event.getGuild().getTextChannelById("713429117546135572");
join.setColor(Color.getHSBColor(227, 74, 64));
join.setTitle("SERVER UPDATE");
join.setDescription(event.getMember().getAsMention() + " has now left the server!");
spamChannel.sendMessage(join.build()).queue();
}
Default channel settings
To quote the JDA Wiki:
There are many reasons why your event listener might not be executed but here are the most common issues:
You are using the wrong login token?
If the token is for another bot which doesn't have access to the desired guilds then the event listener code cannot run.
Your bot is not actually in the guild?
Make sure your bot is online and has access to the resource you are trying to interact with.
You never registered your listener?
Use jda.addEventListener(new MyListener()) on either the JDABuilder or JDA instance
You did not override the correct method?
Use #Override and see if it fails. Your method has to use the correct name and parameter list defined in ListenerAdapter.
You don't actually extend EventListener or ListenerAdapter.
Your class should either use extends ListenerAdapter or implements EventListener.
You are missing a required GatewayIntent for this event.
Make sure that you enableIntents(...) on the JDABuilder to allow the events to be received.
The event has other requirements that might not be satisfied such as the cache not being enabled.
Please check the requirements on the event documentation.
If none of the above apply to you then you might have an issue in your listener's code, at that point you should use a debugger.
For clarification:
You can enable the GUILD_MEMBERS intent by doing builder.enableIntents(GatewayIntent.GUILD_MEMBERS) on JDABuilder.
For example:
JDABuilder builder = JDABuilder.createDefault(token);
builder.enableIntents(GatewayIntent.GUILD_MEMBERS);
builder.addEventListeners(myListener);
JDA jda = builder.build();
See also: Gateway Intents and Member Cache Policy

How to log crash details from CustomActivityOnCrash

We are using the Ereza CustomActivityOnCrash library to handle unexpected issues with our android app. It's activity offers some debug output which we enable in develop and test builds but disable on production builds. In addition we want to log that information about crash details (log entries, stack trace, error details) in background.
CustomActivityOnCrash offers to call event listeners which sounds convenient. I wanted to implement the interface in our logging service, however I do not understand how I can access the existing information in the crash activity that way. Which puzzles me, cause isn't that a natural expectation?
Basically I need to access public methods of an android activity object from an event listener method that does not get handed over anything. How can I access that activity in the handler method? And how can I get the intent of the activity leading to the crash which is the argument the crash activity expects in those public methods it offers to access the existing information it offers? The examples given in the libraries documentation and those I could find on the internet are trivial, they only dump example strings, not the actual data collected by the library.
This all sounds counter intuitive to me. Which is why I think I generally miss something here. Maybe someone has a short hint for me to bring me on track again. Thanks!
Here is the basics of the LogService implementation I imagine:
...
import cat.ereza.customactivityoncrash.CustomActivityOnCrash;
...
public class LogService
implements CustomActivityOnCrash.EventListener {
private static LogService instance;
...
public void log(LogLevel level, String message) {
....
}
public void logCrashDetails(String activityLog, String stackTrace, String errorDetails) {
String message = String.format(
"--- CRASH REPORT ---\n\n-- Activity log:\n%s\n\n- Stack trace:\n%s\n\nError details:\n%s",
activityLog,
stackTrace,
errorDetails);
log(LogLevel.ERROR, message);
}
....
// CustomActivityOnCrash EventListener interface
#Override
public void onLaunchErrorActivity() {
log(LogLevel.INFO, "COAC: app crashed");
logCrashDetails(
// CustomActivityOnCrash.getActivityLogFromIntent(...some intent...),
// CustomActivityOnCrash.getStackTraceFromIntent(...some intent...),
// CustomActivityOnCrash.getAllErrorDetailsFromIntent(...some intent...)
);
}
#Override
public void onRestartAppFromErrorActivity() {
log(LogLevel.INFO, "COAC: app restarted");
}
#Override
public void onCloseAppFromErrorActivity() {
log(LogLevel.INFO, "COAC: app closed");
}
}

Categories