Commit Graph

55 Commits

Author SHA1 Message Date
5f8dc184b4 feat(page): 대시보드 UI/UX 전면 개선 — 모바일 지원, 터치 조작, 접근성
실제 화면을 캡처해 확인한 문제:
- 모바일(390px)에서 3열 고정 레이아웃(사이드바 240 + 대기열 320)이 본문을 ~50px 로 눌러
  "로그인이 필요합니다"가 한 글자씩 세로로 표시되는 등 사실상 사용 불가였다.
- 대기열의 삭제/드래그가 hover 에서만 노출돼, hover 가 없는 터치 기기에서는 접근 자체가 불가능.
  순서 변경도 HTML5 드래그앤드롭뿐이라 모바일에서 동작하지 않았다.
- 조작 요소가 터치 기준(44px)에 한참 못 미쳤다(재생 32px, 삭제 ~24px, 진행바 높이 1px).
- 로그아웃 상태에서도 사이드바·대기열·플레이어바가 자리를 차지했고, 본문은 "로그인이 필요합니다"
  라고만 적어둔 채 정작 버튼은 우상단에만 있어 동선이 끊겼다.
- 아이콘 버튼에 접근성 이름이 없고(title 만), 검색창 안내가 로그인 전에도 "서버를 먼저 선택"이었다.

변경:
- 레이아웃: 반응형으로 재구성. 좁은 화면은 단일 컬럼 + 대기열을 슬라이드 패널(FAB/플레이어바에서 토글),
  넓은 화면은 기존 3열 유지. 로그인 전·서버 미선택 시에는 재생/대기열 영역을 아예 렌더링하지 않는다.
- 대기열: 조작 버튼 상시 노출, 좁은 화면에는 위/아래 이동 버튼 제공(드래그 대체), 넓은 화면은 드래그 유지.
  번호·곡수 표시 추가, 실패 시 이전 순서로 롤백.
- 플레이어바: 버튼을 44~48px 로 키우고 모바일은 진행바를 상단 전체 폭으로 분리. 볼륨은 좁은 화면에서 숨김.
- 검색 결과/서버 카드: 카드 전체를 버튼으로 만들어 hover 없이도 누를 수 있게 하고 재생 아이콘 상시 노출.
- 로그인 화면에 실제 로그인 버튼 배치, 서버 미선택/결과 없음 등 빈 상태 문구 정리.
- 좌측 사이드바를 안내문 전용 죽은 공간에서 "조작 중인 서버 + 서버 전환 + 사용법"으로 교체.
- 아이콘 버튼 aria-label, range input aria-label, 장식 이미지 alt="" 정리. 프로필 이미지 없을 때 이니셜 대체.

검증: tsc 통과, lint 에러 0. 실제 렌더링을 데스크톱(1440x900)·모바일(390x844)에서 캡처해
로그인 전/서버 목록/서버 상세/검색 결과/대기열 패널 화면을 모두 확인했다.
2026-09-29 13:47:26 +09:00
1021a61ead perf(search): 유튜브뮤직 검색과 ytsearch 폴백을 병렬 실행
측정으로 확인한 낭비: YoutubeMusic.getSearchUrl 적중률이 6/10(평균 548ms)이라,
빗나가는 40% 에서는 YTM 을 끝까지 기다린 뒤 다시 ytsearch(~0.5초)를 도는 순차 대기가
통째로 버려지고 있었다.

변경: resolveQuery 기본 경로에서 ytsearch 폴백 검색을 먼저 띄워두고 YTM 결과를 기다린다.
  - YTM 적중  -> 폴백 결과는 버리고 기존과 동일하게 동작(Lavalink 검색 1회가 헛돌 뿐)
  - YTM 빗나감 -> 이미 진행 중인 폴백 결과를 그대로 사용(추가 대기 0)
  - 버려지는 폴백 promise 에 catch 를 달아 unhandledRejection 방지
  - " Topic" 중복 부가 방지 조건 추가
