This commit is contained in:
Tyler Murphy 2022-08-24 07:12:17 -04:00
parent 4ef55c0912
commit 04d5376fa3
21 changed files with 257 additions and 42 deletions

30
pom.xml
View file

@ -11,8 +11,8 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<build>
@ -45,15 +45,6 @@
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
@ -69,7 +60,7 @@
<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<version>5.0.0-alpha.17</version>
<version>5.0.0-alpha.18</version>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
@ -116,6 +107,21 @@
<artifactId>json</artifactId>
<version>20220320</version>
</dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>3.0.7</version>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.39.2.0</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.0.1</version>
</dependency>
</dependencies>
</project>

View file

@ -93,6 +93,8 @@ public class Config {
throw new RuntimeException("Unable to finalize loading of config files.");
}
this.saveConfig();
}
@SuppressWarnings({"rawtypes", "unchecked"})

View file

@ -13,6 +13,7 @@ import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.dv8tion.jda.api.requests.GatewayIntent;
import net.dv8tion.jda.api.utils.MemberCachePolicy;
import net.tylermurphy.ken.command.Responder;
import net.tylermurphy.ken.database.Database;
import net.tylermurphy.ken.music.PlayerManager;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
@ -32,11 +33,13 @@ public class Ken {
private final PlayerManager playerManager;
private final YouTube youTube;
private final Responder responder;
private final Database database;
private Ken(){
Ken.instance = this;
this.config = Config.create("config.yml");
this.log = LoggerFactory.getLogger(Ken.class);
this.database = new Database();
try {
api = JDABuilder.createDefault(config.getString("botToken"))
.setActivity(Activity.playing("@Ken | /help"))
@ -93,6 +96,8 @@ public class Ken {
public YouTube getYouTube() { return youTube; }
public Database getDatabase() { return database; }
public EmbedBuilder getDefaultEmbed() {
EmbedBuilder builder = new EmbedBuilder();
builder.setColor(new Color(

View file

@ -13,7 +13,9 @@ import net.dv8tion.jda.api.interactions.commands.build.Commands;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import net.dv8tion.jda.api.interactions.components.buttons.Button;
import net.dv8tion.jda.api.requests.restaction.WebhookMessageAction;
import net.dv8tion.jda.api.requests.restaction.WebhookMessageCreateAction;
import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction;
import net.dv8tion.jda.api.utils.FileUpload;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.util.*;
import org.reflections.Reflections;
@ -115,9 +117,6 @@ public class Responder extends ListenerAdapter {
return;
}
// Defer Reply
event.deferReply().queue();
// Get slash command options if there are any
List<Object> args = new ArrayList<>();
event.getOptions().forEach(option -> {
@ -157,18 +156,17 @@ public class Responder extends ListenerAdapter {
if(response.error()) {
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.setColor(Color.RED)
.setTitle(":x: **Error**")
.setDescription(response.getMessage());
event.getHook().sendMessageEmbeds(builder.build()).queue();
event.replyEmbeds(builder.build()).setEphemeral(true).queue();
} else {
WebhookMessageAction<?> message;
ReplyCallbackAction message;
if(response.hasEmbed()) {
message = event.getHook().sendMessageEmbeds(response.getEmbeds());
message = event.replyEmbeds(response.getEmbeds());
} else {
message = event.getHook().sendMessage(response.getMessage());
message = event.reply(response.getMessage());
}
if(response.hasButtons()) message = message.addActionRow(response.getButtons());
if(response.hasFile()) message = message.addFile(response.getFile());
if(response.hasFile()) message = message.addFiles(FileUpload.fromData(response.getFile()));
message.queue();
}
} catch (Exception e) {
@ -176,7 +174,7 @@ public class Responder extends ListenerAdapter {
.setColor(Color.RED)
.setTitle(":x: **Error**")
.setDescription(e.getCause().getMessage());
event.getHook().sendMessageEmbeds(builder.build()).queue();
event.replyEmbeds(builder.build()).setEphemeral(true).queue();
}
}

View file

@ -0,0 +1,13 @@
package net.tylermurphy.ken.command.main;
import net.tylermurphy.ken.command.Response;
import javax.management.relation.Role;
public class AddSelfRole {
// public Response execute(Role role, String){
//
// }
}

View file

@ -0,0 +1,4 @@
package net.tylermurphy.ken.command.main;
public class DeleteSelfRole {
}

View file

@ -0,0 +1,4 @@
package net.tylermurphy.ken.command.main;
public class Roles {
}

View file

@ -21,10 +21,9 @@ public class Danbooru {
@Option(name="query",description="Search query for danbooru",type= OptionType.STRING,required=true)
@Option(name="page",description="Page number for danbooru",type= OptionType.INTEGER)
public Response execute(GuildMessageChannel channel, List<Object> args){
if(!(channel instanceof TextChannel)) {
if(!(channel instanceof TextChannel textChannel)) {
return Response.error("This command can only be used in a text channel");
}
TextChannel textChannel = (TextChannel) channel;
if(!textChannel.isNSFW()){
return Response.error("This command can only be used in an NSFW channel");
}

View file

@ -21,10 +21,9 @@ public class E621 {
@Option(name="query",description="Search query for e621",type= OptionType.STRING,required=true)
@Option(name="page",description="Page number for e621",type= OptionType.INTEGER)
public Response execute(GuildMessageChannel channel, List<Object> args){
if(!(channel instanceof TextChannel)) {
if(!(channel instanceof TextChannel textChannel)) {
return Response.error("This command can only be used in a text channel");
}
TextChannel textChannel = (TextChannel) channel;
if(!textChannel.isNSFW()){
return Response.error("This command can only be used in an NSFW channel");
}

View file

@ -23,10 +23,9 @@ public class Gelbooru {
@Option(name="query",description="Search query for gelbooru",type=OptionType.STRING,required=true)
@Option(name="page",description="Page number for gelbooru",type= OptionType.INTEGER)
public Response execute(GuildMessageChannel channel, List<Object> args){
if(!(channel instanceof TextChannel)) {
if(!(channel instanceof TextChannel textChannel)) {
return Response.error("This command can only be used in a text channel");
}
TextChannel textChannel = (TextChannel) channel;
if(!textChannel.isNSFW()){
return Response.error("This command can only be used in an NSFW channel");
}

View file

@ -19,10 +19,9 @@ public class Hentai {
@Command(name="hentai", description="Retrieves a random hentai image")
@Selection(name="query", description="Type of post you want to get", type=OptionType.STRING, required=true, choices={"ass","bdsm","cum","hentai","femdom","doujin","maid","orgy","nsfwwallpapers","nsfwmobilewallpapers","gif","blowjob","feet","pussy","uglybastard","gangbang","cumslut","glasses","thighs","tentacles","masturbation","school","yuri","succubus"})
public Response execute(GuildMessageChannel channel, List<Object> args){
if(!(channel instanceof TextChannel)) {
if(!(channel instanceof TextChannel textChannel)) {
return Response.error("This command can only be used in a text channel");
}
TextChannel textChannel = (TextChannel) channel;
if(!textChannel.isNSFW()){
return Response.error("This command can only be used in an NSFW channel");
}

View file

@ -24,10 +24,9 @@ public class Konachan {
@Option(name="query",description="Search query for konachan",type= OptionType.STRING,required=true)
@Option(name="page",description="Page number for konachan",type= OptionType.INTEGER)
public Response execute(GuildMessageChannel channel, List<Object> args){
if(!(channel instanceof TextChannel)) {
if(!(channel instanceof TextChannel textChannel)) {
return Response.error("This command can only be used in a text channel");
}
TextChannel textChannel = (TextChannel) channel;
if(!textChannel.isNSFW()){
return Response.error("This command can only be used in an NSFW channel");
}

View file

@ -23,10 +23,9 @@ public class Rule34 {
@Option(name="query",description="Search query for rule34",type=OptionType.STRING,required=true)
@Option(name="page",description="Page number for rule34",type= OptionType.INTEGER)
public Response execute(GuildMessageChannel channel, List<Object> args){
if(!(channel instanceof TextChannel)) {
if(!(channel instanceof TextChannel textChannel)) {
return Response.error("This command can only be used in a text channel");
}
TextChannel textChannel = (TextChannel) channel;
if(!textChannel.isNSFW()){
return Response.error("This command can only be used in an NSFW channel");
}

View file

@ -23,10 +23,9 @@ public class Yandere {
@Option(name="query",description="Search query for yande.re",type= OptionType.STRING,required=true)
@Option(name="page",description="Page number for yande.re",type= OptionType.INTEGER)
public Response execute(GuildMessageChannel channel, List<Object> args){
if(!(channel instanceof TextChannel)) {
if(!(channel instanceof TextChannel textChannel)) {
return Response.error("This command can only be used in a text channel");
}
TextChannel textChannel = (TextChannel) channel;
if(!textChannel.isNSFW()){
return Response.error("This command can only be used in an NSFW channel");
}

View file

@ -36,10 +36,9 @@ public class nHentai {
@Command(name="nhentai", description="Search for a post off of nhentai")
@Option(name="query", description="Post id or search for nhentai", type=OptionType.STRING, required=true)
public Response execute(GuildMessageChannel channel, List<Object> args) {
if (!(channel instanceof TextChannel)) {
if (!(channel instanceof TextChannel textChannel)) {
return Response.error("This command can only be used in a text channel");
}
TextChannel textChannel = (TextChannel) channel;
if (!textChannel.isNSFW()) {
return Response.error("This command can only be used in an NSFW channel");
}

View file

@ -0,0 +1,33 @@
package net.tylermurphy.ken.database;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.database.connections.DatabaseConnection;
import net.tylermurphy.ken.database.connections.MySQLConnection;
import net.tylermurphy.ken.database.connections.SQLiteConnection;
import java.sql.Connection;
import java.sql.SQLException;
public class Database {
private final DatabaseConnection connection;
private final SelfRoleTable selfRoleTable;
public Database(){
if(Ken.getInstance().getConfig().getBoolean("database.sqlite")) {
connection = new SQLiteConnection();
} else {
connection = new MySQLConnection();
}
selfRoleTable = new SelfRoleTable(this);
}
public SelfRoleTable getSelfRoleData(){
return selfRoleTable;
}
protected Connection connect() throws SQLException {
return connection.connect();
}
}

View file

@ -0,0 +1,56 @@
package net.tylermurphy.ken.database;
import net.tylermurphy.ken.Ken;
import java.sql.*;
public class SelfRoleTable {
private final Database database;
public SelfRoleTable(Database database){
String sql = "CREATE TABLE IF NOT EXISTS self_role_data (\n"
+ " guild_id BIGINT NOT NULL,\n"
+ " page INT NOT NULL,\n"
+ " data TEXT NOT NULL,"
+ " PRIMARY KEY (guild_id,page)\n"
+ ");";
try(Connection connection = database.connect(); Statement statement = connection.createStatement()) {
statement.executeUpdate(sql);
} catch (SQLException e) {
Ken.getInstance().getLogger().error("SQL Error: " + e.getMessage());
}
this.database = database;
}
public String getData(long guildId, int page){
String sql = "SELECT * FROM self_role_data WHERE guild_id=? AND page=?";
try(Connection connection = database.connect(); PreparedStatement statement = connection.prepareStatement(sql)) {
statement.setLong(1, guildId);
statement.setInt(2, page);
ResultSet rs = statement.executeQuery();
if(rs.next()) return rs.getString("data");
else return null;
} catch (SQLException e) {
Ken.getInstance().getLogger().error("SQL Error: " + e.getMessage());
return null;
}
}
public boolean setData(long guildId, int page, String data){
String sql = "INSERT OR REPLACE INTO self_role_data (guild_id, page, data) VALUES(?,?,?)";
try(Connection connection = database.connect(); PreparedStatement statement = connection.prepareStatement(sql)) {
statement.setLong(1, guildId);
statement.setInt(2, page);
statement.setString(3, data);
return statement.executeUpdate() != 0;
} catch (SQLException e) {
Ken.getInstance().getLogger().error("SQL Error: " + e.getMessage());
return false;
}
}
}

View file

@ -0,0 +1,10 @@
package net.tylermurphy.ken.database.connections;
import java.sql.Connection;
import java.sql.SQLException;
public interface DatabaseConnection {
Connection connect() throws SQLException;
}

View file

@ -0,0 +1,43 @@
package net.tylermurphy.ken.database.connections;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import net.tylermurphy.ken.Ken;
import java.sql.Connection;
import java.sql.SQLException;
public class MySQLConnection implements DatabaseConnection {
private final HikariDataSource ds;
public MySQLConnection(){
HikariConfig config = new HikariConfig();
String host = Ken.getInstance().getConfig().getString("database.host");
String port = Ken.getInstance().getConfig().getString("database.port");
String username = Ken.getInstance().getConfig().getString("database.username");
String password = Ken.getInstance().getConfig().getString("database.password");
String databaseName = Ken.getInstance().getConfig().getString("database.databaseName");
config.setJdbcUrl("jdbc:mariadb://"+host+":"+port+"/"+databaseName);
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
config.addDataSourceProperty("user", username);
config.addDataSourceProperty("password",password);
config.addDataSourceProperty("autoCommit", "true");
config.setAutoCommit(true);
config.setMaximumPoolSize(20);
ds = new HikariDataSource(config);
}
@Override
public Connection connect() throws SQLException {
return ds.getConnection();
}
}

View file

@ -0,0 +1,46 @@
package net.tylermurphy.ken.database.connections;
import net.tylermurphy.ken.Ken;
import org.sqlite.SQLiteConfig;
import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class SQLiteConnection implements DatabaseConnection {
private final File databaseFile;
private final SQLiteConfig config;
public SQLiteConnection(){
try {
Class.forName("org.sqlite.JDBC");
} catch (ClassNotFoundException e) {
Ken.getInstance().getLogger().error(e.getMessage());
throw new RuntimeException(e.getMessage());
}
databaseFile = new File(Ken.getInstance().getConfigFolder(), "database.db");
config = new SQLiteConfig();
config.setSynchronous(SQLiteConfig.SynchronousMode.NORMAL);
config.setTempStore(SQLiteConfig.TempStore.MEMORY);
}
@Override
public Connection connect() {
Connection conn = null;
try {
String url = "jdbc:sqlite:"+databaseFile;
conn = DriverManager.getConnection(url, config.toProperties());
} catch (SQLException e) {
Ken.getInstance().getLogger().error(e.getMessage());
e.printStackTrace();
}
return conn;
}
}

View file

@ -13,14 +13,17 @@
# Example: "N1q2O3E4NzgyNRGHjk#zFTgy.G7Qb2Z.Hr36Qj5p3P56GueIFxVQOAAEre22DXB4u56FX11c"
botToken: ""
# This is the information used to connect to a MySQL compatible database. A database is REQUIRED
# for KenBotReborn to function.
# This is the information used to connect to a MySQL compatible database. A database is recommended
# for KenBotReborn to function. You can use a sqlite database instead, but its highly discoursed.
# If you want to use MySQL, put your database connection information below, if you want to use sqlite,
# set database.sqlite to true, and every other option will be ignored.
database:
host: "127.0.0.1"
port: "3306"
username: "root"
password: "admin"
databaseName: "database"
sqlite: false
# If you want the ability for KenBotReborn to play music from YouTube in a voice channel, then
# you need access to the YoutubeAPI. Get a YouTube API key from the Google Developer Console and