Réécriture totale du code. C'est un addon nouveau
This commit is contained in:
parent
ec0ce2ae25
commit
c32da2f131
427
src/com/bernard/discord/commands/JulSoundBox.java
Normal file
427
src/com/bernard/discord/commands/JulSoundBox.java
Normal file
@ -0,0 +1,427 @@
|
|||||||
|
package com.bernard.discord.commands;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
import com.bernard.discord.api.Command;
|
||||||
|
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
|
||||||
|
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
|
||||||
|
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
|
||||||
|
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
|
||||||
|
import com.sedmelluq.discord.lavaplayer.player.event.AudioEvent;
|
||||||
|
import com.sedmelluq.discord.lavaplayer.player.event.AudioEventListener;
|
||||||
|
import com.sedmelluq.discord.lavaplayer.player.event.TrackEndEvent;
|
||||||
|
import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers;
|
||||||
|
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
|
||||||
|
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
|
||||||
|
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||||
|
import com.sedmelluq.discord.lavaplayer.track.playback.AudioFrame;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.core.EmbedBuilder;
|
||||||
|
import net.dv8tion.jda.core.MessageBuilder;
|
||||||
|
import net.dv8tion.jda.core.audio.AudioSendHandler;
|
||||||
|
import net.dv8tion.jda.core.entities.Guild;
|
||||||
|
import net.dv8tion.jda.core.entities.GuildVoiceState;
|
||||||
|
import net.dv8tion.jda.core.entities.Message;
|
||||||
|
import net.dv8tion.jda.core.entities.MessageChannel;
|
||||||
|
import net.dv8tion.jda.core.entities.User;
|
||||||
|
import net.dv8tion.jda.core.entities.VoiceChannel;
|
||||||
|
import net.dv8tion.jda.core.managers.AudioManager;
|
||||||
|
|
||||||
|
public class JulSoundBox {
|
||||||
|
|
||||||
|
private static final String soundFolder = "/var/julia/julsoundbox/sounds/";
|
||||||
|
public static final String soundExtension = ".opus";
|
||||||
|
static AudioPlayerManager playerManager = new DefaultAudioPlayerManager();
|
||||||
|
static AudioManager manager;
|
||||||
|
static VoiceChannel currentChannel = null;
|
||||||
|
static VoiceChannel oldChannel = null;//Si set, JuL'IA retournera dans ce salon dès qu'une chanson finira
|
||||||
|
static BernardSoundHandler soundHandler;
|
||||||
|
static Queue<AudioTrack> playlist;
|
||||||
|
Random randomizator;
|
||||||
|
static boolean play;
|
||||||
|
|
||||||
|
@Command(name = "playing",grp="snd",group="SoundBox", admin = false, description = "Demande à JuL'IA quel son elle est en train de jouer")
|
||||||
|
public void playing(Guild guild, Message message) {
|
||||||
|
if(soundHandler.currentTrack == null && playlist.isEmpty()) {
|
||||||
|
notifyUser("Ben je suis en fait en train de jouer .... rien du tout", message.getAuthor(), message.getChannel());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
EmbedBuilder builder = new EmbedBuilder();
|
||||||
|
String playing = "";
|
||||||
|
if(soundHandler.currentTrack == null)
|
||||||
|
playing = "Rien du tout !";
|
||||||
|
else
|
||||||
|
playing = soundHandler.currentTrack.getIdentifier();
|
||||||
|
builder.addField("Je joue ", playing, false);
|
||||||
|
|
||||||
|
String queued = "";
|
||||||
|
if(playlist.isEmpty())
|
||||||
|
queued = "Rien du tout !";
|
||||||
|
else {
|
||||||
|
for (AudioTrack audioTrack : playlist)
|
||||||
|
queued += audioTrack.getIdentifier().substring(soundFolder.length()) + ",";
|
||||||
|
queued = queued.substring(0, queued.length()-1);
|
||||||
|
}
|
||||||
|
builder.addField("J'ai prévu ", queued, false);
|
||||||
|
message.getChannel().sendMessage(builder.build()).complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sneakPlay(String sound,VoiceChannel chan) {
|
||||||
|
oldChannel = currentChannel;
|
||||||
|
manager.openAudioConnection(chan);
|
||||||
|
currentChannel = chan;
|
||||||
|
|
||||||
|
playerManager.loadItem("/var/julia/julsoundbox/sounds/" + sound + soundExtension, new AudioLoadResultHandler() {
|
||||||
|
@Override
|
||||||
|
public void trackLoaded(AudioTrack track) {
|
||||||
|
playlist = appendFirst(track, playlist);
|
||||||
|
play = true;
|
||||||
|
soundHandler.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playlistLoaded(AudioPlaylist playlist) {
|
||||||
|
System.err.println("Quoikesquevousavezfaitlà ?!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void noMatches() {
|
||||||
|
System.err.println("A moins de transformer le texte en données sonores brutes, je sais pas quoi prononcer");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadFailed(FriendlyException exception) {
|
||||||
|
System.err.println("Je n'ai pas réussi à charger le son ... désolé (en meme temps, vu comme mes devs codent !)");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Command(name = "come",grp="snd",group="SoundBox", admin = true, description = "Ammène julia dans le salon vocal auquel l'utilisateur est connécté")
|
||||||
|
public void come(Guild guild, Message message, User user) {
|
||||||
|
final GuildVoiceState memberVoiceState = guild.getMember(user).getVoiceState();
|
||||||
|
System.out.println("Coming into channel of voice state "+memberVoiceState);
|
||||||
|
if(!memberVoiceState.inVoiceChannel())
|
||||||
|
manager.closeAudioConnection();
|
||||||
|
else {
|
||||||
|
manager.openAudioConnection(memberVoiceState.getChannel());
|
||||||
|
currentChannel = memberVoiceState.getChannel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Command(name = "go",grp="snd",group="SoundBox", admin = true, description = "Ammène julia dans le salon spécifié")
|
||||||
|
public void go(Guild guild, Message message, User user) {
|
||||||
|
String channelName = message.getContentRaw().substring(message.getContentRaw().indexOf("go")+3);
|
||||||
|
System.out.println("Going to channel : "+channelName);
|
||||||
|
switch(channelName) {
|
||||||
|
case "néant":
|
||||||
|
case "rien":
|
||||||
|
case "away":
|
||||||
|
case "null":
|
||||||
|
case "nichts":
|
||||||
|
if(currentChannel != null)
|
||||||
|
manager.closeAudioConnection();
|
||||||
|
currentChannel = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<VoiceChannel> chans = guild.getVoiceChannelsByName(channelName,true);
|
||||||
|
if(chans.size() <= 0) {
|
||||||
|
notifyUser("Je ne connais pas le channel '"+channelName+"'", user, message.getChannel());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
currentChannel = chans.get(0);
|
||||||
|
manager.openAudioConnection(currentChannel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Command(name = "play",grp="snd",group="SoundBox", admin = true, description = "Reprends ou lance la lecture d'un son")
|
||||||
|
public void play(Guild guild, Message message, User user) {
|
||||||
|
String soundName = null;
|
||||||
|
if(message.getContentRaw().endsWith("play")) {
|
||||||
|
if(soundHandler.currentTrack != null || !playlist.isEmpty()) {
|
||||||
|
soundHandler.update(true);
|
||||||
|
return;
|
||||||
|
}else {
|
||||||
|
System.out.println("Random mode !!!");
|
||||||
|
File[] songsFiles = new File("/var/julia/julsoundbox/sounds/").listFiles();
|
||||||
|
soundName = songsFiles[randomizator.nextInt(songsFiles.length)].getName().substring(0, soundExtension.length()+1);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
soundName = message.getContentRaw().substring(message.getContentRaw().indexOf("play")+5);
|
||||||
|
if(!checkUserSoundPermission(user, soundName)){
|
||||||
|
notifyUser("Vous n'avez pas accès à ce morceau", user, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println("Trying to play : "+soundName);
|
||||||
|
playerManager.loadItem("/var/julia/julsoundbox/sounds/" + soundName + soundExtension, new AudioLoadResultHandler() {
|
||||||
|
@Override
|
||||||
|
public void trackLoaded(AudioTrack track) {
|
||||||
|
playlist = appendFirst(track, playlist);
|
||||||
|
play = true;
|
||||||
|
soundHandler.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playlistLoaded(AudioPlaylist playlist) {
|
||||||
|
notifyUser("Quoikesquevousavezfaitlà ?!", user, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void noMatches() {
|
||||||
|
notifyUser("A moins de transformer le texte en données sonores brutes, je sais pas quoi prononcer", user, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadFailed(FriendlyException exception) {
|
||||||
|
notifyUser("Je n'ai pas réussi à charger le son ... désolé (en meme temps, vu comme mes devs codent !)", user, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Command(name = "play2",grp="snd",group="SoundBox", admin = true, description = "Reprends ou lance la lecture d'un son2")
|
||||||
|
public void play2(Guild guild, Message message, User user) {
|
||||||
|
String soundName = message.getContentRaw().substring(message.getContentRaw().indexOf("play2")+6);
|
||||||
|
System.out.println("Trying to play : "+soundName);
|
||||||
|
playerManager.loadItem("/var/julia/julsoundbox/sounds/" + soundName + soundExtension, new AudioLoadResultHandler() {
|
||||||
|
@Override
|
||||||
|
public void trackLoaded(AudioTrack track) {
|
||||||
|
soundHandler.altTrack = track;
|
||||||
|
soundHandler.altPlayer.startTrack(track, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playlistLoaded(AudioPlaylist playlist) {
|
||||||
|
notifyUser("Quoikesquevousavezfaitlà ?!", user, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void noMatches() {
|
||||||
|
notifyUser("A moins de transformer le texte en données sonores brutes, je sais pas quoi prononcer", user, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadFailed(FriendlyException exception) {
|
||||||
|
notifyUser("Je n'ai pas réussi à charger le son ... désolé (en meme temps, vu comme mes devs codent !)", user, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Command(name = "queue",grp="snd",group="SoundBox", admin = true, description = "Ajoute un son à la liste de lecture")
|
||||||
|
public void queue(Guild guild, Message message, User user) {
|
||||||
|
String soundName = null;
|
||||||
|
if(message.getContentRaw().indexOf("queue")+5 == message.getContentRaw().length()) {
|
||||||
|
File[] songsFiles = new File("/var/julia/julsoundbox/sounds/").listFiles();
|
||||||
|
soundName = songsFiles[randomizator.nextInt(songsFiles.length)].getName().substring(0, ".opus".length());
|
||||||
|
}else{
|
||||||
|
soundName = message.getContentRaw().substring(message.getContentRaw().indexOf("queue")+6);
|
||||||
|
if(!checkUserSoundPermission(user, soundName)){
|
||||||
|
notifyUser("Vous n'avez pas accès à ce morceau", user, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
playerManager.loadItem(soundFolder + soundName + ".opus", new AudioLoadResultHandler() {
|
||||||
|
@Override
|
||||||
|
public void trackLoaded(AudioTrack track) {
|
||||||
|
playlist.add(track);
|
||||||
|
soundHandler.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playlistLoaded(AudioPlaylist playlist) {
|
||||||
|
notifyUser("Quoikesquevousavezfaitlà ?!", user, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void noMatches() {
|
||||||
|
notifyUser("A moins de transformer le texte en données sonores brutes, je sais pas quoi prononcer", user, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadFailed(FriendlyException exception) {
|
||||||
|
notifyUser("Je n'ai pas réussi à charger le son ... désolé (en meme temps, vu comme mes devs codent !)", user, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Command(name = "unqueue",grp="snd",group="SoundBox", admin = true, description = "Enlève un son de la liste de lecture")//TODO test
|
||||||
|
public void unqueue(Guild guild, Message message, User user) {
|
||||||
|
String soundId = message.getContentRaw().substring(message.getContentRaw().indexOf("unqueue")+8);
|
||||||
|
if(soundId.matches("^[0-9]+$")) {
|
||||||
|
Iterator<AudioTrack> it = playlist.iterator();
|
||||||
|
int end = Integer.parseInt(soundId, 10) - 1;//Mathe way
|
||||||
|
int i = 0;
|
||||||
|
AudioTrack track = null;
|
||||||
|
for(;i<end && it.hasNext();i++)
|
||||||
|
track = it.next();
|
||||||
|
if(i==end && track != null)
|
||||||
|
playlist.remove(track);
|
||||||
|
else
|
||||||
|
notifyUser("Il n'y a pas de son dans la playlist au "+(end+1)+"ième élement", user, null);
|
||||||
|
}else {
|
||||||
|
Iterator<AudioTrack> it = playlist.iterator();
|
||||||
|
while(it.hasNext()) {
|
||||||
|
AudioTrack t = it.next();
|
||||||
|
if(t.getUserData().equals(soundId))
|
||||||
|
playlist.remove(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
soundHandler.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Command(name = "pause",grp="snd",group="SoundBox", admin = true, description = "Met le son joué en pause (wow)")
|
||||||
|
public void pause(Guild guild, Message message, User user) {
|
||||||
|
soundHandler.update(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Command(name = "chut",grp="snd",group="SoundBox", admin = true, description = "Arette le son que JuL'IA joue (un !!play reprendra le morceau suivant ")
|
||||||
|
public void chut(Guild guild, Message message, User user) {
|
||||||
|
play = false;
|
||||||
|
soundHandler.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Command(name = "soundInit",grp="snd",group="SoundBox", admin = true, description = "Evite que tout le programme ne crashe .... a ne pas oublier (en attendant que tout 'fonctionne' ...)")
|
||||||
|
public void soundInit(Guild guild) {
|
||||||
|
playerManager = new DefaultAudioPlayerManager();
|
||||||
|
soundHandler = new BernardSoundHandler();
|
||||||
|
manager = guild.getAudioManager();
|
||||||
|
AudioSourceManagers.registerLocalSource(playerManager);
|
||||||
|
manager.setSendingHandler(soundHandler);
|
||||||
|
currentChannel = null;
|
||||||
|
playlist = new LinkedList<>();
|
||||||
|
randomizator = new Random();
|
||||||
|
play = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BernardSoundHandler implements AudioSendHandler,AudioEventListener {
|
||||||
|
|
||||||
|
public AudioTrack currentTrack;
|
||||||
|
public AudioTrack altTrack;
|
||||||
|
|
||||||
|
private final AudioPlayer audioPlayer;
|
||||||
|
final AudioPlayer altPlayer;
|
||||||
|
|
||||||
|
public BernardSoundHandler() {
|
||||||
|
audioPlayer = playerManager.createPlayer();
|
||||||
|
altPlayer = playerManager.createPlayer();
|
||||||
|
audioPlayer.addListener(this);
|
||||||
|
altPlayer.addListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void next() {
|
||||||
|
currentTrack = playlist.poll();
|
||||||
|
audioPlayer.startTrack(currentTrack, false);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update() {
|
||||||
|
audioPlayer.setPaused(!JulSoundBox.play);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(boolean play) {
|
||||||
|
JulSoundBox.play = play;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEvent(AudioEvent event) {
|
||||||
|
if(event instanceof TrackEndEvent) {
|
||||||
|
altTrack = null;
|
||||||
|
if(oldChannel != null) {
|
||||||
|
manager.openAudioConnection(oldChannel);
|
||||||
|
currentChannel = oldChannel;
|
||||||
|
|
||||||
|
}
|
||||||
|
if(playlist.size() > 0) {
|
||||||
|
currentTrack = playlist.poll();
|
||||||
|
audioPlayer.startTrack(currentTrack, false);
|
||||||
|
update();
|
||||||
|
}else {
|
||||||
|
play = false;
|
||||||
|
currentTrack = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private AudioFrame lastFrame;
|
||||||
|
/////////// Methods for sound playing ///////////
|
||||||
|
@Override
|
||||||
|
public boolean canProvide() {
|
||||||
|
if(altTrack != null) {
|
||||||
|
AudioFrame f1 = audioPlayer.provide();
|
||||||
|
AudioFrame f2 = altPlayer.provide();
|
||||||
|
lastFrame = (Math.random() > 0.5)?f1:f2;
|
||||||
|
}else
|
||||||
|
lastFrame = audioPlayer.provide();
|
||||||
|
return lastFrame != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] provide20MsAudio() {
|
||||||
|
return lastFrame.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOpus() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final boolean checkUserSoundPermission(User user,String sound) {
|
||||||
|
if(sound.indexOf("/") == -1)
|
||||||
|
return true;
|
||||||
|
File soundFile = new File(soundFolder,sound+".opus");
|
||||||
|
if(!soundFile.exists())
|
||||||
|
return true;//will be catched later, returning false will cause the 'not permitted' message appear
|
||||||
|
File lockFile = new File(soundFile.getParent(),"lock");//TODO Change with BernardFilesAPI
|
||||||
|
if(!lockFile.exists())
|
||||||
|
return true;//No lock file : the folder is open
|
||||||
|
try {
|
||||||
|
Scanner sc = new Scanner(new FileInputStream(lockFile));
|
||||||
|
while(sc.hasNextLine())
|
||||||
|
if(user.getId().equals(sc.nextLine())) {
|
||||||
|
sc.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
sc.close();
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
System.err.println("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
|
||||||
|
System.err.println("No right to access to "+lockFile.getAbsolutePath());
|
||||||
|
e.printStackTrace();
|
||||||
|
System.err.println("\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////// Useful static functions ///////////////
|
||||||
|
|
||||||
|
public static final void notifyUser(String problem, User user, MessageChannel channel) {
|
||||||
|
MessageBuilder builder = new MessageBuilder();
|
||||||
|
builder.append(user);
|
||||||
|
builder.append(" : ");
|
||||||
|
builder.append(problem);
|
||||||
|
user.openPrivateChannel().queue((chan) -> {
|
||||||
|
chan.sendMessage(builder.build()).queue();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final <T> Queue<T> appendFirst(T element,Queue<T> queue){
|
||||||
|
Queue<T> out = new LinkedList<T>();
|
||||||
|
out.add(element);
|
||||||
|
for (T t : queue) {
|
||||||
|
out.add(t);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,736 +0,0 @@
|
|||||||
package com.bernard.djulia;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.ShortBuffer;
|
|
||||||
import java.security.GeneralSecurityException;
|
|
||||||
import java.text.DateFormat;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import java.util.concurrent.FutureTask;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
|
||||||
import java.util.concurrent.locks.Lock;
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import com.bernard.djulia.DJuLIA.JuliaAudioSendHandler.JuliaAudioChannel;
|
|
||||||
import com.bernard.djulia.DJuLIA.JuliaAudioTrack.Type;
|
|
||||||
import com.bernard.juliabot.api.Command;
|
|
||||||
import com.bernard.juliabot.api.Discord;
|
|
||||||
import com.bernard.juliabot.api.DiscordCCommande;
|
|
||||||
import com.bernard.juliabot.api.JuLIAddon;
|
|
||||||
import com.bernard.juliabot.api.Trukilie;
|
|
||||||
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
|
|
||||||
import com.google.api.client.http.javanet.NetHttpTransport;
|
|
||||||
import com.google.api.client.json.JsonFactory;
|
|
||||||
import com.google.api.client.json.jackson2.JacksonFactory;
|
|
||||||
import com.google.api.services.youtube.YouTube;
|
|
||||||
import com.google.api.services.youtube.model.SearchListResponse;
|
|
||||||
import com.google.api.services.youtube.model.SearchResult;
|
|
||||||
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
|
|
||||||
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
|
|
||||||
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
|
|
||||||
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
|
|
||||||
import com.sedmelluq.discord.lavaplayer.player.event.AudioEvent;
|
|
||||||
import com.sedmelluq.discord.lavaplayer.player.event.AudioEventListener;
|
|
||||||
import com.sedmelluq.discord.lavaplayer.player.event.PlayerPauseEvent;
|
|
||||||
import com.sedmelluq.discord.lavaplayer.player.event.PlayerResumeEvent;
|
|
||||||
import com.sedmelluq.discord.lavaplayer.player.event.TrackEndEvent;
|
|
||||||
import com.sedmelluq.discord.lavaplayer.player.event.TrackExceptionEvent;
|
|
||||||
import com.sedmelluq.discord.lavaplayer.player.event.TrackStartEvent;
|
|
||||||
import com.sedmelluq.discord.lavaplayer.player.event.TrackStuckEvent;
|
|
||||||
import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers;
|
|
||||||
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
|
|
||||||
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
|
|
||||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
|
||||||
import com.sedmelluq.discord.lavaplayer.track.playback.AudioFrame;
|
|
||||||
|
|
||||||
import net.dv8tion.jda.core.EmbedBuilder;
|
|
||||||
import net.dv8tion.jda.core.Permission;
|
|
||||||
import net.dv8tion.jda.core.audio.AudioSendHandler;
|
|
||||||
import net.dv8tion.jda.core.entities.Guild;
|
|
||||||
import net.dv8tion.jda.core.entities.Member;
|
|
||||||
import net.dv8tion.jda.core.entities.Message;
|
|
||||||
import net.dv8tion.jda.core.entities.MessageChannel;
|
|
||||||
import net.dv8tion.jda.core.entities.MessageEmbed;
|
|
||||||
import net.dv8tion.jda.core.entities.MessageEmbed.Field;
|
|
||||||
import net.dv8tion.jda.core.entities.PrivateChannel;
|
|
||||||
import net.dv8tion.jda.core.entities.Role;
|
|
||||||
import net.dv8tion.jda.core.entities.TextChannel;
|
|
||||||
import net.dv8tion.jda.core.entities.User;
|
|
||||||
import net.dv8tion.jda.core.entities.VoiceChannel;
|
|
||||||
import net.dv8tion.jda.core.events.message.react.GenericMessageReactionEvent;
|
|
||||||
import net.dv8tion.jda.core.events.message.react.MessageReactionAddEvent;
|
|
||||||
import net.dv8tion.jda.core.managers.AudioManager;
|
|
||||||
|
|
||||||
|
|
||||||
@JuLIAddon(devs = "Mysaa", name = "djulia", version = "beta")
|
|
||||||
public class DJuLIA {
|
|
||||||
|
|
||||||
public static final String MUSIC = "musique";
|
|
||||||
|
|
||||||
Map<Long,JuliaAudioSendHandler> guilds = new HashMap<>();
|
|
||||||
|
|
||||||
Map<Long,Long> localGuilds = new HashMap<>();
|
|
||||||
|
|
||||||
AudioPlayerManager audioManager;
|
|
||||||
|
|
||||||
YouTube youtube = getService();
|
|
||||||
|
|
||||||
public DJuLIA() {
|
|
||||||
audioManager = new DefaultAudioPlayerManager();
|
|
||||||
AudioSourceManagers.registerRemoteSources(audioManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Command(admin = false, description = "Permet de jouer un ou plusieurs morceaux", name = "play")
|
|
||||||
public void playCommand(DiscordCCommande commande) {
|
|
||||||
Guild g = getGuild(commande);
|
|
||||||
if(g==null) {
|
|
||||||
bMsg(commande.getChannel(), "Impossible de deviner dans quel serveur vous voulez éxecuter cette commande (y a la commande soundGuild)");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String arg = commande.getStringCommand().substring(commande.getStringCommand().split(" ")[0].length());
|
|
||||||
if(!arg.isEmpty())arg = arg.substring(1);// On enlève l'espace en trop
|
|
||||||
|
|
||||||
if(arg.isEmpty()) {
|
|
||||||
if(!playButton(g, commande.getUser()))
|
|
||||||
bMsg(commande.getChannel(), g.getMember(commande.getUser()).getEffectiveName()+", vous en pouvez pas lancer la lecture ...");
|
|
||||||
return;
|
|
||||||
}else {
|
|
||||||
JuliaAudioTrack jat = understandSong(arg, commande.getChannel(), commande.getUser());
|
|
||||||
if(jat==null) {
|
|
||||||
bMsg(commande.getChannel(),"Je ne sais pas quoi jouer quand tu me dis "+arg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sender(g).getChan(MUSIC).play(jat);
|
|
||||||
if(playingMessages.get(g.getIdLong()).stream().anyMatch(m->m.getGuild().getIdLong()==g.getIdLong()))
|
|
||||||
addPlayingMessage(g, commande.getChannel().sendMessage("DUMMY MESSAGE").complete());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@Command(admin = false, description = "Permet de rajouter un morcau à la file d'attente", name = "queue")
|
|
||||||
public void queueCommand(DiscordCCommande commande) {
|
|
||||||
Guild g = getGuild(commande);
|
|
||||||
if(g==null) {
|
|
||||||
bMsg(commande.getChannel(), "Impossible de deviner dans quel serveur vous voulez éxecuter cette commande (y a la commande soundGuild)");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String arg = commande.getStringCommand().substring(commande.getStringCommand().split(" ")[0].length());
|
|
||||||
if(!arg.isEmpty())arg = arg.substring(1);// On enlève l'espace en trop
|
|
||||||
|
|
||||||
|
|
||||||
JuliaAudioTrack jat = understandSong(arg, commande.getChannel(), commande.getUser());
|
|
||||||
if(jat==null) {
|
|
||||||
bMsg(commande.getChannel(),"Je ne sais pas quoi jouer quand tu me dis "+arg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sender(g).getChan(MUSIC).queue(jat);
|
|
||||||
if(playingMessages.get(g.getIdLong()).stream().anyMatch(m->m.getGuild().getIdLong()==g.getIdLong()))
|
|
||||||
addPlayingMessage(g, commande.getChannel().sendMessage("DUMMY MESSAGE").complete());
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Command(admin = false, description = "Définis le serveur utilisé pour les commandes de son de cet utilisateur", name = "soundGuild", synopsis = "!!soundGuild [null|long guildid|string guildName]")
|
|
||||||
public void soundGuild(DiscordCCommande commande) {
|
|
||||||
String arg = commande.getStringCommand().substring(commande.getStringCommand().split(" ")[0].length());
|
|
||||||
if(!arg.isEmpty())arg = arg.substring(1);// On enlève l'espace en trop
|
|
||||||
if(arg.equalsIgnoreCase("null") || (arg.isEmpty() && !(commande.getChannel() instanceof TextChannel))) {
|
|
||||||
localGuilds.remove(commande.getUser().getIdLong());
|
|
||||||
bMsg(commande.getChannel(), "Très bien, aucun serveur n'est séléctionné");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(arg.isEmpty()) {
|
|
||||||
bMsg(commande.getChannel(), "Vous devez indiquer un serveur ou lancer cette commande dans un serveur");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Long l = null;
|
|
||||||
Guild g = null;
|
|
||||||
try {
|
|
||||||
l = Long.parseLong(arg);
|
|
||||||
g = Trukilie.jda().getGuildById(l);
|
|
||||||
}catch(NumberFormatException e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
if(g!=null) {
|
|
||||||
localGuilds.put(commande.getUser().getIdLong(), g.getIdLong());
|
|
||||||
bMsg(commande.getChannel(), "Très bien, le serveur `"+g.getName()+"` a été séléctionné *(id "+g.getIdLong()+")*");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<Guild> guilds = Trukilie.jda().getGuildsByName(arg, true);
|
|
||||||
if(guilds.isEmpty()) {
|
|
||||||
bMsg(commande.getChannel(), "Excuse-moi, `"+arg+"` ne correspond à aucun nom ou id de serveur (que je connaisse, du moins :wink:)");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int index = 0;
|
|
||||||
if(guilds.size() > 1) {
|
|
||||||
index = selector(commande.getChannel(),commande.getUser(),"Quel serveur électionnez-vous ?",guilds.stream().map(gu->"`"+ gu.getName()+"` *(id:"+gu.getId()+")*").collect(Collectors.toList()));
|
|
||||||
if(index==-1) {
|
|
||||||
bMsg(commande.getChannel(), "Tu n'as pas séléctionné de serveur, donc je ne t'en assigne pas");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
localGuilds.put(commande.getUser().getIdLong(), guilds.get(index).getIdLong());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Commandes internes
|
|
||||||
public boolean playButton(Guild g,User u) {
|
|
||||||
JuliaAudioChannel chan = guilds.get(g.getIdLong()).getChan(MUSIC);
|
|
||||||
if(!isDJ(g, u) && chan.currentTrack().querier.getIdLong() != u.getIdLong())
|
|
||||||
return false;
|
|
||||||
chan.play();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
public boolean pauseButton(Guild g,User u) {
|
|
||||||
JuliaAudioChannel chan = guilds.get(g.getIdLong()).getChan(MUSIC);
|
|
||||||
if(!isDJ(g, u) && chan.currentTrack().querier.getIdLong() != u.getIdLong())
|
|
||||||
return false;
|
|
||||||
chan.pause();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
public boolean nextButton(Guild g,User u) {
|
|
||||||
JuliaAudioChannel chan = guilds.get(g.getIdLong()).getChan(MUSIC);
|
|
||||||
if(!isDJ(g, u) && chan.currentTrack().querier.getIdLong() != u.getIdLong())
|
|
||||||
return false;
|
|
||||||
chan.next();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
public boolean stopButton(Guild g,User u) {
|
|
||||||
JuliaAudioChannel chan = guilds.get(g.getIdLong()).getChan(MUSIC);
|
|
||||||
if(!isDJ(g, u) && chan.currentTrack().querier.getIdLong() != u.getIdLong())
|
|
||||||
return false;
|
|
||||||
chan.stop();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
public boolean loopButton(Guild g,User u) {
|
|
||||||
if(!isDJ(g, u))
|
|
||||||
return false;
|
|
||||||
JuliaAudioChannel chan = guilds.get(g.getIdLong()).getChan(MUSIC);
|
|
||||||
chan.looping = !chan.looping;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
public boolean emptyButton(Guild g,User u) {
|
|
||||||
if(!isDJ(g, u))
|
|
||||||
return false;
|
|
||||||
JuliaAudioChannel chan = guilds.get(g.getIdLong()).getChan(MUSIC);
|
|
||||||
chan.empty();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Map<Long,Set<Message>> playingMessages = new HashMap<>();
|
|
||||||
public void updatePlayingMessages(Guild g) {
|
|
||||||
if(!playingMessages.containsKey(g.getIdLong()))
|
|
||||||
return;
|
|
||||||
JuliaAudioChannel chan = guilds.get(g.getIdLong()).getChan(MUSIC);
|
|
||||||
JuliaAudioTrack playing = chan.currentTrack();
|
|
||||||
EmbedBuilder builder = new EmbedBuilder();
|
|
||||||
builder.setAuthor("DJulia in the place");
|
|
||||||
builder.setTitle("Je joue "+playing.displayName+" demandé par"+g.getMember(playing.querier));
|
|
||||||
int progressP100 = (int) (chan.playProgress()*10);
|
|
||||||
String t1 = "==========",t2 = "----------";
|
|
||||||
builder.setDescription("`<"+t1.substring(progressP100)+t2.substring(10-progressP100)+">`");
|
|
||||||
builder.addField("Il y a "+chan.trackLeftCount()+" musiques dans la queue", null, false);
|
|
||||||
MessageEmbed embed = builder.build();
|
|
||||||
for(Message m : playingMessages.get(g.getIdLong()))
|
|
||||||
m.editMessage(embed).queue();
|
|
||||||
}
|
|
||||||
public void addPlayingMessage(Guild g,Message m) {
|
|
||||||
if(!playingMessages.containsKey(g.getIdLong()))
|
|
||||||
playingMessages.put(g.getIdLong(),new HashSet<>());
|
|
||||||
playingMessages.get(g.getIdLong()).add(m);
|
|
||||||
updatePlayingMessages(g);
|
|
||||||
m.addReaction("▶").queue();
|
|
||||||
m.addReaction("⏸").queue();
|
|
||||||
m.addReaction("⏭").queue();
|
|
||||||
m.addReaction("⏹").queue();
|
|
||||||
m.addReaction("🔁").queue();
|
|
||||||
m.addReaction("🗑").queue();
|
|
||||||
}
|
|
||||||
@Discord(description = "Vérifie les boutons des playing messages")
|
|
||||||
public void onReact(MessageReactionAddEvent e) {
|
|
||||||
if(!playingMessages.containsKey(e.getGuild().getIdLong()))return;
|
|
||||||
if(!playingMessages.get(e.getGuild().getIdLong()).stream().map(Message::getIdLong).anyMatch(l->l==e.getMessageIdLong()))return;
|
|
||||||
if(e.getReactionEmote().isEmote())return;
|
|
||||||
if(!"▶⏸⏭⏹🔁🗑".contains(e.getReactionEmote().getName()))return;
|
|
||||||
Guild g = getGuild(e.getUser(),e.getChannel());
|
|
||||||
User u = e.getUser();
|
|
||||||
switch(e.getReactionEmote().getName()) {
|
|
||||||
case "▶":
|
|
||||||
playButton(g, u);
|
|
||||||
break;
|
|
||||||
case "⏸":
|
|
||||||
pauseButton(g, u);
|
|
||||||
break;
|
|
||||||
case "⏭":
|
|
||||||
nextButton(g, u);
|
|
||||||
break;
|
|
||||||
case "⏹":
|
|
||||||
stopButton(g, u);
|
|
||||||
break;
|
|
||||||
case "🔁":
|
|
||||||
loopButton(g, u);
|
|
||||||
break;
|
|
||||||
case "🗑":
|
|
||||||
emptyButton(g, u);
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Guild getGuild(DiscordCCommande commande) {
|
|
||||||
return getGuild(commande.getUser(), commande.getChannel());
|
|
||||||
}
|
|
||||||
public Guild getGuild(User u,MessageChannel chan) {
|
|
||||||
|
|
||||||
if(chan instanceof TextChannel)
|
|
||||||
return ((TextChannel)chan).getGuild();
|
|
||||||
|
|
||||||
if(localGuilds.containsKey(u.getIdLong()))
|
|
||||||
return Trukilie.jda().getGuildById(localGuilds.get(u.getIdLong()));
|
|
||||||
|
|
||||||
List<Guild> mutualGuilds = u.getMutualGuilds();
|
|
||||||
if(mutualGuilds.size() == 1)
|
|
||||||
return mutualGuilds.get(0);
|
|
||||||
|
|
||||||
Set<Guild> vocalGuilds = mutualGuilds.stream()
|
|
||||||
.filter(gu->gu.getMember(u).getVoiceState().inVoiceChannel())
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
if(vocalGuilds.size() == 1)
|
|
||||||
return vocalGuilds.iterator().next();
|
|
||||||
|
|
||||||
Set<Guild> vocalGuildsWithJulia = vocalGuilds.stream()
|
|
||||||
.filter(g->guilds.containsKey(g.getIdLong()))
|
|
||||||
.filter(g->guilds.get(g.getIdLong()).currentChannel.getId().equals(g.getMember(u).getVoiceState().getAudioChannel().getId()))
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
if(vocalGuildsWithJulia.size() == 1)
|
|
||||||
return vocalGuildsWithJulia.iterator().next();
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JuliaAudioTrack understandSong(String text,MessageChannel chan, User u) {
|
|
||||||
//TODO every case
|
|
||||||
Pattern youtubeURL = Pattern.compile("^(https?\\:\\/\\/)?(www\\.)?(youtube\\.com|youtu\\.?be)\\/.+$");
|
|
||||||
String toLoad = text;
|
|
||||||
String displayName = toLoad;
|
|
||||||
Type type = Type.LOCAL;
|
|
||||||
if(!youtubeURL.matcher(text).find()) {
|
|
||||||
//Search in files
|
|
||||||
//TODO à implémenter : les fichiers locaux*
|
|
||||||
|
|
||||||
//else make youtube search
|
|
||||||
try {
|
|
||||||
YouTube.Search.List request = youtube.search().list("snippet");
|
|
||||||
SearchListResponse response = request.setMaxResults(10L)
|
|
||||||
.setQ(text)
|
|
||||||
.setType("video")
|
|
||||||
.execute();
|
|
||||||
List<SearchResult> results = response.getItems();
|
|
||||||
int index = selector(chan, u, "Quelle vidéo Youtube voulez-vous lire ?", results.stream().map(s->s.getSnippet().getTitle()+" de "+s.getSnippet().getChannelTitle()).collect(Collectors.toList()));
|
|
||||||
toLoad = "htp://youtu.be/"+results.get(index).getId();
|
|
||||||
displayName = results.get(index).getSnippet().getTitle();
|
|
||||||
type = Type.YOUTUBE;
|
|
||||||
//TODO traiter le cas pas de réponce
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AudioTrack[] t = {null};
|
|
||||||
try {
|
|
||||||
audioManager.loadItem(toLoad, new AudioLoadResultHandler() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void trackLoaded(AudioTrack track) {
|
|
||||||
t[0] = track;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void playlistLoaded(AudioPlaylist playlist) {
|
|
||||||
//TODO gérer les playlistes
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void noMatches() {
|
|
||||||
System.err.println("Les vérifications n'on pas marchées DJulia");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void loadFailed(FriendlyException exception) {
|
|
||||||
exception.printStackTrace();
|
|
||||||
}
|
|
||||||
}).get();
|
|
||||||
return new JuliaAudioTrack(t[0], type, toLoad, u, displayName);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (ExecutionException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDJ(Guild g,User u) {
|
|
||||||
Optional<Role> rr = g.getRolesByName("dj", true).stream().findAny();
|
|
||||||
if(!rr.isPresent())
|
|
||||||
return g.getMember(u).hasPermission(Permission.ADMINISTRATOR);
|
|
||||||
else
|
|
||||||
return g.getMember(u).getRoles().contains(rr.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<Long,Object> waitingEmojis = new HashMap<>();
|
|
||||||
Map<Long,Lock> everyEventLocks = new HashMap<>();
|
|
||||||
|
|
||||||
public int selector(MessageChannel chan,String title,List<String> choices) {
|
|
||||||
List<User> authorized = new ArrayList<>();
|
|
||||||
if(chan instanceof TextChannel)
|
|
||||||
authorized = ((TextChannel)chan).getMembers().stream().map(Member::getUser).collect(Collectors.toList());
|
|
||||||
else
|
|
||||||
authorized = List.of(((PrivateChannel)chan).getUser());
|
|
||||||
return selector(chan,authorized,title,choices);
|
|
||||||
}
|
|
||||||
public int selector(MessageChannel chan,User authorized,String title,List<String> choices) {
|
|
||||||
return selector(chan,List.of(authorized),title,choices);
|
|
||||||
}
|
|
||||||
public int selector(MessageChannel chan,List<User> authorized,String title,List<String> choices) {
|
|
||||||
String[] enames;
|
|
||||||
if(choices.size() > 20) {
|
|
||||||
throw new IllegalArgumentException("Je ne gère pas (encore) les trop nombreux choix >20");
|
|
||||||
}
|
|
||||||
if(choices.size() <= 10)
|
|
||||||
enames = new String[] {"one","two","three","four","five","six","seven","eight","nine","ten"};
|
|
||||||
else
|
|
||||||
enames = new String[] {"regional_indicator_a","regional_indicator_b","regional_indicator_c","regional_indicator_d","regional_indicator_e","regional_indicator_f","regional_indicator_g","regional_indicator_h","regional_indicator_i","regional_indicator_j","regional_indicator_k","regional_indicator_l","regional_indicator_m","regional_indicator_n","regional_indicator_o","regional_indicator_p","regional_indicator_q","regional_indicator_r","regional_indicator_s","regional_indicator_t","regional_indicator_u","regional_indicator_v","regional_indicator_w","regional_indicator_x","regional_indicator_y","regional_indicator_z"};
|
|
||||||
|
|
||||||
EmbedBuilder builder = new EmbedBuilder();
|
|
||||||
builder.setTitle(title);
|
|
||||||
for (int i = 0; i < choices.size(); i++)
|
|
||||||
builder.addField(":"+enames[i]+":", choices.get(i), false);
|
|
||||||
|
|
||||||
Calendar c = Calendar.getInstance();
|
|
||||||
c.add(Calendar.HOUR, 1);
|
|
||||||
String expiration = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.getDefault()).format(c.getTime());
|
|
||||||
|
|
||||||
builder.setFooter("Éxpire le "+expiration, null);
|
|
||||||
|
|
||||||
Message m = chan.sendMessage(builder.build()).complete();
|
|
||||||
|
|
||||||
for (int i = 0; i < choices.size(); i++)
|
|
||||||
m.addReaction(enames[i]).queue();
|
|
||||||
|
|
||||||
|
|
||||||
Object o = new Object();
|
|
||||||
waitingEmojis.put(m.getIdLong(), o);
|
|
||||||
ReentrantLock lock = new ReentrantLock();
|
|
||||||
everyEventLocks.put(m.getIdLong(), lock);
|
|
||||||
int index = -1;
|
|
||||||
do {
|
|
||||||
lock.unlock();
|
|
||||||
try {
|
|
||||||
o.wait(c.getTimeInMillis() - Calendar.getInstance().getTimeInMillis());
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
lock.lock();
|
|
||||||
|
|
||||||
//Check for emoji
|
|
||||||
Message mm = chan.getMessageById(m.getIdLong()).complete();
|
|
||||||
index = mm.getReactions().stream()
|
|
||||||
.filter(mr->!inter(mr.getUsers().complete(),authorized).isEmpty())
|
|
||||||
.mapToInt(mr->Arrays.binarySearch(enames,0,choices.size(),mr.getReactionEmote().getName()))
|
|
||||||
.filter(i->i>=0)
|
|
||||||
.findAny()
|
|
||||||
.orElse(-1);
|
|
||||||
}while(index==-1 || Calendar.getInstance().after(c));
|
|
||||||
|
|
||||||
waitingEmojis.remove(m.getIdLong());
|
|
||||||
everyEventLocks.remove(m.getIdLong());
|
|
||||||
|
|
||||||
lock.unlock();
|
|
||||||
o.notifyAll();
|
|
||||||
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Discord(description = "Regarde les réactions pour le sélecteur")
|
|
||||||
public void reaction(GenericMessageReactionEvent event) {
|
|
||||||
long messageID = event.getMessageIdLong();
|
|
||||||
if(!waitingEmojis.containsKey(messageID))
|
|
||||||
return;
|
|
||||||
Optional.ofNullable(everyEventLocks.get(messageID)).ifPresent(Lock::lock);
|
|
||||||
if(!waitingEmojis.containsKey(messageID))
|
|
||||||
return;
|
|
||||||
everyEventLocks.get(messageID).unlock();
|
|
||||||
waitingEmojis.get(messageID).notifyAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final <E> Set<E> inter(Collection<E> c1,Collection<E> c2) {
|
|
||||||
return c1.stream()
|
|
||||||
.distinct()
|
|
||||||
.filter(c2::contains)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Guild targetGuild(DiscordCCommande commande) {
|
|
||||||
Guild g = getGuild(commande);
|
|
||||||
if(g==null) {
|
|
||||||
bMsg(commande.getChannel(),"Je ne sais pas pour quel serveur vous voulez lancer ces commandes. Veuillez utiliser `!!soundGuild` pour séléctionner le serveur");
|
|
||||||
}
|
|
||||||
return g;
|
|
||||||
}
|
|
||||||
public static final void bMsg(MessageChannel chan,String text) {
|
|
||||||
EmbedBuilder builder = new EmbedBuilder();
|
|
||||||
builder.addField(new Field("text", text, true));
|
|
||||||
chan.sendMessage(builder.build()).queue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public JuliaAudioSendHandler sender(Guild g) {
|
|
||||||
if(guilds.containsKey(g.getIdLong()))
|
|
||||||
return guilds.get(g.getIdLong());
|
|
||||||
guilds.put(g.getIdLong(), new JuliaAudioSendHandler(g));
|
|
||||||
return guilds.get(g.getIdLong());
|
|
||||||
}
|
|
||||||
|
|
||||||
public class JuliaAudioSendHandler implements AudioSendHandler{
|
|
||||||
VoiceChannel currentChannel;
|
|
||||||
Guild currentGuild;
|
|
||||||
AudioManager manager;
|
|
||||||
Map<String,JuliaAudioChannel> chans = new HashMap<>();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public JuliaAudioSendHandler(Guild g) {
|
|
||||||
currentChannel = g.getMember(Trukilie.jda().getSelfUser()).getVoiceState().getChannel();
|
|
||||||
manager = g.getAudioManager();
|
|
||||||
manager.setSendingHandler(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public JuliaAudioChannel getChan(String chanName) {
|
|
||||||
if(chans.containsKey(chanName))
|
|
||||||
return chans.get(chanName);
|
|
||||||
JuliaAudioChannel chan = new JuliaAudioChannel();
|
|
||||||
chans.put(chanName, chan);
|
|
||||||
return chan;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void goTo(VoiceChannel chan) {
|
|
||||||
currentChannel = chan;
|
|
||||||
manager.openAudioConnection(chan);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class JuliaAudioChannel implements AudioEventListener{
|
|
||||||
AudioPlayer player;
|
|
||||||
AudioFrame frame;
|
|
||||||
List<JuliaAudioTrack> playlist;
|
|
||||||
int playlistIndex = 0;
|
|
||||||
boolean looping = false;
|
|
||||||
|
|
||||||
public JuliaAudioChannel() {
|
|
||||||
player = audioManager.createPlayer();
|
|
||||||
player.addListener(this);
|
|
||||||
playlist = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void play() {
|
|
||||||
if(playlistIndex<playlist.size())
|
|
||||||
player.setPaused(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void play(JuliaAudioTrack track) {
|
|
||||||
playlist.add(playlistIndex+1, track);
|
|
||||||
player.playTrack(playlist.get(playlistIndex).track.makeClone());
|
|
||||||
player.setPaused(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void queue(JuliaAudioTrack track) {
|
|
||||||
playlist.add(track);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void pause() {
|
|
||||||
player.setPaused(!player.isPaused());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void next() {
|
|
||||||
player.stopTrack();
|
|
||||||
playlistIndex++;
|
|
||||||
player.playTrack(playlist.get(playlistIndex).track.makeClone());
|
|
||||||
// Let paused state as it is
|
|
||||||
///XXX check TrackEndEvent is not launc
|
|
||||||
}
|
|
||||||
|
|
||||||
public void empty() {
|
|
||||||
player.stopTrack();
|
|
||||||
playlistIndex=0;
|
|
||||||
player.setPaused(true);
|
|
||||||
playlist.clear();
|
|
||||||
looping = false;
|
|
||||||
///XXX check TrackEndEvent is not launced
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stop() {
|
|
||||||
player.stopTrack();
|
|
||||||
playlistIndex++;
|
|
||||||
player.playTrack(playlist.get(playlistIndex).track.makeClone());
|
|
||||||
player.setPaused(true);
|
|
||||||
///XXX check TrackEndEvent is not launched
|
|
||||||
}
|
|
||||||
|
|
||||||
public float playProgress() {
|
|
||||||
return ((float)currentTrack().track.getPosition()) / currentTrack().track.getDuration();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int trackLeftCount() {
|
|
||||||
return playlist.size()-playlistIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JuliaAudioTrack currentTrack() {
|
|
||||||
return playlist.get(playlistIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<JuliaAudioTrack> getPlaylist() {
|
|
||||||
return playlist;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onEvent(AudioEvent event) {
|
|
||||||
|
|
||||||
if(event instanceof TrackEndEvent) {
|
|
||||||
if(playlist.size()-1>=playlistIndex) {
|
|
||||||
if(!looping)
|
|
||||||
playlistIndex++;
|
|
||||||
if(playlistIndex<playlist.size()) {
|
|
||||||
player.playTrack(playlist.get(playlistIndex).track.makeClone());
|
|
||||||
player.setPaused(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}else if(event instanceof TrackExceptionEvent) {
|
|
||||||
|
|
||||||
}else if(event instanceof TrackStuckEvent) {
|
|
||||||
|
|
||||||
}else if(event instanceof PlayerPauseEvent) {
|
|
||||||
|
|
||||||
}else if(event instanceof PlayerResumeEvent) {
|
|
||||||
|
|
||||||
}else if(event instanceof TrackStartEvent) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canProvide() {
|
|
||||||
chans.values().stream().forEach(c->c.frame = c.player.provide());
|
|
||||||
return chans.values().stream().anyMatch(c->c.frame!=null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] provide20MsAudio() {
|
|
||||||
int dataL = chans.values().stream().map(c->c.frame).filter(f->f!=null).findAny().get().getDataLength();
|
|
||||||
Set<ShortBuffer> afs = chans.values().stream()
|
|
||||||
.map(c->c.frame)
|
|
||||||
.filter(af->af!=null)
|
|
||||||
.map(af->ByteBuffer.wrap(af.getData()).asShortBuffer())
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
int n = afs.size();
|
|
||||||
|
|
||||||
byte[] result = new byte[dataL];
|
|
||||||
ShortBuffer resultBuffer = ByteBuffer.wrap(result).asShortBuffer();
|
|
||||||
|
|
||||||
int samples = dataL / 2;
|
|
||||||
|
|
||||||
for (int i = 0; i < samples; i++) {
|
|
||||||
int j = i;
|
|
||||||
resultBuffer.put(i, (short) (afs.stream().mapToInt(sb->sb.get(j)/n).sum()));
|
|
||||||
}
|
|
||||||
updatePlayingMessages(currentGuild);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isOpus() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class JuliaAudioTrack{
|
|
||||||
AudioTrack track;
|
|
||||||
Type type;
|
|
||||||
String identifier;
|
|
||||||
User querier;
|
|
||||||
String displayName;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public JuliaAudioTrack(AudioTrack track, Type type, String identifier, User querier,String displayName) {
|
|
||||||
this.track = track;
|
|
||||||
this.type = type;
|
|
||||||
this.identifier = identifier;
|
|
||||||
this.querier = querier;
|
|
||||||
this.displayName = displayName;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static enum Type{
|
|
||||||
LOCAL,
|
|
||||||
YOUTUBE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static final String APPLICATION_NAME = "DJulia";
|
|
||||||
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build and return an authorized API client service.
|
|
||||||
*
|
|
||||||
* @return an authorized API client service
|
|
||||||
* @throws GeneralSecurityException, IOException
|
|
||||||
*/
|
|
||||||
public static YouTube getService() throws GeneralSecurityException, IOException {
|
|
||||||
final NetHttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
|
|
||||||
return new YouTube.Builder(httpTransport, JSON_FACTORY, null)
|
|
||||||
.setApplicationName(APPLICATION_NAME)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user