URL 입력/`-p`(스포티파이 우선) 경로는 기존과 동일하게 동작한다.

실측 A/B(YTM 이 빗나가는 3곡, 검색+해석+리졸브 구간):
  기존 1500 / 1688 / 1391ms  ->  신규 1224 / 1180 / 1399ms
  재생은 3곡 모두 성공, 관찰 중 멈춤 0. tsc 통과.
2026-09-18 20:51:44 +09:00
8ab5b84fa7 docs(readme): 리졸버 3단계 폴백 구조 반영 + 운영본을 resolver/ 로 일원화
- resolver/ytresolver.py 를 현재 운영본(.5 /opt/ytresolver.py)과 동일하게 갱신.
  (직전 커밋에서 scripts/ 로 잘못 중복 저장했던 사본은 제거)
- 루트 README / bot README:
  - 아키텍처 다이어그램에 3단계 폴백(내부API 0.3초 / yt-dlp 상주 1.7초 / 쿠키 6~8초) 표기
  - "왜 리졸버가 필요한가"를 SABR 기준으로 갱신, upstream feat/sabr-support 가 55초에서
    403으로 끊긴다는 검증 결과와 재검증 조건을 주석으로 남김
  - 성능 메모를 현재 구조(병렬화·예열·내부API)와 실측치로 갱신
    첫 소리 약 7초 -> 4.9초 -> 2.6초 -> 1.6~2.3초, 남은 병목은 음성접속·유튜브뮤직 검색
2026-09-18 19:54:27 +09:00
79f6201f85 perf(resolver): 유튜브 내부 API(VISIONOS) 직접 호출을 0순위로 적용 — 리졸브 0.3초대
기존 상주 yt-dlp(1.7~2.3초) 앞에 내부 player API 직접 호출을 두고, 실패 시 기존 경로로
자동 폴백한다. visitorData 는 리졸버가 스스로 발급/캐시(6시간)하고 만료 시 재발급하므로
봇과의 별도 배선이 필요 없다.

경로 우선순위: 내부API(0.3초) -> 상주 yt-dlp -> yt-dlp+쿠키(연령제한)

실측(운영 적용 후):
  일반 유튜브 URL 리졸브 274~559ms (적용 전 1.7~2.3초)
  연령제한 영상은 내부API가 LOGIN_REQUIRED 를 주어 쿠키 경로로 폴백(6~8초, 정상 재생)

재생 검증(운영 리졸버 + 운영 Lavalink, 전 케이스 성공/끊김 0):
  짧은영상 18초 824ms | 일반곡 1646ms | 해외곡 2098ms | 스포티파이 2522ms
  플레이리스트 2722ms | 곡전환 2230ms(전환 6.0초)
  연령제한 4건(사용자 제공): 1453 / 1522 / 7653 / 8209ms 전부 재생 성공
  32분 연속재생: position 5,180 -> 1,920,160ms, 멈춤 0/383
리졸버 경로 통계(테스트 1시간): 내부API 9 / 상주lib 폴백 0 / 쿠키 폴백 3(연령제한)

롤백: /opt/ytresolver.py.bak-20260918-153001 로 교체 후 systemctl restart ytresolver
2026-09-18 16:32:09 +09:00
2e6c956265 ops(resolver): 상주 yt-dlp 리졸버 적용본을 저장소에 기록
운영(.5 /opt/ytresolver.py)에 적용한 내용을 형상관리한다. 기존에는 저장소 밖에만
존재해 변경 이력이 남지 않았다.

변경 핵심:
- yt-dlp zipapp 을 sys.path 에 넣어 import, YoutubeDL 인스턴스를 프로세스에 상주.
  요청마다 발생하던 프로세스 기동 비용(실측 0.40s)을 제거.
- player_client=default 단독 사용(기존 default,web_safari,tv 는 첫 번째에서 이미
  성공해 나머지 2개 시도 시간이 낭비됐음).
