Compare commits

...

4 commits

22 changed files with 4740 additions and 7 deletions

7
.gitignore vendored
View file

@ -38,4 +38,9 @@ build/
.DS_Store
### Other Stuff ###
**/resources/config*.json
**/resources/config*.json
!**/resources/config.example.json
!**/resources/config.schema.json
### why would this not be here already ###
/logs/

12
.idea/dataSources.xml Normal file
View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="doki_dev@100.101.88.31" uuid="7b6e6be7-b812-4b86-aab2-e991866cb0ad">
<driver-ref>mariadb</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>org.mariadb.jdbc.Driver</jdbc-driver>
<jdbc-url>jdbc:mariadb://100.101.88.31:3306/doki_dev</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
</component>
</project>

25
.idea/jsonSchemas.xml Normal file
View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JsonSchemaMappingsProjectConfiguration">
<state>
<map>
<entry key="Doki Config">
<value>
<SchemaInfo>
<option name="generatedName" value="New Schema" />
<option name="name" value="Doki Config" />
<option name="relativePathToSchema" value="src/main/resources/config.schema.json" />
<option name="patterns">
<list>
<Item>
<option name="path" value="src/main/resources/config.json" />
</Item>
</list>
</option>
</SchemaInfo>
</value>
</entry>
</map>
</state>
</component>
</project>

View file

@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">

6
.idea/sqldialects.xml Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SqlDialectMappings">
<file url="PROJECT" dialect="MariaDB" />
</component>
</project>

160
logs/latest.log Normal file
View file

