fix: rewrite radio voice connection — no thread blocking, no abort, no URL loss
- remove 30s+30s VoiceHelper.waitForCondition that blocked JDA event thread - remove abort on voice/player timeout (TrackScheduler retries sendTrack itself) - remove openAudioConnection() that conflicted with Lavalink voice interceptor - preserve stream URL across stopRadio/restart instead of losing it - pass null queueRepository to GuildMusicManager (radio has no queue persistence) - run startRadio in virtual thread from RadioBotListener/RadioCommand
This commit is contained in:
parent
37d50ab240
commit
25cf66aea2
3 changed files with 17 additions and 41 deletions
|
|
@ -91,7 +91,7 @@ public class RadioBotListener extends ListenerAdapter {
|
|||
radioManager.setRadio(guild.getIdLong(), url);
|
||||
|
||||
VoiceChannel vc = member.getVoiceState().getChannel().asVoiceChannel();
|
||||
radioManager.startRadio(guild.getIdLong(), vc.getIdLong());
|
||||
Thread.startVirtualThread(() -> radioManager.startRadio(guild.getIdLong(), vc.getIdLong()));
|
||||
|
||||
event.getChannel().sendMessage("📻 Радио запущено: **" + url + "**").queue();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package creator.loki.feature.radio;
|
|||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
|
@ -10,7 +9,6 @@ import creator.loki.feature.music.core.LavalinkManager;
|
|||
import creator.loki.feature.music.manage.GuildMusicManager;
|
||||
import creator.loki.feature.music.repository.QueueRepository;
|
||||
import creator.loki.util.LoggerDecorator;
|
||||
import creator.loki.util.VoiceHelper;
|
||||
import dev.arbjerg.lavalink.client.AbstractAudioLoadResultHandler;
|
||||
import dev.arbjerg.lavalink.client.Link;
|
||||
import dev.arbjerg.lavalink.client.player.TrackLoaded;
|
||||
|
|
@ -22,7 +20,6 @@ import org.slf4j.LoggerFactory;
|
|||
@Singleton
|
||||
public class RadioManager {
|
||||
private static final Logger logger = LoggerFactory.getLogger(RadioManager.class);
|
||||
private static final long CONNECT_TIMEOUT_MS = 30000;
|
||||
|
||||
private final Map<Long, GuildRadioState> radioStates = new ConcurrentHashMap<>();
|
||||
private final QueueRepository queueRepository;
|
||||
|
|
@ -62,11 +59,15 @@ public class RadioManager {
|
|||
GuildRadioState state = radioStates.get(guildId);
|
||||
if (state == null || state.streamUrl == null || state.streamUrl.isBlank()) return;
|
||||
if (radioJda == null || lavalinkManager == null) return;
|
||||
if (isRadioActive(guildId) && state.musicManager != null) {
|
||||
stopRadio(guildId);
|
||||
}
|
||||
var finalState = radioStates.computeIfAbsent(guildId, id -> new GuildRadioState());
|
||||
finalState.streamUrl = getRadioUrl(guildId);
|
||||
|
||||
String url = state.streamUrl;
|
||||
int vol = state.volume;
|
||||
if (state.musicManager != null) stopRadio(guildId);
|
||||
|
||||
GuildRadioState finalState = radioStates.computeIfAbsent(guildId, id -> new GuildRadioState());
|
||||
finalState.streamUrl = url;
|
||||
finalState.volume = vol;
|
||||
|
||||
Guild guild = radioJda.getGuildById(guildId);
|
||||
if (guild == null) {
|
||||
logger.warn("Radio: guild {} not found in radio bot cache", guildId);
|
||||
|
|
@ -77,45 +78,20 @@ public class RadioManager {
|
|||
logger.warn("Radio: voice channel {} not found in guild {}", channelId, guildId);
|
||||
return;
|
||||
}
|
||||
logger.debug("Radio: connecting to channel {}/{} in guild {}", vc.getName(), channelId, guildId);
|
||||
var self = guild.getMember(guild.getJDA().getSelfUser());
|
||||
if (self == null) {
|
||||
logger.warn("Radio: self member is null for guild {}", guildId);
|
||||
return;
|
||||
}
|
||||
logger.debug(
|
||||
"Radio: bot has CONNECT permission: {}",
|
||||
self.hasPermission(vc, net.dv8tion.jda.api.Permission.VOICE_CONNECT));
|
||||
guild.getJDA().getDirectAudioController().connect(vc);
|
||||
if (!guild.getAudioManager().isConnected()) {
|
||||
guild.getAudioManager().openAudioConnection(vc);
|
||||
}
|
||||
var link = lavalinkManager.getOrCreateLink(guildId);
|
||||
|
||||
VoiceHelper.waitForCondition(
|
||||
() -> self.getVoiceState().inAudioChannel(), CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
if (self.getVoiceState().inAudioChannel()) {
|
||||
logger.info("Radio: voice connected for guild {}", guildId);
|
||||
} else {
|
||||
logger.warn("Radio: voice not connected after {}ms for guild {}", CONNECT_TIMEOUT_MS, guildId);
|
||||
}
|
||||
|
||||
VoiceHelper.waitForCondition(
|
||||
() -> link.getCachedPlayer() != null, CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
if (link.getCachedPlayer() != null) {
|
||||
logger.info("Radio: player created for guild {}", guildId);
|
||||
} else {
|
||||
logger.warn("Radio: no player after {}ms for guild {}", CONNECT_TIMEOUT_MS, guildId);
|
||||
}
|
||||
|
||||
if (!self.getVoiceState().inAudioChannel() || link.getCachedPlayer() == null) {
|
||||
LoggerDecorator.warn(logger, "Radio: skipping — no voice or player for guild " + guildId);
|
||||
if (!self.hasPermission(vc, net.dv8tion.jda.api.Permission.VOICE_CONNECT)) {
|
||||
logger.warn("Radio: no CONNECT permission in channel {}/{}", channelId, guildId);
|
||||
return;
|
||||
}
|
||||
|
||||
var mm = new GuildMusicManager(guildId, lavalinkManager, queueRepository);
|
||||
int vol = finalState.volume;
|
||||
var url = finalState.streamUrl;
|
||||
var link = lavalinkManager.getOrCreateLink(guildId);
|
||||
guild.getJDA().getDirectAudioController().connect(vc);
|
||||
|
||||
var mm = new GuildMusicManager(guildId, lavalinkManager, null);
|
||||
finalState.musicManager = mm;
|
||||
lavalinkManager
|
||||
.getOrCreateLink(guildId)
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ public class RadioCommand implements Command {
|
|||
}
|
||||
|
||||
long channelId = member.getVoiceState().getChannel().getIdLong();
|
||||
radioManager.startRadio(guildId, channelId);
|
||||
Thread.startVirtualThread(() -> radioManager.startRadio(guildId, channelId));
|
||||
context
|
||||
.getChannel()
|
||||
.sendMessageEmbeds(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue