Fixed issue with emotes that contain colons

This commit is contained in:
nuttylmao
2025-04-16 02:10:05 +10:00
parent e3d71f77f5
commit e14f58d01d
2 changed files with 147 additions and 87 deletions
+74 -43
View File
@@ -336,7 +336,7 @@ async function TwitchChatMessage(data) {
const platformElements = `<img src="icons/platforms/twitch.png" class="platform"/>`; const platformElements = `<img src="icons/platforms/twitch.png" class="platform"/>`;
platformDiv.innerHTML = platformElements; platformDiv.innerHTML = platformElements;
} }
// Render badges // Render badges
if (showBadges) { if (showBadges) {
@@ -352,7 +352,21 @@ async function TwitchChatMessage(data) {
// Render emotes // Render emotes
for (i in data.emotes) { for (i in data.emotes) {
const emoteElement = `<img src="${data.emotes[i].imageUrl}" class="emote"/>`; const emoteElement = `<img src="${data.emotes[i].imageUrl}" class="emote"/>`;
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 // Render cheermotes
@@ -417,7 +431,21 @@ async function TwitchAnnouncement(data) {
for (i in data.parts) { for (i in data.parts) {
if (data.parts[i].type == `emote`) { if (data.parts[i].type == `emote`) {
const emoteElement = `<img src="${data.parts[i].imageUrl}" class="emote"/>`; const emoteElement = `<img src="${data.parts[i].imageUrl}" class="emote"/>`;
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) { async function TwitchGiftBomb(data) {
if (!showTwitchSubs) if (!showTwitchSubs)
return; return;
const username = data.displayName; const username = data.displayName;
const gifts = data.gifts; const gifts = data.gifts;
const subTier = data.subTier; const subTier = data.subTier;
@@ -755,7 +783,7 @@ function PatreonPledgeCreated(data) {
return; return;
const user = data.attributes.full_name; 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 = `<img src="icons/platforms/patreon.png" class="platform"/>`; const patreonIcon = `<img src="icons/platforms/patreon.png" class="platform"/>`;
let message = `${patreonIcon} ${user} joined Patreon ($${amount})`; let message = `${patreonIcon} ${user} joined Patreon ($${amount})`;
@@ -1057,9 +1085,9 @@ async function GetPronouns(platform, username) {
const response = await client.getUserPronouns(platform, username); const response = await client.getUserPronouns(platform, username);
const userFound = response.pronoun.userFound; const userFound = response.pronoun.userFound;
const pronouns = userFound ? `${response.pronoun.pronounSubject}/${response.pronoun.pronounObject}` : ''; const pronouns = userFound ? `${response.pronoun.pronounSubject}/${response.pronoun.pronounObject}` : '';
pronounMap.set(username, pronouns); pronounMap.set(username, pronouns);
return pronouns; return pronouns;
} }
} }
@@ -1100,12 +1128,11 @@ function AddMessageItem(element, elementID, platform, userId) {
while (messageList.clientWidth > 10 * window.innerWidth) { while (messageList.clientWidth > 10 * window.innerWidth) {
messageList.removeChild(messageList.firstChild); messageList.removeChild(messageList.firstChild);
} }
if (hideAfter > 0) if (hideAfter > 0) {
{
setTimeout(function () { setTimeout(function () {
lineItem.style.opacity = 0; lineItem.style.opacity = 0;
setTimeout(function() { setTimeout(function () {
messageList.removeChild(lineItem); messageList.removeChild(lineItem);
}, 1000); }, 1000);
}, hideAfter * 1000); }, hideAfter * 1000);
@@ -1215,42 +1242,46 @@ function GetWinnersList(gifts) {
function TranslateToFurry(sentence) { function TranslateToFurry(sentence) {
const words = sentence.toLowerCase().split(/\b/); const words = sentence.toLowerCase().split(/\b/);
const furryWords = words.map(word => { const furryWords = words.map(word => {
if (/\w+/.test(word)) { if (/\w+/.test(word)) {
let newWord = word; let newWord = word;
// Common substitutions // Common substitutions
newWord = newWord.replace(/l/g, 'w'); newWord = newWord.replace(/l/g, 'w');
newWord = newWord.replace(/r/g, 'w'); newWord = newWord.replace(/r/g, 'w');
newWord = newWord.replace(/th/g, 'f'); newWord = newWord.replace(/th/g, 'f');
newWord = newWord.replace(/you/g, 'yous'); newWord = newWord.replace(/you/g, 'yous');
newWord = newWord.replace(/my/g, 'mah'); newWord = newWord.replace(/my/g, 'mah');
newWord = newWord.replace(/me/g, 'meh'); newWord = newWord.replace(/me/g, 'meh');
newWord = newWord.replace(/am/g, 'am'); newWord = newWord.replace(/am/g, 'am');
newWord = newWord.replace(/is/g, 'is'); newWord = newWord.replace(/is/g, 'is');
newWord = newWord.replace(/are/g, 'are'); newWord = newWord.replace(/are/g, 'are');
newWord = newWord.replace(/very/g, 'vewy'); newWord = newWord.replace(/very/g, 'vewy');
newWord = newWord.replace(/pretty/g, 'pwetty'); newWord = newWord.replace(/pretty/g, 'pwetty');
newWord = newWord.replace(/little/g, 'wittle'); newWord = newWord.replace(/little/g, 'wittle');
newWord = newWord.replace(/nice/g, 'nyce'); newWord = newWord.replace(/nice/g, 'nyce');
// Random additions // Random additions
if (Math.random() < 0.15) { if (Math.random() < 0.15) {
newWord += ' nya~'; newWord += ' nya~';
} else if (Math.random() < 0.1) { } else if (Math.random() < 0.1) {
newWord += ' >w<'; newWord += ' >w<';
} else if (Math.random() < 0.05) { } else if (Math.random() < 0.05) {
newWord += ' owo'; newWord += ' owo';
}
return newWord;
} }
return word;
return newWord;
}
return word;
}); });
return furryWords.join(''); return furryWords.join('');
} }
function EscapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
+73 -44
View File
@@ -319,8 +319,7 @@ async function TwitchChatMessage(data) {
const isSharedChat = data.isSharedChat; const isSharedChat = data.isSharedChat;
if (isSharedChat) { if (isSharedChat) {
if (showTwitchSharedChat > 1) { if (showTwitchSharedChat > 1) {
if (!data.sharedChat.primarySource) if (!data.sharedChat.primarySource) {
{
const sharedChatChannel = data.sharedChat.sourceRoom.name; const sharedChatChannel = data.sharedChat.sourceRoom.name;
sharedChatDiv.style.display = 'block'; sharedChatDiv.style.display = 'block';
sharedChatChannelDiv.innerHTML = `💬 ${sharedChatChannel}`; sharedChatChannelDiv.innerHTML = `💬 ${sharedChatChannel}`;
@@ -380,8 +379,7 @@ async function TwitchChatMessage(data) {
messageDiv.style.color = messageColor; messageDiv.style.color = messageColor;
// Remove the line break // Remove the line break
if (inlineChat) if (inlineChat) {
{
instance.querySelector("#colon-separator").style.display = `inline`; instance.querySelector("#colon-separator").style.display = `inline`;
instance.querySelector("#line-space").style.display = `none`; instance.querySelector("#line-space").style.display = `none`;
} }
@@ -406,7 +404,21 @@ async function TwitchChatMessage(data) {
// Render emotes // Render emotes
for (i in data.emotes) { for (i in data.emotes) {
const emoteElement = `<img src="${data.emotes[i].imageUrl}" class="emote"/>`; const emoteElement = `<img src="${data.emotes[i].imageUrl}" class="emote"/>`;
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 // Render cheermotes
@@ -585,7 +597,21 @@ async function TwitchAnnouncement(data) {
for (i in data.parts) { for (i in data.parts) {
if (data.parts[i].type == `emote`) { if (data.parts[i].type == `emote`) {
const emoteElement = `<img src="${data.parts[i].imageUrl}" class="emote"/>`; const emoteElement = `<img src="${data.parts[i].imageUrl}" class="emote"/>`;
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); messageDiv.innerText = TranslateToFurry(data.message);
// Remove the line break // Remove the line break
if (inlineChat) if (inlineChat) {
{
instance.querySelector("#colon-separator").style.display = `inline`; instance.querySelector("#colon-separator").style.display = `inline`;
instance.querySelector("#line-space").style.display = `none`; instance.querySelector("#line-space").style.display = `none`;
} }
@@ -1227,9 +1252,9 @@ function PatreonPledgeCreated(data) {
cardDiv.classList.add('patreon'); cardDiv.classList.add('patreon');
const user = data.attributes.full_name; 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 = `<img src="icons/platforms/patreon.png" class="platform"/>`; const patreonIcon = `<img src="icons/platforms/patreon.png" class="platform"/>`;
titleDiv.innerHTML = `${patreonIcon} ${user} joined Patreon ($${amount})`; titleDiv.innerHTML = `${patreonIcon} ${user} joined Patreon ($${amount})`;
AddMessageItem(instance, data.id); AddMessageItem(instance, data.id);
@@ -1812,9 +1837,9 @@ async function GetPronouns(platform, username) {
const response = await client.getUserPronouns(platform, username); const response = await client.getUserPronouns(platform, username);
const userFound = response.pronoun.userFound; const userFound = response.pronoun.userFound;
const pronouns = userFound ? `${response.pronoun.pronounSubject}/${response.pronoun.pronounObject}` : ''; const pronouns = userFound ? `${response.pronoun.pronounSubject}/${response.pronoun.pronounObject}` : '';
pronounMap.set(username, pronouns); pronounMap.set(username, pronouns);
return pronouns; return pronouns;
} }
} }
@@ -1977,42 +2002,46 @@ function GetWinnersList(gifts) {
function TranslateToFurry(sentence) { function TranslateToFurry(sentence) {
const words = sentence.toLowerCase().split(/\b/); const words = sentence.toLowerCase().split(/\b/);
const furryWords = words.map(word => { const furryWords = words.map(word => {
if (/\w+/.test(word)) { if (/\w+/.test(word)) {
let newWord = word; let newWord = word;
// Common substitutions // Common substitutions
newWord = newWord.replace(/l/g, 'w'); newWord = newWord.replace(/l/g, 'w');
newWord = newWord.replace(/r/g, 'w'); newWord = newWord.replace(/r/g, 'w');
newWord = newWord.replace(/th/g, 'f'); newWord = newWord.replace(/th/g, 'f');
newWord = newWord.replace(/you/g, 'yous'); newWord = newWord.replace(/you/g, 'yous');
newWord = newWord.replace(/my/g, 'mah'); newWord = newWord.replace(/my/g, 'mah');
newWord = newWord.replace(/me/g, 'meh'); newWord = newWord.replace(/me/g, 'meh');
newWord = newWord.replace(/am/g, 'am'); newWord = newWord.replace(/am/g, 'am');
newWord = newWord.replace(/is/g, 'is'); newWord = newWord.replace(/is/g, 'is');
newWord = newWord.replace(/are/g, 'are'); newWord = newWord.replace(/are/g, 'are');
newWord = newWord.replace(/very/g, 'vewy'); newWord = newWord.replace(/very/g, 'vewy');
newWord = newWord.replace(/pretty/g, 'pwetty'); newWord = newWord.replace(/pretty/g, 'pwetty');
newWord = newWord.replace(/little/g, 'wittle'); newWord = newWord.replace(/little/g, 'wittle');
newWord = newWord.replace(/nice/g, 'nyce'); newWord = newWord.replace(/nice/g, 'nyce');
// Random additions // Random additions
if (Math.random() < 0.15) { if (Math.random() < 0.15) {
newWord += ' nya~'; newWord += ' nya~';
} else if (Math.random() < 0.1) { } else if (Math.random() < 0.1) {
newWord += ' >w<'; newWord += ' >w<';
} else if (Math.random() < 0.05) { } else if (Math.random() < 0.05) {
newWord += ' owo'; newWord += ' owo';
}
return newWord;
} }
return word;
return newWord;
}
return word;
}); });
return furryWords.join(''); return furryWords.join('');
} }
function EscapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}