Merge branch 'devel'
This commit is contained in:
commit
25513feb91
@ -64,6 +64,10 @@ dependencies {
|
||||
compile 'mysql:mysql-connector-java'
|
||||
compile 'org.reflections:reflections:0.9.11'
|
||||
compile 'org.apache.commons:commons-lang3:3.7'
|
||||
compile 'com.google.api-client:google-api-client:1.23.0'
|
||||
compile 'com.google.apis:google-api-services-youtube:v3-rev192-1.23.0'
|
||||
compile 'com.google.oauth-client:google-oauth-client-java6:1.23.0'
|
||||
compile 'com.google.oauth-client:google-oauth-client-jetty:1.23.0'
|
||||
|
||||
testCompile('org.springframework.boot:spring-boot-starter-test')
|
||||
testCompile('com.jayway.jsonpath:json-path')
|
||||
|
@ -23,7 +23,7 @@ public class Music implements Commande {
|
||||
public AudioM audio;
|
||||
Logger logger = LogManager.getLogger();
|
||||
public Music() {
|
||||
audio = new AudioM(MainBot.jda.getGuilds().get(0));
|
||||
audio = AudioM.getInstance(MainBot.jda.getGuilds().get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -32,7 +32,7 @@ public class Madame implements Commande{
|
||||
|
||||
String url = redirect.get("http://dites.bonjourmadame.fr/random");
|
||||
logger.debug("URL: "+url);
|
||||
if(scanPageForTipeee(url)){
|
||||
if(scanPageForTipeee(url, logger)){
|
||||
logger.debug("Advertisement detected! Retry! ("+url+")");
|
||||
}
|
||||
else{
|
||||
@ -82,7 +82,7 @@ public class Madame implements Commande{
|
||||
* @throws StringIndexOutOfBoundsException
|
||||
* @throws IOException
|
||||
*/
|
||||
private boolean scanPageForTipeee(String url) throws StringIndexOutOfBoundsException, IOException{
|
||||
public static boolean scanPageForTipeee(String url, Logger logger) throws StringIndexOutOfBoundsException, IOException{
|
||||
String content = FindContentOnWebPage.getSourceUrl(url);
|
||||
String imgClickLink = content.substring(content.indexOf("photo post"));
|
||||
imgClickLink = imgClickLink.substring(imgClickLink.indexOf("<a"));
|
||||
|
42
src/main/java/net/Broken/Commands/ytTest.java
Normal file
42
src/main/java/net/Broken/Commands/ytTest.java
Normal file
@ -0,0 +1,42 @@
|
||||
package net.Broken.Commands;
|
||||
|
||||
import net.Broken.Commande;
|
||||
import net.Broken.audio.AudioM;
|
||||
import net.Broken.audio.NotConnectedException;
|
||||
import net.Broken.audio.NullMusicManager;
|
||||
import net.Broken.audio.Youtube.YoutubeTools;
|
||||
import net.dv8tion.jda.core.events.message.MessageReceivedEvent;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class ytTest implements Commande {
|
||||
@Override
|
||||
public void action(String[] args, MessageReceivedEvent event) {
|
||||
YoutubeTools yt = YoutubeTools.getInstance(null);
|
||||
|
||||
// try {
|
||||
//// event.getTextChannel().sendMessage(yt.getRelatedVideo(args[0])).queue();
|
||||
//// AudioM.getInstance(null).getGuildMusicManager().scheduler.autoPlay();
|
||||
//
|
||||
// } catch (NotConnectedException e) {
|
||||
// e.printStackTrace();
|
||||
// } catch (NullMusicManager nullMusicManager) {
|
||||
// nullMusicManager.printStackTrace();
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrivateUsable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAdminCmd() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNSFW() {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
package net.Broken;
|
||||
|
||||
import net.Broken.RestApi.ApiCommandLoader;
|
||||
import net.Broken.Tools.Command.CommandLoader;
|
||||
import net.Broken.Tools.DayListener.DayListener;
|
||||
import net.Broken.Tools.DayListener.Listeners.DailyMadame;
|
||||
import net.Broken.Tools.DayListener.Listeners.ResetSpam;
|
||||
import net.Broken.audio.Youtube.YoutubeTools;
|
||||
import net.dv8tion.jda.core.AccountType;
|
||||
import net.dv8tion.jda.core.JDA;
|
||||
import net.dv8tion.jda.core.JDABuilder;
|
||||
@ -16,6 +18,7 @@ import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.security.auth.login.LoginException;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@ -28,15 +31,13 @@ public class Init {
|
||||
* @param dev dev Mode or not
|
||||
* @return JDA object
|
||||
*/
|
||||
static JDA initBot(String token, boolean dev){
|
||||
boolean okInit;
|
||||
static JDA initJda(String token, boolean dev){
|
||||
JDA jda = null;
|
||||
logger.debug("-------------------INITIALISATION-------------------");
|
||||
|
||||
//Bot démarrer sans token
|
||||
if (token == null) {
|
||||
logger.fatal("Veuilliez indiquer le token du bot en argument...");
|
||||
okInit=false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -56,7 +57,6 @@ public class Init {
|
||||
*************************************/
|
||||
jda.getPresence().setGame(Game.of("Statut: Loading..."));
|
||||
jda.getTextChannels().forEach(textChannel -> textChannel.sendTyping().queue());
|
||||
CommandLoader.load();
|
||||
|
||||
|
||||
//On recupere le l'id serveur
|
||||
@ -94,9 +94,9 @@ public class Init {
|
||||
dayListener.addListener(new DailyMadame());
|
||||
dayListener.start();
|
||||
|
||||
|
||||
logger.debug("-----------------FIN INITIALISATION-----------------");
|
||||
|
||||
jda.getPresence().setGame(Game.of("Statut: Ok!"));
|
||||
|
||||
}
|
||||
catch (LoginException | InterruptedException | RateLimitedException e)
|
||||
@ -107,4 +107,12 @@ public class Init {
|
||||
|
||||
return jda;
|
||||
}
|
||||
|
||||
|
||||
static void polish(JDA jda){
|
||||
CommandLoader.load();
|
||||
ApiCommandLoader.load();
|
||||
jda.getPresence().setGame(Game.of("Statut: Ok!"));
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import net.Broken.Tools.EmbedMessageUtils;
|
||||
import net.Broken.Tools.MessageTimeOut;
|
||||
import net.Broken.Tools.PrivateMessage;
|
||||
import net.Broken.Tools.UserSpamUtils;
|
||||
import net.Broken.audio.Youtube.YoutubeTools;
|
||||
import net.dv8tion.jda.core.JDA;
|
||||
import net.dv8tion.jda.core.Permission;
|
||||
import net.dv8tion.jda.core.entities.ChannelType;
|
||||
@ -20,6 +21,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
@ -36,6 +38,7 @@ public class MainBot {
|
||||
public static boolean roleFlag = false;
|
||||
public static HashMap<User, UserSpamUtils> spamUtils = new HashMap<>();
|
||||
public static JDA jda;
|
||||
public static boolean ready = false;
|
||||
|
||||
|
||||
|
||||
@ -69,7 +72,7 @@ public class MainBot {
|
||||
i++;
|
||||
}
|
||||
|
||||
jda = Init.initBot(token, dev);
|
||||
jda = Init.initJda(token, dev);
|
||||
ConfigurableApplicationContext ctx = SpringApplication.run(MainBot.class, args);
|
||||
if(jda == null) {
|
||||
System.exit(SpringApplication.exit(ctx, (ExitCodeGenerator) () -> {
|
||||
@ -78,8 +81,14 @@ public class MainBot {
|
||||
}));
|
||||
}
|
||||
|
||||
try {
|
||||
YoutubeTools.getInstance(jda.getGuilds().get(0)).getYouTubeService();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
ApiCommandLoader.load();
|
||||
Init.polish(jda);
|
||||
ready = true;
|
||||
|
||||
|
||||
|
||||
@ -95,8 +104,14 @@ public class MainBot {
|
||||
*/
|
||||
public static void handleCommand(CommandParser.CommandContainer cmd)
|
||||
{
|
||||
//On verifie que la commande existe
|
||||
|
||||
if(!ready)
|
||||
{
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//On verifie que la commande existe
|
||||
if (commandes.containsKey(cmd.commande))
|
||||
{
|
||||
Commande cmdObj = commandes.get(cmd.commande);
|
||||
@ -145,13 +160,25 @@ public class MainBot {
|
||||
else
|
||||
{
|
||||
MessageReceivedEvent event = cmd.event;
|
||||
if(event.isFromType(ChannelType.PRIVATE))
|
||||
event.getPrivateChannel().sendMessage(EmbedMessageUtils.getUnknowCommand()).queue();
|
||||
else {
|
||||
Message message = event.getTextChannel().sendMessage(EmbedMessageUtils.getUnknowCommand()).complete();
|
||||
new MessageTimeOut(messageTimeOut, message, event.getMessage());
|
||||
if(commandes.size() == 0){
|
||||
if(event.isFromType(ChannelType.PRIVATE))
|
||||
event.getPrivateChannel().sendMessage("Loading please wait...").queue();
|
||||
else {
|
||||
Message message = event.getTextChannel().sendMessage("Loading please wait...").complete();
|
||||
new MessageTimeOut(messageTimeOut, message, event.getMessage());
|
||||
}
|
||||
}
|
||||
logger.warn("Commande inconnue");
|
||||
else{
|
||||
|
||||
if(event.isFromType(ChannelType.PRIVATE))
|
||||
event.getPrivateChannel().sendMessage(EmbedMessageUtils.getUnknowCommand()).queue();
|
||||
else {
|
||||
Message message = event.getTextChannel().sendMessage(EmbedMessageUtils.getUnknowCommand()).complete();
|
||||
new MessageTimeOut(messageTimeOut, message, event.getMessage());
|
||||
}
|
||||
logger.warn("Commande inconnue");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
30
src/main/java/net/Broken/RestApi/Commands/AutoFlowOff.java
Normal file
30
src/main/java/net/Broken/RestApi/Commands/AutoFlowOff.java
Normal file
@ -0,0 +1,30 @@
|
||||
package net.Broken.RestApi.Commands;
|
||||
|
||||
import net.Broken.Commands.Music;
|
||||
import net.Broken.RestApi.CommandInterface;
|
||||
import net.Broken.RestApi.Data.CommandPostData;
|
||||
import net.Broken.RestApi.Data.CommandResponseData;
|
||||
import net.Broken.audio.AudioM;
|
||||
import net.Broken.audio.NotConnectedException;
|
||||
import net.Broken.audio.NullMusicManager;
|
||||
import net.Broken.audio.TrackScheduler;
|
||||
import net.dv8tion.jda.core.entities.User;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
public class AutoFlowOff implements CommandInterface{
|
||||
|
||||
@Override
|
||||
public ResponseEntity<CommandResponseData> action(Music musicCommande, CommandPostData data, User user) {
|
||||
AudioM audioM = AudioM.getInstance(null);
|
||||
try {
|
||||
TrackScheduler scheduler = audioM.getGuildMusicManager().scheduler;
|
||||
scheduler.setAutoFlow(false);
|
||||
return new ResponseEntity<>(new CommandResponseData(data.command,"ok"), HttpStatus.OK);
|
||||
} catch (NullMusicManager | NotConnectedException nullMusicManager) {
|
||||
LogManager.getLogger().catching(nullMusicManager);
|
||||
return new ResponseEntity<>(new CommandResponseData(data.command,"Not connected", "connect"), HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
31
src/main/java/net/Broken/RestApi/Commands/AutoFlowOn.java
Normal file
31
src/main/java/net/Broken/RestApi/Commands/AutoFlowOn.java
Normal file
@ -0,0 +1,31 @@
|
||||
package net.Broken.RestApi.Commands;
|
||||
|
||||
import net.Broken.Commands.Music;
|
||||
import net.Broken.RestApi.CommandInterface;
|
||||
import net.Broken.RestApi.Data.CommandPostData;
|
||||
import net.Broken.RestApi.Data.CommandResponseData;
|
||||
import net.Broken.audio.AudioM;
|
||||
import net.Broken.audio.NotConnectedException;
|
||||
import net.Broken.audio.NullMusicManager;
|
||||
import net.Broken.audio.TrackScheduler;
|
||||
import net.dv8tion.jda.core.entities.User;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
public class AutoFlowOn implements CommandInterface{
|
||||
|
||||
@Override
|
||||
public ResponseEntity<CommandResponseData> action(Music musicCommande, CommandPostData data, User user) {
|
||||
AudioM audioM = AudioM.getInstance(null);
|
||||
try {
|
||||
TrackScheduler scheduler = audioM.getGuildMusicManager().scheduler;
|
||||
scheduler.setAutoFlow(true);
|
||||
return new ResponseEntity<>(new CommandResponseData(data.command,"ok"), HttpStatus.OK);
|
||||
} catch (NullMusicManager | NotConnectedException nullMusicManager) {
|
||||
LogManager.getLogger().catching(nullMusicManager);
|
||||
return new ResponseEntity<>(new CommandResponseData(data.command,"Not connected", "connect"), HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@ import org.springframework.http.ResponseEntity;
|
||||
public class Connect implements CommandInterface{
|
||||
@Override
|
||||
public ResponseEntity<CommandResponseData> action(Music musicCommande, CommandPostData data, User user) {
|
||||
AudioM audioM = musicCommande.getAudioManager();
|
||||
AudioM audioM = AudioM.getInstance(null);
|
||||
if(data.chanelId == null)
|
||||
return new ResponseEntity<>(new CommandResponseData(data.command,"Missing chanelId"),HttpStatus.BAD_REQUEST);
|
||||
VoiceChannel voiceChannel = null;
|
||||
|
@ -14,13 +14,15 @@ public class CurrentMusicData {
|
||||
private final long currentPos;
|
||||
private final String state;
|
||||
private final boolean pause;
|
||||
private final boolean autoflow;
|
||||
|
||||
|
||||
public CurrentMusicData(UserAudioTrackData info, long currentPos, String state, boolean pause) {
|
||||
public CurrentMusicData(UserAudioTrackData info, long currentPos, String state, boolean pause, boolean autoflow) {
|
||||
this.info = info;
|
||||
this.currentPos = currentPos;
|
||||
this.state = state;
|
||||
this.pause = pause;
|
||||
this.autoflow = autoflow;
|
||||
}
|
||||
|
||||
public UserAudioTrackData getInfo() {
|
||||
@ -37,4 +39,8 @@ public class CurrentMusicData {
|
||||
else
|
||||
return state;
|
||||
}
|
||||
|
||||
public boolean isAutoflow() {
|
||||
return autoflow;
|
||||
}
|
||||
}
|
||||
|
23
src/main/java/net/Broken/RestApi/GeneralApiController.java
Normal file
23
src/main/java/net/Broken/RestApi/GeneralApiController.java
Normal file
@ -0,0 +1,23 @@
|
||||
package net.Broken.RestApi;
|
||||
|
||||
import net.Broken.MainBot;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/")
|
||||
public class GeneralApiController {
|
||||
@RequestMapping(value = "/isReady", method = RequestMethod.GET)
|
||||
public ResponseEntity<String> isReady(){
|
||||
if(MainBot.ready){
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
}
|
@ -51,16 +51,16 @@ public class MusicWebAPIController {
|
||||
AudioTrack currentTrack = player.getPlayingTrack();
|
||||
if(currentTrack == null)
|
||||
{
|
||||
return new CurrentMusicData(null,0, "STOP",false);
|
||||
return new CurrentMusicData(null,0, "STOP",false, musicCommande.audio.getGuildMusicManager().scheduler.isAutoFlow());
|
||||
}
|
||||
UserAudioTrackData uat = new UserAudioTrackData(musicCommande.audio.getGuildMusicManager().scheduler.getCurrentPlayingTrack());
|
||||
return new CurrentMusicData(uat, currentTrack.getPosition(), currentTrack.getState().toString(), player.isPaused());
|
||||
return new CurrentMusicData(uat, currentTrack.getPosition(), currentTrack.getState().toString(), player.isPaused(), musicCommande.audio.getGuildMusicManager().scheduler.isAutoFlow());
|
||||
} catch (NullMusicManager | NotConnectedException nullMusicManager) {
|
||||
return new CurrentMusicData(null,0, "STOP",false);
|
||||
return new CurrentMusicData(null,0, "STOP",false, false);
|
||||
}
|
||||
}else
|
||||
{
|
||||
return new CurrentMusicData(null,0, "DISCONNECTED",false);
|
||||
return new CurrentMusicData(null,0, "DISCONNECTED",false, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.Broken.Tools.DayListener.Listeners;
|
||||
|
||||
import net.Broken.Commands.Over18.Madame;
|
||||
import net.Broken.MainBot;
|
||||
import net.Broken.Tools.DayListener.NewDayListener;
|
||||
import net.Broken.Tools.Redirection;
|
||||
@ -24,8 +25,16 @@ public class DailyMadame implements NewDayListener{
|
||||
while(!success && !error)
|
||||
{
|
||||
try {
|
||||
chanel.sendMessage("Le Daily Madame mes petits cochons :kissing_heart:\n" + redirect.get("http://dites.bonjourmadame.fr/random")).queue();
|
||||
success=true;
|
||||
|
||||
String url = redirect.get("http://dites.bonjourmadame.fr/random");
|
||||
logger.debug("URL: "+url);
|
||||
if(Madame.scanPageForTipeee(url, logger)){
|
||||
logger.debug("Advertisement detected! Retry! ("+url+")");
|
||||
}
|
||||
else{
|
||||
chanel.sendMessage("Le Daily Madame mes petits cochons :kissing_heart:\n" + url).queue();
|
||||
success=true;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
errorCp++;
|
||||
logger.warn("Erreur de redirection. (Essais n°"+errorCp+")");
|
||||
|
@ -52,10 +52,19 @@ public class AudioM {
|
||||
private Guild guild;
|
||||
private Logger logger = LogManager.getLogger();
|
||||
|
||||
private static AudioM INSTANCE;
|
||||
|
||||
public static AudioM getInstance(Guild guild){
|
||||
if(INSTANCE == null){
|
||||
INSTANCE = new AudioM(guild);
|
||||
}
|
||||
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public AudioM(Guild guild) {
|
||||
private AudioM(Guild guild) {
|
||||
this.playerManager = new DefaultAudioPlayerManager();
|
||||
AudioSourceManagers.registerRemoteSources(playerManager);
|
||||
AudioSourceManagers.registerLocalSource(playerManager);
|
||||
@ -80,11 +89,7 @@ public class AudioM {
|
||||
logger.info("Single Track detected!");
|
||||
UserAudioTrack uat = new UserAudioTrack(event.getAuthor(), track);
|
||||
Message message = event.getTextChannel().sendMessage(EmbedMessageUtils.getMusicOk("Ajout de "+track.getInfo().title+" à la file d'attente!")).complete();
|
||||
List<Message> messages = new ArrayList<Message>(){{
|
||||
add(message);
|
||||
add(event.getMessage());
|
||||
}};
|
||||
new MessageTimeOut(messages, MainBot.messageTimeOut).start();
|
||||
new MessageTimeOut(MainBot.messageTimeOut, message, event.getMessage()).start();
|
||||
|
||||
play(guild, voiceChannel, musicManager, uat, onHead);
|
||||
}
|
||||
@ -95,11 +100,7 @@ public class AudioM {
|
||||
AudioTrack firstTrack = playlist.getSelectedTrack();
|
||||
|
||||
Message message = event.getTextChannel().sendMessage(EmbedMessageUtils.getMusicOk("Ajout de "+firstTrack.getInfo().title+" et les 30 premiers titres à la file d'attente!")).complete();
|
||||
List<Message> messages = new ArrayList<Message>(){{
|
||||
add(message);
|
||||
add(event.getMessage());
|
||||
}};
|
||||
new MessageTimeOut(messages, MainBot.messageTimeOut).start();
|
||||
new MessageTimeOut(MainBot.messageTimeOut, message, event.getMessage()).start();
|
||||
|
||||
playListLoader(playlist, playlistLimit ,event.getAuthor() , onHead);
|
||||
|
||||
@ -132,6 +133,37 @@ public class AudioM {
|
||||
});
|
||||
}
|
||||
|
||||
public void loadAndPlayAuto(String trackUrl){
|
||||
playerManager.loadItemOrdered(musicManager, trackUrl, new AudioLoadResultHandler(){
|
||||
@Override
|
||||
public void trackLoaded(AudioTrack track) {
|
||||
logger.info("Auto add " + track.getInfo().title +" to playlist.");
|
||||
UserAudioTrack userAudioTrack = new UserAudioTrack(MainBot.jda.getSelfUser(),track);
|
||||
play(guild, playedChanel, musicManager, userAudioTrack, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playlistLoaded(AudioPlaylist playlist) {
|
||||
AudioTrack track = playlist.getTracks().get(0);
|
||||
logger.info("Auto add " + track.getInfo().title +" to playlist.");
|
||||
UserAudioTrack userAudioTrack = new UserAudioTrack(MainBot.jda.getSelfUser(),track);
|
||||
play(guild, playedChanel, musicManager, userAudioTrack, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void noMatches() {
|
||||
logger.warn("Track not found: "+trackUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadFailed(FriendlyException exception) {
|
||||
logger.error("Cant load media!");
|
||||
logger.error(exception.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load playlist to playlist
|
||||
* @param playlist Loaded playlist
|
||||
@ -270,7 +302,7 @@ public class AudioM {
|
||||
*/
|
||||
public void add(MessageReceivedEvent event, String url, int playListLimit, boolean onHead) {
|
||||
if(playedChanel != null){
|
||||
loadAndPlay(event,playedChanel, url, playListLimit,onHead);
|
||||
loadAndPlay(event ,playedChanel, url, playListLimit,onHead);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -320,6 +352,7 @@ public class AudioM {
|
||||
public AudioPlayerManager getPlayerManager() {
|
||||
return playerManager;
|
||||
}
|
||||
|
||||
public VoiceChannel getPlayedChanel() {
|
||||
return playedChanel;
|
||||
}
|
||||
|
@ -1,11 +1,14 @@
|
||||
package net.Broken.audio;
|
||||
|
||||
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
|
||||
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
|
||||
import com.sedmelluq.discord.lavaplayer.player.event.AudioEventAdapter;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
|
||||
import net.Broken.MainBot;
|
||||
import net.Broken.RestApi.Data.UserAudioTrackData;
|
||||
import net.Broken.audio.Youtube.YoutubeTools;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@ -21,6 +24,8 @@ public class TrackScheduler extends AudioEventAdapter {
|
||||
private final AudioPlayer player;
|
||||
private final BlockingDeque<UserAudioTrack> queue;
|
||||
private UserAudioTrack currentPlayingTrack;
|
||||
private boolean autoFlow = false;
|
||||
private ArrayList<String> history = new ArrayList<>();
|
||||
Logger logger = LogManager.getLogger();
|
||||
|
||||
/**
|
||||
@ -42,12 +47,23 @@ public class TrackScheduler extends AudioEventAdapter {
|
||||
// Calling startTrack with the noInterrupt set to true will start the track only if nothing is currently playing. If
|
||||
// something is playing, it returns false and does nothing. In that case the player was already playing so this
|
||||
// track goes to the queue instead.
|
||||
if(track.getSubmittedUser() != MainBot.jda.getSelfUser()){
|
||||
logger.debug("Flush history");
|
||||
history = new ArrayList<>();
|
||||
}
|
||||
|
||||
history.add(track.getAudioTrack().getIdentifier());
|
||||
if (!player.startTrack(track.getAudioTrack(), true)) {
|
||||
queue.offer(track);
|
||||
}
|
||||
else{
|
||||
currentPlayingTrack = track;
|
||||
}
|
||||
if(track.getSubmittedUser() != MainBot.jda.getSelfUser()) {
|
||||
needAutoPlay();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -58,15 +74,23 @@ public class TrackScheduler extends AudioEventAdapter {
|
||||
// Calling startTrack with the noInterrupt set to true will start the track only if nothing is currently playing. If
|
||||
// something is playing, it returns false and does nothing. In that case the player was already playing so this
|
||||
// track goes to the queue instead.
|
||||
if(track.getSubmittedUser() != MainBot.jda.getSelfUser()){
|
||||
logger.debug("Flush history");
|
||||
history = new ArrayList<>();
|
||||
}
|
||||
|
||||
history.add(track.getAudioTrack().getIdentifier());
|
||||
if (!player.startTrack(track.getAudioTrack(), true)) {
|
||||
queue.addFirst(track);
|
||||
}
|
||||
else{
|
||||
currentPlayingTrack = track;
|
||||
}
|
||||
if(track.getSubmittedUser() != MainBot.jda.getSelfUser()) {
|
||||
needAutoPlay();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void pause() {
|
||||
player.setPaused(true);
|
||||
}
|
||||
@ -76,7 +100,6 @@ public class TrackScheduler extends AudioEventAdapter {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void stop(){
|
||||
player.stopTrack();
|
||||
this.currentPlayingTrack = null;
|
||||
@ -115,11 +138,13 @@ public class TrackScheduler extends AudioEventAdapter {
|
||||
return false;
|
||||
} else {
|
||||
logger.info("Delete succeful");
|
||||
needAutoPlay();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.info("Delete failure! Not found.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -130,9 +155,11 @@ public class TrackScheduler extends AudioEventAdapter {
|
||||
// Start the next track, regardless of if something is already playing or not. In case queue was empty, we are
|
||||
// giving null to startTrack, which is a valid argument and will simply stop the player.
|
||||
UserAudioTrack track = queue.poll();
|
||||
this.currentPlayingTrack = track;
|
||||
if(track != null)
|
||||
this.currentPlayingTrack = track;
|
||||
if(track != null)
|
||||
player.startTrack(track.getAudioTrack(), false);
|
||||
needAutoPlay();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -140,8 +167,35 @@ public class TrackScheduler extends AudioEventAdapter {
|
||||
// Only start the next track if the end reason is suitable for it (FINISHED or LOAD_FAILED)
|
||||
if (endReason.mayStartNext) {
|
||||
nextTrack();
|
||||
needAutoPlay();
|
||||
}
|
||||
}
|
||||
|
||||
private void needAutoPlay(){
|
||||
if((queue.size() < 1) && autoFlow && currentPlayingTrack != null){
|
||||
logger.info("Auto add needed!");
|
||||
AudioM audioM = AudioM.getInstance(null);
|
||||
YoutubeTools youtubeTools = YoutubeTools.getInstance(null);
|
||||
try {
|
||||
String id = youtubeTools.getRelatedVideo(currentPlayingTrack.getAudioTrack().getInfo().identifier, history);
|
||||
logger.info("Related id: "+id);
|
||||
audioM.loadAndPlayAuto(id);
|
||||
|
||||
} catch (GoogleJsonResponseException e) {
|
||||
logger.error("There was a service error: " + e.getDetails().getCode() + " : " + e.getDetails().getMessage());
|
||||
} catch (Throwable t) {
|
||||
logger.catching(t);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void setAutoFlow(boolean autoFlow) {
|
||||
this.autoFlow = autoFlow;
|
||||
needAutoPlay();
|
||||
}
|
||||
|
||||
public boolean isAutoFlow() {
|
||||
return autoFlow;
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ public class WebLoadUtils {
|
||||
AudioPlayerManager playerM = musicCommand.getAudioManager().getPlayerManager();
|
||||
try {
|
||||
|
||||
AudioM audioM = musicCommand.getAudioManager();
|
||||
AudioM audioM = AudioM.getInstance(null);
|
||||
playerM.loadItemOrdered(musicCommand.getAudioManager().getGuildMusicManager(), data.url, new AudioLoadResultHandler() {
|
||||
@Override
|
||||
public void trackLoaded(AudioTrack track) {
|
||||
|
41
src/main/java/net/Broken/audio/Youtube/Authorization.java
Normal file
41
src/main/java/net/Broken/audio/Youtube/Authorization.java
Normal file
@ -0,0 +1,41 @@
|
||||
package net.Broken.audio.Youtube;
|
||||
|
||||
import com.google.api.client.auth.oauth2.AuthorizationCodeFlow;
|
||||
import com.google.api.client.auth.oauth2.AuthorizationCodeRequestUrl;
|
||||
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
|
||||
import com.google.api.client.extensions.java6.auth.oauth2.VerificationCodeReceiver;
|
||||
import com.google.api.client.util.Preconditions;
|
||||
import net.Broken.Tools.PrivateMessage;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class Authorization extends AuthorizationCodeInstalledApp {
|
||||
|
||||
private Guild guild;
|
||||
private Logger logger = LogManager.getLogger();
|
||||
|
||||
/**
|
||||
* @param flow authorization code flow
|
||||
* @param receiver verification code receiver
|
||||
*/
|
||||
public Authorization(AuthorizationCodeFlow flow, VerificationCodeReceiver receiver, Guild guild) {
|
||||
super(flow, receiver);
|
||||
this.guild = guild;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAuthorization(AuthorizationCodeRequestUrl authorizationUrl) throws IOException {
|
||||
notify(authorizationUrl.build());
|
||||
}
|
||||
|
||||
protected void notify(String url){
|
||||
Preconditions.checkNotNull(url);
|
||||
logger.fatal("Please open this URL: "+url);
|
||||
PrivateMessage.send(guild.getOwner().getUser(),"Please open this url to confirm google api account acces : " + url,null);
|
||||
|
||||
|
||||
}
|
||||
}
|
54
src/main/java/net/Broken/audio/Youtube/Receiver.java
Normal file
54
src/main/java/net/Broken/audio/Youtube/Receiver.java
Normal file
@ -0,0 +1,54 @@
|
||||
package net.Broken.audio.Youtube;
|
||||
|
||||
import com.google.api.client.extensions.java6.auth.oauth2.AbstractPromptReceiver;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class Receiver extends AbstractPromptReceiver {
|
||||
|
||||
private static Receiver INSTANCE;
|
||||
private Guild guild;
|
||||
private String code;
|
||||
|
||||
private Receiver(Guild guild){
|
||||
this.guild = guild;
|
||||
}
|
||||
|
||||
public static Receiver getInstance(Guild guild){
|
||||
if(INSTANCE == null)
|
||||
INSTANCE = new Receiver(guild);
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getRedirectUri() throws IOException {
|
||||
return System.getenv("SITE_URL") + "/youtube/callback/";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String waitForCode() {
|
||||
if(System.getenv("SITE_URL").isEmpty()){
|
||||
LogManager.getLogger().fatal("Please set \"SITE_URL\" environment variable and restart the bot!");
|
||||
}
|
||||
while(code == null){
|
||||
try {
|
||||
Thread.sleep(50);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
}
|
143
src/main/java/net/Broken/audio/Youtube/YoutubeTools.java
Normal file
143
src/main/java/net/Broken/audio/Youtube/YoutubeTools.java
Normal file
@ -0,0 +1,143 @@
|
||||
package net.Broken.audio.Youtube;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
|
||||
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
|
||||
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
|
||||
import com.google.api.client.http.HttpTransport;
|
||||
import com.google.api.client.json.JsonFactory;
|
||||
import com.google.api.client.json.jackson2.JacksonFactory;
|
||||
import com.google.api.client.util.store.FileDataStoreFactory;
|
||||
import com.google.api.services.youtube.YouTube;
|
||||
import com.google.api.services.youtube.YouTubeScopes;
|
||||
import com.google.api.services.youtube.model.SearchListResponse;
|
||||
import com.google.api.services.youtube.model.SearchResult;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
public class YoutubeTools {
|
||||
/** Application name. */
|
||||
private final String APPLICATION_NAME = "Discord Bot";
|
||||
|
||||
/** Directory to store user credentials for this application. */
|
||||
private final File DATA_STORE_DIR = new File(".credentials/java-youtube-api");
|
||||
private final File CLIENT_SECRET_DIR = new File(".credentials/client_secret.json");
|
||||
|
||||
/** Global instance of the {@link FileDataStoreFactory}. */
|
||||
private FileDataStoreFactory DATA_STORE_FACTORY;
|
||||
|
||||
/** Global instance of the JSON factory. */
|
||||
private final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
|
||||
|
||||
/** Global instance of the HTTP transport. */
|
||||
private HttpTransport HTTP_TRANSPORT;
|
||||
|
||||
private Logger logger = LogManager.getLogger();
|
||||
|
||||
private Guild guild;
|
||||
|
||||
/** Global instance of the scopes required by this quickstart.
|
||||
*
|
||||
* If modifying these scopes, delete your previously saved credentials
|
||||
* at ~/.credentials/drive-java-quickstart
|
||||
*/
|
||||
private final Collection<String> SCOPES = Arrays.asList(YouTubeScopes.YOUTUBEPARTNER, YouTubeScopes.YOUTUBE_FORCE_SSL);
|
||||
|
||||
private static YoutubeTools INSTANCE ;
|
||||
|
||||
private YoutubeTools(Guild guild){
|
||||
|
||||
try {
|
||||
HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
|
||||
DATA_STORE_FACTORY = new FileDataStoreFactory(DATA_STORE_DIR);
|
||||
} catch (Throwable t) {
|
||||
logger.catching(t);
|
||||
}
|
||||
this.guild = guild;
|
||||
}
|
||||
|
||||
public static YoutubeTools getInstance(Guild guild){
|
||||
if(INSTANCE == null)
|
||||
INSTANCE = new YoutubeTools(guild);
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates an authorized Credential object.
|
||||
* @return an authorized Credential object.
|
||||
* @throws IOException
|
||||
*/
|
||||
private Credential authorize() throws IOException {
|
||||
// Load client secrets.
|
||||
InputStream in = new FileInputStream(CLIENT_SECRET_DIR);
|
||||
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader( in ));
|
||||
|
||||
|
||||
// Build flow and trigger user authorization request.
|
||||
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
|
||||
HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
|
||||
.setDataStoreFactory(DATA_STORE_FACTORY)
|
||||
.setAccessType("online")
|
||||
.build();
|
||||
|
||||
|
||||
|
||||
Credential credential = new Authorization(flow, Receiver.getInstance(null), guild).authorize("user");
|
||||
logger.debug("Credentials saved to " + DATA_STORE_DIR.getAbsolutePath());
|
||||
return credential;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and return an authorized API client service, such as a YouTube
|
||||
* Data API client service.
|
||||
* @return an authorized API client service
|
||||
* @throws IOException
|
||||
*/
|
||||
public YouTube getYouTubeService() throws IOException {
|
||||
Credential credential = authorize();
|
||||
return new YouTube.Builder(
|
||||
HTTP_TRANSPORT, JSON_FACTORY, credential)
|
||||
.setApplicationName(APPLICATION_NAME)
|
||||
.build();
|
||||
}
|
||||
|
||||
public String getRelatedVideo(String videoId, ArrayList<String> history) throws IOException, GoogleJsonResponseException, Throwable {
|
||||
|
||||
YouTube youtube = getYouTubeService();
|
||||
|
||||
HashMap<String, String> parameters = new HashMap<>();
|
||||
parameters.put("part", "snippet");
|
||||
parameters.put("relatedToVideoId", videoId);
|
||||
parameters.put("type", "video");
|
||||
|
||||
YouTube.Search.List searchListRelatedVideosRequest = youtube.search().list(parameters.get("part"));
|
||||
if (parameters.containsKey("relatedToVideoId") && parameters.get("relatedToVideoId") != "") {
|
||||
searchListRelatedVideosRequest.setRelatedToVideoId(parameters.get("relatedToVideoId"));
|
||||
}
|
||||
|
||||
if (parameters.containsKey("type") && !parameters.get("type").equals("")) {
|
||||
searchListRelatedVideosRequest.setType(parameters.get("type"));
|
||||
}
|
||||
|
||||
SearchListResponse response = searchListRelatedVideosRequest.execute();
|
||||
|
||||
for(SearchResult item : response.getItems()){
|
||||
if(!history.contains(item.getId().getVideoId())){
|
||||
return item.getId().getVideoId();
|
||||
}
|
||||
else
|
||||
logger.debug("ID already on history");
|
||||
}
|
||||
|
||||
logger.debug("All on history ?");
|
||||
return response.getItems().get(0).getId().getVideoId();
|
||||
|
||||
}
|
||||
}
|
12
src/main/java/net/Broken/webView/CheckPage.java
Normal file
12
src/main/java/net/Broken/webView/CheckPage.java
Normal file
@ -0,0 +1,12 @@
|
||||
package net.Broken.webView;
|
||||
|
||||
import net.Broken.MainBot;
|
||||
|
||||
public class CheckPage {
|
||||
public static String getPageIfReady(String page){
|
||||
if(MainBot.ready)
|
||||
return page;
|
||||
else
|
||||
return "loading";
|
||||
}
|
||||
}
|
@ -11,6 +11,11 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
public class GeneralWebView {
|
||||
@RequestMapping("/")
|
||||
public String music(Model model){
|
||||
return "index";
|
||||
|
||||
return CheckPage.getPageIfReady("index");
|
||||
}
|
||||
@RequestMapping("/loading")
|
||||
public String loading(Model model){
|
||||
return "loading";
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
public class MusicWebView {
|
||||
@RequestMapping("/music")
|
||||
public String music(Model model){
|
||||
return "music";
|
||||
return CheckPage.getPageIfReady("music");
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,6 @@ public class RegisterWebView {
|
||||
@RequestMapping("/register")
|
||||
public String music(@RequestParam(value="id", required = true, defaultValue = "") String id, Model model){
|
||||
model.addAttribute("id", id);
|
||||
return "register";
|
||||
return CheckPage.getPageIfReady("register");
|
||||
}
|
||||
}
|
||||
|
24
src/main/java/net/Broken/webView/YoutubeCallBack.java
Normal file
24
src/main/java/net/Broken/webView/YoutubeCallBack.java
Normal file
@ -0,0 +1,24 @@
|
||||
package net.Broken.webView;
|
||||
|
||||
|
||||
import net.Broken.audio.Youtube.Receiver;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
@Controller
|
||||
public class YoutubeCallBack {
|
||||
@RequestMapping("/youtube/callback")
|
||||
public String callback(@RequestParam(value="error", required = false, defaultValue = "") String error,
|
||||
@RequestParam(value = "code", required = false, defaultValue = "") String code,
|
||||
Model model){
|
||||
model.addAttribute("error", error);
|
||||
model.addAttribute("code", code);
|
||||
if(!code.equals("")){
|
||||
Receiver.getInstance(null).setCode(code);
|
||||
}
|
||||
|
||||
return "youtubeCallBack";
|
||||
}
|
||||
}
|
@ -25,8 +25,12 @@
|
||||
</File>
|
||||
</Appenders>
|
||||
<Loggers>
|
||||
<Logger name="net.Broken" level="trace" additivity="false">
|
||||
<AppenderRef ref="Console"/>
|
||||
<AppenderRef ref="current"/>
|
||||
<AppenderRef ref="RollingFile"/>
|
||||
</Logger>
|
||||
<Root level="debug">
|
||||
<AppenderRef ref="RollingFile" level="info" />
|
||||
<AppenderRef ref="Console" level="info"/>
|
||||
<AppenderRef ref="RollingFile" level="info"/>
|
||||
<AppenderRef ref="current" level="info"/>
|
||||
|
153
src/main/resources/static/error/404.html
Normal file
153
src/main/resources/static/error/404.html
Normal file
@ -0,0 +1,153 @@
|
||||
<!DOCTYPE html>
|
||||
<html >
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0"/>
|
||||
<title>Music Control - Discord Bot</title>
|
||||
<link rel="icon"
|
||||
type="image/x-icon"
|
||||
href="favicon.png"/>
|
||||
|
||||
<!-- CSS -->
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"/>
|
||||
<link href="css/materialize.css" type="text/css" rel="stylesheet" media="screen,projection"/>
|
||||
<link href="css/style.css" type="text/css" rel="stylesheet" media="screen,projection"/>
|
||||
</head>
|
||||
|
||||
<body class="blue-grey lighten-5" >
|
||||
|
||||
<!--__________________________________________________________-->
|
||||
<!-- NAV BAR -->
|
||||
<!-- AND -->
|
||||
<!-- LOGIN -->
|
||||
<!--__________________________________________________________-->
|
||||
<nav class="blue-grey darken-4 z-depth-3" role="navigation">
|
||||
<div class="nav-wrapper container">
|
||||
<a id="logo-container" href="/" class="brand-logo">Discord Bot</a>
|
||||
<ul class="right hide-on-med-and-down">
|
||||
|
||||
<li >
|
||||
<a class="waves-effect waves-light sidenav-trigger" href="/" data-target="slide-out">Home</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="waves-effect waves-light" href="/music" >Music Control</a>
|
||||
</li>
|
||||
<li id="nav-bar-account">
|
||||
<a class="dropdown-account" data-activates="dropdown1"><i class="material-icons">account_box</i></a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<ul id="nav-mobile" class="side-nav">
|
||||
<li class="active">
|
||||
<a class="waves-effect waves-light sidenav-trigger" href="/" data-target="slide-out">Home</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="waves-effect waves-light sidenav-trigger" href="/music" data-target="slide-out" >Music Control</a>
|
||||
</li>
|
||||
|
||||
<!--TODO Connection mobile-->
|
||||
</ul>
|
||||
<a href="#" data-activates="nav-mobile" class="button-navbar-mobile button-collapse"><i class="material-icons">menu</i></a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- Dropdown connected -->
|
||||
<ul id="dropdown_connected" class="dropdown-content ">
|
||||
<li>
|
||||
<a class="center blue-grey-text text-darken-4" id="nav-name" style="text-decoration: underline; font-weight: bold"></a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li>
|
||||
<a class="center tooltipped" data-position="left" data-delay="50" data-tooltip="Under Development!">My Account</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="center tooltipped" data-position="left" data-delay="50" data-tooltip="Under Development!">My Playlists</a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li><a class="center red-text" id="nav-disconnect" style="font-weight: bold">Disconnect</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<!--________________________________________-->
|
||||
<!-- Connection modal -->
|
||||
<!--________________________________________-->
|
||||
<div id="modal_connection" class="modal">
|
||||
<div class="modal-content">
|
||||
<div class="row center">
|
||||
<div class="col s12">
|
||||
<h3 class="" style="font-weight: bold">Sign in</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row center" style="margin-bottom: 0px">
|
||||
<form name="login_form" id="login_form" action="javascript:void(0);" onsubmit="tryConnection()">
|
||||
<div class="row" style="margin-bottom: 0px">
|
||||
<div class="input-field col s6 offset-s3">
|
||||
<i class="material-icons prefix">account_box</i>
|
||||
<input name="username" id="user_input" type="text" class="validate"/>
|
||||
<label for="user_input" data-error="User not registered!">User Name</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="input-field col s6 offset-s3">
|
||||
<i class="material-icons prefix">security</i>
|
||||
<input name="password" id="password_input" type="password" class="validate"/>
|
||||
<label for="password_input" data-error="Wrong password!">Password</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" style="margin-bottom: 10px">
|
||||
<button id="btn-submit-connect" class="btn waves-effect waves-light light-green darken-1 scale-transition scale-out" type="submit" name="action" >
|
||||
Submit<i class="material-icons right">send</i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<a class="btn waves-effect waves-light brown" href="/register">
|
||||
Create account<i class="material-icons right">person_add</i>
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!--__________________________________________________________-->
|
||||
<!-- -->
|
||||
<!-- END -->
|
||||
<!-- -->
|
||||
<!--__________________________________________________________-->
|
||||
|
||||
<div class="section no-pad-bot main" id="index-banner">
|
||||
|
||||
<div class="center row">
|
||||
<div class="row center valign-wrapper">
|
||||
<div class="col s6">
|
||||
<h1 class="red-text text-darken-2 "><b>Oops!</b></h1>
|
||||
<h2 class=" blue-grey-text "><b>Page not found!</b></h2>
|
||||
<a class="btn btn-large light-green darken-3 waves-effect" href="/">
|
||||
<i class="large material-icons">home</i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col s6">
|
||||
<img class="" src="/img/404.gif" style="border:none;outline: none">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Scripts-->
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.js"
|
||||
integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
|
||||
crossorigin="anonymous"></script>
|
||||
|
||||
<script src="/js/materialize.js"></script>
|
||||
<script src="/js/navabar.js"></script>
|
||||
<script src="/js/js.cookie.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
BIN
src/main/resources/static/img/404.gif
Normal file
BIN
src/main/resources/static/img/404.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.9 MiB |
18
src/main/resources/static/js/loading.js
Normal file
18
src/main/resources/static/js/loading.js
Normal file
@ -0,0 +1,18 @@
|
||||
$(document).ready(function () {
|
||||
setInterval("loop()",1000);
|
||||
});
|
||||
|
||||
function loop() {
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "/api/isReady",
|
||||
success: function (data) {
|
||||
console.log("Ready");
|
||||
debugger;
|
||||
location.reload();
|
||||
}
|
||||
|
||||
}).fail(function (data) {
|
||||
console.log("Not ready");
|
||||
});
|
||||
}
|
@ -10,7 +10,8 @@ var btn_info;
|
||||
var btn_disconnect;
|
||||
var btn_flush;
|
||||
var btn_add;
|
||||
|
||||
var switchAutoFlow;
|
||||
var loadingFlag = false;
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
@ -21,7 +22,7 @@ $(document).ready(function() {
|
||||
btn_disconnect = $('#btn_disconnect');
|
||||
btn_flush = $('#flush_btn');
|
||||
btn_add = $('#add_btn');
|
||||
|
||||
switchAutoFlow = $("#autoflow");
|
||||
|
||||
setInterval("getCurentMusic()",1000);
|
||||
$('#modalAdd').modal();
|
||||
@ -160,7 +161,10 @@ function getCurentMusic() {
|
||||
|
||||
break;
|
||||
}
|
||||
if(switchAutoFlow.is(':checked') != data.autoflow)
|
||||
switchAutoFlow.prop('checked', data.autoflow);
|
||||
getPlayList();
|
||||
|
||||
})
|
||||
.fail(function (data) {
|
||||
if(!error){
|
||||
@ -177,7 +181,7 @@ function getPlayList() {
|
||||
data = data.list;
|
||||
if(data != null && data.length != 0){
|
||||
var noUpdate = comparePlaylist(data, savedPlaylist);
|
||||
|
||||
// console.log("List up to date : "+noUpdate);
|
||||
if(!noUpdate){
|
||||
savedPlaylist = data;
|
||||
$('#playlist_list').empty();
|
||||
@ -208,13 +212,25 @@ function getPlayList() {
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
else{
|
||||
$('#playlist_list').empty();
|
||||
savedPlaylist = {};
|
||||
}
|
||||
if(loadingFlag){
|
||||
modal_loading.modal('close');
|
||||
loadingFlag = false;
|
||||
}
|
||||
|
||||
|
||||
}).fail(function (data) {
|
||||
if(!error){
|
||||
alert("Comunication error, please refresh.");
|
||||
error = true;
|
||||
}
|
||||
if(loadingFlag){
|
||||
modal_loading.modal('close');
|
||||
loadingFlag = false;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@ -249,7 +265,7 @@ function getChannels(){
|
||||
|
||||
function updateModal(data){
|
||||
$('#modal_title').text("Title: "+ data.info.audioTrackInfo.title);
|
||||
$('#modal_author').text("Author: "+ data.info.author);
|
||||
$('#modal_author').text("Author: "+ data.info.audioTrackInfo.author);
|
||||
$('#modal_lenght').text("Duration: "+ msToTime(data.info.audioTrackInfo.length));
|
||||
$('#modal_url').text("URL: "+ data.info.audioTrackInfo.uri);
|
||||
$('#modal_submit').text("Submitted by: "+ data.info.user);
|
||||
@ -307,8 +323,9 @@ function sendCommand(command){
|
||||
data: JSON.stringify(command),
|
||||
success: function (data) {
|
||||
console.log(data);
|
||||
loadingFlag = true;
|
||||
getCurentMusic();
|
||||
modal_loading.modal('close');
|
||||
|
||||
}
|
||||
|
||||
}).fail(function (data) {
|
||||
@ -437,6 +454,15 @@ function listeners() {
|
||||
$('#btn_disconnect').click(function () {
|
||||
sendCommand({command : "DISCONNECT"})
|
||||
});
|
||||
|
||||
switchAutoFlow.click(function () {
|
||||
console.log(switchAutoFlow.is(':checked'))
|
||||
if(switchAutoFlow.is(':checked')){
|
||||
sendCommand({command: 'AUTOFLOWON'})
|
||||
}
|
||||
else
|
||||
sendCommand({command: 'AUTOFLOWOFF'})
|
||||
});
|
||||
}
|
||||
|
||||
function disableBtn(btn) {
|
||||
|
@ -124,8 +124,9 @@
|
||||
</div>
|
||||
|
||||
<!-- Scripts-->
|
||||
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.js"
|
||||
integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
|
||||
crossorigin="anonymous"></script>
|
||||
<script th:src="@{/js/materialize.js}"></script>
|
||||
<script th:src="@{/js/navabar.js}"></script>
|
||||
<script th:src="@{/js/js.cookie.js}"></script>
|
||||
|
79
src/main/resources/templates/loading.html
Normal file
79
src/main/resources/templates/loading.html
Normal file
@ -0,0 +1,79 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0"/>
|
||||
<title>Music Control - Discord Bot</title>
|
||||
<link rel="icon"
|
||||
type="image/x-icon"
|
||||
href="/favicon.png"/>
|
||||
|
||||
<!-- CSS -->
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"/>
|
||||
<link href="css/materialize.css" type="text/css" rel="stylesheet" media="screen,projection"/>
|
||||
<link href="css/style.css" type="text/css" rel="stylesheet" media="screen,projection"/>
|
||||
</head>
|
||||
|
||||
<body class="blue-grey lighten-5" >
|
||||
|
||||
<!--__________________________________________________________-->
|
||||
<!-- NAV BAR -->
|
||||
<!-- AND -->
|
||||
<!-- LOGIN -->
|
||||
<!--__________________________________________________________-->
|
||||
<nav class="blue-grey darken-4 z-depth-3" role="navigation">
|
||||
<div class="nav-wrapper container">
|
||||
<a id="logo-container" href="/" class="brand-logo">Discord Bot</a>
|
||||
<ul class="right hide-on-med-and-down">
|
||||
|
||||
</ul>
|
||||
|
||||
<ul id="nav-mobile" class="side-nav">
|
||||
|
||||
</ul>
|
||||
<a href="#" data-activates="nav-mobile" class="button-navbar-mobile button-collapse"><i class="material-icons">menu</i></a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!--__________________________________________________________-->
|
||||
<!-- -->
|
||||
<!-- END -->
|
||||
<!-- -->
|
||||
<!--__________________________________________________________-->
|
||||
|
||||
<div class="section no-pad-bot main" id="index-banner">
|
||||
<div class="row center center-align">
|
||||
<h3 class="">Bot is starting</h3>
|
||||
</div>
|
||||
<div class="row center" >
|
||||
<div class="preloader-wrapper big active">
|
||||
<div class="spinner-layer spinner-blue-only">
|
||||
<div class="circle-clipper left">
|
||||
<div class="circle"></div>
|
||||
</div>
|
||||
<div class="gap-patch">
|
||||
<div class="circle"></div>
|
||||
</div>
|
||||
<div class="circle-clipper right">
|
||||
<div class="circle"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row center center-align">
|
||||
<h3>Please wait</h3>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Scripts-->
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.js"
|
||||
integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
|
||||
crossorigin="anonymous"></script>
|
||||
|
||||
<script th:src="@{/js/materialize.js}"></script>
|
||||
<script th:src="@{/js/loading.js}"></script>
|
||||
<script th:src="@{/js/js.cookie.js}"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -174,11 +174,11 @@
|
||||
<tr>
|
||||
<th style="padding: 0px;">
|
||||
<div class="row center valign-wrapper" style="margin: 0px">
|
||||
<div class="col s4 center"><h5>Playlist</h5></div>
|
||||
<div class="col s4 center">
|
||||
<div class="col s3 center blue-grey-text text-darken-3"><h5><b>Playlist</b></h5></div>
|
||||
<div class="col s3 center">
|
||||
<a class="waves-effect waves-light btn modal-trigger red darken-4" id="flush_btn"><i class="material-icons">delete_sweep</i></a>
|
||||
</div>
|
||||
<div class="col s4 center">
|
||||
<div class="col s3 center" style="padding-right: 0px">
|
||||
<!-- Modal Trigger -->
|
||||
<a class="waves-effect waves-light btn modal-trigger green darken-4" id="add_btn" href="#modalAdd"><i class="material-icons">add_circle_outline</i></a>
|
||||
|
||||
@ -215,6 +215,17 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col s3 center " style="padding-left: 0px">
|
||||
<div class="row switch blue-grey-text text-darken-3" style="margin-bottom: 0px">
|
||||
AutoFlow
|
||||
</div>
|
||||
<div class="row switch tooltipped" data-position="bottom" data-delay="50" data-tooltip="Experimental!">
|
||||
<label>
|
||||
<input type="checkbox" id="autoflow"/>
|
||||
<span class="lever"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</th>
|
||||
@ -360,7 +371,9 @@
|
||||
</p>
|
||||
|
||||
<!-- Scripts-->
|
||||
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.js"
|
||||
integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
|
||||
crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
var needLogin = true;
|
||||
|
@ -191,7 +191,9 @@
|
||||
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.js"
|
||||
integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
|
||||
crossorigin="anonymous"></script>
|
||||
<script th:src="@{/js/materialize.js}"></script>
|
||||
<script th:src="@{/js/register.js}"></script>
|
||||
<script th:src="@{/js/navabar.js}"></script>
|
||||
|
141
src/main/resources/templates/youtubeCallBack.html
Normal file
141
src/main/resources/templates/youtubeCallBack.html
Normal file
@ -0,0 +1,141 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0"/>
|
||||
<title>Music Control - Discord Bot</title>
|
||||
<link rel="icon"
|
||||
type="image/x-icon"
|
||||
href="/favicon.png"/>
|
||||
|
||||
<!-- CSS -->
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"/>
|
||||
<link href="/css/materialize.css" type="text/css" rel="stylesheet" media="screen,projection"/>
|
||||
<link href="/css/style.css" type="text/css" rel="stylesheet" media="screen,projection"/>
|
||||
</head>
|
||||
|
||||
<body class="blue-grey lighten-5" >
|
||||
|
||||
<!--__________________________________________________________-->
|
||||
<!-- NAV BAR -->
|
||||
<!-- AND -->
|
||||
<!-- LOGIN -->
|
||||
<!--__________________________________________________________-->
|
||||
<nav class="blue-grey darken-4 z-depth-3" role="navigation">
|
||||
<div class="nav-wrapper container">
|
||||
<a id="logo-container" href="/" class="brand-logo">Discord Bot</a>
|
||||
<ul class="right hide-on-med-and-down">
|
||||
|
||||
<li >
|
||||
<a class="waves-effect waves-light sidenav-trigger" href="/" data-target="slide-out">Home</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="waves-effect waves-light" href="/music" >Music Control</a>
|
||||
</li>
|
||||
<li id="nav-bar-account">
|
||||
<a class="dropdown-account" data-activates="dropdown1"><i class="material-icons">account_box</i></a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<ul id="nav-mobile" class="side-nav">
|
||||
<li class="active">
|
||||
<a class="waves-effect waves-light sidenav-trigger" href="/" data-target="slide-out">Home</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="waves-effect waves-light sidenav-trigger" href="/music" data-target="slide-out" >Music Control</a>
|
||||
</li>
|
||||
|
||||
<!--TODO Connection mobile-->
|
||||
</ul>
|
||||
<a href="#" data-activates="nav-mobile" class="button-navbar-mobile button-collapse"><i class="material-icons">menu</i></a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- Dropdown connected -->
|
||||
<ul id="dropdown_connected" class="dropdown-content ">
|
||||
<li>
|
||||
<a class="center blue-grey-text text-darken-4" id="nav-name" style="text-decoration: underline; font-weight: bold"></a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li>
|
||||
<a class="center tooltipped" data-position="left" data-delay="50" data-tooltip="Under Development!">My Account</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="center tooltipped" data-position="left" data-delay="50" data-tooltip="Under Development!">My Playlists</a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li><a class="center red-text" id="nav-disconnect" style="font-weight: bold">Disconnect</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<!--________________________________________-->
|
||||
<!-- Connection modal -->
|
||||
<!--________________________________________-->
|
||||
<div id="modal_connection" class="modal">
|
||||
<div class="modal-content">
|
||||
<div class="row center">
|
||||
<div class="col s12">
|
||||
<h3 class="" style="font-weight: bold">Sign in</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row center" style="margin-bottom: 0px">
|
||||
<form name="login_form" id="login_form" action="javascript:void(0);" onsubmit="tryConnection()">
|
||||
<div class="row" style="margin-bottom: 0px">
|
||||
<div class="input-field col s6 offset-s3">
|
||||
<i class="material-icons prefix">account_box</i>
|
||||
<input name="username" id="user_input" type="text" class="validate"/>
|
||||
<label for="user_input" data-error="User not registered!">User Name</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="input-field col s6 offset-s3">
|
||||
<i class="material-icons prefix">security</i>
|
||||
<input name="password" id="password_input" type="password" class="validate"/>
|
||||
<label for="password_input" data-error="Wrong password!">Password</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" style="margin-bottom: 10px">
|
||||
<button id="btn-submit-connect" class="btn waves-effect waves-light light-green darken-1 scale-transition scale-out" type="submit" name="action" >
|
||||
Submit<i class="material-icons right">send</i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<a class="btn waves-effect waves-light brown" href="/register">
|
||||
Create account<i class="material-icons right">person_add</i>
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!--__________________________________________________________-->
|
||||
<!-- -->
|
||||
<!-- END -->
|
||||
<!-- -->
|
||||
<!--__________________________________________________________-->
|
||||
|
||||
<div class="section no-pad-bot main" id="index-banner">
|
||||
|
||||
<div class="center row">
|
||||
<div class="col s12">
|
||||
<h2 th:text="Succes" th:if="!${#strings.isEmpty(code)}"></h2>
|
||||
<h2 th:text="${error}" th:if="${#strings.isEmpty(code)}"></h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Scripts-->
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.js"
|
||||
integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
|
||||
crossorigin="anonymous"></script>
|
||||
|
||||
<script th:src="@{/js/materialize.js}"></script>
|
||||
<script th:src="@{/js/navabar.js}"></script>
|
||||
<script th:src="@{/js/js.cookie.js}"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user