fix: Lavalink 노드 미연결 시 unhandledRejection 방지

노드가 CONNECTED 상태가 아닐 때 joinVoiceChannel이 throw 되어
fire-and-forget handleMessage에서 처리되지 않은 Promise 거부로 번지던 문제 수정.
- LavalinkManager.hasReadyNode() 추가
- channelJoin에서 노드 미연결 시 안내 임베드 반환 + join try/catch
- messageCreate의 handleMessage 호출에 .catch 추가

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
tkrmagid
2026-06-11 01:32:32 +09:00
parent 67ff52227d
commit d335287e7e
3 changed files with 36 additions and 5 deletions

View File

@@ -3,6 +3,7 @@ import { client, lavalinkManager } from "../index";
import { Command } from "../types/Command";
import { GuildPlayer } from "../classes/GuildPlayer";
import { getTextChannelAndMsg } from "../utils/music/Channel";
import { Logger } from "../utils/Logger";
/** join 명령어 */
export default class implements Command {
@@ -73,15 +74,38 @@ export async function channelJoin(guild: Guild | null, voiceChannelId: string |
let player = lavalinkManager.getPlayer(guild.id);
if (player) return { embed: client.mkembed({ title: `이미 <#${player.voiceChannelId}> 참가중입니다.` }), player };
player = new GuildPlayer(
guild,
await lavalinkManager.shoukaku.joinVoiceChannel({
// 연결 가능한 Lavalink 노드가 없으면 joinVoiceChannel이 throw 되어 unhandledRejection으로 번짐.
// 노드 미연결 시 사용자에게 안내만 하고 종료.
if (!lavalinkManager.hasReadyNode()) {
return { embed: client.mkembed({
title: "음악 서버에 연결할 수 없습니다.",
description: "잠시 후 다시 시도해주세요.",
color: "DarkRed",
}) };
}
let voicePlayer;
try {
voicePlayer = await lavalinkManager.shoukaku.joinVoiceChannel({
guildId: guild.id,
channelId: voiceChannel.id,
shardId: guild.shardId,
deaf: true,
mute: false,
}),
});
} catch (err) {
Logger.error(`[channelJoin] 음성채널 참가 실패: ${String(err)}`);
return { embed: client.mkembed({
title: "음성채널 참가에 실패했습니다.",
description: "잠시 후 다시 시도해주세요.",
color: "DarkRed",
}) };
}
player = new GuildPlayer(
guild,
voicePlayer,
voiceChannel.id,
channel,
msg,