Compare commits
10 Commits
8557f7ab8e
...
c962d9a0d3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c962d9a0d3 | ||
|
|
136e9ed0bc | ||
|
|
859e5c5862 | ||
|
|
43b63f1ba8 | ||
|
|
eca2563abf | ||
|
|
e6bfd1841f | ||
|
|
f140b41bf5 | ||
|
|
8733899aa0 | ||
|
|
e5fd05e601 | ||
|
|
6a5a9c7a75 |
9
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
9
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@@ -53,5 +53,12 @@ body:
|
|||||||
required: true
|
required: true
|
||||||
- label: I have searched for similar issues [on the issues page](https://github.com/jagrosh/MusicBot/issues?q=is%3Aissue)
|
- label: I have searched for similar issues [on the issues page](https://github.com/jagrosh/MusicBot/issues?q=is%3Aissue)
|
||||||
required: true
|
required: true
|
||||||
- label: "I am running the latest version of the bot: "
|
- label: I am using an official release from [the releases page](https://github.com/jagrosh/MusicBot/releases)
|
||||||
required: true
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: version
|
||||||
|
attributes:
|
||||||
|
label: JMusicBot Version
|
||||||
|
description: Which version of JMusicBot are you running?
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|||||||
70
pom.xml
70
pom.xml
@@ -8,9 +8,9 @@
|
|||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
<repository>
|
<repository>
|
||||||
<id>dv8tion</id>
|
<id>chew</id>
|
||||||
<name>m2-dv8tion</name>
|
<name>m2-chew</name>
|
||||||
<url>https://m2.dv8tion.net/releases</url>
|
<url>https://m2.chew.pro/releases</url>
|
||||||
</repository>
|
</repository>
|
||||||
<repository>
|
<repository>
|
||||||
<id>central</id>
|
<id>central</id>
|
||||||
@@ -31,9 +31,9 @@
|
|||||||
<url>https://m2.duncte123.dev/releases</url>
|
<url>https://m2.duncte123.dev/releases</url>
|
||||||
</repository>
|
</repository>
|
||||||
<repository>
|
<repository>
|
||||||
<id>arbjergDev-snapshots</id>
|
<id>arbjergDev</id>
|
||||||
<name>Lavalink Repository</name>
|
<name>Lavalink Repository</name>
|
||||||
<url>https://maven.lavalink.dev/snapshots</url>
|
<url>https://maven.lavalink.dev/releases</url>
|
||||||
</repository>
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
@@ -42,25 +42,63 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.dv8tion</groupId>
|
<groupId>net.dv8tion</groupId>
|
||||||
<artifactId>JDA</artifactId>
|
<artifactId>JDA</artifactId>
|
||||||
<version>4.4.1_353</version>
|
<version>6.3.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>club.minnced</groupId>
|
||||||
|
<artifactId>jdave-api</artifactId>
|
||||||
|
<version>0.1.7</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>club.minnced</groupId>
|
||||||
|
<artifactId>jdave-native-linux-x86-64</artifactId>
|
||||||
|
<version>0.1.7</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.jagrosh</groupId>
|
<groupId>club.minnced</groupId>
|
||||||
<artifactId>jda-utilities</artifactId>
|
<artifactId>jdave-native-linux-aarch64</artifactId>
|
||||||
<version>3.0.5</version>
|
<version>0.1.7</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>club.minnced</groupId>
|
||||||
|
<artifactId>jdave-native-win-x86-64</artifactId>
|
||||||
|
<version>0.1.7</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>club.minnced</groupId>
|
||||||
|
<artifactId>jdave-native-darwin</artifactId>
|
||||||
|
<version>0.1.7</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>pw.chew</groupId>
|
||||||
|
<artifactId>jda-chewtils</artifactId>
|
||||||
|
<version>2.2.1</version>
|
||||||
|
<scope>compile</scope>
|
||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>pw.chew</groupId>
|
||||||
|
<artifactId>jda-chewtils-command</artifactId>
|
||||||
|
<version>2.2.1</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>pw.chew</groupId>
|
||||||
|
<artifactId>jda-chewtils-examples</artifactId>
|
||||||
|
<version>2.2.1</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Music Dependencies -->
|
<!-- Music Dependencies -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>dev.arbjerg</groupId>
|
<groupId>dev.arbjerg</groupId>
|
||||||
<artifactId>lavaplayer</artifactId>
|
<artifactId>lavaplayer</artifactId>
|
||||||
<version>2.1.1</version>
|
<version>2.2.4</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.lavalink-devs</groupId>
|
<groupId>dev.lavalink.youtube</groupId>
|
||||||
<artifactId>lavaplayer-youtube-source</artifactId>
|
<artifactId>common</artifactId>
|
||||||
<version>1.0.4</version>
|
<version>1.13.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.jagrosh</groupId>
|
<groupId>com.github.jagrosh</groupId>
|
||||||
@@ -77,7 +115,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ch.qos.logback</groupId>
|
<groupId>ch.qos.logback</groupId>
|
||||||
<artifactId>logback-classic</artifactId>
|
<artifactId>logback-classic</artifactId>
|
||||||
<version>1.2.13</version>
|
<version>1.5.18</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.typesafe</groupId>
|
<groupId>com.typesafe</groupId>
|
||||||
@@ -149,7 +187,7 @@
|
|||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<maven.compiler.source>11</maven.compiler.source>
|
<maven.compiler.source>25</maven.compiler.source>
|
||||||
<maven.compiler.target>11</maven.compiler.target>
|
<maven.compiler.target>25</maven.compiler.target>
|
||||||
</properties>
|
</properties>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
30
scripts/Dockerfile
Normal file
30
scripts/Dockerfile
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
FROM eclipse-temurin:25-jre
|
||||||
|
|
||||||
|
LABEL maintainer="Elijah"
|
||||||
|
|
||||||
|
ARG BUILD_DATE
|
||||||
|
ARG VERSION
|
||||||
|
|
||||||
|
LABEL org.label-schema.schema-version="1.0"
|
||||||
|
LABEL org.label-schema.build-date=$BUILD_DATE
|
||||||
|
LABEL org.label-schema.name="jmusicbot25"
|
||||||
|
LABEL org.label-schema.description="Java based Discord music bot"
|
||||||
|
LABEL org.label-schema.version=$VERSION
|
||||||
|
LABEL org.label-schema.docker.cmd="docker run -v ./config:/jmb/config -d jmusicbot25"
|
||||||
|
|
||||||
|
# Install tini (Debian-based now, so use apt)
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y --no-install-recommends tini && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN mkdir -p /jmb/config
|
||||||
|
|
||||||
|
COPY JMusicBot-Snapshot-All.jar /jmb/JMusicBot.jar
|
||||||
|
COPY docker-entrypoint.sh /jmb/docker-entrypoint.sh
|
||||||
|
RUN chmod 755 /jmb/docker-entrypoint.sh
|
||||||
|
|
||||||
|
VOLUME /jmb/config
|
||||||
|
|
||||||
|
WORKDIR /jmb/config
|
||||||
|
|
||||||
|
ENTRYPOINT ["/usr/bin/tini", "--", "/jmb/docker-entrypoint.sh"]
|
||||||
9
scripts/docker-compose.yaml
Normal file
9
scripts/docker-compose.yaml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
version: '2.2'
|
||||||
|
|
||||||
|
services:
|
||||||
|
jmusicbot:
|
||||||
|
image: jmusicbot25
|
||||||
|
container_name: jmusicbot25-instance
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./config:/jmb/config
|
||||||
3
scripts/docker-entrypoint.sh
Normal file
3
scripts/docker-entrypoint.sh
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
java -jar -Dnogui=true /jmb/JMusicBot.jar
|
||||||
@@ -9,7 +9,7 @@ DOWNLOAD=true
|
|||||||
LOOP=true
|
LOOP=true
|
||||||
|
|
||||||
download() {
|
download() {
|
||||||
if [ $DOWNLOAD == true ]; then
|
if [ $DOWNLOAD = true ]; then
|
||||||
URL=$(curl -s https://api.github.com/repos/jagrosh/MusicBot/releases/latest \
|
URL=$(curl -s https://api.github.com/repos/jagrosh/MusicBot/releases/latest \
|
||||||
| grep -i "browser_download_url.*\.jar" \
|
| grep -i "browser_download_url.*\.jar" \
|
||||||
| sed 's/.*\(http.*\)"/\1/')
|
| sed 's/.*\(http.*\)"/\1/')
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import com.jagrosh.jmusicbot.playlist.PlaylistLoader;
|
|||||||
import com.jagrosh.jmusicbot.settings.SettingsManager;
|
import com.jagrosh.jmusicbot.settings.SettingsManager;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import net.dv8tion.jda.api.JDA;
|
import net.dv8tion.jda.api.JDA;
|
||||||
|
import net.dv8tion.jda.api.OnlineStatus;
|
||||||
import net.dv8tion.jda.api.entities.Activity;
|
import net.dv8tion.jda.api.entities.Activity;
|
||||||
import net.dv8tion.jda.api.entities.Guild;
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
|
|
||||||
@@ -121,6 +122,9 @@ public class Bot
|
|||||||
Activity game = config.getGame()==null || config.getGame().getName().equalsIgnoreCase("none") ? null : config.getGame();
|
Activity game = config.getGame()==null || config.getGame().getName().equalsIgnoreCase("none") ? null : config.getGame();
|
||||||
if(!Objects.equals(jda.getPresence().getActivity(), game))
|
if(!Objects.equals(jda.getPresence().getActivity(), game))
|
||||||
jda.getPresence().setActivity(game);
|
jda.getPresence().setActivity(game);
|
||||||
|
OnlineStatus status = config.getStatus();
|
||||||
|
if(status != OnlineStatus.UNKNOWN && jda.getPresence().getStatus() != status)
|
||||||
|
jda.getPresence().setStatus(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutdown()
|
public void shutdown()
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ public class BotConfig
|
|||||||
evalEngine;
|
evalEngine;
|
||||||
private boolean stayInChannel, songInGame, npImages, updatealerts, useEval, dbots;
|
private boolean stayInChannel, songInGame, npImages, updatealerts, useEval, dbots;
|
||||||
private long owner, maxSeconds, aloneTimeUntilStop;
|
private long owner, maxSeconds, aloneTimeUntilStop;
|
||||||
|
private int maxYTPlaylistPages;
|
||||||
private double skipratio;
|
private double skipratio;
|
||||||
private OnlineStatus status;
|
private OnlineStatus status;
|
||||||
private Activity game;
|
private Activity game;
|
||||||
@@ -91,6 +92,7 @@ public class BotConfig
|
|||||||
useEval = config.getBoolean("eval");
|
useEval = config.getBoolean("eval");
|
||||||
evalEngine = config.getString("evalengine");
|
evalEngine = config.getString("evalengine");
|
||||||
maxSeconds = config.getLong("maxtime");
|
maxSeconds = config.getLong("maxtime");
|
||||||
|
maxYTPlaylistPages = config.getInt("maxytplaylistpages");
|
||||||
aloneTimeUntilStop = config.getLong("alonetimeuntilstop");
|
aloneTimeUntilStop = config.getLong("alonetimeuntilstop");
|
||||||
playlistsFolder = config.getString("playlistsfolder");
|
playlistsFolder = config.getString("playlistsfolder");
|
||||||
aliases = config.getConfig("aliases");
|
aliases = config.getConfig("aliases");
|
||||||
@@ -341,6 +343,11 @@ public class BotConfig
|
|||||||
return maxSeconds;
|
return maxSeconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxYTPlaylistPages()
|
||||||
|
{
|
||||||
|
return maxYTPlaylistPages;
|
||||||
|
}
|
||||||
|
|
||||||
public String getMaxTime()
|
public String getMaxTime()
|
||||||
{
|
{
|
||||||
return TimeUtil.formatTime(maxSeconds * 1000);
|
return TimeUtil.formatTime(maxSeconds * 1000);
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ import com.jagrosh.jmusicbot.settings.SettingsManager;
|
|||||||
import com.jagrosh.jmusicbot.utils.OtherUtil;
|
import com.jagrosh.jmusicbot.utils.OtherUtil;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import javax.security.auth.login.LoginException;
|
|
||||||
import net.dv8tion.jda.api.*;
|
import net.dv8tion.jda.api.*;
|
||||||
|
import net.dv8tion.jda.api.audio.AudioModuleConfig;
|
||||||
import net.dv8tion.jda.api.entities.Activity;
|
import net.dv8tion.jda.api.entities.Activity;
|
||||||
import net.dv8tion.jda.api.requests.GatewayIntent;
|
import net.dv8tion.jda.api.requests.GatewayIntent;
|
||||||
import net.dv8tion.jda.api.utils.cache.CacheFlag;
|
import net.dv8tion.jda.api.utils.cache.CacheFlag;
|
||||||
@@ -39,27 +39,28 @@ import net.dv8tion.jda.api.exceptions.ErrorResponseException;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import ch.qos.logback.classic.Level;
|
import ch.qos.logback.classic.Level;
|
||||||
|
import club.minnced.discord.jdave.interop.JDaveSessionFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author John Grosh (jagrosh)
|
* @author John Grosh (jagrosh)
|
||||||
*/
|
*/
|
||||||
public class JMusicBot
|
public class JMusicBot {
|
||||||
{
|
|
||||||
public final static Logger LOG = LoggerFactory.getLogger(JMusicBot.class);
|
public final static Logger LOG = LoggerFactory.getLogger(JMusicBot.class);
|
||||||
public final static Permission[] RECOMMENDED_PERMS = {Permission.MESSAGE_READ, Permission.MESSAGE_WRITE, Permission.MESSAGE_HISTORY, Permission.MESSAGE_ADD_REACTION,
|
public final static Permission[] RECOMMENDED_PERMS = { Permission.VIEW_CHANNEL, Permission.MESSAGE_SEND,
|
||||||
Permission.MESSAGE_EMBED_LINKS, Permission.MESSAGE_ATTACH_FILES, Permission.MESSAGE_MANAGE, Permission.MESSAGE_EXT_EMOJI,
|
Permission.MESSAGE_HISTORY, Permission.MESSAGE_ADD_REACTION,
|
||||||
Permission.VOICE_CONNECT, Permission.VOICE_SPEAK, Permission.NICKNAME_CHANGE};
|
Permission.MESSAGE_EMBED_LINKS, Permission.MESSAGE_ATTACH_FILES, Permission.MESSAGE_MANAGE,
|
||||||
public final static GatewayIntent[] INTENTS = {GatewayIntent.DIRECT_MESSAGES, GatewayIntent.GUILD_MESSAGES, GatewayIntent.GUILD_MESSAGE_REACTIONS, GatewayIntent.GUILD_VOICE_STATES};
|
Permission.MESSAGE_EXT_EMOJI,
|
||||||
|
Permission.VOICE_CONNECT, Permission.VOICE_SPEAK, Permission.NICKNAME_CHANGE };
|
||||||
|
public final static GatewayIntent[] INTENTS = { GatewayIntent.MESSAGE_CONTENT, GatewayIntent.DIRECT_MESSAGES,
|
||||||
|
GatewayIntent.GUILD_MESSAGES, GatewayIntent.GUILD_MESSAGE_REACTIONS, GatewayIntent.GUILD_VOICE_STATES };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param args the command line arguments
|
* @param args the command line arguments
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args)
|
public static void main(String[] args) {
|
||||||
{
|
if (args.length > 0)
|
||||||
if(args.length > 0)
|
switch (args[0].toLowerCase()) {
|
||||||
switch(args[0].toLowerCase())
|
|
||||||
{
|
|
||||||
case "generate-config":
|
case "generate-config":
|
||||||
BotConfig.writeDefaultConfig();
|
BotConfig.writeDefaultConfig();
|
||||||
return;
|
return;
|
||||||
@@ -68,8 +69,7 @@ public class JMusicBot
|
|||||||
startBot();
|
startBot();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void startBot()
|
private static void startBot() {
|
||||||
{
|
|
||||||
// create prompt to handle startup
|
// create prompt to handle startup
|
||||||
Prompt prompt = new Prompt("JMusicBot");
|
Prompt prompt = new Prompt("JMusicBot");
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ public class JMusicBot
|
|||||||
// load config
|
// load config
|
||||||
BotConfig config = new BotConfig(prompt);
|
BotConfig config = new BotConfig(prompt);
|
||||||
config.load();
|
config.load();
|
||||||
if(!config.isValid())
|
if (!config.isValid())
|
||||||
return;
|
return;
|
||||||
LOG.info("Loaded config from " + config.getConfigLocation());
|
LOG.info("Loaded config from " + config.getConfigLocation());
|
||||||
|
|
||||||
@@ -94,19 +94,14 @@ public class JMusicBot
|
|||||||
Bot bot = new Bot(waiter, config, settings);
|
Bot bot = new Bot(waiter, config, settings);
|
||||||
CommandClient client = createCommandClient(config, settings, bot);
|
CommandClient client = createCommandClient(config, settings, bot);
|
||||||
|
|
||||||
|
if (!prompt.isNoGUI()) {
|
||||||
if(!prompt.isNoGUI())
|
try {
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
GUI gui = new GUI(bot);
|
GUI gui = new GUI(bot);
|
||||||
bot.setGUI(gui);
|
bot.setGUI(gui);
|
||||||
gui.init();
|
gui.init();
|
||||||
|
|
||||||
LOG.info("Loaded config from " + config.getConfigLocation());
|
LOG.info("Loaded config from " + config.getConfigLocation());
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch(Exception e)
|
|
||||||
{
|
|
||||||
LOG.error("Could not start GUI. If you are "
|
LOG.error("Could not start GUI. If you are "
|
||||||
+ "running on a server or in a location where you cannot display a "
|
+ "running on a server or in a location where you cannot display a "
|
||||||
+ "window, please run in nogui mode using the -Dnogui=true flag.");
|
+ "window, please run in nogui mode using the -Dnogui=true flag.");
|
||||||
@@ -114,25 +109,32 @@ public class JMusicBot
|
|||||||
}
|
}
|
||||||
|
|
||||||
// attempt to log in and start
|
// attempt to log in and start
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
JDA jda = JDABuilder.create(config.getToken(), Arrays.asList(INTENTS))
|
JDA jda = JDABuilder.create(config.getToken(), Arrays.asList(INTENTS))
|
||||||
.enableCache(CacheFlag.MEMBER_OVERRIDES, CacheFlag.VOICE_STATE)
|
.enableCache(CacheFlag.MEMBER_OVERRIDES, CacheFlag.VOICE_STATE)
|
||||||
.disableCache(CacheFlag.ACTIVITY, CacheFlag.CLIENT_STATUS, CacheFlag.EMOTE, CacheFlag.ONLINE_STATUS)
|
.disableCache(CacheFlag.ACTIVITY, CacheFlag.CLIENT_STATUS, CacheFlag.EMOJI, CacheFlag.ONLINE_STATUS,
|
||||||
|
CacheFlag.STICKER, CacheFlag.SCHEDULED_EVENTS)
|
||||||
.setActivity(config.isGameNone() ? null : Activity.playing("loading..."))
|
.setActivity(config.isGameNone() ? null : Activity.playing("loading..."))
|
||||||
.setStatus(config.getStatus()==OnlineStatus.INVISIBLE || config.getStatus()==OnlineStatus.OFFLINE
|
.setStatus(
|
||||||
? OnlineStatus.INVISIBLE : OnlineStatus.DO_NOT_DISTURB)
|
config.getStatus() == OnlineStatus.INVISIBLE || config.getStatus() == OnlineStatus.OFFLINE
|
||||||
|
? OnlineStatus.INVISIBLE
|
||||||
|
: OnlineStatus.DO_NOT_DISTURB)
|
||||||
.addEventListeners(client, waiter, new Listener(bot))
|
.addEventListeners(client, waiter, new Listener(bot))
|
||||||
.setBulkDeleteSplittingEnabled(true)
|
.setBulkDeleteSplittingEnabled(true)
|
||||||
|
.setAudioModuleConfig(new AudioModuleConfig()
|
||||||
|
.withDaveSessionFactory(new JDaveSessionFactory()))
|
||||||
.build();
|
.build();
|
||||||
bot.setJDA(jda);
|
bot.setJDA(jda);
|
||||||
|
|
||||||
// check if something about the current startup is not supported
|
// check if something about the current startup is not supported
|
||||||
String unsupportedReason = OtherUtil.getUnsupportedBotReason(jda);
|
String unsupportedReason = OtherUtil.getUnsupportedBotReason(jda);
|
||||||
if (unsupportedReason != null)
|
if (unsupportedReason != null) {
|
||||||
{
|
prompt.alert(Prompt.Level.ERROR, "JMusicBot",
|
||||||
prompt.alert(Prompt.Level.ERROR, "JMusicBot", "JMusicBot cannot be run on this Discord bot: " + unsupportedReason);
|
"JMusicBot cannot be run on this Discord bot: " + unsupportedReason);
|
||||||
try{ Thread.sleep(5000);}catch(InterruptedException ignored){} // this is awful but until we have a better way...
|
try {
|
||||||
|
Thread.sleep(5000);
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
} // this is awful but until we have a better way...
|
||||||
jda.shutdown();
|
jda.shutdown();
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
@@ -140,41 +142,29 @@ public class JMusicBot
|
|||||||
// other check that will just be a warning now but may be required in the future
|
// other check that will just be a warning now but may be required in the future
|
||||||
// check if the user has changed the prefix and provide info about the
|
// check if the user has changed the prefix and provide info about the
|
||||||
// message content intent
|
// message content intent
|
||||||
if(!"@mention".equals(config.getPrefix()))
|
if (!"@mention".equals(config.getPrefix())) {
|
||||||
{
|
|
||||||
LOG.info("JMusicBot", "You currently have a custom prefix set. "
|
LOG.info("JMusicBot", "You currently have a custom prefix set. "
|
||||||
+ "If your prefix is not working, make sure that the 'MESSAGE CONTENT INTENT' is Enabled "
|
+ "If your prefix is not working, make sure that the 'MESSAGE CONTENT INTENT' is Enabled "
|
||||||
+ "on https://discord.com/developers/applications/" + jda.getSelfUser().getId() + "/bot");
|
+ "on https://discord.com/developers/applications/" + jda.getSelfUser().getId() + "/bot");
|
||||||
}
|
}
|
||||||
}
|
} catch (IllegalArgumentException ex) {
|
||||||
catch (LoginException ex)
|
|
||||||
{
|
|
||||||
prompt.alert(Prompt.Level.ERROR, "JMusicBot", ex + "\nPlease make sure you are "
|
|
||||||
+ "editing the correct config.txt file, and that you have used the "
|
|
||||||
+ "correct token (not the 'secret'!)\nConfig Location: " + config.getConfigLocation());
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
catch(IllegalArgumentException ex)
|
|
||||||
{
|
|
||||||
prompt.alert(Prompt.Level.ERROR, "JMusicBot", "Some aspect of the configuration is "
|
prompt.alert(Prompt.Level.ERROR, "JMusicBot", "Some aspect of the configuration is "
|
||||||
+ "invalid: " + ex + "\nConfig Location: " + config.getConfigLocation());
|
+ "invalid: " + ex + "\nConfig Location: " + config.getConfigLocation());
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
} catch (ErrorResponseException ex) {
|
||||||
catch(ErrorResponseException ex)
|
|
||||||
{
|
|
||||||
prompt.alert(Prompt.Level.ERROR, "JMusicBot", ex + "\nInvalid reponse returned when "
|
prompt.alert(Prompt.Level.ERROR, "JMusicBot", ex + "\nInvalid reponse returned when "
|
||||||
+ "attempting to connect, please make sure you're connected to the internet");
|
+ "attempting to connect, please make sure you're connected to the internet");
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CommandClient createCommandClient(BotConfig config, SettingsManager settings, Bot bot)
|
private static CommandClient createCommandClient(BotConfig config, SettingsManager settings, Bot bot) {
|
||||||
{
|
|
||||||
// instantiate about command
|
// instantiate about command
|
||||||
AboutCommand aboutCommand = new AboutCommand(Color.BLUE.brighter(),
|
AboutCommand aboutCommand = new AboutCommand(Color.BLUE.brighter(),
|
||||||
"a music bot that is [easy to host yourself!](https://github.com/jagrosh/MusicBot) (v" + OtherUtil.getCurrentVersion() + ")",
|
"a music bot that is [easy to host yourself!](https://github.com/jagrosh/MusicBot) (v"
|
||||||
new String[]{"High-quality music playback", "FairQueue™ Technology", "Easy to host yourself"},
|
+ OtherUtil.getCurrentVersion() + ")",
|
||||||
RECOMMENDED_PERMS);
|
new String[] { "High-quality music playback", "FairQueue™ Technology", "Easy to host yourself" },
|
||||||
|
RECOMMENDED_PERMS);
|
||||||
aboutCommand.setIsAuthor(false);
|
aboutCommand.setIsAuthor(false);
|
||||||
aboutCommand.setReplacementCharacter("\uD83C\uDFB6"); // 🎶
|
aboutCommand.setReplacementCharacter("\uD83C\uDFB6"); // 🎶
|
||||||
|
|
||||||
@@ -227,21 +217,20 @@ public class JMusicBot
|
|||||||
new SetgameCmd(bot),
|
new SetgameCmd(bot),
|
||||||
new SetnameCmd(bot),
|
new SetnameCmd(bot),
|
||||||
new SetstatusCmd(bot),
|
new SetstatusCmd(bot),
|
||||||
new ShutdownCmd(bot)
|
new ShutdownCmd(bot));
|
||||||
);
|
|
||||||
|
|
||||||
// enable eval if applicable
|
// enable eval if applicable
|
||||||
if(config.useEval())
|
if (config.useEval())
|
||||||
cb.addCommand(new EvalCmd(bot));
|
cb.addCommand(new EvalCmd(bot));
|
||||||
|
|
||||||
// set status if set in config
|
// set status if set in config
|
||||||
if(config.getStatus() != OnlineStatus.UNKNOWN)
|
if (config.getStatus() != OnlineStatus.UNKNOWN)
|
||||||
cb.setStatus(config.getStatus());
|
cb.setStatus(config.getStatus());
|
||||||
|
|
||||||
// set game
|
// set game
|
||||||
if(config.getGame() == null)
|
if (config.getGame() == null)
|
||||||
cb.useDefaultGame();
|
cb.useDefaultGame();
|
||||||
else if(config.isGameNone())
|
else if (config.isGameNone())
|
||||||
cb.setActivity(null);
|
cb.setActivity(null);
|
||||||
else
|
else
|
||||||
cb.setActivity(config.getGame());
|
cb.setActivity(config.getGame());
|
||||||
|
|||||||
@@ -20,12 +20,12 @@ import java.util.concurrent.TimeUnit;
|
|||||||
import net.dv8tion.jda.api.JDA;
|
import net.dv8tion.jda.api.JDA;
|
||||||
import net.dv8tion.jda.api.entities.Guild;
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
import net.dv8tion.jda.api.entities.User;
|
import net.dv8tion.jda.api.entities.User;
|
||||||
import net.dv8tion.jda.api.entities.VoiceChannel;
|
import net.dv8tion.jda.api.entities.channel.concrete.VoiceChannel;
|
||||||
import net.dv8tion.jda.api.events.ReadyEvent;
|
|
||||||
import net.dv8tion.jda.api.events.ShutdownEvent;
|
|
||||||
import net.dv8tion.jda.api.events.guild.GuildJoinEvent;
|
import net.dv8tion.jda.api.events.guild.GuildJoinEvent;
|
||||||
import net.dv8tion.jda.api.events.guild.voice.GuildVoiceUpdateEvent;
|
import net.dv8tion.jda.api.events.guild.voice.GuildVoiceUpdateEvent;
|
||||||
import net.dv8tion.jda.api.events.message.guild.GuildMessageDeleteEvent;
|
import net.dv8tion.jda.api.events.message.MessageDeleteEvent;
|
||||||
|
import net.dv8tion.jda.api.events.session.ReadyEvent;
|
||||||
|
import net.dv8tion.jda.api.events.session.ShutdownEvent;
|
||||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -85,10 +85,11 @@ public class Listener extends ListenerAdapter
|
|||||||
catch(Exception ignored) {} // ignored
|
catch(Exception ignored) {} // ignored
|
||||||
}, 0, 24, TimeUnit.HOURS);
|
}, 0, 24, TimeUnit.HOURS);
|
||||||
}
|
}
|
||||||
|
bot.resetGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onGuildMessageDelete(GuildMessageDeleteEvent event)
|
public void onMessageDelete(MessageDeleteEvent event)
|
||||||
{
|
{
|
||||||
bot.getNowplayingHandler().onMessageDelete(event.getGuild(), event.getMessageIdLong());
|
bot.getNowplayingHandler().onMessageDelete(event.getGuild(), event.getMessageIdLong());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import com.jagrosh.jmusicbot.queue.AbstractQueue;
|
|||||||
import com.jagrosh.jmusicbot.settings.QueueType;
|
import com.jagrosh.jmusicbot.settings.QueueType;
|
||||||
import com.jagrosh.jmusicbot.utils.TimeUtil;
|
import com.jagrosh.jmusicbot.utils.TimeUtil;
|
||||||
import com.jagrosh.jmusicbot.settings.RepeatMode;
|
import com.jagrosh.jmusicbot.settings.RepeatMode;
|
||||||
import com.jagrosh.jmusicbot.utils.OtherUtil;
|
|
||||||
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
|
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
|
||||||
import com.sedmelluq.discord.lavaplayer.player.event.AudioEventAdapter;
|
import com.sedmelluq.discord.lavaplayer.player.event.AudioEventAdapter;
|
||||||
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
|
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
|
||||||
@@ -37,11 +36,11 @@ import com.sedmelluq.discord.lavaplayer.source.youtube.YoutubeAudioTrack;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import net.dv8tion.jda.api.EmbedBuilder;
|
import net.dv8tion.jda.api.EmbedBuilder;
|
||||||
import net.dv8tion.jda.api.JDA;
|
import net.dv8tion.jda.api.JDA;
|
||||||
import net.dv8tion.jda.api.MessageBuilder;
|
|
||||||
import net.dv8tion.jda.api.audio.AudioSendHandler;
|
import net.dv8tion.jda.api.audio.AudioSendHandler;
|
||||||
import net.dv8tion.jda.api.entities.Guild;
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
import net.dv8tion.jda.api.entities.Message;
|
|
||||||
import net.dv8tion.jda.api.entities.User;
|
import net.dv8tion.jda.api.entities.User;
|
||||||
|
import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder;
|
||||||
|
import net.dv8tion.jda.api.utils.messages.MessageCreateData;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -119,7 +118,7 @@ public class AudioHandler extends AudioEventAdapter implements AudioSendHandler
|
|||||||
|
|
||||||
public boolean isMusicPlaying(JDA jda)
|
public boolean isMusicPlaying(JDA jda)
|
||||||
{
|
{
|
||||||
return guild(jda).getSelfMember().getVoiceState().inVoiceChannel() && audioPlayer.getPlayingTrack()!=null;
|
return guild(jda).getSelfMember().getVoiceState().inAudioChannel() && audioPlayer.getPlayingTrack()!=null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getVotes()
|
public Set<String> getVotes()
|
||||||
@@ -216,14 +215,14 @@ public class AudioHandler extends AudioEventAdapter implements AudioSendHandler
|
|||||||
|
|
||||||
|
|
||||||
// Formatting
|
// Formatting
|
||||||
public Message getNowPlaying(JDA jda)
|
public MessageCreateData getNowPlaying(JDA jda)
|
||||||
{
|
{
|
||||||
if(isMusicPlaying(jda))
|
if(isMusicPlaying(jda))
|
||||||
{
|
{
|
||||||
Guild guild = guild(jda);
|
Guild guild = guild(jda);
|
||||||
AudioTrack track = audioPlayer.getPlayingTrack();
|
AudioTrack track = audioPlayer.getPlayingTrack();
|
||||||
MessageBuilder mb = new MessageBuilder();
|
MessageCreateBuilder mb = new MessageCreateBuilder();
|
||||||
mb.append(FormatUtil.filter(manager.getBot().getConfig().getSuccess()+" **Now Playing in "+guild.getSelfMember().getVoiceState().getChannel().getAsMention()+"...**"));
|
mb.setContent(FormatUtil.filter(manager.getBot().getConfig().getSuccess()+" **Now Playing in "+guild.getSelfMember().getVoiceState().getChannel().getAsMention()+"...**"));
|
||||||
EmbedBuilder eb = new EmbedBuilder();
|
EmbedBuilder eb = new EmbedBuilder();
|
||||||
eb.setColor(guild.getSelfMember().getColor());
|
eb.setColor(guild.getSelfMember().getColor());
|
||||||
RequestMetadata rm = getRequestMetadata();
|
RequestMetadata rm = getRequestMetadata();
|
||||||
@@ -264,10 +263,10 @@ public class AudioHandler extends AudioEventAdapter implements AudioSendHandler
|
|||||||
else return null;
|
else return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Message getNoMusicPlaying(JDA jda)
|
public MessageCreateData getNoMusicPlaying(JDA jda)
|
||||||
{
|
{
|
||||||
Guild guild = guild(jda);
|
Guild guild = guild(jda);
|
||||||
return new MessageBuilder()
|
return new MessageCreateBuilder()
|
||||||
.setContent(FormatUtil.filter(manager.getBot().getConfig().getSuccess()+" **Now Playing...**"))
|
.setContent(FormatUtil.filter(manager.getBot().getConfig().getSuccess()+" **Now Playing...**"))
|
||||||
.setEmbeds(new EmbedBuilder()
|
.setEmbeds(new EmbedBuilder()
|
||||||
.setTitle("No music playing")
|
.setTitle("No music playing")
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ import net.dv8tion.jda.api.Permission;
|
|||||||
import net.dv8tion.jda.api.entities.Activity;
|
import net.dv8tion.jda.api.entities.Activity;
|
||||||
import net.dv8tion.jda.api.entities.Guild;
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
import net.dv8tion.jda.api.entities.Message;
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
import net.dv8tion.jda.api.entities.TextChannel;
|
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||||
import net.dv8tion.jda.api.exceptions.PermissionException;
|
import net.dv8tion.jda.api.utils.messages.MessageCreateData;
|
||||||
import net.dv8tion.jda.api.exceptions.RateLimitedException;
|
import net.dv8tion.jda.api.utils.messages.MessageEditData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -54,7 +54,7 @@ public class NowplayingHandler
|
|||||||
|
|
||||||
public void setLastNPMessage(Message m)
|
public void setLastNPMessage(Message m)
|
||||||
{
|
{
|
||||||
lastNP.put(m.getGuild().getIdLong(), new Pair<>(m.getTextChannel().getIdLong(), m.getIdLong()));
|
lastNP.put(m.getGuild().getIdLong(), new Pair<>(m.getChannelIdLong(), m.getIdLong()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearLastNPMessage(Guild guild)
|
public void clearLastNPMessage(Guild guild)
|
||||||
@@ -81,7 +81,7 @@ public class NowplayingHandler
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
AudioHandler handler = (AudioHandler)guild.getAudioManager().getSendingHandler();
|
AudioHandler handler = (AudioHandler)guild.getAudioManager().getSendingHandler();
|
||||||
Message msg = handler.getNowPlaying(bot.getJDA());
|
MessageCreateData msg = handler.getNowPlaying(bot.getJDA());
|
||||||
if(msg==null)
|
if(msg==null)
|
||||||
{
|
{
|
||||||
msg = handler.getNoMusicPlaying(bot.getJDA());
|
msg = handler.getNoMusicPlaying(bot.getJDA());
|
||||||
@@ -89,7 +89,7 @@ public class NowplayingHandler
|
|||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
tc.editMessageById(pair.getValue(), msg).queue(m->{}, t -> lastNP.remove(guildId));
|
tc.editMessageById(pair.getValue(), MessageEditData.fromCreateData(msg)).queue(m->{}, t -> lastNP.remove(guildId));
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
@@ -105,7 +105,7 @@ public class NowplayingHandler
|
|||||||
// update bot status if applicable
|
// update bot status if applicable
|
||||||
if(bot.getConfig().getSongInStatus())
|
if(bot.getConfig().getSongInStatus())
|
||||||
{
|
{
|
||||||
if(track!=null && bot.getJDA().getGuilds().stream().filter(g -> g.getSelfMember().getVoiceState().inVoiceChannel()).count()<=1)
|
if(track!=null && bot.getJDA().getGuilds().stream().filter(g -> g.getSelfMember().getVoiceState().inAudioChannel()).count()<=1)
|
||||||
bot.getJDA().getPresence().setActivity(Activity.listening(track.getInfo().title));
|
bot.getJDA().getPresence().setActivity(Activity.listening(track.getInfo().title));
|
||||||
else
|
else
|
||||||
bot.resetGame();
|
bot.resetGame();
|
||||||
|
|||||||
@@ -49,7 +49,9 @@ public class PlayerManager extends DefaultAudioPlayerManager
|
|||||||
{
|
{
|
||||||
TransformativeAudioSourceManager.createTransforms(bot.getConfig().getTransforms()).forEach(t -> registerSourceManager(t));
|
TransformativeAudioSourceManager.createTransforms(bot.getConfig().getTransforms()).forEach(t -> registerSourceManager(t));
|
||||||
|
|
||||||
registerSourceManager(new YoutubeAudioSourceManager(true));
|
YoutubeAudioSourceManager yt = new YoutubeAudioSourceManager(true);
|
||||||
|
yt.setPlaylistPageCount(bot.getConfig().getMaxYTPlaylistPages());
|
||||||
|
registerSourceManager(yt);
|
||||||
|
|
||||||
registerSourceManager(SoundCloudAudioSourceManager.createDefault());
|
registerSourceManager(SoundCloudAudioSourceManager.createDefault());
|
||||||
registerSourceManager(new BandcampAudioSourceManager());
|
registerSourceManager(new BandcampAudioSourceManager());
|
||||||
@@ -63,8 +65,6 @@ public class PlayerManager extends DefaultAudioPlayerManager
|
|||||||
AudioSourceManagers.registerLocalSource(this);
|
AudioSourceManagers.registerLocalSource(this);
|
||||||
|
|
||||||
DuncteBotSources.registerAll(this, "en-US");
|
DuncteBotSources.registerAll(this, "en-US");
|
||||||
|
|
||||||
source(YoutubeAudioSourceManager.class).setPlaylistPageCount(10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bot getBot()
|
public Bot getBot()
|
||||||
|
|||||||
@@ -16,10 +16,10 @@
|
|||||||
package com.jagrosh.jmusicbot.audio;
|
package com.jagrosh.jmusicbot.audio;
|
||||||
|
|
||||||
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
|
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
|
||||||
import com.sedmelluq.discord.lavaplayer.source.youtube.YoutubeAudioSourceManager;
|
|
||||||
import com.sedmelluq.discord.lavaplayer.track.AudioItem;
|
import com.sedmelluq.discord.lavaplayer.track.AudioItem;
|
||||||
import com.sedmelluq.discord.lavaplayer.track.AudioReference;
|
import com.sedmelluq.discord.lavaplayer.track.AudioReference;
|
||||||
import com.typesafe.config.Config;
|
import com.typesafe.config.Config;
|
||||||
|
import dev.lavalink.youtube.YoutubeAudioSourceManager;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|||||||
@@ -21,8 +21,9 @@ import com.jagrosh.jmusicbot.Bot;
|
|||||||
import com.jagrosh.jmusicbot.settings.Settings;
|
import com.jagrosh.jmusicbot.settings.Settings;
|
||||||
import com.jagrosh.jmusicbot.audio.AudioHandler;
|
import com.jagrosh.jmusicbot.audio.AudioHandler;
|
||||||
import net.dv8tion.jda.api.entities.GuildVoiceState;
|
import net.dv8tion.jda.api.entities.GuildVoiceState;
|
||||||
import net.dv8tion.jda.api.entities.TextChannel;
|
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||||
import net.dv8tion.jda.api.entities.VoiceChannel;
|
import net.dv8tion.jda.api.entities.channel.concrete.VoiceChannel;
|
||||||
|
import net.dv8tion.jda.api.entities.channel.middleman.AudioChannel;
|
||||||
import net.dv8tion.jda.api.exceptions.PermissionException;
|
import net.dv8tion.jda.api.exceptions.PermissionException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,11 +65,11 @@ public abstract class MusicCommand extends Command
|
|||||||
}
|
}
|
||||||
if(beListening)
|
if(beListening)
|
||||||
{
|
{
|
||||||
VoiceChannel current = event.getGuild().getSelfMember().getVoiceState().getChannel();
|
AudioChannel current = event.getGuild().getSelfMember().getVoiceState().getChannel();
|
||||||
if(current==null)
|
if(current==null)
|
||||||
current = settings.getVoiceChannel(event.getGuild());
|
current = settings.getVoiceChannel(event.getGuild());
|
||||||
GuildVoiceState userState = event.getMember().getVoiceState();
|
GuildVoiceState userState = event.getMember().getVoiceState();
|
||||||
if(!userState.inVoiceChannel() || userState.isDeafened() || (current!=null && !userState.getChannel().equals(current)))
|
if(!userState.inAudioChannel() || userState.isDeafened() || (current!=null && !userState.getChannel().equals(current)))
|
||||||
{
|
{
|
||||||
event.replyError("You must be listening in "+(current==null ? "a voice channel" : current.getAsMention())+" to use that!");
|
event.replyError("You must be listening in "+(current==null ? "a voice channel" : current.getAsMention())+" to use that!");
|
||||||
return;
|
return;
|
||||||
@@ -81,7 +82,7 @@ public abstract class MusicCommand extends Command
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!event.getGuild().getSelfMember().getVoiceState().inVoiceChannel())
|
if(!event.getGuild().getSelfMember().getVoiceState().inAudioChannel())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import com.jagrosh.jmusicbot.Bot;
|
|||||||
import com.jagrosh.jmusicbot.commands.AdminCommand;
|
import com.jagrosh.jmusicbot.commands.AdminCommand;
|
||||||
import com.jagrosh.jmusicbot.settings.Settings;
|
import com.jagrosh.jmusicbot.settings.Settings;
|
||||||
import com.jagrosh.jmusicbot.utils.FormatUtil;
|
import com.jagrosh.jmusicbot.utils.FormatUtil;
|
||||||
import net.dv8tion.jda.api.entities.TextChannel;
|
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import com.jagrosh.jmusicbot.Bot;
|
|||||||
import com.jagrosh.jmusicbot.commands.AdminCommand;
|
import com.jagrosh.jmusicbot.commands.AdminCommand;
|
||||||
import com.jagrosh.jmusicbot.settings.Settings;
|
import com.jagrosh.jmusicbot.settings.Settings;
|
||||||
import com.jagrosh.jmusicbot.utils.FormatUtil;
|
import com.jagrosh.jmusicbot.utils.FormatUtil;
|
||||||
import net.dv8tion.jda.api.entities.VoiceChannel;
|
import net.dv8tion.jda.api.entities.channel.concrete.VoiceChannel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -23,10 +23,10 @@ import com.jagrosh.jmusicbot.settings.RepeatMode;
|
|||||||
import com.jagrosh.jmusicbot.settings.Settings;
|
import com.jagrosh.jmusicbot.settings.Settings;
|
||||||
import com.jagrosh.jmusicbot.utils.FormatUtil;
|
import com.jagrosh.jmusicbot.utils.FormatUtil;
|
||||||
import net.dv8tion.jda.api.EmbedBuilder;
|
import net.dv8tion.jda.api.EmbedBuilder;
|
||||||
import net.dv8tion.jda.api.MessageBuilder;
|
|
||||||
import net.dv8tion.jda.api.entities.Role;
|
import net.dv8tion.jda.api.entities.Role;
|
||||||
import net.dv8tion.jda.api.entities.TextChannel;
|
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||||
import net.dv8tion.jda.api.entities.VoiceChannel;
|
import net.dv8tion.jda.api.entities.channel.concrete.VoiceChannel;
|
||||||
|
import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -48,10 +48,10 @@ public class SettingsCmd extends Command
|
|||||||
protected void execute(CommandEvent event)
|
protected void execute(CommandEvent event)
|
||||||
{
|
{
|
||||||
Settings s = event.getClient().getSettingsFor(event.getGuild());
|
Settings s = event.getClient().getSettingsFor(event.getGuild());
|
||||||
MessageBuilder builder = new MessageBuilder()
|
MessageCreateBuilder builder = new MessageCreateBuilder()
|
||||||
.append(EMOJI + " **")
|
.addContent(EMOJI + " **")
|
||||||
.append(FormatUtil.filter(event.getSelfUser().getName()))
|
.addContent(FormatUtil.filter(event.getSelfUser().getName()))
|
||||||
.append("** settings:");
|
.addContent("** settings:");
|
||||||
TextChannel tchan = s.getTextChannel(event.getGuild());
|
TextChannel tchan = s.getTextChannel(event.getGuild());
|
||||||
VoiceChannel vchan = s.getVoiceChannel(event.getGuild());
|
VoiceChannel vchan = s.getVoiceChannel(event.getGuild());
|
||||||
Role role = s.getRole(event.getGuild());
|
Role role = s.getRole(event.getGuild());
|
||||||
@@ -70,7 +70,7 @@ public class SettingsCmd extends Command
|
|||||||
+ "\nDefault Playlist: " + (s.getDefaultPlaylist() == null ? "None" : "**" + s.getDefaultPlaylist() + "**")
|
+ "\nDefault Playlist: " + (s.getDefaultPlaylist() == null ? "None" : "**" + s.getDefaultPlaylist() + "**")
|
||||||
)
|
)
|
||||||
.setFooter(event.getJDA().getGuilds().size() + " servers | "
|
.setFooter(event.getJDA().getGuilds().size() + " servers | "
|
||||||
+ event.getJDA().getGuilds().stream().filter(g -> g.getSelfMember().getVoiceState().inVoiceChannel()).count()
|
+ event.getJDA().getGuilds().stream().filter(g -> g.getSelfMember().getVoiceState().inAudioChannel()).count()
|
||||||
+ " audio connections", null);
|
+ " audio connections", null);
|
||||||
event.getChannel().sendMessage(builder.setEmbeds(ebuilder.build()).build()).queue();
|
event.getChannel().sendMessage(builder.setEmbeds(ebuilder.build()).build()).queue();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import com.jagrosh.jmusicbot.Bot;
|
|||||||
import com.jagrosh.jmusicbot.audio.AudioHandler;
|
import com.jagrosh.jmusicbot.audio.AudioHandler;
|
||||||
import com.jagrosh.jmusicbot.commands.MusicCommand;
|
import com.jagrosh.jmusicbot.commands.MusicCommand;
|
||||||
import net.dv8tion.jda.api.Permission;
|
import net.dv8tion.jda.api.Permission;
|
||||||
import net.dv8tion.jda.api.entities.Message;
|
import net.dv8tion.jda.api.utils.messages.MessageCreateData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -41,7 +41,7 @@ public class NowplayingCmd extends MusicCommand
|
|||||||
public void doCommand(CommandEvent event)
|
public void doCommand(CommandEvent event)
|
||||||
{
|
{
|
||||||
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
|
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
|
||||||
Message m = handler.getNowPlaying(event.getJDA());
|
MessageCreateData m = handler.getNowPlaying(event.getJDA());
|
||||||
if(m==null)
|
if(m==null)
|
||||||
{
|
{
|
||||||
event.reply(handler.getNoMusicPlaying(event.getJDA()));
|
event.reply(handler.getNoMusicPlaying(event.getJDA()));
|
||||||
|
|||||||
@@ -28,10 +28,10 @@ import com.jagrosh.jmusicbot.settings.RepeatMode;
|
|||||||
import com.jagrosh.jmusicbot.settings.Settings;
|
import com.jagrosh.jmusicbot.settings.Settings;
|
||||||
import com.jagrosh.jmusicbot.utils.FormatUtil;
|
import com.jagrosh.jmusicbot.utils.FormatUtil;
|
||||||
import com.jagrosh.jmusicbot.utils.TimeUtil;
|
import com.jagrosh.jmusicbot.utils.TimeUtil;
|
||||||
import net.dv8tion.jda.api.MessageBuilder;
|
|
||||||
import net.dv8tion.jda.api.Permission;
|
import net.dv8tion.jda.api.Permission;
|
||||||
import net.dv8tion.jda.api.entities.Message;
|
|
||||||
import net.dv8tion.jda.api.exceptions.PermissionException;
|
import net.dv8tion.jda.api.exceptions.PermissionException;
|
||||||
|
import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder;
|
||||||
|
import net.dv8tion.jda.api.utils.messages.MessageCreateData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -75,9 +75,9 @@ public class QueueCmd extends MusicCommand
|
|||||||
List<QueuedTrack> list = ah.getQueue().getList();
|
List<QueuedTrack> list = ah.getQueue().getList();
|
||||||
if(list.isEmpty())
|
if(list.isEmpty())
|
||||||
{
|
{
|
||||||
Message nowp = ah.getNowPlaying(event.getJDA());
|
MessageCreateData nowp = ah.getNowPlaying(event.getJDA());
|
||||||
Message nonowp = ah.getNoMusicPlaying(event.getJDA());
|
MessageCreateData nonowp = ah.getNoMusicPlaying(event.getJDA());
|
||||||
Message built = new MessageBuilder()
|
MessageCreateData built = new MessageCreateBuilder()
|
||||||
.setContent(event.getClient().getWarning() + " There is no music in the queue!")
|
.setContent(event.getClient().getWarning() + " There is no music in the queue!")
|
||||||
.setEmbeds((nowp==null ? nonowp : nowp).getEmbeds().get(0)).build();
|
.setEmbeds((nowp==null ? nonowp : nowp).getEmbeds().get(0)).build();
|
||||||
event.reply(built, m ->
|
event.reply(built, m ->
|
||||||
|
|||||||
@@ -18,10 +18,13 @@ package com.jagrosh.jmusicbot.commands.music;
|
|||||||
import com.jagrosh.jdautilities.command.CommandEvent;
|
import com.jagrosh.jdautilities.command.CommandEvent;
|
||||||
import com.jagrosh.jmusicbot.Bot;
|
import com.jagrosh.jmusicbot.Bot;
|
||||||
import com.jagrosh.jmusicbot.audio.AudioHandler;
|
import com.jagrosh.jmusicbot.audio.AudioHandler;
|
||||||
|
import com.jagrosh.jmusicbot.audio.RequestMetadata;
|
||||||
import com.jagrosh.jmusicbot.commands.DJCommand;
|
import com.jagrosh.jmusicbot.commands.DJCommand;
|
||||||
import com.jagrosh.jmusicbot.commands.MusicCommand;
|
import com.jagrosh.jmusicbot.commands.MusicCommand;
|
||||||
import com.jagrosh.jmusicbot.utils.TimeUtil;
|
import com.jagrosh.jmusicbot.utils.TimeUtil;
|
||||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,6 +32,8 @@ import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
|||||||
*/
|
*/
|
||||||
public class SeekCmd extends MusicCommand
|
public class SeekCmd extends MusicCommand
|
||||||
{
|
{
|
||||||
|
private final static Logger LOG = LoggerFactory.getLogger("Seeking");
|
||||||
|
|
||||||
public SeekCmd(Bot bot)
|
public SeekCmd(Bot bot)
|
||||||
{
|
{
|
||||||
super(bot);
|
super(bot);
|
||||||
@@ -52,7 +57,7 @@ public class SeekCmd extends MusicCommand
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!DJCommand.checkDJPermission(event) && playingTrack.getUserData(Long.class) != event.getAuthor().getIdLong())
|
if (!DJCommand.checkDJPermission(event) && playingTrack.getUserData(RequestMetadata.class).getOwner() != event.getAuthor().getIdLong())
|
||||||
{
|
{
|
||||||
event.replyError("You cannot seek **" + playingTrack.getInfo().title + "** because you didn't add it!");
|
event.replyError("You cannot seek **" + playingTrack.getInfo().title + "** because you didn't add it!");
|
||||||
return;
|
return;
|
||||||
@@ -73,19 +78,18 @@ public class SeekCmd extends MusicCommand
|
|||||||
if (seekMilliseconds > trackDuration)
|
if (seekMilliseconds > trackDuration)
|
||||||
{
|
{
|
||||||
event.replyError("Cannot seek to `" + TimeUtil.formatTime(seekMilliseconds) + "` because the current track is `" + TimeUtil.formatTime(trackDuration) + "` long!");
|
event.replyError("Cannot seek to `" + TimeUtil.formatTime(seekMilliseconds) + "` because the current track is `" + TimeUtil.formatTime(trackDuration) + "` long!");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
try
|
playingTrack.setPosition(seekMilliseconds);
|
||||||
{
|
}
|
||||||
playingTrack.setPosition(seekMilliseconds);
|
catch (Exception e)
|
||||||
}
|
{
|
||||||
catch (Exception e)
|
event.replyError("An error occurred while trying to seek: " + e.getMessage());
|
||||||
{
|
LOG.warn("Failed to seek track " + playingTrack.getIdentifier(), e);
|
||||||
event.replyError("An error occurred while trying to seek!");
|
return;
|
||||||
e.printStackTrace();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
event.replySuccess("Successfully seeked to `" + TimeUtil.formatTime(playingTrack.getPosition()) + "/" + TimeUtil.formatTime(playingTrack.getDuration()) + "`!");
|
event.replySuccess("Successfully seeked to `" + TimeUtil.formatTime(playingTrack.getPosition()) + "/" + TimeUtil.formatTime(playingTrack.getDuration()) + "`!");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ import com.jagrosh.jmusicbot.utils.OtherUtil;
|
|||||||
import com.sedmelluq.discord.lavaplayer.tools.PlayerLibrary;
|
import com.sedmelluq.discord.lavaplayer.tools.PlayerLibrary;
|
||||||
import net.dv8tion.jda.api.JDAInfo;
|
import net.dv8tion.jda.api.JDAInfo;
|
||||||
import net.dv8tion.jda.api.Permission;
|
import net.dv8tion.jda.api.Permission;
|
||||||
import net.dv8tion.jda.api.entities.ChannelType;
|
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
||||||
|
import net.dv8tion.jda.api.utils.FileUpload;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -80,8 +81,8 @@ public class DebugCmd extends OwnerCommand
|
|||||||
|
|
||||||
if(event.isFromType(ChannelType.PRIVATE)
|
if(event.isFromType(ChannelType.PRIVATE)
|
||||||
|| event.getSelfMember().hasPermission(event.getTextChannel(), Permission.MESSAGE_ATTACH_FILES))
|
|| event.getSelfMember().hasPermission(event.getTextChannel(), Permission.MESSAGE_ATTACH_FILES))
|
||||||
event.getChannel().sendFile(sb.toString().getBytes(), "debug_information.txt").queue();
|
event.getChannel().sendFiles(FileUpload.fromData(sb.toString().getBytes(), "debug_information.txt")).queue();
|
||||||
else
|
else
|
||||||
event.reply("Debug Information: " + sb.toString());
|
event.reply("Debug Information: " + sb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import javax.script.ScriptEngineManager;
|
|||||||
import com.jagrosh.jdautilities.command.CommandEvent;
|
import com.jagrosh.jdautilities.command.CommandEvent;
|
||||||
import com.jagrosh.jmusicbot.Bot;
|
import com.jagrosh.jmusicbot.Bot;
|
||||||
import com.jagrosh.jmusicbot.commands.OwnerCommand;
|
import com.jagrosh.jmusicbot.commands.OwnerCommand;
|
||||||
import net.dv8tion.jda.api.entities.ChannelType;
|
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import net.dv8tion.jda.api.entities.Guild;
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
import net.dv8tion.jda.api.entities.Role;
|
import net.dv8tion.jda.api.entities.Role;
|
||||||
import net.dv8tion.jda.api.entities.TextChannel;
|
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||||
import net.dv8tion.jda.api.entities.VoiceChannel;
|
import net.dv8tion.jda.api.entities.channel.concrete.VoiceChannel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import java.util.HashMap;
|
|||||||
import net.dv8tion.jda.api.entities.Guild;
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,6 +33,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
*/
|
*/
|
||||||
public class SettingsManager implements GuildSettingsManager<Settings>
|
public class SettingsManager implements GuildSettingsManager<Settings>
|
||||||
{
|
{
|
||||||
|
private final static Logger LOG = LoggerFactory.getLogger("Settings");
|
||||||
private final static String SETTINGS_FILE = "serversettings.json";
|
private final static String SETTINGS_FILE = "serversettings.json";
|
||||||
private final HashMap<Long,Settings> settings;
|
private final HashMap<Long,Settings> settings;
|
||||||
|
|
||||||
@@ -63,17 +65,17 @@ public class SettingsManager implements GuildSettingsManager<Settings>
|
|||||||
} catch (NoSuchFileException e) {
|
} catch (NoSuchFileException e) {
|
||||||
// create an empty json file
|
// create an empty json file
|
||||||
try {
|
try {
|
||||||
LoggerFactory.getLogger("Settings").info("serversettings.json will be created in " + OtherUtil.getPath("serversettings.json").toAbsolutePath());
|
LOG.info("serversettings.json will be created in " + OtherUtil.getPath("serversettings.json").toAbsolutePath());
|
||||||
Files.write(OtherUtil.getPath("serversettings.json"), new JSONObject().toString(4).getBytes());
|
Files.write(OtherUtil.getPath("serversettings.json"), new JSONObject().toString(4).getBytes());
|
||||||
} catch(IOException ex) {
|
} catch(IOException ex) {
|
||||||
LoggerFactory.getLogger("Settings").warn("Failed to create new settings file: "+ex);
|
LOG.warn("Failed to create new settings file: "+ex);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} catch(IOException | JSONException e) {
|
} catch(IOException | JSONException e) {
|
||||||
LoggerFactory.getLogger("Settings").warn("Failed to load server settings: "+e);
|
LOG.warn("Failed to load server settings: "+e);
|
||||||
}
|
}
|
||||||
|
|
||||||
LoggerFactory.getLogger("Settings").info("serversettings.json loaded from " + OtherUtil.getPath("serversettings.json").toAbsolutePath());
|
LOG.info("serversettings.json loaded from " + OtherUtil.getPath("serversettings.json").toAbsolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -127,7 +129,7 @@ public class SettingsManager implements GuildSettingsManager<Settings>
|
|||||||
try {
|
try {
|
||||||
Files.write(OtherUtil.getPath(SETTINGS_FILE), obj.toString(4).getBytes());
|
Files.write(OtherUtil.getPath(SETTINGS_FILE), obj.toString(4).getBytes());
|
||||||
} catch(IOException ex){
|
} catch(IOException ex){
|
||||||
LoggerFactory.getLogger("Settings").warn("Failed to write to file: "+ex);
|
LOG.warn("Failed to write to file: "+ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ package com.jagrosh.jmusicbot.utils;
|
|||||||
import com.jagrosh.jmusicbot.audio.RequestMetadata.UserInfo;
|
import com.jagrosh.jmusicbot.audio.RequestMetadata.UserInfo;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import net.dv8tion.jda.api.entities.Role;
|
import net.dv8tion.jda.api.entities.Role;
|
||||||
import net.dv8tion.jda.api.entities.TextChannel;
|
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||||
import net.dv8tion.jda.api.entities.User;
|
import net.dv8tion.jda.api.entities.User;
|
||||||
import net.dv8tion.jda.api.entities.VoiceChannel;
|
import net.dv8tion.jda.api.entities.channel.concrete.VoiceChannel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -94,7 +94,7 @@ public class FormatUtil {
|
|||||||
|
|
||||||
public static String listOfRoles(List<Role> list, String query)
|
public static String listOfRoles(List<Role> list, String query)
|
||||||
{
|
{
|
||||||
String out = " Multiple text channels found matching \""+query+"\":";
|
String out = " Multiple roles found matching \""+query+"\":";
|
||||||
for(int i=0; i<6 && i<list.size(); i++)
|
for(int i=0; i<6 && i<list.size(); i++)
|
||||||
out+="\n - "+list.get(i).getName()+" (ID:"+list.get(i).getId()+")";
|
out+="\n - "+list.get(i).getName()+" (ID:"+list.get(i).getId()+")";
|
||||||
if(list.size()>6)
|
if(list.size()>6)
|
||||||
|
|||||||
@@ -224,7 +224,9 @@ public class OtherUtil
|
|||||||
ApplicationInfo info = jda.retrieveApplicationInfo().complete();
|
ApplicationInfo info = jda.retrieveApplicationInfo().complete();
|
||||||
if (info.isBotPublic())
|
if (info.isBotPublic())
|
||||||
return "\"Public Bot\" is enabled. Using JMusicBot as a public bot is not supported. Please disable it in the "
|
return "\"Public Bot\" is enabled. Using JMusicBot as a public bot is not supported. Please disable it in the "
|
||||||
+ "Developer Dashboard at https://discord.com/developers/applications/" + jda.getSelfUser().getId() + "/bot.";
|
+ "Developer Dashboard at https://discord.com/developers/applications/" + jda.getSelfUser().getId() + "/bot ."
|
||||||
|
+ "You may also need to disable all Installation Contexts at https://discord.com/developers/applications/"
|
||||||
|
+ jda.getSelfUser().getId() + "/installation .";
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,6 +98,15 @@ stayinchannel = false
|
|||||||
|
|
||||||
maxtime = 0
|
maxtime = 0
|
||||||
|
|
||||||
|
// This sets the maximum number of pages of songs that can be loaded from a YouTube
|
||||||
|
// playlist. Each page can contain up to 100 tracks. Playing a playlist with more
|
||||||
|
// pages than the maximum will stop loading after the provided number of pages.
|
||||||
|
// For example, if the max was set to 15 and a playlist contained 1850 tracks,
|
||||||
|
// only the first 1500 tracks (15 pages) would be loaded. By default, this is
|
||||||
|
// set to 10 pages (1000 tracks).
|
||||||
|
|
||||||
|
maxytplaylistpages = 10
|
||||||
|
|
||||||
|
|
||||||
// This sets the ratio of users that must vote to skip the currently playing song.
|
// This sets the ratio of users that must vote to skip the currently playing song.
|
||||||
// Guild owners can define their own skip ratios, but this will be used if a guild
|
// Guild owners can define their own skip ratios, but this will be used if a guild
|
||||||
|
|||||||
Reference in New Issue
Block a user