diff --git a/horizontal-chat/script.js b/horizontal-chat/script.js index 7cc89be..5c041d0 100644 --- a/horizontal-chat/script.js +++ b/horizontal-chat/script.js @@ -336,7 +336,7 @@ async function TwitchChatMessage(data) { const platformElements = ``; platformDiv.innerHTML = platformElements; } - + // Render badges if (showBadges) { @@ -352,7 +352,21 @@ async function TwitchChatMessage(data) { // Render emotes for (i in data.emotes) { const emoteElement = ``; - messageDiv.innerHTML = messageDiv.innerHTML.replace(new RegExp(`\\b${data.emotes[i].name}\\b`), emoteElement); + 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'); + messageDiv.innerHTML = messageDiv.innerHTML.replace(regex, emoteElement); } // Render cheermotes @@ -417,7 +431,21 @@ async function TwitchAnnouncement(data) { for (i in data.parts) { if (data.parts[i].type == `emote`) { const emoteElement = ``; - message = message.replace(new RegExp(`\\b${data.parts[i].text}\\b`), emoteElement); + const emoteName = EscapeRegExp(data.parts[i].text); + + 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'); + message = message.replace(regex, emoteElement); } } @@ -482,7 +510,7 @@ async function TwitchGiftSub(data) { async function TwitchGiftBomb(data) { if (!showTwitchSubs) return; - + const username = data.displayName; const gifts = data.gifts; const subTier = data.subTier; @@ -755,7 +783,7 @@ function PatreonPledgeCreated(data) { return; const user = data.attributes.full_name; - const amount = (data.attributes.will_pay_amount_cents/100).toFixed(2); + const amount = (data.attributes.will_pay_amount_cents / 100).toFixed(2); const patreonIcon = ``; let message = `${patreonIcon} ${user} joined Patreon ($${amount})`; @@ -1057,9 +1085,9 @@ async function GetPronouns(platform, username) { const response = await client.getUserPronouns(platform, username); const userFound = response.pronoun.userFound; const pronouns = userFound ? `${response.pronoun.pronounSubject}/${response.pronoun.pronounObject}` : ''; - + pronounMap.set(username, pronouns); - + return pronouns; } } @@ -1100,12 +1128,11 @@ function AddMessageItem(element, elementID, platform, userId) { while (messageList.clientWidth > 10 * window.innerWidth) { messageList.removeChild(messageList.firstChild); } - - if (hideAfter > 0) - { + + if (hideAfter > 0) { setTimeout(function () { lineItem.style.opacity = 0; - setTimeout(function() { + setTimeout(function () { messageList.removeChild(lineItem); }, 1000); }, hideAfter * 1000); @@ -1215,42 +1242,46 @@ function GetWinnersList(gifts) { function TranslateToFurry(sentence) { const words = sentence.toLowerCase().split(/\b/); - + const furryWords = words.map(word => { - if (/\w+/.test(word)) { - let newWord = word; - - // Common substitutions - newWord = newWord.replace(/l/g, 'w'); - newWord = newWord.replace(/r/g, 'w'); - newWord = newWord.replace(/th/g, 'f'); - newWord = newWord.replace(/you/g, 'yous'); - newWord = newWord.replace(/my/g, 'mah'); - newWord = newWord.replace(/me/g, 'meh'); - newWord = newWord.replace(/am/g, 'am'); - newWord = newWord.replace(/is/g, 'is'); - newWord = newWord.replace(/are/g, 'are'); - newWord = newWord.replace(/very/g, 'vewy'); - newWord = newWord.replace(/pretty/g, 'pwetty'); - newWord = newWord.replace(/little/g, 'wittle'); - newWord = newWord.replace(/nice/g, 'nyce'); - - // Random additions - if (Math.random() < 0.15) { - newWord += ' nya~'; - } else if (Math.random() < 0.1) { - newWord += ' >w<'; - } else if (Math.random() < 0.05) { - newWord += ' owo'; + if (/\w+/.test(word)) { + let newWord = word; + + // Common substitutions + newWord = newWord.replace(/l/g, 'w'); + newWord = newWord.replace(/r/g, 'w'); + newWord = newWord.replace(/th/g, 'f'); + newWord = newWord.replace(/you/g, 'yous'); + newWord = newWord.replace(/my/g, 'mah'); + newWord = newWord.replace(/me/g, 'meh'); + newWord = newWord.replace(/am/g, 'am'); + newWord = newWord.replace(/is/g, 'is'); + newWord = newWord.replace(/are/g, 'are'); + newWord = newWord.replace(/very/g, 'vewy'); + newWord = newWord.replace(/pretty/g, 'pwetty'); + newWord = newWord.replace(/little/g, 'wittle'); + newWord = newWord.replace(/nice/g, 'nyce'); + + // Random additions + if (Math.random() < 0.15) { + newWord += ' nya~'; + } else if (Math.random() < 0.1) { + newWord += ' >w<'; + } else if (Math.random() < 0.05) { + newWord += ' owo'; + } + + return newWord; } - - return newWord; - } - return word; + return word; }); - + return furryWords.join(''); - } +} + +function EscapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} diff --git a/multichat-overlay/script.js b/multichat-overlay/script.js index 5e56c0d..8fd61b8 100644 --- a/multichat-overlay/script.js +++ b/multichat-overlay/script.js @@ -319,8 +319,7 @@ async function TwitchChatMessage(data) { const isSharedChat = data.isSharedChat; if (isSharedChat) { if (showTwitchSharedChat > 1) { - if (!data.sharedChat.primarySource) - { + if (!data.sharedChat.primarySource) { const sharedChatChannel = data.sharedChat.sourceRoom.name; sharedChatDiv.style.display = 'block'; sharedChatChannelDiv.innerHTML = `💬 ${sharedChatChannel}`; @@ -380,8 +379,7 @@ async function TwitchChatMessage(data) { messageDiv.style.color = messageColor; // Remove the line break - if (inlineChat) - { + if (inlineChat) { instance.querySelector("#colon-separator").style.display = `inline`; instance.querySelector("#line-space").style.display = `none`; } @@ -406,7 +404,21 @@ async function TwitchChatMessage(data) { // Render emotes for (i in data.emotes) { const emoteElement = ``; - messageDiv.innerHTML = messageDiv.innerHTML.replace(new RegExp(`\\b${data.emotes[i].name}\\b`), emoteElement); + 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'); + messageDiv.innerHTML = messageDiv.innerHTML.replace(regex, emoteElement); } // Render cheermotes @@ -585,7 +597,21 @@ async function TwitchAnnouncement(data) { for (i in data.parts) { if (data.parts[i].type == `emote`) { const emoteElement = ``; - content.querySelector("#message").innerHTML = content.querySelector("#message").innerHTML.replace(new RegExp(`\\b${data.parts[i].text}\\b`), emoteElement); + const emoteName = EscapeRegExp(data.parts[i].text); + + 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'); + content.querySelector("#message").innerHTML = content.querySelector("#message").innerHTML.replace(regex, emoteElement); } } @@ -920,8 +946,7 @@ function YouTubeMessage(data) { messageDiv.innerText = TranslateToFurry(data.message); // Remove the line break - if (inlineChat) - { + if (inlineChat) { instance.querySelector("#colon-separator").style.display = `inline`; instance.querySelector("#line-space").style.display = `none`; } @@ -1227,9 +1252,9 @@ function PatreonPledgeCreated(data) { cardDiv.classList.add('patreon'); const user = data.attributes.full_name; - const amount = (data.attributes.will_pay_amount_cents/100).toFixed(2); + const amount = (data.attributes.will_pay_amount_cents / 100).toFixed(2); const patreonIcon = ``; - + titleDiv.innerHTML = `${patreonIcon} ${user} joined Patreon ($${amount})`; AddMessageItem(instance, data.id); @@ -1812,9 +1837,9 @@ async function GetPronouns(platform, username) { const response = await client.getUserPronouns(platform, username); const userFound = response.pronoun.userFound; const pronouns = userFound ? `${response.pronoun.pronounSubject}/${response.pronoun.pronounObject}` : ''; - + pronounMap.set(username, pronouns); - + return pronouns; } } @@ -1977,42 +2002,46 @@ function GetWinnersList(gifts) { function TranslateToFurry(sentence) { const words = sentence.toLowerCase().split(/\b/); - + const furryWords = words.map(word => { - if (/\w+/.test(word)) { - let newWord = word; - - // Common substitutions - newWord = newWord.replace(/l/g, 'w'); - newWord = newWord.replace(/r/g, 'w'); - newWord = newWord.replace(/th/g, 'f'); - newWord = newWord.replace(/you/g, 'yous'); - newWord = newWord.replace(/my/g, 'mah'); - newWord = newWord.replace(/me/g, 'meh'); - newWord = newWord.replace(/am/g, 'am'); - newWord = newWord.replace(/is/g, 'is'); - newWord = newWord.replace(/are/g, 'are'); - newWord = newWord.replace(/very/g, 'vewy'); - newWord = newWord.replace(/pretty/g, 'pwetty'); - newWord = newWord.replace(/little/g, 'wittle'); - newWord = newWord.replace(/nice/g, 'nyce'); - - // Random additions - if (Math.random() < 0.15) { - newWord += ' nya~'; - } else if (Math.random() < 0.1) { - newWord += ' >w<'; - } else if (Math.random() < 0.05) { - newWord += ' owo'; + if (/\w+/.test(word)) { + let newWord = word; + + // Common substitutions + newWord = newWord.replace(/l/g, 'w'); + newWord = newWord.replace(/r/g, 'w'); + newWord = newWord.replace(/th/g, 'f'); + newWord = newWord.replace(/you/g, 'yous'); + newWord = newWord.replace(/my/g, 'mah'); + newWord = newWord.replace(/me/g, 'meh'); + newWord = newWord.replace(/am/g, 'am'); + newWord = newWord.replace(/is/g, 'is'); + newWord = newWord.replace(/are/g, 'are'); + newWord = newWord.replace(/very/g, 'vewy'); + newWord = newWord.replace(/pretty/g, 'pwetty'); + newWord = newWord.replace(/little/g, 'wittle'); + newWord = newWord.replace(/nice/g, 'nyce'); + + // Random additions + if (Math.random() < 0.15) { + newWord += ' nya~'; + } else if (Math.random() < 0.1) { + newWord += ' >w<'; + } else if (Math.random() < 0.05) { + newWord += ' owo'; + } + + return newWord; } - - return newWord; - } - return word; + return word; }); - + return furryWords.join(''); - } +} + +function EscapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +}