tkrmagid a491a1a98e feat(page): 대시보드 디자인을 유튜브 뮤직(웹) 다크 테마로 전면 교체
- 상단 바: ☰ + 로고 + 반투명 검색창 + 프로필 메뉴(좁은 화면은 돋보기 → 전체 폭 검색)
- 왼쪽 메뉴: 홈/서버 목록 + 봇이 있는 내 서버 목록, 넓은 화면 펼침(240)/접힘(72), 좁은 화면 서랍
- 홈: 서버를 원형 카드로, 서버 페이지: 앨범 페이지 형태(왼쪽 아이콘·정보, 오른쪽 재생 목록)
- 검색: 필터 칩(전체/노래/동영상/Spotify) + 상위 검색결과 카드 + 구역별 목록(모두 표시)
- 하단 재생바: 위쪽 빨간 진행선, 조작·시간 / 곡 정보 / hover 볼륨·재생 화면(⌃)
- 재생 화면: 큰 앨범아트 + 다음 트랙 탭, 좁은 화면은 전체 화면 플레이어
- 재생/대기열/서버 로직을 hooks(usePlayer/useQueue/useServers)로 분리해 구독을 한 번만 연다
- 스낵바 알림, 파비콘, README 화면·버튼 문서 갱신

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 05:04:49 +09:00

music_bot_v2

디스코드 음악봇 + 웹 대시보드 모노레포. 디스코드에서 명령으로 음악을 틀 수도 있고, 웹에서 로그인해 검색·재생·대기열을 제어할 수도 있다. 성인인증(연령제한) 영상 재생까지 지원한다.

구성

디렉터리 내용 문서
bot/ 디스코드 봇 본체(discord.js + shoukaku/Lavalink). 검색·재생·대기열·자동재생·연령제한 우회. bot/README.md
page/ 웹 대시보드(Next.js 16 + NextAuth + Redis). 브라우저에서 봇 제어·상태 표시. page/README.md
resolver/ ytresolver.py — 오디오 URL 리졸버(+systemd 유닛). 유튜브 내부 API 우선, 실패 시 yt-dlp로 폴백. 봇이 SABR/연령제한 우회에 사용. 아래 + bot/README §1·2
scripts/ refresh-cookies.mjs — 유튜브 쿠키(ytcookie.txt) 재발급 스크립트(Chromium). bot/README §4

전체 아키텍처

                         ┌─────────────── 디스코드 제어 평면 ───────────────┐
[Discord 유저] ── 명령 ──▶ 봇(music1/2/3, .5 docker) ── shoukaku ──▶ Lavalink(.6:2333)
                               │  ▲                                   └ youtube-plugin(일반)
                               │  │ 재생 직전 리졸브
                               ▼  │
                         ytresolver(.5:8779) ─┬─ ① 유튜브 내부 API(VISIONOS)  ~0.3초
                               │              ├─ ② yt-dlp 상주 호출          ~1.7초
                               │              └─ ③ yt-dlp + 쿠키(연령제한)    ~6~8초
                               │                                   ──▶ 직접 오디오 URL
                               │                                   (Lavalink http 소스로 재생)
                               │
         ┌───────── Redis(.7) Pub/Sub + Key ─────────┐   ← 제어/상태 버스
         │                                           │
[브라우저] ──▶ 웹 대시보드 page/(Next.js, NextAuth) ──┘
              · site→bot: "site-bot" 명령 + 결과키 폴링(botRpc)
              · bot→site: "bot-site" 이벤트 → SSE 실시간 표시
  • 봇과 대시보드는 직접 연결되지 않고 Redis로 느슨하게 연동된다(대시보드는 Redis만 있으면 봇과 통신).
  • 유튜브가 스트리밍을 SABR 방식으로 바꾼 뒤 Lavalink의 youtube-plugin(1.18.2)만으로는 실재생이 막힌다. 그래서 resolver/가 재생 직전에 직접 오디오 URL을 뽑아 주고, 봇은 그 URL을 Lavalink http 소스로 재생한다.
  • 리졸버는 3단계로 폴백한다. ①이 대부분을 처리하고, 연령제한처럼 로그인이 필요한 영상만 ③으로 내려간다.
    1. 유튜브 내부 API(VISIONOS 클라이언트) — player API 한 번으로 오디오 직링크 획득(~0.3초). visitorData는 리졸버가 스스로 발급·캐시(6시간)하고 만료 시 자동 재발급한다.
    2. yt-dlp 상주 호출 — zipapp을 import해 YoutubeDL 인스턴스를 재사용(프로세스 기동 비용 제거, ~1.7초).
    3. yt-dlp + 쿠키 — 연령제한(로그인 필요) 영상 전용 경로(68초).
  • 봇 서버(.5)와 Lavalink(.6)가 같은 공인 IP라, .5에서 뽑은 스트림 URL을 .6이 그대로 재생한다.
  • 첫 곡 재생 지연은 음성채널 접속과 곡 해석을 병렬로 돌리고, 곡이 정해지는 즉시 리졸브를 예열해 줄였다 (bot/src/classes/LavalinkManager.ts의 resolveQuery/prewarmTrack).

빠르게 보기

  • 봇 배포/쿠키/검색·재생 동작·성능·트러블슈팅 → bot/README.md
  • 대시보드 개발/환경변수/Redis 통신 구조/API·UI → page/README.md

리포 규칙

  • bot/.gitignore가 *.env, *.db를 제외 → 실제 토큰/DB는 커밋되지 않는다. 예시는 bot/.env.example.
  • 원격: Gitea git.tkrmagid.kr/tkrmagid/music_bot_v2 (master).
Description
음악봇 v2
Readme 1.8 MiB
Languages
TypeScript 88.2%
Python 8.8%
JavaScript 1.9%
CSS 0.5%
Dockerfile 0.4%
Other 0.2%