Skip to content

Commit 0f8ee48

Browse files
committed
Merge beta into Arabic localization PR
2 parents bac6554 + ca76c8a commit 0f8ee48

297 files changed

Lines changed: 18872 additions & 4579 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ settings.json
1010
*.backup
1111
AGENTS.md
1212
CLAUDE.md
13-
node_modules/
14-
package.lock
15-
electron_app_reference/
13+
node_modules/
14+
ssn-streamdeck/
15+
package.lock
16+
electron_app_reference/
1617
.npm-cache/
1718

1819
# Local browser model blobs (download at install/runtime, not in git)

AGENTS.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,11 @@ If you need more context on how Electron wiring differs from the extension boots
3636
## Message Contracts
3737

3838
- Every outbound event follows the canonical structure referenced in `docs/event-reference.html`. Required fields (`platform`, `type`, `chatname`, `chatmessage`, etc.) must stay intact.
39-
- Additional, non-standard details belong inside the top-level `meta` object. Populate `meta` with plain JSON values (no functions/classes) so downstream consumers can safely parse them.
39+
- `textonly` applies only to `chatmessage`: `true` means render `chatmessage` as plain text, while `false` means `chatmessage` may contain sanitized/renderable HTML. Other normal fields are expected to be plain text; media fields such as `chatimg` and `contentimg` carry URLs/data.
40+
- Donation-style chat rows should use `hasDonation` and optional `donoValue`. Do not set `event: "donation"` just because a normal chat/tip row has a donation value; `event` changes routing/filter behavior and should only be used for true normalized platform actions or paid item types.
41+
- Prefer specific event names over generic donation names when a platform exposes distinct paid support types. For example, YouTube Super Chat uses `event: "superchat"`, Super Sticker uses `event: "supersticker"`, and Jewels/Gifts use `event: "jeweldonation"`.
42+
- Use existing payload fields first. Only populate `meta` when there is additional structured data that downstream consumers actually need and no existing field handles it well.
43+
- Additional, non-standard details that truly need to be transmitted belong inside the top-level `meta` object. Populate `meta` with plain JSON values (no functions/classes) so downstream consumers can safely parse them.
4044
- Avoid emitting ad-hoc top-level keys—coordinate changes through the event reference doc before shipping.
4145

4246
## Custom Overlay Notes

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ Much more than just an overlay - Social Stream Ninja is a complete chat ecosyste
203203
- bigo.tv (no pop out)
204204
- circle.so (and community domains like community.talkinghealthtech.com or members.firstinfam.com)
205205
- sooplive.com (pop out the chat to use; supports https://play.sooplive.com/*?vtype=chat)
206+
- flextv.co.kr (open the live channel page with chat visible)
206207
- on24.com ( Q&A - questions supported)
207208
- meetme
208209
- moonbeam.stream (no pop out)
@@ -879,7 +880,7 @@ The `voice` parameter works with partial matching, so you can use terms like "si
879880

880881
#### Premium TTS Options
881882

882-
Unlike the system TTS (free), all premium TTS options are fully supported by both the Social Stream Ninja app and OBS browser sources with direct audio capture capabilities. These options provide superior language support and much easier integration.
883+
Unlike the system TTS (free), browser/provider TTS options are designed to play through the page, which makes OBS capture much easier when "Control audio via OBS" is enabled. Self-hosted local endpoints also work, but the endpoint still needs to be reachable from the page that is playing TTS; see the Local AI TTS Guide for localhost, CORS, and OBS browser-source setup notes.
883884

884885
##### Kokoro Premium FREE TTS
885886
Social Stream Ninja now includes Kokoro TTS, a high-quality browser-based text-to-speech solution that runs directly in the browser. Benefits include:

actions.html

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,44 @@ <h2>Session ID Required</h2>
321321
})(window);
322322

