diff --git a/.github/workflows/make-release.yml b/.github/workflows/make-release.yml new file mode 100644 index 000000000..dc71379f5 --- /dev/null +++ b/.github/workflows/make-release.yml @@ -0,0 +1,70 @@ +name: Make Release +on: + workflow_dispatch: + inputs: + version_number: + description: 'Version Number' + required: true + type: string + info: + description: 'Description of this Release' + required: true + type: string + +jobs: + build_jar: + name: Build Jar + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Set up JDK 8 + uses: actions/setup-java@v2 + with: + java-version: '8' + distribution: 'adopt' + cache: maven + - name: Set Version + uses: datamonsters/replace-action@v2 + with: + files: 'pom.xml' + replacements: 'Snapshot=${{ github.event.inputs.version_number }}' + - name: Build with Maven + run: mvn --batch-mode --update-snapshots verify + - name: Rename jar + run: mv target/*-All.jar JMusicBot-${{ github.event.inputs.version_number }}.jar + - name: Upload jar + uses: actions/upload-artifact@v3 + with: + name: jar + path: JMusicBot-${{ github.event.inputs.version_number }}.jar + if-no-files-found: error + create_release: + name: Create Release + runs-on: ubuntu-latest + needs: build_jar + steps: + - name: Download a Build Artifact + uses: actions/download-artifact@v3.0.0 + with: + name: jar + path: . + - name: Show Artifacts + run: ls -R + - name: Create Release + uses: ncipollo/release-action@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + tag: ${{ github.event.inputs.version_number }} + name: Version ${{ github.event.inputs.version_number }} + draft: true + prerelease: false + artifacts: "*.jar" + body: | + ${{ github.event.inputs.info }} + + --- + ### Setup + https://jmusicbot.com/setup + https://jmusicbot.com/config + # Download: [JMusicBot-${{ github.event.inputs.version_number }}.jar](https://github.com/jagrosh/MusicBot/releases/download/${{ github.event.inputs.version_number }}/JMusicBot-${{ github.event.inputs.version_number }}.jar) diff --git a/pom.xml b/pom.xml index a48fe01f6..b5b4cf6fe 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ JMusicBot Snapshot jar - + dv8tion @@ -20,15 +20,28 @@ jitpack.io https://jitpack.io + + true + always + - + + - net.dv8tion - JDA - 4.3.0_324 + net.dv8tion + JDA + 4.4.1_353 + + com.jagrosh + jda-utilities + 3.0.5 + pom + + + - - com.jagrosh - jda-utilities - 3.0.5 - pom - - com.github.jagrosh JLyrics - -SNAPSHOT + master-SNAPSHOT - + + ch.qos.logback logback-classic @@ -76,8 +79,10 @@ org.jsoup jsoup - 1.14.2 + 1.15.3 + + junit junit @@ -91,7 +96,7 @@ test - + @@ -133,7 +138,7 @@ - + UTF-8 1.8 diff --git a/src/main/java/com/jagrosh/jmusicbot/BotConfig.java b/src/main/java/com/jagrosh/jmusicbot/BotConfig.java index 185f31102..e29783293 100644 --- a/src/main/java/com/jagrosh/jmusicbot/BotConfig.java +++ b/src/main/java/com/jagrosh/jmusicbot/BotConfig.java @@ -64,13 +64,7 @@ public void load() try { // get the path to the config, default config.txt - path = OtherUtil.getPath(System.getProperty("config.file", System.getProperty("config", "config.txt"))); - if(path.toFile().exists()) - { - if(System.getProperty("config.file") == null) - System.setProperty("config.file", System.getProperty("config", path.toAbsolutePath().toString())); - ConfigFactory.invalidateCaches(); - } + path = getConfigPath(); // load in the config file, plus the default values //Config config = ConfigFactory.parseFile(path.toFile()).withFallback(ConfigFactory.load()); @@ -204,21 +198,11 @@ public void load() private void writeToFile() { - String original = OtherUtil.loadResource(this, "/reference.conf"); - byte[] bytes; - if(original==null) - { - bytes = ("token = "+token+"\r\nowner = "+owner).getBytes(); - } - else - { - bytes = original.substring(original.indexOf(START_TOKEN)+START_TOKEN.length(), original.indexOf(END_TOKEN)) - .replace("BOT_TOKEN_HERE", token) + byte[] bytes = loadDefaultConfig().replace("BOT_TOKEN_HERE", token) .replace("0 // OWNER ID", Long.toString(owner)) .replace("CLIENT_ID_HERE", spotifyClientId) .replace("CLIENT_SECRET_HERE", spotifyClientSecret) .trim().getBytes(); - } try { Files.write(path, bytes); @@ -231,6 +215,43 @@ private void writeToFile() } } + private static String loadDefaultConfig() + { + String original = OtherUtil.loadResource(new JMusicBot(), "/reference.conf"); + return original==null + ? "token = BOT_TOKEN_HERE\r\nowner = 0 // OWNER ID" + : original.substring(original.indexOf(START_TOKEN)+START_TOKEN.length(), original.indexOf(END_TOKEN)).trim(); + } + + private static Path getConfigPath() + { + Path path = OtherUtil.getPath(System.getProperty("config.file", System.getProperty("config", "config.txt"))); + if(path.toFile().exists()) + { + if(System.getProperty("config.file") == null) + System.setProperty("config.file", System.getProperty("config", path.toAbsolutePath().toString())); + ConfigFactory.invalidateCaches(); + } + return path; + } + + public static void writeDefaultConfig() + { + Prompt prompt = new Prompt(null, null, true, true); + prompt.alert(Prompt.Level.INFO, "JMusicBot Config", "Generating default config file"); + Path path = BotConfig.getConfigPath(); + byte[] bytes = BotConfig.loadDefaultConfig().getBytes(); + try + { + prompt.alert(Prompt.Level.INFO, "JMusicBot Config", "Writing default config file to " + path.toAbsolutePath().toString()); + Files.write(path, bytes); + } + catch(Exception ex) + { + prompt.alert(Prompt.Level.ERROR, "JMusicBot Config", "An error occurred writing the default config file: " + ex.getMessage()); + } + } + public boolean isValid() { return valid; diff --git a/src/main/java/com/jagrosh/jmusicbot/JMusicBot.java b/src/main/java/com/jagrosh/jmusicbot/JMusicBot.java index 5d94a453c..d2b9b571a 100644 --- a/src/main/java/com/jagrosh/jmusicbot/JMusicBot.java +++ b/src/main/java/com/jagrosh/jmusicbot/JMusicBot.java @@ -34,6 +34,7 @@ import net.dv8tion.jda.api.entities.Activity; import net.dv8tion.jda.api.requests.GatewayIntent; import net.dv8tion.jda.api.utils.cache.CacheFlag; +import net.dv8tion.jda.api.exceptions.ErrorResponseException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,36 +44,43 @@ */ public class JMusicBot { - public final static String PLAY_EMOJI = "\u25B6"; // ▶ - public final static String PAUSE_EMOJI = "\u23F8"; // ⏸ - public final static String STOP_EMOJI = "\u23F9"; // ⏹ + public final static Logger LOG = LoggerFactory.getLogger(JMusicBot.class); public final static Permission[] RECOMMENDED_PERMS = {Permission.MESSAGE_READ, Permission.MESSAGE_WRITE, Permission.MESSAGE_HISTORY, Permission.MESSAGE_ADD_REACTION, Permission.MESSAGE_EMBED_LINKS, Permission.MESSAGE_ATTACH_FILES, Permission.MESSAGE_MANAGE, Permission.MESSAGE_EXT_EMOJI, Permission.MANAGE_CHANNEL, Permission.VOICE_CONNECT, Permission.VOICE_SPEAK, Permission.NICKNAME_CHANGE}; public final static GatewayIntent[] INTENTS = {GatewayIntent.DIRECT_MESSAGES, GatewayIntent.GUILD_MESSAGES, GatewayIntent.GUILD_MESSAGE_REACTIONS, GatewayIntent.GUILD_VOICE_STATES, GatewayIntent.GUILD_EMOJIS}; + /** * @param args the command line arguments */ public static void main(String[] args) { - // startup log - Logger log = LoggerFactory.getLogger("Startup"); - + if(args.length > 0) + switch(args[0].toLowerCase()) + { + case "generate-config": + BotConfig.writeDefaultConfig(); + return; + default: + } + startBot(); + } + + private static void startBot() + { // create prompt to handle startup - Prompt prompt = new Prompt("JMusicBot", "Switching to nogui mode. You can manually start in nogui mode by including the -Dnogui=true flag."); + Prompt prompt = new Prompt("JMusicBot"); - // get and check latest version - String version = OtherUtil.checkVersion(prompt); - - // check for valid java version - if(!System.getProperty("java.vm.name").contains("64")) - prompt.alert(Prompt.Level.WARNING, "Java Version", "It appears that you may not be using a supported Java version. Please use 64-bit java."); + // startup checks + OtherUtil.checkVersion(prompt); + OtherUtil.checkJavaVersion(prompt); // load config BotConfig config = new BotConfig(prompt); config.load(); if(!config.isValid()) return; + LOG.info("Loaded config from " + config.getConfigLocation()); // set up the listener EventWaiter waiter = new EventWaiter(); @@ -80,7 +88,7 @@ public static void main(String[] args) Bot bot = new Bot(waiter, config, settings); AboutCommand aboutCommand = new AboutCommand(Color.BLUE.brighter(), - "a music bot that is [easy to host yourself!](https://github.com/jagrosh/MusicBot) (v"+version+")", + "a music bot that is [easy to host yourself!](https://github.com/jagrosh/MusicBot) (v" + OtherUtil.getCurrentVersion() + ")", new String[]{"High-quality music playback", "FairQueue™ Technology", "Easy to host yourself"}, RECOMMENDED_PERMS); aboutCommand.setIsAuthor(false); @@ -161,14 +169,12 @@ else if(config.getGame().getName().equalsIgnoreCase("none")) } catch(Exception e) { - log.error("Could not start GUI. If you are " + LOG.error("Could not start GUI. If you are " + "running on a server or in a location where you cannot display a " + "window, please run in nogui mode using the -Dnogui=true flag."); } } - log.info("Loaded config from " + config.getConfigLocation()); - // attempt to log in and start try { @@ -196,5 +202,11 @@ else if(config.getGame().getName().equalsIgnoreCase("none")) + "invalid: " + ex + "\nConfig Location: " + config.getConfigLocation()); System.exit(1); } + catch(ErrorResponseException ex) + { + prompt.alert(Prompt.Level.ERROR, "JMusicBot", ex + "\nInvalid reponse returned when " + + "attempting to connect, please make sure you're connected to the internet"); + System.exit(1); + } } } diff --git a/src/main/java/com/jagrosh/jmusicbot/audio/AudioHandler.java b/src/main/java/com/jagrosh/jmusicbot/audio/AudioHandler.java index 600f34eec..b2ca7179d 100644 --- a/src/main/java/com/jagrosh/jmusicbot/audio/AudioHandler.java +++ b/src/main/java/com/jagrosh/jmusicbot/audio/AudioHandler.java @@ -46,6 +46,10 @@ */ public class AudioHandler extends AudioEventAdapter implements AudioSendHandler { + public final static String PLAY_EMOJI = "\u25B6"; // ▶ + public final static String PAUSE_EMOJI = "\u23F8"; // ⏸ + public final static String STOP_EMOJI = "\u23F9"; // ⏹ + private final FairQueue queue = new FairQueue<>(); private final List defaultQueue = new LinkedList<>(); private final Set votes = new HashSet<>(); @@ -233,12 +237,12 @@ public Message getNowPlaying(JDA jda) eb.setFooter("Source: " + track.getInfo().author, null); double progress = (double)audioPlayer.getPlayingTrack().getPosition()/track.getDuration(); - eb.setDescription((audioPlayer.isPaused() ? JMusicBot.PAUSE_EMOJI : JMusicBot.PLAY_EMOJI) + eb.setDescription(getStatusEmoji() + " "+FormatUtil.progressBar(progress) + " `[" + FormatUtil.formatTime(track.getPosition()) + "/" + FormatUtil.formatTime(track.getDuration()) + "]` " + FormatUtil.volumeIcon(audioPlayer.getVolume())); - return mb.setEmbed(eb.build()).build(); + return mb.setEmbeds(eb.build()).build(); } else return null; } @@ -248,9 +252,9 @@ public Message getNoMusicPlaying(JDA jda) Guild guild = guild(jda); return new MessageBuilder() .setContent(FormatUtil.filter(manager.getBot().getConfig().getSuccess()+" **Now Playing...**")) - .setEmbed(new EmbedBuilder() + .setEmbeds(new EmbedBuilder() .setTitle("No music playing") - .setDescription(JMusicBot.STOP_EMOJI+" "+FormatUtil.progressBar(-1)+" "+FormatUtil.volumeIcon(audioPlayer.getVolume())) + .setDescription(STOP_EMOJI+" "+FormatUtil.progressBar(-1)+" "+FormatUtil.volumeIcon(audioPlayer.getVolume())) .setColor(guild.getSelfMember().getColor()) .build()).build(); } @@ -265,11 +269,16 @@ public String getTopicFormat(JDA jda) if(title==null || title.equals("Unknown Title")) title = track.getInfo().uri; return "**"+title+"** ["+(userid==0 ? "autoplay" : "<@"+userid+">")+"]" - + "\n" + (audioPlayer.isPaused() ? JMusicBot.PAUSE_EMOJI : JMusicBot.PLAY_EMOJI) + " " + + "\n" + getStatusEmoji() + " " + "[" + FormatUtil.formatTime(track.getDuration()) + "] " + FormatUtil.volumeIcon(audioPlayer.getVolume()); } - else return "No music playing " + JMusicBot.STOP_EMOJI + " " + FormatUtil.volumeIcon(audioPlayer.getVolume()); + else return "No music playing " + STOP_EMOJI + " " + FormatUtil.volumeIcon(audioPlayer.getVolume()); + } + + public String getStatusEmoji() + { + return audioPlayer.isPaused() ? PAUSE_EMOJI : PLAY_EMOJI; } // Audio Send Handler methods diff --git a/src/main/java/com/jagrosh/jmusicbot/audio/QueuedTrack.java b/src/main/java/com/jagrosh/jmusicbot/audio/QueuedTrack.java index 691ccbdd8..02ae1559c 100644 --- a/src/main/java/com/jagrosh/jmusicbot/audio/QueuedTrack.java +++ b/src/main/java/com/jagrosh/jmusicbot/audio/QueuedTrack.java @@ -16,6 +16,7 @@ package com.jagrosh.jmusicbot.audio; import com.sedmelluq.discord.lavaplayer.track.AudioTrack; +import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo; import com.jagrosh.jmusicbot.queue.Queueable; import com.jagrosh.jmusicbot.utils.FormatUtil; import net.dv8tion.jda.api.entities.User; @@ -53,6 +54,9 @@ public AudioTrack getTrack() @Override public String toString() { - return "`[" + FormatUtil.formatTime(track.getDuration()) + "]` [**" + track.getInfo().title + "**]("+track.getInfo().uri+") - <@" + track.getUserData(RequestMetadata.class).getOwner() + ">"; + String entry = "`[" + FormatUtil.formatTime(track.getDuration()) + "]` "; + AudioTrackInfo trackInfo = track.getInfo(); + entry = entry + (trackInfo.uri.startsWith("http") ? "[**" + trackInfo.title + "**]("+trackInfo.uri+")" : "**" + trackInfo.title + "**"); + return entry + " - <@" + track.getUserData(RequestMetadata.class).getOwner() + ">"; } } diff --git a/src/main/java/com/jagrosh/jmusicbot/commands/general/SettingsCmd.java b/src/main/java/com/jagrosh/jmusicbot/commands/general/SettingsCmd.java index 7f88e0b2d..94c411d88 100644 --- a/src/main/java/com/jagrosh/jmusicbot/commands/general/SettingsCmd.java +++ b/src/main/java/com/jagrosh/jmusicbot/commands/general/SettingsCmd.java @@ -68,7 +68,7 @@ protected void execute(CommandEvent event) .setFooter(event.getJDA().getGuilds().size() + " servers | " + event.getJDA().getGuilds().stream().filter(g -> g.getSelfMember().getVoiceState().inVoiceChannel()).count() + " audio connections", null); - event.getChannel().sendMessage(builder.setEmbed(ebuilder.build()).build()).queue(); + event.getChannel().sendMessage(builder.setEmbeds(ebuilder.build()).build()).queue(); } } diff --git a/src/main/java/com/jagrosh/jmusicbot/commands/music/PlayCmd.java b/src/main/java/com/jagrosh/jmusicbot/commands/music/PlayCmd.java index 34266b743..75987210a 100644 --- a/src/main/java/com/jagrosh/jmusicbot/commands/music/PlayCmd.java +++ b/src/main/java/com/jagrosh/jmusicbot/commands/music/PlayCmd.java @@ -270,7 +270,12 @@ else if (playlist.getSelectedTrack()!=null) else { int count = loadPlaylist(playlist, null); - if(count==0) + if(playlist.getTracks().size() == 0) + { + m.editMessage(FormatUtil.filter(event.getClient().getWarning()+" The playlist "+(playlist.getName()==null ? "" : "(**"+playlist.getName() + +"**) ")+" could not be loaded or contained 0 entries")).queue(); + } + else if(count==0) { frequentEditAgent.queueEditMessage(FormatUtil.filter(bot.getWarning(event)+" All entries in this playlist "+(playlist.getName()==null ? "" : "(**"+playlist.getName() +"**) ")+"were longer than the allowed maximum (`"+bot.getConfig().getMaxTime()+"`)")); diff --git a/src/main/java/com/jagrosh/jmusicbot/commands/music/QueueCmd.java b/src/main/java/com/jagrosh/jmusicbot/commands/music/QueueCmd.java index 137d62900..fc0333be4 100644 --- a/src/main/java/com/jagrosh/jmusicbot/commands/music/QueueCmd.java +++ b/src/main/java/com/jagrosh/jmusicbot/commands/music/QueueCmd.java @@ -78,7 +78,7 @@ public void doCommand(CommandEvent event) Message nonowp = ah.getNoMusicPlaying(event.getJDA()); Message built = new MessageBuilder() .setContent(bot.getWarning(event) + " There is no music in the queue!") - .setEmbed((nowp==null ? nonowp : nowp).getEmbeds().get(0)).build(); + .setEmbeds((nowp==null ? nonowp : nowp).getEmbeds().get(0)).build(); event.reply(built, m -> { if(nowp!=null) @@ -108,7 +108,7 @@ private String getQueueTitle(AudioHandler ah, String success, int songslength, l StringBuilder sb = new StringBuilder(); if(ah.getPlayer().getPlayingTrack()!=null) { - sb.append(ah.getPlayer().isPaused() ? JMusicBot.PAUSE_EMOJI : JMusicBot.PLAY_EMOJI).append(" **") + sb.append(ah.getStatusEmoji()).append(" **") .append(ah.getPlayer().getPlayingTrack().getInfo().title).append("**\n"); } return FormatUtil.filter(sb.append(success).append(" Current Queue | ").append(songslength) diff --git a/src/main/java/com/jagrosh/jmusicbot/commands/owner/PlaylistCmd.java b/src/main/java/com/jagrosh/jmusicbot/commands/owner/PlaylistCmd.java index 4ac948d1a..6586a516e 100644 --- a/src/main/java/com/jagrosh/jmusicbot/commands/owner/PlaylistCmd.java +++ b/src/main/java/com/jagrosh/jmusicbot/commands/owner/PlaylistCmd.java @@ -72,7 +72,12 @@ public MakelistCmd() protected void execute(CommandEvent event) { String pname = event.getArgs().replaceAll("\\s+", "_"); - if(bot.getPlaylistLoader().getPlaylist(pname)==null) + pname = pname.replaceAll("[*?|\\/\":<>]", ""); + if(pname == null || pname.isEmpty()) + { + event.replyError("Please provide a name for the playlist!"); + } + else if(bot.getPlaylistLoader().getPlaylist(pname) == null) { try { diff --git a/src/main/java/com/jagrosh/jmusicbot/playlist/PlaylistLoader.java b/src/main/java/com/jagrosh/jmusicbot/playlist/PlaylistLoader.java index f352cd788..602235fcf 100644 --- a/src/main/java/com/jagrosh/jmusicbot/playlist/PlaylistLoader.java +++ b/src/main/java/com/jagrosh/jmusicbot/playlist/PlaylistLoader.java @@ -53,7 +53,7 @@ public List getPlaylistNames() else { createFolder(); - return Collections.EMPTY_LIST; + return Collections.emptyList(); } } diff --git a/src/main/java/com/jagrosh/jmusicbot/settings/Settings.java b/src/main/java/com/jagrosh/jmusicbot/settings/Settings.java index f23c62857..1dde2f0b7 100644 --- a/src/main/java/com/jagrosh/jmusicbot/settings/Settings.java +++ b/src/main/java/com/jagrosh/jmusicbot/settings/Settings.java @@ -176,7 +176,7 @@ public EmojiOption[] getSearchingEmojis() @Override public Collection getPrefixes() { - return prefix == null ? Collections.EMPTY_SET : Collections.singleton(prefix); + return prefix == null ? Collections.emptySet() : Collections.singleton(prefix); } // Setters diff --git a/src/main/java/com/jagrosh/jmusicbot/utils/OtherUtil.java b/src/main/java/com/jagrosh/jmusicbot/utils/OtherUtil.java index 00bf82121..545168137 100644 --- a/src/main/java/com/jagrosh/jmusicbot/utils/OtherUtil.java +++ b/src/main/java/com/jagrosh/jmusicbot/utils/OtherUtil.java @@ -150,7 +150,14 @@ public static OnlineStatus parseStatus(String status) return st == null ? OnlineStatus.ONLINE : st; } - public static String checkVersion(Prompt prompt) + public static void checkJavaVersion(Prompt prompt) + { + if(!System.getProperty("java.vm.name").contains("64")) + prompt.alert(Prompt.Level.WARNING, "Java Version", + "It appears that you may not be using a supported Java version. Please use 64-bit java."); + } + + public static void checkVersion(Prompt prompt) { // Get current version number String version = getCurrentVersion(); @@ -160,11 +167,8 @@ public static String checkVersion(Prompt prompt) if(latestVersion!=null && !latestVersion.equals(version)) { - prompt.alert(Prompt.Level.WARNING, "Version", String.format(NEW_VERSION_AVAILABLE, version, latestVersion)); + prompt.alert(Prompt.Level.WARNING, "JMusicBot Version", String.format(NEW_VERSION_AVAILABLE, version, latestVersion)); } - - // Return the current version - return version; } public static String getCurrentVersion() diff --git a/src/main/resources/natives/linux-aarch32/libconnector.so b/src/main/resources/natives/linux-aarch32/libconnector.so new file mode 100644 index 000000000..85d41f05a Binary files /dev/null and b/src/main/resources/natives/linux-aarch32/libconnector.so differ diff --git a/src/main/resources/natives/linux-aarch64/libconnector.so b/src/main/resources/natives/linux-aarch64/libconnector.so new file mode 100644 index 000000000..abf337ab2 Binary files /dev/null and b/src/main/resources/natives/linux-aarch64/libconnector.so differ diff --git a/src/main/resources/natives/linux-arm/libconnector.so b/src/main/resources/natives/linux-arm/libconnector.so new file mode 100644 index 000000000..0668792ab Binary files /dev/null and b/src/main/resources/natives/linux-arm/libconnector.so differ diff --git a/src/main/resources/natives/linux-armhf/libconnector.so b/src/main/resources/natives/linux-armhf/libconnector.so new file mode 100644 index 000000000..0668792ab Binary files /dev/null and b/src/main/resources/natives/linux-armhf/libconnector.so differ diff --git a/src/main/resources/natives/linux-x86/libconnector.so b/src/main/resources/natives/linux-x86/libconnector.so new file mode 100644 index 000000000..41b001230 Binary files /dev/null and b/src/main/resources/natives/linux-x86/libconnector.so differ