EngineBotMusic

A music bot

Node.js Other 작성자 Béret
이 템플릿 배포하기
스크린샷 1

소개

README.md

목차
GitHub에서 열기

EngineBot Music

Discord bot engine, and the music bot running on it - by levraiberet

Overview

  • EngineBot — the engine, in src/core/. Loader, router, Components v2 helpers, database drivers. Knows nothing about music.
  • Music — the bot, in src/music/, src/commands/music/, src/components/, src/events/. Built on the engine.
Commands UI Voice Multiserver Database
Prefix & Slash Components v2 DAVE (E2EE) ✅ Yes ✅ 8 drivers ✅

The bot

  • /play <link or words> — plays it, or queues it. Also !play / !p.
  • /player — brings the panel back down after the channel has scrolled.

Everything else is on the panel itself:

Button What it does
⏮️ Restart the track, or step back to the last one within the first 5s
⏸️ / ▶️ Pause and resume
⏭️ Skip
⏹️ Stop and leave
🔁 Off → repeat track → repeat queue
Add Queue a link or a search, without leaving the panel
🔀 Shuffle what's waiting
📜 The full queue, privately
🔊 Volume, 0 to 200

The panel shows the artist, the track on air, a generated progress bar that advances on its own, and the next few tracks waiting. It repaints on every click and on a slow tick, both thinned through coalesce() so Discord's rate limit is never the thing that breaks.

Add opens a small box for a link or a few words. What lands is announced in the channel under whoever asked for it, and the panel is reposted below that line so it stays the last message — a panel buried above the announcements is a panel nobody can press.

The command list is deliberately short: anything the panel already does well has no command of its own. What's left is what a button can't do — /seek, /playnext, /search, /lyrics, /volume, /skip <count>, /queue <page>.

The bot leaves on its own a minute after the last listener does.

Why it feels fast

Measured on this machine, one click used to cost about five seconds. Where it went:

Step Cost
yt-dlp lookup (spawn + network) ~2500 ms
Card render, no cover art ~20 ms
Card render, blurred cover + PNG encode ~21 ms
PNG encode alone ~10 ms

The image was never the problem — the whole card is ~20 ms. It was yt-dlp, and the panel waiting on it. Three things fixed that:

Stream URLs are cached per track for an hour (src/music/resolve.js), and the next track's URL is resolved in the background while the current one plays, so skip lands on a URL already in hand. An expired link fails on open, so play() drops it and retries once on a fresh one rather than dying on a stale entry.

The panel no longer waits for audio. Advancing the queue is instant; opening the stream is what takes seconds. So the queue moves, the panel is drawn from the new state, and the stream catches up on its own — the repaint used to sit behind the whole download.

The panel no longer waits for its own image. A fresh panel goes out in two passes: the text and the controls first, the card as an edit once it's drawn. Everything below the image builds in ~0.4 ms; the card is ~20 ms of canvas plus a 21 KB upload, and it used to go first.

The card is drawn under setImmediate(), which matters more than it looks: canvas work is synchronous once it starts, so simply not awaiting it still blocked the send for the full render. Handing it to the next tick took first paint from 23 ms to 0.45 ms.

Without the card, the panel states the track in text, so the first pass is never a blank box. An in-place repaint (the 10 s ticker) deliberately stays a single edit — the card is already on screen there, and blanking it to fill it back in would make the image flicker.

Instant controls skip the lock. Pause, shuffle and loop touch nothing but local state, so they no longer queue up behind a skip that's still resolving. Every button used to be as slow as the slowest one in flight.

Adding still costs a real lookup — nothing can remove that — so the Add button greys out and reads Adding… for its duration, and comes back whatever happens, including on a failed search.

Emojis

Buttons use the bot's application emojis through @beret.27/discord-app-emojis. src/music/emojis.js asks for play, pause, skip, previous, stop, shuffle, loop, queue, volume, mute, music, artist, disc and live, and each one falls back to its Unicode twin when the application doesn't have it. Drop matching images into ./emojis/ (play.png, skip.png, …) and the bot uploads them on first boot, and the buttons pick them up with no code change.

Voice

Audio goes out end-to-end encrypted over DAVE, Discord's voice E2EE. @discordjs/voice turns it on as soon as @snazzah/davey is installed, which is a dependency here; joinVoiceChannel passes daveEncryption: true to make the choice visible, and the connect log says whether the session negotiated it.

Tracks are resolved with yt-dlp (through youtube-dl-exec) — the stream URL is fetched at play time, not queue time, because those URLs expire in a few hours and a long queue would outlive them.

The engine

Driver What it is
auto SQLite on Node 22.5+, else enginedb. No dependency either way.
sqlite A SQLite file, through node:sqlite.
enginedb The engine's format. Append-only log, folded into a snapshot.
fusion Speed first. All in RAM. Hungry.
spectral Memory first. Interned values, deflated on disk.
json One readable JSON file.
text One key<TAB>value line per entry. Copy it for your own.
mysql A MySQL server. Needs npm install mysql2.
memory Saves nothing. For tests.

Your own driver: extend Driver, point driver at the file's path.

Setup

Bash
npm install
cp .env.example .env   # then put your token in it
npm start

The token is all it needs. The app id is read from it. Turn on the Message Content intent for the prefix commands, and the Server Members/voice states the bot already asks for come with the invite.

License

MIT

변수

배포할 때 입력하는 값이에요. 배포의 환경 변수가 돼요.

  • TOKEN TOKEN The token of the bot 필수, 시크릿
  • LAVALINK_HOST LAVALINK_HOST 필수
  • LAVALINK_PORT LAVALINK_PORT 필수
  • LAVALINK_PASSWORD LAVALINK_PASSWORD 필수
  • LAVALINK_SECURE LAVALINK_SECURE 필수

배포 방법

  1. 1 배포 페이지 열기배포 이름을 정하세요. 확인할 때 로그인해요.
  2. 2 변수 채우기템플릿이 요구하는 값이며 배포의 환경 변수로 저장돼요.
  3. 3 리소스 확인요금제의 공유 풀에서 가져와 실행해요. 모든 계정은 무료로 시작해요.

로그인하고 신고하기

악용을 막기 위해 신고는 계정과 연결돼요.

로그인