Compare commits

..

8 Commits

26 changed files with 598 additions and 636 deletions

View File

@ -30,7 +30,7 @@ dependencies {
exclude group: "org.springframework.boot", module: "spring-boot-starter-logging"
}
implementation("org.springframework.boot:spring-boot-starter-log4j2")
implementation 'org.codehaus.groovy:groovy-all:3.0.10'
implementation 'org.codehaus.groovy:groovy-all:3.0.11'
implementation 'com.sedmelluq:lavaplayer:1.3.77'

View File

@ -8,10 +8,7 @@ import net.Broken.Tools.UserManager.Stats.UserStatsUtils;
import net.Broken.audio.AudioM;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.events.ReadyEvent;
import net.dv8tion.jda.api.events.guild.GuildJoinEvent;
import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent;
@ -19,6 +16,7 @@ import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleRemoveEvent;
import net.dv8tion.jda.api.events.guild.voice.GuildVoiceJoinEvent;
import net.dv8tion.jda.api.events.guild.voice.GuildVoiceLeaveEvent;
import net.dv8tion.jda.api.events.guild.voice.GuildVoiceMoveEvent;
import net.dv8tion.jda.api.events.interaction.ButtonClickEvent;
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
@ -121,6 +119,8 @@ public class BotListener extends ListenerAdapter {
logger.debug("I'm alone, close audio connection.");
AudioM.getInstance(event.getGuild()).stop();
}
} else if (event.getMember().getUser() == MainBot.jda.getSelfUser()) {
AudioM.getInstance(event.getGuild()).clearLastButton();
}
AutoVoiceChannel autoVoiceChannel = AutoVoiceChannel.getInstance(event.getGuild());
autoVoiceChannel.leave(event.getChannelLeft());
@ -141,12 +141,48 @@ public class BotListener extends ListenerAdapter {
}
}
@Override
public void onButtonClick(@NotNull ButtonClickEvent event) {
super.onButtonClick(event);
event.deferReply().queue();
AudioM audioM = AudioM.getInstance(event.getGuild());
switch (event.getComponentId()) {
case "pause" -> audioM.pause(event);
case "play" -> audioM.resume(event);
case "next" -> audioM.skipTrack(event);
case "stop" -> audioM.stop(event);
case "disconnect" -> audioM.disconect(event);
}
}
@Override
public void onSlashCommand(@NotNull SlashCommandEvent event) {
HashMap<String, SlashCommand> commands = MainBot.slashCommands;
super.onSlashCommand(event);
if (commands.containsKey(event.getName())) {
commands.get(event.getName()).action(event);
SlashCommand commandRunner = commands.get(event.getName());
// It's form private message
if (!event.isFromGuild()) {
if (commandRunner.isPrivateUsable()) {
commandRunner.action(event);
} else {
MessageEmbed message = EmbedMessageUtils.buildStandar(new EmbedBuilder()
.setTitle(":no_entry_sign: This command is not usable in private message")
.setColor(Color.red)
);
event.replyEmbeds(message).setEphemeral(true).queue();
}
} else {
if (!commandRunner.isNSFW() || event.getTextChannel().isNSFW()) {
commandRunner.action(event);
} else {
MessageEmbed message = EmbedMessageUtils.buildStandar(new EmbedBuilder()
.setTitle(":underage: This command is only usable in NSFW channels")
.setColor(Color.red)
);
event.replyEmbeds(message).setEphemeral(true).queue();
}
}
}
}
@ -186,4 +222,5 @@ public class BotListener extends ListenerAdapter {
return guildPref;
}
}

View File

@ -1,48 +0,0 @@
package net.Broken.Commands;
import net.Broken.Commande;
import net.Broken.Tools.DayListener.DayListener;
import net.dv8tion.jda.api.entities.ChannelType;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* Admin command to manually trigger daily action(s)
*/
public class DayTrigger implements Commande {
Logger logger = LogManager.getLogger();
@Override
public void action(String[] args, MessageReceivedEvent event) {
if (!event.isFromType(ChannelType.PRIVATE))
event.getMessage().delete().queue();
DayListener.getInstance().trigger();
}
@Override
public boolean isPrivateUsable() {
return true;
}
@Override
public boolean isAdminCmd() {
return true;
}
/**
* Determines if the command is usable only by bot level admin user
*
* @return boolean
*/
@Override
public boolean isBotAdminCmd() {
return true;
}
@Override
public boolean isNSFW() {
return false;
}
}

View File

@ -1,47 +0,0 @@
package net.Broken.Commands.Over18;
import net.Broken.Tools.Command.NoDev;
import net.Broken.Tools.Command.NumberedCommande;
import org.apache.logging.log4j.LogManager;
/**
* Ass command, return random picture from les400culs.com
*/
@NoDev()
public class Ass extends NumberedCommande {
public Ass() {
super(LogManager.getLogger(), "http://les400culs.com/", "-2/", "featured-img", "img");
}
@Override
public String toString() {
return "Ass";
}
@Override
public boolean isPrivateUsable() {
return false;
}
@Override
public boolean isAdminCmd() {
return false;
}
/**
* Determines if the command is usable only by bot level admin user
*
* @return boolean
*/
@Override
public boolean isBotAdminCmd() {
return false;
}
@Override
public boolean isNSFW() {
return true;
}
}

View File

@ -1,40 +0,0 @@
package net.Broken.Commands;
import net.Broken.Commande;
import net.Broken.Tools.UserManager.Stats.UserStatsUtils;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
public class Rank implements Commande {
@Override
public void action(String[] args, MessageReceivedEvent event) {
UserStatsUtils userStats = UserStatsUtils.getINSTANCE();
MessageEmbed msg = userStats.getRankMessage(event.getMember());
event.getTextChannel().sendMessage(msg).queue();
}
@Override
public boolean isPrivateUsable() {
return false;
}
@Override
public boolean isAdminCmd() {
return false;
}
/**
* Determines if the command is usable only by bot level admin user
*
* @return boolean
*/
@Override
public boolean isBotAdminCmd() {
return false;
}
@Override
public boolean isNSFW() {
return false;
}
}

View File

@ -65,4 +65,6 @@ public class ReportUsers implements Commande {
public boolean isNSFW() {
return false;
}
}

View File

@ -1,63 +0,0 @@
package net.Broken.Commands;
import net.Broken.Commande;
import net.Broken.DB.Repository.GuildPreferenceRepository;
import net.Broken.MainBot;
import net.Broken.SpringContext;
import net.Broken.Tools.EmbedMessageUtils;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.context.ApplicationContext;
import java.awt.*;
public class Settings implements Commande {
private Logger logger = LogManager.getLogger();
private GuildPreferenceRepository guildPreferenceRepository;
public Settings() {
ApplicationContext context = SpringContext.getAppContext();
guildPreferenceRepository = (GuildPreferenceRepository) context.getBean("guildPreferenceRepository");
}
@Override
public void action(String[] args, MessageReceivedEvent event) {
EmbedBuilder builder = new EmbedBuilder()
.setTitle("Settings")
.setDescription("You can do all the configuration on the web page in the \"Bot Settings\" menu.\nhttps://" + MainBot.url).setColor(Color.green);
event.getTextChannel().sendMessage(EmbedMessageUtils.buildStandar(builder)).queue();
}
@Override
public boolean isPrivateUsable() {
return false;
}
@Override
public boolean isAdminCmd() {
return true;
}
/**
* Determines if the command is usable only by bot level admin user
*
* @return boolean
*/
@Override
public boolean isBotAdminCmd() {
return false;
}
@Override
public boolean isNSFW() {
return false;
}
}

View File

