Refacto des commandes + listeners + ajout de la commande queue et de la commande skip

This commit is contained in:
Melaine Gérard 2024-12-25 10:53:08 +01:00
parent f58669e522
commit e2d61d644a
12 changed files with 226 additions and 31 deletions

View File

@ -1,6 +1,6 @@
package org.camelia.studio.kiss.shot.acerola; package org.camelia.studio.kiss.shot.acerola;
import org.camelia.studio.kiss.shot.acerola.listeners.ReadyListener; import org.camelia.studio.kiss.shot.acerola.listeners.bot.ReadyListener;
import org.camelia.studio.kiss.shot.acerola.managers.ListenerManager; import org.camelia.studio.kiss.shot.acerola.managers.ListenerManager;
import org.camelia.studio.kiss.shot.acerola.utils.Configuration; import org.camelia.studio.kiss.shot.acerola.utils.Configuration;
import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDA;

View File

@ -34,6 +34,16 @@ public class TrackScheduler extends AudioEventAdapter {
player.startTrack(queue.poll(), false); player.startTrack(queue.poll(), false);
} }
public void nextTrack(int nextTrack) {
if (nextTrack < 1) {
return;
}
for (int i = 0; i < nextTrack - 1; i++) {
queue.poll();
}
player.startTrack(queue.poll(), false);
}
public Queue<AudioTrack> getQueue() { public Queue<AudioTrack> getQueue() {
return queue; return queue;
} }

View File

