diff --git a/bot/src/classes/GuildPlayer.ts b/bot/src/classes/GuildPlayer.ts index e226bda..4b92c5b 100644 --- a/bot/src/classes/GuildPlayer.ts +++ b/bot/src/classes/GuildPlayer.ts @@ -7,6 +7,7 @@ import { GuildType } from "../../db/db"; import { DB } from "../utils/Database"; import { shuffle } from "../utils/Shuffle"; import { checkTextChannelAndMsg } from "../utils/music/Channel"; +import { Logger } from "../utils/Logger"; const DelayAfterErrMs = 1000 * 5; const idleEndTime = 1000 * 60 * 10; @@ -50,7 +51,40 @@ export class GuildPlayer { }); this.player.on("closed", () => { if (this.isDead) return; - this.delete(); + Logger.info(`[GuildPlayer] 음성 연결이 끊어졌습니다. 재접속을 대기합니다...`); + setTimeout(() => { + if (this.isDead) return; + // 5초가 지났는데도 연결이 복구되지 않았을 때만 방을 나갑니다. + + // 디스코드 방에 내 봇(me)이 없으면 봇을 삭제(delete)한다! + if (!this.guild.members.me?.voice?.channelId) { + Logger.warn(`[GuildPlayer] 음성채널에 봇이 없습니다. player를 초기화합니다.`); + return this.delete(); + } + + /** + * declare enum State { + * CONNECTING = 0, + * CONNECTED = 1, + * DISCONNECTING = 2, + * DISCONNECTED = 3 + * } + */ + // (1 = CONNECTED, Shoukaku 버전에 따라 연결 상태 체크가 다를 수 있으니 안전하게 확인) + if (this.player && this.player.node.state !== 1) { + Logger.warn(`[GuildPlayer] 연결 복구 실패. 봇을 퇴장시킵니다.`); + return this.delete(); + } + }, 5000); + }); + + this.player.on("exception", async (data) => { + Logger.error(`[Lavalink] 재생 중 에러 발생: ${data.exception?.message}`); + await this.errMsg("유튜브 차단 또는 재생 오류로 인해 이 곡을 건너뜁니다."); + }); + this.player.on("stuck", async (data) => { + Logger.error(`[Lavalink] 곡 로딩 멈춤(Stuck) 발생: ${data.thresholdMs}ms 초과`); + await this.errMsg("음원 로딩이 멈췄습니다. 다음 곡으로 넘어갑니다."); }); }