diff --git a/.gitignore b/.gitignore
index 954ef51..2d41bf2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,4 +41,7 @@ bin/
### Mac OS ###
.DS_Store
-config.yml
\ No newline at end of file
+config.yml
+strong.txt
+moderate.txt
+mild.txt
\ No newline at end of file
diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml
index 005d496..c493be9 100644
--- a/.idea/sqldialects.xml
+++ b/.idea/sqldialects.xml
@@ -1,7 +1,7 @@
-
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index bf458bc..5ef9e76 100644
--- a/build.gradle
+++ b/build.gradle
@@ -4,13 +4,13 @@ plugins {
id 'com.github.johnrengelman.shadow' version '5.2.0'
}
-mainClassName = 'net.nevet5.buzzbot.Bot'
+mainClassName = 'net.nevet5gi.buzzbot.Bot'
-group 'net.nevet5'
+group 'net.nevet5gi'
version '0.3.0'
-def jdaVer = '4.4.0_350'
-sourceCompatibility = targetCompatibility = JavaVersion.VERSION_17
+sourceCompatibility = JavaVersion.VERSION_17
+targetCompatibility = JavaVersion.VERSION_17
repositories {
mavenCentral()
@@ -27,13 +27,13 @@ repositories {
}
dependencies {
- implementation("net.dv8tion:JDA:$jdaVer")
- implementation 'ch.qos.logback:logback-classic:1.2.8'
- implementation group: 'me.duncte123', name: 'botCommons', version: '2.3.8'
+ implementation 'net.dv8tion:JDA:4.4.0_350'
+ implementation 'ch.qos.logback:logback-classic:1.2.11'
+ implementation 'me.duncte123:botCommons:2.3.8'
implementation 'com.google.code.gson:gson:2.9.0'
implementation 'me.carleslc.Simple-YAML:Simple-Yaml:1.7.2'
- implementation group: 'mysql', name: 'mysql-connector-java', version: '8.0.28'
- implementation 'com.github.Kaktushose:jda-commands:v.2.2.0'
+ implementation 'mysql:mysql-connector-java:8.0.29'
+ //implementation 'com.github.Kaktushose:jda-commands:v.2.2.0'
}
compileJava.options.encoding = 'UTF-8'
\ No newline at end of file
diff --git a/src/main/java/net/nevet5/buzzbot/Group.java b/src/main/java/net/nevet5/buzzbot/Group.java
deleted file mode 100644
index 55f297c..0000000
--- a/src/main/java/net/nevet5/buzzbot/Group.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package net.nevet5.buzzbot;
-
-public class Group {
-
-}
diff --git a/src/main/java/net/nevet5/buzzbot/Listener.java b/src/main/java/net/nevet5/buzzbot/Listener.java
deleted file mode 100644
index 1114080..0000000
--- a/src/main/java/net/nevet5/buzzbot/Listener.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package net.nevet5.buzzbot;
-
-import net.dv8tion.jda.api.entities.User;
-import net.dv8tion.jda.api.events.ReadyEvent;
-import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
-import net.dv8tion.jda.api.hooks.ListenerAdapter;
-import net.nevet5.buzzbot.commands.utils.CommandManager;
-
-import javax.annotation.Nonnull;
-
-public class Listener extends ListenerAdapter {
- private final CommandManager manager = new CommandManager();
-
- @Override
- public void onReady(@Nonnull ReadyEvent event) {
- System.out.println("BuzzBot is ready: " + event.getJDA().getSelfUser().getAsTag());
- }
-
- @Override
- public void onGuildMessageReceived(@Nonnull GuildMessageReceivedEvent event) {
- User user = event.getAuthor();
-
- if (user.isBot() || event.isWebhookMessage()) {
- return;
- }
-
- String raw = event.getMessage().getContentRaw();
-
- if (raw.startsWith(Config.getConfig().getString("bot.prefix"))) {
- manager.handle(event);
- }
- }
-}
diff --git a/src/main/java/net/nevet5/buzzbot/Test.java b/src/main/java/net/nevet5/buzzbot/Test.java
deleted file mode 100644
index de05dde..0000000
--- a/src/main/java/net/nevet5/buzzbot/Test.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package net.nevet5.buzzbot;
-
-public class Test {
- public static void main(String[] args) {
- Config.loadConfig();
-
-
-
-
-
-// SqlDB db = new SqlDB();
-// BanEntry ban = new BanEntry(972924565361695745L, "nevetS", 3866, Date.valueOf(LocalDate.now()), Time.valueOf(LocalTime.now()), true, 0, "Reason", "test3", 865368792980914186L, "DevHQ", 824071914673668138L);
-// db.insertBan(ban, "masterbanlist");
- }
-}
diff --git a/src/main/java/net/nevet5/buzzbot/commands/BanCmd.java b/src/main/java/net/nevet5/buzzbot/commands/BanCmd.java
deleted file mode 100644
index 42bd9e4..0000000
--- a/src/main/java/net/nevet5/buzzbot/commands/BanCmd.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package net.nevet5.buzzbot.commands;
-
-import net.nevet5.buzzbot.commands.utils.CommandContext;
-import net.nevet5.buzzbot.commands.utils.ICommand;
-
-import java.util.List;
-
-public class BanCmd implements ICommand {
- @Override
- public void handle(CommandContext ctx) {
- //TODO Add checks for commands so they dont break the bot
- //TODO Get username and discriminator of person banned and mod
- //TODO DM Person who was banned with info about ban
- //TODO Make bans able to be modified by original banner only
-
- String userName;
- long userId;
- long banLength;
- String banReason;
-
- List args = ctx.getArgs();
-
- if (args.size() < 3) {
- ctx.getChannel().sendMessage("Not enough arguments, please try again").queue();
- return;
- }
-
- if (args.get(0).contains("<@")) {
- userId = Long.parseLong(args.get(0).replace("<","").replace("@","").replace("&","").replace(">",""));
- } else {
- userId = Long.parseLong(args.get(0));
- }
-
- if (args.get(1).contains("perm")) {
- banLength = 0;
- } else if (args.get(1).contains("h")) {
- banLength = Long.parseLong(args.get(1).replace("h",""));
- } else if (args.get(1).contains("d")) {
- banLength = Long.parseLong(args.get(1).replace("d","")) * 24;
- } else if (args.get(1).contains("w")) {
- banLength = Long.parseLong(args.get(1).replace("w","")) * 24 * 7;
- } else if (args.get(1).contains("m")) {
- banLength = Long.parseLong(args.get(1).replace("m", "")) * 24 * 30;
- } else if (args.get(1).contains("y")) {
- banLength = Long.parseLong(args.get(1).replace("y","")) * 24 * 365;
- } else {
- return;
- }
-
- StringBuilder sb = new StringBuilder();
- if (args.size() >= 2) {
- for (int i = 2; i < args.size(); i++) {
- sb.append(args.get(i));
- sb.append(" ");
- }
- }
- banReason = sb.toString().trim();
-
- if (banLength == 0) {
- ctx.getChannel().sendMessage("<@" + ctx.getMessage().getAuthor().getId() + "> permanently banned <@" + userId + ">. Reason: " + banReason).queue();
- } else {
- ctx.getChannel().sendMessage("<@" + ctx.getMessage().getAuthor().getId() + "> banned <@" + userId + "> for " + banLength + " hours. Reason: " + banReason).queue();
- }
-
-
- //ctx.getEvent().getGuild().ban(cmdf, 1 , "").submit();
- //ctx.getMessage().reply("yes ban");
- }
-
- @Override
- public String getName() {
- return "ban";
- }
-
- @Override
- public String getHelp() {
- return "Bans the specified user";
- }
-}
diff --git a/src/main/java/net/nevet5/buzzbot/commands/HelpCmd.java b/src/main/java/net/nevet5/buzzbot/commands/HelpCmd.java
deleted file mode 100644
index ba5f2e9..0000000
--- a/src/main/java/net/nevet5/buzzbot/commands/HelpCmd.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package net.nevet5.buzzbot.commands;
-
-import net.dv8tion.jda.api.EmbedBuilder;
-import net.dv8tion.jda.api.entities.TextChannel;
-import net.nevet5.buzzbot.Config;
-import net.nevet5.buzzbot.commands.utils.CommandContext;
-import net.nevet5.buzzbot.commands.utils.CommandManager;
-import net.nevet5.buzzbot.commands.utils.ICommand;
-
-import java.util.List;
-
-public class HelpCmd implements ICommand {
-
- private final CommandManager manager;
-
- public HelpCmd(CommandManager manager) {
- this.manager = manager;
- }
-
- @Override
- public void handle(CommandContext ctx) {
- List args = ctx.getArgs();
- TextChannel channel = ctx.getChannel();
-
- if (args.isEmpty()) {
- StringBuilder builder = new StringBuilder();
-
- EmbedBuilder eb = new EmbedBuilder();
-
- eb.setTitle("List of Commands");
-
- manager.getCommands().stream().map(ICommand::getName).forEach(
- (it) -> builder.append('`').append(Config.getConfig().getString("bot.prefix")).append(it).append("`\n")
- );
-
- eb.addField("", builder.toString(), false);
- channel.sendMessageEmbeds(eb.build()).queue();
-
- return;
- }
-
- String search = args.get(0);
- ICommand command = manager.getCommand(search);
-
- if (command == null) {
- channel.sendMessage("Nothing found for " + search);
- return;
- }
-
- channel.sendMessage(command.getHelp()).queue();
- }
-
- @Override
- public String getName() {
- return "help";
- }
-
- @Override
- public String getHelp() {
- return "Shows the list of bot commands\n" +
- "Usage: `" + Config.getConfig().getString("bot.prefix") + "help [command]`";
- }
-
- @Override
- public List getAliases() {
- return List.of("commands", "cmds", "commandlist");
- }
-}
diff --git a/src/main/java/net/nevet5/buzzbot/commands/TestCmd.java b/src/main/java/net/nevet5/buzzbot/commands/TestCmd.java
deleted file mode 100644
index b3ee17f..0000000
--- a/src/main/java/net/nevet5/buzzbot/commands/TestCmd.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package net.nevet5.buzzbot.commands;
-
-import net.nevet5.buzzbot.commands.utils.CommandContext;
-import net.nevet5.buzzbot.commands.utils.ICommand;
-
-public class TestCmd implements ICommand {
- @Override
- public void handle(CommandContext ctx) {
- ctx.getMessage().reply("text").queue();
- }
-
- @Override
- public String getName() {
- return "test";
- }
-
- @Override
- public String getHelp() {
- return null;
- }
-}
diff --git a/src/main/java/net/nevet5/buzzbot/commands/WarnCmd.java b/src/main/java/net/nevet5/buzzbot/commands/WarnCmd.java
deleted file mode 100644
index a3f51b4..0000000
--- a/src/main/java/net/nevet5/buzzbot/commands/WarnCmd.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package net.nevet5.buzzbot.commands;
-
-import net.nevet5.buzzbot.commands.utils.CommandContext;
-import net.nevet5.buzzbot.commands.utils.ICommand;
-
-public class WarnCmd implements ICommand {
- @Override
- public void handle(CommandContext ctx) {
- ctx.getMessage().reply("This command has not been implemented yet").queue();
- }
-
- @Override
- public String getName() {
- return "warn";
- }
-
- @Override
- public String getHelp() {
- return "Warns the specified user";
- }
-}
diff --git a/src/main/java/net/nevet5/buzzbot/commands/utils/CommandManager.java b/src/main/java/net/nevet5/buzzbot/commands/utils/CommandManager.java
deleted file mode 100644
index 1bf6bc5..0000000
--- a/src/main/java/net/nevet5/buzzbot/commands/utils/CommandManager.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package net.nevet5.buzzbot.commands.utils;
-
-import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
-import net.nevet5.buzzbot.Config;
-import net.nevet5.buzzbot.commands.*;
-
-import javax.annotation.Nullable;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.regex.Pattern;
-
-public class CommandManager {
- protected final List commands = new ArrayList<>();
-
- public CommandManager() {
- //Add to this list in alphabetical order
- addCommand(new BanCmd());
- addCommand(new HelpCmd(this));
- addCommand(new MuteCmd());
- addCommand(new PandaCmd());
- addCommand(new PingCmd());
- addCommand(new UnbanCmd());
- addCommand(new UnmuteCmd());
- addCommand(new UnwarnCmd());
- addCommand(new WarnCmd());
- //addCommand(new CommandClass());
- }
-
- private void addCommand(ICommand cmd) {
- boolean nameFound = this.commands.stream().anyMatch((it) -> it.getName().equalsIgnoreCase(cmd.getName()));
-
- if (nameFound) {
- throw new IllegalArgumentException("A command with this name is already present");
- }
-
- commands.add(cmd);
- }
-
- public List getCommands() {
- return commands;
- }
-
- @Nullable
- public ICommand getCommand(String search) {
- String searchLower = search.toLowerCase();
-
- for (ICommand cmd : this.commands) {
- if (cmd.getName().equals(searchLower) || cmd.getAliases().contains(searchLower)) {
- return cmd;
- }
- }
-
- return null;
- }
-
- public void handle(GuildMessageReceivedEvent event) {
- String[] split = event.getMessage().getContentRaw()
- .replaceFirst("(?i)" + Pattern.quote(Config.getConfig().getString("bot.prefix")), "")
- .split("\\s+");
-
- String invoke = split[0].toLowerCase();
- ICommand cmd = this.getCommand(invoke);
-
- if (cmd !=null) {
- event.getChannel().sendTyping().queue();
- List args = Arrays.asList(split).subList(1, split.length);
-
- CommandContext ctx = new CommandContext(event, args);
-
- cmd.handle(ctx);
- }
- }
-}
diff --git a/src/main/java/net/nevet5/buzzbot/commands/utils/ICommand.java b/src/main/java/net/nevet5/buzzbot/commands/utils/ICommand.java
deleted file mode 100644
index 1fc9a48..0000000
--- a/src/main/java/net/nevet5/buzzbot/commands/utils/ICommand.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package net.nevet5.buzzbot.commands.utils;
-
-import java.util.List;
-
-public interface ICommand {
- void handle(CommandContext ctx);
-
- String getName();
-
- String getHelp();
-
- default List getAliases() {
- return List.of();
- }
-}
diff --git a/src/main/java/net/nevet5/buzzbot/database/SqlDB.java b/src/main/java/net/nevet5/buzzbot/database/SqlDB.java
deleted file mode 100644
index 2af491c..0000000
--- a/src/main/java/net/nevet5/buzzbot/database/SqlDB.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package net.nevet5.buzzbot.database;
-
-import net.nevet5.buzzbot.Config;
-import net.nevet5.buzzbot.objects.BanData;
-
-import java.sql.*;
-
-public class SqlDB {
- //TODO Make this a two way class for reading and writing from db
-
- private Connection connect;
- private Statement statement;
- private ResultSet resultSet;
-
- public SqlDB() {
- try {
- Class.forName("com.mysql.jdbc.Driver");
- connect = DriverManager.getConnection("jdbc:mysql://" + Config.getConfig().getString("database.url") + "/" + Config.getConfig().getString("database.database"), Config.getConfig().getString("database.user"), Config.getConfig().getString("database.password"));
- statement = connect.createStatement();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- public void insertBan(BanData ban, String table) {
- try {
- System.out.println("Created Statement");
- statement.executeUpdate("INSERT INTO " + table + " VALUES (default, " + ban.getUserId() + ", '" + ban.getUserName() + "', '" + ban.getUserDiscriminator() + "', '" + ban.getDate() + "', '" + ban.getTime() + "', " + ban.getBanType() + ", " + ban.getBanLength() + ", '" + ban.getBanReason() + "', '" + ban.getModName() + "', " + ban.getModId() + ", '" + ban.getServerName() + "', " + ban.getServerId() + ")");
- System.out.println("Executed Statement");
- close();
- System.out.println("Closed");
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
-
- private BanData query(long userId) throws SQLException {
- BanData ban = new BanData();
-
- String group = "masterbanlist"; //TODO Make this use GuildUtils in order to get the proper group for the server
-
- resultSet = statement.executeQuery("SELECT * IN " + group + " WHERE userId='" + userId + "'");
-
- while (resultSet.next()) {
- ban.setUserId(resultSet.getLong("userid"));
- ban.setUserName(resultSet.getString("username"));
- ban.setUserDiscriminator(resultSet.getInt("userdiscriminator"));
- ban.setDate(resultSet.getDate("bandate"));
- ban.setTime(resultSet.getTime("bantime"));
- ban.setBanType(resultSet.getBoolean("bantype"));
- ban.setBanLength(resultSet.getInt(""));
- ban.setBanReason(resultSet.getString("banreason"));
- ban.setModName(resultSet.getString("modname"));
- ban.setModId(resultSet.getLong("modid"));
- ban.setServerName(resultSet.getString("servername"));
- ban.setServerId(resultSet.getLong("serverid"));
- }
-
- return ban;
- }
-
- private void close() {
- try {
- //if (resultSet != null) {
- // resultSet.close();
- //}
-
- if (statement != null) {
- statement.close();
- }
-
- if (connect != null) {
- connect.close();
- }
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
-
-}
diff --git a/src/main/java/net/nevet5/buzzbot/util/GuildUtils.java b/src/main/java/net/nevet5/buzzbot/util/GuildUtils.java
deleted file mode 100644
index 8477db6..0000000
--- a/src/main/java/net/nevet5/buzzbot/util/GuildUtils.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package net.nevet5.buzzbot.util;
-
-import net.nevet5.buzzbot.Group;
-
-public class GuildUtils {
- public static Group getGroupById(long guildId) {
-
- return new Group();
- }
-}
diff --git a/src/main/java/net/nevet5/buzzbot/util/JsonUtils.java b/src/main/java/net/nevet5/buzzbot/util/JsonUtils.java
deleted file mode 100644
index bd965c2..0000000
--- a/src/main/java/net/nevet5/buzzbot/util/JsonUtils.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package net.nevet5.buzzbot.util;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import net.nevet5.buzzbot.objects.UserData;
-
-import java.io.*;
-import java.lang.reflect.Type;
-
-public class JsonUtils {
- T object;
-
- public void createJson(T object) throws IOException {
- Writer writer = new FileWriter("./" + object.getName() + ".json");
-
- GsonBuilder builder = new GsonBuilder();
- builder.setPrettyPrinting();
- Gson gson = builder.create();
- String jsonString = gson.toJson(object);
- writer.write(jsonString);
- writer.close();
- }
-
- public T loadJson(String jsonFileName) throws FileNotFoundException {
- BufferedReader reader = new BufferedReader(new FileReader("./" + jsonFileName + ".json"));
-
- return new Gson().fromJson(reader, (Type) object);
- }
-}
\ No newline at end of file
diff --git a/src/main/java/net/nevet5/buzzbot/Bot.java b/src/main/java/net/nevet5gi/buzzbot/Bot.java
similarity index 86%
rename from src/main/java/net/nevet5/buzzbot/Bot.java
rename to src/main/java/net/nevet5gi/buzzbot/Bot.java
index 253c8ce..3f1e08d 100644
--- a/src/main/java/net/nevet5/buzzbot/Bot.java
+++ b/src/main/java/net/nevet5gi/buzzbot/Bot.java
@@ -1,16 +1,19 @@
-package net.nevet5.buzzbot;
+package net.nevet5gi.buzzbot;
-import com.github.kaktushose.jda.commands.JDACommands;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.entities.Activity;
import net.dv8tion.jda.api.utils.cache.CacheFlag;
+import net.nevet5gi.buzzbot.commands.utils.CommandManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import javax.security.auth.login.LoginException;
import java.util.EnumSet;
public class Bot {
public static JDA jda;
+ private static final Logger LOGGER = LoggerFactory.getLogger(Bot.class);
public static void main(String[] args) {
Config.loadConfig();
@@ -25,12 +28,13 @@ public class Bot {
.enableCache(CacheFlag.VOICE_STATE)
.addEventListeners(new Listener())
.build();
+ CommandManager.registerSlashCommands();
getActivity();
} catch (LoginException e) {
e.printStackTrace();
}
- JDACommands.start(jda, Bot.class, "net.nevet5.buzzbot.commands.slash");
+ Listener.startProfanityFilter();
}
public static void getActivity() {
diff --git a/src/main/java/net/nevet5/buzzbot/Config.java b/src/main/java/net/nevet5gi/buzzbot/Config.java
similarity index 64%
rename from src/main/java/net/nevet5/buzzbot/Config.java
rename to src/main/java/net/nevet5gi/buzzbot/Config.java
index 24eb61f..a787bef 100644
--- a/src/main/java/net/nevet5/buzzbot/Config.java
+++ b/src/main/java/net/nevet5gi/buzzbot/Config.java
@@ -1,26 +1,29 @@
-package net.nevet5.buzzbot;
+package net.nevet5gi.buzzbot;
import org.simpleyaml.configuration.file.YamlFile;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.io.IOException;
public class Config {
private static final YamlFile YML_FILE = new YamlFile("./config.yml");
+ private static final Logger LOGGER = LoggerFactory.getLogger(Config.class);
public static void loadConfig() {
YML_FILE.setConfigurationFile("./config.yml");
try {
if (!YML_FILE.exists()) {
- System.out.println("Config file not found, creating new one...");
+ LOGGER.info("Config file not found, creating new one...");
YML_FILE.createNewFile(true);
- System.out.println("Config file created!");
+ LOGGER.info("Config file created!");
} else {
- System.out.println("Loading Config file...");
+ LOGGER.info("Loading Config file...");
YML_FILE.loadWithComments();
- System.out.println("Config file loaded!");
+ LOGGER.info("Config file loaded!");
}
} catch (final Exception e) {
- System.out.println("Error while loading config file!");
+ LOGGER.error("Error while loading config file!");
e.printStackTrace();
}
@@ -33,6 +36,9 @@ public class Config {
YML_FILE.addDefault("database.database", "buzzbot");
YML_FILE.addDefault("database.user", "barry");
YML_FILE.addDefault("database.password", "benson");
+ YML_FILE.addDefault("filter.path.mild", "./mild.txt");
+ YML_FILE.addDefault("filter.path.moderate", "./moderate.txt");
+ YML_FILE.addDefault("filter.path.strong", "./strong.txt");
try {
YML_FILE.save();
diff --git a/src/main/java/net/nevet5gi/buzzbot/Group.java b/src/main/java/net/nevet5gi/buzzbot/Group.java
new file mode 100644
index 0000000..8babc49
--- /dev/null
+++ b/src/main/java/net/nevet5gi/buzzbot/Group.java
@@ -0,0 +1,5 @@
+package net.nevet5gi.buzzbot;
+
+public class Group {
+
+}
diff --git a/src/main/java/net/nevet5gi/buzzbot/Listener.java b/src/main/java/net/nevet5gi/buzzbot/Listener.java
new file mode 100644
index 0000000..ee03180
--- /dev/null
+++ b/src/main/java/net/nevet5gi/buzzbot/Listener.java
@@ -0,0 +1,83 @@
+package net.nevet5gi.buzzbot;
+
+import net.dv8tion.jda.api.entities.User;
+import net.dv8tion.jda.api.events.ReadyEvent;
+import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
+import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
+import net.dv8tion.jda.api.events.message.guild.GuildMessageUpdateEvent;
+import net.dv8tion.jda.api.hooks.ListenerAdapter;
+import net.nevet5gi.buzzbot.commands.utils.CommandManager;
+import net.nevet5gi.buzzbot.database.SqlDB;
+import net.nevet5gi.buzzbot.functions.ProfanityFilter;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nonnull;
+
+public class Listener extends ListenerAdapter {
+ private static final Logger LOGGER = LoggerFactory.getLogger(Listener.class);
+ private final CommandManager manager = new CommandManager();
+ private static final ProfanityFilter profanityFilter = new ProfanityFilter();
+
+ public static void startProfanityFilter() {
+ profanityFilter.buildDictionaries();
+ }
+
+ @Override
+ public void onReady(@Nonnull ReadyEvent event) {
+ LOGGER.info("BuzzBot is ready: " + event.getJDA().getSelfUser().getAsTag());
+ }
+
+ @Override
+ public void onGuildMessageReceived(@Nonnull GuildMessageReceivedEvent event) {
+ User user = event.getAuthor();
+ String raw = event.getMessage().getContentRaw();
+
+ if (user.isBot() || event.isWebhookMessage()) {
+ return;
+ }
+
+ if (profanityFilter.containsProfanity(raw, "strong")) {
+ SqlDB sql = new SqlDB();
+ int profanityLevel = sql.getGuildData(event.getGuild().getIdLong()).getProfanityLevel();
+
+ switch (profanityLevel) {
+ case 1:
+ if (profanityFilter.containsProfanity(raw, "mild")) profanityFilter.handle(event);
+ case 2:
+ if (profanityFilter.containsProfanity(raw, "moderate")) profanityFilter.handle(event);
+ case 3:
+ profanityFilter.handle(event);
+ }
+ }
+
+ if (raw.startsWith(Config.getConfig().getString("bot.prefix"))) {
+ manager.handle(event);
+ }
+ }
+
+ @Override
+ public void onGuildMessageUpdate(@Nonnull GuildMessageUpdateEvent event) {
+ String raw = event.getMessage().getContentRaw();
+
+ if (profanityFilter.containsProfanity(raw, "strong")) {
+ SqlDB sql = new SqlDB();
+ int profanityLevel = sql.getGuildData(event.getGuild().getIdLong()).getProfanityLevel();
+
+ switch (profanityLevel) {
+ case 1:
+ if (profanityFilter.containsProfanity(raw, "mild")) profanityFilter.handleEdit(event);
+ case 2:
+ if (profanityFilter.containsProfanity(raw, "moderate")) profanityFilter.handleEdit(event);
+ case 3:
+ profanityFilter.handleEdit(event);
+ }
+ }
+ }
+
+ @Override
+ public void onSlashCommand(@NotNull SlashCommandEvent event) {
+ manager.handle(event);
+ }
+}
diff --git a/src/main/java/net/nevet5gi/buzzbot/Test.java b/src/main/java/net/nevet5gi/buzzbot/Test.java
new file mode 100644
index 0000000..2a09d6b
--- /dev/null
+++ b/src/main/java/net/nevet5gi/buzzbot/Test.java
@@ -0,0 +1,64 @@
+package net.nevet5gi.buzzbot;
+
+import net.dv8tion.jda.api.JDA;
+import net.dv8tion.jda.api.JDABuilder;
+import net.dv8tion.jda.api.utils.cache.CacheFlag;
+import net.nevet5gi.buzzbot.database.SqlDB;
+import net.nevet5gi.buzzbot.objects.BanData;
+import net.nevet5gi.buzzbot.objects.GuildData;
+
+import javax.security.auth.login.LoginException;
+import java.sql.Date;
+import java.sql.Time;
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.util.EnumSet;
+
+public class Test {
+ private static JDA jda;
+ public static void main(String[] args) {
+ Config.loadConfig();
+
+ SqlDB sql = new SqlDB();
+ GuildData guild = new GuildData();
+
+ guild.setName("DevHQ");
+ guild.setId(824071914673668138L);
+ guild.setGroup("developer");
+ guild.setProfanityLevel(3);
+
+ sql.addGuild(guild);
+
+ //sqlTest();
+ }
+
+ private static void initJda() {
+ try {
+ jda = JDABuilder.createDefault(Config.getConfig().getString("bot.token"))
+ .disableCache(EnumSet.of(
+ CacheFlag.CLIENT_STATUS,
+ CacheFlag.ACTIVITY,
+ CacheFlag.EMOTE
+ ))
+ .enableCache(CacheFlag.VOICE_STATE)
+ .addEventListeners(new Listener())
+ .build();
+ } catch (LoginException e) {
+ e.printStackTrace();
+ jda = null;
+ }
+ }
+
+ private static void sqlTest() {
+ SqlDB db = new SqlDB();
+ BanData ban = new BanData(972924565361695745L, "nevetS", 3866, Date.valueOf(LocalDate.now()), Time.valueOf(LocalTime.now()), true, 0, "Reason", "test3", 865368792980914186L, "DevHQ", 824071914673668138L);
+ db.insertBan(ban, "masterbanlist");
+
+ SqlDB db2 = new SqlDB();
+ BanData qban = db2.queryBan(972924565361695745L, "masterbanlist");
+
+ System.out.println(qban.getUserName());
+ System.out.println(qban.getDate());
+ System.out.println(qban.getBanReason());
+ }
+}
diff --git a/src/main/java/net/nevet5gi/buzzbot/commands/BanCmd.java b/src/main/java/net/nevet5gi/buzzbot/commands/BanCmd.java
new file mode 100644
index 0000000..e8b19d9
--- /dev/null
+++ b/src/main/java/net/nevet5gi/buzzbot/commands/BanCmd.java
@@ -0,0 +1,92 @@
+package net.nevet5gi.buzzbot.commands;
+
+import net.nevet5gi.buzzbot.Bot;
+import net.nevet5gi.buzzbot.commands.utils.CommandContext;
+import net.nevet5gi.buzzbot.commands.utils.ICommand;
+import net.nevet5gi.buzzbot.objects.BanData;
+
+import java.util.List;
+
+public class BanCmd implements ICommand {
+ @Override
+ public void handle(CommandContext ctx) {
+ //TODO Add checks for commands so they dont break the bot
+ //TODO Get username and discriminator of person banned and mod
+ //TODO DM Person who was banned with info about ban
+ //TODO Make bans able to be modified by original banner only
+
+ List args = ctx.getArgs();
+
+ if (args.size() < 3) {
+ ctx.getChannel().sendMessage("Not enough arguments, please try again").queue();
+ return;
+ }
+
+ BanData ban = new BanData();
+
+ if (args.get(0).contains("<@")) {
+ ban.setUserId(Long.parseLong(args.get(0).replace("<","").replace("@","").replace("&","").replace(">","")));
+ } else {
+ ban.setUserId(Long.parseLong(args.get(0)));
+ }
+
+ if (args.get(1).contains("perm")) {
+ ban.setBanLength(0);
+ ban.setBanType(true);
+ } else if (args.get(1).contains("h")) {
+ ban.setBanLength(Integer.parseInt(args.get(1).replace("h","")));
+ ban.setBanType(false);
+ } else if (args.get(1).contains("d")) {
+ ban.setBanLength(Integer.parseInt(args.get(1).replace("d","")) * 24);
+ ban.setBanType(false);
+ } else if (args.get(1).contains("w")) {
+ ban.setBanLength(Integer.parseInt(args.get(1).replace("w","")) * 24 * 7);
+ ban.setBanType(false);
+ } else if (args.get(1).contains("m")) {
+ ban.setBanLength(Integer.parseInt(args.get(1).replace("m", "")) * 24 * 30);
+ ban.setBanType(false);
+ } else if (args.get(1).contains("y")) {
+ ban.setBanLength(Integer.parseInt(args.get(1).replace("y","")) * 24 * 365);
+ ban.setBanType(false);
+ } else {
+ ctx.getChannel().sendMessage("Invalid time argument, please try again").queue();
+ return;
+ }
+
+ StringBuilder sb = new StringBuilder();
+ if (args.size() >= 2) {
+ for (int i = 2; i < args.size(); i++) {
+ sb.append(args.get(i));
+ sb.append(" ");
+ }
+ }
+ ban.setBanReason(sb.toString().trim());
+
+ if (ban.getBanLength() == 0) {
+ ctx.getChannel().sendMessage("<@" + ctx.getMessage().getAuthor().getId() + "> permanently banned <@" + ban.getUserId() + ">. Reason: " + ban.getBanReason()).queue();
+ } else {
+ ctx.getChannel().sendMessage("<@" + ctx.getMessage().getAuthor().getId() + "> banned <@" + ban.getUserId() + "> for " + ban.getBanLength() + " hours. Reason: " + ban.getBanReason()).queue();
+ }
+
+ Bot.jda.retrieveUserById(ban.getUserId()).queue(user -> { ban.setUserName(user.getName()); });
+ Bot.jda.retrieveUserById(ban.getUserId()).queue(user -> { ban.setUserDiscriminator(Integer.parseInt(user.getDiscriminator())); });
+ ban.setModId(ctx.getMessage().getAuthor().getIdLong());
+ ban.setModName(ctx.getMessage().getAuthor().getName());
+ ban.setServerId(ctx.getGuild().getIdLong());
+ ban.setServerName(ctx.getGuild().getName());
+
+
+ //ctx.getEvent().getGuild().ban(cmdf, 1 , "").submit();
+ //ctx.getMessage().reply("yes ban");
+ }
+
+ @Override
+ public String getName() {
+ return "ban";
+ }
+
+ @Override
+ public String getHelp() {
+ return "Bans the specified user";
+ }
+}
diff --git a/src/main/java/net/nevet5gi/buzzbot/commands/HelpCmd.java b/src/main/java/net/nevet5gi/buzzbot/commands/HelpCmd.java
new file mode 100644
index 0000000..c5dea17
--- /dev/null
+++ b/src/main/java/net/nevet5gi/buzzbot/commands/HelpCmd.java
@@ -0,0 +1,124 @@
+package net.nevet5gi.buzzbot.commands;
+
+import net.dv8tion.jda.api.EmbedBuilder;
+import net.dv8tion.jda.api.entities.TextChannel;
+import net.dv8tion.jda.api.interactions.commands.OptionMapping;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import net.dv8tion.jda.api.interactions.commands.build.CommandData;
+import net.nevet5gi.buzzbot.Config;
+import net.nevet5gi.buzzbot.commands.utils.*;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+public class HelpCmd implements ICommand, ISlashCommand {
+
+ private final CommandManager manager;
+
+ public HelpCmd(CommandManager manager) {
+ this.manager = manager;
+ }
+
+ @Override
+ public void handle(CommandContext ctx) {
+ List args = ctx.getArgs();
+ TextChannel channel = ctx.getChannel();
+
+ if (args.isEmpty()) {
+ StringBuilder sb = new StringBuilder();
+
+ EmbedBuilder eb = new EmbedBuilder();
+
+ eb.setTitle("List of Commands");
+
+ manager.getCommands().stream().map(ICmdGeneric::getName).forEach(
+ (it) -> sb.append('`').append(Config.getConfig().getString("bot.prefix")).append(it).append("`\n")
+ );
+
+ eb.addField("", sb.toString(), false);
+ channel.sendMessageEmbeds(eb.build()).queue();
+
+ return;
+ }
+
+ String search = args.get(0);
+ ICommand command = manager.getCommand(search);
+ ISlashCommand slashCommand = manager.getSlashCommand(search);
+
+ if (command == null && slashCommand == null) {
+ channel.sendMessage("Nothing found for " + search).queue();
+ return;
+ }
+
+ channel.sendMessage(command.getHelp()).queue();
+ }
+
+ @Override
+ public void handleSlash(CommandContext ctx) {
+ StringBuilder sb = new StringBuilder();
+ EmbedBuilder eb = new EmbedBuilder();
+
+ OptionMapping option = ctx.getSlashEvent().getOption("command");
+ String cmd = null;
+ if (option != null) cmd = option.getAsString();
+
+ if (cmd == null) {
+ ICommand command = manager.getCommand(ctx.getSlashEvent().getName());
+ ISlashCommand slashCommand = manager.getSlashCommand(ctx.getSlashEvent().getName());
+
+ if (command == null && slashCommand == null) {
+ ctx.getSlashEvent().getHook().sendMessage("Nothing found for " + ctx.getSlashEvent()).queue();
+ return;
+ }
+
+ eb.setTitle("Commands");
+
+ manager.getCommands().stream().map(ICmdGeneric::getName).forEach(
+ (it) -> sb.append('`').append(Config.getConfig().getString("bot.prefix")).append(it).append("`\n")
+ );
+
+ eb.addField("", sb.toString(), false);
+
+ } else {
+ ICommand scmd = manager.getCommand(cmd);
+
+ if (scmd != null) {
+ eb.setTitle(scmd.getName());
+ eb.addField("", scmd.getHelp(), false);
+ } else {
+ eb.setTitle("Error");
+ eb.addField("", "Unknown command, run `/help` to see a list of available commands", false);
+ }
+ }
+
+ ctx.getSlashEvent().getHook().sendMessageEmbeds(eb.build()).queue();
+ }
+
+ @Override
+ public String getName() {
+ return "help";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Lists bot commands";
+ }
+
+ @Override
+ public @NotNull CommandData getCommandData() {
+
+ return new CommandData(this.getName(), this.getDescription())
+ .addOption(OptionType.STRING, "command", "Gives info on this command", false);
+ }
+
+ @Override
+ public String getHelp() {
+ return "Shows the list of bot commands\n" +
+ "Usage: `" + Config.getConfig().getString("bot.prefix") + "help [command]`";
+ }
+
+ @Override
+ public List getAliases() {
+ return List.of("commands", "cmds", "commandlist");
+ }
+}
diff --git a/src/main/java/net/nevet5/buzzbot/commands/MuteCmd.java b/src/main/java/net/nevet5gi/buzzbot/commands/MuteCmd.java
similarity index 70%
rename from src/main/java/net/nevet5/buzzbot/commands/MuteCmd.java
rename to src/main/java/net/nevet5gi/buzzbot/commands/MuteCmd.java
index 8c16c95..2086a38 100644
--- a/src/main/java/net/nevet5/buzzbot/commands/MuteCmd.java
+++ b/src/main/java/net/nevet5gi/buzzbot/commands/MuteCmd.java
@@ -1,7 +1,7 @@
-package net.nevet5.buzzbot.commands;
+package net.nevet5gi.buzzbot.commands;
-import net.nevet5.buzzbot.commands.utils.CommandContext;
-import net.nevet5.buzzbot.commands.utils.ICommand;
+import net.nevet5gi.buzzbot.commands.utils.CommandContext;
+import net.nevet5gi.buzzbot.commands.utils.ICommand;
public class MuteCmd implements ICommand {
@Override
diff --git a/src/main/java/net/nevet5/buzzbot/commands/PandaCmd.java b/src/main/java/net/nevet5gi/buzzbot/commands/PandaCmd.java
similarity index 91%
rename from src/main/java/net/nevet5/buzzbot/commands/PandaCmd.java
rename to src/main/java/net/nevet5gi/buzzbot/commands/PandaCmd.java
index 2742579..a9ea106 100644
--- a/src/main/java/net/nevet5/buzzbot/commands/PandaCmd.java
+++ b/src/main/java/net/nevet5gi/buzzbot/commands/PandaCmd.java
@@ -1,13 +1,13 @@
-package net.nevet5.buzzbot.commands;
+package net.nevet5gi.buzzbot.commands;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import net.dv8tion.jda.api.EmbedBuilder;
-import net.nevet5.buzzbot.Config;
-import net.nevet5.buzzbot.commands.utils.CommandContext;
-import net.nevet5.buzzbot.commands.utils.ICommand;
+import net.nevet5gi.buzzbot.Config;
+import net.nevet5gi.buzzbot.commands.utils.CommandContext;
+import net.nevet5gi.buzzbot.commands.utils.ICommand;
import java.io.IOException;
import java.net.URI;
diff --git a/src/main/java/net/nevet5/buzzbot/commands/PingCmd.java b/src/main/java/net/nevet5gi/buzzbot/commands/PingCmd.java
similarity index 76%
rename from src/main/java/net/nevet5/buzzbot/commands/PingCmd.java
rename to src/main/java/net/nevet5gi/buzzbot/commands/PingCmd.java
index a156cd0..f04440a 100644
--- a/src/main/java/net/nevet5/buzzbot/commands/PingCmd.java
+++ b/src/main/java/net/nevet5gi/buzzbot/commands/PingCmd.java
@@ -1,9 +1,9 @@
-package net.nevet5.buzzbot.commands;
+package net.nevet5gi.buzzbot.commands;
import net.dv8tion.jda.api.JDA;
-import net.nevet5.buzzbot.Config;
-import net.nevet5.buzzbot.commands.utils.CommandContext;
-import net.nevet5.buzzbot.commands.utils.ICommand;
+import net.nevet5gi.buzzbot.Config;
+import net.nevet5gi.buzzbot.commands.utils.CommandContext;
+import net.nevet5gi.buzzbot.commands.utils.ICommand;
public class PingCmd implements ICommand {
@Override
diff --git a/src/main/java/net/nevet5gi/buzzbot/commands/TestCmd.java b/src/main/java/net/nevet5gi/buzzbot/commands/TestCmd.java
new file mode 100644
index 0000000..58a002e
--- /dev/null
+++ b/src/main/java/net/nevet5gi/buzzbot/commands/TestCmd.java
@@ -0,0 +1,50 @@
+package net.nevet5gi.buzzbot.commands;
+
+import net.dv8tion.jda.api.entities.IMentionable;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+import net.dv8tion.jda.api.interactions.commands.build.CommandData;
+import net.nevet5gi.buzzbot.commands.utils.CommandContext;
+import net.nevet5gi.buzzbot.commands.utils.ICommand;
+import net.nevet5gi.buzzbot.commands.utils.ISlashCommand;
+
+public class TestCmd implements ICommand, ISlashCommand {
+ @Override
+ public void handle(CommandContext ctx) {
+ ctx.getMessage().reply("test command").queue();
+ }
+
+ @Override
+ public void handleSlash(CommandContext ctx) {
+ long number = ctx.getSlashEvent().getOption("number").getAsLong();
+ IMentionable member = ctx.getSlashEvent().getOption("mention").getAsMentionable();
+ boolean testBoolean = ctx.getSlashEvent().getOption("boolean").getAsBoolean();
+
+ String content = "number: " + number + ", mention: " + member.getAsMention() + ", boolean: " + testBoolean;
+
+ ctx.getSlashEvent().getHook().sendMessage(content).queue();
+ }
+
+ @Override
+ public String getDescription() {
+ return "Checks the piung between bot and API";
+ }
+
+ @Override
+ public CommandData getCommandData() {
+ return new CommandData(this.getName(), this.getDescription())
+ .addOption(OptionType.INTEGER, "number", "test number", true)
+ .addOption(OptionType.MENTIONABLE, "mention", "mentioned member or role", true)
+ .addOption(OptionType.BOOLEAN, "boolean", "test boolean", true);
+ }
+
+ @Override
+ public String getName() {
+ return "test";
+ }
+
+
+ @Override
+ public String getHelp() {
+ return "tests api ping";
+ }
+}
diff --git a/src/main/java/net/nevet5/buzzbot/commands/UnbanCmd.java b/src/main/java/net/nevet5gi/buzzbot/commands/UnbanCmd.java
similarity index 70%
rename from src/main/java/net/nevet5/buzzbot/commands/UnbanCmd.java
rename to src/main/java/net/nevet5gi/buzzbot/commands/UnbanCmd.java
index 9671f2a..ee1636e 100644
--- a/src/main/java/net/nevet5/buzzbot/commands/UnbanCmd.java
+++ b/src/main/java/net/nevet5gi/buzzbot/commands/UnbanCmd.java
@@ -1,7 +1,7 @@
-package net.nevet5.buzzbot.commands;
+package net.nevet5gi.buzzbot.commands;
-import net.nevet5.buzzbot.commands.utils.CommandContext;
-import net.nevet5.buzzbot.commands.utils.ICommand;
+import net.nevet5gi.buzzbot.commands.utils.CommandContext;
+import net.nevet5gi.buzzbot.commands.utils.ICommand;
public class UnbanCmd implements ICommand {
@Override
diff --git a/src/main/java/net/nevet5/buzzbot/commands/UnmuteCmd.java b/src/main/java/net/nevet5gi/buzzbot/commands/UnmuteCmd.java
similarity index 71%
rename from src/main/java/net/nevet5/buzzbot/commands/UnmuteCmd.java
rename to src/main/java/net/nevet5gi/buzzbot/commands/UnmuteCmd.java
index a618649..4af7ec3 100644
--- a/src/main/java/net/nevet5/buzzbot/commands/UnmuteCmd.java
+++ b/src/main/java/net/nevet5gi/buzzbot/commands/UnmuteCmd.java
@@ -1,7 +1,7 @@
-package net.nevet5.buzzbot.commands;
+package net.nevet5gi.buzzbot.commands;
-import net.nevet5.buzzbot.commands.utils.CommandContext;
-import net.nevet5.buzzbot.commands.utils.ICommand;
+import net.nevet5gi.buzzbot.commands.utils.CommandContext;
+import net.nevet5gi.buzzbot.commands.utils.ICommand;
public class UnmuteCmd implements ICommand {
@Override
diff --git a/src/main/java/net/nevet5/buzzbot/commands/UnwarnCmd.java b/src/main/java/net/nevet5gi/buzzbot/commands/UnwarnCmd.java
similarity index 75%
rename from src/main/java/net/nevet5/buzzbot/commands/UnwarnCmd.java
rename to src/main/java/net/nevet5gi/buzzbot/commands/UnwarnCmd.java
index 845dbea..58d0615 100644
--- a/src/main/java/net/nevet5/buzzbot/commands/UnwarnCmd.java
+++ b/src/main/java/net/nevet5gi/buzzbot/commands/UnwarnCmd.java
@@ -1,7 +1,7 @@
-package net.nevet5.buzzbot.commands;
+package net.nevet5gi.buzzbot.commands;
-import net.nevet5.buzzbot.commands.utils.CommandContext;
-import net.nevet5.buzzbot.commands.utils.ICommand;
+import net.nevet5gi.buzzbot.commands.utils.CommandContext;
+import net.nevet5gi.buzzbot.commands.utils.ICommand;
public class UnwarnCmd implements ICommand {
//TODO Make this command only work for warns that were given from the same server
diff --git a/src/main/java/net/nevet5gi/buzzbot/commands/WarnCmd.java b/src/main/java/net/nevet5gi/buzzbot/commands/WarnCmd.java
new file mode 100644
index 0000000..6740052
--- /dev/null
+++ b/src/main/java/net/nevet5gi/buzzbot/commands/WarnCmd.java
@@ -0,0 +1,38 @@
+package net.nevet5gi.buzzbot.commands;
+
+import net.dv8tion.jda.api.interactions.commands.build.CommandData;
+import net.nevet5gi.buzzbot.commands.utils.CommandContext;
+import net.nevet5gi.buzzbot.commands.utils.ICommand;
+import net.nevet5gi.buzzbot.commands.utils.ISlashCommand;
+
+public class WarnCmd implements ICommand, ISlashCommand {
+ @Override
+ public void handle(CommandContext ctx) {
+ ctx.getMessage().reply("This command has not been implemented yet").queue();
+ }
+
+ @Override
+ public void handleSlash(CommandContext ctx) {
+ ctx.getSlashEvent().getHook().sendMessage("This command has not been implemented yet").queue();
+ }
+
+ @Override
+ public String getName() {
+ return "warn";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Warns specified user";
+ }
+
+ @Override
+ public CommandData getCommandData() {
+ return new CommandData(this.getName(), this.getDescription());
+ }
+
+ @Override
+ public String getHelp() {
+ return "Warns the specified user";
+ }
+}
diff --git a/src/main/java/net/nevet5/buzzbot/commands/utils/CommandContext.java b/src/main/java/net/nevet5gi/buzzbot/commands/utils/CommandContext.java
similarity index 61%
rename from src/main/java/net/nevet5/buzzbot/commands/utils/CommandContext.java
rename to src/main/java/net/nevet5gi/buzzbot/commands/utils/CommandContext.java
index b6e90c1..2fd75ab 100644
--- a/src/main/java/net/nevet5/buzzbot/commands/utils/CommandContext.java
+++ b/src/main/java/net/nevet5gi/buzzbot/commands/utils/CommandContext.java
@@ -1,13 +1,15 @@
-package net.nevet5.buzzbot.commands.utils;
+package net.nevet5gi.buzzbot.commands.utils;
import me.duncte123.botcommons.commands.ICommandContext;
import net.dv8tion.jda.api.entities.Guild;
+import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import java.util.List;
public class CommandContext implements ICommandContext {
- private final GuildMessageReceivedEvent event;
+ private GuildMessageReceivedEvent event;
+ private SlashCommandEvent slashEvent;
private final List args;
public CommandContext(GuildMessageReceivedEvent event, List args) {
@@ -15,6 +17,11 @@ public class CommandContext implements ICommandContext {
this.args = args;
}
+ public CommandContext(SlashCommandEvent slashEvent, List args) {
+ this.slashEvent = slashEvent;
+ this.args = args;
+ }
+
@Override
public Guild getGuild() {
return null;
@@ -25,6 +32,10 @@ public class CommandContext implements ICommandContext {
return this.event;
}
+ public SlashCommandEvent getSlashEvent() {
+ return this.slashEvent;
+ }
+
public List getArgs() {
return this.args;
}
diff --git a/src/main/java/net/nevet5gi/buzzbot/commands/utils/CommandManager.java b/src/main/java/net/nevet5gi/buzzbot/commands/utils/CommandManager.java
new file mode 100644
index 0000000..34e8a0a
--- /dev/null
+++ b/src/main/java/net/nevet5gi/buzzbot/commands/utils/CommandManager.java
@@ -0,0 +1,124 @@
+package net.nevet5gi.buzzbot.commands.utils;
+
+import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
+import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
+import net.dv8tion.jda.api.interactions.commands.build.CommandData;
+import net.nevet5gi.buzzbot.Bot;
+import net.nevet5gi.buzzbot.Config;
+import net.nevet5gi.buzzbot.commands.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Pattern;
+
+public class CommandManager {
+ private static final Logger LOGGER = LoggerFactory.getLogger(CommandManager.class);
+ protected final List commands = new ArrayList<>();
+ protected static List slashList = new ArrayList<>();
+
+ public CommandManager() {
+ //Add to this list in alphabetical order
+ addCommand(new BanCmd());
+ addCommand(new HelpCmd(this));
+ addCommand(new MuteCmd());
+ addCommand(new PandaCmd());
+ addCommand(new PingCmd());
+ addCommand(new TestCmd());
+ addCommand(new UnbanCmd());
+ addCommand(new UnmuteCmd());
+ addCommand(new UnwarnCmd());
+ addCommand(new WarnCmd());
+ //addCommand(new CommandClass());
+ }
+
+ private void addCommand(ICmdGeneric cmd) {
+ boolean nameFound = commands.stream().anyMatch((it) -> it.getName().equalsIgnoreCase(cmd.getName()));
+ if (nameFound) {
+ throw new IllegalArgumentException("A command with this name is already present");
+ }
+
+ if (cmd instanceof ICommand) {
+ commands.add((ICommand) cmd);
+ }
+
+ if (cmd instanceof ISlashCommand) {
+ slashList.add(((ISlashCommand) cmd));
+ }
+ }
+
+ public static void registerSlashCommands() {
+ if (slashList != null) {
+ List cmdDataList = new ArrayList<>();
+ for (ISlashCommand slashCmd : slashList) {
+ cmdDataList.add(slashCmd.getCommandData());
+ }
+ Bot.jda.updateCommands().addCommands(cmdDataList).queue();
+ }
+ }
+
+ public List getCommands() {
+ return commands;
+ }
+
+ @Nullable
+ public ICommand getCommand(String search) {
+ String searchLower = search.toLowerCase();
+
+ for (ICommand cmd : commands) {
+ if (cmd.getName().equals(searchLower) || cmd.getAliases().contains(searchLower)) {
+ return cmd;
+ }
+ }
+
+ return null;
+ }
+
+ @Nullable
+ public ISlashCommand getSlashCommand(String search) {
+ String searchLower = search.toLowerCase();
+
+ for (ISlashCommand scmd : slashList) {
+ if (scmd.getName().equals(searchLower) || scmd.getAliases().contains(searchLower)) {
+ return scmd;
+ }
+ }
+
+ return null;
+ }
+
+ public void handle(GuildMessageReceivedEvent event) {
+ String[] split = event.getMessage().getContentRaw()
+ .replaceFirst("(?i)" + Pattern.quote(Config.getConfig().getString("bot.prefix")), "")
+ .split("\\s+");
+
+ String invoke = split[0].toLowerCase();
+ ICommand cmd = getCommand(invoke);
+
+ if (cmd != null) {
+ event.getChannel().sendTyping().queue();
+ List args = Arrays.asList(split).subList(1, split.length);
+
+ CommandContext ctx = new CommandContext(event, args);
+
+ cmd.handle(ctx);
+ }
+ }
+
+ public void handle(SlashCommandEvent event) {
+ String invoke = event.getName();
+ ISlashCommand cmd = getSlashCommand(invoke);
+
+ if (cmd != null) {
+ event.deferReply().queue();
+ List args = new ArrayList<>();
+
+ CommandContext ctx = new CommandContext(event, args);
+
+ cmd.handleSlash(ctx);
+ }
+ }
+}
diff --git a/src/main/java/net/nevet5gi/buzzbot/commands/utils/ICmdGeneric.java b/src/main/java/net/nevet5gi/buzzbot/commands/utils/ICmdGeneric.java
new file mode 100644
index 0000000..8ae5b55
--- /dev/null
+++ b/src/main/java/net/nevet5gi/buzzbot/commands/utils/ICmdGeneric.java
@@ -0,0 +1,14 @@
+package net.nevet5gi.buzzbot.commands.utils;
+
+import java.util.List;
+
+public interface ICmdGeneric {
+
+ String getName();
+
+ String getHelp();
+
+ default List getAliases(){
+ return List.of();
+ }
+}
diff --git a/src/main/java/net/nevet5gi/buzzbot/commands/utils/ICommand.java b/src/main/java/net/nevet5gi/buzzbot/commands/utils/ICommand.java
new file mode 100644
index 0000000..5e17c90
--- /dev/null
+++ b/src/main/java/net/nevet5gi/buzzbot/commands/utils/ICommand.java
@@ -0,0 +1,7 @@
+package net.nevet5gi.buzzbot.commands.utils;
+
+public interface ICommand extends ICmdGeneric {
+
+ void handle(CommandContext ctx);
+
+}
diff --git a/src/main/java/net/nevet5gi/buzzbot/commands/utils/ISlashCommand.java b/src/main/java/net/nevet5gi/buzzbot/commands/utils/ISlashCommand.java
new file mode 100644
index 0000000..1ce0857
--- /dev/null
+++ b/src/main/java/net/nevet5gi/buzzbot/commands/utils/ISlashCommand.java
@@ -0,0 +1,11 @@
+package net.nevet5gi.buzzbot.commands.utils;
+
+import net.dv8tion.jda.api.interactions.commands.build.CommandData;
+
+public interface ISlashCommand extends ICmdGeneric {
+ void handleSlash(CommandContext ctx);
+
+ String getDescription();
+
+ CommandData getCommandData();
+}
diff --git a/src/main/java/net/nevet5gi/buzzbot/database/SqlDB.java b/src/main/java/net/nevet5gi/buzzbot/database/SqlDB.java
new file mode 100644
index 0000000..9115c7a
--- /dev/null
+++ b/src/main/java/net/nevet5gi/buzzbot/database/SqlDB.java
@@ -0,0 +1,169 @@
+package net.nevet5gi.buzzbot.database;
+
+import net.nevet5gi.buzzbot.Config;
+import net.nevet5gi.buzzbot.objects.BanData;
+import net.nevet5gi.buzzbot.objects.GuildData;
+import net.nevet5gi.buzzbot.objects.MuteData;
+import net.nevet5gi.buzzbot.objects.WarnData;
+
+import java.sql.*;
+
+public class SqlDB {
+ //TODO Make this a two way class for reading and writing from db
+
+ private Connection connect;
+ private Statement statement;
+ private ResultSet resultSet;
+
+ public SqlDB() {
+ try {
+ Class.forName("com.mysql.cj.jdbc.Driver");
+ connect = DriverManager.getConnection("jdbc:mysql://" + Config.getConfig().getString("database.url") + "/" + Config.getConfig().getString("database.database"), Config.getConfig().getString("database.user"), Config.getConfig().getString("database.password"));
+ statement = connect.createStatement();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void insertBan(BanData ban, String table) {
+ try {
+ statement.executeUpdate("INSERT INTO " + table + " VALUES (default, " + ban.getUserId() + ", '" + ban.getUserName() + "', '" + ban.getUserDiscriminator() + "', '" + ban.getDate() + "', '" + ban.getTime() + "', " + ban.getBanType() + ", " + ban.getBanLength() + ", '" + ban.getBanReason() + "', '" + ban.getModName() + "', " + ban.getModId() + ", '" + ban.getServerName() + "', " + ban.getServerId() + ")");
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ close();
+ }
+
+ public void insertMute(MuteData mute, String table) {
+ try {
+ statement.executeUpdate("INSERT INTO " + table + " VALUES (default, " + mute.getUserId() + ", '" + mute.getUserName() + "', '" + mute.getUserDiscriminator() + "', '" + mute.getDate() + "', '" + mute.getTime() + "', " + mute.getMuteLength() + ", '" + mute.getMuteReason() + "', '" + mute.getModName() + "', " + mute.getModId() + ", '" + mute.getServerName() + "', " + mute.getServerId() + ")");
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void insertWarn(WarnData warn, String table) {
+ try {
+ statement.executeUpdate("INSERT INTO " + table + " VALUES (default, " + warn.getUserId() + ", '" + warn.getUserName() + "', '" + warn.getUserDiscriminator() + "', '" + warn.getDate() + "', '" + warn.getTime() + "', " + warn.getBanType() + ", " + warn.getBanLength() + ", '" + warn.getBanReason() + "', '" + warn.getModName() + "', " + warn.getModId() + ", '" + warn.getServerName() + "', " + warn.getServerId() + ")");
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public BanData queryBan(long userId, String table) {
+ BanData ban = new BanData();
+
+ try {
+ //TODO Make this use GuildUtils in order to get the proper group for the server
+
+ resultSet = statement.executeQuery("SELECT * FROM " + table + " WHERE userId=" + userId);
+
+ while (resultSet.next()) {
+ ban.setUserId(resultSet.getLong("userid"));
+ ban.setUserName(resultSet.getString("username"));
+ ban.setUserDiscriminator(resultSet.getInt("userdiscriminator"));
+ ban.setDate(resultSet.getDate("bandate"));
+ ban.setTime(resultSet.getTime("bantime"));
+ ban.setBanType(resultSet.getBoolean("bantype"));
+ ban.setBanLength(resultSet.getInt("banlength"));
+ ban.setBanReason(resultSet.getString("banreason"));
+ ban.setModName(resultSet.getString("modname"));
+ ban.setModId(resultSet.getLong("modid"));
+ ban.setServerName(resultSet.getString("servername"));
+ ban.setServerId(resultSet.getLong("serverid"));
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ return null;
+ }
+
+ close();
+ return ban;
+ }
+
+ public MuteData queryMute(long userId, String table) {
+ MuteData mute = new MuteData();
+
+ try {
+ resultSet = statement.executeQuery("SELECT * FROM " + table + "WHERE userId=" + userId);
+
+ while (resultSet.next()) {
+ mute.setUserId(resultSet.getLong("userid"));
+ mute.setUserName(resultSet.getString("username"));
+ mute.setUserDiscriminator(resultSet.getInt("userdiscriminator"));
+ //mute.setDate(resultSet.);
+ }
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+
+ return mute;
+ }
+
+ public WarnData queryWarn(long userId, String table) {
+ WarnData warn = new WarnData();
+
+ try {
+ resultSet = statement.executeQuery("SELECT * FROM " + table + "WHERE userId=" + userId);
+
+ while (resultSet.next()) {
+ warn.setUserId(resultSet.getLong("userid"));
+ warn.setUserName(resultSet.getString("username"));
+ warn.setUserDiscriminator(resultSet.getInt("userdiscriminator"));
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ return warn;
+ }
+
+ public void addGuild(GuildData guild) {
+ try {
+ statement.executeUpdate("INSERT INTO guild_settings VALUES (\"" + guild.getName() + "\", " + guild.getId() + ", \"" + guild.getGroup() + "\", " + guild.getProfanityLevel() + ")");
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ close();
+ }
+
+ public GuildData getGuildData(long guildId) {
+ GuildData guild = new GuildData();
+
+ try {
+ resultSet = statement.executeQuery("SELECT * FROM guild_settings WHERE guild_id=" + guildId);
+
+ while (resultSet.next()) {
+ guild.setName(resultSet.getString("guild_name"));
+ guild.setId(resultSet.getLong("guild_id"));
+ guild.setGroup(resultSet.getString("guild_group"));
+ guild.setProfanityLevel(resultSet.getInt("profanity_level"));
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ return guild;
+ }
+
+ private void close() {
+ try {
+ if (resultSet != null) {
+ resultSet.close();
+ }
+
+ if (statement != null) {
+ statement.close();
+ }
+
+ if (connect != null) {
+ connect.close();
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/src/main/java/net/nevet5gi/buzzbot/functions/ProfanityFilter.java b/src/main/java/net/nevet5gi/buzzbot/functions/ProfanityFilter.java
new file mode 100644
index 0000000..b298cdf
--- /dev/null
+++ b/src/main/java/net/nevet5gi/buzzbot/functions/ProfanityFilter.java
@@ -0,0 +1,109 @@
+package net.nevet5gi.buzzbot.functions;
+
+import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
+import net.dv8tion.jda.api.events.message.guild.GuildMessageUpdateEvent;
+import net.nevet5gi.buzzbot.Config;
+import net.nevet5gi.buzzbot.util.Dictionary;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class ProfanityFilter {
+ private final Dictionary mildDictionary;
+ private final Dictionary moderateDictionary;
+ private final Dictionary strongDictionary;
+
+ public ProfanityFilter() {
+ mildDictionary = new Dictionary();
+ moderateDictionary = new Dictionary();
+ strongDictionary = new Dictionary();
+ }
+
+ public void handle(GuildMessageReceivedEvent event) {
+ event.getMessage().delete().queue();
+ event.getChannel().sendMessage("No swearing please :)").queue();
+ }
+
+ public void handleEdit(GuildMessageUpdateEvent event) {
+ event.getMessage().delete().queue();
+ event.getChannel().sendMessage("Nice try ;)").queue();
+ }
+
+ public void buildDictionaries() {
+ String mildPath = Config.getConfig().getString("filter.path.mild");
+ String moderatePath = Config.getConfig().getString("filter.path.moderate");
+ String strongPath = Config.getConfig().getString("filter.path.strong");
+
+ String line;
+ BufferedReader in = null;
+
+ try {
+ in = new BufferedReader(new FileReader(mildPath));
+ while ((line = in.readLine()) != null) {
+ mildDictionary.addToDictionary(line);
+ moderateDictionary.addToDictionary(line);
+ strongDictionary.addToDictionary(line);
+ }
+
+ in = new BufferedReader(new FileReader(moderatePath));
+ while ((line = in.readLine()) != null) {
+ moderateDictionary.addToDictionary(line);
+ strongDictionary.addToDictionary(line);
+ }
+
+ in = new BufferedReader(new FileReader(strongPath));
+ while ((line = in.readLine()) != null) {
+ strongDictionary.addToDictionary(line);
+ }
+
+ } catch (FileNotFoundException e) { // FileReader
+ e.printStackTrace();
+ } catch (IOException e) { // readLine
+ e.printStackTrace();
+ } finally {
+ try {
+ in.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public boolean containsProfanity(String input, String strength) {
+ Dictionary dictionary = null;
+
+ switch (strength) {
+ case "mild" -> dictionary = mildDictionary;
+ case "moderate" -> dictionary = moderateDictionary;
+ case "strong" -> dictionary = strongDictionary;
+ }
+
+ if (dictionary == null) {
+ dictionary = new Dictionary();
+ }
+
+ input = convert(input);
+
+ for (String profanity : dictionary.getDictionary()) {
+ String pattern = "\\b" + Pattern.quote(profanity) + "\\b";
+ Pattern p = Pattern.compile(pattern);
+ Matcher m = p.matcher(input);
+ if (m.find()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public String convert(String input) {
+ return input.toLowerCase()
+ .replace("@", "a")
+ .replace("$", "s")
+ .replace("!", "i")
+ .replace("(", "c");
+ }
+}
diff --git a/src/main/java/net/nevet5/buzzbot/objects/BanData.java b/src/main/java/net/nevet5gi/buzzbot/objects/BanData.java
similarity index 96%
rename from src/main/java/net/nevet5/buzzbot/objects/BanData.java
rename to src/main/java/net/nevet5gi/buzzbot/objects/BanData.java
index dc601d6..f05e3d1 100644
--- a/src/main/java/net/nevet5/buzzbot/objects/BanData.java
+++ b/src/main/java/net/nevet5gi/buzzbot/objects/BanData.java
@@ -1,4 +1,4 @@
-package net.nevet5.buzzbot.objects;
+package net.nevet5gi.buzzbot.objects;
import java.sql.Date;
import java.sql.Time;
diff --git a/src/main/java/net/nevet5gi/buzzbot/objects/GuildData.java b/src/main/java/net/nevet5gi/buzzbot/objects/GuildData.java
new file mode 100644
index 0000000..cf80943
--- /dev/null
+++ b/src/main/java/net/nevet5gi/buzzbot/objects/GuildData.java
@@ -0,0 +1,40 @@
+package net.nevet5gi.buzzbot.objects;
+
+public class GuildData {
+ private String name;
+ private long id;
+ private String group;
+ private int profanityLevel;
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setGroup(String group) {
+ this.group = group;
+ }
+
+ public String getGroup() {
+ return group;
+ }
+
+ public void setProfanityLevel(int level) {
+ this.profanityLevel = level;
+ }
+
+ public int getProfanityLevel() {
+ return profanityLevel;
+ }
+}
diff --git a/src/main/java/net/nevet5/buzzbot/objects/MuteData.java b/src/main/java/net/nevet5gi/buzzbot/objects/MuteData.java
similarity index 95%
rename from src/main/java/net/nevet5/buzzbot/objects/MuteData.java
rename to src/main/java/net/nevet5gi/buzzbot/objects/MuteData.java
index 708f3e1..6442b0b 100644
--- a/src/main/java/net/nevet5/buzzbot/objects/MuteData.java
+++ b/src/main/java/net/nevet5gi/buzzbot/objects/MuteData.java
@@ -1,4 +1,4 @@
-package net.nevet5.buzzbot.objects;
+package net.nevet5gi.buzzbot.objects;
import java.sql.Date;
import java.sql.Time;
diff --git a/src/main/java/net/nevet5/buzzbot/objects/UserData.java b/src/main/java/net/nevet5gi/buzzbot/objects/UserData.java
similarity index 98%
rename from src/main/java/net/nevet5/buzzbot/objects/UserData.java
rename to src/main/java/net/nevet5gi/buzzbot/objects/UserData.java
index 61d392d..f7d2b03 100644
--- a/src/main/java/net/nevet5/buzzbot/objects/UserData.java
+++ b/src/main/java/net/nevet5gi/buzzbot/objects/UserData.java
@@ -1,4 +1,4 @@
-package net.nevet5.buzzbot.objects;
+package net.nevet5gi.buzzbot.objects;
import java.sql.Date;
import java.sql.Time;
diff --git a/src/main/java/net/nevet5/buzzbot/objects/WarnData.java b/src/main/java/net/nevet5gi/buzzbot/objects/WarnData.java
similarity index 96%
rename from src/main/java/net/nevet5/buzzbot/objects/WarnData.java
rename to src/main/java/net/nevet5gi/buzzbot/objects/WarnData.java
index 1b7e61e..513baa3 100644
--- a/src/main/java/net/nevet5/buzzbot/objects/WarnData.java
+++ b/src/main/java/net/nevet5gi/buzzbot/objects/WarnData.java
@@ -1,4 +1,4 @@
-package net.nevet5.buzzbot.objects;
+package net.nevet5gi.buzzbot.objects;
import java.sql.Date;
import java.sql.Time;
diff --git a/src/main/java/net/nevet5gi/buzzbot/util/Dictionary.java b/src/main/java/net/nevet5gi/buzzbot/util/Dictionary.java
new file mode 100644
index 0000000..bc65adb
--- /dev/null
+++ b/src/main/java/net/nevet5gi/buzzbot/util/Dictionary.java
@@ -0,0 +1,15 @@
+package net.nevet5gi.buzzbot.util;
+
+import java.util.ArrayList;
+
+public class Dictionary {
+ private final ArrayList dictionary = new ArrayList<>();
+
+ public void addToDictionary(String word) {
+ dictionary.add(word);
+ }
+
+ public ArrayList getDictionary() {
+ return dictionary;
+ }
+}
diff --git a/src/main/java/net/nevet5gi/buzzbot/util/JsonUtils.java b/src/main/java/net/nevet5gi/buzzbot/util/JsonUtils.java
new file mode 100644
index 0000000..d33d3be
--- /dev/null
+++ b/src/main/java/net/nevet5gi/buzzbot/util/JsonUtils.java
@@ -0,0 +1,39 @@
+package net.nevet5gi.buzzbot.util;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import net.nevet5gi.buzzbot.objects.UserData;
+
+import java.io.*;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+
+public class JsonUtils {
+ T object;
+
+ public void createJson(T object) {
+ try {
+ Writer writer = new FileWriter("./" + object.getName() + ".json");
+
+ GsonBuilder builder = new GsonBuilder();
+ builder.setPrettyPrinting();
+ Gson gson = builder.create();
+ String jsonString = gson.toJson(object);
+ writer.write(jsonString);
+ writer.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public T loadJson(String jsonFileName) {
+ try {
+ BufferedReader reader = new BufferedReader(new FileReader("./" + jsonFileName + ".json"));
+
+ return new Gson().fromJson(reader, (Type) object);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+}
\ No newline at end of file