323323
var urlParams = new URLSearchParams(window.location.search);
324+
var SERVER_EXCLUSIVE_TRANSPORT_VERSION = "3.52.0";
325+
// Transport migration guard: only pages with full server parity may skip the legacy bridge.
326+
var TRANSPORT_CAPABILITIES = {
327+
serverFeed: false,
328+
serverTargeted: false,
329+
upstreamCommands: false,
330+
customChannel: true,
331+
legacyBridgeRequired: true,
332+
legacyBridgeReason: "Flow Actions uses channel 6 and sendTargetP2P('actions') is still bridge-only."
333+
};
334+
function versionAtLeast(value, minimum) {
335+
var a = String(value || "").split(".");
336+
var b = String(minimum || "").split(".");
337+
var len = Math.max(a.length, b.length);
338+
for (var i = 0; i < len; i++) {
339+
var av = parseInt(a[i], 10) || 0;
340+
var bv = parseInt(b[i], 10) || 0;
341+
if (av > bv) return true;
342+
if (av < bv) return false;
343+
}
344+
return true;
345+
}
346+
// Only feed-carrying server params listed by this page may disable the bridge; server3 alone is command-only.
347+
function hasExclusiveServerTransport(caps) {
348+
var params = caps && typeof caps.exclusiveServerParams === "object" ? caps.exclusiveServerParams : { server2: true };
349+
return (params.server === true && urlParams.has("server")) ||
350+
(params.server2 !== false && urlParams.has("server2")) ||
351+
(params.server3 === true && urlParams.has("server2") && urlParams.has("server3"));
352+
}
353+
function useServerOnlyTransport() {
354+
var caps = (typeof TRANSPORT_CAPABILITIES === "object" && TRANSPORT_CAPABILITIES) ? TRANSPORT_CAPABILITIES : {};
355+
return hasExclusiveServerTransport(caps) &&
356+
versionAtLeast(urlParams.get("v"), SERVER_EXCLUSIVE_TRANSPORT_VERSION) &&
357+
caps.serverFeed === true &&
358+
caps.legacyBridgeRequired !== true &&
359+
caps.upstreamCommands !== true &&
360+
caps.customChannel !== true;
361+
}
324362
var iframe = null;
325363
var connectedPeers = {};
326364
var roomID = "test";
@@ -1242,18 +1280,19 @@ <h2>Session ID Required</h2>
12421280
setupSocket();
12431281
}
12441282

1245-
// Create iframe for receiving WebRTC data channel messages
1246-
iframe = document.createElement("iframe");
1247-
iframe.connectedPeers = connectedPeers;
1248-
iframe.src = "https://vdo.socialstream.ninja/?ln&salt=vdo.ninja&password=" + password +
1249-
"&solo&view=" + roomID + "&novideo&noaudio&label=actions&cleanoutput&room=" + roomID;
1250-
iframe.style.width = "0px";
1251-
iframe.style.height = "0px";
1252-
iframe.style.position = "fixed";
1253-
iframe.style.left = "-100px";
1254-
iframe.style.top = "-100px";
1255-
iframe.id = "frame1";
1256-
document.body.appendChild(iframe);
1283+
if (!useServerOnlyTransport()) {
1284+
iframe = document.createElement("iframe");
1285+
iframe.connectedPeers = connectedPeers;
1286+
iframe.src = "https://vdo.socialstream.ninja/?ln&salt=vdo.ninja&password=" + encodeURIComponent(password) +
1287+
"&solo&view=" + roomID + "&novideo&noaudio&label=actions&cleanoutput&room=" + roomID;
1288+
iframe.style.width = "0px";
1289+
iframe.style.height = "0px";
1290+
iframe.style.position = "fixed";
1291+
iframe.style.left = "-100px";
1292+
iframe.style.top = "-100px";
1293+
iframe.id = "frame1";
1294+
document.body.appendChild(iframe);
1295+
}
12571296

12581297
console.log("Actions page initialized with session ID:", roomID);
12591298

0 commit comments

Comments
 (0)