Skip to content

Commit deafae8

Browse files
authored
Merge pull request #784 from steveseguin/beta
Beta
2 parents 493ba47 + 0eafb7a commit deafae8

11 files changed

Lines changed: 1833 additions & 124 deletions

File tree

background.js

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7061,11 +7061,14 @@ function sendToStreamerBot(data, fakechat = false, relayed = false) {
70617061
const payloadData = {
70627062
...data, // Copy original data
70637063
chatname: username || data.chatname || data.userid || "Host⚡",
7064-
isBot: isBot,
7064+
bot: isBot || !!data.bot, // local isBot = Ollama prefix detection; data.bot = platform/list bot flag
7065+
mod: !!data.mod,
7066+
host: !!data.host,
7067+
admin: !!data.admin,
7068+
vip: !!data.vip,
70657069
chatmessage: cleaned,
7066-
// Add any other relevant info Streamer.bot action might need
7067-
source: "SocialStream.Ninja", // Explicitly add source
7068-
originalPlatform: data.type || "unknown" // Preserve original platform info
7070+
source: "SocialStream.Ninja",
7071+
originalPlatform: data.type || "unknown"
70697072
};
70707073

70717074
if (videoId) {
@@ -7080,9 +7083,30 @@ function sendToStreamerBot(data, fakechat = false, relayed = false) {
70807083
const actionId = settings.streamerbotactionid.textsetting;
70817084
console.log(`Triggering Streamer.bot Action ID: ${actionId}`);
70827085

7083-
// Pass the prepared chat data as an argument named 'chatData' to the action
7086+
// Pass chat data fields as flat args so CPH.TryGetArg<T>() works directly in C#
7087+
// e.g. CPH.TryGetArg<string>("chatmessage", out string msg) — do NOT wrap in a nested object
70847088
const args = {
7085-
chatData: payloadData
7089+
chatmessage: payloadData.chatmessage || '',
7090+
chatname: payloadData.chatname || '',
7091+
userid: String(payloadData.userid || ''),
7092+
chatimg: payloadData.chatimg || '',
7093+
bot: payloadData.bot,
7094+
mod: payloadData.mod,
7095+
host: payloadData.host,
7096+
admin: payloadData.admin,
7097+
vip: payloadData.vip,
7098+
originalPlatform: payloadData.originalPlatform || 'unknown',
7099+
source: payloadData.source || 'SocialStream.Ninja',
7100+
type: payloadData.type || '',
7101+
nameColor: payloadData.nameColor || '#FFFFFF',
7102+
chatbadges: String(payloadData.chatbadges || ''),
7103+
membership: String(payloadData.membership || ''),
7104+
hasDonation: String(payloadData.hasDonation || ''),
7105+
contentimg: payloadData.contentimg || '',
7106+
subtitle: payloadData.subtitle || '',
7107+
textonly: !!payloadData.textonly,
7108+
tid: payloadData.tid || '',
7109+
id: payloadData.id || ''
70867110
};
70877111

70887112
if (payloadData.videoId) {

img/sb_actions.png

54 KB
Loading

img/sb_history.png

105 KB
Loading

manifest.json

Lines changed: 16 additions & 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.47.3",
5+
"version": "3.47.4",
66
"homepage_url": "http://socialstream.ninja/",
77
"browser_specific_settings": {
88
"gecko": {
@@ -74,6 +74,7 @@
7474
"https://patreon.com/*",
7575
"https://simps.com/app/*",
7676
"https://velora.tv/*",
77+
"https://api.velora.tv/*",
7778
"https://studio.kwai.com/*",
7879
"https://studio.favorited.com/popout/chat",
7980
"https://*/*autoreloadwithsocialstream",
@@ -1191,6 +1192,20 @@
11911192
"http://localhost:8181/*/kick.html*"
11921193
]
11931194
},
1195+
{
1196+
"js": [
1197+
"./lite/vendor/socket.io.min.js",
1198+
"./sources/websocket/velora.js"
1199+
],
1200+
"matches": [
1201+
"https://socialstream.ninja/sources/websocket/velora*",
1202+
"https://beta.socialstream.ninja/sources/websocket/velora*",
1203+
"https://socialstream.ninja/beta/sources/websocket/velora*",
1204+
"file:///C:/Users/steve/Code/social_stream/sources/websocket/velora.html*",
1205+
"http://localhost:8080/*/velora.html*",
1206+
"http://localhost:8181/*/velora.html*"
1207+
]
1208+
},
11941209
{
11951210
"js": [
11961211
"./sources/websocket/rumble.js"

popup.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6269,13 +6269,13 @@ <h3>Printer Control</h3>
62696269
</div>
62706270
<div>
62716271
<div class="textInputContainer" style="display: inline-block; width: 250px;">
6272-
<input type="text" id="streamerbotactionid" class="textInput" autocomplete="off" placeholder="Enter Streamer.bot Action GUID" data-textsetting="streamerbotactionid" />
6272+
<input type="text" id="streamerbotactionid" class="textInput" autocomplete="off" placeholder="Enter Streamer.bot Action ID" data-textsetting="streamerbotactionid" />
62736273
<label for="streamerbotactionid"><span data-translate="streamerbot-action-id">&gt; Streamer.bot Action ID</span></label>
62746274
</div>
62756275
</div>
62766276
<p>
62776277
<span>
6278-
The Streamer.bot support is experimental and challenging to setup. I have a <a href="https://socialstream.ninja/streamerbot.html" class="lightblue" target="_blank">GUIDE HERE</a>, but I'd welcome support from Streamer.bot devs to improve it all further.
6278+
See the <a href="https://socialstream.ninja/streamerbot.html" class="lightblue" target="_blank">setup guide</a> for step-by-step instructions on creating the required Action in Streamer.bot and finding its Action ID. Leave the password blank if you have not set one in Streamer.bot's WebSocket Server settings.
62796279
<br />
62806280
</span>
62816281
</p>

sources/velora.js

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@
7575

7676
var channelName = "";
7777

78+
var processedMessages = new Set();
79+
7880
function processMessage(ele){
7981
console.log(ele);
8082
if (!ele || !ele.isConnected){
@@ -98,7 +100,8 @@
98100

99101
var name="";
100102
try {
101-
name = escapeHtml(ele.querySelector("[title^='View profile for'], [class*='border-amber'] .text-sm.font-semibold.leading-tight.text-white").textContent);
103+
var nameEl = ele.querySelector("[title^='View profile for']");
104+
if (nameEl) { name = escapeHtml(nameEl.textContent.trim()); }
102105
} catch(e){
103106
}
104107

@@ -117,7 +120,8 @@
117120

118121
var msg="";
119122
try {
120-
msg = getAllContentNodes(ele.querySelector("div > div > div.text-sm.break-words.text-white, [class*='border-amber'] > div > div > p")).trim();
123+
var msgEl = ele.querySelector(".chat-message-content > div:last-child");
124+
if (msgEl) { msg = getAllContentNodes(msgEl).trim(); }
121125
} catch(e){
122126
}
123127

@@ -136,6 +140,15 @@
136140
return;
137141
}
138142

143+
var msgKey = name + "|\u00b6|" + msg;
144+
if (processedMessages.has(msgKey)){
145+
ele.skip = true;
146+
return;
147+
}
148+
processedMessages.add(msgKey);
149+
if (processedMessages.size > 200){
150+
processedMessages.delete(processedMessages.values().next().value);
151+
}
139152

140153
ele.skip = true;
141154

@@ -165,20 +178,27 @@
165178
}
166179
}
167180
var isExtensionOn = true;
181+
var cachedViewerEl = null;
168182

169183
function checkViewers(){
170184
if (isExtensionOn && (settings.showviewercount || settings.hypemode)){
171185
try {
172186

173187

174-
if (window.location.href === "https://velora.tv/dashboard/stream/popout?panels=chat"){
175-
var viewerSpan = document.querySelector(".min-w-0 > .mt-1").childNodes[0];
176-
} else {
177-
var viewerSpan = document.querySelector(".inline-flex.items-center.gap-2.rounded-full > .tracking-normal.text-white.font-semibold").parentNode.nextElementSibling.childNodes[1];
188+
if (!cachedViewerEl || !cachedViewerEl.isConnected){
189+
cachedViewerEl = null;
190+
var els = document.querySelectorAll("div, span");
191+
for (var i = 0; i < els.length; i++){
192+
var el = els[i];
193+
if (!el.childElementCount && /^[\d,.]+[km]?\s+viewers?$/i.test(el.textContent.trim())){
194+
cachedViewerEl = el;
195+
break;
196+
}
197+
}
178198
}
179199

180-
if (viewerSpan && viewerSpan.textContent){
181-
let views = viewerSpan.textContent.toUpperCase();
200+
if (cachedViewerEl && cachedViewerEl.textContent){
201+
let views = cachedViewerEl.textContent.toUpperCase();
182202
let multiplier = 1;
183203
if (views.includes("K")){
184204
multiplier = 1000;
@@ -312,10 +332,9 @@
312332
}
313333
checking = setInterval(function(){
314334
try {
315-
var container = document.querySelector(".duration-300.rounded-none > .flex-1.overflow-y-auto.p-4.space-y-3.min-h-0");
316-
if (!container && window.location.href.startsWith("https://velora.tv/dashboard/stream/popout?")){
317-
container = document.querySelector("body");
318-
}
335+
var container = document.querySelector(".chat-scroll-hidden");
336+
337+
if (!container){ return; }
319338

320339
if (!container.marked){
321340
container.marked=true;
@@ -324,11 +343,7 @@
324343

325344
setTimeout(function(){
326345
dataIndex = 0;
327-
if (window.location.href.startsWith("https://velora.tv/dashboard/stream/popout?")){
328-
onElementInserted(container, true);
329-
} else {
330-
onElementInserted(container);
331-
}
346+
onElementInserted(container);
332347
},2000);
333348
}
334349
checkViewers();

sources/websocket/kick.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3845,18 +3845,18 @@ function updateKickStreamEditorFields(channel) {
38453845
}
38463846

38473847
async function fetchCurrentKickChannelInfo() {
3848-
let path = '/public/v1/channels';
38493848
if (state.channelId != null) {
3850-
path += `?broadcaster_user_id=${encodeURIComponent(String(state.channelId))}`;
3851-
} else if (state.channelSlug) {
3852-
path += `?slug=${encodeURIComponent(normalizeChannel(state.channelSlug))}`;
3853-
}
3854-
const data = await apiFetch(path);
3855-
return pickKickChannelBySlug(
3856-
unwrapKickChannelPayload(data),
3857-
normalizeChannel(state.channelSlug),
3858-
{ allowSingletonWithoutSlug: true }
3859-
);
3849+
const path = `/public/v1/channels?broadcaster_user_id=${encodeURIComponent(String(state.channelId))}`;
3850+
const data = await apiFetch(path);
3851+
const channels = unwrapKickChannelPayload(data);
3852+
return channels[0] || null;
3853+
}
3854+
if (state.channelSlug) {
3855+
return fetchKickChannelBySlug(normalizeChannel(state.channelSlug));
3856+
}
3857+
const data = await apiFetch('/public/v1/channels');
3858+
const channels = unwrapKickChannelPayload(data);
3859+
return channels[0] || null;
38603860
}
38613861

38623862
async function refreshKickStreamInfo() {

0 commit comments

Comments
 (0)