@ -0,0 +1,160 @@
00:05:09.171 JDA MainWS-ReadThread net.hypr.doki.utils.DBUtils #doesUserRecordExist L39 DBUtils DEBUG Searching DB for (usr437970062922612737,srv:445821876183367680)
00:06:54.132 JDA Gateway-Worker 1 n.d.j.i.requests.WebSocketClient #sendKeepAlive L737 WebSocketClient WARN Missed 2 heartbeats! Trying to reconnect...
00:06:54.134 JDA MainWS-ReadThread net.hypr.doki.utils.DBUtils #doesUserRecordExist L44 DBUtils DEBUG An SQL error occurred
00:06:54.134 JDA MainWS-ReadThread n.h.doki.listeners.LevellingListener #onMessageReceived L56 LevellingListener INFO No record of user ID 437970062922612737 in server 445821876183367680, creating blank record
00:06:54.135 JDA MainWS-ReadThread net.hypr.doki.utils.DBUtils #createUserRecord L58 DBUtils INFO Creating record (usr:437970062922612737,srv:445821876183367680,unm:fwoppydwisk)
00:06:54.135 JDA MainWS-ReadThread n.d.j.a.hooks.InterfacedEventManager #handle L102 JDA ERROR One of the EventListeners had an uncaught exception
java.lang.RuntimeException: java.sql.SQLException: Cannot get a connection, general error
at net.hypr.doki.listeners.LevellingListener.onMessageReceived(LevellingListener.java:60)
at net.dv8tion.jda.api.hooks.ListenerAdapter.onEvent(ListenerAdapter.java:456)
at net.dv8tion.jda.api.hooks.InterfacedEventManager.handle(InterfacedEventManager.java:98)
at net.dv8tion.jda.internal.hooks.EventManagerProxy.handleInternally(EventManagerProxy.java:88)
at net.dv8tion.jda.internal.hooks.EventManagerProxy.handle(EventManagerProxy.java:70)
at net.dv8tion.jda.internal.JDAImpl.handleEvent(JDAImpl.java:169)
at net.dv8tion.jda.internal.handle.MessageCreateHandler.handleInternally(MessageCreateHandler.java:138)
at net.dv8tion.jda.internal.handle.SocketHandler.handle(SocketHandler.java:39)
at net.dv8tion.jda.internal.requests.WebSocketClient.onDispatch(WebSocketClient.java:1009)
at net.dv8tion.jda.internal.requests.WebSocketClient.onEvent(WebSocketClient.java:892)
at net.dv8tion.jda.internal.requests.WebSocketClient.handleEvent(WebSocketClient.java:870)
at net.dv8tion.jda.internal.requests.WebSocketClient.onBinaryMessage(WebSocketClient.java:1048)
at com.neovisionaries.ws.client.ListenerManager.callOnBinaryMessage(ListenerManager.java:385)
at com.neovisionaries.ws.client.ReadingThread.callOnBinaryMessage(ReadingThread.java:276)
at com.neovisionaries.ws.client.ReadingThread.handleBinaryFrame(ReadingThread.java:996)
at com.neovisionaries.ws.client.ReadingThread.handleFrame(ReadingThread.java:755)
at com.neovisionaries.ws.client.ReadingThread.main(ReadingThread.java:108)
at com.neovisionaries.ws.client.ReadingThread.runMain(ReadingThread.java:64)
at com.neovisionaries.ws.client.WebSocketThread.run(WebSocketThread.java:45)
Caused by: java.sql.SQLException: Cannot get a connection, general error
at org.apache.commons.dbcp2.PoolingDataSource.getConnection(PoolingDataSource.java:151)
at org.apache.commons.dbcp2.BasicDataSource.getConnection(BasicDataSource.java:714)
at net.hypr.doki.utils.DBUtils.createUserRecord(DBUtils.java:60)
at net.hypr.doki.listeners.LevellingListener.onMessageReceived(LevellingListener.java:58)
... 18 common frames omitted
Caused by: java.lang.InterruptedException: null
at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1611)
at org.apache.commons.pool2.impl.LinkedBlockingDeque.takeFirst(LinkedBlockingDeque.java:1324)
at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:313)
at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:233)
at org.apache.commons.dbcp2.PoolingDataSource.getConnection(PoolingDataSource.java:139)
... 21 common frames omitted
00:06:54.508 JDA MainWS-ReadThread net.hypr.doki.utils.DBUtils #doesUserRecordExist L39 DBUtils DEBUG Searching DB for (usr437970062922612737,srv:445821876183367680)
00:08:16.901 JDA Gateway-Worker 1 n.d.j.i.requests.WebSocketClient #sendKeepAlive L737 WebSocketClient WARN Missed 2 heartbeats! Trying to reconnect...
00:08:16.902 JDA MainWS-ReadThread net.hypr.doki.utils.DBUtils #doesUserRecordExist L44 DBUtils DEBUG An SQL error occurred
00:08:16.903 JDA MainWS-ReadThread n.h.doki.listeners.LevellingListener #onMessageReceived L56 LevellingListener INFO No record of user ID 437970062922612737 in server 445821876183367680, creating blank record
00:08:16.903 JDA MainWS-ReadThread net.hypr.doki.utils.DBUtils #createUserRecord L58 DBUtils INFO Creating record (usr:437970062922612737,srv:445821876183367680,unm:fwoppydwisk)
00:08:16.903 JDA MainWS-ReadThread n.d.j.a.hooks.InterfacedEventManager #handle L102 JDA ERROR One of the EventListeners had an uncaught exception
java.lang.RuntimeException: java.sql.SQLException: Cannot get a connection, general error
at net.hypr.doki.listeners.LevellingListener.onMessageReceived(LevellingListener.java:60)
at net.dv8tion.jda.api.hooks.ListenerAdapter.onEvent(ListenerAdapter.java:456)
at net.dv8tion.jda.api.hooks.InterfacedEventManager.handle(InterfacedEventManager.java:98)
at net.dv8tion.jda.internal.hooks.EventManagerProxy.handleInternally(EventManagerProxy.java:88)
at net.dv8tion.jda.internal.hooks.EventManagerProxy.handle(EventManagerProxy.java:70)
at net.dv8tion.jda.internal.JDAImpl.handleEvent(JDAImpl.java:169)
at net.dv8tion.jda.internal.handle.MessageCreateHandler.handleInternally(MessageCreateHandler.java:138)
at net.dv8tion.jda.internal.handle.SocketHandler.handle(SocketHandler.java:39)
at net.dv8tion.jda.internal.requests.WebSocketClient.onDispatch(WebSocketClient.java:1009)
at net.dv8tion.jda.internal.requests.WebSocketClient.onEvent(WebSocketClient.java:892)
at net.dv8tion.jda.internal.requests.WebSocketClient.handleEvent(WebSocketClient.java:870)
at net.dv8tion.jda.internal.requests.WebSocketClient.onBinaryMessage(WebSocketClient.java:1048)
at com.neovisionaries.ws.client.ListenerManager.callOnBinaryMessage(ListenerManager.java:385)
at com.neovisionaries.ws.client.ReadingThread.callOnBinaryMessage(ReadingThread.java:276)
at com.neovisionaries.ws.client.ReadingThread.handleBinaryFrame(ReadingThread.java:996)
at com.neovisionaries.ws.client.ReadingThread.handleFrame(ReadingThread.java:755)
at com.neovisionaries.ws.client.ReadingThread.main(ReadingThread.java:108)
at com.neovisionaries.ws.client.ReadingThread.runMain(ReadingThread.java:64)
at com.neovisionaries.ws.client.WebSocketThread.run(WebSocketThread.java:45)
Caused by: java.sql.SQLException: Cannot get a connection, general error
at org.apache.commons.dbcp2.PoolingDataSource.getConnection(PoolingDataSource.java:151)
at org.apache.commons.dbcp2.BasicDataSource.getConnection(BasicDataSource.java:714)
at net.hypr.doki.utils.DBUtils.createUserRecord(DBUtils.java:60)
at net.hypr.doki.listeners.LevellingListener.onMessageReceived(LevellingListener.java:58)
... 18 common frames omitted
Caused by: java.lang.InterruptedException: null
at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1611)
at org.apache.commons.pool2.impl.LinkedBlockingDeque.takeFirst(LinkedBlockingDeque.java:1324)
at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:313)
at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:233)
at org.apache.commons.dbcp2.PoolingDataSource.getConnection(PoolingDataSource.java:139)
... 21 common frames omitted
00:08:19.543 JDA MainWS-ReadThread n.d.j.i.requests.WebSocketClient #handleReconnect L591 WebSocketClient WARN Got disconnected from WebSocket (Code 1000). Appending to reconnect queue
00:08:21.804 JDA MainWS-ReadThread n.d.j.i.requests.WebSocketClient #onConnected L430 WebSocketClient INFO Connected to WebSocket
00:08:22.179 JDA MainWS-ReadThread n.d.j.i.requests.WebSocketClient #ready L216 JDA INFO Finished (Re)Loading!
00:10:31.426 JDA MainWS-ReadThread net.hypr.doki.utils.DBUtils #doesUserRecordExist L39 DBUtils DEBUG Searching DB for (usr437970062922612737,srv:445821876183367680)
00:12:29.320 JDA Gateway-Worker 1 n.d.j.i.requests.WebSocketClient #sendKeepAlive L737 WebSocketClient WARN Missed 2 heartbeats! Trying to reconnect...
00:12:29.324 JDA MainWS-ReadThread net.hypr.doki.utils.DBUtils #doesUserRecordExist L44 DBUtils DEBUG An SQL error occurred
00:12:29.325 JDA MainWS-ReadThread n.h.doki.listeners.LevellingListener #onMessageReceived L56 LevellingListener INFO No record of user ID 437970062922612737 in server 445821876183367680, creating blank record
00:12:29.326 JDA MainWS-ReadThread net.hypr.doki.utils.DBUtils #createUserRecord L58 DBUtils INFO Creating record (usr:437970062922612737,srv:445821876183367680,unm:fwoppydwisk)
00:12:29.326 JDA MainWS-ReadThread n.d.j.a.hooks.InterfacedEventManager #handle L102 JDA ERROR One of the EventListeners had an uncaught exception
java.lang.RuntimeException: java.sql.SQLException: Cannot get a connection, general error
at net.hypr.doki.listeners.LevellingListener.onMessageReceived(LevellingListener.java:60)
at net.dv8tion.jda.api.hooks.ListenerAdapter.onEvent(ListenerAdapter.java:456)
at net.dv8tion.jda.api.hooks.InterfacedEventManager.handle(InterfacedEventManager.java:98)
at net.dv8tion.jda.internal.hooks.EventManagerProxy.handleInternally(EventManagerProxy.java:88)
at net.dv8tion.jda.internal.hooks.EventManagerProxy.handle(EventManagerProxy.java:70)
at net.dv8tion.jda.internal.JDAImpl.handleEvent(JDAImpl.java:169)
at net.dv8tion.jda.internal.handle.MessageCreateHandler.handleInternally(MessageCreateHandler.java:138)
at net.dv8tion.jda.internal.handle.SocketHandler.handle(SocketHandler.java:39)
at net.dv8tion.jda.internal.requests.WebSocketClient.onDispatch(WebSocketClient.java:1009)
at net.dv8tion.jda.internal.requests.WebSocketClient.onEvent(WebSocketClient.java:892)
at net.dv8tion.jda.internal.requests.WebSocketClient.handleEvent(WebSocketClient.java:870)
at net.dv8tion.jda.internal.requests.WebSocketClient.onBinaryMessage(WebSocketClient.java:1048)
at com.neovisionaries.ws.client.ListenerManager.callOnBinaryMessage(ListenerManager.java:385)
at com.neovisionaries.ws.client.ReadingThread.callOnBinaryMessage(ReadingThread.java:276)
at com.neovisionaries.ws.client.ReadingThread.handleBinaryFrame(ReadingThread.java:996)
at com.neovisionaries.ws.client.ReadingThread.handleFrame(ReadingThread.java:755)
at com.neovisionaries.ws.client.ReadingThread.main(ReadingThread.java:108)
at com.neovisionaries.ws.client.ReadingThread.runMain(ReadingThread.java:64)
at com.neovisionaries.ws.client.WebSocketThread.run(WebSocketThread.java:45)
Caused by: java.sql.SQLException: Cannot get a connection, general error
at org.apache.commons.dbcp2.PoolingDataSource.getConnection(PoolingDataSource.java:151)
at org.apache.commons.dbcp2.BasicDataSource.getConnection(BasicDataSource.java:714)
at net.hypr.doki.utils.DBUtils.createUserRecord(DBUtils.java:60)
at net.hypr.doki.listeners.LevellingListener.onMessageReceived(LevellingListener.java:58)
... 18 common frames omitted
Caused by: java.lang.InterruptedException: null
at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1611)
at org.apache.commons.pool2.impl.LinkedBlockingDeque.takeFirst(LinkedBlockingDeque.java:1324)
at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:313)
at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:233)
at org.apache.commons.dbcp2.PoolingDataSource.getConnection(PoolingDataSource.java:139)
... 21 common frames omitted
00:21:26.676 JDA MainWS-ReadThread net.hypr.doki.utils.DBUtils #doesUserRecordExist L39 DBUtils DEBUG Searching DB for (usr419880181101232129,srv:445821876183367680)
00:23:29.574 JDA Gateway-Worker 1 n.d.j.i.requests.WebSocketClient #sendKeepAlive L737 WebSocketClient WARN Missed 2 heartbeats! Trying to reconnect...
00:23:29.576 JDA MainWS-ReadThread net.hypr.doki.utils.DBUtils #doesUserRecordExist L44 DBUtils DEBUG An SQL error occurred
00:23:29.576 JDA MainWS-ReadThread n.h.doki.listeners.LevellingListener #onMessageReceived L56 LevellingListener INFO No record of user ID 419880181101232129 in server 445821876183367680, creating blank record
00:23:29.576 JDA MainWS-ReadThread net.hypr.doki.utils.DBUtils #createUserRecord L58 DBUtils INFO Creating record (usr:419880181101232129,srv:445821876183367680,unm:notashelf)
00:23:29.576 JDA MainWS-ReadThread n.d.j.a.hooks.InterfacedEventManager #handle L102 JDA ERROR One of the EventListeners had an uncaught exception
java.lang.RuntimeException: java.sql.SQLException: Cannot get a connection, general error
at net.hypr.doki.listeners.LevellingListener.onMessageReceived(LevellingListener.java:60)
at net.dv8tion.jda.api.hooks.ListenerAdapter.onEvent(ListenerAdapter.java:456)
at net.dv8tion.jda.api.hooks.InterfacedEventManager.handle(InterfacedEventManager.java:98)
at net.dv8tion.jda.internal.hooks.EventManagerProxy.handleInternally(EventManagerProxy.java:88)
at net.dv8tion.jda.internal.hooks.EventManagerProxy.handle(EventManagerProxy.java:70)
at net.dv8tion.jda.internal.JDAImpl.handleEvent(JDAImpl.java:169)
at net.dv8tion.jda.internal.handle.MessageCreateHandler.handleInternally(MessageCreateHandler.java:138)
at net.dv8tion.jda.internal.handle.SocketHandler.handle(SocketHandler.java:39)
at net.dv8tion.jda.internal.requests.WebSocketClient.onDispatch(WebSocketClient.java:1009)
at net.dv8tion.jda.internal.requests.WebSocketClient.onEvent(WebSocketClient.java:892)
at net.dv8tion.jda.internal.requests.WebSocketClient.handleEvent(WebSocketClient.java:870)
at net.dv8tion.jda.internal.requests.WebSocketClient.onBinaryMessage(WebSocketClient.java:1048)
at com.neovisionaries.ws.client.ListenerManager.callOnBinaryMessage(ListenerManager.java:385)
at com.neovisionaries.ws.client.ReadingThread.callOnBinaryMessage(ReadingThread.java:276)
at com.neovisionaries.ws.client.ReadingThread.handleBinaryFrame(ReadingThread.java:996)
at com.neovisionaries.ws.client.ReadingThread.handleFrame(ReadingThread.java:755)
at com.neovisionaries.ws.client.ReadingThread.main(ReadingThread.java:108)
at com.neovisionaries.ws.client.ReadingThread.runMain(ReadingThread.java:64)
at com.neovisionaries.ws.client.WebSocketThread.run(WebSocketThread.java:45)
Caused by: java.sql.SQLException: Cannot get a connection, general error
at org.apache.commons.dbcp2.PoolingDataSource.getConnection(PoolingDataSource.java:151)
at org.apache.commons.dbcp2.BasicDataSource.getConnection(BasicDataSource.java:714)
at net.hypr.doki.utils.DBUtils.createUserRecord(DBUtils.java:60)
at net.hypr.doki.listeners.LevellingListener.onMessageReceived(LevellingListener.java:58)
... 18 common frames omitted
Caused by: java.lang.InterruptedException: null
at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1611)
at org.apache.commons.pool2.impl.LinkedBlockingDeque.takeFirst(LinkedBlockingDeque.java:1324)
at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:313)
at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:233)
at org.apache.commons.dbcp2.PoolingDataSource.getConnection(PoolingDataSource.java:139)
... 21 common frames omitted
00:23:29.950 JDA MainWS-ReadThread net.hypr.doki.utils.DBUtils #doesUserRecordExist L39 DBUtils DEBUG Searching DB for (usr419880181101232129,srv:445821876183367680)