- 라이브러리 호출 실패 시 기존 subprocess 경로(익명 -> 쿠키)로 자동 폴백해 안전망 유지.

실측: 리졸브 4.2~4.7s -> 1.7~2.3s / 첫 소리 4.9s -> 2.6s
검증: 운영 리졸버+운영 Lavalink 로 90초 재생, 끊김 0/17. itag 251 동일, loadType=track.
롤백: /opt/ytresolver.py.bak-20260917-154054 로 교체 후 systemctl restart ytresolver
2026-09-17 15:44:43 +09:00
6de959be43 perf(play): 음성접속과 곡 해석 병렬화 + 첫 곡 yt-dlp 예열로 첫 재생 단축
기존: player_play 가 channelJoin() 완료 후에야 search() 를 시작(직렬)하고,
첫 곡은 playNext 시점에 yt-dlp 리졸브(콜드 3.6~4.2s)를 그제서야 수행했다.

- LavalinkManager.search 를 resolveQuery(해석) + addResolved(큐 반영)로 분리.
  resolveQuery 는 플레이어가 필요 없어 음성접속과 동시에 실행 가능.
- resolveQuery 가 해석 직후 prewarmTrack() 으로 첫 곡 오디오 리졸브를 즉시 예열.
  GuildPlayer.resolvePlayable 과 동일한 target 계산식을 써 캐시가 확실히 적중하게 함.
- RedisClient player_play/player_playlist: 해석을 먼저 출발시키고 음성접속과 병렬 진행.
- 구간 계측 로그 추가(음성접속/해석대기/오디오 리졸브 대기).

검증: tsc 통과. 실측 A/B(동일 조건, 미캐시 곡):
  기존 직렬 접속2.00s+리졸브3.03s = 5.03s → 신규 병렬 2.00s+0.97s = 2.98s (약 2s 단축).
2026-09-17 13:11:11 +09:00
1bb1d10b25 fix(play): 스포티파이 트랙은 유튜브뮤직 오디오로 재생(뮤비 폴백 방지)
문제: 대시보드에서 스포티파이 곡을 고르면 track.url(open.spotify.com/track/..)을
Lavalink가 그대로 resolve → 유튜브 '영상(뮤비)'으로 폴백 재생됨.

수정: LavalinkManager.search에서 스포티파이 트랙 URL을 감지하면 메타데이터
(제목+아티스트)를 조회해 YoutubeMusic.getSearchUrl ?? `ytsearch:.. Topic` 오디오
검색으로 대체. 직접 입력/대시보드/`-p` 모든 경로에 적용. youtube 등 타 URL은 무영향.

- Spotify.parseTrackId / Spotify.getTrackById 추가.
- 검증: tsc 통과, Spotify /tracks/{id} 메타데이터 조회 정상, 파싱 정상.
2026-09-13 02:21:20 +09:00
f5778a7763 Merge page-improvements: 대시보드 개선 + BRPOP RPC + 로그인 연동 2026-09-13 01:59:48 +09:00
8e3791fb37 fix(page): PlayerBar useRef 초기값의 Date.now() purity lint 에러 해소
react-hooks/purity 가 useRef 초기화의 Date.now() 호출을 에러로 잡는데,
초기값은 최초 렌더 1회만 평가되어 안전하므로 해당 라인만 eslint-disable 처리.
동작 변경 없음. npm run lint 0 errors.
2026-09-13 01:59:25 +09:00
31b64b73c5 refactor(rpc): site↔bot 명령 응답을 SETEX+폴링에서 LPUSH+BRPOP 블로킹으로 전환
- bot: reply() 헬퍼(LPUSH+EXPIRE) 추가, 67개 setex 응답 지점을 일괄 교체.
  결과키를 리스트에 push해 사이트가 BRPOP으로 블로킹 수신하도록 함.
- page(api.ts botRpc): short-polling 제거, 요청마다 전용 커넥션(duplicate)으로
  BRPOP 대기 → 응답 즉시 수신(폴링 지연/헛 GET 제거), 전용 커넥션은 finally에서 정리.