@ -93,7 +93,6 @@ public class Init {
jda.addEventListener(new BotListener());
jda.getPresence().setPresence(OnlineStatus.ONLINE, Activity.playing(MainBot.url));
logger.info("-----------------------END INIT-----------------------");

View File

@ -38,5 +38,9 @@ public interface SlashCommand {
*/
boolean isNSFW();
boolean isPrivateUsable();
boolean isDisableByDefault();
}

View File

@ -81,4 +81,14 @@ public class Cat implements SlashCommand {
public boolean isNSFW() {
return false;
}
@Override
public boolean isPrivateUsable() {
return true;
}
@Override
public boolean isDisableByDefault() {
return false;
}
}

View File

@ -55,4 +55,14 @@ public class Clear implements SlashCommand {
public boolean isNSFW() {
return false;
}
@Override
public boolean isPrivateUsable() {
return false;
}
@Override
public boolean isDisableByDefault() {
return true;
}
}

View File

@ -1,41 +0,0 @@
package net.Broken.SlashCommands;
import net.Broken.SlashCommand;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
import java.util.List;
public class Invite implements SlashCommand {
@Override
public void action(SlashCommandEvent event) {
event.reply(event.getJDA().setRequiredScopes("bot", "applications.commands").getInviteUrl(Permission.ADMINISTRATOR)).setEphemeral(true).queue();
}
@Override
public String getDescription() {
return "Get the link to invite this bot to your server";
}
@Override
public List<OptionData> getOptions() {
return null;
}
@Override
public List<SubcommandData> getSubcommands() {
return null;
}
@Override
public boolean isBotAdminCmd() {
return false;
}
@Override
public boolean isNSFW() {
return false;
}
}

View File

@ -130,4 +130,14 @@ public class Music implements SlashCommand {
public boolean isNSFW() {
return false;
}
@Override
public boolean isPrivateUsable() {
return false;
}
@Override
public boolean isDisableByDefault() {
return false;
}
}

View File

@ -0,0 +1,46 @@
package net.Broken.SlashCommands.Over18;
import net.Broken.Tools.Command.Ignore;
import net.Broken.Tools.Command.NoDev;
import net.Broken.Tools.Command.NumberedSlashCommand;
import net.Broken.Tools.FindContentOnWebPage;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
@NoDev
@Ignore
public class Ass extends NumberedSlashCommand {
Logger logger = LogManager.getLogger();
public Ass() {
super(LogManager.getLogger(), "http://les400culs.com/", "-2/", "featured-img", "img");
}
@Override
public String getDescription() {
return "Return random image from les400culs.com";
}
@Override
public boolean isBotAdminCmd() {
return false;
}
@Override
public boolean isNSFW() {
return true;
}
@Override
public boolean isPrivateUsable() {
return true;
}
@Override
public boolean isDisableByDefault() {
return true;
}
}

View File

@ -1,39 +1,26 @@
package net.Broken.Commands.Over18;
package net.Broken.SlashCommands.Over18;
import net.Broken.Tools.Command.Ignore;
import net.Broken.Tools.Command.NoDev;
import net.Broken.Tools.Command.NumberedCommande;
import net.Broken.Tools.Command.NumberedSlashCommand;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* Boobs command, return random picture from lesaintdesseins.fr
*/
@NoDev()
public class Boobs extends NumberedCommande {
@NoDev
@Ignore
public class Boobs extends NumberedSlashCommand {
Logger logger = LogManager.getLogger();
public Boobs() {
super(LogManager.getLogger(), "http://lesaintdesseins.fr/", "-2/", "featured-img", "img");
}
@Override
public String toString() {
return "Boobs";
}
@Override
public boolean isPrivateUsable() {
return false;
public String getDescription() {
return "Return random image from les400culs.com";
}
@Override
public boolean isAdminCmd() {
return false;
}
/**
* Determines if the command is usable only by bot level admin user
*
* @return boolean
*/
@Override
public boolean isBotAdminCmd() {
return false;
@ -43,4 +30,14 @@ public class Boobs extends NumberedCommande {
public boolean isNSFW() {
return true;
}
@Override
public boolean isPrivateUsable() {
return true;
}
@Override
public boolean isDisableByDefault() {
return true;
}
}

View File

@ -1,55 +1,21 @@
package net.Broken.Commands.Over18;
package net.Broken.SlashCommands.Over18;
import net.Broken.Tools.Command.Ignore;
import net.Broken.Tools.Command.NoDev;
import net.Broken.Tools.Command.NumberedCommande;
import net.Broken.Tools.Command.NumberedSlashCommand;
import net.Broken.Tools.FindContentOnWebPage;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
/**
* Madame command that return random picture from dites.bonjourmadame.fr
*/
@NoDev
public class Madame extends NumberedCommande {
public String HELP = "Yo really? Just type Madame to see some :cat:";
public class Madame extends NumberedSlashCommand {
Logger logger = LogManager.getLogger();
MessageReceivedEvent event;
public Madame() {
super(LogManager.getLogger(), "https://www.bonjourmadame.fr/page/", "/");
}
@Override
public boolean isPrivateUsable() {
return false;
}
@Override
public boolean isAdminCmd() {
return false;
}
/**
* Determines if the command is usable only by bot level admin user
*
* @return boolean
*/
@Override
public boolean isBotAdminCmd() {
return false;
}
@Override
public boolean isNSFW() {
return true;
}
/**
* Detect if picture link go to Tepeee
*
@ -107,4 +73,29 @@ public class Madame extends NumberedCommande {
imgUrl = removeParams(imgUrl);
return imgUrl;
}
@Override
public String getDescription() {
return "Return random image from bonjourmadame.fr";
}
@Override
public boolean isBotAdminCmd() {
return false;
}
@Override
public boolean isNSFW() {
return true;
}
@Override
public boolean isPrivateUsable() {
return true;
}
@Override
public boolean isDisableByDefault() {
return true;
}
}

View File

@ -0,0 +1,59 @@
package net.Broken.SlashCommands;
import net.Broken.MainBot;
import net.Broken.SlashCommand;
import net.Broken.Tools.UserManager.Stats.UserStatsUtils;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
import net.dv8tion.jda.api.interactions.components.Button;
import java.util.List;
public class Rank implements SlashCommand {
@Override
public void action(SlashCommandEvent event) {
event.deferReply().queue();
UserStatsUtils userStats = UserStatsUtils.getINSTANCE();
MessageEmbed messageEmbed = userStats.getRankMessage(event.getMember());
event.getHook().sendMessageEmbeds(messageEmbed).addActionRow(
Button.link("https://" + MainBot.url + "/rank", "More stats")
).queue();
}
@Override
public String getDescription() {
return "Get the top 5 ranking of this server";
}
@Override
public List<OptionData> getOptions() {
return null;
}
@Override
public List<SubcommandData> getSubcommands() {
return null;
}
@Override
public boolean isBotAdminCmd() {
return false;
}
@Override
public boolean isNSFW() {
return false;
}
@Override
public boolean isPrivateUsable() {
return false;
}
@Override
public boolean isDisableByDefault() {
return false;
}
}

View File

@ -1,152 +0,0 @@
package net.Broken.Tools.Command;
import net.Broken.Commande;
import net.Broken.Tools.FindContentOnWebPage;
import net.Broken.Tools.LimitChecker;
import net.Broken.Tools.TrueRandom;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.concurrent.LinkedBlockingQueue;
/**
* Abstact class used for all command that need to find the max number of page on a web site.
*/
@Ignore
public abstract class NumberedCommande implements Commande {
protected int minNumber = 1;
protected int maxNumber = -1;
protected String baseURL;
protected String divClass;
protected String htmlType;
protected String urlSuffix;
protected LinkedBlockingQueue<Integer> randomQueue = new LinkedBlockingQueue<>();
private Logger logger = LogManager.getLogger();
/**
* Default constructor
*
* @param logger Logger used for logs
* @param baseURL WebSite base url
* @param divClass DivClass to search to extract image
* @param htmlType HTML tag to extract image (img)
*/
public NumberedCommande(Logger logger, String baseURL, String urlSuffix, String divClass, String htmlType) {
this.logger = logger;
this.baseURL = baseURL;
this.divClass = divClass;
this.htmlType = htmlType;
this.urlSuffix = urlSuffix;
try {
logger.debug("Checking max...");
maxNumber = LimitChecker.doYourJob(baseURL, 2, urlSuffix);
logger.info("Limit is " + maxNumber);
} catch (IOException e) {
logger.catching(e);
}
}
public NumberedCommande(Logger logger, String baseURL, String urlSuffix) {
this(logger, baseURL, urlSuffix, null, null);
}
@Override
public void action(String[] args, MessageReceivedEvent event) {
try {
if (args.length == 0) {
String result = poll();
event.getTextChannel().sendMessage(event.getAuthor().getAsMention() + "\n" + result).queue();
} else {
switch (args[0].toLowerCase()) {
case "update":
logger.info("update commande from " + event.getMessage().getAuthor().getName());
event.getTextChannel().sendMessage(event.getAuthor().getAsMention() + "\n:arrow_right: Updating...").queue();
int newNumber = maxNumber;
try {
newNumber = LimitChecker.doYourJob(baseURL, maxNumber, urlSuffix);
} catch (IOException e) {
e.printStackTrace();
}
if (newNumber == maxNumber) {
event.getTextChannel().sendMessage(event.getAuthor().getAsMention() + "\n:arrow_right: 0 new picture found :cry:").queue();
} else if (newNumber - maxNumber == 1)
event.getTextChannel().sendMessage(event.getAuthor().getAsMention() + "\n:arrow_right: " + (newNumber - maxNumber) + " picture has been found :kissing_heart:").queue();
else
event.getTextChannel().sendMessage(event.getAuthor().getAsMention() + "\n:arrow_right: " + (newNumber - maxNumber) + " pictures has been found :kissing_heart:").queue();
logger.info((newNumber - maxNumber) + " new image(s) found.");
maxNumber = newNumber;
break;
case "get":
if (args.length >= 2) {
int number = -1;
try {
number = Integer.parseInt(args[1]);
URL url = new URL(baseURL + number + "-2/");
HttpURLConnection huc = (HttpURLConnection) url.openConnection();
huc.setRequestMethod("GET");
huc.connect();
int result = huc.getResponseCode();
if (result == 200) {
event.getTextChannel().sendMessage(event.getAuthor().getAsMention() + "\n" + baseURL + number + urlSuffix).queue();
} else {
event.getTextChannel().sendMessage(event.getAuthor().getAsMention() + "\n:warning: **__Error__** :warning:\n:arrow_right: Page not found (404)").queue();
}
} catch (NumberFormatException e) {
event.getTextChannel().sendMessage(event.getAuthor().getAsMention() + "\n:warning: **__Error__** :warning:\n:arrow_right: Bad argument. `//help " + this.toString().toLowerCase() + "` for more info ").queue();
} catch (IOException e) {
logger.catching(e);
event.getTextChannel().sendMessage(event.getAuthor().getAsMention() + "\n:warning: **__Error__** :warning:\n:arrow_right: Internal error...").queue();
}
} else {
event.getTextChannel().sendMessage(event.getAuthor().getAsMention() + "\n:warning: **__Error__** :warning:\n:arrow_right: Bad argument. `//help " + this.toString().toLowerCase() + "` for more info ").queue();
logger.warn("Bad Argument: " + event.getMessage().getContentRaw() + " From " + event.getAuthor().getName());
}
break;
default:
event.getTextChannel().sendMessage(event.getAuthor().getAsMention() + "\n:warning: **__Error__** :warning:\n:arrow_right: Bad argument. `//help " + this.toString().toLowerCase() + "` for more info ").queue();
logger.warn("Bad Argument: " + event.getMessage().getContentRaw() + " From " + event.getAuthor().getName());
break;
}
}
} catch (IOException e) {
logger.catching(e);
}
}
private void completeRandom() throws IOException {
TrueRandom trueRandom = TrueRandom.getINSTANCE();
ArrayList<Integer> numbers = trueRandom.getNumbers(minNumber, maxNumber);
randomQueue.addAll(numbers);
}
protected void checkRandom() throws IOException {
logger.trace("Queue size: " + randomQueue.size());
if (randomQueue.isEmpty()) {
logger.debug("Queue empty, update it.");
completeRandom();
}
}
public String poll() throws IOException {
checkRandom();
int randomResult = randomQueue.poll();
return FindContentOnWebPage.doYourJob(baseURL + randomResult + urlSuffix, divClass, htmlType);
}
}

View File

@ -0,0 +1,112 @@
package net.Broken.Tools.Command;
import net.Broken.Commande;
import net.Broken.SlashCommand;
import net.Broken.Tools.EmbedMessageUtils;
import net.Broken.Tools.FindContentOnWebPage;
import net.Broken.Tools.LimitChecker;
import net.Broken.Tools.TrueRandom;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
/**
* Abstact class used for all command that need to find the max number of page on a web site.
*/
@Ignore
public abstract class NumberedSlashCommand implements SlashCommand {
protected int minNumber = 1;
protected int maxNumber = -1;
protected String baseURL;
protected String divClass;
protected String htmlType;
protected String urlSuffix;
protected LinkedBlockingQueue<Integer> randomQueue = new LinkedBlockingQueue<>();
private Logger logger = LogManager.getLogger();
/**
* Default constructor
*
* @param logger Logger used for logs
* @param baseURL WebSite base url
* @param divClass DivClass to search to extract image
* @param htmlType HTML tag to extract image (img)
*/
public NumberedSlashCommand(Logger logger, String baseURL, String urlSuffix, String divClass, String htmlType) {
this.logger = logger;
this.baseURL = baseURL;
this.divClass = divClass;
this.htmlType = htmlType;
this.urlSuffix = urlSuffix;
try {
logger.debug("Checking max...");
maxNumber = LimitChecker.doYourJob(baseURL, 2, urlSuffix);
logger.info("Limit is " + maxNumber);
} catch (IOException e) {
logger.catching(e);
}
}
public NumberedSlashCommand(Logger logger, String baseURL, String urlSuffix) {
this(logger, baseURL, urlSuffix, null, null);
}
@Override
public void action(SlashCommandEvent event) {
event.deferReply().queue();
try {
String result = poll();
event.getHook().sendMessage(event.getMember().getAsMention() + "\n" + result).queue();
} catch (IOException e) {
logger.catching(e);
MessageEmbed message = EmbedMessageUtils.getInternalError();
event.getHook().setEphemeral(true).sendMessageEmbeds(message).queue();
}
}
private void fillRandomQueue() throws IOException {
TrueRandom trueRandom = TrueRandom.getINSTANCE();
ArrayList<Integer> numbers = trueRandom.getNumbers(minNumber, maxNumber);
randomQueue.addAll(numbers);
}
protected void checkRandom() throws IOException {
logger.trace("Queue size: " + randomQueue.size());
if (randomQueue.isEmpty()) {
logger.debug("Queue empty, update it.");
fillRandomQueue();
}
}
public String poll() throws IOException {
checkRandom();
int randomResult = randomQueue.poll();
return FindContentOnWebPage.doYourJob(baseURL + randomResult + urlSuffix, divClass, htmlType);
}
@Override
public List<OptionData> getOptions() {
return null;
}
@Override
public List<SubcommandData> getSubcommands() {
return null;
}
}

View File

@ -50,13 +50,10 @@ public class SlashCommandLoader {
NoSuchMethodException e) {
logger.error("Failed to load " + name + "!");
}
}
} else {
logger.trace("Ignored command: " + name);
}
}
}
@ -68,8 +65,10 @@ public class SlashCommandLoader {
if (v.getSubcommands() != null) {
command.addSubcommands(v.getSubcommands());
}
command.setDefaultEnabled(!v.isDisableByDefault());
commandListUpdateAction.addCommands(command);
});
commandListUpdateAction.queue();
}
}

