A Discord bot for Phantom's server. Refactored from an earlier dynamic-lobby
Discord bot as a cleaner src-layout uv project with a fully extensible cog
architecture and a local LLM chat module.
- Dynamic lobbies (
dynamic_lobbies/listener_voice) — when a user joins the "Voice Lobby Template" voice channel, a voice lobby + chat lobby + access role are created, tracked in SQLite, and cleaned up when empty. - Rename / purge / pull utilities — rename your current voice channel, purge chat history or stale empty lobbies, and pull members into your channel with accept/reject buttons.
- LLM chat (
llm_module) — @-mention the bot in #bot_channel to talk to a local LM Studio server. Per-user chat history is persisted to JSON. - Hermes agent channel — an admin-only
hermes_agenttext channel underbot-section, reserved for exchanging hermes-agent context. Separate from the LLM module; auto-created with the rest of the structure. - Extension management — load/unload/reload cogs at runtime and a
/helpercommand that posts one embed per cog with load/unload/reload buttons into the status channel. - StalkerPlayer (
stalker_player) — a music player panel driven by buttons. Auto-boots a local Lavalink 4 server with the youtube plugin and plays/pauses/skips/loops tracks, stalking a chosen user across voice channels with optional claimable control.
- Create the bot at https://discord.com/developers/applications and copy its token.
- Configure channels: the desired server structure lives in
channel_config.json(repo root) — abot-sectioncategory withbot_chatter,bot_status,stalker_playerand the admin-onlyhermes_agent, plus the lobby categories (dynamic_voice_lobby,dynamic_chat_lobby, "Voice Lobby Template" with its join channel). Everything in this file is auto-created on first start when missing; the only manual step is copying the ids Discord assigns tobot_chatterandbot_statusinto the corresponding.enventries (BOT_CHATTER,BOT_STATUS), andstalker_playerintoSTALKER_CHANNEL. - Copy
.env.exampleto.envand fill in the values.
The music player needs a Lavalink server. The bot can boot its own:
- Place
Lavalink.jar(v4) intolavalink/— the bundled configlavalink/application.ymlenables the youtube plugin. Use Lavalink 4.1.7 or newer. 4.0.0 (bundled with the repo in the past) predates Discord's current voice-server handling: tracks load and "play", but no audio reaches the channel. The jar is gitignored (local-only); keep 4.1.7+ inlavalink/Lavalink.jar. - Provide a portable Java 17+ JRE at
lavalink/jre/bin/java.exe, or pointJAVA_PATHat any Java 17+java.exe. - Run
\stalkerin Discord; the panel posts into the configured channel. Commands:\stalker,\play <query>,\pause,\resume,\skip,\stop,\join,\leave,\stalk @user,\unstalk.
uv run phantomcoreThe console script is registered in pyproject.toml; you can also use
uv run python -m phantomcore.
Dependencies keep loose >= minimum constraints in pyproject.toml so pip
resolution stays forward-compatible. All pinned versions are currently the
latest release on PyPI and show no known CVEs at the pinned versions (checked
against the OSV database). The only routine maintenance is to refresh the lock
with
uv lock && uv sync| Variable | Required | Description |
|---|---|---|
TOKEN |
yes | Discord bot token |
GUILD_ID |
yes | Server that the bot operates in |
OWNER_ID |
yes | Bot owner (for owner-only commands) |
BOT_ID |
yes | The bot's own user id |
BOT_CHATTER |
yes | Id of the bot chat channel (LM Studio + "Online" msg); auto-created via channel_config.json, fill in the assigned id |
BOT_STATUS |
yes | Id of the extension status channel; auto-created via channel_config.json, fill in the assigned id |
EXTENSIONS |
no | Comma-separated cogs to load (default: all core cogs) |
LMSTUDIO_HOST |
no | LM Studio endpoint, default localhost:1234 |
LMSTUDIO_MODEL |
no | Model id on the LM Studio server |
SYSTEM_PROMPT |
no | System prompt used for LLM chat |
LAVALINK_HOST |
no | Lavalink endpoint, default 127.0.0.1:7867 |
LAVALINK_PASSWORD |
yes | Lavalink server password (no default; injected into the booted server) |
JAVA_PATH |
no | Path to a Java 17+ java.exe for Lavalink |
STALKER_CHANNEL |
no | Channel id for the music panel (default: the command channel); auto-created via channel_config.json, fill in the assigned id |
CLAIM_TIME |
no | Seconds to wait before control can change hands, default 300 |
MIT