- search route: 사라진 pollIntervalMs 옵션 제거.

검증: 테스트봇(.9)+.7 Redis 실측 BRPOP 왕복 10ms, 고아 키 없음. bot tsc/page next build 통과.
2026-09-12 23:58:52 +09:00
tkrmagid
221c31bfa1 chore(page): 대시보드 배포 스캐폴딩 추가(Dockerfile + compose 예시, OAuth redirect 안내) 2026-09-12 22:56:58 +09:00
tkrmagid
1efa55c3ec fix(page+bot): 리뷰 지적사항 반영 - 서버 멤버십·같은음성채널 인가(1,2), SSE 공유구독 fan-out(3), botRpc 즉시폴링(4), 큐삭제 encoded 검증(6), 진행바 anchor 타이머(7), 캐시 파싱 가드(8), key 안정화(9), 볼륨 롤백(10), SSE 자동재연결(11), body userId 정리(12) 2026-09-12 22:49:56 +09:00
tkrmagid
ff391cc1c3 docs: README 3단 구성 - 루트(리포 개요/아키텍처), bot/(봇 상세), page/(대시보드 상세) 2026-09-12 22:17:59 +09:00
tkrmagid
cb224cad88 docs(README): 첫 재생 프리워밍+coalescing, 검색 순서(YTM우선→ytsearch Topic)·플래그 문서화 2026-09-12 20:31:58 +09:00
tkrmagid
3a4849acab perf(재생지연): 유튜브 URL 음성접속 전 프리워밍 + 리졸버 진행요청 합치기(coalescing)로 첫 재생 지연 ~2초 단축 2026-09-11 23:02:35 +09:00
tkrmagid
e73f23582c feat(search): 기본 검색을 유튜브뮤직 우선 → 없/이상하면 ytsearch+Topic 폴백으로 변경(-p로 스포티파이 우선) 2026-09-11 20:43:36 +09:00
tkrmagid
3301913e7c fix(YoutubeMusic): 컴필레이션/방송/플레이리스트 패턴도 후순위·배제(원곡 우선, 폴백 활용) 2026-09-11 15:38:36 +09:00
tkrmagid
ddf8801db7 fix(YoutubeMusic): 검색어-제목 관련성 검사 추가 - 무관한 일반영상(토크쇼/재생목록)이면 ytsearch Topic 폴백 2026-09-11 15:37:23 +09:00
tkrmagid
fd92995255 fix(YoutubeMusic): 최상위 결과가 커버/MR류면 null 반환하여 ytsearch Topic 폴백 사용(재생 품질 보호) 2026-09-11 15:35:14 +09:00
tkrmagid
83f7310d53 fix(YoutubeMusic): 검색 0건 버그 수정 - 만료된 고정 params 제거 + itemSectionRenderer 결과 파싱 + 커버/MR/노래방 후순위 정렬 2026-09-11 15:33:28 +09:00
tkrmagid
cf75d047bc docs: 리졸버 호스트 prereq(node22/yt-dlp) 명시 2026-09-11 02:43:46 +09:00
tkrmagid
56bea22e4a feat: 쿠키 파일 기반 설정(YOUTUBE_COOKIE_PATH)+리졸버 URL 설정화, 다음곡 프리페치로 재생지연 단축, ytresolver 리포 포함, 쿠키 재발급 스크립트, README 상세화 2026-09-11 02:34:55 +09:00
tkrmagid
e198c5244a feat: 성인인증(연령제한) 영상 재생 지원 - yt-dlp 리졸버 경유 http 소스 재생 + 재생실패 자동 재시도 2026-09-11 02:24:10 +09:00
adb3c59a85 fix: poToken 스크립트 node:20-alpine 크래시 수정 (jsdom 25로 다운그레이드)
jsdom 30은 require('undici') 시 webidl.util.markAsUncloneable is not a function
(node:20-alpine/undici 비호환)으로 import 단계에서 크래시 → 자식 프로세스 code 1.
jsdom 25.0.1은 undici 6를 사용해 해당 경로를 타지 않으며 node:20-alpine(musl)에서
npm ci 재현 빌드 + 실제 실행으로 poToken 생성·주입(204) 검증 완료.
또한 LavalinkManager 실패 로그가 마지막 줄(=Node.js 버전 푸터)만 남겨 원인을 가리던 문제를
전체 출력 꼬리를 남기도록 수정.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-28 23:32:34 +09:00
a090e853c2 fix: Docker base를 검증된 node:20-alpine로 유지 (better-sqlite3 musl prebuild 호환)
jsdom 30은 node>=20.19만 요구하므로 node:20-alpine로 충분.
node:22-alpine는 better-sqlite3 musl prebuild 미제공 시 소스 컴파일이 필요해 회귀 위험.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-28 23:26:39 +09:00
1263ca4308 feat: 재생 403 우회용 poToken 자동 생성·주입 (youtube-plugin 런타임 엔드포인트)
googlevideo 재생 403(스트림 거절)은 Lavalink youtube-plugin에 유효한
poToken/visitorData가 없어서 발생. 봇이 노드 ready 시점과 2시간 주기로
poToken을 생성해 Lavalink의 POST /youtube 엔드포인트에 주입한다.
- scripts/potoken-refresh.mjs: youtubei.js+bgutils-js+jsdom로 생성 후 주입 (독립 ESM 프로세스)
- LavalinkManager: ready 이벤트 + 2h 인터벌로 자식 프로세스 실행
- deps: bgutils-js 3.2.0, jsdom, youtubei.js 추가 / Docker base node:22-alpine

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-28 23:25:38 +09:00
tkrmagid
5003c044c5 fix: 재생 exception 시 errMsg 재시도 타이머로 인한 다음 곡 중복 진행 방지
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 <noreply@anthropic.com>
2026-08-17 22:01:53 +09:00
tkrmagid
6d79655181 fix: 재생 멈춤(stall) 시 다음 곡으로 자동 진행
노래가 2/3 지점 등에서 버퍼링/멈춘 뒤 다음 곡으로 넘어가지 않고 프리징되던 문제 해결.
- stuck 이벤트: 기존 errMsg는 5초 뒤 같은 곡(queue[0])을 다시 재생해 무한 반복될 수
  있었음. stopTrack으로 end 이벤트를 유도해 실제 다음 곡으로 넘김.
