Skip to content

Commit a30a46c

Browse files
steveseguinclaude
andcommitted
docs: Clarify API toggles and channels for remote control vs chat listener use cases
- Updated popup.html toggle descriptions with clearer tooltips explaining each toggle's purpose - Added emoji indicator (📡) to "Send chat messages to API server" toggle to highlight its importance - Added "Quick Start" section to api.md with two clear use cases: - Remote Control (StreamDeck/Bitfocus): Toggle 1, Channel 1 - Chat Listener (Python/Node): Toggle 1+3, Channel 4 - Added Python and Node.js sample code for receiving chat messages - Updated sampleapi.html with clear use case guidance - Updated docs/commands.html with toggle requirements and improved channel descriptions - Updated docs/customoverlays.md WebSocket section with toggle reference table Fixes confusion where users enable API control but don't receive chat messages because they missed enabling the 3rd toggle for chat relay to channel 4. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent c36f517 commit a30a46c

6 files changed

Lines changed: 187 additions & 47 deletions

File tree

api.md

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,126 @@ The WebSocket API allows real-time, bidirectional communication between your app
8888

8989
If you prefer to keep traffic peer-to-peer without enabling the WebSocket relay, you can instead integrate the Social Stream Ninja WebRTC SDK. It offers a Node- and browser-friendly interface that plugs into the same transport layer used by the extension. A Social Stream Ninja listener example is available at [ninjasdk/demos/socialstreamninja-listener.js](https://github.com/steveseguin/ninjasdk/blob/main/demos/socialstreamninja-listener.js).
9090

91+
### Choose Your Use Case
92+
93+
There are two main reasons to use the WebSocket API:
94+
95+
| Use Case | What You Want | Required Toggle(s) | Channel |
96+
|----------|---------------|-------------------|---------|
97+
| **Remote Control** | Send commands to SSN (clear, feature, next in queue, send chat) from StreamDeck, Bitfocus Companion, or custom apps | ✅ Enable remote API control | Channel 1 (default) |
98+
| **Chat Listener** | Receive chat messages from Twitch/YouTube/etc. in your Python/Node app | ✅ Enable remote API control + ✅ Send chat messages to API server (3rd toggle) | Channel 4 |
99+
100+
**Toggle Reference (Global settings > Mechanics):**
101+
102+
| Toggle | Purpose |
103+
|--------|---------|
104+
| 1. Enable remote API control of extension | Required for ALL API usage. Allows sending commands to the extension. |
105+
| 2. Enable Dock to use and publish via API server | Needed to send commands directly to the Dock page (clear, nextInQueue, etc.) |
106+
| 3. **Send chat messages to API server** | **Required to RECEIVE chat messages!** Routes Twitch/YouTube/etc. chat through the server on channel 4. |
107+
| 4. Dock sends its commands to Extension via server | Optional. Allows Dock to send commands back to extension via server instead of P2P. |
108+
109+
---
110+
111+
### Quick Start: Remote Control (StreamDeck / Bitfocus Companion)
112+
113+
For controlling SSN from StreamDeck, Bitfocus Companion, or similar tools, you only need the **first toggle** enabled.
114+
115+
**Simple HTTP GET request:**
116+
```
117+
https://io.socialstream.ninja/SESSION_ID/nextInQueue
118+
https://io.socialstream.ninja/SESSION_ID/clearOverlay
119+
https://io.socialstream.ninja/SESSION_ID/sendEncodedChat/null/Hello%20World
120+
```
121+
122+
**WebSocket commands:**
123+
```javascript
124+
ws = new WebSocket("wss://io.socialstream.ninja/join/SESSION_ID");
125+
ws.onopen = () => {
126+
// Send a command
127+
ws.send(JSON.stringify({ action: "nextInQueue" }));
128+
ws.send(JSON.stringify({ action: "clearOverlay" }));
129+
ws.send(JSON.stringify({ action: "sendChat", value: "Hello from API!" }));
130+
};
131+
```
132+
133+
See the [StreamDeck Integration Guide](#streamdeck-integration-guide-for-social-stream-ninja) and [Bitfocus Companion](#using-bitfocus-companion-with-social-stream-ninja) sections below for detailed setup.
134+
135+
---
136+
137+
### Quick Start: Receiving Chat Messages (Python / Node.js)
138+
139+
To receive chat messages from Twitch, YouTube, and other platforms in your own application:
140+
141+
**Required toggles (Global settings > Mechanics):**
142+
1.**Enable remote API control of extension**
143+
2.**Send chat messages to API server** (the 3rd toggle) - This is the key one!
144+
145+
**Connect to Channel 4** - This is where chat messages are broadcast:
146+
147+
**Python Example:**
148+
149+
```python
150+
import asyncio
151+
import websockets
152+
import json
153+
154+
SESSION_ID = "YOUR_SESSION_ID_HERE" # From your dock.html URL
155+
156+
async def listen_to_chat():
157+
uri = f"wss://io.socialstream.ninja/join/{SESSION_ID}/4" # Channel 4 receives chat
158+
159+
async with websockets.connect(uri) as ws:
160+
print(f"Connected! Listening for chat messages...")
161+
162+
while True:
163+
message = await ws.recv()
164+
data = json.loads(message)
165+
166+
# Chat messages have 'chatname' and 'chatmessage' fields
167+
if "chatname" in data:
168+
print(f"[{data.get('type', 'unknown')}] {data['chatname']}: {data.get('chatmessage', '')}")
169+
170+
# Check for donations
171+
if data.get('hasDonation'):
172+
print(f" 💰 Donation: {data['hasDonation']}")
173+
174+
asyncio.run(listen_to_chat())
175+
```
176+
177+
**Node.js Example:**
178+
179+
```javascript
180+
const WebSocket = require('ws');
181+
182+
const SESSION_ID = 'YOUR_SESSION_ID_HERE'; // From your dock.html URL
183+
184+
const ws = new WebSocket(`wss://io.socialstream.ninja/join/${SESSION_ID}/4`);
185+
186+
ws.on('open', () => {
187+
console.log('Connected! Listening for chat messages...');
188+
});
189+
190+
ws.on('message', (message) => {
191+
const data = JSON.parse(message);
192+
193+
// Chat messages have 'chatname' and 'chatmessage' fields
194+
if (data.chatname) {
195+
console.log(`[${data.type || 'unknown'}] ${data.chatname}: ${data.chatmessage || ''}`);
196+
197+
// Check for donations
198+
if (data.hasDonation) {
199+
console.log(` 💰 Donation: ${data.hasDonation}`);
200+
}
201+
}
202+
});
203+
204+
ws.on('error', console.error);
205+
```
206+
207+
**Channel Reference for Listeners:**
208+
- Channel 4 (`/join/SESSION/4`) - Receives chat messages from the extension (when "Send chat messages to API server" is enabled)
209+
- Channel 2 (`/join/SESSION/2`) - Receives messages from the Dock (when "Enable Dock to use and publish via API server" is enabled)
210+
91211
### Connecting to the API Server
92212

93213
Connect to the WebSocket server at `wss://io.socialstream.ninja`.

docs/commands.html

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,12 @@ <h4>Message Export</h4>
206206
</div>
207207

208208
<div class="command-note">
209-
<p><strong>Important:</strong> You must enable the Server API toggle in the extension menu for API functionality to work.</p>
209+
<p><strong>Required Settings (Global settings → Mechanics):</strong></p>
210+
<ul style="text-align:left; margin: 10px 0;">
211+
<li><strong>🎮 Remote Control (StreamDeck/Bitfocus):</strong> Enable <em>"Enable remote API control of extension"</em> (Toggle 1) — Connect to <strong>channel 1</strong></li>
212+
<li><strong>📡 Chat Listener (Python/Node apps):</strong> Enable Toggle 1 + <em>"Send chat messages to API server"</em> (Toggle 3) — Connect to <strong>channel 4</strong></li>
213+
</ul>
214+
<p>See the <a href="../api.md">full API documentation</a> for detailed setup guides and code samples.</p>
210215
</div>
211216

212217
<div class="command-card">
@@ -241,19 +246,23 @@ <h4><i class="fas fa-broadcast-tower"></i> Server-Sent Events</h4>
241246

242247
<div class="channel-system">
243248
<h4>Channel System</h4>
244-
<p>The API uses a channel system for message routing control:</p>
249+
<p>The API uses a channel system for message routing:</p>
245250
<div class="code-block">
246251
<pre>
247-
- Channel 1: Main communication channel (default)
248-
- Channel 2: Typically used for dock.html communication
249-
- Channel 3: Often used for extension communication
250-
- Channel 4: Commonly used for featured.html communication
251-
- Channel 5: Used for waitlist.html communication
252+
- Channel 1: Remote control commands (default for StreamDeck/Bitfocus)
253+
- Channel 2: Dock page output
254+
- Channel 3: Extension receives commands from Dock
255+
- Channel 4: <strong>Chat messages from Extension</strong> (use this to receive Twitch/YouTube chat!)
256+
- Channel 5: Waitlist/giveaway communication
252257
- Channels 6-9: Reserved for future use</pre>
253258
</div>
254-
<p>You can specify input and output channels when connecting:</p>
259+
<p>Connect with your desired channel:</p>
255260
<div class="code-block">
256-
<pre>wss://io.socialstream.ninja/join/SESSION_ID/IN_CHANNEL/OUT_CHANNEL</pre>
261+
<pre>// To receive chat messages (listen on channel 4):
262+
wss://io.socialstream.ninja/join/SESSION_ID/4
263+
264+
// To send commands (channel 1 default):
265+
wss://io.socialstream.ninja/join/SESSION_ID</pre>
257266
</div>
258267
</div>
259268
</div>

docs/customoverlays.md

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,21 @@ See `dock.html`, `featured.html`, `events.html` etc. for more examples of iframe
9191

9292
For more direct control or server-side integrations, you can connect to the SSN WebSocket server (`wss://io.socialstream.ninja`). This bypasses the need for an iframe but requires handling the WebSocket connection and message parsing directly in your JavaScript.
9393

94+
**Required Settings (Global settings → Mechanics):**
95+
96+
| Use Case | Required Toggles | Channel |
97+
|----------|-----------------|---------|
98+
| **Remote Control** (send commands) | Toggle 1: "Enable remote API control of extension" | Channel 1 (default) |
99+
| **Chat Listener** (receive chat messages) | Toggle 1 + Toggle 3: "Send chat messages to API server" | Channel 4 |
100+
94101
**Connection:**
95102

96103
```javascript
97104
const urlParams = new URLSearchParams(window.location.search);
98105
const roomID = urlParams.get("session") || "test";
99-
// Choose appropriate IN_CHANNEL and OUT_CHANNEL based on your needs.
100-
// For a simple overlay listening to general messages, IN_CHANNEL 3 or 4 might be suitable.
101-
const inChannel = urlParams.get("in_channel") || "4"; // Channel to listen on
102-
const outChannel = urlParams.get("out_channel") || "3"; // Channel to send to (if needed)
106+
// Channel 4 receives chat messages when "Send chat messages to API server" toggle is enabled
107+
const inChannel = urlParams.get("in_channel") || "4"; // Channel 4 = chat messages from extension
108+
const outChannel = urlParams.get("out_channel") || "3"; // Channel to send commands (if needed)
103109

104110
const socketServerURL = urlParams.get("server") || "wss://io.socialstream.ninja";
105111
const socket = new WebSocket(socketServerURL);
@@ -181,13 +187,13 @@ A typical message object might look like this (fields vary based on source and e
181187
}
182188
```
183189

184-
Refer to `about.md` for more details on these fields.
185-
186-
> **Note:** Reserve the `event` field for true system notifications (follows, raids, /me actions, etc.). Regular chat messages should leave `event` unset/false so they are never mistaken for events.
187-
188-
### Client-Side Filtering and Logic
189-
190-
Your JavaScript code will be responsible for deciding what to do with each incoming message.
190+
Refer to `about.md` for more details on these fields.
191+
192+
> **Note:** Reserve the `event` field for true system notifications (follows, raids, /me actions, etc.). Regular chat messages should leave `event` unset/false so they are never mistaken for events.
193+
194+
### Client-Side Filtering and Logic
195+
196+
Your JavaScript code will be responsible for deciding what to do with each incoming message.
191197

192198
```javascript
193199
function processIncomingSSNMessage(data) {
@@ -591,4 +597,4 @@ This example shows an overlay that only displays new follower and subscriber eve
591597
- **No `background.js` Modification:** Design your custom page to work with the existing SSN message structure and API. Avoid solutions that would require changing the core extension code.
592598
- **Consult Examples:** The existing `dock.html`, `featured.html`, `events.html`, `hype.html`, `waitlist.html`, `confetti.html`, and `credits.html` files in the Social Stream Ninja project are excellent resources for seeing how these principles are applied.
593599

594-
By following this guide, you can create powerful and customized overlay experiences for Social Stream Ninja.
600+
By following this guide, you can create powerful and customized overlay experiences for Social Stream Ninja.

manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "Social Stream Ninja",
33
"description": "Powerful tooling to engage live chat on Youtube, Twitch, Zoom, and more.",
44
"manifest_version": 3,
5-
"version": "3.39.3",
5+
"version": "3.39.4",
66
"homepage_url": "http://socialstream.ninja/",
77
"browser_specific_settings": {
88
"gecko": {

popup.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5439,7 +5439,7 @@ <h3>Printer Control</h3>
54395439
</label>
54405440
<span data-translate="disable-host-chat">🚫🗨️ Disable the host chat and block functions </span>
54415441
</div>
5442-
<div title="See documentation on socialstream.ninja for details.">
5442+
<div title="Allows external apps (Python, Node, StreamDeck, etc.) to control SSN via HTTP/WebSocket API. Enable this to send commands like sendChat, blockUser, etc. to the extension.">
54435443
<label class="switch">
54445444
<input type="checkbox" data-setting="socketserver" />
54455445
<span class="slider round"></span>
@@ -5449,21 +5449,21 @@ <h3>Printer Control</h3>
54495449
<span data-translate="remote-httpwss-api-control-extension">remote API control of extension</span>
54505450
</a>
54515451
</div>
5452-
<div title="This is needed if HTTP/WSS commands are being sent to the dock for remote control, to bypass p2p if needed, and to publish featured messages via server instead of P2P">
5452+
<div title="Connects the Dock/Featured pages to the API server for remote control. Needed if you want to send commands (clear, feature, nextInQueue, etc.) directly to the Dock via HTTP/WebSocket.">
54535453
<label class="switch">
54545454
<input type="checkbox" id="server" data-both="server" />
54555455
<span class="slider round"></span>
54565456
</label>
54575457
<span data-translate="send-featured-chat-via-server-instead-of-p2p">Enable Dock to use and publish via API server</span>
54585458
</div>
5459-
<div title="Mainly useful if P2P not working. It can also be used to send messages to the Dock via the API using channel 3/4">
5459+
<div title="IMPORTANT: Enable this to receive chat messages via WebSocket API! Routes chat from Twitch/YouTube/etc. through the API server (channel 4) so external apps can listen. Required for Python/Node chat listeners.">
54605460
<label class="switch">
54615461
<input type="checkbox" id="server2" data-both="server2" />
54625462
<span class="slider round"></span>
54635463
</label>
5464-
<span data-translate="send-messages-to-dock-via-server-instead-of-p2p">Send messages to Dock from Extension via server</span>
5464+
<span data-translate="send-messages-to-dock-via-server-instead-of-p2p">📡 Send chat messages to API server (for external listeners)</span>
54655465
</div>
5466-
<div title="Mainly useful if P2P not working in cases where you want to send messages to a social end point via the Dock page.">
5466+
<div title="Allows the Dock page to send commands back to the extension via the API server instead of P2P. Useful if P2P connections are blocked or unreliable.">
54675467
<label class="switch" >
54685468
<input type="checkbox" id="server3" data-both="server3" />
54695469
<span class="slider round"></span>

sampleapi.html

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,12 @@ <h1 class="mb-4">Social Stream API Sandbox</h1>
197197
<p class="lead">
198198
This Social Stream API Sandbox is a comprehensive tool for developers to test and interact with the Social Stream Ninja API. It provides a user-friendly interface to experiment with various API features, including message generation, user management, and channel-specific communications. For full API documentation, please visit <a href="https://socialstream.ninja/api" target="_blank">socialstream.ninja/api</a>.
199199
<br/><br/>
200-
Please note that you may need to add <b><i>&server</i></b> to the dock.html or featured.html pages if you wish to send messages to them via the API. By default the extension, nor any dock/overlay page, will connect to the API server by default; they must be configured to work with the API server via menu toggle or URL parameter.
200+
<b>🎮 Remote Control (StreamDeck/Bitfocus):</b> Send commands like clear, nextInQueue, sendChat<br/>
201+
→ Enable: <b>Toggle 1</b> (Enable remote API control) — Connect to <b>channel 1</b> (default)<br/><br/>
202+
<b>📡 Chat Listener (Python/Node apps):</b> Receive chat messages from Twitch/YouTube/etc.<br/>
203+
→ Enable: <b>Toggle 1 + Toggle 3</b> (Send chat messages to API server) — Connect to <b>channel 4</b><br/><br/>
204+
<b>Settings Location:</b> Global settings &gt; Mechanics<br/>
205+
<small>Alternatively, add <b>&server</b> or <b>&server2</b> URL parameters to dock.html/featured.html pages.</small>
201206
</p>
202207
</div>
203208

@@ -379,24 +384,24 @@ <h2>Channel-Specific Messaging</h2>
379384
<option value="7">Channel 7</option>
380385
</select>
381386
</div>
382-
<button class="btn btn-primary" onclick="sendChannelMessage()">Send Channel Message</button>
383-
<p class="note">Send messages to specific channels of the API server for more granular control of API messaging.</p>
384-
</div>
385-
386-
<div class="section">
387-
<h2>Message Filters</h2>
388-
<div class="btn-group" role="group">
389-
<button class="btn btn-info" onclick="sendCommand('emoteonly', 'toggle')">Toggle Emote-only</button>
390-
<button class="btn btn-success" onclick="sendCommand('emoteonly', true)">Enable Emote-only</button>
391-
<button class="btn btn-danger" onclick="sendCommand('emoteonly', false)">Disable Emote-only</button>
392-
</div>
393-
<p class="note">Emote-only mode keeps only emotes/emoji from chat messages and drops messages that become empty after filtering.</p>
394-
</div>
395-
396-
<div class="section">
397-
<h2>Waitlist Commands</h2>
398-
<div class="btn-group" role="group">
399-
<button class="btn btn-warning" onclick="sendCommand('removefromwaitlist', 1)">Remove First from Waitlist</button>
387+
<button class="btn btn-primary" onclick="sendChannelMessage()">Send Channel Message</button>
388+
<p class="note">Send messages to specific channels of the API server for more granular control of API messaging.</p>
389+
</div>
390+
391+
<div class="section">
392+
<h2>Message Filters</h2>
393+
<div class="btn-group" role="group">
394+
<button class="btn btn-info" onclick="sendCommand('emoteonly', 'toggle')">Toggle Emote-only</button>
395+
<button class="btn btn-success" onclick="sendCommand('emoteonly', true)">Enable Emote-only</button>
396+
<button class="btn btn-danger" onclick="sendCommand('emoteonly', false)">Disable Emote-only</button>
397+
</div>
398+
<p class="note">Emote-only mode keeps only emotes/emoji from chat messages and drops messages that become empty after filtering.</p>
399+
</div>
400+
401+
<div class="section">
402+
<h2>Waitlist Commands</h2>
403+
<div class="btn-group" role="group">
404+
<button class="btn btn-warning" onclick="sendCommand('removefromwaitlist', 1)">Remove First from Waitlist</button>
400405
<button class="btn btn-warning" onclick="sendCommand('highlightwaitlist', 1)">Highlight First in Waitlist</button>
401406
<button class="btn btn-warning" onclick="sendCommand('resetwaitlist')">Reset Waitlist</button>
402407
<button class="btn btn-warning" onclick="sendCommand('downloadwaitlist')">Download Waitlist</button>
@@ -936,4 +941,4 @@ <h2>Incoming Messages</h2>
936941
});
937942
</script>
938943
</body>
939-
</html>
944+
</html>

0 commit comments

Comments
 (0)