How to send a DM to someone WITH response in JDA - java

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();

Related

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.

Discord jda bot || UserUpdateActivitiesEvent does not trigger

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

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 add reaction to an embed message JDA

I'm trying to send and embed message when I do the command ~verify and then it sends an embed message and I cant find how to add to there a reaction.
I did already the embed message and sent it but can add the reaction
import Main.Bot;
import net.dv8tion.jda.core.EmbedBuilder;
import net.dv8tion.jda.core.MessageBuilder;
import net.dv8tion.jda.core.entities.Message;
import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.core.hooks.ListenerAdapter;
import java.awt.*;
public class Verify extends ListenerAdapter {
#Override
public void onGuildMessageReceived(GuildMessageReceivedEvent e){
if(e.getAuthor().isBot()) return;
if(e.getMessage().getContentRaw().equalsIgnoreCase(Bot.prefix+"verify")){
EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setColor(Color.red);
embedBuilder.setTitle("Verify yourself!");
embedBuilder.addField("How?","Press the ✔ reaction to verify",false);
embedBuilder.setFooter("Created by SlayZBro#3501",e.getGuild().getIconUrl());
e.getChannel().sendTyping().queue();
e.getChannel().sendMessage(embedBuilder.build()).queue();
embedBuilder.clear();
}
}
}
I need to add the reaction to the embed message
You can access the sent message in the callback for queue() and add reactions there:
channel.sendMessage(embed).queue(message -> message.addReaction(reaction).queue());
To add multiple questions you can use a multiline lambda:
channel.sendMessage(embed).queue(message -> {
message.addReaction(reaction1).queue();
message.addReaction(reaction2).queue();
message.addReaction(reaction3).queue();
});
Also there is no reason to clear the EmbedBuilder because it won't be used again in your code. Builders are usually not resources that need to be closed/cleared unless you use them again and don't want the previous settings.
I understood how to do it. Just need to add this line
e.getChannel().sendMessage(embedBuilder.build()).complete().addReaction("✔").queue();

Java code to handle node failure in jgroups cluster

My Jgroups config file contains the protocol/config
<FD timeout="3000" max_tries="3" />
But how do I use this in the Java code. For example, if there is a cluster and when I detect a failure I want to call an external notifier service via a REST call, like /nodeDown/nodeID
I'm not able to find any java code which does this, all I see is message receive and send, is there a way I can implement this?
Thanks
Adding some more info
I have done the step of writing a RecieverAdpater and override the start, stop, send, recieve method. Please find some code here,
public void receive(Message msg) {
JGroupsDataPacket pckt = (JGroupsDataPacket) msg.getObject();
if ( pckt.getCmd().equals("cacheUpdate") ){
int uid = pckt.getAffectedUid();
cacheUpdateRoutine(uid);
}
if ( pckt.getCmd().equals("ack") ){
System.out.println("got the mesaage!");
}
logger.log(LogLevel.ERROR, "received msg from " + msg.getSrc() + ": " + msg.getObject());
}
public void send(JGroupsDataPacket pckt){
Message msg = new Message(null, null, pckt);
msg.setFlag(Message.Flag.RSVP);
try {
channel.send(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
I want to know where should I add code for example to handle the TimeOutException when I'm sending a message with the RSVP flag enabled. Another requirement is to know, which is the Java callback method which is called when SUSPECT(P) is triggered. I want to catch and handle the machine's going down, timout etc.
Is the viewAccepted() the only place where I can handle this? Is there a sample code around this?
Also is http://www.jgroups.org/manual/html/user-channel.html
the section 3. APIs give all java/programmatic things we can do with JGroups.
Thanks again
I found some documentation here, I think this is the class which I'm supposed to override
public interface MembershipListener {
void viewAccepted(View new_view);
void suspect(Object suspected_mbr);
void block();
void unblock();
}
OK, first off, you have a JChannel. You need to use it to register for view callbacks, like this:
JChannel ch;
ch.setReceiver(this);
'this' extends ReceiverAdapter and overrides viewAccepted():
public void viewAccepted(View view) {
// handle new view
}
To determine the members which left between views v1 and v2:
List<Address> left_mbrs=View.leftMembers(v1,v2);

Categories