- 재생 위치 멈춤 감시(watchdog) 추가: TrackStuckEvent가 안 뜨는 느린 버퍼링
  상황에서도 position이 20초간 진행 없으면 자동 스킵. start에서 시작, clearAllTimers에서 정리.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-17 21:55:05 +09:00
tkrmagid
5a81ce7416 fix: messageCreate의 미await 비동기 호출로 인한 unhandledRejection 추가 차단
기존 player가 있어 channelJoin을 건너뛰는 경로에서 search()가 노드 미연결로
reject될 때 handleMessage는 이미 종료돼 .catch가 잡지 못하던 문제 수정.
- handleMessage 내부 search() await 처리
- prefix 명령어 경로의 messageRun() await 처리 (try/catch가 비동기 오류도 포착)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 01:35:45 +09:00
tkrmagid
d335287e7e 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>
2026-06-11 01:32:32 +09:00
tkrmagid
67ff52227d Merge dev into master: 폴백 dedup ID 수정 2026-05-27 20:37:27 +09:00
tkrmagid
09684b2070 bot: Spotify→YouTube 폴백 dedup ID를 YouTube seed로 사용
폴백 시 lastPlayed.identifier(Spotify ID)와 RD 믹스 첫 곡(YouTube ID)
비교가 안 맞아서, 방금 끝난 곡의 YouTube 버전이 자동재생 큐에 그대로
들어가던 버그 수정.

