Updated docker files and layout
This commit is contained in:
@@ -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;
|
||||
|
||||
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<Long, MusicManager> musicManagers;
|
||||
private final Config config;
|
||||
private final PlayerManager playerManager;
|
||||
private final Map<Long, AudioHandler> 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()) {
|
||||
|
||||
@@ -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.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);
|
||||
@@ -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;
|
||||
@@ -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",
|
||||
"owner": "250842261221277697",
|
||||
"prefix": "!",
|
||||
"volume": 50
|
||||
"volume": 30
|
||||
}
|
||||
Reference in New Issue
Block a user