Музыкальный дискорд бот на lavaplayer загружает музыку, но никогда не воспроизводит ее
Работаю над discord ботом, одной из функций которого должен стать заказ музыки. Когда дописывал, приходил к тому, что при использовании команды бот подключается к каналу, загружает трек из указанной ссылки, но не воспроизводит его, при этом никаких ошибок в консоли не возникает. Пересмотрел 3 руководства, даже полностью копировал код, который работает у авторов, но проблема осталась. Использую Java, IntelliJ IDEA, maven, JDA 5.0.0-alpha.11, lavaplayer 1.3.77. Подозреваю, что проблема заключается в нехватке каких-либо прав. Код ниже:
- Main
public static void main(String[] args) throws Exception {
JDA jda = JDABuilder.createDefault(TOKEN).setChunkingFilter(ChunkingFilter.ALL)
.setMemberCachePolicy(MemberCachePolicy.ALL).enableIntents(GatewayIntent.GUILD_MEMBERS,
GatewayIntent.GUILD_MESSAGES,
GatewayIntent.GUILD_VOICE_STATES).build();
jda.addEventListener(new checker());
}
- AudioSendHandler
public class AudioForwarder implements AudioSendHandler {
private final AudioPlayer player;
private final Guild guild;
private final ByteBuffer buffer = ByteBuffer.allocate(1024);
private final MutableAudioFrame frame = new MutableAudioFrame();
private int time;
public AudioForwarder(AudioPlayer player, Guild guild) {
this.player = player;
this.guild = guild;
frame.setBuffer(buffer);
}
@Override
public boolean canProvide() {
boolean canProvide = player.provide(frame);
if(!canProvide) {
time += 20;
if(time >= 300000) {
time = 0;
guild.getAudioManager().closeAudioConnection();
}
} else {
time = 0;
}
return canProvide;
}
@Nullable
@Override
public ByteBuffer provide20MsAudio() {
final Buffer tmp = ((Buffer) buffer).flip();
return (ByteBuffer) tmp;
}
@Override
public boolean isOpus() {
return true;
}
}
- TrackScheduler
public class TrackScheduler extends AudioEventAdapter {
private final AudioPlayer player;
private final BlockingQueue<AudioTrack> queue = new LinkedBlockingQueue<>();
private boolean isRepeat = false;
public TrackScheduler(AudioPlayer player) {
this.player = player;
}
@Override
public void onTrackEnd(AudioPlayer player, AudioTrack track, AudioTrackEndReason endReason) {
if(isRepeat) {
player.startTrack(track.makeClone(), false);
} else {
player.startTrack(queue.poll(), false);
}
}
public void queue(AudioTrack track) {
if(!player.startTrack(track, true)) {
queue.offer(track);
}
}
public AudioPlayer getPlayer() {
return player;
}
public BlockingQueue<AudioTrack> getQueue() {
return queue;
}
public boolean isRepeat() {
return isRepeat;
}
public void setRepeat(boolean repeat) {
isRepeat = repeat;
}
}
- GuildMusicManager
public class GuildMusicManager {
private TrackScheduler trackScheduler;
private AudioForwarder audioForwarder;
public GuildMusicManager(AudioPlayerManager manager, Guild guild) {
AudioPlayer player = manager.createPlayer();
trackScheduler = new TrackScheduler(player);
player.addListener(trackScheduler);
audioForwarder = new AudioForwarder(player, guild);
}
public TrackScheduler getTrackScheduler() {
return trackScheduler;
}
public AudioForwarder getAudioForwarder() {
return audioForwarder;
}
}
- PlayerManager
public class PlayerManager {
private static PlayerManager INSTANCE;
private Map<Long, GuildMusicManager> guildMusicManagers = new HashMap<>();
private AudioPlayerManager audioPlayerManager = new DefaultAudioPlayerManager();
private PlayerManager() {
AudioSourceManagers.registerRemoteSources(audioPlayerManager);
AudioSourceManagers.registerLocalSource(audioPlayerManager);
}
public static PlayerManager get() {
if(INSTANCE == null) {
INSTANCE = new PlayerManager();
}
return INSTANCE;
}
public GuildMusicManager getGuildMusicManager(Guild guild) {
return guildMusicManagers.computeIfAbsent(guild.getIdLong(), (guildId) -> {
GuildMusicManager musicManager = new GuildMusicManager(audioPlayerManager, guild);
guild.getAudioManager().setSendingHandler(musicManager.getAudioForwarder());
return musicManager;
});
}
public void play(Guild guild, String trackURL) {
GuildMusicManager guildMusicManager = getGuildMusicManager(guild);
audioPlayerManager.loadItemOrdered(guildMusicManager, trackURL, new AudioLoadResultHandler() {
@Override
public void trackLoaded(AudioTrack track) {
guildMusicManager.getTrackScheduler().queue(track);
}
@Override
public void playlistLoaded(AudioPlaylist playlist) {
guildMusicManager.getTrackScheduler().queue(playlist.getTracks().get(0));
}
@Override
public void noMatches() {
}
@Override
public void loadFailed(FriendlyException exception) {
}
});
}
}
- Обработка /play
public void onSlashCommandInteraction(@NotNull SlashCommandInteractionEvent event) {
if (event.getName().equals("play")) {
if (!event.getMember().getVoiceState().inAudioChannel()) {
event.reply("Сначала нужно подключиться к голосовому каналу!").setEphemeral(true).submit();
} else if (!event.getChannel().getId().equals(App.rules.get("music_channel_id"))) {
event.reply("Данное действие можно использовать только в соответствующем канале!")
.setEphemeral(true).submit();
} else if (event.getOption("name").getAsString().equals("null")) {
event.reply("Необходимо указать ссылку на трек!")
.setEphemeral(true).submit();
} else {
event.getGuild().getAudioManager().openAudioConnection(event.getMember().getVoiceState().getChannel());
PlayerManager playerManager = PlayerManager.get();
event.reply("Playing").setEphemeral(true).submit();
playerManager.play(event.getGuild(), event.getOption("name").getAsString());
}
}
}
P.S. На портале разработчиков discord все права включены, на тестовом сервере бот имеет права администратора, роль бота в приоритетах стоит выше всех остальных.