Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
f28c181e8a | |||
1cce7f01b7 | |||
2f020dc5a7 | |||
c7b07a5843 | |||
e2d61d644a | |||
|
f58669e522 | ||
|
c112781ee6 | ||
|
7fce86174f | ||
|
92b762fdb0 |
.env.examplebuild.gradle.ktsdocker-compose.yml
src/main/java/org/camelia/studio/kiss/shot/acerola
KissShotAcerola.java
audio
commands
audio
NowPlayingCommand.javaPauseCommand.javaPlayCommand.javaQueueCommand.javaRepeatCommand.javaShuffleCommand.javaSkipCommand.javaStopCommand.javaVolumeCommand.java
moderation
utils
db
interfaces
listeners
bot
global
managers
models
repositories
services
@ -1,4 +1,8 @@
|
||||
BOT_TOKEN=
|
||||
GUILD_ID=
|
||||
DEFAULT_ROLE_ID=
|
||||
ROLE_ID=
|
||||
ROLE_ID=
|
||||
LOG_CHANNEL_ID=
|
||||
DB_URL=jdbc:postgresql://localhost:5434/kiss_shot_acerola
|
||||
DB_USER=postgres
|
||||
DB_PASSWORD=kiss_shot_acerola
|
@ -17,10 +17,14 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("org.hibernate:hibernate-core:6.6.2.Final")
|
||||
implementation("org.hibernate:hibernate-hikaricp:6.6.2.Final")
|
||||
implementation("org.postgresql:postgresql:42.7.4")
|
||||
implementation("io.github.cdimascio:dotenv-kotlin:6.4.2")
|
||||
implementation("net.dv8tion:JDA:5.2.1")
|
||||
implementation("ch.qos.logback:logback-classic:1.5.12")
|
||||
implementation ("dev.arbjerg:lavaplayer:2.2.2")
|
||||
implementation("jakarta.annotation:jakarta.annotation-api:3.0.0")
|
||||
}
|
||||
|
||||
|
||||
|
13
docker-compose.yml
Normal file
13
docker-compose.yml
Normal file
@ -0,0 +1,13 @@
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:17
|
||||
environment:
|
||||
POSTGRES_PASSWORD: kiss_shot_acerola
|
||||
POSTGRES_DB: kiss_shot_acerola
|
||||
ports:
|
||||
- "5434:5432"
|
||||
volumes:
|
||||
- postgres_kiss_shot_acerola_data:/var/lib/postgresql/data
|
||||
|
||||
volumes:
|
||||
postgres_kiss_shot_acerola_data:
|
@ -1,11 +1,14 @@
|
||||
package org.camelia.studio.kiss.shot.acerola;
|
||||
|
||||
import org.camelia.studio.kiss.shot.acerola.listeners.ReadyListener;
|
||||
import org.camelia.studio.kiss.shot.acerola.db.HibernateConfig;
|
||||
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.utils.Configuration;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.JDABuilder;
|
||||
import net.dv8tion.jda.api.requests.GatewayIntent;
|
||||
import net.dv8tion.jda.api.utils.MemberCachePolicy;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -20,13 +23,14 @@ public class KissShotAcerola {
|
||||
jda = JDABuilder.createDefault(Configuration.getInstance().getDotenv().get("BOT_TOKEN"))
|
||||
.addEventListeners(new ReadyListener())
|
||||
.enableIntents(GatewayIntent.getIntents(GatewayIntent.ALL_INTENTS))
|
||||
.setMemberCachePolicy(MemberCachePolicy.ALL)
|
||||
.build()
|
||||
.awaitReady()
|
||||
;
|
||||
.awaitReady();
|
||||
|
||||
new ListenerManager().registerListeners(jda);
|
||||
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||
HibernateConfig.shutdown();
|
||||
jda.shutdown();
|
||||
}));
|
||||
} catch (Exception e) {
|
||||
|
@ -8,9 +8,10 @@ import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class PlayerManager {
|
||||
@ -39,7 +40,7 @@ public class PlayerManager {
|
||||
});
|
||||
}
|
||||
|
||||
public void loadAndPlay(TextChannel channel, String url) {
|
||||
public void loadAndPlay(GuildMessageChannel channel, String url) {
|
||||
final GuildMusicManager musicManager = getMusicManager(channel.getGuild());
|
||||
|
||||
audioPlayerManager.loadItemOrdered(musicManager, url, new AudioLoadResultHandler() {
|
||||
@ -51,9 +52,14 @@ public class PlayerManager {
|
||||
|
||||
@Override
|
||||
public void playlistLoaded(AudioPlaylist playlist) {
|
||||
final AudioTrack track = playlist.getTracks().get(0);
|
||||
musicManager.scheduler.queue(track);
|
||||
channel.sendMessage("Ajout à la file d'attente: `" + track.getInfo().title + "`").queue();
|
||||
List<AudioTrack> tracks = playlist.getTracks();
|
||||
|
||||
channel.sendMessage(
|
||||
"Ajout à la file d'attente: `" + playlist.getName() + "` - " + tracks.size() + " musiques.")
|
||||
.queue();
|
||||
|
||||
for (AudioTrack track : tracks)
|
||||
musicManager.scheduler.queue(track);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,5 +1,8 @@
|
||||
package org.camelia.studio.kiss.shot.acerola.audio;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
|
||||
import com.sedmelluq.discord.lavaplayer.player.event.AudioEventAdapter;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
@ -7,19 +10,78 @@ import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason;
|
||||
|
||||
public class TrackScheduler extends AudioEventAdapter {
|
||||
private final AudioPlayer player;
|
||||
private final Queue<AudioTrack> queue;
|
||||
private boolean loop = false;
|
||||
private boolean repeat = false;
|
||||
|
||||
public TrackScheduler(AudioPlayer player) {
|
||||
this.player = player;
|
||||
this.queue = new LinkedList<>();
|
||||
}
|
||||
|
||||
public void queue(AudioTrack track) {
|
||||
player.startTrack(track, false);
|
||||
if (!player.startTrack(track, true)) {
|
||||
queue.offer(track);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrackEnd(AudioPlayer player, AudioTrack track, AudioTrackEndReason endReason) {
|
||||
if (endReason.mayStartNext) {
|
||||
// Ici vous pouvez gérer la lecture de la prochaine piste si vous implémentez une file d'attente
|
||||
nextTrack();
|
||||
}
|
||||
}
|
||||
|
||||
public void nextTrack() {
|
||||
AudioTrack track = queue.poll();
|
||||
|
||||
if (loop) {
|
||||
queue.offer(track.makeClone());
|
||||
} else if (repeat) {
|
||||
// ON ajoute la track au début de la queue
|
||||
LinkedList<AudioTrack> list = new LinkedList<>(queue);
|
||||
queue.clear();
|
||||
queue.offer(track.makeClone());
|
||||
while (!list.isEmpty()) {
|
||||
queue.offer(list.poll());
|
||||
}
|
||||
}
|
||||
player.startTrack(track, 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() {
|
||||
return queue;
|
||||
}
|
||||
|
||||
public void clearQueue() {
|
||||
queue.clear();
|
||||
}
|
||||
|
||||
public void shuffle() {
|
||||
LinkedList<AudioTrack> list = new LinkedList<>(queue);
|
||||
queue.clear();
|
||||
while (!list.isEmpty()) {
|
||||
int index = (int) (Math.random() * list.size());
|
||||
queue.offer(list.remove(index));
|
||||
}
|
||||
}
|
||||
|
||||
public void setLoop(boolean loop) {
|
||||
this.loop = loop;
|
||||
}
|
||||
|
||||
public void setRepeat(boolean repeat) {
|
||||
this.repeat = repeat;
|
||||
}
|
||||
}
|
67
src/main/java/org/camelia/studio/kiss/shot/acerola/commands/audio/NowPlayingCommand.java
Normal file
67
src/main/java/org/camelia/studio/kiss/shot/acerola/commands/audio/NowPlayingCommand.java
Normal file
@ -0,0 +1,67 @@
|
||||
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.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.managers.AudioManager;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
public class NowPlayingCommand implements ISlashCommand {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "nowplaying";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Permet de voir la musique en cours de lecture";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(SlashCommandInteractionEvent event) {
|
||||
event.deferReply().queue();
|
||||
|
||||
AudioManager audioManager = event.getGuild().getAudioManager();
|
||||
if (!audioManager.isConnected()) {
|
||||
event.getHook().editOriginal("Je ne suis pas connecté à un canal vocal !").queue();
|
||||
return;
|
||||
}
|
||||
|
||||
GuildMusicManager musicManager = PlayerManager.getInstance().getMusicManager(event.getGuild());
|
||||
AudioTrack playingTrack = musicManager.audioPlayer.getPlayingTrack();
|
||||
|
||||
if (playingTrack == null) {
|
||||
event.getHook().editOriginal("La file d'attente est vide.").queue();
|
||||
return;
|
||||
}
|
||||
|
||||
EmbedBuilder embed = new EmbedBuilder();
|
||||
embed.setTitle("En cours de lecture");
|
||||
embed.setColor(Color.ORANGE);
|
||||
embed.addField("Titre", playingTrack.getInfo().title, false);
|
||||
embed.addField("Durée", formatTime(playingTrack.getDuration()), false);
|
||||
embed.addField("Auteur", playingTrack.getInfo().author, false);
|
||||
embed.addField("Lien", playingTrack.getInfo().uri, false);
|
||||
embed.setImage(playingTrack.getInfo().artworkUrl);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package org.camelia.studio.kiss.shot.acerola.commands.audio;
|
||||
|
||||
import net.dv8tion.jda.api.entities.GuildVoiceState;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import net.dv8tion.jda.api.managers.AudioManager;
|
||||
|
||||
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;
|
||||
|
||||
public class PauseCommand implements ISlashCommand {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "pause";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Permet de mettre en pause la musique en cours de lecture";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(SlashCommandInteractionEvent event) {
|
||||
event.deferReply().queue();
|
||||
Member member = event.getMember();
|
||||
GuildVoiceState voiceState = member.getVoiceState();
|
||||
|
||||
if (!voiceState.inAudioChannel()) {
|
||||
event.getHook().editOriginal("Vous devez être connecté à un salon vocal pour utiliser cette commande !")
|
||||
.queue();
|
||||
return;
|
||||
}
|
||||
|
||||
AudioManager audioManager = event.getGuild().getAudioManager();
|
||||
if (!audioManager.isConnected()) {
|
||||
event.getHook().editOriginal("Je ne suis pas connecté à un canal vocal !").queue();
|
||||
return;
|
||||
}
|
||||
|
||||
if (member.getVoiceState().getChannel() != audioManager.getConnectedChannel()) {
|
||||
event.getHook().editOriginal("Vous devez être dans le même salon vocal que moi pour utiliser cette commande !")
|
||||
.queue();
|
||||
return;
|
||||
}
|
||||
|
||||
GuildMusicManager musicManager = PlayerManager.getInstance().getMusicManager(event.getGuild());
|
||||
|
||||
boolean isPaused = musicManager.audioPlayer.isPaused();
|
||||
|
||||
musicManager.audioPlayer.setPaused(!isPaused);
|
||||
|
||||
if (isPaused) {
|
||||
event.getHook().editOriginal("La musique a été reprise !").queue();
|
||||
return;
|
||||
}
|
||||
|
||||
event.getHook().editOriginal("La musique est en pause !").queue();
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package org.camelia.studio.kiss.shot.acerola.commands.audio;
|
||||
|
||||
import net.dv8tion.jda.api.audio.hooks.ConnectionListener;
|
||||
import net.dv8tion.jda.api.audio.hooks.ConnectionStatus;
|
||||
import net.dv8tion.jda.api.entities.GuildVoiceState;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
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.util.List;
|
||||
|
||||
import org.camelia.studio.kiss.shot.acerola.audio.PlayerManager;
|
||||
import org.camelia.studio.kiss.shot.acerola.interfaces.ISlashCommand;
|
||||
|
||||
public class PlayCommand implements ISlashCommand {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "play";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Permet de lancer une musique en .mp3 dans un salon vocal";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OptionData> getOptions() {
|
||||
return List.of(
|
||||
new OptionData(OptionType.STRING, "url", "URL de la musique à jouer", true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(SlashCommandInteractionEvent event) {
|
||||
event.deferReply().queue();
|
||||
String url = event.getOption("url").getAsString();
|
||||
Member member = event.getMember();
|
||||
GuildVoiceState voiceState = member.getVoiceState();
|
||||
|
||||
if (!voiceState.inAudioChannel()) {
|
||||
event.getHook().editOriginal("Vous devez être connecté à un salon vocal pour utiliser cette commande !")
|
||||
.queue();
|
||||
return;
|
||||
}
|
||||
|
||||
AudioManager audioManager = event.getGuild().getAudioManager();
|
||||
|
||||
if (!audioManager.isConnected()) {
|
||||
audioManager.openAudioConnection(voiceState.getChannel());
|
||||
PlayerManager.getInstance().getMusicManager(event.getGuild()).audioPlayer.setVolume(25);
|
||||
} else if (member.getVoiceState().getChannel() != audioManager.getConnectedChannel()) {
|
||||
event.getHook().editOriginal("Vous devez être dans le même salon vocal que moi pour utiliser cette commande !")
|
||||
.queue();
|
||||
return;
|
||||
}
|
||||
|
||||
audioManager.setConnectionListener(new ConnectionListener() {
|
||||
@Override
|
||||
public void onStatusChange(ConnectionStatus status) {
|
||||
if (status == ConnectionStatus.CONNECTED) {
|
||||
if (voiceState.getChannel().getType() == ChannelType.STAGE) {
|
||||
voiceState.getChannel().asStageChannel().requestToSpeak().queue(speakSuccess -> {
|
||||
audioManager.setConnectionListener(null);
|
||||
}, error -> {
|
||||
audioManager.setConnectionListener(null);
|
||||
});
|
||||
} else {
|
||||
audioManager.setConnectionListener(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
PlayerManager.getInstance().loadAndPlay(event.getChannel().asGuildMessageChannel(), url);
|
||||
event.getHook().editOriginal("Chargement du fichier audio en cours...").queue();
|
||||
}
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
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 voir la file d'attente";
|
||||
}
|
||||
|
||||
@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();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
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.entities.Member;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
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 RepeatCommand implements ISlashCommand {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "repeat";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Permet de répéter la musique en cours";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OptionData> getOptions() {
|
||||
return List.of(
|
||||
new OptionData(OptionType.STRING, "mode", "Le mode de répétition").addChoice("Toute la queue", "all")
|
||||
.addChoice("La musique actuelle", "one").addChoice("Désactiver la répétition", "off")
|
||||
.setRequired(true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(SlashCommandInteractionEvent event) {
|
||||
event.deferReply().queue();
|
||||
|
||||
Member member = event.getMember();
|
||||
GuildVoiceState voiceState = member.getVoiceState();
|
||||
|
||||
if (!voiceState.inAudioChannel()) {
|
||||
event.getHook().editOriginal("Vous devez être connecté à un salon vocal pour utiliser cette commande !")
|
||||
.queue();
|
||||
return;
|
||||
}
|
||||
|
||||
AudioManager audioManager = event.getGuild().getAudioManager();
|
||||
if (!audioManager.isConnected()) {
|
||||
event.getHook().editOriginal("Je ne suis pas connecté à un canal vocal !").queue();
|
||||
return;
|
||||
}
|
||||
|
||||
if (member.getVoiceState().getChannel() != audioManager.getConnectedChannel()) {
|
||||
event.getHook()
|
||||
.editOriginal("Vous devez être dans le même salon vocal que moi pour utiliser cette commande !")
|
||||
.queue();
|
||||
return;
|
||||
}
|
||||
|
||||
String mode = event.getOption("mode").getAsString();
|
||||
GuildMusicManager musicManager = PlayerManager.getInstance().getMusicManager(event.getGuild());
|
||||
|
||||
switch (mode) {
|
||||
case "all":
|
||||
musicManager.scheduler.setLoop(true);
|
||||
musicManager.scheduler.setRepeat(false);
|
||||
|
||||
event.getHook().editOriginal("Toute la queue sera répétée !").queue();
|
||||
break;
|
||||
case "one":
|
||||
musicManager.scheduler.setLoop(false);
|
||||
musicManager.scheduler.setRepeat(true);
|
||||
|
||||
event.getHook().editOriginal("La musique actuelle sera répétée !").queue();
|
||||
break;
|
||||
case "off":
|
||||
musicManager.scheduler.setLoop(false);
|
||||
musicManager.scheduler.setRepeat(false);
|
||||
|
||||
event.getHook().editOriginal("La répétition a été désactivée !").queue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
53
src/main/java/org/camelia/studio/kiss/shot/acerola/commands/audio/ShuffleCommand.java
Normal file
53
src/main/java/org/camelia/studio/kiss/shot/acerola/commands/audio/ShuffleCommand.java
Normal file
@ -0,0 +1,53 @@
|
||||
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.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.managers.AudioManager;
|
||||
|
||||
public class ShuffleCommand implements ISlashCommand {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "shuffle";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Permet de mélanger la file d'attente";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(SlashCommandInteractionEvent event) {
|
||||
event.deferReply().queue();
|
||||
|
||||
// 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.shuffle();
|
||||
|
||||
event.getHook().editOriginal("La file d'attente a été mélangée !").queue();
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -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.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.managers.AudioManager;
|
||||
|
||||
public class StopAudioCommand implements ISlashCommand{
|
||||
public class StopCommand implements ISlashCommand {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "stopaudio";
|
||||
return "stop";
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -35,7 +35,7 @@ public class StopAudioCommand implements ISlashCommand{
|
||||
event.reply("Je ne suis pas connecté à un canal vocal !").queue();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (voiceState.getChannel() != audioManager.getConnectedChannel()) {
|
||||
event.reply("Vous devez être dans le même canal vocal que moi !").queue();
|
||||
return;
|
||||
@ -44,10 +44,10 @@ public class StopAudioCommand implements ISlashCommand{
|
||||
// Arrêter la musique
|
||||
GuildMusicManager musicManager = PlayerManager.getInstance().getMusicManager(event.getGuild());
|
||||
musicManager.audioPlayer.stopTrack();
|
||||
|
||||
|
||||
// Déconnecter le bot
|
||||
audioManager.closeAudioConnection();
|
||||
|
||||
|
||||
event.reply("Musique arrêtée et déconnexion du canal vocal.").queue();
|
||||
}
|
||||
|
@ -0,0 +1,63 @@
|
||||
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.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.OptionType;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
|
||||
import net.dv8tion.jda.api.managers.AudioManager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class VolumeCommand implements ISlashCommand {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "volume";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Permet de changer le volume du bot";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OptionData> getOptions() {
|
||||
return List.of(
|
||||
new OptionData(OptionType.INTEGER, "volume", "Le volume souhaité").setRequired(true).setMinValue(0).setMaxValue(100)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(SlashCommandInteractionEvent event) {
|
||||
event.deferReply().queue();
|
||||
|
||||
GuildVoiceState voiceState = event.getMember().getVoiceState();
|
||||
if (!voiceState.inAudioChannel()) {
|
||||
event.reply("Vous devez être dans un canal vocal pour utiliser cette commande !").queue();
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
GuildMusicManager musicManager = PlayerManager.getInstance().getMusicManager(event.getGuild());
|
||||
|
||||
int volume = Integer.parseInt(event.getOption("volume").getAsString());
|
||||
|
||||
musicManager.audioPlayer.setVolume(volume);
|
||||
|
||||
event.getHook().editOriginal("Le volume a été changé à " + volume + "%").queue();
|
||||
}
|
||||
}
|
126
src/main/java/org/camelia/studio/kiss/shot/acerola/commands/moderation/AvertoCommand.java
Normal file
126
src/main/java/org/camelia/studio/kiss/shot/acerola/commands/moderation/AvertoCommand.java
Normal file
@ -0,0 +1,126 @@
|
||||
package org.camelia.studio.kiss.shot.acerola.commands.moderation;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import org.camelia.studio.kiss.shot.acerola.interfaces.ISlashCommand;
|
||||
import org.camelia.studio.kiss.shot.acerola.models.Averto;
|
||||
import org.camelia.studio.kiss.shot.acerola.models.User;
|
||||
import org.camelia.studio.kiss.shot.acerola.repositories.AvertoRepository;
|
||||
import org.camelia.studio.kiss.shot.acerola.services.UserService;
|
||||
import org.camelia.studio.kiss.shot.acerola.utils.Configuration;
|
||||
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.Message.Attachment;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
|
||||
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.utils.FileUpload;
|
||||
|
||||
public class AvertoCommand implements ISlashCommand {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "averto";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Permet d'avertir un utilisateur";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OptionData> getOptions() {
|
||||
return List.of(
|
||||
new OptionData(OptionType.USER, "utilisateur", "L'utilisateur à avertir", true),
|
||||
new OptionData(OptionType.STRING, "raison", "La raison de l'avertissement", false),
|
||||
new OptionData(OptionType.ATTACHMENT, "file", "Une preuve de l'avertissement", false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultMemberPermissions defaultPermissions() {
|
||||
return DefaultMemberPermissions.enabledFor(Permission.BAN_MEMBERS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(SlashCommandInteractionEvent event) {
|
||||
event.deferReply().setEphemeral(true).queue();
|
||||
try {
|
||||
Member moderator = event.getMember();
|
||||
Member member = event.getOption("utilisateur").getAsMember();
|
||||
|
||||
OptionMapping raisonOptionMapping = event.getOption("raison");
|
||||
String reason = raisonOptionMapping == null ? "Aucune raison spécifiée" : raisonOptionMapping.getAsString();
|
||||
|
||||
OptionMapping fileOptionMapping = event.getOption("file");
|
||||
Attachment file = null;
|
||||
String fileUrl = null;
|
||||
TextChannel logChannel = event.getGuild()
|
||||
.getTextChannelById(Configuration.getInstance().getDotenv().get("LOG_CHANNEL_ID"));
|
||||
|
||||
if (fileOptionMapping != null) {
|
||||
file = fileOptionMapping.getAsAttachment();
|
||||
}
|
||||
|
||||
if (logChannel != null) {
|
||||
File fileTemp = null;
|
||||
if (file != null) {
|
||||
fileTemp = File.createTempFile("proof_" + member.getId() + "_", "." + file.getFileExtension());
|
||||
fileTemp = file.getProxy().downloadToFile(fileTemp).get();
|
||||
}
|
||||
|
||||
Message message = this.sendLogMessage(logChannel, member, fileTemp, reason);
|
||||
|
||||
if (fileTemp != null) {
|
||||
fileUrl = message.getAttachments().get(0).getUrl();
|
||||
fileTemp.delete();
|
||||
}
|
||||
}
|
||||
|
||||
User memberUser = UserService.getInstance().getOrCreateUser(member.getId());
|
||||
User moderatorUser = UserService.getInstance().getOrCreateUser(moderator.getId());
|
||||
|
||||
Averto averto = new Averto(memberUser, moderatorUser);
|
||||
averto.setReason(reason);
|
||||
averto.setFile(fileUrl);
|
||||
|
||||
AvertoRepository.getInstance().save(averto);
|
||||
|
||||
// On tente d'envoyer un message privé à l'utilisateur averti
|
||||
member.getUser().openPrivateChannel().queue(privateChannel -> {
|
||||
privateChannel
|
||||
.sendMessage("Bonjour, Vous avez été averti sur %s pour la raison suivante : %s".formatted(
|
||||
event.getGuild().getName(), reason != null ? reason : "Aucune raison spécifiée"))
|
||||
.queue();
|
||||
});
|
||||
|
||||
event.getHook().editOriginal("L'utilisateur %s a bien été averti !".formatted(member.getAsMention()))
|
||||
.queue();
|
||||
} catch (Exception e) {
|
||||
event.getHook().editOriginal("Une erreur est survenue lors de l'avertissement, " + e.getMessage()).queue();
|
||||
}
|
||||
}
|
||||
|
||||
private Message sendLogMessage(TextChannel logChannel, Member member, File fileTemp, String reason) {
|
||||
EmbedBuilder embedBuilder = new EmbedBuilder();
|
||||
embedBuilder.setTitle("Avertissement - Règlement enfreint");
|
||||
embedBuilder.setDescription("Un utilisateur a été averti pour non respect du règlement");
|
||||
embedBuilder.addField("Utilisateur", member.getAsMention(), false);
|
||||
embedBuilder.addField("Raison", reason != null ? reason : "Aucune raison spécifié", false);
|
||||
|
||||
Message msg = logChannel.sendMessageEmbeds(embedBuilder.build()).complete();
|
||||
|
||||
if (fileTemp != null) {
|
||||
msg = logChannel
|
||||
.sendFiles(FileUpload.fromData(fileTemp)).complete();
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
}
|
99
src/main/java/org/camelia/studio/kiss/shot/acerola/commands/moderation/AvertoListCommand.java
Normal file
99
src/main/java/org/camelia/studio/kiss/shot/acerola/commands/moderation/AvertoListCommand.java
Normal file
@ -0,0 +1,99 @@
|
||||
package org.camelia.studio.kiss.shot.acerola.commands.moderation;
|
||||
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
|
||||
import org.camelia.studio.kiss.shot.acerola.interfaces.ISlashCommand;
|
||||
import org.camelia.studio.kiss.shot.acerola.models.Averto;
|
||||
import org.camelia.studio.kiss.shot.acerola.models.User;
|
||||
import org.camelia.studio.kiss.shot.acerola.services.AvertoService;
|
||||
import org.camelia.studio.kiss.shot.acerola.services.UserService;
|
||||
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
|
||||
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;
|
||||
|
||||
public class AvertoListCommand implements ISlashCommand {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "avertolist";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Liste les avertissements d'un utilisateur";
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultMemberPermissions defaultPermissions() {
|
||||
return DefaultMemberPermissions.enabledFor(Permission.BAN_MEMBERS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OptionData> getOptions() {
|
||||
return List.of(
|
||||
new OptionData(
|
||||
OptionType.USER,
|
||||
"utilisateur",
|
||||
"L'utilisateur dont vous voulez voir les avertissements",
|
||||
false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(SlashCommandInteractionEvent event) {
|
||||
event.deferReply().setEphemeral(true).queue();
|
||||
OptionMapping option = event.getOption("utilisateur");
|
||||
|
||||
Member member = null;
|
||||
List<Averto> avertos = null;
|
||||
User user = null;
|
||||
|
||||
if (option != null) {
|
||||
member = option.getAsMember();
|
||||
user = UserService.getInstance().getOrCreateUser(member.getId());
|
||||
avertos = user.getAvertos();
|
||||
} else {
|
||||
avertos = AvertoService.getInstance().getLatestAvertos(10);
|
||||
}
|
||||
/*
|
||||
* 2 possibilités :
|
||||
* - Aucun utilisateur : On affiche les 10 derniers avertissements du serveur
|
||||
* - Un utilisateur : On affiche les avertissements de cet utilisateur
|
||||
*/
|
||||
|
||||
EmbedBuilder embedBuilder = new EmbedBuilder()
|
||||
.setTitle("Avertissements de " + (member == null ? "tous les utilisateurs" : member.getEffectiveName()))
|
||||
.setColor(0xFF0000);
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (Averto averto : avertos) {
|
||||
count++;
|
||||
if (count > 10) {
|
||||
break;
|
||||
}
|
||||
// On récupère le membre Discord de l'utilisateur
|
||||
Member discordUser = event.getGuild().getMemberById(averto.getUser().getDiscordId());
|
||||
Member moderator = event.getGuild().getMemberById(averto.getModerator().getDiscordId());
|
||||
embedBuilder.addField(
|
||||
"Avertissement #" + averto.getId(),
|
||||
(discordUser != null ? "Utilisateur : " + discordUser.getAsMention() + "\n" : "") +
|
||||
"Raison : " + averto.getReason() + "\n" +
|
||||
(moderator != null ? "Modérateur : " + moderator.getAsMention() : "") + "\n" +
|
||||
"Date : "
|
||||
+ averto.getCreatedAt().format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm")) +
|
||||
"\n" +
|
||||
"Preuve : " + (averto.getFile() != null ? averto.getFile() : "Aucune"),
|
||||
false);
|
||||
}
|
||||
|
||||
event.getHook().editOriginalEmbeds(embedBuilder.build()).queue();
|
||||
}
|
||||
|
||||
}
|
@ -5,7 +5,6 @@ import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
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.unions.GuildChannelUnion;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
|
@ -1,56 +0,0 @@
|
||||
package org.camelia.studio.kiss.shot.acerola.commands.utils;
|
||||
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.GuildVoiceState;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.VoiceChannel;
|
||||
import net.dv8tion.jda.api.entities.channel.unions.AudioChannelUnion;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
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.util.List;
|
||||
|
||||
import org.camelia.studio.kiss.shot.acerola.audio.PlayerManager;
|
||||
import org.camelia.studio.kiss.shot.acerola.interfaces.ISlashCommand;
|
||||
|
||||
public class PlayAudioCommand implements ISlashCommand {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "playaudio";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Permet de lancer une musique en .mp3 dans un salon vocal";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OptionData> getOptions() {
|
||||
return List.of(
|
||||
new OptionData(OptionType.STRING, "url", "URL de la musique à jouer", true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(SlashCommandInteractionEvent event) {
|
||||
event.deferReply().queue();
|
||||
String url = event.getOption("url").getAsString();
|
||||
Member member = event.getMember();
|
||||
GuildVoiceState voiceState = member.getVoiceState();
|
||||
|
||||
if (!member.getVoiceState().inAudioChannel()) {
|
||||
event.getHook().editOriginal("Vous devez être connecté à un salon vocal pour utiliser cette commande !")
|
||||
.queue();
|
||||
return;
|
||||
}
|
||||
|
||||
VoiceChannel channel = voiceState.getChannel().asVoiceChannel();
|
||||
|
||||
AudioManager audioManager = event.getGuild().getAudioManager();
|
||||
audioManager.openAudioConnection(channel);
|
||||
PlayerManager.getInstance().getMusicManager(event.getGuild()).audioPlayer.setVolume(25);
|
||||
PlayerManager.getInstance().loadAndPlay(event.getChannel().asTextChannel(), url);
|
||||
event.getHook().editOriginal("Chargement du fichier audio en cours...").queue();
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
package org.camelia.studio.kiss.shot.acerola.db;
|
||||
|
||||
import io.github.cdimascio.dotenv.Dotenv;
|
||||
import org.camelia.studio.kiss.shot.acerola.interfaces.IEntity;
|
||||
import org.camelia.studio.kiss.shot.acerola.utils.ReflectionUtils;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
public class HibernateConfig {
|
||||
private static final Logger logger = LoggerFactory.getLogger(HibernateConfig.class);
|
||||
private static SessionFactory sessionFactory;
|
||||
|
||||
public static SessionFactory getSessionFactory() {
|
||||
if (sessionFactory == null) {
|
||||
try {
|
||||
logger.info("Initializing Hibernate SessionFactory");
|
||||
Dotenv dotenv = org.camelia.studio.kiss.shot.acerola.utils.Configuration.getInstance().getDotenv();
|
||||
|
||||
Properties props = new Properties();
|
||||
|
||||
// Configuration Hibernate
|
||||
props.put(Environment.HBM2DDL_AUTO, "update"); // On utilise validate au lieu de update
|
||||
|
||||
props.put(Environment.GLOBALLY_QUOTED_IDENTIFIERS, "true");
|
||||
|
||||
// Configuration HikariCP
|
||||
props.put("hibernate.connection.provider_class",
|
||||
"org.hibernate.hikaricp.internal.HikariCPConnectionProvider");
|
||||
props.put("hibernate.hikari.minimumIdle", "5");
|
||||
props.put("hibernate.hikari.maximumPoolSize", "10");
|
||||
props.put("hibernate.hikari.idleTimeout", "300000");
|
||||
props.put("hibernate.hikari.dataSourceClassName",
|
||||
"org.postgresql.ds.PGSimpleDataSource");
|
||||
props.put("hibernate.hikari.dataSource.url", dotenv.get("DB_URL"));
|
||||
props.put("hibernate.hikari.dataSource.user", dotenv.get("DB_USER"));
|
||||
props.put("hibernate.hikari.dataSource.password", dotenv.get("DB_PASSWORD"));
|
||||
|
||||
Configuration configuration = new Configuration();
|
||||
configuration.setProperties(props);
|
||||
|
||||
List<IEntity> entities = ReflectionUtils.loadClasses(
|
||||
"org.camelia.studio.kiss.shot.acerola.models",
|
||||
IEntity.class);
|
||||
|
||||
for (IEntity entity : entities) {
|
||||
configuration.addAnnotatedClass(entity.getClass());
|
||||
}
|
||||
|
||||
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
|
||||
.applySettings(configuration.getProperties())
|
||||
.build();
|
||||
|
||||
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
|
||||
logger.info("Hibernate SessionFactory initialized successfully");
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to initialize Hibernate SessionFactory", e);
|
||||
throw new RuntimeException("Failed to initialize Hibernate SessionFactory", e);
|
||||
}
|
||||
}
|
||||
return sessionFactory;
|
||||
}
|
||||
|
||||
public static void shutdown() {
|
||||
logger.info("Shutting down database connections");
|
||||
if (sessionFactory != null && !sessionFactory.isClosed()) {
|
||||
try {
|
||||
sessionFactory.close();
|
||||
logger.info("SessionFactory closed successfully");
|
||||
} catch (Exception e) {
|
||||
logger.error("Error closing SessionFactory", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
package org.camelia.studio.kiss.shot.acerola.interfaces;
|
||||
|
||||
public interface IEntity {
|
||||
}
|
@ -1,16 +1,23 @@
|
||||
package org.camelia.studio.kiss.shot.acerola.interfaces;
|
||||
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ISlashCommand {
|
||||
String getName();
|
||||
|
||||
String getDescription();
|
||||
|
||||
void execute(SlashCommandInteractionEvent event);
|
||||
|
||||
default List<OptionData> getOptions() {
|
||||
return List.of();
|
||||
}
|
||||
}
|
||||
|
||||
default DefaultMemberPermissions defaultPermissions() {
|
||||
return DefaultMemberPermissions.ENABLED;
|
||||
}
|
||||
}
|
||||
|
@ -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 net.dv8tion.jda.api.JDA;
|
@ -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 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.hooks.ListenerAdapter;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
|
||||
public class GuildMemberJoinListener extends ListenerAdapter {
|
||||
@Override
|
||||
public void onGuildMemberJoin(GuildMemberJoinEvent event) {
|
@ -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.hooks.ListenerAdapter;
|
@ -1,9 +1,9 @@
|
||||
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 net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.VoiceChannel;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.AudioChannel;
|
||||
import net.dv8tion.jda.api.events.guild.voice.GuildVoiceUpdateEvent;
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
import net.dv8tion.jda.api.managers.AudioManager;
|
||||
@ -19,7 +19,7 @@ public class VoiceLeaveListener extends ListenerAdapter {
|
||||
return;
|
||||
}
|
||||
|
||||
VoiceChannel botChannel = audioManager.getConnectedChannel().asVoiceChannel();
|
||||
AudioChannel botChannel = audioManager.getConnectedChannel();
|
||||
|
||||
// Compte le nombre de membres dans le canal (excluant les bots)
|
||||
long realMembersCount = botChannel.getMembers().stream()
|
@ -2,13 +2,11 @@ package org.camelia.studio.kiss.shot.acerola.managers;
|
||||
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
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.listeners.VoiceLeaveListener;
|
||||
|
||||
import org.camelia.studio.kiss.shot.acerola.utils.ReflectionUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ListenerManager {
|
||||
@ -16,11 +14,9 @@ public class ListenerManager {
|
||||
private final Logger logger = LoggerFactory.getLogger(ListenerManager.class.getName());
|
||||
|
||||
public ListenerManager() {
|
||||
listener = new ArrayList<>();
|
||||
|
||||
addListener(new SlashCommandListener());
|
||||
addListener(new GuildMemberJoinListener());
|
||||
addListener(new VoiceLeaveListener());
|
||||
listener = ReflectionUtils.loadClasses(
|
||||
"org.camelia.studio.kiss.shot.acerola.listeners.global",
|
||||
ListenerAdapter.class);
|
||||
}
|
||||
|
||||
public void registerListeners(JDA jda) {
|
||||
@ -30,8 +26,4 @@ public class ListenerManager {
|
||||
logger.info("Listener {} enregistré !", listenerAdapter.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
private void addListener(ListenerAdapter listenerAdapter) {
|
||||
this.listener.add(listenerAdapter);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,81 @@
|
||||
package org.camelia.studio.kiss.shot.acerola.models;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
|
||||
import org.camelia.studio.kiss.shot.acerola.interfaces.IEntity;
|
||||
import org.hibernate.annotations.CreationTimestamp;
|
||||
import org.hibernate.annotations.UpdateTimestamp;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Table(name = "avertos")
|
||||
public class Averto implements IEntity {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
private User user;
|
||||
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
private User moderator;
|
||||
|
||||
@Column(name = "reason", nullable = true, unique = false)
|
||||
private String reason;
|
||||
|
||||
@Column(name = "file", nullable = true, unique = false)
|
||||
private String file;
|
||||
|
||||
@CreationTimestamp
|
||||
@Column(name = "createdAt")
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@UpdateTimestamp
|
||||
@Column(name = "updatedAt")
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
public Averto() {
|
||||
}
|
||||
|
||||
public Averto(User user, User moderator) {
|
||||
this.user = user;
|
||||
this.moderator = moderator;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public LocalDateTime getUpdatedAt() {
|
||||
return updatedAt;
|
||||
}
|
||||
|
||||
public String getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
public String getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
public void setFile(String file) {
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
public void setReason(String reason) {
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public User getModerator() {
|
||||
return moderator;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package org.camelia.studio.kiss.shot.acerola.models;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
|
||||
import org.camelia.studio.kiss.shot.acerola.interfaces.IEntity;
|
||||
import org.hibernate.annotations.CreationTimestamp;
|
||||
import org.hibernate.annotations.UpdateTimestamp;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name = "users")
|
||||
public class User implements IEntity {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@OneToMany(mappedBy = "user", fetch = FetchType.EAGER)
|
||||
private List<Averto> avertos;
|
||||
|
||||
@OneToMany(mappedBy = "moderator", fetch = FetchType.EAGER)
|
||||
private List<Averto> moderatedAvertos;
|
||||
|
||||
@Column(name = "discordId", nullable = false, unique = true)
|
||||
private String discordId;
|
||||
|
||||
@CreationTimestamp
|
||||
@Column(name = "createdAt")
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@UpdateTimestamp
|
||||
@Column(name = "updatedAt")
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
public User() {
|
||||
}
|
||||
|
||||
public User(String discordId) {
|
||||
this.discordId = discordId;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getDiscordId() {
|
||||
return discordId;
|
||||
}
|
||||
|
||||
public void setDiscordId(String discordId) {
|
||||
this.discordId = discordId;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public LocalDateTime getUpdatedAt() {
|
||||
return updatedAt;
|
||||
}
|
||||
|
||||
public List<Averto> getAvertos() {
|
||||
return avertos;
|
||||
}
|
||||
|
||||
public List<Averto> getModeratedAvertos() {
|
||||
return moderatedAvertos;
|
||||
}
|
||||
}
|
53
src/main/java/org/camelia/studio/kiss/shot/acerola/repositories/AvertoRepository.java
Normal file
53
src/main/java/org/camelia/studio/kiss/shot/acerola/repositories/AvertoRepository.java
Normal file
@ -0,0 +1,53 @@
|
||||
package org.camelia.studio.kiss.shot.acerola.repositories;
|
||||
|
||||
import org.camelia.studio.kiss.shot.acerola.db.HibernateConfig;
|
||||
import org.camelia.studio.kiss.shot.acerola.models.Averto;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.query.Order;
|
||||
import org.hibernate.query.SortDirection;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class AvertoRepository {
|
||||
private final SessionFactory sessionFactory;
|
||||
private static AvertoRepository instance;
|
||||
|
||||
public static AvertoRepository getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new AvertoRepository();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public AvertoRepository() {
|
||||
this.sessionFactory = HibernateConfig.getSessionFactory();
|
||||
}
|
||||
|
||||
public List<Averto> findAll() {
|
||||
try (Session session = sessionFactory.openSession()) {
|
||||
return session.createQuery("FROM User", Averto.class)
|
||||
.setOrder(Order.by(Averto.class, "createdAt", SortDirection.DESCENDING))
|
||||
.list();
|
||||
}
|
||||
}
|
||||
|
||||
public List<Averto> findCount(int count) {
|
||||
try (Session session = sessionFactory.openSession()) {
|
||||
return session.createQuery("FROM Averto", Averto.class)
|
||||
.setOrder(Order.by(Averto.class, "createdAt", SortDirection.DESCENDING))
|
||||
.setMaxResults(count)
|
||||
.list();
|
||||
}
|
||||
}
|
||||
|
||||
public Averto save(Averto averto) {
|
||||
try (Session session = sessionFactory.openSession()) {
|
||||
session.beginTransaction();
|
||||
session.persist(averto);
|
||||
session.getTransaction().commit();
|
||||
return averto;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package org.camelia.studio.kiss.shot.acerola.repositories;
|
||||
|
||||
import org.camelia.studio.kiss.shot.acerola.db.HibernateConfig;
|
||||
import org.camelia.studio.kiss.shot.acerola.models.User;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UserRepository {
|
||||
private final SessionFactory sessionFactory;
|
||||
private static UserRepository instance;
|
||||
|
||||
public static UserRepository getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new UserRepository();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public UserRepository() {
|
||||
this.sessionFactory = HibernateConfig.getSessionFactory();
|
||||
}
|
||||
|
||||
public List<User> findAll() {
|
||||
try (Session session = sessionFactory.openSession()) {
|
||||
return session.createQuery("FROM User", User.class).list();
|
||||
}
|
||||
}
|
||||
|
||||
public User findByDiscordId(String discordId) {
|
||||
try (Session session = sessionFactory.openSession()) {
|
||||
return session.createQuery("FROM User WHERE discordId = :discordId", User.class)
|
||||
.setParameter("discordId", discordId)
|
||||
.uniqueResult();
|
||||
}
|
||||
}
|
||||
|
||||
public User save(User user) {
|
||||
try (Session session = sessionFactory.openSession()) {
|
||||
session.beginTransaction();
|
||||
session.persist(user);
|
||||
session.getTransaction().commit();
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
public void update(User user) {
|
||||
try (Session session = sessionFactory.openSession()) {
|
||||
session.beginTransaction();
|
||||
session.merge(user);
|
||||
session.getTransaction().commit();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package org.camelia.studio.kiss.shot.acerola.services;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.camelia.studio.kiss.shot.acerola.models.Averto;
|
||||
import org.camelia.studio.kiss.shot.acerola.repositories.AvertoRepository;
|
||||
|
||||
public class AvertoService {
|
||||
private static AvertoService instance;
|
||||
|
||||
public static AvertoService getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new AvertoService();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public List<Averto> getLatestAvertos(int amount) {
|
||||
return AvertoRepository.getInstance().findCount(amount);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package org.camelia.studio.kiss.shot.acerola.services;
|
||||
|
||||
import org.camelia.studio.kiss.shot.acerola.models.*;
|
||||
import org.camelia.studio.kiss.shot.acerola.repositories.UserRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UserService {
|
||||
private static UserService instance;
|
||||
|
||||
public static UserService getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new UserService();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public User getOrCreateUser(String discordId) {
|
||||
User user = UserRepository.getInstance().findByDiscordId(discordId);
|
||||
|
||||
if (user == null) {
|
||||
user = new User(discordId);
|
||||
UserRepository.getInstance().save(user);
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
public List<User> getAllUsers() {
|
||||
return UserRepository.getInstance().findAll();
|
||||
}
|
||||
|
||||
public void updateUser(User user) {
|
||||
UserRepository.getInstance().update(user);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user