@ -1,4 +1,4 @@
package org.camelia.studio.kiss.shot.acerola.commands.utils; package org.camelia.studio.kiss.shot.acerola.commands.audio;
import net.dv8tion.jda.api.audio.hooks.ConnectionListener; import net.dv8tion.jda.api.audio.hooks.ConnectionListener;
import net.dv8tion.jda.api.audio.hooks.ConnectionStatus; import net.dv8tion.jda.api.audio.hooks.ConnectionStatus;
@ -15,10 +15,10 @@ import java.util.List;
import org.camelia.studio.kiss.shot.acerola.audio.PlayerManager; import org.camelia.studio.kiss.shot.acerola.audio.PlayerManager;
import org.camelia.studio.kiss.shot.acerola.interfaces.ISlashCommand; import org.camelia.studio.kiss.shot.acerola.interfaces.ISlashCommand;
public class PlayAudioCommand implements ISlashCommand { public class PlayCommand implements ISlashCommand {
@Override @Override
public String getName() { public String getName() {
return "playaudio"; return "play";
} }
@Override @Override

View File

@ -0,0 +1,127 @@
package org.camelia.studio.kiss.shot.acerola.commands.audio;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import org.camelia.studio.kiss.shot.acerola.audio.GuildMusicManager;
import org.camelia.studio.kiss.shot.acerola.audio.PlayerManager;
import org.camelia.studio.kiss.shot.acerola.interfaces.ISlashCommand;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.managers.AudioManager;
import java.awt.Color;
public class QueueCommand implements ISlashCommand {
final int TRACKS_PER_PAGE = 10;
@Override
public String getName() {
return "queue";
}
@Override
public String getDescription() {
return "Permet de passer à la musique suivante";
}
@Override
public List<OptionData> getOptions() {
return List.of(
new OptionData(OptionType.INTEGER, "page", "Numéro de la page à visionner").setRequired(false));
}
@Override
public void execute(SlashCommandInteractionEvent event) {
event.deferReply().queue();
OptionMapping option = event.getOption("page");
int page = 1;
if (option != null) {
page = (int) option.getAsInt();
}
if (page < 1) {
event.getHook().editOriginal("La page doit être supérieure à 0.").queue();
return;
}
AudioManager audioManager = event.getGuild().getAudioManager();
if (!audioManager.isConnected()) {
event.getHook().editOriginal("Je ne suis pas connecté à un canal vocal !").queue();
return;
}
// On passe aux musiques suivantes
GuildMusicManager musicManager = PlayerManager.getInstance().getMusicManager(event.getGuild());
Queue<AudioTrack> queue = musicManager.scheduler.getQueue();
AudioTrack currentTrack = musicManager.audioPlayer.getPlayingTrack();
if (queue.isEmpty()) {
event.getHook().editOriginal("La file d'attente est vide.").queue();
return;
}
EmbedBuilder embed = new EmbedBuilder();
embed.setTitle("🎵 File d'attente");
embed.setColor(Color.BLUE);
// Calculer le nombre total de pages
int totalPages = (int) Math.ceil((double) queue.size() / TRACKS_PER_PAGE);
if (totalPages == 0)
totalPages = 1;
// Vérifier que la page demandée est valide
if (page < 1 || page > totalPages) {
event.getHook().editOriginal("❌ Page invalide ! (1-" + totalPages + ")").queue();
return;
}
// Afficher la file d'attente pour la page demandée
if (queue.isEmpty()) {
embed.setDescription("Aucune musique dans la file d'attente");
} else {
List<AudioTrack> trackList = new ArrayList<>(queue);
int startIndex = (page - 1) * TRACKS_PER_PAGE;
int endIndex = Math.min(startIndex + TRACKS_PER_PAGE, trackList.size());
StringBuilder queueList = new StringBuilder();
for (int i = startIndex; i < endIndex; i++) {
AudioTrack track = trackList.get(i);
queueList.append(i + 1)
.append(". `")
.append(track.getInfo().title)
.append("` [")
.append(formatTime(track.getDuration()))
.append("]\n");
}
embed.setDescription(queueList.toString());
}
long totalDuration = queue.stream().mapToLong(AudioTrack::getDuration).sum();
embed.setFooter(String.format("Page %d/%d • %d musiques • Durée totale: %s",
page, totalPages, queue.size(), formatTime(totalDuration)));
event.getHook().editOriginalEmbeds(embed.build()).queue();
}
private String formatTime(long timeInMillis) {
long hours = timeInMillis / 3600000;
long minutes = (timeInMillis % 3600000) / 60000;
long seconds = (timeInMillis % 60000) / 1000;
if (hours > 0) {
return String.format("%d:%02d:%02d", hours, minutes, seconds);
} else {
return String.format("%d:%02d", minutes, seconds);
}
}
}

View File

@ -0,0 +1,70 @@
package org.camelia.studio.kiss.shot.acerola.commands.audio;
import java.util.List;
import org.camelia.studio.kiss.shot.acerola.audio.GuildMusicManager;
import org.camelia.studio.kiss.shot.acerola.audio.PlayerManager;
import org.camelia.studio.kiss.shot.acerola.interfaces.ISlashCommand;
import net.dv8tion.jda.api.entities.GuildVoiceState;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.managers.AudioManager;
public class SkipCommand implements ISlashCommand {
@Override
public String getName() {
return "skip";
}
@Override
public String getDescription() {
return "Permet de passer à la musique suivante";
}
@Override
public List<OptionData> getOptions() {
return List.of(
new OptionData(OptionType.INTEGER, "tracknumber", "Nombre de musique à passer").setRequired(false));
}
@Override
public void execute(SlashCommandInteractionEvent event) {
event.deferReply().queue();
OptionMapping option = event.getOption("tracknumber");
int skipAmount = 1;
if (option != null) {
skipAmount = (int) option.getAsInt();
}
// Vérifier si l'utilisateur est dans un canal vocal
GuildVoiceState voiceState = event.getMember().getVoiceState();
if (!voiceState.inAudioChannel()) {
event.getHook().editOriginal("Vous devez être dans un canal vocal pour utiliser cette commande !").queue();
return;
}
// Vérifier si le bot est dans le même canal vocal
AudioManager audioManager = event.getGuild().getAudioManager();
if (!audioManager.isConnected()) {
event.getHook().editOriginal("Je ne suis pas connecté à un canal vocal !").queue();
return;
}
if (voiceState.getChannel() != audioManager.getConnectedChannel()) {
event.getHook().editOriginal("Vous devez être dans le même canal vocal que moi !").queue();
return;
}
// On passe aux musiques suivantes
GuildMusicManager musicManager = PlayerManager.getInstance().getMusicManager(event.getGuild());
musicManager.scheduler.nextTrack(skipAmount);
event.getHook().editOriginal("Passage de %d musiques.".formatted(skipAmount)).queue();
}
}

View File

@ -1,4 +1,4 @@
package org.camelia.studio.kiss.shot.acerola.commands.utils; package org.camelia.studio.kiss.shot.acerola.commands.audio;
import org.camelia.studio.kiss.shot.acerola.audio.GuildMusicManager; import org.camelia.studio.kiss.shot.acerola.audio.GuildMusicManager;
import org.camelia.studio.kiss.shot.acerola.audio.PlayerManager; import org.camelia.studio.kiss.shot.acerola.audio.PlayerManager;
@ -8,11 +8,11 @@ import net.dv8tion.jda.api.entities.GuildVoiceState;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.managers.AudioManager; import net.dv8tion.jda.api.managers.AudioManager;
public class StopAudioCommand implements ISlashCommand{ public class StopCommand implements ISlashCommand {
@Override @Override
public String getName() { public String getName() {
return "stopaudio"; return "stop";
} }
@Override @Override
@ -35,7 +35,7 @@ public class StopAudioCommand implements ISlashCommand{
event.reply("Je ne suis pas connecté à un canal vocal !").queue(); event.reply("Je ne suis pas connecté à un canal vocal !").queue();
return; return;
} }
if (voiceState.getChannel() != audioManager.getConnectedChannel()) { if (voiceState.getChannel() != audioManager.getConnectedChannel()) {
event.reply("Vous devez être dans le même canal vocal que moi !").queue(); event.reply("Vous devez être dans le même canal vocal que moi !").queue();
return; return;
@ -44,10 +44,10 @@ public class StopAudioCommand implements ISlashCommand{
// Arrêter la musique // Arrêter la musique
GuildMusicManager musicManager = PlayerManager.getInstance().getMusicManager(event.getGuild()); GuildMusicManager musicManager = PlayerManager.getInstance().getMusicManager(event.getGuild());
musicManager.audioPlayer.stopTrack(); musicManager.audioPlayer.stopTrack();
// Déconnecter le bot // Déconnecter le bot
audioManager.closeAudioConnection(); audioManager.closeAudioConnection();
event.reply("Musique arrêtée et déconnexion du canal vocal.").queue(); event.reply("Musique arrêtée et déconnexion du canal vocal.").queue();
} }

View File

@ -5,7 +5,6 @@ import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.channel.ChannelType; import net.dv8tion.jda.api.entities.channel.ChannelType;
import net.dv8tion.jda.api.entities.channel.concrete.*;
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion; import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;

View File

@ -1,4 +1,4 @@
package org.camelia.studio.kiss.shot.acerola.listeners; package org.camelia.studio.kiss.shot.acerola.listeners.bot;
import org.camelia.studio.kiss.shot.acerola.utils.Configuration; import org.camelia.studio.kiss.shot.acerola.utils.Configuration;
import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDA;

View File

@ -1,4 +1,4 @@
package org.camelia.studio.kiss.shot.acerola.listeners; package org.camelia.studio.kiss.shot.acerola.listeners.global;
import org.camelia.studio.kiss.shot.acerola.utils.Configuration; import org.camelia.studio.kiss.shot.acerola.utils.Configuration;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
@ -6,9 +6,6 @@ import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent; import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.hooks.ListenerAdapter;
import java.awt.*;
public class GuildMemberJoinListener extends ListenerAdapter { public class GuildMemberJoinListener extends ListenerAdapter {
@Override @Override
public void onGuildMemberJoin(GuildMemberJoinEvent event) { public void onGuildMemberJoin(GuildMemberJoinEvent event) {

View File

@ -1,4 +1,4 @@
package org.camelia.studio.kiss.shot.acerola.listeners; package org.camelia.studio.kiss.shot.acerola.listeners.global;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.hooks.ListenerAdapter;

View File

@ -1,4 +1,4 @@
package org.camelia.studio.kiss.shot.acerola.listeners; package org.camelia.studio.kiss.shot.acerola.listeners.global;
import org.camelia.studio.kiss.shot.acerola.audio.PlayerManager; import org.camelia.studio.kiss.shot.acerola.audio.PlayerManager;

View File

@ -2,13 +2,11 @@ package org.camelia.studio.kiss.shot.acerola.managers;
import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.camelia.studio.kiss.shot.acerola.listeners.GuildMemberJoinListener;
import org.camelia.studio.kiss.shot.acerola.listeners.SlashCommandListener; import org.camelia.studio.kiss.shot.acerola.utils.ReflectionUtils;
import org.camelia.studio.kiss.shot.acerola.listeners.VoiceLeaveListener;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List; import java.util.List;
public class ListenerManager { public class ListenerManager {
@ -16,11 +14,9 @@ public class ListenerManager {
private final Logger logger = LoggerFactory.getLogger(ListenerManager.class.getName()); private final Logger logger = LoggerFactory.getLogger(ListenerManager.class.getName());
public ListenerManager() { public ListenerManager() {
listener = new ArrayList<>(); listener = ReflectionUtils.loadClasses(
"org.camelia.studio.kiss.shot.acerola.listeners.global",
addListener(new SlashCommandListener()); ListenerAdapter.class);
addListener(new GuildMemberJoinListener());
addListener(new VoiceLeaveListener());
} }
public void registerListeners(JDA jda) { public void registerListeners(JDA jda) {
@ -30,8 +26,4 @@ public class ListenerManager {
logger.info("Listener {} enregistré !", listenerAdapter.getClass().getSimpleName()); logger.info("Listener {} enregistré !", listenerAdapter.getClass().getSimpleName());
} }
} }
private void addListener(ListenerAdapter listenerAdapter) {
this.listener.add(listenerAdapter);
}
} }