Implement scheduled tasks
This commit is contained in:
1 parent
78a149b546
commit
78002d9299
42 files changed
+403
-283
No files matched your search
@@ -4,6 +4,7 @@ NETNEUTRALITY_BOT_ENV=dev
|
|||||||
NETNEUTRALITY_BOT_TOKEN=
|
NETNEUTRALITY_BOT_TOKEN=
|
||||||
NETNEUTRALITY_BOT_PREFIX=$
|
NETNEUTRALITY_BOT_PREFIX=$
|
||||||
NETNEUTRALITY_BOT_OWNER=
|
NETNEUTRALITY_BOT_OWNER=
|
||||||
|
NETNEUTRALITY_BOT_INVITE=
|
||||||
NETNEUTRALITY_API_PORT=9000
|
NETNEUTRALITY_API_PORT=9000
|
||||||
|
|
||||||
MYSQL_HOST=127.0.0.1
|
MYSQL_HOST=127.0.0.1
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ NETNEUTRALITY_BOT_ENV=dev
|
|||||||
NETNEUTRALITY_BOT_TOKEN=
|
NETNEUTRALITY_BOT_TOKEN=
|
||||||
NETNEUTRALITY_BOT_PREFIX=
|
NETNEUTRALITY_BOT_PREFIX=
|
||||||
NETNEUTRALITY_BOT_OWNER=
|
NETNEUTRALITY_BOT_OWNER=
|
||||||
|
NETNEUTRALITY_BOT_INVITE=
|
||||||
NETNEUTRALITY_API_PORT=9000
|
NETNEUTRALITY_API_PORT=9000
|
||||||
|
|
||||||
MYSQL_HOST=127.0.0.1
|
MYSQL_HOST=127.0.0.1
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
services:
|
|
||||||
db:
|
|
||||||
image: mariadb:lts@sha256:4b1e7958f820681b1b93b9cf9ea05a76e0785da12699a1fb1d05e0eb2137e56b
|
|
||||||
container_name: db
|
|
||||||
restart: unless-stopped
|
|
||||||
volumes:
|
|
||||||
- netneutrality-db:/var/lib/mysql
|
|
||||||
- ./sql:/docker-entrypoint-initdb.d
|
|
||||||
environment:
|
|
||||||
MYSQL_USER: 'java'
|
|
||||||
MYSQL_PASSWORD: 'password'
|
|
||||||
MYSQL_DATABASE: 'netneutrality'
|
|
||||||
MYSQL_ROOT_PASSWORD: 'password'
|
|
||||||
MARIADB_AUTO_UPGRADE: '1'
|
|
||||||
ports:
|
|
||||||
- "3306"
|
|
||||||
networks:
|
|
||||||
- internal
|
|
||||||
|
|
||||||
bot:
|
|
||||||
container_name: bot
|
|
||||||
build: ./
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
- db
|
|
||||||
volumes:
|
|
||||||
- ./logs:/app/logs
|
|
||||||
environment:
|
|
||||||
MYSQL_HOST: 'db'
|
|
||||||
MYSQL_USER: 'java'
|
|
||||||
MYSQL_PASSWORD: 'password'
|
|
||||||
MYSQL_DATABASE: 'netneutrality'
|
|
||||||
ports:
|
|
||||||
- "9000:9000"
|
|
||||||
networks:
|
|
||||||
- internal
|
|
||||||
|
|
||||||
webapp:
|
|
||||||
image: bot-webapp:dev
|
|
||||||
build: ../netneutrality-webapp
|
|
||||||
restart: always
|
|
||||||
depends_on:
|
|
||||||
- db
|
|
||||||
- bot
|
|
||||||
volumes:
|
|
||||||
- ./logs:/app/logs
|
|
||||||
environment:
|
|
||||||
DB_CONNECTION: 'mysql'
|
|
||||||
DB_HOST: 'db'
|
|
||||||
DB_PORT: '3306'
|
|
||||||
DB_DATABASE: 'netneutrality'
|
|
||||||
DB_USERNAME: 'java'
|
|
||||||
DB_PASSWORD: 'password'
|
|
||||||
BOT_URL: 'http://bot:9000'
|
|
||||||
ports:
|
|
||||||
- '8080:80'
|
|
||||||
networks:
|
|
||||||
- internal
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
netneutrality-db:
|
|
||||||
|
|
||||||
networks:
|
|
||||||
internal:
|
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
services:
|
services:
|
||||||
netneutrality-db:
|
netneutrality-db:
|
||||||
image: mariadb:lts@sha256:4b1e7958f820681b1b93b9cf9ea05a76e0785da12699a1fb1d05e0eb2137e56b
|
image: mariadb:11
|
||||||
container_name: db
|
container_name: db
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
networks:
|
networks:
|
||||||
|
|||||||
@@ -259,11 +259,6 @@
|
|||||||
<artifactId>commons-lang3</artifactId>
|
<artifactId>commons-lang3</artifactId>
|
||||||
<version>3.17.0</version>
|
<version>3.17.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>commons-codec</groupId>
|
|
||||||
<artifactId>commons-codec</artifactId>
|
|
||||||
<version>1.18.0</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-io</groupId>
|
<groupId>commons-io</groupId>
|
||||||
<artifactId>commons-io</artifactId>
|
<artifactId>commons-io</artifactId>
|
||||||
|
|||||||
+9
-1
@@ -9,7 +9,15 @@
|
|||||||
{
|
{
|
||||||
"groupName": "hibernate orm",
|
"groupName": "hibernate orm",
|
||||||
"matchPackageNames": [
|
"matchPackageNames": [
|
||||||
"org.hibernate.orm:**"
|
"org.hibernate.orm:**",
|
||||||
|
"com.mysql:**"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"groupName": "apache commons",
|
||||||
|
"matchPackageNames": [
|
||||||
|
"commons:**",
|
||||||
|
"org.apache.commons:**"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ import me.bobert.netneutrality.core.command.CommandManager;
|
|||||||
import me.bobert.netneutrality.core.db.DatabaseMigration;
|
import me.bobert.netneutrality.core.db.DatabaseMigration;
|
||||||
import me.bobert.netneutrality.core.db.SessionManager;
|
import me.bobert.netneutrality.core.db.SessionManager;
|
||||||
import me.bobert.netneutrality.core.tasks.TaskManager;
|
import me.bobert.netneutrality.core.tasks.TaskManager;
|
||||||
|
import me.bobert.netneutrality.core.thread.ScheduledTaskManager;
|
||||||
import me.bobert.netneutrality.core.thread.ThreadManager;
|
import me.bobert.netneutrality.core.thread.ThreadManager;
|
||||||
import me.bobert.netneutrality.hooks.EventsHandler;
|
import me.bobert.netneutrality.hooks.EventsHandler;
|
||||||
import me.bobert.netneutrality.http.server.WebApi;
|
import me.bobert.netneutrality.http.server.WebApi;
|
||||||
import me.bobert.netneutrality.music.MusicManager;
|
import me.bobert.netneutrality.music.MusicManager;
|
||||||
import me.bobert.netneutrality.thread.ShutdownThread;
|
|
||||||
import me.bobert.netneutrality.utils.Settings;
|
import me.bobert.netneutrality.utils.Settings;
|
||||||
import net.dv8tion.jda.api.JDA;
|
import net.dv8tion.jda.api.JDA;
|
||||||
import net.dv8tion.jda.api.JDABuilder;
|
import net.dv8tion.jda.api.JDABuilder;
|
||||||
@@ -79,7 +79,7 @@ public class NetNeutrality {
|
|||||||
new WebApi(Integer.parseInt(Settings.getInstance().get("NETNEUTRALITY_API_PORT", "9000")));
|
new WebApi(Integer.parseInt(Settings.getInstance().get("NETNEUTRALITY_API_PORT", "9000")));
|
||||||
jda.getPresence().setActivity(Activity.watching("you"));
|
jda.getPresence().setActivity(Activity.watching("you"));
|
||||||
|
|
||||||
Runtime.getRuntime().addShutdownHook(new ShutdownThread(this));
|
Runtime.getRuntime().addShutdownHook(new Thread(this::shutdown));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NetNeutrality getInstance() {
|
public static NetNeutrality getInstance() {
|
||||||
@@ -108,6 +108,7 @@ public class NetNeutrality {
|
|||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
System.out.println("[Net Neutrality] Shutting down...");
|
System.out.println("[Net Neutrality] Shutting down...");
|
||||||
|
ScheduledTaskManager.cancelAll();
|
||||||
MusicManager.disconnectPlayers();
|
MusicManager.disconnectPlayers();
|
||||||
ThreadManager.shutdownExecutor();
|
ThreadManager.shutdownExecutor();
|
||||||
disconnect();
|
disconnect();
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import me.bobert.netneutrality.core.command.CommandOptionsBuilder;
|
|||||||
import me.bobert.netneutrality.core.command.impl.AbstractCommand;
|
import me.bobert.netneutrality.core.command.impl.AbstractCommand;
|
||||||
import me.bobert.netneutrality.core.command.options.CommandOption;
|
import me.bobert.netneutrality.core.command.options.CommandOption;
|
||||||
import me.bobert.netneutrality.core.context.CommandContext;
|
import me.bobert.netneutrality.core.context.CommandContext;
|
||||||
import me.bobert.netneutrality.core.tasks.BuiltInTask;
|
import me.bobert.netneutrality.core.tasks.Task;
|
||||||
import me.bobert.netneutrality.tasks.help.BotInfo;
|
import me.bobert.netneutrality.tasks.help.BotInfo;
|
||||||
import me.bobert.netneutrality.tasks.help.CommandHelp;
|
import me.bobert.netneutrality.tasks.help.CommandHelp;
|
||||||
import me.bobert.netneutrality.tasks.help.ReportBug;
|
import me.bobert.netneutrality.tasks.help.ReportBug;
|
||||||
@@ -65,9 +65,9 @@ public class HelpCommand extends AbstractCommand {
|
|||||||
public CommandExecutionResult execute(CommandContext context) {
|
public CommandExecutionResult execute(CommandContext context) {
|
||||||
String command = context.getOption("command", null, CommandOption::getAsString);
|
String command = context.getOption("command", null, CommandOption::getAsString);
|
||||||
if (command == null) {
|
if (command == null) {
|
||||||
Button commands = BuiltInTask.createButton(CommandHelp.class);
|
Button commands = Task.createButton(CommandHelp.class);
|
||||||
Button info = BuiltInTask.createButton(BotInfo.class);
|
Button info = Task.createButton(BotInfo.class);
|
||||||
Button reportbug = BuiltInTask.createButton(ReportBug.class);
|
Button reportbug = Task.createButton(ReportBug.class);
|
||||||
ActionRow row = ActionRow.of(commands, info, reportbug);
|
ActionRow row = ActionRow.of(commands, info, reportbug);
|
||||||
context.replyEphemeral("Thanks for using the Net Neutrality Bot! What do you need help with?", List.of(row));
|
context.replyEphemeral("Thanks for using the Net Neutrality Bot! What do you need help with?", List.of(row));
|
||||||
return CommandExecutionResult.none();
|
return CommandExecutionResult.none();
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package me.bobert.netneutrality.core.command;
|
|||||||
* https://discord.gg/qUa6zNFZsd
|
* https://discord.gg/qUa6zNFZsd
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import me.bobert.netneutrality.utils.ReflectionHelper;
|
||||||
import net.dv8tion.jda.api.JDA;
|
import net.dv8tion.jda.api.JDA;
|
||||||
import net.dv8tion.jda.api.interactions.InteractionContextType;
|
import net.dv8tion.jda.api.interactions.InteractionContextType;
|
||||||
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
|
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
|
||||||
@@ -12,9 +13,7 @@ import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
|||||||
import net.dv8tion.jda.api.requests.restaction.CommandListUpdateAction;
|
import net.dv8tion.jda.api.requests.restaction.CommandListUpdateAction;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.reflections.Reflections;
|
|
||||||
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -39,34 +38,27 @@ public class CommandManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void initCommands() {
|
public static void initCommands() {
|
||||||
Set<Class<? extends Command>> classes = new Reflections("me.bobert.netneutrality.command").getSubTypesOf(Command.class);
|
ReflectionHelper.loadCommands(Command.class, command -> {
|
||||||
for (Class<? extends Command> s : classes) {
|
if (!command.isEnabled()) {
|
||||||
try {
|
logger.info("Skipping command {} as it is disabled", command.getClass().getName());
|
||||||
if (Modifier.isAbstract(s.getModifiers())) {
|
return;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Command command = s.getConstructor().newInstance();
|
|
||||||
if (!command.isEnabled()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command.getCommandName() == null) {
|
|
||||||
throw new IllegalArgumentException("Command name is null");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command.getDescription() == null && command.getType() == Command.Type.SLASH) {
|
|
||||||
throw new IllegalArgumentException("Command description is null");
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandContainer container = new CommandContainer(command);
|
|
||||||
if (!commands.containsKey(command.getCommandName())) {
|
|
||||||
commands.put(command.getCommandName(), container);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("Failed to load command {}: {}", s.getSimpleName(), e.getMessage());
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (command.getCommandName() == null) {
|
||||||
|
logger.error("Failed to load command {}: Command name is null", command.getClass().getName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command.getDescription() == null && command.getType() == Command.Type.SLASH) {
|
||||||
|
logger.error("Failed to load command {}: Command description is null", command.getClass().getName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandContainer container = new CommandContainer(command);
|
||||||
|
if (!commands.containsKey(command.getCommandName())) {
|
||||||
|
commands.put(command.getCommandName(), container);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void registerSlashCommands(JDA jda) {
|
public static void registerSlashCommands(JDA jda) {
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public class CommandProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
logger.info("Context ID: {}", context.getId());
|
logger.debug("Context ID: {}", context.getId());
|
||||||
logger.info("Executing command {} on guild {}", command.getCommandName(), context.getGuild() == null ? "PrivateMessage" : context.getGuild().getId());
|
logger.info("Executing command {} on guild {}", command.getCommandName(), context.getGuild() == null ? "PrivateMessage" : context.getGuild().getId());
|
||||||
configureSentry(command);
|
configureSentry(command);
|
||||||
|
|
||||||
|
|||||||
@@ -151,6 +151,10 @@ public interface Context {
|
|||||||
replyEphemeralWithLimit(message);
|
replyEphemeralWithLimit(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default void replyEphemeral(String message, LayoutComponent component) {
|
||||||
|
replyEphemeral(message, List.of(component));
|
||||||
|
}
|
||||||
|
|
||||||
default void replyEphemeral(String message, List<LayoutComponent> components) {
|
default void replyEphemeral(String message, List<LayoutComponent> components) {
|
||||||
replyEphemeral(MessageCreateData.fromContent(message), components);
|
replyEphemeral(MessageCreateData.fromContent(message), components);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ package me.bobert.netneutrality.core.tasks;
|
|||||||
* https://discord.gg/qUa6zNFZsd
|
* https://discord.gg/qUa6zNFZsd
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
import me.bobert.netneutrality.core.context.TaskContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a task that has a known ID and is loaded at runtime.
|
* Represents a task that has a known ID and is loaded at runtime.
|
||||||
@@ -13,13 +13,5 @@ import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
|||||||
*/
|
*/
|
||||||
public interface BuiltInTask extends Task {
|
public interface BuiltInTask extends Task {
|
||||||
|
|
||||||
static Button createButton(Class<? extends BuiltInTask> clazz) {
|
void executeTask(TaskContext context);
|
||||||
BuiltInTask builtInTask = TaskManager.getInstance().findBuiltInTaskByClass(clazz);
|
|
||||||
|
|
||||||
if (builtInTask == null) {
|
|
||||||
throw new IllegalArgumentException("Task class " + clazz.getName() + " was not registered by the task manager.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return builtInTask.createButton();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package me.bobert.netneutrality.core.tasks;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) anthorob
|
||||||
|
*
|
||||||
|
* https://discord.gg/qUa6zNFZsd
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public interface ScheduledTask {
|
||||||
|
|
||||||
|
class TimeFrame {
|
||||||
|
private final int interval;
|
||||||
|
private final TimeUnit unit;
|
||||||
|
|
||||||
|
private TimeFrame(int interval, TimeUnit unit) {
|
||||||
|
this.interval = interval;
|
||||||
|
this.unit = unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TimeFrame minutely() {
|
||||||
|
return new TimeFrame(1, TimeUnit.MINUTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TimeFrame minutely(int interval) {
|
||||||
|
return new TimeFrame(interval, TimeUnit.MINUTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TimeFrame hourly() {
|
||||||
|
return new TimeFrame(1, TimeUnit.HOURS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TimeFrame hourly(int interval) {
|
||||||
|
return new TimeFrame(interval, TimeUnit.HOURS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TimeFrame daily() {
|
||||||
|
return new TimeFrame(1, TimeUnit.DAYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TimeFrame daily(int interval) {
|
||||||
|
return new TimeFrame(interval, TimeUnit.DAYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TimeFrame custom(int interval, TimeUnit unit) {
|
||||||
|
return new TimeFrame(interval, unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getInterval() {
|
||||||
|
return interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TimeUnit getUnit() {
|
||||||
|
return unit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String getId();
|
||||||
|
|
||||||
|
TimeFrame getTimeFrame();
|
||||||
|
|
||||||
|
void run();
|
||||||
|
}
|
||||||
+1
-1
@@ -6,7 +6,7 @@ package me.bobert.netneutrality.core.tasks;
|
|||||||
* https://discord.gg/qUa6zNFZsd
|
* https://discord.gg/qUa6zNFZsd
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public interface IStepTask {
|
public interface StepTask {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the type of input expected for a step.
|
* Defines the type of input expected for a step.
|
||||||
@@ -7,6 +7,7 @@ package me.bobert.netneutrality.core.tasks;
|
|||||||
|
|
||||||
import me.bobert.netneutrality.core.context.CommandContext;
|
import me.bobert.netneutrality.core.context.CommandContext;
|
||||||
import me.bobert.netneutrality.core.context.TaskContext;
|
import me.bobert.netneutrality.core.context.TaskContext;
|
||||||
|
import me.bobert.netneutrality.core.tasks.trait.WithButton;
|
||||||
import me.bobert.netneutrality.core.tasks.trait.WithChildren;
|
import me.bobert.netneutrality.core.tasks.trait.WithChildren;
|
||||||
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
||||||
|
|
||||||
@@ -64,8 +65,6 @@ public interface Task {
|
|||||||
|
|
||||||
OffsetDateTime getCreationTime();
|
OffsetDateTime getCreationTime();
|
||||||
|
|
||||||
Button createButton();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>This method is used to reply to the interaction that triggered this task.</p>
|
* <p>This method is used to reply to the interaction that triggered this task.</p>
|
||||||
* <p>If the task is implementing {@link WithChildren}, the child tasks must be instanciated in this method.</p>
|
* <p>If the task is implementing {@link WithChildren}, the child tasks must be instanciated in this method.</p>
|
||||||
@@ -80,4 +79,14 @@ public interface Task {
|
|||||||
Lifecycle execute(TaskContext context);
|
Lifecycle execute(TaskContext context);
|
||||||
|
|
||||||
void insert(CommandContext context);
|
void insert(CommandContext context);
|
||||||
|
|
||||||
|
static Button createButton(Class<? extends WithButton> clazz) {
|
||||||
|
WithButton withButton = TaskManager.getInstance().findButtonTaskByClass(clazz);
|
||||||
|
|
||||||
|
if (withButton == null) {
|
||||||
|
throw new IllegalArgumentException("Task " + clazz.getName() + " was not registered by the task manager.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return withButton.createButton();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -11,28 +11,24 @@ import me.bobert.netneutrality.core.context.InteractionContext;
|
|||||||
import me.bobert.netneutrality.core.context.TaskContext;
|
import me.bobert.netneutrality.core.context.TaskContext;
|
||||||
import me.bobert.netneutrality.core.tasks.trait.Deletable;
|
import me.bobert.netneutrality.core.tasks.trait.Deletable;
|
||||||
import me.bobert.netneutrality.core.tasks.trait.NotAcknowledgeable;
|
import me.bobert.netneutrality.core.tasks.trait.NotAcknowledgeable;
|
||||||
|
import me.bobert.netneutrality.core.tasks.trait.WithButton;
|
||||||
import me.bobert.netneutrality.core.tasks.trait.WithChildren;
|
import me.bobert.netneutrality.core.tasks.trait.WithChildren;
|
||||||
import me.bobert.netneutrality.core.tasks.trait.WithParent;
|
import me.bobert.netneutrality.core.tasks.trait.WithParent;
|
||||||
import me.bobert.netneutrality.core.thread.ThreadManager;
|
import me.bobert.netneutrality.core.thread.ScheduledTaskManager;
|
||||||
import me.bobert.netneutrality.db.service.TaskService;
|
import me.bobert.netneutrality.db.service.TaskService;
|
||||||
import me.bobert.netneutrality.exceptions.GracefulContextError;
|
import me.bobert.netneutrality.exceptions.GracefulContextError;
|
||||||
import me.bobert.netneutrality.exceptions.TaskExecutionException;
|
import me.bobert.netneutrality.exceptions.TaskExecutionException;
|
||||||
import me.bobert.netneutrality.thread.CleanupTaskThread;
|
import me.bobert.netneutrality.utils.ReflectionHelper;
|
||||||
import net.dv8tion.jda.api.interactions.InteractionHook;
|
import net.dv8tion.jda.api.interactions.InteractionHook;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.reflections.Reflections;
|
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@@ -63,12 +59,11 @@ public class TaskManager {
|
|||||||
|
|
||||||
public void init() {
|
public void init() {
|
||||||
loadBuiltInTasks();
|
loadBuiltInTasks();
|
||||||
|
loadScheduledTasks();
|
||||||
taskService.loadTasks();
|
taskService.loadTasks();
|
||||||
|
|
||||||
ThreadManager.getScheduledExecutor().scheduleWithFixedDelay(new CleanupTaskThread(), 1, 5, TimeUnit.MINUTES);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TaskService getTaskService() {
|
public TaskService getTaskService() {
|
||||||
return taskService;
|
return taskService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +96,7 @@ public class TaskManager {
|
|||||||
taskService.persistTask(persistableTask);
|
taskService.persistTask(persistableTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task instanceof IStepTask) {
|
if (task instanceof StepTask) {
|
||||||
pendingTasks.add(task);
|
pendingTasks.add(task);
|
||||||
} else {
|
} else {
|
||||||
tasks.put(id, task);
|
tasks.put(id, task);
|
||||||
@@ -176,7 +171,7 @@ public class TaskManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug("Executing task: {}", taskId);
|
logger.info("Executing task: {}", taskId);
|
||||||
Task.Lifecycle status = task.execute(context);
|
Task.Lifecycle status = task.execute(context);
|
||||||
handleTaskLifecycle(task, status);
|
handleTaskLifecycle(task, status);
|
||||||
|
|
||||||
@@ -205,7 +200,7 @@ public class TaskManager {
|
|||||||
|
|
||||||
public <E extends Task> Optional<E> findTaskByPartialId(Class<E> clazz, String partialId) {
|
public <E extends Task> Optional<E> findTaskByPartialId(Class<E> clazz, String partialId) {
|
||||||
List<E> tasks = findTasksByPartialId(clazz, partialId);
|
List<E> tasks = findTasksByPartialId(clazz, partialId);
|
||||||
return Optional.ofNullable(tasks.isEmpty() ? null : tasks.get(0));
|
return Optional.ofNullable(tasks.isEmpty() ? null : tasks.getFirst());
|
||||||
}
|
}
|
||||||
|
|
||||||
public <E extends Task> List<E> findTasksByPartialId(Class<E> clazz, String partialId) {
|
public <E extends Task> List<E> findTasksByPartialId(Class<E> clazz, String partialId) {
|
||||||
@@ -216,10 +211,10 @@ public class TaskManager {
|
|||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public BuiltInTask findBuiltInTaskByClass(Class<? extends BuiltInTask> clazz) {
|
public WithButton findButtonTaskByClass(Class<? extends WithButton> clazz) {
|
||||||
return tasks.values().stream()
|
return tasks.values().stream()
|
||||||
.filter(clazz::isInstance)
|
.filter(clazz::isInstance)
|
||||||
.map(task -> (BuiltInTask) task)
|
.map(task -> (WithButton) task)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
}
|
}
|
||||||
@@ -237,22 +232,27 @@ public class TaskManager {
|
|||||||
private void loadBuiltInTasks() {
|
private void loadBuiltInTasks() {
|
||||||
logger.info("Loading built-in tasks...");
|
logger.info("Loading built-in tasks...");
|
||||||
|
|
||||||
Set<Class<? extends BuiltInTask>> classes = new Reflections("me.bobert.netneutrality.tasks").getSubTypesOf(BuiltInTask.class);
|
ReflectionHelper.loadTasks(BuiltInTask.class, builtInTask -> {
|
||||||
for (Class<? extends BuiltInTask> s : classes) {
|
if (builtInTask.isInsertable()) {
|
||||||
try {
|
logger.info("Loaded task: {}", builtInTask.getClass().getName());
|
||||||
if (Modifier.isAbstract(s.getModifiers())) {
|
tasks.put(builtInTask.getId(), builtInTask);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
BuiltInTask task = s.getConstructor().newInstance();
|
|
||||||
|
|
||||||
logger.info("Loaded task: {}", task);
|
|
||||||
tasks.put(task.getId(), task);
|
|
||||||
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
|
|
||||||
| InvocationTargetException | NoSuchMethodException | SecurityException e) {
|
|
||||||
logger.error("Failed to instantiate built-in task", e);
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadScheduledTasks() {
|
||||||
|
logger.info("Loading scheduled tasks...");
|
||||||
|
|
||||||
|
ReflectionHelper.loadTasks(ScheduledTask.class, scheduledTask -> {
|
||||||
|
String taskId = scheduledTask.getId();
|
||||||
|
|
||||||
|
if (taskId == null || taskId.trim().isEmpty()) {
|
||||||
|
logger.error("Cannot load scheduled task {}: task ID is null or empty", scheduledTask.getClass().getName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScheduledTaskManager.schedule(scheduledTask);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteInteraction(Task task) {
|
private void deleteInteraction(Task task) {
|
||||||
|
|||||||
+2
-3
@@ -1,4 +1,4 @@
|
|||||||
package me.bobert.netneutrality.core.tasks;
|
package me.bobert.netneutrality.core.tasks.impl;
|
||||||
/*
|
/*
|
||||||
* Copyright (c) anthorob
|
* Copyright (c) anthorob
|
||||||
*
|
*
|
||||||
@@ -7,6 +7,7 @@ package me.bobert.netneutrality.core.tasks;
|
|||||||
|
|
||||||
import me.bobert.netneutrality.core.context.CommandContext;
|
import me.bobert.netneutrality.core.context.CommandContext;
|
||||||
import me.bobert.netneutrality.core.context.TaskContext;
|
import me.bobert.netneutrality.core.context.TaskContext;
|
||||||
|
import me.bobert.netneutrality.core.tasks.BuiltInTask;
|
||||||
|
|
||||||
public abstract class AbstractBuiltInTask extends AbstractTask implements BuiltInTask {
|
public abstract class AbstractBuiltInTask extends AbstractTask implements BuiltInTask {
|
||||||
|
|
||||||
@@ -35,6 +36,4 @@ public abstract class AbstractBuiltInTask extends AbstractTask implements BuiltI
|
|||||||
executeTask(context);
|
executeTask(context);
|
||||||
return Lifecycle.BUILTIN;
|
return Lifecycle.BUILTIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void executeTask(TaskContext context);
|
|
||||||
}
|
}
|
||||||
+3
-1
@@ -1,4 +1,4 @@
|
|||||||
package me.bobert.netneutrality.core.tasks;
|
package me.bobert.netneutrality.core.tasks.impl;
|
||||||
/*
|
/*
|
||||||
* Copyright (c) anthorob
|
* Copyright (c) anthorob
|
||||||
*
|
*
|
||||||
@@ -6,6 +6,8 @@ package me.bobert.netneutrality.core.tasks;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import me.bobert.netneutrality.core.context.CommandContext;
|
import me.bobert.netneutrality.core.context.CommandContext;
|
||||||
|
import me.bobert.netneutrality.core.tasks.PersistableTask;
|
||||||
|
import me.bobert.netneutrality.core.tasks.TaskManager;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public abstract class AbstractPersistableTask extends AbstractTask implements PersistableTask {
|
public abstract class AbstractPersistableTask extends AbstractTask implements PersistableTask {
|
||||||
+2
-9
@@ -9,13 +9,11 @@ package me.bobert.netneutrality.core.tasks.impl;
|
|||||||
import me.bobert.netneutrality.core.context.CommandContext;
|
import me.bobert.netneutrality.core.context.CommandContext;
|
||||||
import me.bobert.netneutrality.core.context.MessageContext;
|
import me.bobert.netneutrality.core.context.MessageContext;
|
||||||
import me.bobert.netneutrality.core.context.TaskContext;
|
import me.bobert.netneutrality.core.context.TaskContext;
|
||||||
import me.bobert.netneutrality.core.tasks.AbstractTask;
|
import me.bobert.netneutrality.core.tasks.StepTask;
|
||||||
import me.bobert.netneutrality.core.tasks.IStepTask;
|
|
||||||
import me.bobert.netneutrality.core.tasks.TaskManager;
|
import me.bobert.netneutrality.core.tasks.TaskManager;
|
||||||
import net.dv8tion.jda.api.entities.Guild;
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
import net.dv8tion.jda.api.entities.Message;
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
import net.dv8tion.jda.api.entities.Role;
|
import net.dv8tion.jda.api.entities.Role;
|
||||||
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
|
||||||
import net.fellbaum.jemoji.Emoji;
|
import net.fellbaum.jemoji.Emoji;
|
||||||
import net.fellbaum.jemoji.EmojiManager;
|
import net.fellbaum.jemoji.EmojiManager;
|
||||||
|
|
||||||
@@ -27,7 +25,7 @@ import java.util.UUID;
|
|||||||
* Represents a task that consists of multiple sequential steps. The task starts with an initial message (question)
|
* Represents a task that consists of multiple sequential steps. The task starts with an initial message (question)
|
||||||
* and expects a user response. Each step can lead to another step, forming a workflow.
|
* and expects a user response. Each step can lead to another step, forming a workflow.
|
||||||
*/
|
*/
|
||||||
public abstract class StepTask extends AbstractTask implements IStepTask {
|
public abstract class AbstractStepTask extends AbstractTask implements StepTask {
|
||||||
private final Object stepLock = new Object();
|
private final Object stepLock = new Object();
|
||||||
private CommandContext commandContext;
|
private CommandContext commandContext;
|
||||||
private Guild guild;
|
private Guild guild;
|
||||||
@@ -110,11 +108,6 @@ public abstract class StepTask extends AbstractTask implements IStepTask {
|
|||||||
return getCreationTime().plusMinutes(60).isBefore(OffsetDateTime.now());
|
return getCreationTime().plusMinutes(60).isBefore(OffsetDateTime.now());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Button createButton() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates the user input against the expected step type.
|
* Validates the user input against the expected step type.
|
||||||
*
|
*
|
||||||
+3
-1
@@ -1,4 +1,4 @@
|
|||||||
package me.bobert.netneutrality.core.tasks;
|
package me.bobert.netneutrality.core.tasks.impl;
|
||||||
/*
|
/*
|
||||||
* Copyright (c) anthorob
|
* Copyright (c) anthorob
|
||||||
*
|
*
|
||||||
@@ -6,6 +6,8 @@ package me.bobert.netneutrality.core.tasks;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import me.bobert.netneutrality.core.context.CommandContext;
|
import me.bobert.netneutrality.core.context.CommandContext;
|
||||||
|
import me.bobert.netneutrality.core.tasks.Task;
|
||||||
|
import me.bobert.netneutrality.core.tasks.TaskManager;
|
||||||
|
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@@ -5,49 +5,40 @@ package me.bobert.netneutrality.core.tasks.impl;
|
|||||||
* https://discord.gg/qUa6zNFZsd
|
* https://discord.gg/qUa6zNFZsd
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import me.bobert.netneutrality.core.tasks.GenericRandomIdTask;
|
|
||||||
import me.bobert.netneutrality.core.tasks.Task;
|
import me.bobert.netneutrality.core.tasks.Task;
|
||||||
import me.bobert.netneutrality.core.tasks.trait.WithChildren;
|
import me.bobert.netneutrality.core.tasks.trait.WithButton;
|
||||||
import net.dv8tion.jda.api.interactions.components.ActionRow;
|
import net.dv8tion.jda.api.entities.emoji.Emoji;
|
||||||
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
||||||
import net.dv8tion.jda.api.interactions.components.buttons.ButtonStyle;
|
import net.dv8tion.jda.api.interactions.components.buttons.ButtonStyle;
|
||||||
|
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public abstract class ButtonTask extends GenericRandomIdTask {
|
public abstract class ButtonTask extends GenericRandomIdTask implements WithButton {
|
||||||
private final ButtonStyle buttonStyle;
|
private final ButtonStyle buttonStyle;
|
||||||
private final String buttonLabel;
|
private final String buttonLabel;
|
||||||
|
private Emoji emoji;
|
||||||
|
|
||||||
public ButtonTask(ButtonStyle buttonStyle, String buttonLabel) {
|
public ButtonTask(ButtonStyle buttonStyle, String buttonLabel) {
|
||||||
this.buttonStyle = buttonStyle;
|
this.buttonStyle = buttonStyle;
|
||||||
this.buttonLabel = buttonLabel;
|
this.buttonLabel = buttonLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task setEmoji(Emoji emoji) {
|
||||||
|
this.emoji = emoji;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Button createButton() {
|
public Button createButton() {
|
||||||
if (buttonStyle == null || buttonLabel == null) {
|
if (buttonStyle == null || buttonLabel == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Button.of(buttonStyle, getId(), buttonLabel);
|
return Button.of(buttonStyle, getId(), buttonLabel, emoji);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isExpired() {
|
public boolean isExpired() {
|
||||||
return getCreationTime().plusMinutes(15).isBefore(OffsetDateTime.now());
|
return getCreationTime().plusMinutes(15).isBefore(OffsetDateTime.now());
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionRow createActionRow(List<Task> tasks) {
|
|
||||||
ActionRow row = ActionRow.of(tasks.stream().map(Task::createButton).toList());
|
|
||||||
if (this instanceof WithChildren parent) {
|
|
||||||
parent.addChild(tasks);
|
|
||||||
}
|
|
||||||
|
|
||||||
return row;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ActionRow createActionRow(Task... tasks) {
|
|
||||||
return createActionRow(List.of(tasks));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -6,8 +6,6 @@ package me.bobert.netneutrality.core.tasks.impl;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import me.bobert.netneutrality.context.tasks.EmojiTaskContext;
|
import me.bobert.netneutrality.context.tasks.EmojiTaskContext;
|
||||||
import me.bobert.netneutrality.core.tasks.AbstractPersistableTask;
|
|
||||||
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
@@ -54,9 +52,4 @@ public abstract class EmojiTask extends AbstractPersistableTask {
|
|||||||
public String getId() {
|
public String getId() {
|
||||||
return String.format(EmojiTaskContext.ID, getGuildId(), getMessageId());
|
return String.format(EmojiTaskContext.ID, getGuildId(), getMessageId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Button createButton() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+1
-8
@@ -1,4 +1,4 @@
|
|||||||
package me.bobert.netneutrality.core.tasks;
|
package me.bobert.netneutrality.core.tasks.impl;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) anthorob
|
* Copyright (c) anthorob
|
||||||
@@ -6,8 +6,6 @@ package me.bobert.netneutrality.core.tasks;
|
|||||||
* https://discord.gg/qUa6zNFZsd
|
* https://discord.gg/qUa6zNFZsd
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
|
||||||
|
|
||||||
public abstract class GenericCustomIdTask extends AbstractTask {
|
public abstract class GenericCustomIdTask extends AbstractTask {
|
||||||
private final String customId;
|
private final String customId;
|
||||||
|
|
||||||
@@ -19,9 +17,4 @@ public abstract class GenericCustomIdTask extends AbstractTask {
|
|||||||
public String getId() {
|
public String getId() {
|
||||||
return customId;
|
return customId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Button createButton() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package me.bobert.netneutrality.core.tasks;
|
package me.bobert.netneutrality.core.tasks.impl;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) anthorob
|
* Copyright (c) anthorob
|
||||||
@@ -6,7 +6,6 @@ package me.bobert.netneutrality.core.tasks.impl;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import me.bobert.netneutrality.core.context.TaskContext;
|
import me.bobert.netneutrality.core.context.TaskContext;
|
||||||
import me.bobert.netneutrality.core.tasks.GenericRandomIdTask;
|
|
||||||
import net.dv8tion.jda.api.interactions.modals.ModalMapping;
|
import net.dv8tion.jda.api.interactions.modals.ModalMapping;
|
||||||
|
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package me.bobert.netneutrality.core.tasks.trait;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) anthorob
|
||||||
|
*
|
||||||
|
* https://discord.gg/qUa6zNFZsd
|
||||||
|
*/
|
||||||
|
|
||||||
|
import me.bobert.netneutrality.core.tasks.Task;
|
||||||
|
import net.dv8tion.jda.api.interactions.components.ActionRow;
|
||||||
|
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface WithButton {
|
||||||
|
|
||||||
|
Button createButton();
|
||||||
|
|
||||||
|
default ActionRow createActionRow(List<Task> tasks) {
|
||||||
|
ActionRow row = ActionRow.of(tasks.stream().filter(task -> task instanceof WithButton).map(task -> (WithButton) task).map(WithButton::createButton).toList());
|
||||||
|
if (this instanceof WithChildren parent) {
|
||||||
|
parent.addChild(tasks);
|
||||||
|
}
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
default ActionRow createActionRow(Task... tasks) {
|
||||||
|
return createActionRow(List.of(tasks));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package me.bobert.netneutrality.core.thread;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) anthorob
|
||||||
|
*
|
||||||
|
* https://discord.gg/qUa6zNFZsd
|
||||||
|
*/
|
||||||
|
|
||||||
|
import me.bobert.netneutrality.core.LogHandler;
|
||||||
|
import me.bobert.netneutrality.core.tasks.ScheduledTask;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
|
||||||
|
public class ScheduledTaskManager {
|
||||||
|
private static final Logger logger = LogManager.getLogger(ScheduledTaskManager.class);
|
||||||
|
private static final ScheduledExecutorService executorService = ThreadManager.getScheduledExecutor();
|
||||||
|
private static final Map<String, ScheduledFuture<?>> scheduledTasks = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private ScheduledTaskManager() {}
|
||||||
|
|
||||||
|
public static void schedule(ScheduledTask task) {
|
||||||
|
String taskId = task.getId();
|
||||||
|
|
||||||
|
if (scheduledTasks.containsKey(taskId)) {
|
||||||
|
logger.warn("Task {} is already scheduled.", taskId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScheduledTask.TimeFrame timeFrame = task.getTimeFrame();
|
||||||
|
|
||||||
|
Runnable runnable = () -> {
|
||||||
|
logger.info("Executing scheduled task: {}", taskId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
task.run();
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("An exception was thrown while executing scheduled task {}", taskId);
|
||||||
|
LogHandler.log(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ScheduledFuture<?> future = executorService.scheduleWithFixedDelay(
|
||||||
|
runnable,
|
||||||
|
1,
|
||||||
|
timeFrame.getInterval(),
|
||||||
|
timeFrame.getUnit()
|
||||||
|
);
|
||||||
|
|
||||||
|
scheduledTasks.put(taskId, future);
|
||||||
|
logger.info("Successfully scheduled task: {} with interval {} {}",
|
||||||
|
taskId, timeFrame.getInterval(), timeFrame.getUnit());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void cancelAll() {
|
||||||
|
logger.info("Cancelling all {} scheduled tasks", scheduledTasks.size());
|
||||||
|
scheduledTasks.forEach((id, future) -> future.cancel(false));
|
||||||
|
scheduledTasks.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,12 +15,9 @@ import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
|||||||
import dev.lavalink.youtube.YoutubeAudioSourceManager;
|
import dev.lavalink.youtube.YoutubeAudioSourceManager;
|
||||||
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
import me.bobert.netneutrality.core.command.CommandExecutionResult;
|
||||||
import me.bobert.netneutrality.core.context.CommandContext;
|
import me.bobert.netneutrality.core.context.CommandContext;
|
||||||
import me.bobert.netneutrality.core.thread.ThreadManager;
|
|
||||||
import me.bobert.netneutrality.db.GSettings;
|
import me.bobert.netneutrality.db.GSettings;
|
||||||
import me.bobert.netneutrality.db.service.GuildService;
|
import me.bobert.netneutrality.db.service.GuildService;
|
||||||
import me.bobert.netneutrality.music.source.UdioAudioSourceManager;
|
import me.bobert.netneutrality.music.source.UdioAudioSourceManager;
|
||||||
import me.bobert.netneutrality.thread.MusicManagerCleanupThread;
|
|
||||||
import me.bobert.netneutrality.thread.MusicPlayerAutoDisconnectThread;
|
|
||||||
import me.bobert.netneutrality.utils.MusicUtils;
|
import me.bobert.netneutrality.utils.MusicUtils;
|
||||||
import me.bobert.netneutrality.utils.Settings;
|
import me.bobert.netneutrality.utils.Settings;
|
||||||
import net.dv8tion.jda.api.entities.Guild;
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
@@ -31,7 +28,6 @@ import org.apache.logging.log4j.Logger;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
public class MusicManager {
|
public class MusicManager {
|
||||||
|
|
||||||
@@ -72,9 +68,6 @@ public class MusicManager {
|
|||||||
String po = Settings.getInstance().get("NETNEUTRALITY_PO_TOKEN");
|
String po = Settings.getInstance().get("NETNEUTRALITY_PO_TOKEN");
|
||||||
String visitor = Settings.getInstance().get("NETNEUTRALITY_VISITOR_DATA");
|
String visitor = Settings.getInstance().get("NETNEUTRALITY_VISITOR_DATA");
|
||||||
dev.lavalink.youtube.clients.Web.setPoTokenAndVisitorData(po, visitor);
|
dev.lavalink.youtube.clients.Web.setPoTokenAndVisitorData(po, visitor);
|
||||||
|
|
||||||
ThreadManager.getScheduledExecutor().scheduleWithFixedDelay(new MusicPlayerAutoDisconnectThread(), 15, 15, TimeUnit.MINUTES);
|
|
||||||
ThreadManager.getScheduledExecutor().scheduleWithFixedDelay(new MusicManagerCleanupThread(), 1, 1, TimeUnit.HOURS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void disconnectPlayers() {
|
public static void disconnectPlayers() {
|
||||||
|
|||||||
@@ -6,10 +6,12 @@ package me.bobert.netneutrality.tasks.help;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import me.bobert.netneutrality.core.context.TaskContext;
|
import me.bobert.netneutrality.core.context.TaskContext;
|
||||||
import me.bobert.netneutrality.core.tasks.AbstractBuiltInTask;
|
import me.bobert.netneutrality.core.tasks.impl.AbstractBuiltInTask;
|
||||||
|
import me.bobert.netneutrality.core.tasks.trait.WithButton;
|
||||||
|
import me.bobert.netneutrality.utils.Settings;
|
||||||
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
||||||
|
|
||||||
public class BotInfo extends AbstractBuiltInTask {
|
public class BotInfo extends AbstractBuiltInTask implements WithButton {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getId() {
|
public String getId() {
|
||||||
@@ -23,7 +25,7 @@ public class BotInfo extends AbstractBuiltInTask {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void executeTask(TaskContext context) {
|
public void executeTask(TaskContext context) {
|
||||||
context.sendMessageInPrivate("For information about the bot and to follow the development, " +
|
context.replyEphemeral("For information about the bot and to follow the development, " +
|
||||||
"you can join the discord here: https://discord.gg/udVJwTgV");
|
"you can join the discord here: " + Settings.getDiscordInvite());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,12 +6,13 @@ package me.bobert.netneutrality.tasks.help;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import me.bobert.netneutrality.core.context.TaskContext;
|
import me.bobert.netneutrality.core.context.TaskContext;
|
||||||
import me.bobert.netneutrality.core.tasks.AbstractBuiltInTask;
|
import me.bobert.netneutrality.core.tasks.impl.AbstractBuiltInTask;
|
||||||
|
import me.bobert.netneutrality.core.tasks.trait.WithButton;
|
||||||
import me.bobert.netneutrality.utils.MessageFunction;
|
import me.bobert.netneutrality.utils.MessageFunction;
|
||||||
import me.bobert.netneutrality.utils.Settings;
|
import me.bobert.netneutrality.utils.Settings;
|
||||||
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
||||||
|
|
||||||
public class CommandHelp extends AbstractBuiltInTask {
|
public class CommandHelp extends AbstractBuiltInTask implements WithButton {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getId() {
|
public String getId() {
|
||||||
|
|||||||
@@ -6,10 +6,12 @@ package me.bobert.netneutrality.tasks.help;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import me.bobert.netneutrality.core.context.TaskContext;
|
import me.bobert.netneutrality.core.context.TaskContext;
|
||||||
import me.bobert.netneutrality.core.tasks.AbstractBuiltInTask;
|
import me.bobert.netneutrality.core.tasks.impl.AbstractBuiltInTask;
|
||||||
|
import me.bobert.netneutrality.core.tasks.trait.WithButton;
|
||||||
|
import me.bobert.netneutrality.utils.Settings;
|
||||||
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
||||||
|
|
||||||
public class ReportBug extends AbstractBuiltInTask {
|
public class ReportBug extends AbstractBuiltInTask implements WithButton {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getId() {
|
public String getId() {
|
||||||
@@ -23,7 +25,7 @@ public class ReportBug extends AbstractBuiltInTask {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void executeTask(TaskContext context) {
|
public void executeTask(TaskContext context) {
|
||||||
context.sendMessageInPrivate("To report a bug with the bot, you can either use the /report-bug command " +
|
context.replyEphemeral("To report a bug with the bot, you can either use the /report-bug command " +
|
||||||
"or join the discord here: https://discord.gg/udVJwTgV");
|
"or join the discord here: " + Settings.getDiscordInvite());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,15 +109,12 @@ public class LoadPlaylistTask extends ButtonTask implements WithChildren, Deleta
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Lifecycle.KEEP;
|
return Lifecycle.KEEP;
|
||||||
});
|
}).setEmoji(Emoji.fromFormatted("U+1F60E"));
|
||||||
|
|
||||||
Task cancel = CancelButton.create(this, cancelText, context -> Lifecycle.REMOVE_SELF_AND_CHILDREN);
|
Task cancel = CancelButton.create(this, cancelText, context -> Lifecycle.REMOVE_SELF_AND_CHILDREN)
|
||||||
addChild(accept, cancel);
|
.setEmoji(Emoji.fromFormatted("U+1F92E"));
|
||||||
|
|
||||||
return ActionRow.of(
|
return createActionRow(accept, cancel);
|
||||||
accept.createButton().withEmoji(Emoji.fromFormatted("U+1F60E")),
|
|
||||||
cancel.createButton().withEmoji(Emoji.fromFormatted("U+1F92E"))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ package me.bobert.netneutrality.tasks.reaction;
|
|||||||
* https://discord.gg/qUa6zNFZsd
|
* https://discord.gg/qUa6zNFZsd
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import me.bobert.netneutrality.core.tasks.impl.StepTask;
|
import me.bobert.netneutrality.core.tasks.impl.AbstractStepTask;
|
||||||
import net.dv8tion.jda.api.entities.Message;
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
import net.dv8tion.jda.api.entities.Role;
|
import net.dv8tion.jda.api.entities.Role;
|
||||||
|
|
||||||
public class EmojiRoleFirstStep extends StepTask {
|
public class EmojiRoleFirstStep extends AbstractStepTask {
|
||||||
private final Message target;
|
private final Message target;
|
||||||
|
|
||||||
public EmojiRoleFirstStep(Message target) {
|
public EmojiRoleFirstStep(Message target) {
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ public class EmojiRoleModify extends ButtonTask implements WithChildren {
|
|||||||
});
|
});
|
||||||
|
|
||||||
ActionRow row = createActionRow(addEmojiTask, removeEmojiTask, deleteMappingTask);
|
ActionRow row = createActionRow(addEmojiTask, removeEmojiTask, deleteMappingTask);
|
||||||
context.replyEphemeral("Select what you want to do with this message", List.of(row));
|
context.replyEphemeral("Select what you want to do with this message", row);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ package me.bobert.netneutrality.tasks.reaction;
|
|||||||
* https://discord.gg/qUa6zNFZsd
|
* https://discord.gg/qUa6zNFZsd
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import me.bobert.netneutrality.core.tasks.impl.StepTask;
|
import me.bobert.netneutrality.core.tasks.impl.AbstractStepTask;
|
||||||
import me.bobert.netneutrality.tasks.emoji.EmojiReactionRoleTask;
|
import me.bobert.netneutrality.tasks.emoji.EmojiReactionRoleTask;
|
||||||
import net.dv8tion.jda.api.entities.Message;
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.StringJoiner;
|
import java.util.StringJoiner;
|
||||||
|
|
||||||
public class EmojiRoleRemoveStep extends StepTask {
|
public class EmojiRoleRemoveStep extends AbstractStepTask {
|
||||||
private final Message target;
|
private final Message target;
|
||||||
private final EmojiReactionRoleTask task;
|
private final EmojiReactionRoleTask task;
|
||||||
|
|
||||||
@@ -22,6 +22,11 @@ public class EmojiRoleRemoveStep extends StepTask {
|
|||||||
this.task = task;
|
this.task = task;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "emoji-role-remove";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StepType getStepType() {
|
public StepType getStepType() {
|
||||||
return StepType.EMOJI;
|
return StepType.EMOJI;
|
||||||
@@ -54,9 +59,4 @@ public class EmojiRoleRemoveStep extends StepTask {
|
|||||||
task.removeEmoji(emoji);
|
task.removeEmoji(emoji);
|
||||||
return StepResult.success("Removed emoji successfully!");
|
return StepResult.success("Removed emoji successfully!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "emoji-role-remove";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -8,14 +8,14 @@ package me.bobert.netneutrality.tasks.reaction;
|
|||||||
|
|
||||||
import me.bobert.netneutrality.core.tasks.Task;
|
import me.bobert.netneutrality.core.tasks.Task;
|
||||||
import me.bobert.netneutrality.core.tasks.TaskManager;
|
import me.bobert.netneutrality.core.tasks.TaskManager;
|
||||||
import me.bobert.netneutrality.core.tasks.impl.StepTask;
|
import me.bobert.netneutrality.core.tasks.impl.AbstractStepTask;
|
||||||
import me.bobert.netneutrality.tasks.emoji.EmojiReactionRoleTask;
|
import me.bobert.netneutrality.tasks.emoji.EmojiReactionRoleTask;
|
||||||
import net.dv8tion.jda.api.entities.Message;
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
import net.dv8tion.jda.api.entities.Role;
|
import net.dv8tion.jda.api.entities.Role;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class EmojiRoleSecondStep extends StepTask {
|
public class EmojiRoleSecondStep extends AbstractStepTask {
|
||||||
private final Message target;
|
private final Message target;
|
||||||
private final Role role;
|
private final Role role;
|
||||||
|
|
||||||
|
|||||||
+14
-6
@@ -1,27 +1,35 @@
|
|||||||
package me.bobert.netneutrality.thread;
|
package me.bobert.netneutrality.tasks.scheduled;
|
||||||
/*
|
/*
|
||||||
* Copyright (c) anthorob
|
* Copyright (c) anthorob
|
||||||
*
|
*
|
||||||
* https://discord.gg/qUa6zNFZsd
|
* https://discord.gg/qUa6zNFZsd
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import me.bobert.netneutrality.core.tasks.ScheduledTask;
|
||||||
import me.bobert.netneutrality.music.MusicManager;
|
import me.bobert.netneutrality.music.MusicManager;
|
||||||
import me.bobert.netneutrality.music.TrackScheduler;
|
import me.bobert.netneutrality.music.TrackScheduler;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
public class MusicManagerCleanupThread implements Runnable {
|
public class MusicManagerCleanup implements ScheduledTask {
|
||||||
private static final Logger logger = LogManager.getLogger(MusicManagerCleanupThread.class);
|
private static final Logger logger = LogManager.getLogger(MusicManagerCleanup.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return "MusicManagerCleanup";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TimeFrame getTimeFrame() {
|
||||||
|
return TimeFrame.hourly();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
for (MusicManager manager : MusicManager.getManagers()) {
|
for (MusicManager manager : MusicManager.getManagers()) {
|
||||||
processManager(manager);
|
processManager(manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
logger.error("Interrupted while running MusicManagerCleanupThread", e);
|
logger.error("Interrupted while running MusicManagerCleanupThread", e);
|
||||||
}
|
}
|
||||||
+15
-5
@@ -1,10 +1,12 @@
|
|||||||
package me.bobert.netneutrality.thread;
|
package me.bobert.netneutrality.tasks.scheduled;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) anthorob
|
* Copyright (c) anthorob
|
||||||
*
|
*
|
||||||
* https://discord.gg/qUa6zNFZsd
|
* https://discord.gg/qUa6zNFZsd
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import me.bobert.netneutrality.core.tasks.ScheduledTask;
|
||||||
import me.bobert.netneutrality.music.MusicManager;
|
import me.bobert.netneutrality.music.MusicManager;
|
||||||
import net.dv8tion.jda.api.entities.Member;
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
import net.dv8tion.jda.api.entities.channel.middleman.AudioChannel;
|
import net.dv8tion.jda.api.entities.channel.middleman.AudioChannel;
|
||||||
@@ -13,17 +15,25 @@ import org.apache.logging.log4j.Logger;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class MusicPlayerAutoDisconnectThread implements Runnable {
|
public class MusicPlayerAutoDisconnect implements ScheduledTask {
|
||||||
private static final Logger logger = LogManager.getLogger(MusicPlayerAutoDisconnectThread.class);
|
private static final Logger logger = LogManager.getLogger(MusicPlayerAutoDisconnect.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return "MusicPlayerAutoDisconnect";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TimeFrame getTimeFrame() {
|
||||||
|
return TimeFrame.minutely(15);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
for (MusicManager manager : MusicManager.getManagers()) {
|
for (MusicManager manager : MusicManager.getManagers()) {
|
||||||
processManager(manager);
|
processManager(manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
logger.error("Interrupted while running MusicPlayerAutoDisconnectThread", e);
|
logger.error("Interrupted while running MusicPlayerAutoDisconnectThread", e);
|
||||||
}
|
}
|
||||||
+14
-3
@@ -1,4 +1,4 @@
|
|||||||
package me.bobert.netneutrality.thread;/*
|
package me.bobert.netneutrality.tasks.scheduled;/*
|
||||||
* Copyright (c) anthorob
|
* Copyright (c) anthorob
|
||||||
*
|
*
|
||||||
* https://discord.gg/qUa6zNFZsd
|
* https://discord.gg/qUa6zNFZsd
|
||||||
@@ -6,6 +6,7 @@ package me.bobert.netneutrality.thread;/*
|
|||||||
|
|
||||||
import me.bobert.netneutrality.core.tasks.BuiltInTask;
|
import me.bobert.netneutrality.core.tasks.BuiltInTask;
|
||||||
import me.bobert.netneutrality.core.tasks.PersistableTask;
|
import me.bobert.netneutrality.core.tasks.PersistableTask;
|
||||||
|
import me.bobert.netneutrality.core.tasks.ScheduledTask;
|
||||||
import me.bobert.netneutrality.core.tasks.Task;
|
import me.bobert.netneutrality.core.tasks.Task;
|
||||||
import me.bobert.netneutrality.core.tasks.TaskManager;
|
import me.bobert.netneutrality.core.tasks.TaskManager;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
@@ -13,8 +14,18 @@ import org.apache.logging.log4j.Logger;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class CleanupTaskThread implements Runnable {
|
public class TaskCleanup implements ScheduledTask {
|
||||||
private static final Logger logger = LogManager.getLogger(CleanupTaskThread.class);
|
private static final Logger logger = LogManager.getLogger(TaskCleanup.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return "TaskCleanup";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TimeFrame getTimeFrame() {
|
||||||
|
return TimeFrame.minutely(5);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package me.bobert.netneutrality.thread;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) anthorob
|
|
||||||
*
|
|
||||||
* https://discord.gg/qUa6zNFZsd
|
|
||||||
*/
|
|
||||||
|
|
||||||
import me.bobert.netneutrality.NetNeutrality;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.core.LoggerContext;
|
|
||||||
import org.apache.logging.log4j.core.config.Configurator;
|
|
||||||
|
|
||||||
public class ShutdownThread extends Thread {
|
|
||||||
private final NetNeutrality main;
|
|
||||||
|
|
||||||
public ShutdownThread(NetNeutrality main) {
|
|
||||||
this.main = main;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (LogManager.getContext() instanceof LoggerContext) {
|
|
||||||
System.out.println("Shutting down log4j2");
|
|
||||||
Configurator.shutdown((LoggerContext) LogManager.getContext());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (main.getJDA() != null) {
|
|
||||||
main.shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package me.bobert.netneutrality.utils;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) anthorob
|
||||||
|
*
|
||||||
|
* https://discord.gg/qUa6zNFZsd
|
||||||
|
*/
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.reflections.Reflections;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public class ReflectionHelper {
|
||||||
|
private static final Logger logger = LogManager.getLogger(ReflectionHelper.class);
|
||||||
|
private static final BiConsumer<Class<?>, Exception> DEFAULT_FAILURE = (aClass, e) -> logger.error("Failed to load class: {}", aClass.getName(), e);
|
||||||
|
|
||||||
|
public static <E> void loadClassesFromPackage(String packageName, Class<E> clazz, Consumer<E> onInstanciated, BiConsumer<Class<?>, Exception> onFailed) {
|
||||||
|
Set<Class<? extends E>> classes = new Reflections(packageName).getSubTypesOf(clazz);
|
||||||
|
for (Class<? extends E> s : classes) {
|
||||||
|
try {
|
||||||
|
if (Modifier.isAbstract(s.getModifiers())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
E instance = s.getConstructor().newInstance();
|
||||||
|
onInstanciated.accept(instance);
|
||||||
|
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
|
||||||
|
| InvocationTargetException | NoSuchMethodException | SecurityException e) {
|
||||||
|
onFailed.accept(s, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <E> void loadCommands(Class<E> clazz, Consumer<E> onInstanciated, BiConsumer<Class<?>, Exception> onFailed) {
|
||||||
|
loadClassesFromPackage("me.bobert.netneutrality.command", clazz, onInstanciated, onFailed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <E> void loadCommands(Class<E> clazz, Consumer<E> onInstanciated) {
|
||||||
|
loadClassesFromPackage("me.bobert.netneutrality.command", clazz, onInstanciated, DEFAULT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <E> void loadTasks(Class<E> clazz, Consumer<E> onInstanciated, BiConsumer<Class<?>, Exception> onFailed) {
|
||||||
|
loadClassesFromPackage("me.bobert.netneutrality.tasks", clazz, onInstanciated, onFailed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <E> void loadTasks(Class<E> clazz, Consumer<E> onInstanciated) {
|
||||||
|
loadClassesFromPackage("me.bobert.netneutrality.tasks", clazz, onInstanciated, DEFAULT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -54,6 +54,10 @@ public class Settings {
|
|||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getDiscordInvite() {
|
||||||
|
return Settings.getInstance().get("NETNEUTRALITY_BOT_INVITE", "https://discord.gg/PyCpd7JGMp");
|
||||||
|
}
|
||||||
|
|
||||||
public static String getVersion() {
|
public static String getVersion() {
|
||||||
return Settings.getInstance().getMavenVersion();
|
return Settings.getInstance().getMavenVersion();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user