Skip to content

Commit 0833551

Browse files
authored
Merge pull request #682 from steveseguin/beta
Beta
2 parents 7f064b0 + 8b7b208 commit 0833551

15 files changed

Lines changed: 1201 additions & 538 deletions

actions/EventFlowEditor.js

Lines changed: 71 additions & 63 deletions
Large diffs are not rendered by default.

api.md

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ There is an easy to use sandbox to play with some of the common API commands and
99
**Table of Contents**
1010

1111
- [WebSocket API](#websocket-api)
12+
- [Choose Your Use Case](#choose-your-use-case)
13+
- [Quick Start: Remote Control (StreamDeck / Bitfocus Companion)](#quick-start-remote-control-streamdeck--bitfocus-companion)
14+
- [Quick Start: Receiving Chat Messages (Python / Node.js)](#quick-start-receiving-chat-messages-python--nodejs)
1215
- [Connecting to the API Server](#connecting-to-the-api-server)
1316
- [Channel System Explained](#channel-system-explained)
1417
- [Available Commands](#available-commands)
@@ -88,6 +91,126 @@ The WebSocket API allows real-time, bidirectional communication between your app
8891

8992
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).
9093

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

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

background.html

Lines changed: 94 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -359,14 +359,14 @@
359359
box-shadow: 0 0 8px var(--success-color);
360360
}
361361

362-
.status-inactive {
363-
background-color: var(--alert-color);
364-
}
365-
366-
.status-warning {
367-
background-color: #FFCC00;
368-
box-shadow: 0 0 8px #FFCC00;
369-
}
362+
.status-inactive {
363+
background-color: var(--alert-color);
364+
}
365+
366+
.status-warning {
367+
background-color: #FFCC00;
368+
box-shadow: 0 0 8px #FFCC00;
369+
}
370370

371371
.stat-value {
372372
font-size: 24px;
@@ -619,31 +619,35 @@ <h3>
619619
</svg>
620620
Connection Status
621621
</h3>
622-
<div class="status-item">
623-
<span class="status-indicator" id="websocket-status"></span>
624-
API WebSocket (Optional): <span id="websocket-status-text">Checking...</span>
625-
</div>
626-
<div class="status-item">
627-
<span class="status-indicator" id="signaling-status"></span>
628-
Signaling (VDO.Ninja): <span id="signaling-status-text">Checking...</span>
629-
</div>
630-
<div class="status-item">
631-
<span class="status-indicator" id="webrtc-status"></span>
632-
WebRTC (P2P): <span id="webrtc-status-text">Checking...</span>
633-
</div>
622+
<div class="status-item">
623+
<span class="status-indicator" id="websocket-status"></span>
624+
🎮 Remote Control API (ch 1/2): <span id="websocket-status-text">Checking...</span>
625+
</div>
626+
<div class="status-item">
627+
<span class="status-indicator" id="websocket-dock-status"></span>
628+
📡 Chat to External Apps (ch 3/4): <span id="websocket-dock-status-text">Checking...</span>
629+
</div>
630+
<div class="status-item">
631+
<span class="status-indicator" id="signaling-status"></span>
632+
📶 Signaling (VDO.Ninja): <span id="signaling-status-text">Checking...</span>
633+
</div>
634+
<div class="status-item">
635+
<span class="status-indicator" id="webrtc-status"></span>
636+
🔗 WebRTC (P2P): <span id="webrtc-status-text">Checking...</span>
637+
</div>
634638
<div class="status-item">
635639
<span class="status-indicator" id="extension-status"></span>
636-
Extension: <span id="extension-status-text">Checking...</span>
640+
Extension: <span id="extension-status-text">Checking...</span>
637641
</div>
638642
<div class="status-item" id="session-info">
639643
Session ID: <span id="session-id">Loading...</span>
640644
</div>
641-
<div class="status-item" id="peer-list" style="margin-top: 10px; font-size: 12px; color: #777;">
642-
<div id="peer-list-content"></div>
643-
</div>
644-
<div class="status-item" style="margin-top: 6px; font-size: 12px; color: #555;">
645-
Note: You only need either WebRTC (P2P) <em>or</em> the API WebSocket; both are not required. WebRTC uses the VDO.Ninja signaling server for peer discovery; the API WebSocket is for optional server-based control/relay.
646-
</div>
645+
<div class="status-item" id="peer-list" style="margin-top: 10px; font-size: 12px; color: #777;">
646+
<div id="peer-list-content"></div>
647+
</div>
648+
<div class="status-item" style="margin-top: 6px; font-size: 12px; color: #555;">
649+
Note: WebRTC (P2P) is the default transport. The API WebSockets are optional: 🎮 Remote Control for StreamDeck/Bitfocus commands, 📡 Chat Relay to receive chat in external apps (Python/Node).
650+
</div>
647651
</div>
648652

649653
<div class="card" id="message-stats">
@@ -673,19 +677,31 @@ <h3>
673677
<div id="features-list">
674678
<div class="feature-item">
675679
<span class="status-indicator" id="midi-status"></span>
676-
MIDI Support
680+
🎹 MIDI Support
677681
</div>
678682
<div class="feature-item">
679683
<span class="status-indicator" id="sentiment-status"></span>
680-
Sentiment Analysis
684+
🧠 Sentiment Analysis
681685
</div>
682686
<div class="feature-item">
683687
<span class="status-indicator" id="waitlist-status"></span>
684-
Waitlist Mode
688+
📋 Waitlist Mode
685689
</div>
686690
<div class="feature-item">
687691
<span class="status-indicator" id="hype-status"></span>
688-
Hype Mode
692+
🔥 Hype Mode
693+
</div>
694+
<div class="feature-item">
695+
<span class="status-indicator" id="spotify-status"></span>
696+
🎵 Spotify
697+
</div>
698+
<div class="feature-item">
699+
<span class="status-indicator" id="streamerbot-status"></span>
700+
🤖 Streamer.bot
701+
</div>
702+
<div class="feature-item">
703+
<span class="status-indicator" id="customjs-status"></span>
704+
🔧 Custom JS
689705
</div>
690706
</div>
691707
</div>
@@ -775,11 +791,11 @@ <h3>Test Flow</h3>
775791
<textarea id="test-message" rows="3">Hello, world!</textarea>
776792
</div>
777793

778-
<div class="test-options">
779-
<label class="test-checkbox">
780-
<input type="checkbox" id="test-mod">
781-
Moderator
782-
</label>
794+
<div class="test-options">
795+
<label class="test-checkbox">
796+
<input type="checkbox" id="test-mod">
797+
Moderator
798+
</label>
783799

784800
<label class="test-checkbox">
785801
<input type="checkbox" id="test-vip">
@@ -791,47 +807,47 @@ <h3>Test Flow</h3>
791807
Admin
792808
</label>
793809

794-
<label class="test-checkbox">
795-
<input type="checkbox" id="test-donation">
796-
Has Donation
797-
</label>
798-
</div>
799-
800-
<div id="donation-amount" class="test-group" style="display: none;">
801-
<label for="test-donation-amount">Donation Amount:</label>
802-
<input type="text" id="test-donation-amount" value="$5.00">
803-
</div>
804-
805-
<div class="test-options">
806-
<label class="test-checkbox">
807-
<input type="checkbox" id="test-firsttime">
808-
First-time chatter
809-
</label>
810-
811-
<label class="test-checkbox">
812-
<input type="checkbox" id="test-lastactivity">
813-
Set last activity
814-
</label>
815-
</div>
816-
817-
<div id="lastactivity-controls" class="test-group" style="display: none;">
818-
<label for="test-lastactivity-value">Last activity</label>
819-
<div style="display: flex; gap: 8px; align-items: center;">
820-
<input type="number" id="test-lastactivity-value" value="60" min="0" style="width: 110px;">
821-
<select id="test-lastactivity-unit">
822-
<option value="minutes" selected>Minutes ago</option>
823-
<option value="hours">Hours ago</option>
824-
<option value="days">Days ago</option>
825-
</select>
826-
</div>
827-
<p class="test-help" style="color: #a0a0a0; font-size: 13px; margin: 6px 0 0 0;">Applies to message-properties “last activity” filters using the current time as reference.</p>
828-
</div>
829-
830-
<div class="test-options">
831-
<label class="test-checkbox">
832-
<input type="checkbox" id="test-all-active-flows">
833-
Test against all active flows (not just current flow)
834-
</label>
810+
<label class="test-checkbox">
811+
<input type="checkbox" id="test-donation">
812+
Has Donation
813+
</label>
814+
</div>
815+
816+
<div id="donation-amount" class="test-group" style="display: none;">
817+
<label for="test-donation-amount">Donation Amount:</label>
818+
<input type="text" id="test-donation-amount" value="$5.00">
819+
</div>
820+
821+
<div class="test-options">
822+
<label class="test-checkbox">
823+
<input type="checkbox" id="test-firsttime">
824+
First-time chatter
825+
</label>
826+
827+
<label class="test-checkbox">
828+
<input type="checkbox" id="test-lastactivity">
829+
Set last activity
830+
</label>
831+
</div>
832+
833+
<div id="lastactivity-controls" class="test-group" style="display: none;">
834+
<label for="test-lastactivity-value">Last activity</label>
835+
<div style="display: flex; gap: 8px; align-items: center;">
836+
<input type="number" id="test-lastactivity-value" value="60" min="0" style="width: 110px;">
837+
<select id="test-lastactivity-unit">
838+
<option value="minutes" selected>Minutes ago</option>
839+
<option value="hours">Hours ago</option>
840+
<option value="days">Days ago</option>
841+
</select>
842+
</div>
843+
<p class="test-help" style="color: #a0a0a0; font-size: 13px; margin: 6px 0 0 0;">Applies to message-properties “last activity” filters using the current time as reference.</p>
844+
</div>
845+
846+
<div class="test-options">
847+
<label class="test-checkbox">
848+
<input type="checkbox" id="test-all-active-flows">
849+
Test against all active flows (not just current flow)
850+
</label>
835851
</div>
836852

837853
<div class="test-warning" id="unsaved-flow-warning" style="display: none; color: #e76f51; margin: 10px 0;">
@@ -852,4 +868,4 @@ <h3>Test Flow</h3>
852868

853869
<script type="text/javascript" src="./loader.js"></script>
854870
</body>
855-
</html>
871+
</html>

0 commit comments

Comments
 (0)