Updated docker files and layout
This commit is contained in:
1
.dockerignore
Normal file
1
.dockerignore
Normal file
@@ -0,0 +1 @@
|
|||||||
|
target/
|
||||||
54
Dockerfile
54
Dockerfile
@@ -1,19 +1,49 @@
|
|||||||
FROM alpine:3.16
|
ARG JAVA_VERSION=17
|
||||||
|
|
||||||
ARG version
|
FROM alpine:3.16 AS build
|
||||||
|
|
||||||
ENV VERSION ${version}
|
ARG MAVEN_VERSION=3.8.7
|
||||||
ENV JAVA_HOME /usr/lib/jvm/java-8
|
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 \
|
RUN apk --no-cache add sudo curl tar bash procps \
|
||||||
&& apk --no-cache add wget \
|
&& apk --no-cache add openjdk${JAVA_VERSION}
|
||||||
&& apk --no-cache add openjdk8-jre
|
|
||||||
|
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
|
WORKDIR /app
|
||||||
VOLUME /app
|
COPY ./src ./src
|
||||||
|
COPY ./pom.xml ./pom.xml
|
||||||
|
RUN mvn -f ./pom.xml clean package
|
||||||
|
|
||||||
COPY ./start.sh /app
|
FROM alpine:3.16
|
||||||
COPY ./config.txt /app
|
|
||||||
RUN chmod +x /app/start.sh
|
|
||||||
|
|
||||||
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"]
|
||||||
13
Makefile
Normal file
13
Makefile
Normal file
@@ -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
|
||||||
16
README.md
16
README.md
@@ -1,5 +1,17 @@
|
|||||||
# Siren
|
# Siren
|
||||||
A Docker containerized version of [MusicBot](https://github.com/jagrosh/MusicBot)
|
A Java/Docker Discord music bot
|
||||||
|
|
||||||
`docker build .`
|
`docker build -t siren .`
|
||||||
`docker-compose up -d`
|
`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
|
||||||
|
```
|
||||||
184
config.txt
184
config.txt
@@ -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
|
|
||||||
|
|
||||||
@@ -1,13 +1,9 @@
|
|||||||
version: '3'
|
version: '3'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
musicbot:
|
siren:
|
||||||
build:
|
image: siren
|
||||||
context: .
|
container_name: siren
|
||||||
args:
|
|
||||||
version: 0.3.8
|
|
||||||
image: musicbot
|
|
||||||
container_name: musicbot
|
|
||||||
volumes:
|
volumes:
|
||||||
- ./data:/app
|
- ./data:/app
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|||||||
4
pom.xml
4
pom.xml
@@ -2,8 +2,8 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>com.bensherriff</groupId>
|
<groupId>com.bensherriff</groupId>
|
||||||
<artifactId>Siren</artifactId>
|
<artifactId>siren</artifactId>
|
||||||
<version>Snapshot</version>
|
<version>0.1.0</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
package com.bensherriff.siren;
|
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.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.tools.FriendlyException;
|
||||||
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
|
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
|
||||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||||
|
import net.dv8tion.jda.api.JDA;
|
||||||
import net.dv8tion.jda.api.JDABuilder;
|
import net.dv8tion.jda.api.JDABuilder;
|
||||||
import net.dv8tion.jda.api.entities.Guild;
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
import net.dv8tion.jda.api.entities.TextChannel;
|
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.managers.AudioManager;
|
||||||
import net.dv8tion.jda.api.requests.GatewayIntent;
|
import net.dv8tion.jda.api.requests.GatewayIntent;
|
||||||
import net.dv8tion.jda.api.utils.cache.CacheFlag;
|
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 javax.security.auth.login.LoginException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -24,52 +28,60 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class MusicBot extends ListenerAdapter {
|
public class MusicBot extends ListenerAdapter {
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger(MusicBot.class);
|
||||||
private final static GatewayIntent[] INTENTS = {
|
private final static GatewayIntent[] INTENTS = {
|
||||||
GatewayIntent.DIRECT_MESSAGES, GatewayIntent.GUILD_MESSAGES, GatewayIntent.GUILD_MESSAGE_REACTIONS,
|
GatewayIntent.DIRECT_MESSAGES, GatewayIntent.GUILD_MESSAGES, GatewayIntent.GUILD_MESSAGE_REACTIONS,
|
||||||
GatewayIntent.GUILD_VOICE_STATES
|
GatewayIntent.GUILD_VOICE_STATES
|
||||||
};
|
};
|
||||||
private final AudioPlayerManager playerManager;
|
private final PlayerManager playerManager;
|
||||||
private final Map<Long, MusicManager> musicManagers;
|
private final Map<Long, AudioHandler> musicManagers;
|
||||||
private final Config config;
|
private final Settings settings;
|
||||||
|
|
||||||
|
private JDA jda;
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void start() throws IOException, LoginException {
|
private static void start() throws IOException, LoginException {
|
||||||
ConfigManager configManager = new ConfigManager();
|
SettingsManager settingsManager = new SettingsManager();
|
||||||
Config config = configManager.load();
|
Settings settings = settingsManager.load();
|
||||||
MusicBot musicBot = new MusicBot(config);
|
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)
|
.enableCache(CacheFlag.MEMBER_OVERRIDES, CacheFlag.VOICE_STATE)
|
||||||
.disableCache(CacheFlag.ACTIVITY, CacheFlag.CLIENT_STATUS, CacheFlag.EMOTE)
|
.disableCache(CacheFlag.ACTIVITY, CacheFlag.CLIENT_STATUS, CacheFlag.EMOTE)
|
||||||
.addEventListeners(musicBot)
|
.addEventListeners(musicBot)
|
||||||
.setBulkDeleteSplittingEnabled(true)
|
.setBulkDeleteSplittingEnabled(true)
|
||||||
.build();
|
.build();
|
||||||
|
musicBot.setJDA(jda);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MusicBot(Config config) {
|
private MusicBot(Settings settings) {
|
||||||
this.musicManagers = new HashMap<>();
|
this.musicManagers = new HashMap<>();
|
||||||
this.config = config;
|
this.settings = settings;
|
||||||
|
|
||||||
this.playerManager = new DefaultAudioPlayerManager();
|
this.playerManager = new PlayerManager(this);
|
||||||
AudioSourceManagers.registerRemoteSources(playerManager);
|
this.playerManager.initialize();
|
||||||
AudioSourceManagers.registerLocalSource(playerManager);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized MusicManager getGuildAudioPlayer(Guild guild) {
|
public void setJDA(JDA jda) {
|
||||||
long guildId = Long.parseLong(guild.getId());
|
this.jda = jda;
|
||||||
MusicManager musicManager = musicManagers.get(guildId);
|
}
|
||||||
|
|
||||||
if (musicManager == null) {
|
public JDA getJDA() {
|
||||||
musicManager = new MusicManager(playerManager);
|
return jda;
|
||||||
musicManagers.put(guildId, musicManager);
|
}
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
@@ -92,15 +104,29 @@ public class MusicBot extends ListenerAdapter {
|
|||||||
super.onGuildMessageReceived(event);
|
super.onGuildMessageReceived(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadAndPlay(final TextChannel channel, final String trackUrl) {
|
private synchronized AudioHandler getGuildAudioPlayer(Guild guild) {
|
||||||
MusicManager musicManager = getGuildAudioPlayer(channel.getGuild());
|
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
|
@Override
|
||||||
public void trackLoaded(AudioTrack track) {
|
public void trackLoaded(AudioTrack track) {
|
||||||
channel.sendMessage("Adding **" + track.getInfo().title + "** to queue").queue();
|
channel.sendMessage("Adding **" + track.getInfo().title + "** to queue").queue();
|
||||||
|
play(channel.getGuild(), audioHandler, track);
|
||||||
play(channel.getGuild(), musicManager, track);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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();
|
channel.sendMessage("Adding **" + firstTrack.getInfo().title + "** to queue (first track of playlist " + playlist.getName() + ")").queue();
|
||||||
|
play(channel.getGuild(), audioHandler, firstTrack);
|
||||||
play(channel.getGuild(), musicManager, firstTrack);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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());
|
connectToFirstVoiceChannel(guild.getAudioManager());
|
||||||
musicManager.scheduler.queue(track);
|
audioHandler.addTrack(track);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stop(TextChannel channel) {
|
private void stop(TextChannel channel) {
|
||||||
MusicManager musicManager = getGuildAudioPlayer(channel.getGuild());
|
AudioHandler audioHandler = getGuildAudioPlayer(channel.getGuild());
|
||||||
musicManager.player.stopTrack();
|
audioHandler.stopTrack();
|
||||||
channel.getGuild().getAudioManager().closeAudioConnection();
|
channel.getGuild().getAudioManager().closeAudioConnection();
|
||||||
channel.sendMessage("Stopping music").queue();
|
channel.sendMessage("Stopping music").queue();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void skipTrack(TextChannel channel) {
|
private void skipTrack(TextChannel channel) {
|
||||||
MusicManager musicManager = getGuildAudioPlayer(channel.getGuild());
|
AudioHandler audioHandler = getGuildAudioPlayer(channel.getGuild());
|
||||||
musicManager.scheduler.nextTrack();
|
audioHandler.nextTrack();
|
||||||
|
channel.sendMessage("Skipped to next track").queue();
|
||||||
channel.sendMessage("Skipped to next track.").queue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void changeVolume(TextChannel channel, String vol) {
|
private void changeVolume(TextChannel channel, String vol) {
|
||||||
MusicManager musicManager = getGuildAudioPlayer(channel.getGuild());
|
AudioHandler audioHandler = getGuildAudioPlayer(channel.getGuild());
|
||||||
int volume = Integer.parseInt(vol);
|
int volume = Integer.parseInt(vol);
|
||||||
config.setVolume(volume);
|
settings.setVolume(volume);
|
||||||
musicManager.player.setVolume(volume);
|
audioHandler.setVolume(volume);
|
||||||
channel.sendMessage("Set volume to " + volume).queue();
|
channel.sendMessage("Set volume to " + volume).queue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO connect to user's channel instead of first voice channel
|
||||||
private static void connectToFirstVoiceChannel(AudioManager audioManager) {
|
private static void connectToFirstVoiceChannel(AudioManager audioManager) {
|
||||||
if (!audioManager.isConnected()) {
|
if (!audioManager.isConnected()) {
|
||||||
for (VoiceChannel voiceChannel : audioManager.getGuild().getVoiceChannels()) {
|
for (VoiceChannel voiceChannel : audioManager.getGuild().getVoiceChannels()) {
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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<AudioTrack> 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
80
src/main/java/com/bensherriff/siren/audio/AudioHandler.java
Normal file
80
src/main/java/com/bensherriff/siren/audio/AudioHandler.java
Normal file
@@ -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<AudioTrack> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.player.DefaultAudioPlayerManager;
|
||||||
import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers;
|
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() {
|
public void initialize() {
|
||||||
AudioSourceManagers.registerRemoteSources(this);
|
AudioSourceManagers.registerRemoteSources(this);
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
package com.bensherriff.siren;
|
package com.bensherriff.siren.settings;
|
||||||
|
|
||||||
public class Config {
|
public class Settings {
|
||||||
|
|
||||||
private String token;
|
private String token = "";
|
||||||
private String owner;
|
private String owner = "";
|
||||||
|
|
||||||
private String prefix;
|
private String prefix = "!";
|
||||||
private int volume;
|
private int volume = 100;
|
||||||
|
|
||||||
public String getToken() {
|
public String getToken() {
|
||||||
return token;
|
return token;
|
||||||
@@ -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 {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"token": "OTMyMzAxMjQ4NTQ2MzYxMzQ2.YeQ_Mg.n4H8Cl3dQ1u5aFL1ZvTmfcGwpEY",
|
"token": "OTMyMzAxMjQ4NTQ2MzYxMzQ2.YeQ_Mg.n4H8Cl3dQ1u5aFL1ZvTmfcGwpEY",
|
||||||
"owner": "250842261221277697",
|
"owner": "250842261221277697",
|
||||||
"prefix": "!",
|
"prefix": "!",
|
||||||
"volume": 50
|
"volume": 30
|
||||||
}
|
}
|
||||||
20
start.sh
20
start.sh
@@ -1,12 +1,14 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
if [ -f /config.txt ]; then
|
#if [ -f /config.txt ]; then
|
||||||
echo "configuration file found"
|
# echo "configuration file found"
|
||||||
mv /config.txt .
|
# mv /config.txt .
|
||||||
fi
|
#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
|
java -jar /usr/local/lib/siren.jar
|
||||||
wget https://github.com/jagrosh/MusicBot/releases/download/${VERSION}/JMusicBot-${VERSION}.jar
|
|
||||||
fi
|
|
||||||
|
|
||||||
java -Dnogui=true -jar JMusicBot-${VERSION}.jar
|
|
||||||
Reference in New Issue
Block a user