Documentation Index
Fetch the complete documentation index at: https://mintlify.com/discord-jda/JDA/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Message events are fired when messages are created, updated, deleted, or when users interact with them through reactions or polls.
Required Intents
Message events require the following Gateway Intents:
GUILD_MESSAGES - For messages in guild channels
DIRECT_MESSAGES - For messages in DMs
MESSAGE_CONTENT - For accessing message content (privileged)
JDA jda = JDABuilder.createDefault(token)
.enableIntents(
GatewayIntent.GUILD_MESSAGES,
GatewayIntent.DIRECT_MESSAGES,
GatewayIntent.MESSAGE_CONTENT
)
.build();
Message Lifecycle Events
MessageReceivedEvent
Fired when a message is sent in a channel your bot has access to.
Package: net.dv8tion.jda.api.events.message
@Override
public void onMessageReceived(MessageReceivedEvent event) {
Message message = event.getMessage();
User author = event.getAuthor();
MessageChannel channel = event.getChannel();
// Check if message is from a bot
if (event.isWebhookMessage()) {
System.out.println("Message from webhook");
return;
}
// Get member (null in DMs)
Member member = event.getMember();
if (member != null) {
System.out.println("Guild message from: " + member.getEffectiveName());
}
// Access message content
String content = message.getContentRaw();
System.out.println("Message: " + content);
}
Key Methods:
getMessage() - The message that was received
getAuthor() - The user who sent the message
getMember() - The member who sent the message (null in DMs)
getChannel() - The channel where the message was sent
isWebhookMessage() - Whether the message was sent by a webhook
MessageUpdateEvent
Fired when a message is edited.
Package: net.dv8tion.jda.api.events.message
@Override
public void onMessageUpdate(MessageUpdateEvent event) {
Message message = event.getMessage();
System.out.println("Message updated: " + event.getMessageId());
System.out.println("New content: " + message.getContentRaw());
// Check if message was edited
if (message.isEdited()) {
System.out.println("Edited at: " + message.getTimeEdited());
}
}
Key Methods:
getMessage() - The updated message
getMessageId() / getMessageIdLong() - The message ID
getChannel() - The channel containing the message
MessageDeleteEvent
Fired when a message is deleted.
Package: net.dv8tion.jda.api.events.message
@Override
public void onMessageDelete(MessageDeleteEvent event) {
long messageId = event.getMessageIdLong();
MessageChannel channel = event.getChannel();
System.out.println("Message " + messageId + " deleted in " + channel.getName());
}
Note: This event only provides the message ID, not the full message object, as the message has been deleted.
Key Methods:
getMessageId() / getMessageIdLong() - The deleted message ID
getChannel() - The channel where the message was deleted
MessageBulkDeleteEvent
Fired when multiple messages are deleted at once (bulk delete).
Package: net.dv8tion.jda.api.events.message
@Override
public void onMessageBulkDelete(MessageBulkDeleteEvent event) {
List<String> messageIds = event.getMessageIds();
int count = event.getMessageIds().size();
System.out.println(count + " messages were bulk deleted");
System.out.println("Deleted IDs: " + messageIds);
}
Key Methods:
getMessageIds() - List of deleted message IDs
getChannel() - The channel where messages were deleted
Reaction Events
Reaction events fire when users add or remove reactions from messages.
MessageReactionAddEvent
Fired when a user adds a reaction to a message.
Package: net.dv8tion.jda.api.events.message.react
@Override
public void onMessageReactionAdd(MessageReactionAddEvent event) {
User user = event.getUser();
MessageReaction.ReactionEmoji emoji = event.getReaction().getEmoji();
// Handle custom emoji
if (emoji.getType() == MessageReaction.ReactionEmoji.Type.CUSTOM) {
System.out.println("Custom emoji: " + emoji.getName());
} else {
// Unicode emoji
System.out.println("Unicode emoji: " + emoji.getAsReactionCode());
}
// Retrieve the message
event.retrieveMessage().queue(message -> {
System.out.println("Reaction added to: " + message.getContentRaw());
});
}
Key Methods:
getUser() - The user who added the reaction
getUserIdLong() - The user ID
getReaction() - The reaction that was added
getEmoji() - The emoji of the reaction
retrieveMessage() - Retrieves the full message (RestAction)
MessageReactionRemoveEvent
Fired when a user removes a reaction from a message.
Package: net.dv8tion.jda.api.events.message.react
@Override
public void onMessageReactionRemove(MessageReactionRemoveEvent event) {
User user = event.getUser();
MessageReaction.ReactionEmoji emoji = event.getReaction().getEmoji();
System.out.println(user.getName() + " removed reaction: " + emoji.getName());
}
MessageReactionRemoveAllEvent
Fired when all reactions are removed from a message.
Package: net.dv8tion.jda.api.events.message.react
@Override
public void onMessageReactionRemoveAll(MessageReactionRemoveAllEvent event) {
long messageId = event.getMessageIdLong();
System.out.println("All reactions removed from message: " + messageId);
}
MessageReactionRemoveEmojiEvent
Fired when all reactions of a specific emoji are removed from a message.
Package: net.dv8tion.jda.api.events.message.react
@Override
public void onMessageReactionRemoveEmoji(MessageReactionRemoveEmojiEvent event) {
MessageReaction.ReactionEmoji emoji = event.getReaction().getEmoji();
long count = event.getReaction().getCount();
System.out.println("All " + emoji.getName() + " reactions removed (" + count + ")");
}
Poll Events
Poll events fire when users vote on message polls.
MessagePollVoteAddEvent
Fired when a user votes in a poll.
Package: net.dv8tion.jda.api.events.message.poll
@Override
public void onMessagePollVoteAdd(MessagePollVoteAddEvent event) {
long answerId = event.getAnswerId();
User user = event.getUser();
System.out.println(user.getName() + " voted for answer: " + answerId);
// Retrieve the message to get poll details
event.retrieveMessage().queue(message -> {
MessagePoll poll = message.getPoll();
if (poll != null) {
System.out.println("Poll: " + poll.getQuestion().getText());
}
});
}
Key Methods:
getAnswerId() - The ID of the poll answer
getUser() - The user who voted
getMessageIdLong() - The message containing the poll
retrieveMessage() - Retrieves the full message
MessagePollVoteRemoveEvent
Fired when a user removes their vote from a poll.
Package: net.dv8tion.jda.api.events.message.poll
@Override
public void onMessagePollVoteRemove(MessagePollVoteRemoveEvent event) {
long answerId = event.getAnswerId();
User user = event.getUser();
System.out.println(user.getName() + " removed vote from answer: " + answerId);
}
Generic Message Events
GenericMessageEvent
Base event for all message-related events.
@Override
public void onGenericMessage(GenericMessageEvent event) {
// Fires for all message events
System.out.println("Message event type: " + event.getClass().getSimpleName());
}
GenericMessageReactionEvent
Base event for all reaction-related events.
@Override
public void onGenericMessageReaction(GenericMessageReactionEvent event) {
// Fires for all reaction events
MessageReaction.ReactionEmoji emoji = event.getReaction().getEmoji();
System.out.println("Reaction event for: " + emoji.getName());
}
GenericMessagePollVoteEvent
Base event for all poll vote events.
@Override
public void onGenericMessagePollVote(GenericMessagePollVoteEvent event) {
// Fires for all poll vote events
System.out.println("Poll vote event for answer: " + event.getAnswerId());
}
Example: Command Handler
Here’s a complete example of a simple command handler using message events:
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
public class CommandHandler extends ListenerAdapter {
private static final String PREFIX = "!";
@Override
public void onMessageReceived(MessageReceivedEvent event) {
// Ignore bots
if (event.getAuthor().isBot()) return;
String content = event.getMessage().getContentRaw();
// Check for prefix
if (!content.startsWith(PREFIX)) return;
// Parse command
String[] parts = content.substring(PREFIX.length()).split("\\s+");
String command = parts[0].toLowerCase();
switch (command) {
case "ping":
event.getChannel().sendMessage("Pong!").queue();
break;
case "info":
event.getChannel().sendMessage(
"Message from: " + event.getAuthor().getAsTag() +
"\nChannel: " + event.getChannel().getName()
).queue();
break;
case "react":
event.getMessage().addReaction(event.getJDA()
.getEmojiById("123456789")).queue();
break;
}
}
}
Tips and Best Practices
-
Cache Messages - Message objects are not cached by default. Use
enableCache(CacheFlag.MESSAGE) if you need to access messages later
-
Check Permissions - Always verify your bot has permission to send messages before responding:
if (event.getGuild().getSelfMember().hasPermission(event.getChannel(), Permission.MESSAGE_SEND)) {
// Send message
}
-
Handle Rate Limits - Use
.queue() instead of .complete() to avoid blocking and handle rate limits gracefully
-
Filter Webhooks - Use
isWebhookMessage() to filter out webhook messages if needed
-
DM vs Guild - Check if
getMember() is null to determine if a message is from a DM