Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Message and Event receivers #345

Merged
merged 9 commits into from
Jan 27, 2022
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import net.dv8tion.jda.api.requests.GatewayIntent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.togetherjava.tjbot.commands.Commands;
import org.togetherjava.tjbot.commands.system.CommandSystem;
import org.togetherjava.tjbot.commands.Features;
import org.togetherjava.tjbot.commands.system.BotCore;
import org.togetherjava.tjbot.config.Config;
import org.togetherjava.tjbot.db.Database;

Expand All @@ -22,7 +22,7 @@
* New commands can be created by implementing
* {@link net.dv8tion.jda.api.events.interaction.SlashCommandEvent} or extending
* {@link org.togetherjava.tjbot.commands.SlashCommandAdapter}. They can then be registered in
* {@link Commands}.
* {@link Features}.
*/
public enum Application {
;
Expand Down Expand Up @@ -79,7 +79,7 @@ public static void runBot(String token, Path databasePath) {
JDA jda = JDABuilder.createDefault(token)
.enableIntents(GatewayIntent.GUILD_MEMBERS)
.build();
jda.addEventListener(new CommandSystem(jda, database));
jda.addEventListener(new BotCore(jda, database));
jda.awaitReady();
logger.info("Bot is ready");

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.togetherjava.tjbot.commands;

import net.dv8tion.jda.api.hooks.EventListener;

/**
* Receives all incoming Discord events, unfiltered. A list of all available event types can be
* found in {@link net.dv8tion.jda.api.hooks.ListenerAdapter}.
*
* If possible, prefer one of the more concrete features instead, such as {@link SlashCommand} or
* {@link MessageReceiver}. Take care to not accidentally implement both, this and one of the other
* {@link Feature}s, as this might result in events being received multiple times.
* <p>
* All event receivers have to implement this interface. A new receiver can then be registered by
* adding it to {@link Features}.
* <p>
* <p>
* After registration, the system will notify a receiver for any incoming Discord event.
*/
@FunctionalInterface
public interface EventReceiver extends EventListener, Feature {
// Basically a renaming of JDAs EventListener, plus our Feature marker interface
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.togetherjava.tjbot.commands;

/**
* Interface for features supported by the bots core system.
* <p>
* New features are added in {@link org.togetherjava.tjbot.commands.Features} and from there picked
* up by {@link org.togetherjava.tjbot.commands.system.BotCore}.
*/
public interface Feature {
// Marker interface
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package org.togetherjava.tjbot.commands;

import net.dv8tion.jda.api.JDA;
import org.jetbrains.annotations.NotNull;
import org.togetherjava.tjbot.commands.basic.PingCommand;
import org.togetherjava.tjbot.commands.basic.VcActivityCommand;
import org.togetherjava.tjbot.commands.free.FreeCommand;
import org.togetherjava.tjbot.commands.mathcommands.TeXCommand;
import org.togetherjava.tjbot.commands.moderation.*;
import org.togetherjava.tjbot.commands.moderation.temp.TemporaryModerationRoutine;
import org.togetherjava.tjbot.commands.system.BotCore;
import org.togetherjava.tjbot.commands.tags.TagCommand;
import org.togetherjava.tjbot.commands.tags.TagManageCommand;
import org.togetherjava.tjbot.commands.tags.TagSystem;
import org.togetherjava.tjbot.commands.tags.TagsCommand;
import org.togetherjava.tjbot.db.Database;
import org.togetherjava.tjbot.routines.ModAuditLogRoutine;

import java.util.ArrayList;
import java.util.Collection;

/**
* Utility class that offers all features that should be registered by the system, such as commands.
* New features have to be added here, where {@link BotCore} will then pick it up from and register
* it with the system.
* <p>
* To add a new slash command, extend the commands returned by
* {@link #createFeatures(JDA, Database)}.
*/
public enum Features {
;

/**
* Creates all features that should be registered with this application.
* <p>
* Calling this method multiple times will result in multiple features being created, which
* generally should be avoided.
*
* @param jda the JDA instance commands will be registered at
* @param database the database of the application, which features can use to persist data
* @return a collection of all features
*/
public static @NotNull Collection<Feature> createFeatures(@NotNull JDA jda,
@NotNull Database database) {
TagSystem tagSystem = new TagSystem(database);
ModerationActionsStore actionsStore = new ModerationActionsStore(database);

// NOTE The system can add special system relevant commands also by itself,
// hence this list may not necessarily represent the full list of all commands actually
// available.
Collection<Feature> features = new ArrayList<>();

// Routines
// TODO This should be moved into some proper command system instead (see GH issue #235
// which adds support for routines)
new ModAuditLogRoutine(jda, database).start();
new TemporaryModerationRoutine(jda, actionsStore).start();

// Message receivers

// Event receivers
features.add(new RejoinMuteListener(actionsStore));

// Slash commands
features.add(new PingCommand());
features.add(new TeXCommand());
features.add(new TagCommand(tagSystem));
features.add(new TagManageCommand(tagSystem));
features.add(new TagsCommand(tagSystem));
features.add(new VcActivityCommand());
features.add(new WarnCommand(actionsStore));
features.add(new KickCommand(actionsStore));
features.add(new BanCommand(actionsStore));
features.add(new UnbanCommand(actionsStore));
features.add(new AuditCommand(actionsStore));
features.add(new MuteCommand(actionsStore));
features.add(new UnmuteCommand(actionsStore));

// Mixtures
features.add(new FreeCommand());

return features;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.togetherjava.tjbot.commands;

import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.api.events.message.guild.GuildMessageUpdateEvent;
import org.jetbrains.annotations.NotNull;

/**
* Receives incoming Discord guild messages.
* <p>
* All message receivers have to implement this interface. For convenience, there is a
* {@link MessageReceiverAdapter} available that implemented most methods already. A new receiver
* can then be registered by adding it to {@link Features}.
* <p>
* <p>
* After registration, the system will notify a receiver whenever a new message was sent or an
* existing message was updated in any of the guilds the bot is added to.
*/
public interface MessageReceiver extends Feature {
/**
* Triggered by the core system whenever a new message was sent in a text channel of a guild the
* bot has been added to.
*
* @param event the event that triggered this, containing information about the corresponding
* message that was sent
*/
void onMessageSent(@NotNull GuildMessageReceivedEvent event);

/**
* Triggered by the core system whenever an existing message was edited in a text channel of a
* guild the bot has been added to.
*
* @param event the event that triggered this, containing information about the corresponding
* message that was edited
*/
void onMessageUpdated(@NotNull GuildMessageUpdateEvent event);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.togetherjava.tjbot.commands;

import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.api.events.message.guild.GuildMessageUpdateEvent;
import org.jetbrains.annotations.NotNull;

/**
* Adapter implementation of a {@link MessageReceiver}. A new receiver can then be registered by
* adding it to {@link Features}.
* <p>
* {@link #onMessageSent(GuildMessageReceivedEvent)} and
* {@link #onMessageUpdated(GuildMessageUpdateEvent)} can be overridden if desired. The default
* implementation is empty, the adapter will not react to such events.
*/
public abstract class MessageReceiverAdapter implements MessageReceiver {

@SuppressWarnings("NoopMethodInAbstractClass")
@Override
public void onMessageSent(@NotNull GuildMessageReceivedEvent event) {
// Adapter does not react by default, subclasses may change this behavior
}

@SuppressWarnings("NoopMethodInAbstractClass")
@Override
public void onMessageUpdated(@NotNull GuildMessageUpdateEvent event) {
// Adapter does not react by default, subclasses may change this behavior
}
}
Loading