From 1e6f91d238884839ab13c09030904511b98ef062 Mon Sep 17 00:00:00 2001 From: Donald Shan Date: Mon, 26 Dec 2022 16:01:18 -0800 Subject: Added changing Discord Status feature Discord status of the bot will now change based on what is playing --- src/main/java/Main.java | 65 ++---------------------- src/main/java/audio/GuildMusicManager.java | 7 +-- src/main/java/audio/Music.java | 79 ++++++++++++------------------ src/main/java/audio/TrackScheduler.java | 23 +++++++-- src/main/java/utility/SpotifyAPI.java | 31 ++++++------ src/main/java/utility/StatusHandler.java | 41 ++++++++++++++++ src/main/java/utility/YouTubeAPI.java | 6 ++- 7 files changed, 118 insertions(+), 134 deletions(-) create mode 100644 src/main/java/utility/StatusHandler.java diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 30983d9..8154037 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,67 +1,22 @@ import audio.Music; -import commands.CommandManager; -import net.dv8tion.jda.api.JDA; -import net.dv8tion.jda.api.JDABuilder; -import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.events.ReadyEvent; -import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; -import net.dv8tion.jda.api.interactions.commands.OptionType; -import net.dv8tion.jda.api.interactions.commands.build.CommandData; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; - -import javax.security.auth.login.LoginException; +import utility.StatusHandler; import java.io.FileReader; - public class Main extends ListenerAdapter { - public static JDABuilder jdabuilder = JDABuilder.createDefault(readSetting("discordToken")).addEventListeners(new Main()); - public static JDA jda; + public static StatusHandler statusHandler; + + - public static Music musicPlayer = new Music("$",readSetting("youtubeApi")); public static void main( String[] args) { - try { - jdabuilder.addEventListeners(musicPlayer); - jdabuilder.addEventListeners(new CommandManager(musicPlayer)); - jda = jdabuilder.build(); - setSlashCommands(); - System.out.println("Bot Started"); - } catch (LoginException e) { - throw new RuntimeException(e); - } + new Music("$",readSetting("youtubeApi"),readSetting("discordToken")); } - - public static void setSlashCommands(){ - // jda.updateCommands().queue(); - jda.upsertCommand(new CommandData("play","Adds a song to the queue with a URL or search terms"). - addOption(OptionType.STRING,"term","The link or search terms of the music to queue") - ).queue(); - jda.upsertCommand(new CommandData("queue-recursive","Adds a set amount of random songs from a playlist"). - addOption(OptionType.STRING,"url","The link of the playlist") - .addOption(OptionType.INTEGER,"amount","The amount of songs to queue") - ).queue(); - jda.upsertCommand(new CommandData("leave","Clears the queue and disconnects the bot from voice channel")).queue(); - jda.upsertCommand(new CommandData("showqueue","Shows the current queue")).queue(); - jda.upsertCommand(new CommandData("pause","Pauses the player")).queue(); - jda.upsertCommand(new CommandData("controls","Show an interface to control the player")).queue(); - jda.upsertCommand(new CommandData("skip","Skips the current song")).queue(); - jda.upsertCommand(new CommandData("nowplaying","Shows a detailed view of the current song playing")).queue(); - jda.upsertCommand(new CommandData("stop","Stops the player and clears the queue")).queue(); - jda.upsertCommand(new CommandData("remove","Remove a track in queue")).queue(); - jda.upsertCommand(new CommandData("shuffle","Shuffle the current queue")).queue(); - jda.upsertCommand(new CommandData("vtmusic","Queues a set number of random VTuber songs and covers"). - addOption(OptionType.INTEGER,"number","Number of songs to queue") - ).queue(); - jda.upsertCommand(new CommandData("volume","Set the volume or leave blank to check current volume"). - addOption(OptionType.INTEGER,"volume","Volume from 0-100") - ).queue(); - - - } public static String readSetting(String parameter){ Object obj = null; try { @@ -73,16 +28,6 @@ public class Main extends ListenerAdapter { return (String) jo.get(parameter); } - @Override - public void onMessageReceived(MessageReceivedEvent e) { - JDA jda = e.getJDA(); - Message message = e.getMessage(); - String msg = message.getContentDisplay(); - if(msg.startsWith("!maintenance") && e.getAuthor().getId().equals("246787839570739211")){ - jda.getPresence().setActivity(net.dv8tion.jda.api.entities.Activity.watching("Maintenance Mode!")); - } - - } @Override public void onReady(ReadyEvent event) { diff --git a/src/main/java/audio/GuildMusicManager.java b/src/main/java/audio/GuildMusicManager.java index 0757422..5a9adb7 100644 --- a/src/main/java/audio/GuildMusicManager.java +++ b/src/main/java/audio/GuildMusicManager.java @@ -1,14 +1,15 @@ package audio; import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; +import net.dv8tion.jda.api.JDA; + public class GuildMusicManager { public final AudioPlayer player; - public final TrackScheduler scheduler; - public GuildMusicManager(AudioPlayerManager manager) { + public GuildMusicManager(AudioPlayerManager manager, JDA jda) { player = manager.createPlayer(); - scheduler = new TrackScheduler(player); + scheduler = new TrackScheduler(player,jda); player.addListener(scheduler); } diff --git a/src/main/java/audio/Music.java b/src/main/java/audio/Music.java index 26c7773..afca6f2 100644 --- a/src/main/java/audio/Music.java +++ b/src/main/java/audio/Music.java @@ -8,9 +8,13 @@ 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 commands.CommandManager; import commands.UIPusher; import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.JDABuilder; import net.dv8tion.jda.api.MessageBuilder; +import net.dv8tion.jda.api.entities.Activity; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.TextChannel; import net.dv8tion.jda.api.entities.VoiceChannel; @@ -24,10 +28,8 @@ import net.dv8tion.jda.api.interactions.components.selections.SelectionMenu; import net.dv8tion.jda.api.managers.AudioManager; import org.jetbrains.annotations.NotNull; import se.michaelthelin.spotify.model_objects.specification.PlaylistTrack; -import utility.EmbedMaker; -import utility.SpotifyAPI; -import utility.URLChecker; -import utility.YouTubeAPI; +import utility.*; +import javax.security.auth.login.LoginException; import java.awt.*; import java.io.*; import java.net.MalformedURLException; @@ -38,21 +40,39 @@ import java.util.*; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; + public class Music extends ListenerAdapter { - ArrayList currentlyLoadedPlaylist = new ArrayList<>(); - String ytapiKey; + public static JDA jda; + public static JDABuilder jdabuilder; + private ArrayList currentlyLoadedPlaylist = new ArrayList<>(); + private String ytapiKey; static String append = "$"; private final URLChecker urlCheck = new URLChecker(); - UIPusher uiPusher = new UIPusher(); + private StatusHandler statusHandler; + private UIPusher uiPusher = new UIPusher(); private final AudioPlayerManager playerManager; private final Map musicManagers; private final SpotifyAPI spotifyAPI = new SpotifyAPI(); private final EmbedMaker embedMaker = new EmbedMaker(); - public Music(String append, String ytapiKey) { + + public Music(String append, String ytapiKey, String discordToken) { this.musicManagers = new HashMap<>(); this.ytapiKey = ytapiKey; Music.append = append; this.playerManager = new DefaultAudioPlayerManager(); + jdabuilder = JDABuilder.createDefault(discordToken); + try { + jdabuilder.addEventListeners(this); + jdabuilder.addEventListeners(new CommandManager(this)); + jda = jdabuilder.build(); + statusHandler = new StatusHandler(jda); + statusHandler.setSlashCommands(); + System.out.println("Bot Started"); + } catch (LoginException e) { + throw new RuntimeException(e); + } + + //Registering audio sources AudioSourceManagers.registerRemoteSources(playerManager); AudioSourceManagers.registerLocalSource(playerManager); } @@ -61,7 +81,7 @@ public class Music extends ListenerAdapter { GuildMusicManager musicManager = musicManagers.get(guildId); if (musicManager == null) { - musicManager = new GuildMusicManager(playerManager); + musicManager = new GuildMusicManager(playerManager,jda); musicManagers.put(guildId, musicManager); } guild.getAudioManager().setSendingHandler(musicManager.getSendHandler()); @@ -126,15 +146,6 @@ public class Music extends ListenerAdapter { if((append+"holoadd").equals(command[0])){ event.getChannel().sendMessage("The url has been successfully added to the database").queue(); } - /* else if("!dev".equals(command[0])){ - try { - YouTubeAPI youTubeAPI = new YouTubeAPI(ytapiKey); - youTubeAPI.getAllURLPlaylist("PLQmVFdwvZgfXlb2RDXWV1NaPXgYPu786G"); - } - catch (Exception e){ - - } - }*/ super.onGuildMessageReceived(event); } @@ -205,6 +216,7 @@ public class Music extends ListenerAdapter { String userQuery = event.getOption("term").getAsString(); if (urlCheck.isURL(userQuery) && !urlCheck.getURLType(userQuery).equals("spotify")&&!urlCheck.getURLType(userQuery).equals("spotify-playlist")) { //The term is a URL event.reply("Found Video: " + userQuery).queue(); + loadAndPlay((TextChannel) event.getChannel(), userQuery, false); } else { //Run checks if its not a directly playable URL @@ -415,31 +427,6 @@ public class Music extends ListenerAdapter { } } - else if(event.getValues().get(0).contains("inspect-queue")) { //THIS FEAUTURE IS NOT FINISHED - //TODO: FINISH THE INSPECT QUEUE FEATURE - Queue queue = getGuildAudioPlayer(event.getGuild()).scheduler.queue; - BlockingQueue newQueue = new LinkedBlockingQueue<>(); - String trackName = event.getValues().get(0).replaceAll("inspect-queue ", ""); - synchronized (queue) { - if (queue.isEmpty()) - { - event.reply("The queue is currently empty!").queue(); - - } - else { - for (AudioTrack track : queue) { - if (!track.getInfo().title.equals(trackName)) { - newQueue.add(track); - } - else{ - - } - } - getGuildAudioPlayer(event.getGuild()).scheduler.queue = newQueue; - } - - } - } } @Override public void onButtonClick(ButtonClickEvent event){ @@ -518,6 +505,7 @@ public class Music extends ListenerAdapter { } play(channel.getGuild(), musicManager, track); + } @Override @@ -530,7 +518,6 @@ public class Music extends ListenerAdapter { channel.sendMessage("Adding to queue " + firstTrack.getInfo().title + " (first track of playlist " + playlist.getName() + ")").queue(); } - play(channel.getGuild(), musicManager, firstTrack); } @@ -555,14 +542,11 @@ public class Music extends ListenerAdapter { private void play(Guild guild, GuildMusicManager musicManager, AudioTrack track) { connectToFirstVoiceChannel(guild.getAudioManager()); musicManager.scheduler.queue(track); - BlockingQueue s = musicManager.scheduler.queue; - } public void skipTrack(SlashCommandEvent event) { GuildMusicManager musicManager = getGuildAudioPlayer(event.getGuild()); musicManager.scheduler.nextTrack(); - event.reply("Skipped to next track.").queue(); } @@ -588,5 +572,4 @@ public class Music extends ListenerAdapter { - } diff --git a/src/main/java/audio/TrackScheduler.java b/src/main/java/audio/TrackScheduler.java index 8377e7a..02329c8 100644 --- a/src/main/java/audio/TrackScheduler.java +++ b/src/main/java/audio/TrackScheduler.java @@ -4,6 +4,8 @@ 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 net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.entities.Activity; import java.util.Collections; import java.util.List; @@ -16,12 +18,13 @@ import java.util.concurrent.LinkedBlockingQueue; public class TrackScheduler extends AudioEventAdapter { public final AudioPlayer player; public BlockingQueue queue; - + public JDA jda; /** * @param player The audio player this scheduler uses */ - public TrackScheduler(AudioPlayer player) { + public TrackScheduler(AudioPlayer player, JDA jda) { this.player = player; + this.jda = jda; this.queue = new LinkedBlockingQueue<>(); } @@ -31,24 +34,34 @@ public class TrackScheduler extends AudioEventAdapter { * @param track The track to play or add to queue. */ public void queue(AudioTrack track) { - if (!player.startTrack(track, true)) { + //!player.startTrack(track, true) + if (player.getPlayingTrack()!= null) { queue.offer(track); + jda.getPresence().setActivity(Activity.playing(player.getPlayingTrack().getInfo().title)); + } + else{ + player.startTrack(track, true); + jda.getPresence().setActivity(Activity.playing(player.getPlayingTrack().getInfo().title)); } + } /** * Start the next track, stopping the current one if it is playing. */ public void nextTrack() { - player.startTrack(queue.poll(), false); + jda.getPresence().setActivity(Activity.playing(player.getPlayingTrack().getInfo().title)); - } + } + //TODO: FIGURE OUT HOW TO CHANGE THE STATUS AT THIS PART @Override public void onTrackEnd(AudioPlayer player, AudioTrack track, AudioTrackEndReason endReason) { // Only start the next track if the end reason is suitable for it (FINISHED or LOAD_FAILED) + jda.getPresence().setActivity(null); if (endReason.mayStartNext) { + jda.getPresence().setActivity(Activity.playing(track.getInfo().title)); nextTrack(); } } diff --git a/src/main/java/utility/SpotifyAPI.java b/src/main/java/utility/SpotifyAPI.java index b4bcac1..4eb4d6e 100644 --- a/src/main/java/utility/SpotifyAPI.java +++ b/src/main/java/utility/SpotifyAPI.java @@ -1,5 +1,4 @@ package utility; - import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import se.michaelthelin.spotify.SpotifyApi; @@ -16,7 +15,6 @@ import java.time.Instant; public class SpotifyAPI { private static final String clientId = readSetting("spotifyClientID"); private static final String clientSecret = readSetting("spotifyClientSecret"); - public static String spotifyapiKey = ""; public static long lastRefresh = 0; private static final SpotifyApi spotifyApi = new SpotifyApi.Builder() @@ -25,26 +23,26 @@ public class SpotifyAPI { .build(); private static final ClientCredentialsRequest clientCredentialsRequest = spotifyApi.clientCredentials() .build(); - - public SpotifyAPI(){ this.spotifyapiKey = readSetting("spotifyApi"); } public static String getSearchTerm_sync(String trackid) { checkRefreshToken(); String searchQuery = ""; - try { - GetTrackRequest getTrackRequest = spotifyApi.getTrack(trackid) - .build(); - final Track track = getTrackRequest.execute(); - searchQuery = track.getName(); - ArtistSimplified[] artists = track.getArtists(); - for (int i = 0;i< artists.length;i++){ - searchQuery = searchQuery + " "+artists[i].getName(); - } - System.out.println(searchQuery); - } catch (Exception e) { - System.out.println("Error: " + e.getMessage()); + try { + GetTrackRequest getTrackRequest = spotifyApi.getTrack(trackid) + .build(); + final Track track = getTrackRequest.execute(); + searchQuery = track.getName(); + ArtistSimplified[] artists = track.getArtists(); + for (int i = 0; i < artists.length; i++) { + searchQuery = searchQuery + " " + artists[i].getName(); + } + System.out.println(searchQuery); + } catch (Exception e) { + System.out.println("Error with getting name: " + e.getMessage() +"Retrying..."); + return null; + } return searchQuery; @@ -86,6 +84,7 @@ public class SpotifyAPI { } public static String readSetting(String parameter){ Object obj = null; + try { obj = new JSONParser().parse(new FileReader("settings//config.json")); } catch (Exception e) { diff --git a/src/main/java/utility/StatusHandler.java b/src/main/java/utility/StatusHandler.java new file mode 100644 index 0000000..43a34cf --- /dev/null +++ b/src/main/java/utility/StatusHandler.java @@ -0,0 +1,41 @@ +package utility; + +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.interactions.commands.OptionType; +import net.dv8tion.jda.api.interactions.commands.build.CommandData; + +public class StatusHandler { + static JDA jda; + public StatusHandler(JDA jda) + { + this.jda = jda; + } + public static void setSlashCommands(){ + // jda.updateCommands().queue(); + jda.upsertCommand(new CommandData("play","Adds a song to the queue with a URL or search terms"). + addOption(OptionType.STRING,"term","The link or search terms of the music to queue") + ).queue(); + jda.upsertCommand(new CommandData("queue-recursive","Adds a set amount of random songs from a playlist"). + addOption(OptionType.STRING,"url","The link of the playlist") + .addOption(OptionType.INTEGER,"amount","The amount of songs to queue") + ).queue(); + jda.upsertCommand(new CommandData("leave","Clears the queue and disconnects the bot from voice channel")).queue(); + jda.upsertCommand(new CommandData("showqueue","Shows the current queue")).queue(); + jda.upsertCommand(new CommandData("pause","Pauses the player")).queue(); + jda.upsertCommand(new CommandData("controls","Show an interface to control the player")).queue(); + jda.upsertCommand(new CommandData("skip","Skips the current song")).queue(); + jda.upsertCommand(new CommandData("nowplaying","Shows a detailed view of the current song playing")).queue(); + jda.upsertCommand(new CommandData("stop","Stops the player and clears the queue")).queue(); + jda.upsertCommand(new CommandData("remove","Remove a track in queue")).queue(); + jda.upsertCommand(new CommandData("shuffle","Shuffle the current queue")).queue(); + jda.upsertCommand(new CommandData("vtmusic","Queues a set number of random VTuber songs and covers"). + addOption(OptionType.INTEGER,"number","Number of songs to queue") + ).queue(); + jda.upsertCommand(new CommandData("volume","Set the volume or leave blank to check current volume"). + addOption(OptionType.INTEGER,"volume","Volume from 0-100") + ).queue(); + + + } + +} diff --git a/src/main/java/utility/YouTubeAPI.java b/src/main/java/utility/YouTubeAPI.java index 61b48ed..4acecf5 100644 --- a/src/main/java/utility/YouTubeAPI.java +++ b/src/main/java/utility/YouTubeAPI.java @@ -5,6 +5,8 @@ import org.json.JSONObject; import org.jsoup.Jsoup; import java.io.IOException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; public class YouTubeAPI { @@ -13,8 +15,8 @@ public class YouTubeAPI { this.ytapiKey = ytapiKey; } public String returnTopVideoURL(String keyword )throws IOException { - String url = "https://www.googleapis.com/youtube/v3/search?part=snippet&maxResults=1&q="+keyword+"&type=video&key="+ytapiKey; - url = url.replaceAll(" ", "%20"); + String url = "https://www.googleapis.com/youtube/v3/search?part=snippet&maxResults=1&q="+ URLEncoder.encode(keyword, StandardCharsets.UTF_8)+"&type=video&key="+ytapiKey; + System.out.println(url); String data = Jsoup.connect(url).ignoreContentType(true).execute().body(); JSONObject obj = new JSONObject(data); JSONArray arr = obj.getJSONArray("items"); -- cgit v1.2.3