Stop the listener rule from locking people out on stale presence
The panel said "you are not in a voice channel" while the client showed the user sitting in the call, which also disabled the only button that could summon the bot. The SDK learns voice participants from gateway events alone — no endpoint to ask — so a bot that restarted, or missed a VoiceChannelJoin, sees every channel as empty forever, and that looks exactly like nobody listening. The rule now refuses only on proven absence: when the bot can see people in voice somewhere in the server and the requester is not among them. With no presence data at all it accepts an explicitly chosen channel and logs that it is trusting the request, and the panel falls back to the channel picker instead of a dead button. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
0b17b880d6
commit
224d5679a3
+17
-4
@@ -32,6 +32,7 @@ export interface ServerRef {
|
||||
*/
|
||||
export interface StoatContext {
|
||||
findUserVoiceChannel(serverId: string, userId: string): VoiceChannelRef | null;
|
||||
hasVoicePresence(serverId: string): boolean;
|
||||
getVoiceChannel(channelId: string): VoiceChannelRef | null;
|
||||
listVoiceChannels(serverId: string): VoiceChannelRef[];
|
||||
getServerName(serverId: string): string | null;
|
||||
@@ -143,16 +144,28 @@ export class MusicManager extends EventEmitter<ManagerEvents> {
|
||||
|
||||
const listening = this.chat.findUserVoiceChannel(serverId, userId);
|
||||
|
||||
if (config.REQUIRE_LISTENER) {
|
||||
if (config.REQUIRE_LISTENER && listening) {
|
||||
// Music follows the listener: you cannot push the bot into a channel you
|
||||
// are not sitting in, and you cannot start playback from nowhere.
|
||||
if (!listening) throw new UserFacingError("Сначала зайдите в голосовой канал");
|
||||
// are not sitting in.
|
||||
if (options.voiceChannelId && options.voiceChannelId !== listening.id) {
|
||||
throw new UserFacingError("Бота можно позвать только в тот канал, где вы находитесь");
|
||||
}
|
||||
} else if (config.REQUIRE_LISTENER) {
|
||||
// Refuse only when we can actually see who is in voice. With no presence
|
||||
// data at all our view is stale rather than empty, and blocking would
|
||||
// strand everyone until the next restart.
|
||||
if (this.chat.hasVoicePresence(serverId)) {
|
||||
throw new UserFacingError("Сначала зайдите в голосовой канал");
|
||||
}
|
||||
if (!options.voiceChannelId) {
|
||||
throw new UserFacingError(
|
||||
"Не вижу, кто в голосовых каналах — выберите канал явно (в панели он появится в списке)",
|
||||
);
|
||||
}
|
||||
log.warn({ serverId, userId }, "voice presence unknown, trusting the requested channel");
|
||||
}
|
||||
|
||||
const target = config.REQUIRE_LISTENER
|
||||
const target = config.REQUIRE_LISTENER && listening
|
||||
? listening
|
||||
: (options.voiceChannelId
|
||||
? this.chat.getVoiceChannel(options.voiceChannelId)
|
||||
|
||||
Reference in New Issue
Block a user