- youtubeMixFromSpotifyTrack: { result, seedYtId } 반환
- autoPlay: 폴백일 때 dedup 기준 ID를 seedYtId로 교체
2026-05-27 20:37:22 +09:00
tkrmagid
e8c63a2118 Merge dev into master: Spotify 자동재생 폴백 2026-05-27 20:33:54 +09:00
tkrmagid
5756f4e10a bot: Spotify 자동재생 폴백 (sprec EMPTY → YouTube RD 믹스)
- sprec이 EMPTY/ERROR/빈 PLAYLIST면 곡 메타데이터(artist, title)로
  ytsearch 후 첫 결과의 videoId로 RD<id> 믹스를 가져와 자동재생 큐 채움
- 리뷰어 확인: ytmsearch는 현재 Lavalink에서 EMPTY를 반환해서 ytsearch 사용
- sprec / 검색 / 믹스 resolve 각 단계에 try/catch 추가 (한 단계 실패 시
  다음 단계로 진행하지 않고 폴백 또는 end로 안전하게 빠짐)
- 진단 로깅: sprec loadType, 폴백 사유, 검색 매칭 videoId, 최종 후보 곡수
2026-05-27 20:33:28 +09:00
tkrmagid
083b54e14e Merge dev into master: 코드 품질 개선 + 음성 WS 자가회복 2026-05-27 20:26:55 +09:00
tkrmagid
e476e23d37 Merge master into dev: 대소문자 수정 통합
origin/master의 c86bc25 (bot/src/utils/shuffle.ts → Shuffle.ts 대소문자 수정)을
dev에 머지. dev에는 이미 26393fe에서 같은 rename + import 경로 갱신이
들어가 있어서 파일명/경로 충돌은 그대로 dev쪽 유지.

Shuffle.ts 내용 충돌은 dev쪽 (d0dcdb1 코드 품질 개선의 Fisher-Yates 1-pass
구현) 유지. master는 d0dcdb1 이전이라 fshuffle 다중 셔플 구버전이었음.
2026-05-16 02:51:04 +09:00
c86bc252f3 대소문자 수정 2026-05-16 02:48:30 +09:00
tkrmagid
a4b3d40efa bot: 음성 WS 끊김 진단 로깅 + 자가 회복
- closed 이벤트에서 code/reason/byRemote 로깅 (4006/4014/4015 등 원인 식별)
- 5초 후 봇이 보이스 채널에 남아있으면 player를 새로 만들어 현재 곡을
  position 그대로 이어서 재생 (일시정지/볼륨 상태도 복원)
- 재접속 실패 시에만 기존처럼 player 정리
- 라우터/네트워크 일시 끊김(4006 세션 만료 등) 시 사용자 체감 끊김 최소화
2026-05-14 11:27:56 +09:00
26393fec2f bot/utils/shuffle.ts → Shuffle.ts 대문자 통일
리눅스 빌드 환경에서 대소문자 잔존 파일과 충돌(TS1261)을 막기 위해
파일명을 PascalCase 로 통일하고 import 경로도 동일하게 수정.
2026-04-28 16:09:29 +09:00
b670a61192 page 전체 코드 품질/보안 개선 및 봇 RPC 검증 정합
[보안/인증]
- 모든 player/queue API 라우트에 세션 가드 추가 (이전: /api/servers 만 보호)
- NextAuth 환경변수 부팅 시점 검증, NEXTAUTH_SECRET 명시
- next.config.ts CSP/보안 헤더 추가, 잘못된 allowedDevOrigins 제거
- Redis 호스트 하드코딩 IP 제거(필수 env 로 강제)

[안정성]
- 봇 RPC 패턴(@/lib/api) 공용화: crypto.randomUUID requestId, JSON.parse 안전, EXPIRE 자동, 폴링 백오프
- SSE(@/lib/sse) 공용화: subscriber error 처리, JSON.parse 안전, 30초 keep-alive, abort/에러 정리
- pause API 양 끝(boolean) 정상화: 프론트 String() 캐스트 + 백엔드 .trim().toLowerCase() 비교 제거
- 봇 RedisClient: isPaused/index/seek/volume falsy 거부 → typeof 검사로 교체(0/false 정상 허용)

[타입/품질]
- next-auth 모듈 보강 → session.user.id, session.accessToken 타입 안전
- DiscordServer/Track/SearchTrack 공용 타입 도입, 컴포넌트 any 제거
- BigInt permissions 안전 검증(타입 가드)
- Logger: NODE_ENV 게이트, error → stderr, ISO 기반 안전 timestamp
- tsconfig target → ES2020 (BigInt 리터럴)

[취약점]
- next 16.2.2 → 16.2.4 (DoS/postcss XSS 패치)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-28 14:56:55 +09:00
e5f3b87b1d package-lock.json 정리 (axios 제거 및 npm audit fix)
- 이전 커밋에서 제거한 axios가 lock 파일에 남아있던 것 정리
- npm audit fix로 transitive 의존성 보안 패치 적용 완료
- 보안 취약점 0건 (이전: high 2, moderate 1)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-27 02:01:14 +09:00
d0dcdb1563 bot 전체 코드 품질 개선 및 버그 수정
- GuildPlayer: 타이머 레이스 컨디션 수정, 모든 타이머 정리 로직 통합 (clearAllTimers)
- GuildPlayer: 이벤트 핸들러에 try-catch 추가 (end, exception, stuck)
- GuildPlayer: start 이벤트에서 endTimer 정리, autoPlay tracks 길이 검증 추가
- RedisClient: player_seek, player_volume에 누락된 return ���가
- RedisClient: queue_remove 인덱스 검증 주석 명확화
- Handler: runCommand에 try-catch 추가하여 에러 시 사용자에게 응답
- Channel: getGuildById에 누락된 await 추가, getMemberById/getVoiceChannelById 안전한 에러 처리
- Command.d.ts: 잘못된 타입 ChatInputChatInputCommandInteraction → ChatInputCommandInteraction 수정
- join.ts: 채널 멘션 닫는 괄호 누락 수정
- shuffle.ts: 제네릭 타입 적용, 불필요한 5회 반복 제거
- import 경로 대소문자 수정 (Shuffle → shuffle) - Linux 호환
- YoutubeMusic/Spotify: 하드코딩된 IP를 환경변수로 분리
- console.log/error → Logger 통일 (YoutubeMusic, Button, channel)
- interactionCreate: 전체 try-catch 추가, silent catch에 로깅 추가
- Database: schema 경로 __dirname 기반으로 수정, 컬럼 화이트리스트 추가
- 사용하지 않는 코드 정리 (axios 의존성, 주석처리된 user 관련 코드)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-26 23:13:16 +09:00
fefdf1fcdb README에 claude code 개발중 항목 추가
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-26 22:52:48 +09:00
tkrmagid-desktop
04044650d0 redis onoff만들어서 쓸때만 .env에 on하기 2026-04-26 20:23:17 +09:00
tkrmagid-desktop
3864b5d082 의도치않은 종료시 오류코드 작성하게 변경 2026-04-26 20:22:59 +09:00
tkrmagid-desktop
7c4c32d849 혼자음성 나가는 오류수정
확실히 이거때문인지는 몰라도 문제가 있어서 수정함
2026-04-26 20:22:40 +09:00
tkrmagid-desktop
cbd56126f7 주석처리
자꾸 오류나서 주석처리했음
2026-04-26 20:20:03 +09:00
tkrmagid-desktop
4037afeb68 수정 2026-04-11 14:22:48 +09:00
tkrmagid-desktop
b329ccc03b README 업데이트 2026-04-10 00:42:26 +09:00
tkrmagid-desktop
374fbdb1ce 대부분 모든기능 제작
하단 player연결, 일시정지, 스킵, 볼륨, 특정시간재생, queue 디자인 변경, queue 변경기능 제작
2026-04-10 00:40:40 +09:00