1157
logs/logs-2024-07-27.log Normal file

File diff suppressed because it is too large Load diff

1595
logs/logs-2024-07-28.log Normal file

File diff suppressed because it is too large Load diff

1234
logs/logs-2024-07-29.log Normal file

File diff suppressed because it is too large Load diff

26
pom.xml
View file

@ -24,11 +24,37 @@
<groupId>io.github.freya022</groupId>
<artifactId>BotCommands</artifactId>
<version>2.10.4</version>
<exclusions>
<exclusion>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20231013</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.5.6</version>
</dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>2.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.8.1</version>
</dependency>
</dependencies>
</project>

View file

@ -19,12 +19,11 @@ public class Config {
* @throws IOException if the config JSON could not be read
*/
public static Config readConfig() throws IOException {
System.out.println(Path.of("config.json"));
try (InputStream in=Thread.currentThread().getContextClassLoader().getResourceAsStream("config.json")) {
assert in != null;
Reader reader = new InputStreamReader(in, StandardCharsets.UTF_8);
return new Gson().fromJson(reader, Config.class);
} catch (IOException e) {
} catch (IOException | NullPointerException e) {
throw new IOException("""
config.json was not found in the root folder (of the project), did you forget to put it ?
Example structure:

View file

@ -6,6 +6,7 @@ import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.requests.GatewayIntent;
import org.apache.commons.dbcp2.BasicDataSource;
import org.slf4j.Logger;
import java.io.IOException;
@ -14,6 +15,8 @@ public class Doki {
private static final Logger LOGGER = Logging.getLogger();
private static JDA jda;
private static Config config;
private static String prefix;
private static final BasicDataSource dataSource = new BasicDataSource();
private Doki(JDA jda, Config config) {
Doki.jda = jda;

View file

@ -1,5 +1,6 @@
package net.hypr.doki.commands;
import com.freya02.botcommands.api.annotations.CommandMarker;
import com.freya02.botcommands.api.prefixed.CommandEvent;
import com.freya02.botcommands.api.prefixed.TextCommand;
import com.freya02.botcommands.api.prefixed.annotations.Category;
@ -11,10 +12,11 @@ import net.dv8tion.jda.api.entities.SelfUser;
import java.awt.*;
@Category("Misc")
@CommandMarker
@Category("Utils")
@Description("Get about info")
public class About extends TextCommand {
@JDATextCommand(name = "about")
@JDATextCommand(name = "about", aliases = {"doki"})
public void execute(CommandEvent event) {
JDA jda = event.getJDA();
SelfUser selfUser = jda.getSelfUser();

View file

@ -0,0 +1,52 @@
package net.hypr.doki.commands;
import com.freya02.botcommands.api.annotations.CommandMarker;
import com.freya02.botcommands.api.prefixed.CommandEvent;
import com.freya02.botcommands.api.prefixed.TextCommand;
import com.freya02.botcommands.api.prefixed.annotations.Category;
import com.freya02.botcommands.api.prefixed.annotations.Description;
import com.freya02.botcommands.api.prefixed.annotations.JDATextCommand;
import net.dv8tion.jda.api.EmbedBuilder;
import net.hypr.doki.utils.DBUtils;
import net.hypr.doki.utils.UserRecord;
import java.awt.*;
import java.sql.SQLException;
import java.util.List;
@CommandMarker
@Category("Levelling")
@Description("Get the global leaderboard")
public class Leaderboard extends TextCommand {
@JDATextCommand(name = "leaderboard", order = 1, aliases = { "lb" })
public void execute(CommandEvent event) throws SQLException {
List<UserRecord> userRecords = DBUtils.getAllUserRecords(event.getGuild().getIdLong());
// Sort the leaderboard highest level first
userRecords.sort((o1, o2) -> o2.totalXp - o1.totalXp);
EmbedBuilder whoIsEmbed = buildLeaderboardEmbed(userRecords, event);
event.reply(whoIsEmbed.build()).queue();
}
private EmbedBuilder buildLeaderboardEmbed(List<UserRecord> userRecords , CommandEvent event) {
StringBuilder leaderboard = new StringBuilder();
int idx = 1;
for (UserRecord record : userRecords) {
leaderboard
.append("**")
.append(idx)
.append(".** ")
.append(record.username)
.append(" - ")
.append(record.level)
.append(" (")
.append(record.totalXp)
.append(" Total XP)\n");
idx += 1;
if (idx > 10) break; // Break out after 10 records is reached
}
return new EmbedBuilder()
.setTitle(event.getGuild().getName() + " Leaderboard")
.setDescription(leaderboard)
.setColor(new Color(210,138,39));
}
}

View file

@ -1,12 +1,14 @@
package net.hypr.doki.commands;
import com.freya02.botcommands.api.annotations.CommandMarker;
import com.freya02.botcommands.api.prefixed.CommandEvent;
import com.freya02.botcommands.api.prefixed.TextCommand;
import com.freya02.botcommands.api.prefixed.annotations.Category;
import com.freya02.botcommands.api.prefixed.annotations.Description;
import com.freya02.botcommands.api.prefixed.annotations.JDATextCommand;
@Category("Misc")
@CommandMarker
@Category("Utils")
@Description("Pong!")
public class Ping extends TextCommand {
@JDATextCommand(name = "ping")

View file

@ -0,0 +1,46 @@
package net.hypr.doki.commands;
import com.freya02.botcommands.api.annotations.CommandMarker;
import com.freya02.botcommands.api.prefixed.BaseCommandEvent;
import com.freya02.botcommands.api.prefixed.CommandEvent;
import com.freya02.botcommands.api.prefixed.TextCommand;
import com.freya02.botcommands.api.prefixed.annotations.Category;
import com.freya02.botcommands.api.prefixed.annotations.Description;
import com.freya02.botcommands.api.prefixed.annotations.JDATextCommand;
import com.freya02.botcommands.api.prefixed.annotations.TextOption;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Member;
import net.hypr.doki.utils.DBUtils;
import net.hypr.doki.utils.UserRecord;
import java.sql.SQLException;
@CommandMarker
@Category("Levelling")
@Description("Get a user's rank")
public class Rank extends TextCommand {
@JDATextCommand(name = "rank", order = 1)
public void execute(BaseCommandEvent event, @TextOption Member member) throws SQLException {
UserRecord userRecord = DBUtils.getUserRecord(member.getIdLong(), event.getGuild().getIdLong());
EmbedBuilder rankEmbed = buildRankEmbed(member, userRecord);
event.reply(rankEmbed.build()).queue();
}
@JDATextCommand(name = "rank", order = 2)
public void execute(CommandEvent event) throws SQLException {
UserRecord userRecord = DBUtils.getUserRecord(event.getMember().getIdLong(), event.getGuild().getIdLong());
EmbedBuilder whoIsEmbed = buildRankEmbed(event.getMember(), userRecord);
event.reply(whoIsEmbed.build()).queue();
}
private EmbedBuilder buildRankEmbed(Member user, UserRecord userRecord) {
int xpToNextLevel = (((userRecord.level + 1) * 5) * 40) - userRecord.xp;
return new EmbedBuilder()
.setAuthor(user.getUser().getName(), null, user.getEffectiveAvatarUrl())
.setThumbnail(user.getEffectiveAvatarUrl())
.addField("Level", String.valueOf(userRecord.level), true)
.addField("XP", String.valueOf(userRecord.xp), true)
.addField("XP Until level " + (userRecord.level + 1), String.valueOf(xpToNextLevel), true)
.setColor(user.getColor());
}
}

View file

@ -0,0 +1,63 @@
package net.hypr.doki.commands;
import com.freya02.botcommands.api.annotations.CommandMarker;
import com.freya02.botcommands.api.prefixed.BaseCommandEvent;
import com.freya02.botcommands.api.prefixed.CommandEvent;
import com.freya02.botcommands.api.prefixed.TextCommand;
import com.freya02.botcommands.api.prefixed.annotations.Category;
import com.freya02.botcommands.api.prefixed.annotations.Description;
import com.freya02.botcommands.api.prefixed.annotations.JDATextCommand;
import com.freya02.botcommands.api.prefixed.annotations.TextOption;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.User;
import java.time.Duration;
import java.time.OffsetDateTime;
import java.util.stream.Collectors;
@CommandMarker
@Category("Utils")
@Description("Get information about a user")
public class WhoIs extends TextCommand {
@JDATextCommand(name = "whois", order = 1)
public void execute(BaseCommandEvent event, @TextOption(example = "<@437970062922612737>") Member user) {
EmbedBuilder whoIsEmbed = buildUserEmbed(user, (CommandEvent) event);
event.reply(whoIsEmbed.build()).queue();
}
@JDATextCommand(name = "whois", order = 2)
public void execute(BaseCommandEvent event, @TextOption(example = "<@437970062922612737>") User user) {
EmbedBuilder whoIsEmbed = buildUserEmbed((Member) user, (CommandEvent) event);
event.reply(whoIsEmbed.build()).queue();
}
@JDATextCommand(name = "whois", order = 3)
public void execute(CommandEvent event) {
EmbedBuilder whoIsEmbed = buildUserEmbed(event.getMember(), event);
event.reply(whoIsEmbed.build()).queue();
}
private EmbedBuilder buildUserEmbed(Member user, CommandEvent event) {
return new EmbedBuilder()
.setAuthor(user.getUser().getName(), null, user.getEffectiveAvatarUrl())
.setThumbnail(user.getEffectiveAvatarUrl())
.addField("Information",
"**Mention:** " + user.getAsMention() +
"\n**ID:** " + user.getId(), true)
.addField("Joined",
"**Discord:** " +
Duration.between(user.getTimeCreated(), OffsetDateTime.now()).toDays() + " days ago\n" +
"**->** <t:" + user.getTimeCreated().toEpochSecond() + ":f>\n**Guild:** " +
Duration.between(user.getTimeJoined(), OffsetDateTime.now()).toDays() + " days ago\n" +
"**->** <t:" + user.getTimeJoined().toEpochSecond() + ":f>", true)
.addField("Guild-Specific",
"**Nickname:** " + user.getNickname() + "\n**Roles (" + ((long) user.getRoles().size() + 1) + "):** `@everyone`, " +
user.getRoles().stream().map(Role::getAsMention)
.collect(Collectors.joining(", ")) +
"\n**Owner:**" + (user.isOwner() ? "Yes" : "No"), false)
.addField("Guild", event.getGuild().getName(), false)
.setColor(user.getColor());
}
}

View file

@ -0,0 +1,64 @@
package net.hypr.doki.listeners;
import com.freya02.botcommands.api.Logging;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.hypr.doki.Doki;
import net.hypr.doki.utils.DBUtils;
import net.hypr.doki.utils.LevellingUtils;
import net.hypr.doki.utils.UserRecord;
import org.slf4j.Logger;
import java.sql.SQLException;
import java.time.Duration;
import java.time.LocalDateTime;
public class LevellingListener extends ListenerAdapter {
@Override
public void onMessageReceived(MessageReceivedEvent event) {
Logger log = Logging.getLogger();
/* Ignore the message if one of the following conditions is met:
- Message is from self user
- Message is from bot
- Message is command (starts with bot prefix)
*/
if (
Doki.getJDA().getSelfUser().getId().equals(event.getAuthor().getId()) ||
event.getAuthor().isBot() ||
event.getMessage().getContentStripped().startsWith(Doki.getPrefix())
) {
log.debug("Ignoring self/bot message with ID " + event.getMessageId());
return;
}
User user = event.getAuthor();
Guild guild = event.getGuild();
boolean userIsInDb = DBUtils.doesUserRecordExist(user.getIdLong(), guild.getIdLong());
if (userIsInDb) {
try {
UserRecord rec = DBUtils.getUserRecord(user.getIdLong(), guild.getIdLong());
Duration timeSinceLastMessage = Duration.between(
rec.lastMessage.toLocalDateTime(),
LocalDateTime.now()
);
if (timeSinceLastMessage.compareTo(Duration.ofHours(1)) > 0) {
// it has been over an hour since the user last sent a message that affected XP
LevellingUtils.incrementXp(log, rec);
} else {
log.debug("Ignoring message ID " + event.getMessageId() + " as not enough time has passed");
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
} else {
log.info("No record of user ID " + user.getId() + " in server " + guild.getId() + ", creating blank record");
try {
DBUtils.createUserRecord(user.getIdLong(), guild.getIdLong(), user.getName());
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
}

View file

@ -0,0 +1,157 @@
package net.hypr.doki.utils;
import com.freya02.botcommands.api.Logging;
import net.hypr.doki.Doki;
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.slf4j.Logger;
import java.math.BigInteger;
import java.sql.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class DBUtils {
/**
* Checks if the user record exists
* @param user_id User ID to search for
* @param server_id Server ID to search for
* @return Whether the record exists or not
*/
public static boolean doesUserRecordExist(long user_id, long server_id) {
Logger log = Logging.getLogger();
BasicDataSource dataSource = Doki.getDataSource();
QueryRunner qr = new QueryRunner(dataSource);
ResultSetHandler<Set<BigInteger>> resultSetHandler = rs -> {
Set<BigInteger> rows = new HashSet<>();
while (rs.next()) {
rows.add(BigInteger.valueOf(rs.getLong(1)));
}
return rows;
};
// Find out if the user is already in the DB
try {
log.debug("Searching DB for (usr" + user_id + ",srv:" + server_id + ")");
Set<BigInteger> foundIds = qr.query("SELECT user_id FROM users WHERE user_id = " + user_id + " AND server_id = " + server_id, resultSetHandler);
log.debug("Matching records: " + foundIds.size());
return !foundIds.isEmpty();
} catch (SQLException ignored) {
log.debug("An SQL error occurred");
return false;
}
}
/**
* Creates a new user record
* @param user_id The users ID
* @param server_id The server ID
* @param username The users username
* @throws SQLException A SQL exception
*/
public static void createUserRecord(long user_id, long server_id, String username) throws SQLException {
Logger log = Logging.getLogger();
log.info("Creating record (usr:" + user_id + ",srv:" + server_id + ",unm:" + username + ")");
BasicDataSource dataSource = Doki.getDataSource();
Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement(
"INSERT INTO users (user_id, server_id, username, last_message) VALUES (?, ?, ?, ?)"
);
stmt.setLong(1, user_id);
stmt.setLong(2, server_id);
stmt.setString(3, username);
stmt.setTimestamp(4, Timestamp.valueOf(LocalDateTime.now()));
stmt.execute();
log.info("Record (usr:" + user_id + ",srv:" + server_id + ",unm:" + username + ") created!");
}
/**
* Updates a user record
* @param user_id User ID of the record to update
* @param server_id Server ID of the record to update
* @param now The current time
* @param xp The new XP count
* @param totalXp The new total XP count
* @param level The new level
* @throws SQLException A SQL exception
*/
public static void updateUserRecord(long user_id, long server_id, Timestamp now, int xp, int totalXp, int level) throws SQLException {
Logger log = Logging.getLogger();
log.info("Updating record (usr:" + user_id + ",srv:" + server_id + ")");
BasicDataSource dataSource = Doki.getDataSource();
Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement(
"UPDATE users SET last_message = ?, xp = ?, total_xp = ?, level = ? WHERE user_id = ? AND server_id = ?"
);
stmt.setTimestamp(1, now);
stmt.setInt(2, xp);
stmt.setInt(3, totalXp);
stmt.setInt(4, level);
stmt.setLong(5, user_id);
stmt.setLong(6, server_id);
stmt.executeQuery();
log.info("Updated record (usr:" + user_id + ",srv:" + server_id + ")!");
}
/**
* Gets a user record
* @param user_id The User ID of the record to get
* @param server_id The Server ID of the record to get
* @return The found UserRecord
* @throws SQLException A SQL exception
*/
public static UserRecord getUserRecord(long user_id, long server_id) throws SQLException {
BasicDataSource dataSource = Doki.getDataSource();
Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement(
"SELECT user_id, server_id, username, last_message, xp, total_xp, level FROM users WHERE user_id = ? AND server_id = ?"
);
stmt.setLong(1, user_id);
stmt.setLong(2, server_id);
ResultSet rs = stmt.executeQuery();
rs.next();
return new UserRecord(
rs.getLong("user_id"),
rs.getLong("server_id"),
rs.getString("username"),
rs.getTimestamp("last_message"),
rs.getInt("xp"),
rs.getInt("total_xp"),
rs.getInt("level")
);
}
/**
* Get all user records for a server
* @param server_id The Server ID
* @return A List of UserRecords
* @throws SQLException A SQL exception
*/
public static List<UserRecord> getAllUserRecords(long server_id) throws SQLException {
BasicDataSource dataSource = Doki.getDataSource();
Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement(
"SELECT user_id, username, last_message, xp, total_xp, level FROM users WHERE server_id = ?"
);
stmt.setLong(1, server_id);
ResultSet rs = stmt.executeQuery();
List<UserRecord> userRecordList = new ArrayList<>();
while (rs.next()) {
userRecordList.add(new UserRecord(
rs.getLong("user_id"),
server_id,
rs.getString("username"),
rs.getTimestamp("last_message"),
rs.getInt("xp"),
rs.getInt("total_xp"),
rs.getInt("level")
));
}
return userRecordList;
}
}

View file

@ -0,0 +1,35 @@
package net.hypr.doki.utils;
import org.slf4j.Logger;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.Random;
public class LevellingUtils {
public static void incrementXp(Logger logger, UserRecord userRecord) throws SQLException {
Random random = new Random();
// Random increment between 15 and 25
int xpInc = (random.nextInt(10) + 16) * 3;
int xpNew = userRecord.xp + xpInc;
int totalXp = userRecord.xp + xpInc;
int levelNew = userRecord.level;
if (xpNew >= ((userRecord.level + 1) * 5) * 40) {
levelNew ++;
xpNew = 0;
}
DBUtils.updateUserRecord(
userRecord.user_id,
userRecord.server_id,
Timestamp.valueOf(LocalDateTime.now()),
xpNew,
totalXp,
levelNew
);
logger.info("Incremented " + userRecord.username + "'s XP in " + userRecord.server_id + " (" + userRecord.xp + " -> " + xpNew + ")");
if (levelNew > userRecord.level) {
logger.info("Incremented " + userRecord.username + "'s level in " + userRecord.server_id + " (" + userRecord.level + " -> " + levelNew + ")");
}
}
}

View file

@ -0,0 +1,49 @@
package net.hypr.doki.utils;
import java.sql.Timestamp;
public class UserRecord {
public final long user_id;
public final long server_id;
public final String username;
public final Timestamp lastMessage;
public final int xp;
public int totalXp;
public final int level;
/**
* Instantiates a new UserRecord
* @param user_id The User ID
* @param server_id The Server/Guild ID
* @param username The Username
*/
public UserRecord (long user_id, long server_id, String username) {
this.user_id = user_id;
this.server_id = server_id;
this.username = username;
this.lastMessage = new Timestamp(0);
this.xp = 0;
this.level = 1;
}
/**
* Instantiates a new UserRecord
* @param user_id The User ID
* @param server_id The Server/Guild ID
* @param username The Username
* @param lastMessage The timestamp of the user's last message
* @param xp The user's XP
* @param totalXp The user's total XP
* @param level The user's level
*/
public UserRecord (long user_id, long server_id, String username, Timestamp lastMessage, int xp, int totalXp, int level) {
this.user_id = user_id;
this.server_id = server_id;
this.username = username;
this.lastMessage = lastMessage;
this.xp = xp;
this.totalXp = totalXp;
this.level = level;
}
}

View file

@ -0,0 +1,42 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"token": {
"type": "string"
},
"prefix": {
"type": "string"
},
"mariadb": {
"type": "object",
"properties": {
"host": {
"type": "string"
},
"user": {
"type": "string"
},
"password": {
"type": "string"
},
"database": {
"type": "string"
}
},
"required": [
"host",
"user",
"password",
"database"
]
}
},
"required": [
"token",
"prefix",
"mariadb"
]
}