A Discord bot that streams a radio station into a voice channel, tracks recently played songs, and (optionally) fetches song metadata from Spotify.
Quick pointers:
- Main implementation: radio.py
- Example environment variables: .env.example
- Dependencies: requirements.txt
- License: LICENSE
- Join a user's voice channel and stream a radio URL into the channel (/radio) — implementation:
radio. - Pause/resume the audio stream (/pause, /resume) — implementations:
pause,resume. - Stop and disconnect the bot (/stop) — implementation:
stop. - Show current song from a station API (/nowplaying) using
get_title_from_apiand detect commercial breaks withget_title_normalized. - Fetch richer metadata (artists, album, cover, Spotify link) via Spotify using
get_song_detailsand display it withpopulate_np_embed. - Maintain a rolling history of up to 50 last played songs and display them with
lastplayedandpopulate_lp_embed. - Background updater that polls the station API and updates history/status:
update_song_history. - Bot activity status updated via
update_activity.
- Python 3.10+ recommended.
- FFmpeg installed on the host for voice streaming (used by discord.py FFmpeg audio source).
- A Discord bot token and a server where you can add the bot.
- (Optional) Spotify developer credentials if you want detailed song metadata.
Install Python dependencies:
pip install -r requirements.txtSee: requirements.txt
- Copy
.env.exampleto.env:- See the template at .env.example
- Fill required variables:
- DISCORD_TOKEN — your Discord bot token (required)
- RADIO_URL — streaming URL for the radio (required)
- SONGS_URL — JSON API endpoint that returns current track info (recommended)
- KEYWORD — a keyword used to detect commercial breaks in the returned title (recommended)
- SPOTIFY_CLIENT_ID and SPOTIFY_CLIENT_SECRET — optional, for Spotify metadata
Important: Keep the
.envsecret. The repo already lists.envin .gitignore.
- Create a bot in the Discord Developer Portal and copy the token into
DISCORD_TOKEN. - Invite the bot to your server with scopes
botandapplications.commands, and grant it the permissions to connect and speak in voice channels
Start the bot from the project root:
python radio.pyThe bot will:
- Load env variables via python-dotenv.
- Connect to Discord using
DISCORD_TOKEN. - Sync slash commands on ready.
- Start the background poller
update_song_historywhich runs every minute (configurable in code).
- /radio — join your voice channel and stream the configured
RADIO_URL(radio). - /pause — pause playback (
pause). - /resume — resume playback (
resume). - /stop — stop and disconnect (
stop). - /nowplaying — show the currently playing song (uses
get_title_from_apiandget_song_details). - /lastplayed — show recent songs saved in memory (
lastplayed`).
The get_title_from_api helper expects SONGS_URL to return JSON with an "icestats" object that includes a "title" field somewhere inside a nested dict. Adjust logic in get_title_from_api if your station's API format differs.
- If slash commands don't appear immediately, wait up to an hour for global sync or use a guild-specific sync during development by modifying
bot.tree.sync()in radio.py. - If Spotify metadata is not shown, ensure
SPOTIFY_CLIENT_IDandSPOTIFY_CLIENT_SECRETare set and valid. - If streaming fails, verify FFmpeg is available on PATH and
RADIO_URLis a valid stream. - The bot prints warnings when optional config is missing; check console logs for messages printed by radio.py.
- Do not commit your
DISCORD_TOKENor Spotify credentials. Use.envor a secrets manager. - The bot keeps an in-memory history (
song_history) of last songs (up to 50) and does not persist them to disk.
This project is covered under the terms in LICENSE.