diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index c84d0fb..108b7a9 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -13,9 +13,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 + - uses: actions/checkout@v2.3.4 + - name: Set up JDK 11 + uses: actions/setup-java@v1.4.3 with: java-version: 11 - name: Grant execute permission for gradlew diff --git a/build.gradle.kts b/build.gradle.kts index 328e3eb..f2329e1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -37,8 +37,8 @@ repositories { } dependencies { - implementation(group = "net.dv8tion", name = "JDA", version = "4.2.0_195") - implementation(group = "com.jagrosh", name = "jda-utilities-command", version = "3.0.3") + implementation(group = "net.dv8tion", name = "JDA", version = "4.2.0_221") + implementation(group = "com.jagrosh", name = "jda-utilities-command", version = "3.0.4") implementation(group = "com.fasterxml.jackson.core", name = "jackson-databind", version = "2.10.1") diff --git a/src/main/java/me/duncte123/hirobot/Hiro.java b/src/main/java/me/duncte123/hirobot/Hiro.java index 42532f0..8657280 100644 --- a/src/main/java/me/duncte123/hirobot/Hiro.java +++ b/src/main/java/me/duncte123/hirobot/Hiro.java @@ -23,10 +23,7 @@ import com.jagrosh.jdautilities.command.CommandClient; import com.jagrosh.jdautilities.command.CommandClientBuilder; import com.jagrosh.jdautilities.command.CommandEvent; -import me.duncte123.hirobot.commands.CVTCommand; -import me.duncte123.hirobot.commands.DialogCommand; -import me.duncte123.hirobot.commands.RouteCommand; -import me.duncte123.hirobot.commands.ValentineCommand; +import me.duncte123.hirobot.commands.*; import me.duncte123.hirobot.database.Database; import me.duncte123.hirobot.database.SQLiteDatabase; import me.duncte123.hirobot.database.objects.Birthday; @@ -51,11 +48,8 @@ public class Hiro { public static final long GENERAL_CHANNEL_ID = 670218976932134925L; public static final long ROLES_CHANNEL_ID = 672361818429325312L; public static final long DEV_CHANNEL_ID = 677954714825916427L; - - private static final Map customEnv = new HashMap<>(); - public final JDA jda; - + private static final Map customEnv = new HashMap<>(); private final Database database; public Hiro() throws LoginException, IOException { @@ -73,25 +67,26 @@ public Hiro() throws LoginException, IOException { builder.setHelpConsumer(this::helpConsumer); builder.addCommands( - new CVTCommand(), - new RouteCommand(), - new ValentineCommand(database), - new DialogCommand() + new CVTCommand(), + new RouteCommand(), + new BdaysCommand(database), + new ValentineCommand(database), + new DialogCommand() ); final CommandClient commandClient = builder.build(); final EventManager eventManager = new EventManager(commandClient, this, database); this.jda = JDABuilder.create( - GatewayIntent.GUILD_MEMBERS, - GatewayIntent.GUILD_MESSAGES, - GatewayIntent.GUILD_MESSAGE_REACTIONS + GatewayIntent.GUILD_MEMBERS, + GatewayIntent.GUILD_MESSAGES, + GatewayIntent.GUILD_MESSAGE_REACTIONS ) - .setToken(customEnv.get("TOKEN")) - .setEventManager(eventManager) - .setMemberCachePolicy(MemberCachePolicy.NONE) - .disableCache(EnumSet.allOf(CacheFlag.class)) - .build(); + .setToken(customEnv.get("TOKEN")) + .setEventManager(eventManager) + .setMemberCachePolicy(MemberCachePolicy.NONE) + .disableCache(EnumSet.allOf(CacheFlag.class)) + .build(); this.loadBirthdays(); } @@ -113,8 +108,8 @@ private void helpConsumer(CommandEvent event) { builder.append("\n\n __").append(category == null ? "No Category" : category.getName()).append("__:\n"); } builder.append("\n`").append(textPrefix).append(prefix == null ? " " : "").append(command.getName()) - .append(command.getArguments() == null ? "`" : " " + command.getArguments() + "`") - .append(" - ").append(command.getHelp()); + .append(command.getArguments() == null ? "`" : " " + command.getArguments() + "`") + .append(" - ").append(command.getHelp()); } } @@ -125,6 +120,16 @@ private void helpConsumer(CommandEvent event) { }, (t) -> event.replyWarning("Help cannot be sent because you are blocking Direct Messages.")); } + private void loadBirthdays() throws IOException { + final var bdayInit = new File("bday.init.json5"); + + if (bdayInit.exists()) { + final List dataArray = ReactionHelpers.MAPPER.readValue(bdayInit, new TypeReference<>() {}); + + dataArray.forEach(this.database::addBirthday); + } + } + public static void main(String[] args) throws Exception { final Map envFile = loadEnvironment(); // Put stuff in the env at runtime so we don't have to worry about them cli command @@ -145,15 +150,4 @@ private static Map loadEnvironment() throws IOException { return env; } - - private void loadBirthdays() throws IOException { - final var bdayInit = new File("bday.init.json5"); - - // TODO: items are duped on boot, delete file? - if (bdayInit.exists()) { - final List dataArray = ReactionHelpers.MAPPER.readValue(bdayInit, new TypeReference<>() {}); - - dataArray.forEach(this.database::addBirthday); - } - } } diff --git a/src/main/java/me/duncte123/hirobot/commands/BdaysCommand.java b/src/main/java/me/duncte123/hirobot/commands/BdaysCommand.java new file mode 100644 index 0000000..b86617c --- /dev/null +++ b/src/main/java/me/duncte123/hirobot/commands/BdaysCommand.java @@ -0,0 +1,103 @@ +/* + * Custom bot for the Hiro Akiba fan server on discord + * Copyright (C) 2020 Duncan "duncte123" Sterken + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package me.duncte123.hirobot.commands; + +import com.jagrosh.jdautilities.command.Command; +import com.jagrosh.jdautilities.command.CommandEvent; +import me.duncte123.hirobot.database.Database; +import me.duncte123.hirobot.database.objects.Birthday; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.entities.User; + +import java.util.stream.Collectors; + +public class BdaysCommand extends Command { + private final Database database; + + public BdaysCommand(Database database) { + this.name = "bdays"; + this.help = "Manage birthdays"; + this.arguments = "[add/delete] [userid] [month-day]"; + this.ownerCommand = true; + + this.database = database; + } + + @Override + protected void execute(CommandEvent event) { + final String args = event.getArgs(); + + if (args.isEmpty()) { + listBdays(event); + return; + } + + final String[] split = args.split("\\s+", 3); + + switch (split[0]) { + case "add": + addBday(event, split); + break; + case "delete": + removeBday(event, split); + break; + default: + event.replyFormatted("I don't know what %s is", split[0]); + break; + } + } + + private void listBdays(CommandEvent event) { + final String bdays = this.database.getBirthdays() + .stream() + .map((b) -> mapBirthday(b, event.getJDA())) + .collect(Collectors.joining("\n")); + + event.reply( + new EmbedBuilder() + .setTitle("Server bdays") + .setDescription(bdays) + .build() + ); + } + + private void addBday(CommandEvent event, String[] args) { + final Birthday birthday = new Birthday( + Long.parseLong(args[1]), + args[2] + ); + + this.database.addBirthday(birthday); + event.reply("Birthday added"); + } + + private void removeBday(CommandEvent event, String[] args) { + this.database.removeBirthday(Long.parseLong(args[1])); + + event.reply("Birthday removed"); + } + + private String mapBirthday(Birthday bday, JDA jda) { + final User userById = jda.getUserById(bday.getUserId()); + final String tag = userById == null ? "" : '`' + userById.getAsTag() + '`'; + + return "<@" + bday.getUserId() + "> " + tag + ": " + bday.getDate(); + } +} diff --git a/src/main/java/me/duncte123/hirobot/database/Database.java b/src/main/java/me/duncte123/hirobot/database/Database.java index dc20209..c53d79c 100644 --- a/src/main/java/me/duncte123/hirobot/database/Database.java +++ b/src/main/java/me/duncte123/hirobot/database/Database.java @@ -23,6 +23,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.time.LocalDate; +import java.util.List; public interface Database { @@ -37,8 +38,12 @@ public interface Database { void clearValentines(); + List getBirthdays(); + void addBirthday(@Nonnull Birthday birthday); + void removeBirthday(long userId); + @Nullable Birthday getBirthday(LocalDate date); } diff --git a/src/main/java/me/duncte123/hirobot/database/SQLiteDatabase.java b/src/main/java/me/duncte123/hirobot/database/SQLiteDatabase.java index 64a67b2..a2d47e5 100644 --- a/src/main/java/me/duncte123/hirobot/database/SQLiteDatabase.java +++ b/src/main/java/me/duncte123/hirobot/database/SQLiteDatabase.java @@ -30,6 +30,8 @@ import java.io.IOException; import java.sql.*; import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.TimeUnit; public class SQLiteDatabase implements Database { @@ -66,16 +68,16 @@ public SQLiteDatabase() { try (final Statement statement = conn.createStatement()) { // language=SQLite statement.execute("CREATE TABLE IF NOT EXISTS valentines (" + - "id INTEGER PRIMARY KEY AUTOINCREMENT," + - "user_id VARCHAR(20) NOT NULL," + - "buddy_index int(2) NOT NULL DEFAULT -1" + - ");"); + "id INTEGER PRIMARY KEY AUTOINCREMENT," + + "user_id VARCHAR(20) NOT NULL," + + "buddy_index int(2) NOT NULL DEFAULT -1" + + ");"); // language=SQLite statement.execute("CREATE TABLE IF NOT EXISTS birthdays (" + - "id INTEGER PRIMARY KEY AUTOINCREMENT," + - "user_id VARCHAR(20) NOT NULL UNIQUE," + - "date VARCHAR(5) NOT NULL" + - ");"); + "id INTEGER PRIMARY KEY AUTOINCREMENT," + + "user_id VARCHAR(20) NOT NULL UNIQUE," + + "date VARCHAR(5) NOT NULL" + + ");"); LOGGER.info("Table initialised"); } @@ -88,8 +90,8 @@ public SQLiteDatabase() { public void setValentine(long userId, int buddyIndex) { try (final Connection conn = ds.getConnection()) { try (final PreparedStatement preparedStatement = conn.prepareStatement( - // language=SQLite - "INSERT INTO valentines(buddy_index, user_id) VALUES(? , ?)" + // language=SQLite + "INSERT INTO valentines(buddy_index, user_id) VALUES(? , ?)" )) { preparedStatement.setInt(1, buddyIndex); preparedStatement.setString(2, String.valueOf(userId)); @@ -105,8 +107,8 @@ public void setValentine(long userId, int buddyIndex) { public int getValentine(long userId) { try (final Connection conn = ds.getConnection()) { try (final PreparedStatement preparedStatement = conn.prepareStatement( - // language=SQLite - "SELECT buddy_index FROM valentines WHERE user_id = ?" + // language=SQLite + "SELECT buddy_index FROM valentines WHERE user_id = ?" )) { preparedStatement.setString(1, String.valueOf(userId)); @@ -136,6 +138,28 @@ public void clearValentines() { } } + @Override + public List getBirthdays() { + final List birthdays = new ArrayList<>(); + + try (final Connection conn = ds.getConnection()) { + try (final Statement smt = conn.createStatement()) { + try (final ResultSet resultSet = smt.executeQuery("SELECT * FROM birthdays")) { + while (resultSet.next()) { + birthdays.add(new Birthday( + resultSet.getLong("user_id"), + resultSet.getString("date") + )); + } + } + } + } catch (SQLException e) { + e.printStackTrace(); + } + + return birthdays; + } + @Override public void addBirthday(@NotNull Birthday birthday) { try (final Connection conn = ds.getConnection()) { @@ -155,6 +179,22 @@ public void addBirthday(@NotNull Birthday birthday) { } } + @Override + public void removeBirthday(long userId) { + try (final Connection conn = ds.getConnection()) { + try (final PreparedStatement smt = + // language=SQLite + conn.prepareStatement("DELETE FROM birthdays WHERE user_id = ?")) { + smt.setLong(1, userId); + + smt.executeUpdate(); + smt.closeOnCompletion(); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + @Nullable @Override public Birthday getBirthday(LocalDate date) {