Skip to content

Commit

Permalink
재시작/초기화 등 관리 명령어, 리팩토링, 버전 1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
qsef1256 committed Feb 12, 2022
1 parent bbca0a3 commit 3ec1069
Show file tree
Hide file tree
Showing 45 changed files with 698 additions and 409 deletions.
3 changes: 3 additions & 0 deletions NOTICE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Apache Commons Lang Copyright 2001-2022 The Apache Software Foundation

This product includes software developed at The Apache Software Foundation (https://www.apache.org/).
26 changes: 22 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,27 @@ Discord bot by qsef1256

* /폭발 - :explosion:

## License

Apache Commons Lang Copyright 2001-2022 The Apache Software Foundation
## Library

* 코어 라이브러리
* [JDA](https://github.com/DV8FromTheWorld/JDA): `Apache-2.0`
* [Chewtils](https://github.com/Chew/JDA-Chewtils): `Apache-2.0`
* DB 라이브러리
* [Hibernate ORM](https://hibernate.org/orm/): `LGPL-2.1`
* [HikariCP](https://github.com/brettwooldridge/HikariCP): `Apache-2.0`
* [MariaDB Connector/J](https://mariadb.com/kb/en/mariadb-connector-j/): `LGPL-2.1-or-later`
* 유틸 라이브러리
* [Lombok](https://projectlombok.org/): `MIT`
* [Apache Commons Lang3](https://github.com/apache/commons-lang): `Apache-2.0`
* [Guava](https://github.com/google/guava): `Apache-2.0`
* [Gson](https://github.com/google/gson): `Apache-2.0`
* [SnakeYAML](https://bitbucket.org/snakeyaml/snakeyaml/src/master/): `Apache-2.0`
* [Reflections](https://github.com/ronmamo/reflections): `WTFPL`
* 테스트/로깅 라이브러리
* [JUnit 5](https://junit.org/junit5/): `EPL-2.0`
* [SLF4J](https://www.slf4j.org/): `MIT`
* [Logback](https://logback.qos.ch/): `EPL-1.0 & LGPL-2.1`

This product includes software developed at The Apache Software Foundation (https://www.apache.org/).
## License

Copyright 2022. qsef1256 All rights reserved.
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>net.qsef1256</groupId>
<artifactId>DiaBot</artifactId>
<version>1.0-SNAPSHOT</version>
<version>1.0</version>
<packaging>jar</packaging>

<name>DiaBot</name>
Expand Down Expand Up @@ -113,7 +113,7 @@
<dependency>
<groupId>pw.chew</groupId>
<artifactId>jda-chewtils</artifactId>
<version>1.23.0</version>
<version>1.24.1</version>
<scope>compile</scope>
<type>pom</type>
</dependency>
Expand Down
86 changes: 66 additions & 20 deletions src/main/java/net/qsef1256/diabot/DiaBot.java
Original file line number Diff line number Diff line change
@@ -1,25 +1,31 @@
package net.qsef1256.diabot;

import com.jagrosh.jdautilities.command.Command;
import com.jagrosh.jdautilities.command.CommandClient;
import com.jagrosh.jdautilities.command.CommandClientBuilder;
import com.jagrosh.jdautilities.command.SlashCommand;
import lombok.Getter;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.entities.Activity;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.dv8tion.jda.api.requests.GatewayIntent;
import net.dv8tion.jda.api.utils.ChunkingFilter;
import net.dv8tion.jda.api.utils.cache.CacheFlag;
import net.qsef1256.diabot.command.HelpCommand;
import net.qsef1256.diabot.database.HibernateManager;
import net.qsef1256.diabot.util.GenericUtil;
import org.jetbrains.annotations.NotNull;
import org.reflections.Reflections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.security.auth.login.LoginException;
import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.Set;

import static org.reflections.scanners.Scanners.SubTypes;
Expand All @@ -28,15 +34,19 @@ public class DiaBot {

public static final Logger logger = LoggerFactory.getLogger(DiaBot.class.getSimpleName());
@Getter
private static final Reflections reflections = new Reflections("net.qsef1256.diabot");
@Getter
private static JDA jda;
@Getter
private static CommandClient commandClient;
private static String[] args;

public static void main(final String[] args) throws LoginException {
if (args == null) {
System.out.println("Please start bot with Discord Bot Token.");
return;
}
DiaBot.args = args;

logger.info("DiaBot is Starting!");
final CommandClientBuilder commandClientBuilder = new CommandClientBuilder();
Expand All @@ -61,28 +71,23 @@ public static void main(final String[] args) throws LoginException {

final JDABuilder builder = JDABuilder.createDefault(args[0]);
configureMemoryUsage(builder);
builder.addEventListeners(
commandClient);
builder.addEventListeners(commandClient);

try {
registerListeners(builder);
} catch (final ReflectiveOperationException e) {
logger.error("Error on loading commands");
logger.error("Error on loading listeners");
e.printStackTrace();
System.exit(1);
}

jda = builder.build();
final Guild guild = jda.getGuildById(commandClient.forcedGuildId());
if (guild != null) {
guild.updateCommands().queue();
}

HelpCommand.initCommands();
HibernateManager.getSessionFactoryFromJPA().openSession();
}

public static void configureMemoryUsage(final JDABuilder builder) {
public static void configureMemoryUsage(final @NotNull JDABuilder builder) {
builder.disableCache(CacheFlag.VOICE_STATE);
builder.setChunkingFilter(ChunkingFilter.ALL); // 모든 길드의 유저 캐싱하기 (권한 필요)
builder.enableIntents(GatewayIntent.GUILD_MEMBERS); // 유저 캐싱 권한 얻기 (권한 필요)
Expand All @@ -91,34 +96,75 @@ public static void configureMemoryUsage(final JDABuilder builder) {

private static void registerCommands(final CommandClientBuilder commandClientBuilder) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
logger.info("Loading Commands");
final Reflections classes = new Reflections("net.qsef1256.diabot");
final Set<Class<?>> commands = classes.get(SubTypes.of(SlashCommand.class).asClass());
final Set<Class<?>> commands = reflections.get(SubTypes.of(Command.class).asClass());

if (commands.size() == 0)
logger.warn("There is no command in the registered package. No commands were loaded.");
for (final Class<?> command : commands) {
if (command.isMemberClass()) continue;

SlashCommand slashCommand = (SlashCommand) command.getConstructor().newInstance();
commandClientBuilder.addSlashCommand(slashCommand);
logger.info("Loaded " + command.getSimpleName() + " successfully");
if (command.isInterface()) continue;
if (Modifier.isAbstract(command.getModifiers())) continue;

String typeDisplay = "Unknown";
if (GenericUtil.typeOf(command.getSuperclass(), Command.class)) {
typeDisplay = "Command";
Command instance = (Command) command.getConstructor().newInstance();
commandClientBuilder.addCommand(instance);
}
if (GenericUtil.typeOf(command.getSuperclass(), SlashCommand.class)) {
typeDisplay = "Slash";
SlashCommand instance = (SlashCommand) command.getConstructor().newInstance();
commandClientBuilder.addSlashCommand(instance);
}

logger.info("Loaded %s %s successfully".formatted(typeDisplay, command.getSimpleName()));
}
}

private static void registerListeners(final JDABuilder builder) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
logger.info("Loading Listeners");
final Reflections classes = new Reflections("net.qsef1256.diabot");
final Set<Class<?>> listeners = classes.get(SubTypes.of(ListenerAdapter.class).asClass());
final Set<Class<?>> listeners = reflections.get(SubTypes.of(ListenerAdapter.class).asClass());

if (listeners.size() == 0)
logger.warn("There is no command in the registered package. No commands were loaded.");
logger.warn("There is no listener in the registered package. No listeners were loaded.");
for (final Class<?> listener : listeners) {
if (listener.isMemberClass()) continue;

ListenerAdapter slashCommand = (ListenerAdapter) listener.getConstructor().newInstance();
builder.addEventListeners(slashCommand);
logger.info("Loaded " + listener.getSimpleName() + " successfully");
}
}

public static void shutdown() {
jda.shutdown();
HibernateManager.shutdown();
}

// Warn: 새로 만든 봇은 추적되지 않음 (직접 닫아야 함)
public static void restart() {
StringBuilder cmd = new StringBuilder();
cmd.append(System.getProperty("java.home"))
.append(File.separator)
.append("bin")
.append(File.separator)
.append("java ");
for (String jvmArg : ManagementFactory.getRuntimeMXBean().getInputArguments()) {
cmd.append(jvmArg).append(" ");
}
cmd.append("-cp ")
.append(ManagementFactory.getRuntimeMXBean().getClassPath())
.append(" ")
.append(DiaBot.class.getName())
.append(" ");
for (String arg : DiaBot.args) {
cmd.append(arg).append(" ");
}
try {
Runtime.getRuntime().exec(cmd.toString());
} catch (IOException e) {
logger.error("Failed to start bot: " + e.getMessage());
e.printStackTrace();
}
shutdown();
}

}
74 changes: 64 additions & 10 deletions src/main/java/net/qsef1256/diabot/command/AdminCommand.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package net.qsef1256.diabot.command;

import com.jagrosh.jdautilities.command.SlashCommand;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.qsef1256.diabot.database.HibernateManager;
import net.qsef1256.diabot.DiaBot;
import net.qsef1256.diabot.enums.DiaEmbed;
import net.qsef1256.diabot.enums.DiaMessage;
import org.jetbrains.annotations.NotNull;

import java.util.Collections;

Expand All @@ -21,13 +26,17 @@ public AdminCommand() {

children = new SlashCommand[]{
new StopCommand(),
new SayCommand()
new SayCommand(),
new ClearCommand(),
new RestartCommand()
};
}

@Override
public void execute(final SlashCommandEvent event) {
event.reply("추가 명령어를 입력하세요! : " + getHelp()).queue();
public void execute(final @NotNull SlashCommandEvent event) {
SlashCommand[] children = getChildren();

event.reply(DiaMessage.needSubCommand(children, event.getMember())).queue();
}

private static class StopCommand extends SlashCommand {
Expand All @@ -37,12 +46,10 @@ public StopCommand() {
}

@Override
public void execute(final SlashCommandEvent event) {
public void execute(final @NotNull SlashCommandEvent event) {
logger.info("Shutting down with command");
event.reply("끄는 중....").setEphemeral(true).queue((msg) -> {
event.getJDA().shutdown();
HibernateManager.shutdown();
});
event.reply("끄는 중....").setEphemeral(true).queue((msg) ->
DiaBot.shutdown());
}
}

Expand All @@ -54,7 +61,7 @@ public SayCommand() {
}

@Override
public void execute(final SlashCommandEvent event) {
public void execute(final @NotNull SlashCommandEvent event) {
final OptionMapping option = event.getOption("메시지");
if (option == null) {
event.reply("메시지를 입력해주세요.").setEphemeral(true).queue();
Expand All @@ -65,4 +72,51 @@ public void execute(final SlashCommandEvent event) {
}
}

private static class ClearCommand extends SlashCommand {

public ClearCommand() {
name = "초기화";
help = "명령어를 초기화 하고 종료 합니다.";
}

@Override
protected void execute(SlashCommandEvent event) {
JDA jda = DiaBot.getJda();
String forcedGuildId = DiaBot.getCommandClient().forcedGuildId();

try {
jda.awaitReady();
} catch (InterruptedException e) {
event.replyEmbeds(DiaEmbed.error(null, null, e, null).build()).queue();
e.printStackTrace();
return;
}

final Guild guild = jda.getGuildById(forcedGuildId);
if (guild != null) {
logger.info("Cleaning Commands");
guild.updateCommands().queue();
} else {
logger.warn("forced Guild is null");
}

event.reply("초기화가 완료 되었습니다. 길드 ID: " + forcedGuildId).setEphemeral(true).queue();
DiaBot.shutdown();
}
}

private static class RestartCommand extends SlashCommand {

public RestartCommand() {
name = "재시작";
help = "다봇을 재시작 합니다.";
}

@Override
protected void execute(@NotNull SlashCommandEvent event) {
event.reply("재시작 진행 중... 새 봇은 개발 툴에서 추적되지 않으니 주의하세요.").setEphemeral(true).queue();
DiaBot.restart();
}
}

}
Loading

0 comments on commit 3ec1069

Please sign in to comment.