Compare commits
4 commits
93c9a797ee
...
d64f157159
Author | SHA1 | Date | |
---|---|---|---|
Anya | d64f157159 | ||
Anya | 5c7f2991ec | ||
Anya | ad09706b77 | ||
Anya | 9544aa677f |
24
pom.xml
24
pom.xml
|
@ -7,17 +7,17 @@
|
||||||
<groupId>moe.oko</groupId>
|
<groupId>moe.oko</groupId>
|
||||||
<artifactId>Kiafumi</artifactId>
|
<artifactId>Kiafumi</artifactId>
|
||||||
<name>Kiafumi</name>
|
<name>Kiafumi</name>
|
||||||
<version>0.9.0-pre</version>
|
<version>0.9.0</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<url>https://oko.moe/kiafumi.htm</url>
|
<url>https://oko.moe/kiafumi.htm</url>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.jdk.version>16</project.jdk.version>
|
<project.jdk.version>17</project.jdk.version>
|
||||||
<mainclass>moe.oko.Kiafumi.Kiafumi</mainclass>
|
<mainclass>moe.oko.Kiafumi.Kiafumi</mainclass>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<!-- JDA (https://mvnrepository.com/artifact/net.dv8tion/JDA) -->
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<!-- JDA (https://mvnrepository.com/artifact/net.dv8tion/JDA) -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.dv8tion</groupId>
|
<groupId>net.dv8tion</groupId>
|
||||||
<artifactId>JDA</artifactId>
|
<artifactId>JDA</artifactId>
|
||||||
|
@ -30,25 +30,20 @@
|
||||||
<artifactId>Simple-Yaml</artifactId>
|
<artifactId>Simple-Yaml</artifactId>
|
||||||
<version>1.7.2</version>
|
<version>1.7.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.httpcomponents</groupId>
|
|
||||||
<artifactId>httpclient</artifactId>
|
|
||||||
<version>4.5.13</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.logging.log4j</groupId>
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
<artifactId>log4j-api</artifactId>
|
<artifactId>log4j-api</artifactId>
|
||||||
<version>2.17.2</version>
|
<version>2.19.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.logging.log4j</groupId>
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
<artifactId>log4j-core</artifactId>
|
<artifactId>log4j-core</artifactId>
|
||||||
<version>2.17.2</version>
|
<version>2.19.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.logging.log4j</groupId>
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
<artifactId>log4j-slf4j-impl</artifactId>
|
<artifactId>log4j-slf4j-impl</artifactId>
|
||||||
<version>2.17.2</version>
|
<version>2.19.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.sedmelluq</groupId>
|
<groupId>com.sedmelluq</groupId>
|
||||||
|
@ -58,7 +53,12 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>mysql</groupId>
|
<groupId>mysql</groupId>
|
||||||
<artifactId>mysql-connector-java</artifactId>
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
<version>8.0.29</version>
|
<version>8.0.30</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.zaxxer</groupId>
|
||||||
|
<artifactId>HikariCP</artifactId>
|
||||||
|
<version>5.0.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- DDG api (https://github.com/nstrydom2/duckduckgo-api) -->
|
<!-- DDG api (https://github.com/nstrydom2/duckduckgo-api) -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -4,7 +4,7 @@ import moe.oko.Kiafumi.command.CommandClass;
|
||||||
import moe.oko.Kiafumi.command.CommandRegistrar;
|
import moe.oko.Kiafumi.command.CommandRegistrar;
|
||||||
import moe.oko.Kiafumi.listener.MainListener;
|
import moe.oko.Kiafumi.listener.MainListener;
|
||||||
import moe.oko.Kiafumi.listener.SkynetListener;
|
import moe.oko.Kiafumi.listener.SkynetListener;
|
||||||
import moe.oko.Kiafumi.model.KiafumiDB;
|
import moe.oko.Kiafumi.model.db.KiafumiDB;
|
||||||
import moe.oko.Kiafumi.model.ServerManager;
|
import moe.oko.Kiafumi.model.ServerManager;
|
||||||
import moe.oko.Kiafumi.util.CommandInfo;
|
import moe.oko.Kiafumi.util.CommandInfo;
|
||||||
import moe.oko.Kiafumi.util.EmbedUI;
|
import moe.oko.Kiafumi.util.EmbedUI;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package moe.oko.Kiafumi;
|
package moe.oko.Kiafumi;
|
||||||
|
|
||||||
import moe.oko.Kiafumi.model.KiafumiDB;
|
import moe.oko.Kiafumi.model.db.DBCredentials;
|
||||||
|
import moe.oko.Kiafumi.model.db.KiafumiDB;
|
||||||
import org.simpleyaml.configuration.file.YamlConfiguration;
|
import org.simpleyaml.configuration.file.YamlConfiguration;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -30,12 +31,10 @@ public class KiafumiConfig {
|
||||||
/*
|
/*
|
||||||
Kia Variable Section
|
Kia Variable Section
|
||||||
*/
|
*/
|
||||||
private boolean sharded;
|
|
||||||
private String activityType;
|
private String activityType;
|
||||||
private String activityMsg;
|
private String activityMsg;
|
||||||
private String statusType;
|
private String statusType;
|
||||||
private List<String> pingResponses;
|
private List<String> pingResponses;
|
||||||
private int gameCheckTime;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
SQL Variable Section
|
SQL Variable Section
|
||||||
|
@ -45,6 +44,10 @@ public class KiafumiConfig {
|
||||||
private String username;
|
private String username;
|
||||||
private String password;
|
private String password;
|
||||||
private String database;
|
private String database;
|
||||||
|
private int poolSize;
|
||||||
|
private long connTimeout;
|
||||||
|
private long idleTimeout;
|
||||||
|
private long maxLifetime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for the config.
|
* Constructor for the config.
|
||||||
|
@ -84,12 +87,10 @@ public class KiafumiConfig {
|
||||||
|
|
||||||
// Kiafumi loaders
|
// Kiafumi loaders
|
||||||
var main = configuration.getConfigurationSection("main");
|
var main = configuration.getConfigurationSection("main");
|
||||||
sharded = main.getBoolean("sharded");
|
|
||||||
activityType = main.getString("activityType");
|
activityType = main.getString("activityType");
|
||||||
activityMsg = main.getString("activityMsg");
|
activityMsg = main.getString("activityMsg");
|
||||||
statusType = main.getString("statusType");
|
statusType = main.getString("statusType");
|
||||||
pingResponses = main.getStringList("pingResponses");
|
pingResponses = main.getStringList("pingResponses");
|
||||||
gameCheckTime = main.getInt("gameCheckTime");
|
|
||||||
|
|
||||||
// SQL loaders
|
// SQL loaders
|
||||||
var sql = configuration.getConfigurationSection("sql");
|
var sql = configuration.getConfigurationSection("sql");
|
||||||
|
@ -98,6 +99,10 @@ public class KiafumiConfig {
|
||||||
username = sql.getString("username");
|
username = sql.getString("username");
|
||||||
password = sql.getString("password");
|
password = sql.getString("password");
|
||||||
database = sql.getString("database");
|
database = sql.getString("database");
|
||||||
|
poolSize = sql.getInt("poolSize");
|
||||||
|
connTimeout = sql.getLong("connectionTimeout");
|
||||||
|
idleTimeout = sql.getLong("idleTimeout");
|
||||||
|
maxLifetime = sql.getLong("maxLifetime");
|
||||||
|
|
||||||
} catch(Exception ex) {
|
} catch(Exception ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
|
@ -125,9 +130,11 @@ public class KiafumiConfig {
|
||||||
|
|
||||||
public String getLogChannel() { return logChannel; }
|
public String getLogChannel() { return logChannel; }
|
||||||
|
|
||||||
public int getGameCheckTime() { return gameCheckTime; }
|
|
||||||
|
|
||||||
public List<String> getPingResponses() { return pingResponses; }
|
public List<String> getPingResponses() { return pingResponses; }
|
||||||
|
|
||||||
public KiafumiDB createDb() { return new KiafumiDB(username, password, host, port, database); }
|
public DBCredentials getCredentials () { return new DBCredentials(
|
||||||
|
username, password, host, port, database, poolSize, connTimeout, idleTimeout, maxLifetime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public KiafumiDB createDb() { return new KiafumiDB(getCredentials()); }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
package moe.oko.Kiafumi.command.image;
|
|
||||||
|
|
||||||
import moe.oko.Kiafumi.command.CommandClass;
|
|
||||||
import moe.oko.Kiafumi.util.CommandInfo;
|
|
||||||
import moe.oko.Kiafumi.util.CommandType;
|
|
||||||
import moe.oko.Kiafumi.util.EmbedUI;
|
|
||||||
import net.dv8tion.jda.api.EmbedBuilder;
|
|
||||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
|
||||||
import org.apache.http.client.methods.HttpGet;
|
|
||||||
import org.apache.http.impl.client.HttpClients;
|
|
||||||
import org.json.JSONArray;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static moe.oko.Kiafumi.util.LoggingManager.error;
|
|
||||||
import static moe.oko.Kiafumi.util.LoggingManager.slashLog;
|
|
||||||
import static moe.oko.Kiafumi.util.ResponseHandlers.STRING_RESPONSE_HANDLER;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mrow :3
|
|
||||||
* @author Kay
|
|
||||||
*/
|
|
||||||
public class CatCommand extends CommandClass {
|
|
||||||
|
|
||||||
private final URI catUrl = URI.create("https://api.thecatapi.com/v1/images/search");
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEnabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "Cat";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void newCommand(String name, SlashCommandInteractionEvent e) {
|
|
||||||
switch (name) {
|
|
||||||
case "cat":
|
|
||||||
slashLog(e);
|
|
||||||
e.deferReply().queue();
|
|
||||||
|
|
||||||
var httpClient = HttpClients.createDefault();
|
|
||||||
var httpGet = new HttpGet(catUrl);
|
|
||||||
try {
|
|
||||||
var responseBody = httpClient.execute(httpGet, STRING_RESPONSE_HANDLER);
|
|
||||||
var array = new JSONArray(responseBody);
|
|
||||||
var obj = array.getJSONObject(0);
|
|
||||||
var eb = new EmbedBuilder()
|
|
||||||
.setColor(EmbedUI.INFO)
|
|
||||||
.setTitle("meow")
|
|
||||||
.setImage(obj.getString("url"))
|
|
||||||
.setFooter(EmbedUI.BRAND);
|
|
||||||
e.getHook().sendMessageEmbeds(eb.build()).queue();
|
|
||||||
} catch (Exception ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
error("Error using CatCommand.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<CommandInfo> getSlashCommandInfo() {
|
|
||||||
List<CommandInfo> cil = new ArrayList<>();
|
|
||||||
cil.add(new CommandInfo("cat", "Provides a random cat!", CommandType.COMMAND));
|
|
||||||
return cil;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -27,322 +27,208 @@ import org.apache.commons.io.FileUtils;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static moe.oko.Kiafumi.util.LoggingManager.info;
|
||||||
import static moe.oko.Kiafumi.util.LoggingManager.slashLog;
|
import static moe.oko.Kiafumi.util.LoggingManager.slashLog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Music Command
|
* Music Command
|
||||||
* Most code taken from SHIRO Project (ISC License still applies)
|
* Some code may be taken from SHIRO Project (ISC License still applies)
|
||||||
* @author Kay
|
* @author Kay, oko
|
||||||
*/
|
*/
|
||||||
public class MusicCommand extends CommandClass {
|
public class MusicCommand extends CommandClass {
|
||||||
|
|
||||||
private static final int PLAYLIST_LIMIT = 200;
|
private final AudioPlayerManager audioPlayerManager = new DefaultAudioPlayerManager();
|
||||||
private static final AudioPlayerManager myManager = new DefaultAudioPlayerManager();
|
private final Map<String, Map.Entry<AudioPlayer, TrackManager>> players = new HashMap<>();
|
||||||
private static final Map<String, Map.Entry<AudioPlayer, TrackManager>> players = new HashMap<>();
|
|
||||||
|
|
||||||
private static final String CD = "\uD83D\uDCBF";
|
public MusicCommand() { AudioSourceManagers.registerRemoteSources(audioPlayerManager); }
|
||||||
private static final String DVD = "\uD83D\uDCC0";
|
|
||||||
private static final String MIC = "\uD83C\uDFA4 **|>** ";
|
|
||||||
|
|
||||||
private static final String QUEUE_TITLE = "__%s has added %d new track%s to the Queue:__";
|
|
||||||
private static final String QUEUE_DESCRIPTION = "%s **|>** %s\n%s\n%s %s\n%s";
|
|
||||||
private static final String QUEUE_INFO = "Info about the Queue: (Size - %d)";
|
|
||||||
private static final String ERROR = "Error while loading \"%s\"";
|
|
||||||
|
|
||||||
private boolean enabled = true;
|
|
||||||
|
|
||||||
public MusicCommand() {
|
|
||||||
AudioSourceManagers.registerRemoteSources(myManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() { return true; }
|
||||||
return enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() { return "Music"; }
|
||||||
return "Music";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void newCommand(String name, SlashCommandInteractionEvent e) {
|
public void newCommand(String name, SlashCommandInteractionEvent e) {
|
||||||
if(e.getGuild() != null) {
|
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case "nowplaying":
|
case "play" -> {
|
||||||
slashLog(e);
|
|
||||||
e.deferReply().queue();
|
|
||||||
if (!hasPlayer(e.getGuild()) || getPlayer(e.getGuild()).getPlayingTrack() == null) { // No song is playing
|
|
||||||
e.getHook().sendMessage("No song is playing.").queue();
|
|
||||||
} else {
|
|
||||||
var track = getPlayer(e.getGuild()).getPlayingTrack();
|
|
||||||
//Works
|
|
||||||
var eb = new EmbedBuilder();
|
|
||||||
eb.setColor(EmbedUI.SUCCESS);
|
|
||||||
eb.setTitle("Track Info");
|
|
||||||
eb.setDescription("Currently Playing - " + track.getInfo().title);
|
|
||||||
eb.addField("Time", "["+ getTimestamp(track.getPosition()) + "/" + getTimestamp(track.getInfo().length) + "]", false);
|
|
||||||
eb.addField("Creator", track.getInfo().author, false);
|
|
||||||
eb.addField("Queued By", getTrackManager(e.getGuild()).getTrackInfo(track).getAuthor().getUser().getName(), false);
|
|
||||||
e.getHook().sendMessageEmbeds(eb.build()).queue();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "queue":
|
|
||||||
slashLog(e);
|
|
||||||
e.deferReply().queue();
|
|
||||||
if (!hasPlayer(e.getGuild()) || getTrackManager(e.getGuild()).getQueuedTracks().isEmpty()) {
|
|
||||||
e.getHook().sendMessage("The queue is empty.").queue();
|
|
||||||
} else {
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
Set<AudioInfo> queue = getTrackManager(e.getGuild()).getQueuedTracks();
|
|
||||||
queue.forEach(audioInfo -> sb.append(buildQueueMessage(audioInfo)));
|
|
||||||
var embedTitle = String.format(QUEUE_INFO, queue.size());
|
|
||||||
|
|
||||||
if (sb.length() <= 1960) {
|
|
||||||
var eb = new EmbedBuilder();
|
|
||||||
eb.setColor(EmbedUI.SUCCESS);
|
|
||||||
eb.setTitle(embedTitle);
|
|
||||||
eb.addField("In Queue", "**>** " + sb.toString(), false);
|
|
||||||
e.getHook().sendMessageEmbeds(eb.build()).queue();
|
|
||||||
} else {
|
|
||||||
var qFile = new File("queue.txt");
|
|
||||||
try {
|
|
||||||
FileUtils.write(qFile, sb.toString(), "UTF-8", false);
|
|
||||||
e.getHook().sendMessage("**Queue was too large to put into text, linked file below contains all songs queued.").queue();
|
|
||||||
e.getHook().sendFile(qFile, qFile.getName(), null).queue();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
if (!qFile.delete()) { // Delete the queue file after we're done
|
|
||||||
qFile.deleteOnExit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "skip":
|
|
||||||
slashLog(e);
|
|
||||||
e.deferReply().queue();
|
|
||||||
if (isIdle(e.getHook(), e.getGuild())) return;
|
|
||||||
|
|
||||||
if (isCurrentDj(e.getMember())) {
|
|
||||||
forceSkipTrack(e.getGuild(), e.getHook());
|
|
||||||
} else {
|
|
||||||
AudioInfo info = getTrackManager(e.getGuild()).getTrackInfo(getPlayer(e.getGuild()).getPlayingTrack());
|
|
||||||
if (info.hasVoted(e.getUser())) {
|
|
||||||
e.getHook().sendMessage("\u26A0 You've already voted to skip this song!").queue();
|
|
||||||
} else {
|
|
||||||
// Determine requisite votes.
|
|
||||||
int votes = info.getSkips();
|
|
||||||
int channelUsers = info.getAuthor().getVoiceState().getChannel().getMembers().size()-1;
|
|
||||||
int required = channelUsers/2;
|
|
||||||
if (votes+1 >= required){
|
|
||||||
getPlayer(e.getGuild()).stopTrack();
|
|
||||||
e.getHook().sendMessage("\u23E9 Skipping current track.").queue();
|
|
||||||
} else {
|
|
||||||
info.addSkip(e.getUser());
|
|
||||||
e.getHook().sendMessage("**" + e.getUser().getName() + "** voted to skip the track. [" + (votes+1) + "/" + (required) + "]").queue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "forceskip":
|
|
||||||
slashLog(e);
|
|
||||||
e.deferReply().queue();
|
|
||||||
if (isIdle(e.getHook(), e.getGuild())) return;
|
|
||||||
if (isCurrentDj(e.getMember()) || isDj(e.getMember())) {
|
|
||||||
forceSkipTrack(e.getGuild(), e.getHook());
|
|
||||||
} else {
|
|
||||||
e.getHook().sendMessage("You don't have permission to do that!\n"
|
|
||||||
+ "Use **/skip** to cast a vote!").queue();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "reset":
|
|
||||||
slashLog(e);
|
|
||||||
e.deferReply().queue();
|
|
||||||
if (!e.getMember().getPermissions().contains(Permission.ADMINISTRATOR) && !e.getMember().isOwner()) {
|
|
||||||
e.getHook().sendMessage("You don't have the required permissions to do that! [ADMIN]").queue();
|
|
||||||
} else {
|
|
||||||
reset(e.getGuild());
|
|
||||||
e.getHook().sendMessage("\uD83D\uDD04 Resetting the music player..").queue();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "shuffle":
|
|
||||||
slashLog(e);
|
|
||||||
e.deferReply().queue();
|
|
||||||
if (isIdle(e.getHook(), e.getGuild())) return;
|
|
||||||
|
|
||||||
if (isDj(e.getMember())) {
|
|
||||||
getTrackManager(e.getGuild()).shuffleQueue();
|
|
||||||
e.getHook().sendMessage("\u2705 Shuffled the queue!").queue();
|
|
||||||
} else {
|
|
||||||
e.getHook().sendMessage("\u26D4 You don't have the permission to do that!").queue();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "stop":
|
|
||||||
e.deferReply().queue();
|
|
||||||
if(isIdle(e.getHook(), e.getGuild())) return;
|
|
||||||
|
|
||||||
getTrackManager(e.getGuild()).purgeQueue();
|
|
||||||
getPlayer(e.getGuild()).stopTrack();
|
|
||||||
e.getHook().sendMessage("Stopped the track. :boom:").queue();
|
|
||||||
break;
|
|
||||||
case "play":
|
|
||||||
e.deferReply().queue();
|
e.deferReply().queue();
|
||||||
var input = e.getOption("url").getAsString();
|
var input = e.getOption("url").getAsString();
|
||||||
slashLog(e, "with search \"" + input + "\".");
|
slashLog(e, "with search \"%s\".".formatted(input));
|
||||||
if(input.contains("https://")) {
|
|
||||||
|
if(input.startsWith("https://"))
|
||||||
loadTrack(input, e.getMember(), e.getHook());
|
loadTrack(input, e.getMember(), e.getHook());
|
||||||
} else {
|
else
|
||||||
loadTrack("ytsearch: " + input, e.getMember(), e.getHook());
|
loadTrack("ytsearch: " + input, e.getMember(), e.getHook());
|
||||||
}
|
}
|
||||||
break;
|
case "skip" -> {
|
||||||
|
e.deferReply().queue();
|
||||||
|
slashLog(e);
|
||||||
|
if (isAdmin(e.getMember())) {
|
||||||
|
getPlayer(e.getGuild()).stopTrack();
|
||||||
|
e.getHook().sendMessage("Skipping the current track.").queue();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var info = getTrackManager(e.getGuild()).getTrackInfo(getPlayer(e.getGuild()).getPlayingTrack());
|
||||||
|
if (info.hasVoted(e.getUser()))
|
||||||
|
e.getHook().setEphemeral(true).sendMessage("You've already voted to skip this track.");
|
||||||
|
else {
|
||||||
|
int votes = info.getSkips();
|
||||||
|
int users = info.getAuthor().getVoiceState().getChannel().getMembers().size()-1;
|
||||||
|
int requiredVotes = users/2;
|
||||||
|
if (votes > requiredVotes) {
|
||||||
|
getPlayer(e.getGuild()).stopTrack();
|
||||||
|
e.getHook().sendMessage("Skipping the current track.").queue();
|
||||||
|
} else {
|
||||||
|
info.addSkip(e.getUser());
|
||||||
|
e.getHook().sendMessage("**%s** has voted to skip the track (%s/%s)"
|
||||||
|
.formatted(e.getUser().getName(), votes, requiredVotes)).queue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "nowplaying" -> {
|
||||||
|
e.deferReply().queue();
|
||||||
|
slashLog(e);
|
||||||
|
if (!hasPlayer(e.getGuild()) || getPlayer(e.getGuild()).getPlayingTrack() == null)
|
||||||
|
e.getHook().sendMessage("No song is currently playing.").queue();
|
||||||
|
else {
|
||||||
|
var track = getPlayer(e.getGuild()).getPlayingTrack().getInfo();
|
||||||
|
e.getHook().sendMessageEmbeds(new EmbedBuilder()
|
||||||
|
.setColor(EmbedUI.SUCCESS)
|
||||||
|
.setAuthor("Now playing")
|
||||||
|
.setDescription("[%s](%s)".formatted(track.title, track.uri))
|
||||||
|
.addField("Info", "Channel: %s\nLength: %s".formatted(track.author, getTimestamp(track.length)), false)
|
||||||
|
.setFooter("Requested by: " + e.getUser().getName()).build()).queue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "queue" -> {
|
||||||
|
e.deferReply().queue();
|
||||||
|
slashLog(e);
|
||||||
|
if (!hasPlayer(e.getGuild()) || getTrackManager(e.getGuild()).getQueuedTracks().isEmpty())
|
||||||
|
e.getHook().sendMessage("There is nothing queued.").queue();
|
||||||
|
else {
|
||||||
|
var trackList = new StringBuilder();
|
||||||
|
var queuedTracks = getTrackManager(e.getGuild()).getQueuedTracks();
|
||||||
|
final short[] trackSize = {-1};
|
||||||
|
queuedTracks.forEach(audioInfo -> {
|
||||||
|
trackList.append(buildQueueString(audioInfo));
|
||||||
|
trackSize[0]++;
|
||||||
|
});
|
||||||
|
var eb = new EmbedBuilder().setColor(EmbedUI.SUCCESS);
|
||||||
|
if (trackList.length() >= 990) {
|
||||||
|
eb.addField("Queue", "**>** " + trackList.toString(), false);
|
||||||
|
} else {
|
||||||
|
eb.addField("Queue", "**>** " + getPlayer(e.getGuild()).getPlayingTrack().getInfo().title
|
||||||
|
+ "\n" + trackSize[0] + " other tracks..", false).build();
|
||||||
|
}
|
||||||
|
e.getHook().sendMessageEmbeds(eb.build()).queue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasPlayer(Guild guild) {
|
private void loadTrack(String input, Member author, InteractionHook hook) {
|
||||||
return players.containsKey(guild.getId());
|
if (author.getVoiceState().getChannel() == null) {
|
||||||
|
hook.setEphemeral(true).sendMessage("You are not in a voice channel.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var server = author.getGuild();
|
||||||
|
getPlayer(server);
|
||||||
|
audioPlayerManager.loadItemOrdered(server, input, new AudioLoadResultHandler() {
|
||||||
|
EmbedBuilder eb;
|
||||||
|
@Override
|
||||||
|
public void trackLoaded(AudioTrack audioTrack) {
|
||||||
|
var trackInfo = audioTrack.getInfo();
|
||||||
|
eb = new EmbedBuilder()
|
||||||
|
.setColor(EmbedUI.SUCCESS)
|
||||||
|
.setAuthor("Playing")
|
||||||
|
.setDescription("[%s](%s)".formatted(trackInfo.title, trackInfo.uri))
|
||||||
|
.addField("Info", "Channel: %s\nLength: %s".formatted(trackInfo.author, getTimestamp(trackInfo.length)), false)
|
||||||
|
.setFooter("Requested by: " + author.getEffectiveName());
|
||||||
|
hook.sendMessageEmbeds(eb.build()).queue();
|
||||||
|
getTrackManager(server).queue(audioTrack, author);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playlistLoaded(AudioPlaylist audioPlaylist) {
|
||||||
|
if (input.startsWith("ytsearch:")) {
|
||||||
|
getTrackManager(server).queue(audioPlaylist.getTracks().get(0), author);
|
||||||
|
var trackInfo = audioPlaylist.getTracks().get(0).getInfo();
|
||||||
|
eb = new EmbedBuilder()
|
||||||
|
.setColor(EmbedUI.SUCCESS)
|
||||||
|
.setAuthor("Playing")
|
||||||
|
.setDescription("[%s](%s)".formatted(trackInfo.title, trackInfo.uri))
|
||||||
|
.addField("Info", "Channel: %s\nLength: %s".formatted(trackInfo.author, getTimestamp(trackInfo.length)), false)
|
||||||
|
.setFooter("Requested by: " + author.getEffectiveName());
|
||||||
|
} else {
|
||||||
|
for (AudioTrack audioTrack : audioPlaylist.getTracks()) {
|
||||||
|
getTrackManager(server).queue(audioTrack, author);
|
||||||
|
eb = new EmbedBuilder()
|
||||||
|
.setColor(EmbedUI.SUCCESS)
|
||||||
|
.setAuthor("Loaded tracks")
|
||||||
|
.setDescription("**%s** tracks added to the queue.".formatted(audioPlaylist.getTracks().size()))
|
||||||
|
.setFooter("Requested by: " + author.getEffectiveName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hook.sendMessageEmbeds(eb.build()).queue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void noMatches() {
|
||||||
|
eb = new EmbedBuilder()
|
||||||
|
.setColor(EmbedUI.FAILURE)
|
||||||
|
.setAuthor("Error")
|
||||||
|
.setDescription("No matches were found.");
|
||||||
|
hook.sendMessageEmbeds(eb.build()).queue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadFailed(FriendlyException e) { hook.sendMessage("Unable to play track.").queue(); }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private TrackManager getTrackManager(Guild server) { return players.get(server.getId()).getValue(); }
|
||||||
|
|
||||||
|
private AudioPlayer getPlayer(Guild server) {
|
||||||
|
var player = hasPlayer(server) ? players.get(server.getId()).getKey() : createPlayer(server);
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AudioPlayer createPlayer(Guild server) {
|
||||||
|
var newPlayer = audioPlayerManager.createPlayer();
|
||||||
|
var manager = new TrackManager(newPlayer);
|
||||||
|
newPlayer.addListener(manager);
|
||||||
|
server.getAudioManager().setSendingHandler(new AudioPlayerSendHandler(newPlayer));
|
||||||
|
players.put(server.getId(), new AbstractMap.SimpleEntry<>(newPlayer, manager));
|
||||||
|
return newPlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasPlayer(Guild server) { return players.containsKey(server.getId()); }
|
||||||
|
|
||||||
|
private boolean isAdmin(Member member) { return member.hasPermission(Permission.ADMINISTRATOR); }
|
||||||
|
|
||||||
|
private String getTimestamp(long ms) {
|
||||||
|
return String.format("%02d:%02d:%02d", ms/(3600*1000),
|
||||||
|
ms/(60*1000) % 60,
|
||||||
|
ms/1000 % 60);
|
||||||
|
}
|
||||||
|
private String buildQueueString(AudioInfo info) {
|
||||||
|
var trackInfo = info.getTrack().getInfo();
|
||||||
|
return "%s [%s]\n".formatted(trackInfo.title, getTimestamp(trackInfo.length));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<CommandInfo> getSlashCommandInfo() {
|
public List<CommandInfo> getSlashCommandInfo() {
|
||||||
List<CommandInfo> cil = new ArrayList<>();
|
List<CommandInfo> cil = new ArrayList<>();
|
||||||
CommandInfo ci = new CommandInfo("nowplaying", "Displays the song being currently played.", CommandType.COMMAND);
|
var playCommandList = new CommandInfo("play", "Adds a new track to the queue.", CommandType.COMMAND);
|
||||||
CommandInfo ci1 = new CommandInfo("queue", "Displays the songs currently queued.", CommandType.COMMAND);
|
playCommandList.addOption("url", "The URL or title of the track you want to play.", OptionType.STRING, true);
|
||||||
CommandInfo ci2 = new CommandInfo("skip", "Votes to skip the song currently playing. Or just skips it if you're the DJ.", CommandType.COMMAND);
|
cil.add(playCommandList);
|
||||||
CommandInfo ci3 = new CommandInfo("forceskip", "Forcibly skips the song that is currently playing.", CommandType.COMMAND);
|
cil.add(new CommandInfo("skip", "Votes to skip the current track.", CommandType.COMMAND));
|
||||||
CommandInfo ci4 = new CommandInfo("reset", "Resets the song player. (Admin Only)", CommandType.COMMAND);
|
cil.add(new CommandInfo("nowplaying", "Displays the currently played track." , CommandType.COMMAND));
|
||||||
CommandInfo ci5 = new CommandInfo("play", "Plays a new song from a URL", CommandType.COMMAND);
|
cil.add(new CommandInfo("queue", "Displays the tracks currently queued.", CommandType.COMMAND));
|
||||||
ci5.addOption("url", "The URL or title of the song that you wanted to play.", OptionType.STRING, true);
|
|
||||||
cil.add(ci);
|
|
||||||
cil.add(ci1);
|
|
||||||
cil.add(ci2);
|
|
||||||
cil.add(ci3);
|
|
||||||
cil.add(ci4);
|
|
||||||
cil.add(ci5);
|
|
||||||
return cil;
|
return cil;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AudioPlayer getPlayer(Guild guild) {
|
|
||||||
AudioPlayer p;
|
|
||||||
if (hasPlayer(guild)) {
|
|
||||||
p = players.get(guild.getId()).getKey();
|
|
||||||
} else {
|
|
||||||
p = createPlayer(guild);
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
private TrackManager getTrackManager(Guild guild) {
|
|
||||||
return players.get(guild.getId()).getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
private AudioPlayer createPlayer(Guild guild) {
|
|
||||||
var nPlayer = myManager.createPlayer();
|
|
||||||
var manager = new TrackManager(nPlayer);
|
|
||||||
nPlayer.addListener(manager);
|
|
||||||
guild.getAudioManager().setSendingHandler(new AudioPlayerSendHandler(nPlayer));
|
|
||||||
players.put(guild.getId(), new AbstractMap.SimpleEntry<>(nPlayer, manager));
|
|
||||||
return nPlayer;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void reset(Guild guild) {
|
|
||||||
players.remove(guild.getId());
|
|
||||||
getPlayer(guild).destroy();
|
|
||||||
getTrackManager(guild).purgeQueue();
|
|
||||||
guild.getAudioManager().closeAudioConnection();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadTrack(String identifier, Member author, InteractionHook chat) {
|
|
||||||
if (author.getVoiceState().getChannel() == null) {
|
|
||||||
chat.sendMessage("You are not in a Voice Channel!").queue();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Guild guild = author.getGuild();
|
|
||||||
getPlayer(guild); // Make sure this guild has a player.
|
|
||||||
|
|
||||||
myManager.loadItemOrdered(guild, identifier, new AudioLoadResultHandler() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void trackLoaded(AudioTrack track) {
|
|
||||||
var eb = new EmbedBuilder();
|
|
||||||
eb.setColor(EmbedUI.SUCCESS);
|
|
||||||
eb.setTitle(author.getEffectiveName() + " has loaded " + track.getInfo().title);
|
|
||||||
eb.addField("Track Info", "Creator: " + track.getInfo().author + "\nLength: " + getTimestamp(track.getInfo().length), false);
|
|
||||||
chat.sendMessageEmbeds(eb.build()).queue();
|
|
||||||
getTrackManager(guild).queue(track, author);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void playlistLoaded(AudioPlaylist playlist) {
|
|
||||||
if (playlist.getSelectedTrack() != null) {
|
|
||||||
trackLoaded(playlist.getSelectedTrack());
|
|
||||||
} else if (playlist.isSearchResult()) {
|
|
||||||
trackLoaded(playlist.getTracks().get(0));
|
|
||||||
} else {
|
|
||||||
EmbedBuilder eb = new EmbedBuilder();
|
|
||||||
eb.setColor(EmbedUI.SUCCESS);
|
|
||||||
eb.setTitle(author.getEffectiveName() + " has loaded " + playlist.getTracks().size() + " songs into the queue");
|
|
||||||
chat.sendMessageEmbeds(eb.build()).queue();
|
|
||||||
for (int i = 0; i < Math.min(playlist.getTracks().size(), PLAYLIST_LIMIT); i++) {
|
|
||||||
getTrackManager(guild).queue(playlist.getTracks().get(i), author);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void noMatches() {
|
|
||||||
chat.sendMessage("\u26A0 No playable tracks were found. (If searching, try the command 'ytplay' instead!)").queue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void loadFailed(FriendlyException exception) {
|
|
||||||
chat.sendMessage("\u26D4 " + exception.getLocalizedMessage()).queue();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
//tryToDelete(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isDj(Member member) {
|
|
||||||
return member.getRoles().stream().anyMatch(r -> r.getName().equals("DJ"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isCurrentDj(Member member) {
|
|
||||||
return getTrackManager(member.getGuild()).getTrackInfo(getPlayer(member.getGuild()).getPlayingTrack()).getAuthor().equals(member);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isIdle(InteractionHook chat, Guild guild) {
|
|
||||||
if (!hasPlayer(guild) || getPlayer(guild).getPlayingTrack() == null) {
|
|
||||||
chat.sendMessage("No music is being played at the moment!").queue();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void forceSkipTrack(Guild guild, InteractionHook chat) {
|
|
||||||
getPlayer(guild).stopTrack();
|
|
||||||
chat.sendMessage("\u23E9 Skipping track!").queue();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String buildQueueMessage(AudioInfo info) {
|
|
||||||
var trackInfo = info.getTrack().getInfo();
|
|
||||||
var title = trackInfo.title;
|
|
||||||
long length = trackInfo.length;
|
|
||||||
return "`[ " + getTimestamp(length) + " ]` " + title + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getTimestamp(long milis) {
|
|
||||||
long seconds = milis / 1000;
|
|
||||||
long hours = Math.floorDiv(seconds, 3600);
|
|
||||||
seconds = seconds - (hours * 3600);
|
|
||||||
long mins = Math.floorDiv(seconds, 60);
|
|
||||||
seconds = seconds - (mins * 60);
|
|
||||||
return (hours == 0 ? "" : hours + ":") + String.format("%02d", mins) + ":" + String.format("%02d", seconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getOrNull(String s) {
|
|
||||||
return s.isEmpty() ? "N/A" : s;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
13
src/main/java/moe/oko/Kiafumi/model/db/DBCredentials.java
Normal file
13
src/main/java/moe/oko/Kiafumi/model/db/DBCredentials.java
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
package moe.oko.Kiafumi.model.db;
|
||||||
|
|
||||||
|
public record DBCredentials(
|
||||||
|
String username,
|
||||||
|
String password,
|
||||||
|
String host,
|
||||||
|
int port,
|
||||||
|
String db,
|
||||||
|
int poolSize,
|
||||||
|
long connTimeout,
|
||||||
|
long idleTimeout,
|
||||||
|
long maxLifetime
|
||||||
|
) {}
|
|
@ -1,6 +1,10 @@
|
||||||
package moe.oko.Kiafumi.model;
|
package moe.oko.Kiafumi.model.db;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import com.zaxxer.hikari.HikariConfig;
|
||||||
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
import moe.oko.Kiafumi.Kiafumi;
|
import moe.oko.Kiafumi.Kiafumi;
|
||||||
|
import moe.oko.Kiafumi.model.Server;
|
||||||
import net.dv8tion.jda.api.entities.Guild;
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
|
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
|
@ -14,10 +18,10 @@ import static moe.oko.Kiafumi.util.LoggingManager.*;
|
||||||
* Kiafumi DB Class
|
* Kiafumi DB Class
|
||||||
* Basically our helpful MySQL functions that pertain to data persistence.
|
* Basically our helpful MySQL functions that pertain to data persistence.
|
||||||
* @author Kay, with moral support from Yodabird
|
* @author Kay, with moral support from Yodabird
|
||||||
* @apiNote I HATE SQL I HATE SQL AAAAAAAAAAAAAA
|
|
||||||
*/
|
*/
|
||||||
public class KiafumiDB {
|
public class KiafumiDB {
|
||||||
// Our actual MySQL Connection, this is created on class construction.
|
|
||||||
|
private HikariDataSource dataSource;
|
||||||
private Connection connection;
|
private Connection connection;
|
||||||
|
|
||||||
// The prepared statement strings
|
// The prepared statement strings
|
||||||
|
@ -30,20 +34,29 @@ public class KiafumiDB {
|
||||||
private final String SERVER_INFO_MODIFY = "UPDATE `serverInfo` SET welcomeChannel=?, modChannel=?, joinRole=? WHERE id = ?";
|
private final String SERVER_INFO_MODIFY = "UPDATE `serverInfo` SET welcomeChannel=?, modChannel=?, joinRole=? WHERE id = ?";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* KiafumiDB Config Constructor
|
* KiafumiDB Connection Constructor
|
||||||
* @param username - username to access database
|
|
||||||
* @param password - password to access database
|
|
||||||
* @param host - host for server
|
|
||||||
* @param port - port for server (3306 is default)
|
|
||||||
* @param db - database name
|
|
||||||
*/
|
*/
|
||||||
public KiafumiDB(String username, String password, String host, int port, String db) {
|
public KiafumiDB(DBCredentials credentials) {
|
||||||
|
var config = new HikariConfig();
|
||||||
|
config.setJdbcUrl("jdbc:mysql://%s:%s/%s".formatted(credentials.host(), credentials.port(), credentials.db()));
|
||||||
|
|
||||||
|
config.setConnectionTimeout(credentials.connTimeout());
|
||||||
|
config.setIdleTimeout(credentials.idleTimeout());
|
||||||
|
config.setMaxLifetime(credentials.maxLifetime());
|
||||||
|
config.setMaximumPoolSize(credentials.poolSize());
|
||||||
|
config.setUsername(credentials.username());
|
||||||
|
|
||||||
|
if (!Strings.isNullOrEmpty(credentials.password()))
|
||||||
|
config.setPassword(credentials.password());
|
||||||
|
this.dataSource = new HikariDataSource(config);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
connection = DriverManager.getConnection("jdbc:mysql://" + host + ":" + port + "/" + db, username, password);
|
connection = dataSource.getConnection();
|
||||||
} catch (Exception ex) {
|
info("Connected to database.");
|
||||||
error("Failed to initialize the MySQL instance.");
|
} catch (SQLException e) {
|
||||||
ex.printStackTrace();
|
error("Unable to connect to database.");
|
||||||
return;
|
e.printStackTrace();
|
||||||
|
this.dataSource = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
initializeTables();
|
initializeTables();
|
|
@ -24,8 +24,6 @@ discord:
|
||||||
invitePermissionLevel: 139855252544
|
invitePermissionLevel: 139855252544
|
||||||
# MAIN CONFIG STACK
|
# MAIN CONFIG STACK
|
||||||
main:
|
main:
|
||||||
# Currently, unimplemented, maybe in the future if performance becomes and issue.
|
|
||||||
sharded: false
|
|
||||||
# Activity Type (STREAMING|PLAYING|WATCHING|COMPETING|DEFAULT)
|
# Activity Type (STREAMING|PLAYING|WATCHING|COMPETING|DEFAULT)
|
||||||
activityType: "PLAYING"
|
activityType: "PLAYING"
|
||||||
# Activity Message
|
# Activity Message
|
||||||
|
@ -50,3 +48,7 @@ sql:
|
||||||
database: "kiafumi"
|
database: "kiafumi"
|
||||||
username: "alpine"
|
username: "alpine"
|
||||||
password: "squidlover42069"
|
password: "squidlover42069"
|
||||||
|
poolSize: 2
|
||||||
|
connectionTimeout: 10000
|
||||||
|
idleTimeout: 600000
|
||||||
|
maxLifetime: 7200000
|
Loading…
Reference in a new issue