Skip to content

Commit 102ed7e

Browse files
committed
Switch to DB-backed channel configuration
Closes #3
1 parent 63be9fc commit 102ed7e

File tree

8 files changed

+241
-91
lines changed

8 files changed

+241
-91
lines changed

build.gradle.kts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
plugins {
22
id("java")
33
application
4+
kotlin("jvm") version "1.6.10"
45
}
56

67
group = "pw.chew"
@@ -22,7 +23,9 @@ dependencies {
2223
implementation("pw.chew", "jda-chewtils", "2.0-SNAPSHOT")
2324
implementation("org.json", "json", "20230227")
2425
implementation("ch.qos.logback", "logback-classic", "1.4.5")
26+
implementation("mysql", "mysql-connector-java", "8.0.28")
2527
implementation("org.mapdb", "mapdb", "3.0.9")
28+
implementation("org.hibernate", "hibernate-core", "5.6.5.Final")
2629
implementation("com.github.ben-manes.caffeine", "caffeine", "3.1.0")
2730

2831
testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.1")
@@ -33,6 +36,11 @@ tasks.getByName<Test>("test") {
3336
useJUnitPlatform()
3437
}
3538

39+
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
40+
kotlinOptions.jvmTarget = "17"
41+
kotlinOptions.apiVersion = "1.6"
42+
}
43+
3644
application {
3745
mainClass.set("pw.chew.mlb.MLBBot")
3846
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright (C) 2021 Chewbotcca
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
package pw.chew.chewbotcca.util;
18+
19+
import org.hibernate.SessionFactory;
20+
import org.hibernate.boot.MetadataSources;
21+
import org.hibernate.boot.registry.StandardServiceRegistry;
22+
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
23+
import pw.chew.mlb.models.Channel;
24+
25+
import java.io.File;
26+
27+
public class DatabaseHelper {
28+
private static SessionFactory sessionFactory;
29+
30+
public static void openConnection() {
31+
// A SessionFactory is set up once for an application!
32+
final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
33+
.loadProperties(new File("bot.properties"))
34+
.build();
35+
try {
36+
sessionFactory = new MetadataSources(registry)
37+
// MLB Bot - Change to channel
38+
.addAnnotatedClass(Channel.class)
39+
.buildMetadata()
40+
.buildSessionFactory();
41+
} catch (Exception e) {
42+
// The registry would be destroyed by the SessionFactory, but we had trouble building the SessionFactory
43+
// so destroy it manually.
44+
e.printStackTrace();
45+
StandardServiceRegistryBuilder.destroy(registry);
46+
}
47+
}
48+
49+
public static SessionFactory getSessionFactory() {
50+
return sessionFactory;
51+
}
52+
}

src/main/java/pw/chew/mlb/MLBBot.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.json.JSONObject;
1111
import org.slf4j.Logger;
1212
import org.slf4j.LoggerFactory;
13+
import pw.chew.chewbotcca.util.DatabaseHelper;
1314
import pw.chew.chewbotcca.util.RestClient;
1415
import pw.chew.mlb.commands.AdminCommand;
1516
import pw.chew.mlb.commands.ConfigCommand;
@@ -40,11 +41,16 @@ public static void main(String[] args) throws IOException {
4041
Properties prop = new Properties();
4142
prop.load(new FileInputStream("bot.properties"));
4243

44+
// Initialize Database for storage
45+
logger.info("Connecting to database...");
46+
DatabaseHelper.openConnection();
47+
logger.info("Connected!");
48+
4349
// Initialize the waiter and client
4450
CommandClientBuilder client = new CommandClientBuilder();
4551

4652
// Set the client settings
47-
client.setActivity(Activity.customStatus("off day! see you tomorrow for WC :)"));
53+
client.setActivity(Activity.customStatus("Thank you everyone for an amazing season. Lot of new features planned for 2024. Stay tuned :)"));
4854
client.setOwnerId("476488167042580481");
4955
client.setPrefix("woody!");
5056

src/main/java/pw/chew/mlb/commands/AdminCommand.java

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import com.jagrosh.jdautilities.command.Command;
44
import com.jagrosh.jdautilities.command.CommandEvent;
5-
import com.jagrosh.jdautilities.menu.EmbedPaginator;
65
import com.jagrosh.jdautilities.menu.Paginator;
76
import net.dv8tion.jda.api.EmbedBuilder;
87
import net.dv8tion.jda.api.entities.Activity;
@@ -13,7 +12,6 @@
1312
import pw.chew.mlb.MLBBot;
1413
import pw.chew.mlb.listeners.GameFeedHandler;
1514
import pw.chew.mlb.objects.ActiveGame;
16-
import pw.chew.mlb.objects.ChannelConfig;
1715

1816
import java.io.File;
1917
import java.util.ArrayList;
@@ -39,8 +37,6 @@ protected void execute(CommandEvent event) {
3937

4038
if (args.startsWith("games")) {
4139
activeGames(event);
42-
} else if (args.startsWith("config")) {
43-
config(event);
4440
} else if (args.startsWith("stats")) {
4541
botStats(event);
4642
} else if (args.startsWith("export")) {
@@ -81,27 +77,6 @@ private void export(CommandEvent event) {
8177
}
8278
}
8379

84-
private void config(CommandEvent event) {
85-
var config = new EmbedPaginator.Builder()
86-
.waitOnSinglePage(false)
87-
.setFinalAction(m -> {
88-
try {
89-
m.clearReactions().queue();
90-
} catch(PermissionException ignored) { }
91-
})
92-
.setEventWaiter(MLBBot.waiter)
93-
.setTimeout(1, TimeUnit.MINUTES)
94-
.clearItems();
95-
96-
for (String key : ConfigCommand.channelsMap.keySet()) {
97-
ChannelConfig channelConfig = ConfigCommand.channelsMap.get(key);
98-
if (channelConfig == null) continue;
99-
config.addItems(ConfigCommand.ConfigGetSubCommand.buildConfigEmbed(channelConfig, key));
100-
}
101-
102-
config.setText("There are %s total configs".formatted(ConfigCommand.channelsMap.size())).build().display(event.getChannel());
103-
}
104-
10580
public void activeGames(CommandEvent event) {
10681
var activeGames = new Paginator.Builder().setColumns(1)
10782
.setItemsPerPage(10)

src/main/java/pw/chew/mlb/commands/ConfigCommand.java

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,11 @@
88
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
99
import net.dv8tion.jda.api.interactions.commands.OptionType;
1010
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
11-
import org.mapdb.DB;
12-
import org.mapdb.DBMaker;
13-
import org.mapdb.HTreeMap;
14-
import org.mapdb.Serializer;
1511
import pw.chew.mlb.objects.ChannelConfig;
1612

1713
import java.util.Arrays;
1814

1915
public class ConfigCommand extends SlashCommand {
20-
private static final DB db = DBMaker.fileDB("channels.db").fileMmapEnable().closeOnJvmShutdown().checksumHeaderBypass().make();
21-
public static final HTreeMap<String, ChannelConfig> channelsMap = db
22-
.hashMap("channels", Serializer.STRING, new ChannelConfig.EntrySerializer())
23-
.createOrOpen();
24-
2516
public ConfigCommand() {
2617
this.name = "config";
2718
this.help = "Configure MLB Bot for this channel";
@@ -42,9 +33,9 @@ public ConfigGetSubCommand() {
4233

4334
@Override
4435
protected void execute(SlashCommandEvent event) {
45-
ChannelConfig config = channelsMap.get(event.getChannel().getId());
36+
ChannelConfig config = ChannelConfig.getConfig(event.getChannel().getId(), false);
4637
if (config == null) {
47-
event.reply("This channel is has not been configured, and is using default settings. Run `/config set` to get started.").setEphemeral(true).queue();
38+
event.reply("This channel has not been configured, and is using default settings. Run `/config set` to get started.").setEphemeral(true).queue();
4839
return;
4940
}
5041

@@ -70,29 +61,24 @@ public ConfigSetSubCommand() {
7061
this.userPermissions = new Permission[]{Permission.MANAGE_CHANNEL};
7162
this.options = Arrays.asList(
7263
new OptionData(OptionType.BOOLEAN, "only_scoring_plays", "Only show scoring plays"),
73-
new OptionData(OptionType.BOOLEAN, "game_advisories", "Show game advisories"),
74-
new OptionData(OptionType.INTEGER, "reach_delay", "Delay for reach (non strikeout/walk)"),
75-
new OptionData(OptionType.INTEGER, "k_or_bb_delay", "Delay for strikeout/walk")
64+
new OptionData(OptionType.BOOLEAN, "game_advisories", "Show game advisories, e.g. pitching changes"),
65+
new OptionData(OptionType.INTEGER, "in_play_delay", "Delay for \"In Play\" (non strikeout/walk)"),
66+
new OptionData(OptionType.INTEGER, "no_play_delay", "Delay for strikeout/walk, usually appears quicker")
7667
/*, new OptionData(OptionType.BOOLEAN, "show_score_on_out_3", "Show score on out 3") */
7768
);
7869
}
7970

8071
@Override
8172
protected void execute(SlashCommandEvent event) {
82-
ChannelConfig current = channelsMap.get(event.getChannel().getId());
83-
if (current == null) {
84-
current = new ChannelConfig();
85-
}
73+
ChannelConfig current = ChannelConfig.getConfig(event.getChannel().getId(), true);
8674

87-
ChannelConfig config = new ChannelConfig(
88-
event.optBoolean("only_scoring_plays", current.onlyScoringPlays()),
89-
event.optBoolean("game_advisories", current.gameAdvisories()),
90-
event.getOption("reach_delay", current.inPlayDelay(), OptionMapping::getAsInt),
91-
event.getOption("k_or_bb_delay", current.noPlayDelay(), OptionMapping::getAsInt),
92-
event.optBoolean("show_score_on_out_3", current.showScoreOnOut3())
93-
);
75+
current.update("OnlyScoringPlays", event.optBoolean("only_scoring_plays", current.onlyScoringPlays()));
76+
current.update("GameAdvisories", event.optBoolean("game_advisories", current.gameAdvisories()));
77+
current.update("InPlayDelay", event.getOption("in_play_delay", current.inPlayDelay(), OptionMapping::getAsInt));
78+
current.update("NoPlayDelay", event.getOption("no_play_delay", current.noPlayDelay(), OptionMapping::getAsInt));
79+
//current.update("showScoreOnOut3", event.optBoolean("show_score_on_out_3", current.showScoreOnOut3()));
9480

95-
channelsMap.put(event.getChannel().getId(), config);
81+
current.saveData();
9682

9783
event.reply("Configuration updated!").setEphemeral(true).queue();
9884
}

src/main/java/pw/chew/mlb/listeners/GameFeedHandler.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ public class GameFeedHandler {
4343
*/
4444
public static void addGame(ActiveGame game) {
4545
ACTIVE_GAMES.add(game);
46+
// make sure config is cached
47+
ChannelConfig.getConfig(game.channelId());
4648

4749
if (!GAME_THREADS.containsKey(game.gamePk())) {
4850
Thread thread = new Thread(() -> runGame(game.gamePk()), "Game-" + game.gamePk());
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package pw.chew.mlb.models
2+
3+
import javax.persistence.Column
4+
import javax.persistence.Entity
5+
import javax.persistence.Id
6+
import javax.persistence.Table
7+
8+
@Entity
9+
@Table(name = "channels")
10+
open class Channel {
11+
@Id
12+
@Column(name = "id", nullable = false)
13+
open var id: Long? = null
14+
15+
/**
16+
* Whether to only show scoring plays
17+
*/
18+
@Column(name = "onlyScoringPlays")
19+
open var onlyScoringPlays: Boolean = false
20+
21+
/**
22+
* Whether to show game advisories
23+
*/
24+
@Column(name = "gameAdvisories")
25+
open var gameAdvisories: Boolean = true
26+
27+
/**
28+
* The amount of time in seconds to delay an in-play ball (non strikeout/walk) before showing it. Default 13.
29+
*/
30+
@Column(name = "inPlayDelay")
31+
open var inPlayDelay: Int = 13
32+
33+
/**
34+
* The amount of time in seconds to delay a strikeout/walk before showing it. Default 18.
35+
*/
36+
@Column(name = "noPlayDelay")
37+
open var noPlayDelay: Int = 18
38+
39+
/**
40+
* Whether to show the score when the third out is recorded. Default true.
41+
*/
42+
@Column(name = "showScoreOnOut3")
43+
open var showScoreOnOut3: Boolean = true
44+
45+
fun setBoolean(info: String, newValue: Boolean) {
46+
// Dynamically call the method based on the info
47+
this.javaClass.getMethod("set${info}", Boolean::class.java).invoke(this, newValue)
48+
}
49+
50+
fun setInt(info: String, newValue: Int) {
51+
// Dynamically call the method based on the info
52+
this.javaClass.getMethod("set${info}", Int::class.java).invoke(this, newValue)
53+
}
54+
55+
fun get(info: String) {
56+
// Dynamically call the method based on the info
57+
this.javaClass.getMethod("get${info}").invoke(this)
58+
}
59+
}

0 commit comments

Comments
 (0)