View File

@ -1,9 +1,9 @@
package net.Broken.Tools.DayListener.Listeners;
import net.Broken.Commands.Over18.Madame;
import net.Broken.DB.Entity.GuildPreferenceEntity;
import net.Broken.DB.Repository.GuildPreferenceRepository;
import net.Broken.MainBot;
import net.Broken.SlashCommands.Over18.Madame;
import net.Broken.SpringContext;
import net.Broken.Tools.DayListener.NewDayListener;
import net.Broken.Tools.FindContentOnWebPage;
@ -50,7 +50,7 @@ public class DailyMadame implements NewDayListener {
} else {
Madame command = (Madame) MainBot.commandes.get("madame");
Madame command = (Madame) MainBot.slashCommands.get("madame");
imgUrl = command.poll();
}

View File

@ -1,9 +1,13 @@
package net.Broken.Tools;
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
import net.Broken.MainBot;
import net.Broken.audio.UserAudioTrack;
import net.Broken.audio.Youtube.SearchResult;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.entities.User;
import java.awt.*;
import java.io.FileNotFoundException;
@ -17,22 +21,52 @@ import java.util.Map;
public class EmbedMessageUtils {
public static EmbedBuilder getError(String message) {
EmbedBuilder temp = new EmbedBuilder().setTitle(":warning: Error! :warning:").setColor(Color.red).setDescription(message);
EmbedBuilder temp = new EmbedBuilder().setTitle(":warning: Error!").setColor(Color.red).setDescription(message);
return temp;
}
public static MessageEmbed getMusicError(String message) {
return new EmbedBuilder().setTitle(":warning: Musique Error :warning:").setDescription(":arrow_right: " + message).setFooter("'//help music' for more info.", MainBot.jda.getSelfUser().getAvatarUrl()).setTimestamp(Instant.now()).setColor(Color.red).setFooter(MainBot.url, MainBot.jda.getSelfUser().getAvatarUrl()).build();
return new EmbedBuilder().setTitle(":warning: Musique Error").setDescription(":arrow_right: " + message).setFooter("'//help music' for more info.", MainBot.jda.getSelfUser().getAvatarUrl()).setTimestamp(Instant.now()).setColor(Color.red).setFooter(MainBot.url, MainBot.jda.getSelfUser().getAvatarUrl()).build();
}
public static MessageEmbed getMusicOk(String message) {
EmbedBuilder temp = new EmbedBuilder().setTitle(":loud_sound: Music :loud_sound:").setDescription(message).setColor(Color.green);
// TODO better display for different action (add icon ?)
EmbedBuilder temp = new EmbedBuilder().setTitle(":loud_sound: " + message).setColor(Color.green);
return buildStandar(temp);
}
public static MessageEmbed getMusicInfo(AudioTrackInfo info, UserAudioTrack userAudioTrack) {
EmbedBuilder temp = new EmbedBuilder().setTitle(":information_source: Currently playing")
.addField("Title", info.title, false)
.addField("Author", info.author, false)
.addField("URL", info.uri, false)
.addField("Submitted by", userAudioTrack.getSubmittedUser().getName(), false)
.setThumbnail("https://img.youtube.com/vi/" + info.identifier + "/hqdefault.jpg")
.setColor(Color.green);
return buildStandar(temp);
}
public static MessageEmbed getMusicAdded(AudioTrackInfo info, Member member, int playlistSize){
EmbedBuilder temp = new EmbedBuilder()
.addField("Title", info.title, false)
.addField("Author", info.author, false)
.addField("Submitted by", member.getEffectiveName(), true)
.setThumbnail("https://img.youtube.com/vi/" + info.identifier + "/hqdefault.jpg")
.setColor(Color.green);
if(playlistSize != -1){
temp.addField("Loaded tracks", Integer.toString(playlistSize), true)
.setTitle(":loud_sound: Playlist added to queue");
}
else {
temp.setTitle(":loud_sound: Track added to queue");
}
temp.addField("URL", info.uri, false);
return buildStandar(temp);
}
public static MessageEmbed getFlushError(String message) {
return buildStandar(new EmbedBuilder().setTitle(":warning: Flush Error :warning: ").setDescription(message).setColor(Color.red));
return buildStandar(new EmbedBuilder().setTitle(":warning: Flush Error").setDescription(message).setColor(Color.red));
}
@ -57,7 +91,7 @@ public class EmbedMessageUtils {
}
public static MessageEmbed getReportUsersError() {
return new EmbedBuilder().setTitle(":warning: Command error :warning: ").setDescription("").setColor(Color.red).setFooter("'//help move' for more info.", MainBot.jda.getSelfUser().getAvatarUrl()).setTimestamp(Instant.now()).build();
return new EmbedBuilder().setTitle(":warning: Command error").setDescription("").setColor(Color.red).setFooter("'//help move' for more info.", MainBot.jda.getSelfUser().getAvatarUrl()).setTimestamp(Instant.now()).build();
}

View File

@ -1,126 +0,0 @@
package net.Broken.Tools;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* Utils to render table in block code
*/
public class TableRenderer {
private int width;
private List<Object> header;
private List<List<Object>> table = new ArrayList<>();
private String empty = "";
public TableRenderer() {
}
/**
* Set Table header(s)
*
* @param header Header(s) as String
*/
public void setHeader(Object... header) {
this.header = Arrays.asList(header);
if (header.length > this.width)
this.width = header.length;
}
/**
* Add row to table
*
* @param content Content(s) as string
*/
public void addRow(Object... content) {
List<Object> objects = Arrays.asList(content);
table.add(objects);
if (content.length > this.width)
this.width = content.length;
}
/**
* Change default empty string
*
* @param str
*/
public void setEmptyString(String str) {
this.empty = str;
}
private String[][] normalizeTable() {
int height = header == null ? table.size() : (table.size() + 1);
String[][] normalized = new String[height][width];
int vIndex = 0;
if (header != null) {
for (int hIndex = 0; hIndex < width; hIndex++) {
if (header.size() > hIndex)
normalized[vIndex][hIndex] = header.get(hIndex).toString();
else
normalized[vIndex][hIndex] = this.empty;
}
vIndex++;
}
for (List<Object> obj : table) {
for (int hIndex = 0; hIndex < width; hIndex++) {
if (obj.size() > hIndex)
normalized[vIndex][hIndex] = obj.get(hIndex).toString();
else
normalized[vIndex][hIndex] = this.empty + "s";
}
vIndex++;
}
return normalized;
}
private int[] getCollumnWidths(String[][] table, int padding) {
int collums[] = new int[width];
for (int vIndex = 0; vIndex < table.length; vIndex++)
for (int hIndex = 0; hIndex < width; hIndex++)
if (table[vIndex][hIndex].length() + padding > collums[hIndex])
collums[hIndex] = table[vIndex][hIndex].length() + padding;
collums[collums.length - 1] -= padding;
return collums;
}
private String buildElement(String element, int width, String emptyChar) {
String result = element;
if (result.length() < width)
result += StringUtils.repeat(emptyChar, width - result.length());
return result;
}
private String buildLine(String[] strings, int[] widths, boolean header) {
String line = IntStream.range(0, strings.length)
.mapToObj((i) -> buildElement(strings[i], widths[i], " "))
.collect(Collectors.joining(""));
line = "" + line + "";
if (header) {
String seperator = IntStream.range(0, strings.length)
.mapToObj((i) -> buildElement("", widths[i], ""))
.collect(Collectors.joining(""));
line += "\n" + "╪═" + seperator + "══╪";
}
return line;
}
public String build() {
String[][] table = normalizeTable();
int[] widths = getCollumnWidths(table, 1);
return IntStream.range(0, table.length)
.mapToObj(i -> buildLine(table[i], widths, header != null && i == 0))
.collect(Collectors.joining("\n"));
}
}

View File

@ -249,7 +249,7 @@ public class UserStatsUtils {
EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setColor(Color.yellow);
embedBuilder.setTitle(member.getGuild().getName() + " Ranking");
embedBuilder.setTitle(":trophy: " + member.getGuild().getName() + " Ranking");
embedBuilder.addField("Top 5:", stringBuilder.toString(), false);
String rank;
switch (pack.selfStats.rank) {
@ -269,7 +269,6 @@ public class UserStatsUtils {
embedBuilder.addField("Your stats:", rank + " with " + pack.selfStats.total + " points", false);
embedBuilder.addField("More stats:", "https://" + MainBot.url + "/rank", false);
return EmbedMessageUtils.buildStandar(embedBuilder);
}

View File

@ -11,15 +11,19 @@ import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
import net.Broken.MainBot;
import net.Broken.RestApi.Data.UserAudioTrackData;
import net.Broken.Tools.EmbedMessageUtils;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder;
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.VoiceChannel;
import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.Button;
import net.dv8tion.jda.api.interactions.components.ComponentLayout;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@ -53,6 +57,8 @@ public class AudioM {
private Guild guild;
private Logger logger = LogManager.getLogger();
private Message lastMessageWithButton;
private AudioM(Guild guild) {
this.playerManager = new DefaultAudioPlayerManager();
AudioSourceManagers.registerRemoteSources(playerManager);
@ -86,8 +92,11 @@ public class AudioM {
public void trackLoaded(AudioTrack track) {
logger.info("[" + guild + "] Single Track detected!");
UserAudioTrack uat = new UserAudioTrack(event.getUser(), track);
Message message = new MessageBuilder().setEmbeds(EmbedMessageUtils.getMusicOk("Add " + track.getInfo().title + " to playlist")).build();
event.getHook().sendMessage(message).queue();
Message message = new MessageBuilder()
.setEmbeds(EmbedMessageUtils.getMusicAdded(track.getInfo(), event.getMember(), -1))
.build();
clearLastButton();
lastMessageWithButton = event.getHook().sendMessage(message).addActionRow(getActionButton()).complete();
play(guild, voiceChannel, musicManager, uat, onHead);
}
@ -95,8 +104,12 @@ public class AudioM {
public void playlistLoaded(AudioPlaylist playlist) {
logger.info("[" + guild + "] Playlist detected! Limit: " + playlistLimit);
AudioTrack firstTrack = playlist.getSelectedTrack();
Message message = new MessageBuilder().setEmbeds(EmbedMessageUtils.getMusicOk("Add " + firstTrack.getInfo().title + " and 30 first videos to playlist !")).build();
event.getHook().sendMessage(message).queue();
int size = Math.min(playlist.getTracks().size(), playlistLimit);
Message message = new MessageBuilder()
.setEmbeds(EmbedMessageUtils.getMusicAdded(firstTrack.getInfo(), event.getMember(), size))
.build();
clearLastButton();
lastMessageWithButton = event.getHook().sendMessage(message).addActionRow(getActionButton()).complete();
playListLoader(playlist, playlistLimit, event.getUser(), onHead);
}
@ -205,11 +218,17 @@ public class AudioM {
*
* @param event
*/
public void skipTrack(SlashCommandEvent event) {
public void skipTrack(GenericInteractionCreateEvent event) {
GuildMusicManager musicManager = getGuildAudioPlayer();
musicManager.scheduler.nextTrack();
Message message = new MessageBuilder().setEmbeds(EmbedMessageUtils.getMusicOk("Next music !")).build();
event.getHook().sendMessage(message).queue();
Message message = new MessageBuilder().setEmbeds(
EmbedMessageUtils.buildStandar(
new EmbedBuilder()
.setTitle(":track_next: Next Track")
.setColor(Color.green)
)).build();
clearLastButton();
lastMessageWithButton = event.getHook().sendMessage(message).addActionRow(getActionButton()).complete();
}
/**
@ -217,11 +236,17 @@ public class AudioM {
*
* @param event
*/
public void pause(SlashCommandEvent event) {
public void pause(GenericInteractionCreateEvent event) {
GuildMusicManager musicManager = getGuildAudioPlayer();
musicManager.scheduler.pause();
Message message = new MessageBuilder().setEmbeds(EmbedMessageUtils.getMusicOk("Playback paused")).build();
event.getHook().sendMessage(message).queue();
Message message = new MessageBuilder().setEmbeds(
EmbedMessageUtils.buildStandar(
new EmbedBuilder()
.setTitle(":pause_button: Playback paused")
.setColor(Color.green)
)).build();
clearLastButton();
lastMessageWithButton = event.getHook().sendMessage(message).addActionRow(getActionButton()).complete();
}
@ -231,11 +256,27 @@ public class AudioM {
*
* @param event
*/
public void resume(SlashCommandEvent event) {
public void resume(GenericInteractionCreateEvent event) {
GuildMusicManager musicManager = getGuildAudioPlayer();
Message message;
if(musicManager.player.getPlayingTrack() == null){
message = new MessageBuilder().setEmbeds(
EmbedMessageUtils.buildStandar(
new EmbedBuilder()
.setTitle(":warning: Nothing to play, playlist is empty !")
.setColor(Color.green)
)).build();
}else{
musicManager.scheduler.resume();
Message message = new MessageBuilder().setEmbeds(EmbedMessageUtils.getMusicOk("Playback resumed")).build();
event.getHook().sendMessage(message).queue();
message = new MessageBuilder().setEmbeds(
EmbedMessageUtils.buildStandar(
new EmbedBuilder()
.setTitle(":arrow_forward: Playback resumed")
.setColor(Color.green)
)).build();
}
clearLastButton();
lastMessageWithButton = event.getHook().sendMessage(message).addActionRow(getActionButton()).complete();
}
/**
@ -243,19 +284,26 @@ public class AudioM {
*
* @param event
*/
public void info(SlashCommandEvent event) {
public void info(GenericInteractionCreateEvent event) {
GuildMusicManager musicManager = getGuildAudioPlayer();
AudioTrackInfo info = musicManager.scheduler.getInfo();
UserAudioTrack userAudioTrack = musicManager.scheduler.getCurrentPlayingTrack();
Message message = new MessageBuilder().setEmbeds(EmbedMessageUtils.getMusicOk(info.title + "\n" + info.uri + "\nSubmitted by: " + userAudioTrack.getSubmittedUser().getName())).build();
event.getHook().sendMessage(message).queue();
Message message = new MessageBuilder().setEmbeds(EmbedMessageUtils.getMusicInfo(info, userAudioTrack)).build();
clearLastButton();
lastMessageWithButton = event.getHook().sendMessage(message).addActionRow(getActionButton()).complete();
}
public void flush(SlashCommandEvent event) {
public void flush(GenericInteractionCreateEvent event) {
GuildMusicManager musicManager = getGuildAudioPlayer();
musicManager.scheduler.flush();
Message message = new MessageBuilder().setEmbeds(EmbedMessageUtils.getMusicOk("Flush playlist!")).build();
event.getHook().sendMessage(message).queue();
Message message = new MessageBuilder().setEmbeds(
EmbedMessageUtils.buildStandar(
new EmbedBuilder()
.setTitle(":wastebasket: Playlist flushed")
.setColor(Color.green)
)).build();
clearLastButton();
lastMessageWithButton = event.getHook().sendMessage(message).addActionRow(getActionButton()).complete();
}
/**
@ -263,21 +311,46 @@ public class AudioM {
*
* @param event
*/
public void list(SlashCommandEvent event) {
public void list(GenericInteractionCreateEvent event) {
GuildMusicManager musicManager = getGuildAudioPlayer();
List<UserAudioTrackData> list = musicManager.scheduler.getList();
StringBuilder resp = new StringBuilder();
if (list.size() == 0) {
resp.append("Oh my god!\nThe playlist is empty ! \n:astonished: ");
} else {
for (UserAudioTrackData trackInfo : list) {
resp.append("- ");
resp.append(trackInfo.getAudioTrackInfo().title);
resp.append("\n");
}
}
Message message = new MessageBuilder().setEmbeds(EmbedMessageUtils.getMusicOk("Playlist:\n\n" + resp.toString())).build();
Message message = new MessageBuilder().setEmbeds(
EmbedMessageUtils.buildStandar(
new EmbedBuilder()
.setTitle(":scroll: Playlist")
.setColor(Color.green)
.setDescription("Oh no ! The playlist is empty !")
)).build();
event.getHook().sendMessage(message).queue();
} else {
StringBuilder resp = new StringBuilder();
int i = 0;
for (UserAudioTrackData trackInfo : list) {
resp.append(":arrow_right: ");
resp.append(trackInfo.getAudioTrackInfo().title);
resp.append(" - ");
resp.append(trackInfo.getAudioTrackInfo().author);
resp.append("\n\n");
if (i >= 5) {
resp.append(":arrow_forward: And ");
resp.append(list.size() - 5);
resp.append(" other tracks ...");
break;
}
i++;
}
Message message = new MessageBuilder().setEmbeds(
EmbedMessageUtils.buildStandar(
new EmbedBuilder()
.setTitle(":scroll: Playlist")
.setColor(Color.green)
.setDescription(resp.toString())
)).build();
event.getHook().sendMessage(message).queue();
}
}
/**
@ -302,16 +375,39 @@ public class AudioM {
*
* @param event
*/
public void stop(SlashCommandEvent event) {
public void stop(GenericInteractionCreateEvent event) {
musicManager.scheduler.stop();
musicManager.scheduler.flush();
if (event != null) {
Message message = new MessageBuilder().setEmbeds(EmbedMessageUtils.getMusicOk("Music stopped")).build();
event.getHook().sendMessage(message).queue();
Message message = new MessageBuilder().setEmbeds(
EmbedMessageUtils.buildStandar(
new EmbedBuilder()
.setTitle(":stop_button: Playback stopped")
.setColor(Color.green)
)).build();
clearLastButton();
lastMessageWithButton = event.getHook().sendMessage(message).addActionRow(getActionButton()).complete();
}
}
public void disconect(GenericInteractionCreateEvent event){
GuildMusicManager musicManager = getGuildAudioPlayer();
musicManager.scheduler.stop();
musicManager.scheduler.flush();
playedChanel = null;
guild.getAudioManager().closeAudioConnection();
clearLastButton();
Message message = new MessageBuilder().setEmbeds(
EmbedMessageUtils.buildStandar(
new EmbedBuilder()
.setTitle(":eject: Disconnected")
.setColor(Color.green)
)).build();
clearLastButton();
event.getHook().sendMessage(message).queue();
}
/**
* Stop current playing track and flush playlist (no confirmation message)
*/
@ -322,6 +418,7 @@ public class AudioM {
musicManager.scheduler.flush();
playedChanel = null;
guild.getAudioManager().closeAudioConnection();
clearLastButton();
}
public GuildMusicManager getGuildMusicManager() {
@ -346,4 +443,38 @@ public class AudioM {
public void setPlayedChanel(VoiceChannel playedChanel) {
this.playedChanel = playedChanel;
}
public void clearLastButton() {
if (lastMessageWithButton != null){
this.lastMessageWithButton.editMessageComponents(new ArrayList<>()).queue();
this.lastMessageWithButton = null;
}
}
public void updateLastButton(){
if (lastMessageWithButton != null)
lastMessageWithButton = lastMessageWithButton.editMessageComponents(ActionRow.of(getActionButton())).complete();
}
private List<Button> getActionButton(){
ArrayList<Button> buttonArrayList = new ArrayList<>();
if(musicManager.player.getPlayingTrack() == null){
buttonArrayList.add(Button.success("play", Emoji.fromUnicode("▶️")).withDisabled(true));
buttonArrayList.add(Button.primary("next", Emoji.fromUnicode("⏭️")).withDisabled(true));
buttonArrayList.add(Button.primary("stop", Emoji.fromUnicode("⏹️")).withDisabled(true));
buttonArrayList.add(Button.danger("disconnect", Emoji.fromUnicode("⏏️")));
return buttonArrayList;
}
if(musicManager.player.isPaused()){
buttonArrayList.add(Button.success("play", Emoji.fromUnicode("▶️")));
}
else{
buttonArrayList.add(Button.success("pause", Emoji.fromUnicode("⏸️")));
}
buttonArrayList.add(Button.primary("next", Emoji.fromUnicode("⏭️")));
buttonArrayList.add(Button.primary("stop", Emoji.fromUnicode("⏹️")));
buttonArrayList.add(Button.danger("disconnect", Emoji.fromUnicode("⏏️")));
return buttonArrayList;
}
}

View File

@ -3,6 +3,7 @@ package net.Broken.audio;
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
import com.sedmelluq.discord.lavaplayer.player.event.AudioEventAdapter;
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason;
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
@ -163,10 +164,11 @@ public class TrackScheduler extends AudioEventAdapter {
// Start the next track, regardless of if something is already playing or not. In case queue was empty, we are
// giving null to startTrack, which is a valid argument and will simply stop the player.
UserAudioTrack track = queue.poll();
if (track != null)
if (track != null){
this.currentPlayingTrack = track;
if (track != null)
player.startTrack(track.getAudioTrack(), false);
}
needAutoPlay();
}
@ -174,9 +176,46 @@ public class TrackScheduler extends AudioEventAdapter {
public void onTrackEnd(AudioPlayer player, AudioTrack track, AudioTrackEndReason endReason) {
// Only start the next track if the end reason is suitable for it (FINISHED or LOAD_FAILED)
if (endReason.mayStartNext) {
logger.debug("[" + guild + "] End of track, start next.");
if(queue.isEmpty()){
logger.debug("[" + guild.getName() + "] End of track, Playlist empty.");
AudioM.getInstance(guild).updateLastButton();
}else{
logger.debug("[" + guild.getName() + "] End of track, start next.");
nextTrack();
}
}
}
@Override
public void onTrackStart(AudioPlayer player, AudioTrack track) {
super.onTrackStart(player, track);
AudioM.getInstance(guild).updateLastButton();
}
@Override
public void onPlayerPause(AudioPlayer player) {
super.onPlayerPause(player);
AudioM.getInstance(guild).updateLastButton();
}
@Override
public void onPlayerResume(AudioPlayer player) {
super.onPlayerResume(player);
AudioM.getInstance(guild).updateLastButton();
}
@Override
public void onTrackException(AudioPlayer player, AudioTrack track, FriendlyException exception) {
super.onTrackException(player, track, exception);
AudioM.getInstance(guild).updateLastButton();
}
@Override
public void onTrackStuck(AudioPlayer player, AudioTrack track, long thresholdMs) {
super.onTrackStuck(player, track, thresholdMs);
AudioM.getInstance(guild).updateLastButton();
}
private void needAutoPlay() {