From 5003c044c513ea5c7f056d4679ac55b62c2731ce Mon Sep 17 00:00:00 2001 From: tkrmagid Date: Mon, 17 Aug 2026 22:01:53 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EC=9E=AC=EC=83=9D=20exception=20?= =?UTF-8?q?=EC=8B=9C=20errMsg=20=EC=9E=AC=EC=8B=9C=EB=8F=84=20=ED=83=80?= =?UTF-8?q?=EC=9D=B4=EB=A8=B8=EB=A1=9C=20=EC=9D=B8=ED=95=9C=20=EB=8B=A4?= =?UTF-8?q?=EC=9D=8C=20=EA=B3=A1=20=EC=A4=91=EB=B3=B5=20=EC=A7=84=ED=96=89?= =?UTF-8?q?=20=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lavalink는 exception 직후 TrackEndEvent(loadFailed)를 보내 end 핸들러가 다음 곡을 진행시킨다. 기존 exception 핸들러의 errMsg는 5초 뒤 queue[0]을 다시 재생해, 이미 진행된 다음 곡을 재시작시키는 부작용이 있었음. - errMsg에 retry 파라미터 추가(기본 true). exception 경로는 retry=false로 호출. - exception이 end를 유발하므로 stopTrack은 부르지 않음(중복 end로 곡 하나 더 스킵 방지). Co-Authored-By: Claude Opus 4.7 --- bot/src/classes/GuildPlayer.ts | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/bot/src/classes/GuildPlayer.ts b/bot/src/classes/GuildPlayer.ts index c40083b..e65bfc6 100644 --- a/bot/src/classes/GuildPlayer.ts +++ b/bot/src/classes/GuildPlayer.ts @@ -103,8 +103,11 @@ export class GuildPlayer { this.player.on("exception", async (data) => { try { - Logger.error(`[Lavalink] 재생 중 에러 발생: ${data.exception?.message}`); - await this.errMsg("유튜브 차단 또는 재생 오류로 인해 이 곡을 건너뜁니다."); + Logger.error(`[Lavalink] 재생 중 에러 발생: ${data.exception?.message}. 다음 곡으로 넘어갑니다.`); + // Lavalink는 exception 직후 TrackEndEvent(loadFailed)를 보내므로 end 핸들러가 다음 곡을 + // 진행시킨다. 여기서 stopTrack을 부르면 end가 중복 발생해 곡을 하나 더 건너뛰므로, + // 안내만 하고 errMsg의 5초 재시도 타이머는 끈다(retry=false). + await this.errMsg("유튜브 차단 또는 재생 오류로 인해 이 곡을 건너뜁니다.", false); } catch (err) { Logger.error(`[GuildPlayer] exception 이벤트 처리 중 에러: ${String(err)}`); } @@ -537,7 +540,7 @@ export class GuildPlayer { }); } - public async errMsg(reason: string) { + public async errMsg(reason: string, retry: boolean = true) { if (!this.msg) return null; await this.msg.edit({ content: this.msg.content, @@ -553,10 +556,14 @@ export class GuildPlayer { this.queue.length > 1, ) ] }); - this.errorTimer = setTimeout(() => { - this.errorTimer = undefined; - this.playNext(); - }, DelayAfterErrMs); + // retry=true일 때만 5초 뒤 현재 queue[0]을 재생. 재생 실패(exception)처럼 Lavalink가 + // 이미 end 이벤트로 다음 곡을 진행시키는 경우엔 retry=false로 호출해 중복 진행을 막는다. + if (retry) { + this.errorTimer = setTimeout(() => { + this.errorTimer = undefined; + this.playNext(); + }, DelayAfterErrMs); + } return null; } } \ No newline at end of file