Merge pull request #19 from nuttylmao/beta

Beta
This commit is contained in:
nuttylmao
2025-11-17 23:42:45 +11:00
committed by GitHub
7 changed files with 183 additions and 13 deletions
+31 -10
View File
@@ -222,21 +222,42 @@ function EscapeRegExp(string) {
} }
// Given a string, return a random hex code. The same input always results in the same output // Given a string, return a random hex code. The same input always results in the same output
function StringToHex(str) { function RandomHex(str) {
// Simple hash function to convert string to a number // Simple hash to convert string to a number
let hash = 0; let hash = 0;
for (let i = 0; i < str.length; i++) { for (let i = 0; i < str.length; i++) {
hash = str.charCodeAt(i) + ((hash << 5) - hash); hash = str.charCodeAt(i) + ((hash << 5) - hash);
hash |= 0; // Convert to 32bit integer hash |= 0;
} }
// Convert hash to a hex color // Use the hash to generate a hue (0360)
let color = '#'; const hue = Math.abs(hash) % 360;
for (let i = 0; i < 3; i++) {
// Extract each byte and convert to 2-digit hex // Force super saturation + readable brightness
const value = (hash >> (i * 8)) & 0xFF; const saturation = 100; // maximum saturation
color += value.toString(16).padStart(2, '0'); const lightness = 55; // tweak 5060 depending on your background
// Convert HSL → RGB → hex
function hslToHex(h, s, l) {
s /= 100;
l /= 100;
const k = n => (n + h / 30) % 12;
const a = s * Math.min(l, 1 - l);
const f = n =>
l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
const r = Math.round(255 * f(0));
const g = Math.round(255 * f(8));
const b = Math.round(255 * f(4));
return (
"#" +
r.toString(16).padStart(2, "0") +
g.toString(16).padStart(2, "0") +
b.toString(16).padStart(2, "0")
);
} }
return color; return hslToHex(hue, saturation, lightness);
} }
+19 -1
View File
@@ -46,6 +46,7 @@ const showTwitchFollows = GetBooleanParam("showTwitchFollows", false);
const showTwitchSubs = GetBooleanParam("showTwitchSubs", true); const showTwitchSubs = GetBooleanParam("showTwitchSubs", true);
const showTwitchChannelPointRedemptions = GetBooleanParam("showTwitchChannelPointRedemptions", true); const showTwitchChannelPointRedemptions = GetBooleanParam("showTwitchChannelPointRedemptions", true);
const showTwitchRaids = GetBooleanParam("showTwitchRaids", true); const showTwitchRaids = GetBooleanParam("showTwitchRaids", true);
const showTwitchWatchStreaks = GetBooleanParam("showTwitchWatchStreaks", true);
const showTwitchSharedChat = GetBooleanParam("showTwitchSharedChat", true); const showTwitchSharedChat = GetBooleanParam("showTwitchSharedChat", true);
const kickUsername = urlParams.get("kickUsername") || ""; const kickUsername = urlParams.get("kickUsername") || "";
@@ -181,6 +182,11 @@ client.on('Twitch.Raid', (response) => {
TwitchRaid(response.data); TwitchRaid(response.data);
}) })
client.on('Twitch.WatchStreak', (response) => {
console.debug(response.data);
TwitchWatchStreak(response.data);
})
client.on('Twitch.ChatMessageDeleted', (response) => { client.on('Twitch.ChatMessageDeleted', (response) => {
console.debug(response.data); console.debug(response.data);
TwitchChatMessageDeleted(response.data); TwitchChatMessageDeleted(response.data);
@@ -789,6 +795,18 @@ async function TwitchRaid(data) {
ShowAlert(message, 'twitch'); ShowAlert(message, 'twitch');
} }
async function TwitchWatchStreak(data) {
if (!showTwitchWatchStreaks)
return;
const displayName = data.displayName;
const watchStreak = data.watchStreak;
let message = `${displayName} is currently on a ${watchStreak} stream streak!`;
ShowAlert(message, 'twitch');
}
function TwitchChatMessageDeleted(data) { function TwitchChatMessageDeleted(data) {
const messageList = document.getElementById("messageList"); const messageList = document.getElementById("messageList");
@@ -878,7 +896,7 @@ function YouTubeMessage(data) {
if (showUsername) { if (showUsername) {
usernameDiv.innerText = data.user.name; usernameDiv.innerText = data.user.name;
if (randomYouTubeColors) if (randomYouTubeColors)
usernameDiv.style.color = StringToHex(data.user.name); usernameDiv.style.color = RandomHex(data.user.name);
else else
usernameDiv.style.color = youtubeColor; // YouTube users do not have colors, so just set it to red usernameDiv.style.color = youtubeColor; // YouTube users do not have colors, so just set it to red
} }
+8
View File
@@ -175,6 +175,14 @@
"defaultValue": true, "defaultValue": true,
"group": "Which Twitch messages do you want to see?" "group": "Which Twitch messages do you want to see?"
}, },
{
"id": "showTwitchWatchStreaks",
"label": "Watch Streaks",
"description": "",
"type": "checkbox",
"defaultValue": true,
"group": "Which Twitch messages do you want to see?"
},
{ {
"id": "showTwitchSharedChat", "id": "showTwitchSharedChat",
"label": "Shared Chat Messages", "label": "Shared Chat Messages",
+68 -1
View File
@@ -51,6 +51,7 @@ const showTwitchFollows = GetBooleanParam("showTwitchFollows", false);
const showTwitchSubs = GetBooleanParam("showTwitchSubs", true); const showTwitchSubs = GetBooleanParam("showTwitchSubs", true);
const showTwitchChannelPointRedemptions = GetBooleanParam("showTwitchChannelPointRedemptions", true); const showTwitchChannelPointRedemptions = GetBooleanParam("showTwitchChannelPointRedemptions", true);
const showTwitchRaids = GetBooleanParam("showTwitchRaids", true); const showTwitchRaids = GetBooleanParam("showTwitchRaids", true);
const showTwitchWatchStreaks = GetBooleanParam("showTwitchWatchStreaks", true);
const showTwitchSharedChat = GetIntParam("showTwitchSharedChat", 2); const showTwitchSharedChat = GetIntParam("showTwitchSharedChat", 2);
const kickUsername = urlParams.get("kickUsername") || ""; const kickUsername = urlParams.get("kickUsername") || "";
@@ -200,6 +201,11 @@ client.on('Twitch.Raid', (response) => {
TwitchRaid(response.data); TwitchRaid(response.data);
}) })
client.on('Twitch.WatchStreak', (response) => {
console.debug(response.data);
TwitchWatchStreak(response.data);
})
client.on('Twitch.ChatMessageDeleted', (response) => { client.on('Twitch.ChatMessageDeleted', (response) => {
console.debug(response.data); console.debug(response.data);
TwitchChatMessageDeleted(response.data); TwitchChatMessageDeleted(response.data);
@@ -1160,6 +1166,67 @@ async function TwitchRaid(data) {
AddMessageItem(instance, data.messageId); AddMessageItem(instance, data.messageId);
} }
async function TwitchWatchStreak(data) {
if (!showTwitchWatchStreaks)
return;
// Get a reference to the template
const template = document.getElementById('cardTemplate');
// Create a new instance of the template
const instance = template.content.cloneNode(true);
// Get divs
const cardDiv = instance.querySelector("#card");
const headerDiv = instance.querySelector("#header");
const avatarDiv = instance.querySelector("#avatar");
const iconDiv = instance.querySelector("#icon");
const titleDiv = instance.querySelector("#title");
const contentDiv = instance.querySelector("#content");
// Set the card background colors
cardDiv.classList.add('twitch');
if (showAvatar) {
// Render avatars
const username = data.userName;
const avatarURL = await GetAvatar(username, 'twitch');
const avatar = new Image();
avatar.src = avatarURL;
avatar.classList.add("avatar");
avatarDiv.appendChild(avatar);
}
const displayName = data.displayName;
const watchStreak = data.watchStreak;
const message = data.message;
titleDiv.innerText = `${displayName} is currently on a ${watchStreak} stream streak! `;
contentDiv.innerText = `${message}`;
// Render emotes
for (i in data.emotes) {
const emoteElement = `<img src="${data.emotes[i].imageUrl}" class="emote"/>`;
const emoteName = EscapeRegExp(data.emotes[i].name);
let regexPattern = emoteName;
// Check if the emote name consists only of word characters (alphanumeric and underscore)
if (/^\w+$/.test(emoteName)) {
regexPattern = `\\b${emoteName}\\b`;
}
else {
// For non-word emotes, ensure they are surrounded by non-word characters or boundaries
regexPattern = `(?<=^|[^\\w])${emoteName}(?=$|[^\\w])`;
}
const regex = new RegExp(regexPattern, 'g');
contentDiv.innerHTML = contentDiv.innerHTML.replace(regex, emoteElement);
}
AddMessageItem(instance, data.messageId);
}
function TwitchChatMessageDeleted(data) { function TwitchChatMessageDeleted(data) {
const messageList = document.getElementById("messageList"); const messageList = document.getElementById("messageList");
@@ -1265,7 +1332,7 @@ async function YouTubeMessage(data) {
if (showUsername) { if (showUsername) {
usernameDiv.innerText = data.user.name; usernameDiv.innerText = data.user.name;
if (randomYouTubeColors) if (randomYouTubeColors)
usernameDiv.style.color = StringToHex(data.user.name); usernameDiv.style.color = RandomHex(data.user.name);
else else
usernameDiv.style.color = youtubeColor; // YouTube users do not have colors, so just set it to red usernameDiv.style.color = youtubeColor; // YouTube users do not have colors, so just set it to red
} }
+8
View File
@@ -282,6 +282,14 @@
"defaultValue": true, "defaultValue": true,
"group": "Which Twitch messages do you want to see?" "group": "Which Twitch messages do you want to see?"
}, },
{
"id": "showTwitchWatchStreaks",
"label": "Watch Streaks",
"description": "",
"type": "checkbox",
"defaultValue": true,
"group": "Which Twitch messages do you want to see?"
},
{ {
"id": "showTwitchSharedChat", "id": "showTwitchSharedChat",
"label": "Shared Chat Messages", "label": "Shared Chat Messages",
+32 -1
View File
@@ -67,6 +67,8 @@ const showTwitchCheers = GetBooleanParam("showTwitchCheers", true);
const twitchCheerAction = urlParams.get("twitchCheerAction") || ""; const twitchCheerAction = urlParams.get("twitchCheerAction") || "";
const showTwitchRaids = GetBooleanParam("showTwitchRaids", true); const showTwitchRaids = GetBooleanParam("showTwitchRaids", true);
const twitchRaidAction = urlParams.get("twitchRaidAction") || ""; const twitchRaidAction = urlParams.get("twitchRaidAction") || "";
const showTwitchWatchStreaks = GetBooleanParam("showTwitchWatchStreaks", true);
const twitchWatchStreaksAction = urlParams.get("twitchWatchStreaksAction") || "";
// Which Kick alerts do you want to see? // Which Kick alerts do you want to see?
const kickUsername = urlParams.get("kickUsername") || ""; const kickUsername = urlParams.get("kickUsername") || "";
@@ -211,6 +213,11 @@ client.on('Twitch.Raid', (response) => {
TwitchRaid(response.data); TwitchRaid(response.data);
}) })
client.on('Twitch.WatchStreak', (response) => {
console.debug(response.data);
TwitchWatchStreak(response.data);
})
client.on('YouTube.SuperChat', (response) => { client.on('YouTube.SuperChat', (response) => {
console.debug(response.data); console.debug(response.data);
YouTubeSuperChat(response.data); YouTubeSuperChat(response.data);
@@ -721,6 +728,30 @@ async function TwitchRaid(data) {
); );
} }
async function TwitchWatchStreak(data) {
if (!showTwitchWatchStreaks)
return;
// Render avatars
const avatarURL = await GetAvatar(data.userName, 'twitch');
// Set the text
const username = data.displayName;
const watchStreak = data.watchStreak;
UpdateAlertBox(
'twitch',
avatarURL,
`${username}`,
`is currently on a ${watchStreak} stream streak!`,
'',
username,
'',
twitchWatchStreaksAction,
data
);
}
function YouTubeSuperChat(data) { function YouTubeSuperChat(data) {
if (!showYouTubeSuperChats) if (!showYouTubeSuperChats)
return; return;
@@ -836,7 +867,7 @@ async function StreamElementsTip(data) {
UpdateAlertBox( UpdateAlertBox(
'streamelements', 'streamelements',
'' '',
`${donater}`, `${donater}`,
`donated ${currency}${formattedAmount}`, `donated ${currency}${formattedAmount}`,
``, ``,
+17
View File
@@ -312,6 +312,23 @@
"showIf": "showTwitchRaids", "showIf": "showTwitchRaids",
"group": "Which Twitch alerts do you want to see?" "group": "Which Twitch alerts do you want to see?"
}, },
{
"id": "showTwitchWatchStreaks",
"label": "Watch Streaks",
"description": "",
"type": "checkbox",
"defaultValue": true,
"group": "Which Twitch alerts do you want to see?"
},
{
"id": "twitchWatchStreaksAction",
"label": "",
"description": "Also run this Streamer.bot Action",
"type": "sb-actions",
"defaultValue": "",
"showIf": "showTwitchWatchStreaks",
"group": "Which Twitch alerts do you want to see?"
},
{ {
"id": "showYouTubeSuperChats", "id": "showYouTubeSuperChats",
"label": "Super Chats", "label": "Super Chats",