diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..9f97022 --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +target/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 6ab3240..56919e2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,19 +1,49 @@ -FROM alpine:3.16 +ARG JAVA_VERSION=17 -ARG version +FROM alpine:3.16 AS build -ENV VERSION ${version} -ENV JAVA_HOME /usr/lib/jvm/java-8 +ARG MAVEN_VERSION=3.8.7 +ARG MAVEN_BASE_URL=https://dlcdn.apache.org/maven/maven-3/${MAVEN_VERSION}/binaries +ARG USER_HOME_DIR="/root" +ARG JAVA_VERSION -RUN apk --no-cache add sudo \ - && apk --no-cache add wget \ - && apk --no-cache add openjdk8-jre +RUN apk --no-cache add sudo curl tar bash procps \ + && apk --no-cache add openjdk${JAVA_VERSION} + +RUN mkdir -p /usr/share/maven /usr/share/maven/ref \ + && echo "Downloading maven" \ + && curl -fsSL -o /tmp/apache-maven.tar.gz ${MAVEN_BASE_URL}/apache-maven-${MAVEN_VERSION}-bin.tar.gz \ + && echo "Unzipping maven" \ + && tar -xzf /tmp/apache-maven.tar.gz -C /usr/share/maven --strip-components=1 \ + && echo "Cleaning and setting links" \ + && rm -f /tmp/apache-maven.tar.gz \ + && ln -s /usr/share/maven/bin/mvn /usr/bin/mvn + +ENV MAVEN_HOME /usr/share/maven +ENV MAVEN_CONFIG "$USER_HOME_DIR/.m2" +ENV JAVA_VER ${JAVA_VERSION} +ENV JAVA_HOME /usr/lib/jvm/java-${JAVA_VERSION}-openjdk WORKDIR /app -VOLUME /app +COPY ./src ./src +COPY ./pom.xml ./pom.xml +RUN mvn -f ./pom.xml clean package -COPY ./start.sh /app -COPY ./config.txt /app -RUN chmod +x /app/start.sh +FROM alpine:3.16 -ENTRYPOINT ["/bin/sh", "-c", "/app/start.sh"] +ARG JAVA_VERSION + +ENV VERSION ${VER} +ENV JAVA_VER ${JAVA_VERSION} +ENV JAVA_HOME /usr/lib/jvm/java-${JAVA_VERSION}-openjdk + +RUN apk --no-cache add sudo bash \ + && apk --no-cache add openjdk${JAVA_VERSION} + +WORKDIR /app +COPY --from=build /app/target/siren-*-All.jar /usr/local/lib/siren.jar +COPY ./start.sh ./start.sh +RUN chmod +x ./start.sh + +ENTRYPOINT ["java", "-jar", "/usr/local/lib/siren.jar"] +#ENTRYPOINT ["/bin/sh", "-c", "./start.sh"] \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a9d714e --- /dev/null +++ b/Makefile @@ -0,0 +1,13 @@ +SHELL := /bin/bash + +build: + docker build --tag siren . + +test: + docker run --rm -it siren:latest bash + +up: + docker-compose up -d + +down: + docker-compose down \ No newline at end of file diff --git a/README.md b/README.md index ecc5e9b..356f316 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,17 @@ # Siren -A Docker containerized version of [MusicBot](https://github.com/jagrosh/MusicBot) +A Java/Docker Discord music bot -`docker build .` -`docker-compose up -d` \ No newline at end of file +`docker build -t siren .` +`docker-compose up -d` + +## Development +Build container + +`docker build -t siren .` + +Run container locally + +``` +docker container run --name siren_test -d -t siren bash +docker exec -it siren_test bash +``` \ No newline at end of file diff --git a/config.txt b/config.txt deleted file mode 100644 index e5ca4fd..0000000 --- a/config.txt +++ /dev/null @@ -1,184 +0,0 @@ -///////////////////////////////////////////////////////// -// Config for the JMusicBot // -///////////////////////////////////////////////////////// -// Any line starting with // is ignored // -// You MUST set the token and owner // -// All other items have defaults if you don't set them // -// Open in Notepad++ for best results // -///////////////////////////////////////////////////////// - - -// This sets the token for the bot to log in with -// This MUST be a bot token (user tokens will not work) -// If you don't know how to get a bot token, please see the guide here: -// https://github.com/jagrosh/MusicBot/wiki/Getting-a-Bot-Token - -token = OTMyMzAxMjQ4NTQ2MzYxMzQ2.YeQ_Mg.n4H8Cl3dQ1u5aFL1ZvTmfcGwpEY - - -// This sets the owner of the bot -// This needs to be the owner's ID (a 17-18 digit number) -// https://github.com/jagrosh/MusicBot/wiki/Finding-Your-User-ID - -owner = 250842261221277697 - -// This sets the prefix for the bot -// The prefix is used to control the commands -// If you use !!, the play command will be !!play -// If you do not set this, the prefix will be a mention of the bot (@Botname play) - -// prefix = "@mention" -prefix = "!" - - -// If you set this, it modifies the default game of the bot -// Set this to NONE to have no game -// Set this to DEFAULT to use the default game -// You can make the game "Playing X", "Listening to X", or "Watching X" -// where X is the title. If you don't include an action, it will use the -// default of "Playing" - -game = "DEFAULT" - - -// If you set this, it will modify the default status of bot -// Valid values: ONLINE IDLE DND INVISIBLE - -status = ONLINE - - -// If you set this to true, the bot will list the title of the song it is currently playing in its -// "Playing" status. Note that this will ONLY work if the bot is playing music on ONE guild; -// if the bot is playing on multiple guilds, this will not work. - -songinstatus=false - - -// If you set this, the bot will also use this prefix in addition to -// the one provided above - -altprefix = "NONE" - - -// If you set these, it will change the various emojis - -success = "🎶" -warning = "💡" -error = "🚫" -loading = "⌚" -searching = "🔎" - - -// If you set this, you change the word used to view the help. -// For example, if you set the prefix to !! and the help to cmds, you would type -// !!cmds to see the help text - -help = help - - -// If you set this, the "nowplaying" command will show youtube thumbnails -// Note: If you set this to true, the nowplaying boxes will NOT refresh -// This is because refreshing the boxes causes the image to be reloaded -// every time it refreshes. - -npimages = false - - -// If you set this, the bot will not leave a voice channel after it finishes a queue. -// Keep in mind that being connected to a voice channel uses additional bandwith, -// so this option is not recommended if bandwidth is a concern. - -stayinchannel = false - - -// This sets the maximum amount of seconds any track loaded can be. If not set or set -// to any number less than or equal to zero, there is no maximum time length. This time -// restriction applies to songs loaded from any source. - -maxtime = 0 - -// This sets the amount of seconds the bot will stay alone on a voice channel until it -// automatically leaves the voice channel and clears the queue. If not set or set -// to any number less than or equal to zero, the bot won't leave when alone. - -alonetimeuntilstop = 0 - -// This sets an alternative folder to be used as the Playlists folder -// This can be a relative or absolute path - -playlistsfolder = "Playlists" - - -// By default, the bot will DM the owner if the bot is running and a new version of the bot -// becomes available. Set this to false to disable this feature. - -updatealerts=true - - -// Changing this changes the lyrics provider -// Currently available providers: "A-Z Lyrics", "Genius", "MusicMatch", "LyricsFreak" -// At the time of writing, I would recommend sticking with A-Z Lyrics or MusicMatch, -// as Genius tends to have a lot of non-song results and you might get something -// completely unrelated to what you want. -// If you are interested in contributing a provider, please see -// https://github.com/jagrosh/JLyrics - -lyrics.default = "A-Z Lyrics" - - -// These settings allow you to configure custom aliases for all commands. -// Multiple aliases may be given, separated by commas. -// -// Example 1: Giving command "play" the alias "p": -// play = [ p ] -// -// Example 2: Giving command "search" the aliases "yts" and "find": -// search = [ yts, find ] - -aliases { - // General commands - settings = [ status ] - - // Music commands - lyrics = [] - nowplaying = [ np, current ] - play = [] - playlists = [ pls ] - queue = [ list ] - remove = [ delete ] - scsearch = [] - search = [ ytsearch ] - shuffle = [] - skip = [ voteskip ] - - // Admin commands - prefix = [ setprefix ] - setdj = [] - settc = [] - setvc = [] - - // DJ Commands - forceremove = [ forcedelete, modremove, moddelete ] - forceskip = [ modskip ] - movetrack = [ move ] - pause = [] - playnext = [] - repeat = [] - skipto = [ jumpto ] - stop = [] - volume = [ vol ] -} - -// If you set this to true, it will enable the eval command for the bot owner. This command -// allows the bot owner to run arbitrary code from the bot's account. -// -// WARNING: -// This command can be extremely dangerous. If you don't know what you're doing, you could -// cause horrific problems on your Discord server or on whatever computer this bot is running -// on. Never run this command unless you are completely positive what you are running. -// -// DO NOT ENABLE THIS IF YOU DON'T KNOW WHAT THIS DOES OR HOW TO USE IT -// IF SOMEONE ASKS YOU TO ENABLE THIS, THERE IS AN 11/10 CHANCE THEY ARE TRYING TO SCAM YOU - -eval=false - diff --git a/docker-compose.yml b/docker-compose.yml index 17d59b0..9a060cc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,13 +1,9 @@ version: '3' services: - musicbot: - build: - context: . - args: - version: 0.3.8 - image: musicbot - container_name: musicbot + siren: + image: siren + container_name: siren volumes: - ./data:/app restart: unless-stopped diff --git a/pom.xml b/pom.xml index a22d680..7e84762 100644 --- a/pom.xml +++ b/pom.xml @@ -2,8 +2,8 @@ 4.0.0 com.bensherriff - Siren - Snapshot + siren + 0.1.0 jar diff --git a/src/main/java/com/bensherriff/siren/AudioPlayerSendHandler.java b/src/main/java/com/bensherriff/siren/AudioPlayerSendHandler.java deleted file mode 100644 index bbda831..0000000 --- a/src/main/java/com/bensherriff/siren/AudioPlayerSendHandler.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.bensherriff.siren; - -import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; -import com.sedmelluq.discord.lavaplayer.track.playback.MutableAudioFrame; -import java.nio.Buffer; -import net.dv8tion.jda.api.audio.AudioSendHandler; - -import java.nio.ByteBuffer; - -public class AudioPlayerSendHandler implements AudioSendHandler { - private final AudioPlayer audioPlayer; - private final ByteBuffer buffer; - private final MutableAudioFrame frame; - - public AudioPlayerSendHandler(AudioPlayer audioPlayer) { - this.audioPlayer = audioPlayer; - this.buffer = ByteBuffer.allocate(1024); - this.frame = new MutableAudioFrame(); - this.frame.setBuffer(buffer); - } - - @Override - public boolean canProvide() { - // returns true if audio was provided - return audioPlayer.provide(frame); - } - - @Override - public ByteBuffer provide20MsAudio() { - // flip to make it a read buffer - ((Buffer) buffer).flip(); - return buffer; - } - - @Override - public boolean isOpus() { - return true; - } -} diff --git a/src/main/java/com/bensherriff/siren/ConfigManager.java b/src/main/java/com/bensherriff/siren/ConfigManager.java deleted file mode 100644 index 62f5298..0000000 --- a/src/main/java/com/bensherriff/siren/ConfigManager.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.bensherriff.siren; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.io.IOException; -import java.io.InputStream; - -public class ConfigManager { - private static final Logger LOGGER = LogManager.getLogger(ConfigManager.class); - private final ObjectMapper mapper = new ObjectMapper(); - - public Config load() throws IOException { - try(InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("config.json")) { - return mapper.readValue(inputStream, Config.class); - } - } -} diff --git a/src/main/java/com/bensherriff/siren/MusicBot.java b/src/main/java/com/bensherriff/siren/MusicBot.java index 5eb91ff..f1271dd 100644 --- a/src/main/java/com/bensherriff/siren/MusicBot.java +++ b/src/main/java/com/bensherriff/siren/MusicBot.java @@ -1,12 +1,14 @@ package com.bensherriff.siren; +import com.bensherriff.siren.audio.AudioHandler; +import com.bensherriff.siren.audio.PlayerManager; +import com.bensherriff.siren.settings.Settings; +import com.bensherriff.siren.settings.SettingsManager; import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler; -import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; -import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager; -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 net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDABuilder; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.TextChannel; @@ -16,6 +18,8 @@ import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.managers.AudioManager; import net.dv8tion.jda.api.requests.GatewayIntent; import net.dv8tion.jda.api.utils.cache.CacheFlag; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import javax.security.auth.login.LoginException; import java.io.IOException; @@ -24,52 +28,60 @@ import java.util.HashMap; import java.util.Map; public class MusicBot extends ListenerAdapter { + private static final Logger LOGGER = LogManager.getLogger(MusicBot.class); private final static GatewayIntent[] INTENTS = { GatewayIntent.DIRECT_MESSAGES, GatewayIntent.GUILD_MESSAGES, GatewayIntent.GUILD_MESSAGE_REACTIONS, GatewayIntent.GUILD_VOICE_STATES }; - private final AudioPlayerManager playerManager; - private final Map musicManagers; - private final Config config; + private final PlayerManager playerManager; + private final Map musicManagers; + private final Settings settings; + + private JDA jda; public static void main(String[] args) throws Exception { start(); } private static void start() throws IOException, LoginException { - ConfigManager configManager = new ConfigManager(); - Config config = configManager.load(); - MusicBot musicBot = new MusicBot(config); + SettingsManager settingsManager = new SettingsManager(); + Settings settings = settingsManager.load(); + MusicBot musicBot = new MusicBot(settings); - JDABuilder.create(config.getToken(), Arrays.asList(INTENTS)) + JDA jda = JDABuilder.create(settings.getToken(), Arrays.asList(INTENTS)) .enableCache(CacheFlag.MEMBER_OVERRIDES, CacheFlag.VOICE_STATE) .disableCache(CacheFlag.ACTIVITY, CacheFlag.CLIENT_STATUS, CacheFlag.EMOTE) .addEventListeners(musicBot) .setBulkDeleteSplittingEnabled(true) .build(); + musicBot.setJDA(jda); } - private MusicBot(Config config) { + private MusicBot(Settings settings) { this.musicManagers = new HashMap<>(); - this.config = config; + this.settings = settings; - this.playerManager = new DefaultAudioPlayerManager(); - AudioSourceManagers.registerRemoteSources(playerManager); - AudioSourceManagers.registerLocalSource(playerManager); + this.playerManager = new PlayerManager(this); + this.playerManager.initialize(); } - private synchronized MusicManager getGuildAudioPlayer(Guild guild) { - long guildId = Long.parseLong(guild.getId()); - MusicManager musicManager = musicManagers.get(guildId); + public void setJDA(JDA jda) { + this.jda = jda; + } - if (musicManager == null) { - musicManager = new MusicManager(playerManager); - musicManagers.put(guildId, musicManager); + public JDA getJDA() { + return jda; + } + + public Settings getSettings() { + return settings; + } + + public void closeAudioConnection(long guildID) { + Guild guild = jda.getGuildById(guildID); + if (guild != null) { + guild.getAudioManager().closeAudioConnection(); } - - guild.getAudioManager().setSendingHandler(musicManager.getSendHandler()); - - return musicManager; } @Override @@ -92,15 +104,29 @@ public class MusicBot extends ListenerAdapter { super.onGuildMessageReceived(event); } - private void loadAndPlay(final TextChannel channel, final String trackUrl) { - MusicManager musicManager = getGuildAudioPlayer(channel.getGuild()); + private synchronized AudioHandler getGuildAudioPlayer(Guild guild) { + long guildId = Long.parseLong(guild.getId()); + AudioHandler audioHandler = musicManagers.get(guildId); - playerManager.loadItemOrdered(musicManager, trackUrl, new AudioLoadResultHandler() { + if (audioHandler == null) { + LOGGER.info("Creating Audio Handler for guild " + guildId); + audioHandler = new AudioHandler(playerManager, guildId); + musicManagers.put(guildId, audioHandler); + } + + guild.getAudioManager().setSendingHandler(audioHandler); + + return audioHandler; + } + + private void loadAndPlay(final TextChannel channel, final String trackUrl) { + AudioHandler audioHandler = getGuildAudioPlayer(channel.getGuild()); + + playerManager.loadItemOrdered(audioHandler, trackUrl, new AudioLoadResultHandler() { @Override public void trackLoaded(AudioTrack track) { channel.sendMessage("Adding **" + track.getInfo().title + "** to queue").queue(); - - play(channel.getGuild(), musicManager, track); + play(channel.getGuild(), audioHandler, track); } @Override @@ -112,8 +138,7 @@ public class MusicBot extends ListenerAdapter { } channel.sendMessage("Adding **" + firstTrack.getInfo().title + "** to queue (first track of playlist " + playlist.getName() + ")").queue(); - - play(channel.getGuild(), musicManager, firstTrack); + play(channel.getGuild(), audioHandler, firstTrack); } @Override @@ -128,33 +153,33 @@ public class MusicBot extends ListenerAdapter { }); } - private void play(Guild guild, MusicManager musicManager, AudioTrack track) { + private void play(Guild guild, AudioHandler audioHandler, AudioTrack track) { connectToFirstVoiceChannel(guild.getAudioManager()); - musicManager.scheduler.queue(track); + audioHandler.addTrack(track); } private void stop(TextChannel channel) { - MusicManager musicManager = getGuildAudioPlayer(channel.getGuild()); - musicManager.player.stopTrack(); + AudioHandler audioHandler = getGuildAudioPlayer(channel.getGuild()); + audioHandler.stopTrack(); channel.getGuild().getAudioManager().closeAudioConnection(); channel.sendMessage("Stopping music").queue(); } private void skipTrack(TextChannel channel) { - MusicManager musicManager = getGuildAudioPlayer(channel.getGuild()); - musicManager.scheduler.nextTrack(); - - channel.sendMessage("Skipped to next track.").queue(); + AudioHandler audioHandler = getGuildAudioPlayer(channel.getGuild()); + audioHandler.nextTrack(); + channel.sendMessage("Skipped to next track").queue(); } private void changeVolume(TextChannel channel, String vol) { - MusicManager musicManager = getGuildAudioPlayer(channel.getGuild()); + AudioHandler audioHandler = getGuildAudioPlayer(channel.getGuild()); int volume = Integer.parseInt(vol); - config.setVolume(volume); - musicManager.player.setVolume(volume); + settings.setVolume(volume); + audioHandler.setVolume(volume); channel.sendMessage("Set volume to " + volume).queue(); } + //TODO connect to user's channel instead of first voice channel private static void connectToFirstVoiceChannel(AudioManager audioManager) { if (!audioManager.isConnected()) { for (VoiceChannel voiceChannel : audioManager.getGuild().getVoiceChannels()) { diff --git a/src/main/java/com/bensherriff/siren/MusicManager.java b/src/main/java/com/bensherriff/siren/MusicManager.java deleted file mode 100644 index 80dc631..0000000 --- a/src/main/java/com/bensherriff/siren/MusicManager.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.bensherriff.siren; - -import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; -import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; - -public class MusicManager { - - public final AudioPlayer player; - public final TrackScheduler scheduler; - - public MusicManager(AudioPlayerManager manager) { - player = manager.createPlayer(); - scheduler = new TrackScheduler(player); - player.addListener(scheduler); - } - - public AudioPlayerSendHandler getSendHandler() { - return new AudioPlayerSendHandler(player); - } -} \ No newline at end of file diff --git a/src/main/java/com/bensherriff/siren/TrackScheduler.java b/src/main/java/com/bensherriff/siren/TrackScheduler.java deleted file mode 100644 index 45cd4d0..0000000 --- a/src/main/java/com/bensherriff/siren/TrackScheduler.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.bensherriff.siren; - -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 java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; - -/** - * This class schedules tracks for the audio player. It contains the queue of tracks. - */ -public class TrackScheduler extends AudioEventAdapter { - private final AudioPlayer player; - private final BlockingQueue queue; - - /** - * @param player The audio player this scheduler uses - */ - public TrackScheduler(AudioPlayer player) { - this.player = player; - this.queue = new LinkedBlockingQueue<>(); - } - - /** - * Add the next track to queue or play right away if nothing is in the queue. - * - * @param track The track to play or add to queue. - */ - public void queue(AudioTrack track) { - // 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 (!player.startTrack(track, true)) { - queue.offer(track); - } - } - - /** - * Start the next track, stopping the current one if it is playing. - */ - public void nextTrack() { - // 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. - player.startTrack(queue.poll(), false); - } - - @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) - if (endReason.mayStartNext) { - nextTrack(); - } - } -} diff --git a/src/main/java/com/bensherriff/siren/audio/AudioHandler.java b/src/main/java/com/bensherriff/siren/audio/AudioHandler.java new file mode 100644 index 0000000..f0ff198 --- /dev/null +++ b/src/main/java/com/bensherriff/siren/audio/AudioHandler.java @@ -0,0 +1,80 @@ +package com.bensherriff.siren.audio; + +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.playback.MutableAudioFrame; +import net.dv8tion.jda.api.audio.AudioSendHandler; + +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +public class AudioHandler extends AudioEventAdapter implements AudioSendHandler { + + private final PlayerManager manager; + private final AudioPlayer player; + private final ByteBuffer buffer; + private final MutableAudioFrame frame; + private final BlockingQueue queue; + private final long guildID; + + public AudioHandler(PlayerManager manager, long guildID) { + this.manager = manager; + player = manager.createPlayer(); + player.setVolume(manager.getBot().getSettings().getVolume()); + player.addListener(this); + this.queue = new LinkedBlockingQueue<>(); + this.buffer = ByteBuffer.allocate(1024); + this.frame = new MutableAudioFrame(); + this.frame.setBuffer(buffer); + this.guildID = guildID; + } + + public void addTrack(AudioTrack track) { + if (!player.startTrack(track, true)) { + queue.offer(track); + } + } + + public void nextTrack() { + player.startTrack(queue.poll(), false); + } + + public void stopTrack() { + player.stopTrack(); + } + + public void setVolume(int volume) { + player.setVolume(volume); + } + + @Override + public void onTrackEnd(AudioPlayer player, AudioTrack track, AudioTrackEndReason endReason) { + if (endReason.mayStartNext) { + nextTrack(); + } else if (queue.isEmpty()) { + manager.getBot().closeAudioConnection(guildID); + } + } + + @Override + public boolean canProvide() { + // returns true if audio was provided + return player.provide(frame); + } + + @Override + public ByteBuffer provide20MsAudio() { + // flip to make it a read buffer + ((Buffer) buffer).flip(); + return buffer; + } + + @Override + public boolean isOpus() { + return true; + } +} \ No newline at end of file diff --git a/src/main/java/com/bensherriff/siren/AudioPlayerManager.java b/src/main/java/com/bensherriff/siren/audio/PlayerManager.java similarity index 50% rename from src/main/java/com/bensherriff/siren/AudioPlayerManager.java rename to src/main/java/com/bensherriff/siren/audio/PlayerManager.java index 8564774..83b678d 100644 --- a/src/main/java/com/bensherriff/siren/AudioPlayerManager.java +++ b/src/main/java/com/bensherriff/siren/audio/PlayerManager.java @@ -1,9 +1,20 @@ -package com.bensherriff.siren; +package com.bensherriff.siren.audio; +import com.bensherriff.siren.MusicBot; import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager; import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers; -public class AudioPlayerManager extends DefaultAudioPlayerManager { +public class PlayerManager extends DefaultAudioPlayerManager { + + private final MusicBot bot; + + public PlayerManager(MusicBot bot) { + this.bot = bot; + } + + public MusicBot getBot() { + return bot; + } public void initialize() { AudioSourceManagers.registerRemoteSources(this); diff --git a/src/main/java/com/bensherriff/siren/Config.java b/src/main/java/com/bensherriff/siren/settings/Settings.java similarity index 73% rename from src/main/java/com/bensherriff/siren/Config.java rename to src/main/java/com/bensherriff/siren/settings/Settings.java index 1296ffd..fd39ffb 100644 --- a/src/main/java/com/bensherriff/siren/Config.java +++ b/src/main/java/com/bensherriff/siren/settings/Settings.java @@ -1,12 +1,12 @@ -package com.bensherriff.siren; +package com.bensherriff.siren.settings; -public class Config { +public class Settings { - private String token; - private String owner; + private String token = ""; + private String owner = ""; - private String prefix; - private int volume; + private String prefix = "!"; + private int volume = 100; public String getToken() { return token; diff --git a/src/main/java/com/bensherriff/siren/settings/SettingsManager.java b/src/main/java/com/bensherriff/siren/settings/SettingsManager.java new file mode 100644 index 0000000..afe189c --- /dev/null +++ b/src/main/java/com/bensherriff/siren/settings/SettingsManager.java @@ -0,0 +1,24 @@ +package com.bensherriff.siren.settings; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.IOException; +import java.io.InputStream; + +public class SettingsManager { + private static final Logger LOGGER = LogManager.getLogger(SettingsManager.class); + private final ObjectMapper mapper = new ObjectMapper(); + + public Settings load() throws IOException { + // If settings is not available, create new default settings + try(InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("settings.json")) { + return mapper.readValue(inputStream, Settings.class); + } + } + + public void write(Settings settings) throws IOException { + + } +} diff --git a/src/main/resources/config.json b/src/main/resources/settings.json similarity index 89% rename from src/main/resources/config.json rename to src/main/resources/settings.json index 03c592b..47c7c93 100644 --- a/src/main/resources/config.json +++ b/src/main/resources/settings.json @@ -2,5 +2,5 @@ "token": "OTMyMzAxMjQ4NTQ2MzYxMzQ2.YeQ_Mg.n4H8Cl3dQ1u5aFL1ZvTmfcGwpEY", "owner": "250842261221277697", "prefix": "!", - "volume": 50 + "volume": 30 } \ No newline at end of file diff --git a/start.sh b/start.sh index 8ed0cf2..bb97b7a 100755 --- a/start.sh +++ b/start.sh @@ -1,12 +1,14 @@ #!/bin/bash -if [ -f /config.txt ]; then - echo "configuration file found" - mv /config.txt . -fi +#if [ -f /config.txt ]; then +# echo "configuration file found" +# mv /config.txt . +#fi +# +#if [ ! -f JMusicBot-${VERSION}.jar ]; then +# wget https://github.com/jagrosh/MusicBot/releases/download/${VERSION}/JMusicBot-${VERSION}.jar +#fi +# +#java -Dnogui=true -jar JMusicBot-${VERSION}.jar -if [ ! -f JMusicBot-${VERSION}.jar ]; then - wget https://github.com/jagrosh/MusicBot/releases/download/${VERSION}/JMusicBot-${VERSION}.jar -fi - -java -Dnogui=true -jar JMusicBot-${VERSION}.jar +java -jar /usr/local/lib/siren.jar \ No newline at end of file