Skip to content

Commit 5fbc030

Browse files
committed
Move auto icons to a database
1 parent 961e41e commit 5fbc030

File tree

14 files changed

+415
-78
lines changed

14 files changed

+415
-78
lines changed

src/commander/java/com/mcmoddev/mmdbot/commander/TheCommander.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@
100100
import net.dv8tion.jda.api.requests.RestAction;
101101
import net.dv8tion.jda.api.utils.cache.CacheFlag;
102102
import net.dv8tion.jda.api.utils.messages.MessageRequest;
103-
import okhttp3.OkHttpClient;
104103
import org.flywaydb.core.Flyway;
105104
import org.jdbi.v3.core.Jdbi;
106105
import org.slf4j.Logger;

src/core/java/com/mcmoddev/mmdbot/core/database/jdbi/JdbiFactories.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
package com.mcmoddev.mmdbot.core.database.jdbi;
2222

2323
import com.mcmoddev.mmdbot.core.util.Constants;
24+
import net.dv8tion.jda.api.entities.ISnowflake;
2425
import org.jdbi.v3.core.argument.Argument;
2526
import org.jdbi.v3.core.argument.NullArgument;
2627
import org.jdbi.v3.core.config.ConfigRegistry;
@@ -43,16 +44,21 @@
4344
public final class JdbiFactories {
4445
private static final Map<Type, ArgumentFactory<?>> BY_TYPE_FACTORIES = new HashMap<>();
4546

46-
public static final ArgumentFactory<UUID> UUID = create(Types.JAVA_OBJECT, java.util.UUID.class, ((position, statement, ctx, value) -> statement.setString(position, value.toString())));
47+
public static final ArgumentFactory<UUID> UUID = createAndRegister(Types.JAVA_OBJECT, java.util.UUID.class, ((position, statement, ctx, value) -> statement.setString(position, value.toString())));
48+
public static final ArgumentFactory<ISnowflake> SNOWFLAKE = create(Types.BIGINT, ISnowflake.class, ((position, statement, ctx, value) -> statement.setLong(position, value.getIdLong())));
4749
public static final ArgumentFactory<List> LIST = create(Types.JAVA_OBJECT, List.class, ((position, statement, ctx, value) -> statement.setString(position, Constants.Gsons.NO_PRETTY_PRINTING.toJson(value))));
4850

4951
public static <T> ArgumentFactory<T> create(int sqlType, Type type, Factory<T> factory) {
50-
final var fct = new ArgumentFactory<T>(sqlType, type) {
52+
return new ArgumentFactory<T>(sqlType, type) {
5153
@Override
5254
protected Argument build(final T value, final ConfigRegistry config) {
5355
return (position, statement, ctx) -> factory.accept(position, statement, ctx, value);
5456
}
5557
};
58+
}
59+
60+
public static <T> ArgumentFactory<T> createAndRegister(int sqlType, Type type, Factory<T> factory) {
61+
final var fct = create(sqlType, type, factory);
5662
BY_TYPE_FACTORIES.put(type, fct);
5763
return fct;
5864
}
@@ -74,10 +80,12 @@ public JdbiArgumentFactory() {
7480

7581
@Override
7682
public Optional<Argument> build(final Type type, final Object value, final ConfigRegistry config) {
77-
if (List.class.isAssignableFrom(GenericTypes.getErasedType(type))) {
83+
final Class<?> erased = GenericTypes.getErasedType(type);
84+
if (List.class.isAssignableFrom(erased)) {
7885
return LIST.build(type, value, config);
79-
}
80-
if (BY_TYPE_FACTORIES.containsKey(type)) {
86+
} else if (ISnowflake.class.isAssignableFrom(erased)) {
87+
return SNOWFLAKE.build(type, value, config);
88+
} else if (BY_TYPE_FACTORIES.containsKey(erased)) {
8189
return BY_TYPE_FACTORIES.get(type).build(type, value, config);
8290
}
8391
return Optional.empty();

src/painter/java/com/mcmoddev/mmdbot/painter/ThePainter.java

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.mcmoddev.mmdbot.core.bot.BotRegistry;
2626
import com.mcmoddev.mmdbot.core.bot.BotType;
2727
import com.mcmoddev.mmdbot.core.bot.RegisterBotType;
28+
import com.mcmoddev.mmdbot.core.database.jdbi.JdbiFactories;
2829
import com.mcmoddev.mmdbot.core.event.Events;
2930
import com.mcmoddev.mmdbot.core.util.DotenvLoader;
3031
import com.mcmoddev.mmdbot.core.util.TaskScheduler;
@@ -34,19 +35,25 @@
3435
import com.mcmoddev.mmdbot.painter.servericon.ServerIconCommand;
3536
import com.mcmoddev.mmdbot.painter.servericon.auto.AutomaticIconChanger;
3637
import com.mcmoddev.mmdbot.painter.servericon.auto.command.AutoIconSetCommand;
38+
import com.mcmoddev.mmdbot.painter.util.dao.AutoIconDAO;
39+
import com.mcmoddev.mmdbot.painter.util.dao.DayCounterDAO;
40+
import com.mcmoddev.mmdbot.painter.util.migration.AutoIconsMigration;
41+
import com.mcmoddev.mmdbot.painter.util.migration.DayCounterMigration;
3742
import io.github.cdimascio.dotenv.Dotenv;
3843
import net.dv8tion.jda.api.JDA;
3944
import net.dv8tion.jda.api.JDABuilder;
45+
import org.flywaydb.core.Flyway;
46+
import org.jdbi.v3.core.Jdbi;
47+
import org.jdbi.v3.sqlobject.SqlObjectPlugin;
4048
import org.slf4j.Logger;
4149
import org.slf4j.LoggerFactory;
50+
import org.sqlite.SQLiteDataSource;
4251

4352
import java.io.IOException;
53+
import java.nio.file.Files;
4454
import java.nio.file.Path;
45-
import java.time.Duration;
46-
import java.time.LocalDateTime;
4755
import java.time.OffsetDateTime;
4856
import java.time.ZoneId;
49-
import java.time.temporal.ChronoUnit;
5057
import java.util.Date;
5158
import java.util.GregorianCalendar;
5259
import java.util.Set;
@@ -93,6 +100,10 @@ public static ThePainter getInstance() {
93100

94101
private JDA jda;
95102

103+
private Jdbi jdbi;
104+
private DayCounterDAO dayCounter;
105+
private AutoIconDAO autoIcons;
106+
96107
public ThePainter(final Path runPath, final Dotenv dotenv) {
97108
this.dotenv = dotenv;
98109
this.runPath = runPath;
@@ -102,6 +113,10 @@ public ThePainter(final Path runPath, final Dotenv dotenv) {
102113
public void start() {
103114
instance = this;
104115

116+
this.jdbi = createDatabaseConnection(runPath);
117+
this.dayCounter = jdbi.onDemand(DayCounterDAO.class);
118+
this.autoIcons = jdbi.onDemand(AutoIconDAO.class);
119+
105120
final var commandClient = new CommandClientBuilder()
106121
.setOwnerId("000000000000")
107122
.useHelpBuilder(false)
@@ -122,6 +137,12 @@ public void start() {
122137
}
123138
}
124139

140+
@Override
141+
public void migrateData() throws IOException {
142+
AutoIconsMigration.migrate(runPath);
143+
DayCounterMigration.migrate(runPath);
144+
}
145+
125146
@Override
126147
public BotType<?> getType() {
127148
return BOT_TYPE;
@@ -140,10 +161,23 @@ public Path getRunPath() {
140161
return runPath;
141162
}
142163

164+
public Jdbi database() {
165+
return jdbi;
166+
}
167+
public DayCounterDAO dayCounter() {
168+
return dayCounter;
169+
}
170+
public AutoIconDAO autoIcon() {
171+
return autoIcons;
172+
}
173+
143174
@Override
144175
public void shutdown() {
145176
instance = null;
146177
jda.shutdownNow();
178+
jda = null;
179+
jdbi = null;
180+
dayCounter = null;
147181
}
148182

149183
@SuppressWarnings({"MagicConstant"})
@@ -153,4 +187,29 @@ private static Date measureNext12PMUTC() {
153187
calendar.set(day.getYear(), day.getMonthValue() - 1, day.getDayOfMonth(), 0, 0, 0);
154188
return calendar.getTime();
155189
}
190+
191+
public static Jdbi createDatabaseConnection(final Path runPath) {
192+
final var dbPath = runPath.resolve("data.db");
193+
if (!Files.exists(dbPath)) {
194+
try {
195+
Files.createFile(dbPath);
196+
} catch (IOException e) {
197+
throw new RuntimeException("Exception creating database!", e);
198+
}
199+
}
200+
final var url = "jdbc:sqlite:" + dbPath;
201+
SQLiteDataSource dataSource = new SQLiteDataSource();
202+
dataSource.setUrl(url);
203+
dataSource.setDatabaseName(BotRegistry.THE_PAINTER_NAME);
204+
205+
final var flyway = Flyway.configure()
206+
.dataSource(dataSource)
207+
.locations("classpath:painter/db")
208+
.load();
209+
flyway.migrate();
210+
211+
return Jdbi.create(dataSource)
212+
.installPlugin(new SqlObjectPlugin())
213+
.registerArgument(JdbiFactories.JdbiArgumentFactory.FACTORY);
214+
}
156215
}

src/painter/java/com/mcmoddev/mmdbot/painter/servericon/auto/AutomaticIconChanger.java

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import com.mcmoddev.mmdbot.core.util.Utils;
2424
import com.mcmoddev.mmdbot.painter.ThePainter;
2525
import com.mcmoddev.mmdbot.painter.util.ImageUtils;
26+
import com.mcmoddev.mmdbot.painter.util.dao.AutoIconDAO;
27+
import com.mcmoddev.mmdbot.painter.util.dao.DayCounterDAO;
2628
import lombok.extern.slf4j.Slf4j;
2729
import net.dv8tion.jda.api.EmbedBuilder;
2830
import net.dv8tion.jda.api.entities.Guild;
@@ -36,43 +38,44 @@ public class AutomaticIconChanger implements Runnable {
3638
@Override
3739
public void run() {
3840
if (ThePainter.getInstance() != null) {
39-
final var dayCounter = DayCounter.read();
40-
for (final var guild : ThePainter.getInstance().getJDA().getGuilds()) {
41+
for (final AutoIconDAO.WithGuildConfiguration withGuild : ThePainter.getInstance().autoIcon().allEnabled()) {
42+
final Guild guild = ThePainter.getInstance().getJDA().getGuildById(withGuild.guildId());
43+
if (guild == null) {
44+
ThePainter.getInstance().autoIcon().delete(withGuild.guildId());
45+
return;
46+
}
47+
4148
try {
42-
final var conf = AutomaticIconConfiguration.get(guild.getId());
43-
if (conf != null && conf.enabled()) {
44-
doRun(guild, conf, dayCounter);
45-
dayCounter.write();
46-
}
49+
doRun(guild, withGuild.configuration(), ThePainter.getInstance().dayCounter());
4750
} catch (Exception exception) {
4851
ThePainter.LOGGER.error("Encountered exception cycling icon for guild {}: ", guild, exception);
4952
}
5053
}
5154
}
5255
}
5356

54-
private void doRun(Guild guild, AutomaticIconConfiguration configuration, DayCounter dayCounter) throws Exception {
55-
final var current = dayCounter.getCurrentDay(guild);
57+
private void doRun(Guild guild, AutomaticIconConfiguration configuration, DayCounterDAO dayCounter) throws Exception {
58+
final var currentDay = dayCounter.getCurrentDay(guild);
5659
final int nextDay;
5760
final boolean backwards;
58-
if (current.backwards()) {
59-
if (current.day() <= 1) {
61+
if (dayCounter.isBackwards(guild)) {
62+
if (currentDay <= 1) {
6063
// If the current day is 1, or lower, go to the start
6164
nextDay = 2;
6265
backwards = false;
6366
} else {
6467
// Else, go to the previous day
65-
nextDay = current.day() - 1;
68+
nextDay = currentDay - 1;
6669
backwards = true;
6770
}
6871
} else {
69-
if (current.day() >= configuration.colours().size()) {
72+
if (currentDay >= configuration.colours().size()) {
7073
// If the current day is greater, or equal to the amount of colours, start going back
7174
nextDay = configuration.colours().size() - 1;
7275
backwards = true;
7376
} else {
7477
// Else, go to the next day
75-
nextDay = current.day() + 1;
78+
nextDay = currentDay + 1;
7679
backwards = false;
7780
}
7881
}
@@ -96,7 +99,7 @@ private void doRun(Guild guild, AutomaticIconConfiguration configuration, DayCou
9699
))
97100
.queue();
98101

99-
dayCounter.setDay(guild, nextDay, backwards);
102+
dayCounter.update(guild, nextDay, backwards);
100103
}
101104

102105
private RestAction<?> logChange(MessageChannel channel, Guild guild, int newColour, int currentDay, boolean backwards) {

src/painter/java/com/mcmoddev/mmdbot/painter/servericon/auto/AutomaticIconConfiguration.java

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,45 +20,51 @@
2020
*/
2121
package com.mcmoddev.mmdbot.painter.servericon.auto;
2222

23+
import com.google.common.reflect.TypeToken;
2324
import com.google.gson.Gson;
2425
import com.google.gson.GsonBuilder;
25-
import com.mcmoddev.mmdbot.painter.ThePainter;
2626
import com.mcmoddev.mmdbot.painter.servericon.IconConfiguration;
2727
import com.mcmoddev.mmdbot.painter.servericon.ServerIconMaker;
28+
import org.jdbi.v3.core.statement.StatementContext;
2829

29-
import javax.annotation.Nullable;
3030
import java.awt.image.BufferedImage;
3131
import java.io.IOException;
32-
import java.nio.file.Files;
32+
import java.lang.reflect.Type;
33+
import java.sql.ResultSet;
34+
import java.sql.SQLException;
3335
import java.util.List;
3436

35-
public record AutomaticIconConfiguration(List<Integer> colours, long logChannelId, boolean isRing, boolean enabled) {
36-
static final Gson GSON = new GsonBuilder()
37+
public record AutomaticIconConfiguration(
38+
List<Integer> colours, long logChannelId, boolean isRing, boolean enabled
39+
) {
40+
public static final Gson GSON = new GsonBuilder()
3741
.disableHtmlEscaping().create();
3842

43+
public String serializeColors() {
44+
return GSON.toJson(colours());
45+
}
46+
3947
public BufferedImage createImage(int day) throws IOException {
4048
return ServerIconMaker.createIcon(IconConfiguration.builder()
4149
.setCircular(isRing).setHasRing(isRing)
4250
.setColour(colours.get(day - 1))
4351
.build());
4452
}
4553

46-
@Nullable
47-
public static AutomaticIconConfiguration get(String guildId) throws IOException {
48-
final var path = ThePainter.getInstance().getRunPath().resolve("autoicons").resolve(guildId + ".json");
49-
if (Files.exists(path)) {
50-
try (final var reader = Files.newBufferedReader(path)) {
51-
return GSON.fromJson(reader, AutomaticIconConfiguration.class);
52-
}
54+
public static final class RowMapper implements org.jdbi.v3.core.mapper.RowMapper<AutomaticIconConfiguration> {
55+
private static final Type COLOUR_LIST_TYPE = new TypeToken<List<Integer>>() {}.getType();
56+
57+
@Override
58+
public AutomaticIconConfiguration map(final ResultSet rs, final StatementContext ctx) throws SQLException {
59+
return from(rs);
5360
}
54-
return null;
55-
}
5661

57-
public void save(String guildId) throws IOException {
58-
final var path = ThePainter.getInstance().getRunPath().resolve("autoicons").resolve(guildId + ".json");
59-
if (!Files.exists(path)) Files.createDirectories(path.getParent());
60-
try (final var writer = Files.newBufferedWriter(path)) {
61-
GSON.toJson(this, writer);
62+
public static AutomaticIconConfiguration from(final ResultSet rs) throws SQLException {
63+
return new AutomaticIconConfiguration(
64+
GSON.fromJson(rs.getString("colours"), COLOUR_LIST_TYPE),
65+
rs.getLong("log_channel"),
66+
rs.getBoolean("ring"), rs.getBoolean("enabled")
67+
);
6268
}
6369
}
6470
}

src/painter/java/com/mcmoddev/mmdbot/painter/servericon/auto/command/AutoIconEnableCommands.java

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,8 @@
2222

2323
import com.jagrosh.jdautilities.command.SlashCommand;
2424
import com.jagrosh.jdautilities.command.SlashCommandEvent;
25+
import com.mcmoddev.mmdbot.painter.ThePainter;
2526
import com.mcmoddev.mmdbot.painter.servericon.ServerIconCommand;
26-
import com.mcmoddev.mmdbot.painter.servericon.auto.AutomaticIconConfiguration;
27-
import lombok.SneakyThrows;
2827

2928
public class AutoIconEnableCommands {
3029
public static final class DisableCommand extends SlashCommand {
@@ -35,14 +34,8 @@ public DisableCommand() {
3534
}
3635

3736
@Override
38-
@SneakyThrows
3937
protected void execute(final SlashCommandEvent event) {
40-
final var cfg = AutomaticIconConfiguration.get(event.getGuild().getId());
41-
if (cfg == null) {
42-
event.getHook().editOriginal("Server has no icon configuration!").queue();
43-
return;
44-
}
45-
new AutomaticIconConfiguration(cfg.colours(), cfg.logChannelId(), cfg.isRing(), false).save(event.getGuild().getId());
38+
ThePainter.getInstance().autoIcon().setEnabled(event.getGuild(), false);
4639
event.reply("Successfully disabled auto icon.").queue();
4740
}
4841
}
@@ -55,14 +48,8 @@ public EnableCommand() {
5548
}
5649

5750
@Override
58-
@SneakyThrows
5951
protected void execute(final SlashCommandEvent event) {
60-
final var cfg = AutomaticIconConfiguration.get(event.getGuild().getId());
61-
if (cfg == null) {
62-
event.getHook().editOriginal("Server has no icon configuration!").queue();
63-
return;
64-
}
65-
new AutomaticIconConfiguration(cfg.colours(), cfg.logChannelId(), cfg.isRing(), true).save(event.getGuild().getId());
52+
ThePainter.getInstance().autoIcon().setEnabled(event.getGuild(), true);
6653
event.reply("Successfully enabled auto icon.").queue();
6754
}
6855
}

0 commit comments

Comments
 (0)