Control Your Sonos Speakers with Community Voting
A democratic music bot for Discord and Slack that lets teams control Sonos speakers with Spotify integration. Features community voting, democratic skip tracking with "gong" commands, and seamless multi-platform support.
๐ต Perfect for: Offices, shared spaces, gaming communities, Discord servers, and music lovers who want fair queue control
โจ Key Features:
- ๐ค AI Natural Language - Talk naturally! "@bot play the best songs by Queen" (NEW!)
- ๐ณ๏ธ Democratic Voting - Community decides what plays next with vote-to-play system
- ๐ Gong System - Skip tracks democratically when enough users vote to gong
- ๐ฎ Discord Support - Full emoji reaction voting (๐ต to vote, ๐ to gong)
- ๐ฌ Slack Integration - Modern Socket Mode support with channel-based permissions
- ๐ถ Spotify Integration - Search and queue tracks, albums, and playlists
- ๐ฅ Multi-Platform - Run Discord and Slack simultaneously on one Sonos system
- ๐ฏ Role-Based Permissions - Admin controls for flush, volume, and queue management
- ๐ซ Gong Ban System - Tracks voted down become immune to re-queuing
- ๐๏ธ Soundcraft Ui24R Support - Control mixer volume on multiple buses directly from chat (NEW!)
Screenshot
SlackONOS is licensed under the GNU Affero General Public License v3 (AGPL-3.0-or-later).
- You may use, modify and redistribute this software under the terms of the AGPL-3.0 license.
- If you run a modified version as a network service, you must make the corresponding source code available to users.
- Commercial entities that wish to use SlackONOS without AGPL obligations (e.g. closed-source forks or proprietary integrations) may contact the author to discuss separate commercial licensing.
See the LICENSE file for full details.
SlackONOS respects your privacy. Optional anonymous telemetry helps us understand usage and improve the bot.
What's Collected (Anonymous Only):
- โ Startup, heartbeat (24h), and shutdown events
- โ Uptime duration (hours/days running)
- โ OS platform & Node.js version
- โ Release version/commit hash
- โ Anonymous instance ID (random UUID, persisted in config - no PII)
What's NOT Collected:
- โ No user data, usernames, or chat messages
- โ No Slack/Discord server information
- โ No song titles, playlists, or listening history
- โ No IP addresses or location data
- โ No command usage or voting patterns
Telemetry is enabled by default but can be disabled anytime:
{
"telemetryEnabled": false
}Or, disable telemetry instantly from Slack (admin channel):
setconfig telemetryEnabled false
๐ Full Telemetry Documentation - Details, privacy info, and self-hosting options
Use the telemetry admin command in Slack (admin channel) to view current status and what data is being sent.
Note: Analytics data is not publicly viewable; it is only accessible to the maintainers for improving the bot. If you self-host, you control all telemetry endpoints.
What You Need:
- A Sonos speaker configured with Spotify
- A Slack bot token OR Discord bot token (or both!)
- A server running Node.js
- Static IP address for your Sonos speaker
- Spotify Developer credentials (Client ID & Secret) from https://developer.spotify.com/dashboard/applications
Docker Installation (Recommended)
services:
slackonos:
container_name: slackonos
image: htilly/slackonos:latest
restart: unless-stopped
volumes:
- /PATH_TO_CONFIG_FOLDER:/app/config๐ Complete Discord Setup Guide - Step-by-step Discord bot configuration
๐ Complete Slack Setup Guide - Socket Mode Slack bot setup (tokens, scopes, events)
๐๏ธ Soundcraft Ui24R Integration - Control mixer volume directly from Slack/Discord
SlackONOS is a democratic music bot that gives communities fair control over shared Sonos speakers. Instead of one person controlling the music, everyone can participate through voting and democratic skip features.
Uses node-sonos for Sonos control.
- โ Slack - Modern Socket Mode with channel-based admin permissions
- โ Discord - Full support with role-based admin + emoji reaction voting
- ๐ต Shared Queue - Both platforms control the same Sonos speaker simultaneously
- ๐ณ๏ธ Cross-Platform Democracy - Gong and vote systems work across all platforms
Firewall Settings:
- Server must reach Sonos on port 1400 (TCP)
- Sonos must have internet access for Spotify streaming
- Recommended: Static IP for Sonos speaker
Configuration You must provide the token of your Slack bot and the IP of your Sonos in either config.json (see config.json.example), as arguments or as environment variables. Examples:
node index.js --legacySlackBotToken "MySlackBotToken" --sonos "192.168.0.1"or
legacySlackBotToken="MySlackBotToken" sonos="192.168.0.1" node index.jsYou can also provide any of the other variables from config.json.example as arguments or environment variables. The blacklist can be provided as either an array in config.json, or as a comma-separated string when using arguments or environment variables.
Channel Configuration (Important for Large Workspaces)
SlackONOS uses two channels: adminChannel (for admin commands) and standardChannel (for regular users).
For workspaces with 100+ channels: Use channel IDs instead of channel names to avoid Slack API rate limits during startup.
- Channel names (default):
"adminChannel": "music-admin"โ Bot scans all channels to find ID (slow, but auto-upgrades to IDs after first run) - Channel IDs (recommended):
"adminChannel": "C01ABC123XY"โ Direct lookup (instant)
๐ NEW: Auto-save Feature
If you configure channel names, SlackONOS will automatically update your config.json with the discovered IDs after the first successful startup. This means:
- First startup: Slow (1-3 minutes in large workspaces)
- All future startups: Instant (uses saved IDs)
Manual Configuration (Optional)
You can also manually set channel IDs to skip the first slow startup.
How to find Channel IDs:
- In Slack web/desktop, right-click the channel
- Select "View channel details"
- Scroll to bottom, copy the Channel ID (format:
C+ 9+ alphanumeric characters)
Example config.json:
{
"adminChannel": "C01ABC123XY",
"standardChannel": "C987DEF654",
...
}Logo for the bot in #Slack can be found at "doc/images/SlackONOS.png
Socket Mode Migration
As of v2.0, SlackONOS has migrated from the deprecated RTM API to Socket Mode for improved reliability and performance. This requires new configuration:
Required Changes:
- New App-Level Token Required: You MUST create an app-level token (starts with
xapp-) in your Slack app settings - Socket Mode Must Be Enabled: Enable Socket Mode in your Slack app configuration
- Updated Configuration: Both
slackAppToken(app-level) andtoken(bot token,xoxb-) are now required
Migration Steps:
- Go to https://api.slack.com/apps/YOUR_APP_ID/socket-mode
- Enable Socket Mode
- Generate an app-level token with
connections:writescope - Add the token to your
config.json:{ "slackAppToken": "xapp-1-A0...", "token": "xoxb-123...", ... }
Legacy Bot Token Support
- Legacy bots can no longer be created
- If you were using
legacySlackBotToken, you must create a new Slack app and configure it with Socket Mode - The
useLegacyBotconfiguration option has been removed
Architectural Improvements (v2.0)
SlackONOS v2.0 includes significant architectural improvements:
- Modular Design: Slack and Spotify integrations are now separate, clean modules (
slack.js,spotify-async.js) - Non-Blocking Operations: All Spotify API calls use async/await with native
fetch, eliminating blocking operations - Declarative Command Registry: Commands are defined in a clean, maintainable registry instead of large switch statements
- Improved Error Handling: Centralized error handling and logging for better debugging
- Robust Event Handling: Better filtering and processing of Slack events
- Network Resilience: Increased ping timeouts to handle network latency better
What can it do?
Talk to the bot naturally by mentioning it in Slack or Discord! No need to remember exact commands.
Examples:
@SlackONOS play the best songs by U2โ Queues U2's top tracks@bot add Forever Youngโ Adds the song to queue@SlackONOS what's playing?โ Shows current track@bot skip this terrible songโ Gongs the current track@SlackONOS show me the queueโ Lists all queued tracks
๐ Batch Add with Smart Themes (NEW!):
@SlackONOS add some christmas musicโ Adds 5 holiday tracks@bot play a few summer hitsโ Queues summer beach songs@SlackONOS give me 10 80s classicsโ Adds ten 80s hits@bot spela lite partylรฅtarโ Queues party music (works in Swedish!)
Quantity Words:
| Phrase | Tracks Added |
|---|---|
| "a couple", "ett par" | 2 |
| "a few", "nรฅgra" | 3-4 |
| "some", "lite", "several" | 5 |
| "many", "lots", "massa" | 8 |
| "10", "fifteen", etc. | Exact number |
Smart Theme Boosters: The AI automatically enhances searches based on detected themes:
| Theme | Triggers | Search Enhancement |
|---|---|---|
| ๐ Christmas | jul, xmas, christmas |
+christmas holiday |
| ๐ Party | party, fest, dansband |
+party upbeat |
| ๐ Chill | chill, relax, lugn, mysig |
+chill mellow |
| ๐ช Workout | workout, gym, trรคning |
+workout energetic |
| โ๏ธ Summer | sommar, summer, beach |
+summer beach hits |
| ๐ผ 80s | 80s, 80-tal, eighties |
+80s classic hits |
| ๐ฟ 90s | 90s, 90-tal, nineties |
+90s classic hits |
| ๐ธ Rock | rock, metal |
+rock classic |
| ๐ต Pop | pop, hits |
+pop hits |
| ๐บ Disco | disco, funk |
+disco dance funk |
| ๐ Ballads | ballad, kรคrleks, love |
+ballad love romantic |
| ๐ค Hip-hop | hip hop, rap, hiphop |
+hip hop rap hits |
| ๐ค Country | country, nashville |
+country hits |
| ๐ท Jazz | jazz, blues |
+jazz blues classic |
| ๐ป Classical | klassisk, classical, opera |
+classical orchestra |
| ๐ด Reggae | reggae, ska, caribbean |
+reggae caribbean |
| ๐ง Indie | indie, alternative |
+indie alternative |
| ๐ EDM | edm, electro, house, techno |
+electronic dance |
| ๐ Latin | latin, salsa, bachata |
+latin dance |
| ๐ธ๐ช Swedish | svensk, swedish |
+swedish svenska |
| ๐ถ Kids | barnlรฅt, kids, children |
+children kids |
Auto-Play Behavior:
- If music is playing: New tracks are added to the queue
- If music is stopped: Queue is cleared, tracks added, and playback starts automatically
The AI automatically knows the current season and can suggest themed music!
Seasonal Awareness: The bot detects the current month and adjusts music suggestions:
| Season | Period | Themes |
|---|---|---|
| ๐ Winter/Holiday | December - Jan 6 | Christmas, holiday classics |
| ๐ Halloween | Oct 15-31 | Spooky, horror soundtracks |
| โ๏ธ Summer | June - August | Beach vibes, feel-good hits |
| ๐ธ Spring | March - May | Uplifting, fresh vibes |
| ๐ Valentine's | Feb 10-14 | Love songs, romantic ballads |
| ๐ Autumn | Sept - Nov (early) | Cozy, acoustic, nostalgic |
| โ๏ธ Winter | Jan 7+, Feb | Cozy, chill, warming |
Example: In December, asking for "add some seasonal music" will automatically queue Christmas tracks!
Venue/Default Theme: Configure a default theme for your venue that subtly influences all bulk music requests:
setconfig defaultTheme lounge
setconfig themePercentage 30
| Setting | Values | Description |
|---|---|---|
defaultTheme |
lounge, club, office, cafe, etc. |
Base music style for your venue |
themePercentage |
0-100 | Percentage of tracks matching venue theme |
How it works:
When you request "100 christmas songs" with defaultTheme: lounge and themePercentage: 30:
- ~70 christmas songs (what you asked for)
- ~30 lounge-style tracks (venue atmosphere)
This ensures your venue's vibe is always maintained, even during themed requests!
How it works:
- Powered by OpenAI GPT-4o-mini for accurate command parsing
- Understands natural language in multiple languages (Swedish, English, etc.)
- Falls back to regular commands if AI is disabled
- Optional feature - works without AI if no API key is provided
Setup:
- Get an OpenAI API key from https://platform.openai.com/api-keys
- Add to
config.json:"openaiApiKey": "sk-proj-..." - That's it! Start mentioning the bot naturally
Note: AI parsing only activates when you @mention the bot with text that doesn't start with a known command. Regular commands (like add song name) still work instantly without AI.
Community Queue Management: The bot queues song requests and plays them in order. If enough people dislike the current track, they can use the "gong" command to democratically skip it.
Music Control:
add <song/artist/album>- Add music to the queue and start playingsearch <text>- Search for tracks without adding to queuebestof <artist>- Queue the top 10 tracks by an artistcurrent- Show currently playing track with time remaininglist- Display the current queuestatus- Show playback status
Democratic Features:
gong- Vote to skip the current track (requires multiple votes)vote <track number>- Vote to move a queued track up in prioritygongcheck- See current gong votes and who votedvotecheck- See current vote counts for tracksvolume- View current volume level
Discord Emoji Reactions:
- ๐ต - Vote for a track (click on "Added..." messages)
- ๐ - Gong/skip a track (click on "Added..." messages)
Queue Management:
flush- Clear the entire queuenext- Skip to next track immediatelyprevious- Go back to previous trackshuffle- Shuffle the playlist
Playback Control:
play- Resume playbackstop- Stop playbacksetvolume <number>- Set Sonos volume (0-100)setvolume <channel> <number>- Set Soundcraft mixer channel volume (if enabled)
System:
blacklist add <@user>- Prevent user from adding songsblacklist remove <@user>- Restore user permissionsblacklist list- Show blacklisted userssetconfig- View/change runtime settings (gongLimit, voteLimit, defaultTheme, etc.)configdump- Show all current configuration values including AI theme contextaiunparsed [N]- Show last N unparsed AI commands (default: 10)
Perfect for:
- ๐ข Office Environments - Democratic music control for shared workspaces
- ๐ฎ Discord Communities - Music bot for gaming servers and communities
- ๐ Shared Living Spaces - Fair queue management for roommates
- ๐ Events & Parties - Let guests control the music democratically
- โ Cafes & Lounges - Customer-influenced playlists with admin oversight
For detailed installation instructions, see the INSTALL file.
For Discord-specific setup, see the Discord Setup Guide.
Wiki: https://github.com/htilly/SlackONOS/wiki
Contributions are welcome! Please feel free to submit pull requests, report bugs, or suggest features.
Development:
- Run tests:
npm test - Docker build:
docker build -t slackonos . - See TESTING.md for test workflow information
Use this section to quickly diagnose AI-related issues.
- Enable/Disable AI: Set
openaiApiKeyinconfig/config.json. Remove it to disable AI (direct commands still work). - Startup Validation: On boot, the bot validates the API key by sending a tiny request.
- โ
AI natural language parsing enabled with OpenAI (API key validated) - โ
Invalid OpenAI API key format - must start with "sk-" - โ
OpenAI API key is invalid or unauthorized (401) - โ
OpenAI API quota exceeded (429)โ Check billing: https://platform.openai.com/account/billing - โ
Cannot connect to OpenAI APIโ Network/connectivity
- โ
- Runtime Errors:
AI parsing error: 429 ... quota exceededโ AI disabled automatically; bot continues with direct commandsAI parsing returned nullโ Low confidence or API failure; try clearer phrasing or use direct command
- Logs to look for:
Incoming MENTION from ...โ Message routed to AI parserโจ AI parsed: "..." โ add [...]/bestof [...] (95%)โ Parsed successfullyAI add: applied boosters [christmas holiday] โ query "..."โ Theme detected and search enhancedAI add: deduplicated 50 โ 32 unique, selecting top 5โ Duplicates filtered outAI add: current state = stoppedโ Auto-play mode activatedAI disabled, falling back to standard processingโ No key or validation failed
- Admin Commands:
aiunparsed- View recent commands that AI couldn't parse (useful for training/debugging)configdump- View all current config values including AI settings
- Common Pitfalls:
- Duplicate handling in Slack: we ignore
messageevents containing<@bot>and only processapp_mentionto prevent doubles. - Natural language like
"One med U2"is sanitized to"One U2"to improve Spotify matching. - Batch-add deduplicates tracks by normalized name (removes "- Single Edit", "Remaster", etc.)
- Duplicate handling in Slack: we ignore
- Cost Notes: Uses GPT-4o-mini; typical requests are very cheap (~$0.0001/request). Direct commands never call AI.
Discord music bot, Slack music bot, Sonos Discord integration, democratic music voting, office music bot, Spotify Discord controller, Sonos Slack bot, community music control, democratic skip, vote-to-play, gaming server music, shared speaker control
Feedback Welcome!
Please drop a comment or send a PM if you use this bot! Contributions and improvements are much appreciated!
KnownBugs
* Validate add / unique track doesnยดt work. I.e - You can add same track 10 times in a row.
* Vote does not move track in queue.
ToDo
- Simple "view" window of what is happening in the channel. I.e. - Put on big-screen of what is happening in #music
- Backend DB
- Now playing. Announce when starting a new song.
- When asking for "Stat" show most played songs and most active users.
- When local playlist is empty -> fallback and start playing "$playlist", i.e. Spotify topp 100.
- Limit consecutive song additions by non-admin
- Delete range of songs from queue
DONE
- Code cleaning and refactoring (templates, migration logic, legacy file cleanup)
- Comprehensive integration test suite (21 tests)
- Unit tests for voting, parsing, and utilities
- Text-to-speech (TTS) feature
- Soundcraft mixer integration with volume control
- AI-powered music suggestions (OpenAI)
- Discord support
- Telemetry with PostHog (opt-out available)
- Vote to flush entire queue
- New vote system including votecheck
- Restrict songs already in the queue
- Now works with latest async version of node-sonos.
- Add spotify playlist
- Added "bestof" - Add the topp 10 tracks by selected artist.
- Added gongcheck - Thanks to "Warren Harding"
- Added blacklist function. Enter usernames in "blacklist.txt".
- Updated 'node-sonos' with getQueue and addSpotify. See: https://github.com/bencevans/node-sonos/commit/bfb995610c8aa20bda09e370b0f5d31ba0caa6a0
- Added new function, search.
- Added new function, Append. Reuse the old queue and add new track to the end of it.
- Admin: Delete entire queue.
- Regularly delete the entries from the queue when the song has been played.
- When adding a new track, do the following logic:
- Check "status". (fixed.. sort of..)
- If "playing", do a "list". Delete all songs in the queue with lower number than the current track. Then add song to queue.
- If "sleep" clear queue, add song to queue and do "play".
- When adding a new track, do the following logic:
- Add clear-queue functionality.
- Fix queue function.
- Fix GONG function. If X Gongs within X sec then next.
- Admin commands from i.e."swe-music-admin".
- Vote - If +1 in slack then move in queue. (sort of)
- Ask "what is playing".
