0% found this document useful (0 votes)
4K views

JS

1. The document defines global variables and event settings for a Twitch chat widget. 2. On startup, it grabs chat settings from fields and initializes the global variables. 3. It also defines test events for different user types (broadcaster, moderator, subscriber, regular user) that can be used to simulate messages in the widget.

Uploaded by

88.diankurnia
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4K views

JS

1. The document defines global variables and event settings for a Twitch chat widget. 2. On startup, it grabs chat settings from fields and initializes the global variables. 3. It also defines test events for different user types (broadcaster, moderator, subscriber, regular user) that can be used to simulate messages in the widget.

Uploaded by

88.diankurnia
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 21

let ver = "1.

0"

// global variables
let msgLimit, hideAfter, hideCommands, provider, hasEmotes, widget_width;
let totalMsg = 0;
let ignoredUsers = [];
let commands = [];
let removeSelector;
let displayBadges = 'no';
let displayPronouns = 'no';
let displayUpdates = false
let colors_enabled = true
let test_streamer, test_mod, test_sub, test_reg;

let previousName = null;


let previousMsg = null;

let displayedMsg = []

let events = {
cheer: {
enabled: false,
min: 1,
class: "cheer"
},
tip: {
enabled: false,
min: 1,
currency: "$",
class: "tip"
},
sub: {
enabled: false,
class: "sub"
},
resub: {
enabled: false,
class: "resub"
},
gift: {
enabled: false,
class: "gift"
},
direct: {
enabled: false,
class: "direct"
}
}

// Initial setup on widget startup


window.addEventListener('onWidgetLoad', async function (obj) {
// Grabbing chat settings from fields
const fieldData = obj.detail.fieldData;

hideAfter = fieldData.hideAfter;
msgLimit = fieldData.messagesLimit;
hideCommands = fieldData.hideCommands;
events.cheer.enabled = fieldData.cheerEnabled;
events.cheer.min = fieldData.cheerMin;

events.tip.enabled = fieldData.tipEnabled;
events.tip.min = fieldData.tipMin;
events.tip.currency = fieldData.tipCurrency;

events.sub.enabled = fieldData.subEnabled;

events.resub.enabled = fieldData.resubEnabled;

events.gift.enabled = fieldData.giftEnabled;

events.direct.enabled = fieldData.directEnabled;

widget_width = $(document).width();
channelName = fieldData.testMessageName

test_streamer = new CustomEvent("onEventReceived", {


detail: {
listener: "message",
event: {
service: "twitch",
data: {
time: Date.now(),
tags: {
"badge-info": "",
badges: "broadcaster/1,subscriber/1",
color: "#5B99FF",
"display-name": "StreamElements",
emotes: "25:46-50",
flags: "",
id: "43285909-412c-4eee-b80d-89f72ba53142",
mod: "1",
"room-id": "85827806",
subscriber: "0",
"tmi-sent-ts": "1579444549265",
turbo: "0",
"user-id": "100135110",
"user-type": "mod"
},
nick: channelName,
userId: "100135110",
displayName: "Broadcaster",
displayColor: "#5B99FF",
badges: [{
type: "moderator",
version: "1",
url: "https://static-cdn.jtvnw.net/badges/v1/3267646d-33f0-
4b17-b3df-f923a41db1d0/3",
description: "Moderator"
}, {
type: "partner",
version: "1",
url: "https://static-cdn.jtvnw.net/badges/v1/d12a2e27-16f6-
41d0-ab77-b780518f00a3/3",
description: "Verified"
}],
channel: channelName,
text: "Check Eightyeight on Ko-Fi!",
isAction: !1,
emotes: [{
type: "twitch",
name: "Kappa",
id: "25",
gif: !1,
urls: {
1: "https://static-cdn.jtvnw.net/emoticons/v1/25/1.0",
2: "https://static-cdn.jtvnw.net/emoticons/v1/25/1.0",
4: "https://static-cdn.jtvnw.net/emoticons/v1/25/3.0"
},
start: 46,
end: 50
}],
msgId: ""
},
renderedText: 'Lorem Ipsum <img
src="https://static-cdn.jtvnw.net/emoticons/v1/25/1.0" srcset="https://static-
cdn.jtvnw.net/emoticons/v1/25/1.0 1x,
https://static-cdn.jtvnw.net/emoticons/v1/25/1.0 2x,
https://static-cdn.jtvnw.net/emoticons/v1/25/3.0 4x" title="Kappa" class="emote">
Broadcaster Test'
}
}
});

test_mod = new CustomEvent("onEventReceived", {


detail: {
listener: "message",
event: {
service: "twitch",
data: {
time: Date.now(),
tags: {
"badge-info": "",
badges: "moderator/1,partner/1",
color: "#5B99FF",
"display-name": "StreamElements",
emotes: "25:46-50",
flags: "",
id: "43285909-412c-4eee-b80d-89f72ba53142",
mod: "1",
"room-id": "85827806",
subscriber: "0",
"tmi-sent-ts": "1579444549265",
turbo: "0",
"user-id": "100135110",
"user-type": "mod"
},
nick: channelName,
userId: "100135110",
displayName: 'Moderator',
displayColor: "#5B99FF",
badges: [{
type: "moderator",
version: "1",
url: "https://static-cdn.jtvnw.net/badges/v1/3267646d-33f0-
4b17-b3df-f923a41db1d0/3",
description: "Moderator"
}, {
type: "partner",
version: "1",
url: "https://static-cdn.jtvnw.net/badges/v1/d12a2e27-16f6-
41d0-ab77-b780518f00a3/3",
description: "Verified"
}],
channel: channelName,
text: "Custom emotes, YCH, Animated emotes.",
isAction: !1,
emotes: [],
msgId: ""
},
renderedText: 'Eightyeight - Grow with Fun. <img
src="https://static-cdn.jtvnw.net/emoticons/v1/25/1.0" srcset="https://static-
cdn.jtvnw.net/emoticons/v1/25/1.0 1x,
https://static-cdn.jtvnw.net/emoticons/v1/25/1.0 2x,
https://static-cdn.jtvnw.net/emoticons/v1/25/3.0 4x" title="Kappa" class="emote">'
}
}
});

test_sub = new CustomEvent("onEventReceived", {


detail: {
listener: "message",
event: {
service: "twitch",
data: {
time: Date.now(),
tags: {
"badge-info": "",
badges: "subscriber/1",
color: "#5B99FF",
"display-name": "StreamElements",
emotes: "25:46-50",
flags: "",
id: "43285909-412c-4eee-b80d-89f72ba53142",
mod: "1",
"room-id": "85827806",
subscriber: "0",
"tmi-sent-ts": "1579444549265",
turbo: "0",
"user-id": "100135110",
"user-type": "mod"
},
nick: channelName,
userId: "100135110",
displayName: 'Subscriber',
displayColor: "#5B99FF",
badges: [{
type: "moderator",
version: "1",
url: "https://static-cdn.jtvnw.net/badges/v1/3267646d-33f0-
4b17-b3df-f923a41db1d0/3",
description: "Moderator"
}, {
type: "partner",
version: "1",
url: "https://static-cdn.jtvnw.net/badges/v1/d12a2e27-16f6-
41d0-ab77-b780518f00a3/3",
description: "Verified"
}],
channel: channelName,
text: "Eightyeight - Grow with Fun.",
isAction: !1,
emotes: [],
msgId: ""
},
renderedText: 'Eightyeight - Grow with Fun. <img
src="https://static-cdn.jtvnw.net/emoticons/v1/25/1.0" srcset="https://static-
cdn.jtvnw.net/emoticons/v1/25/1.0 1x,
https://static-cdn.jtvnw.net/emoticons/v1/25/1.0 2x,
https://static-cdn.jtvnw.net/emoticons/v1/25/3.0 4x" title="Kappa" class="emote">'
}
}
});

test_reg = new CustomEvent("onEventReceived", {


detail: {
listener: "message",
event: {
service: "twitch",
data: {
time: Date.now(),
tags: {
"badge-info": "",
badges: "",
color: "#5B99FF",
"display-name": "StreamElements",
emotes: "25:46-50",
flags: "",
id: "43285909-412c-4eee-b80d-89f72ba53142",
mod: "1",
"room-id": "85827806",
subscriber: "0",
"tmi-sent-ts": "1579444549265",
turbo: "0",
"user-id": "100135110",
"user-type": "mod"
},
nick: channelName,
userId: "100135110",
displayName: channelName,
displayColor: "#5B99FF",
badges: [],
channel: channelName,
text: "Eightyeight - Grow with Fun. Kappa",
isAction: !1,
emotes: [],
msgId: ""
},
renderedText: 'Eightyeight - Grow with Fun. <img
src="https://static-cdn.jtvnw.net/emoticons/v1/25/1.0" srcset="https://static-
cdn.jtvnw.net/emoticons/v1/25/1.0 1x,
https://static-cdn.jtvnw.net/emoticons/v1/25/1.0 2x,
https://static-cdn.jtvnw.net/emoticons/v1/25/3.0 4x" title="Kappa" class="emote">'
}
}
});
test_reg.detail.event.data.text = fieldData.testMessageText;

fetch('https://api.streamelements.com/kappa/v2/channels/' +
obj.detail.channel.id + '/')
.then(response => response.json()).then((profile) => {
provider = profile.provider;
});

removeSelector = ".message-row:nth-last-child(n+" + (msgLimit + 1) + ")"

// Ignore message
ignoredUsers = fieldData.ignoredUsers.toLowerCase()
.replace(" ", "").split(",");
commands = fieldData.ignoredCommands.toLowerCase()
.replace(" ", "").split(",");
});

// for StreamElements events


window.addEventListener('onEventReceived', function (obj) {
// Define what to do on different events

if (obj.detail.event.listener === 'widget-button') {


switch (obj.detail.event.field) {
case 'testMessage':
test_streamer.detail.event.data.msgId = (Math.random() +
1).toString(36).substring(7) + (Math.random() + 1).toString(36).substring(7)
window.dispatchEvent(test_streamer);
break;
case 'testMessage1':
test_mod.detail.event.data.msgId = (Math.random() +
1).toString(36).substring(7) + (Math.random() + 1).toString(36).substring(7)
window.dispatchEvent(test_mod);
break
case 'testMessage2':
test_sub.detail.event.data.msgId = (Math.random() +
1).toString(36).substring(7) + (Math.random() + 1).toString(36).substring(7)
window.dispatchEvent(test_sub);
break
case 'testMessage3':
test_reg.detail.event.data.msgId = (Math.random() +
1).toString(36).substring(7) + (Math.random() + 1).toString(36).substring(7)
window.dispatchEvent(test_reg);
break
}
}

// message deletion
if (obj.detail.listener === "delete-message") {
const msgId = obj.detail.event.msgId;
$(`.message-row[data-msgid=${msgId}]`).remove();
return;
} else if (obj.detail.listener === "delete-messages") {
const sender = obj.detail.event.userId;
$(`.message-row[data-sender=${sender}]`).remove();
return;
}

if (obj.detail.listener === "cheer-latest") {


let evt = obj.detail.event;
let username = evt.name;
let amount = evt.amount;
if (amount < events.cheer.min || !events.cheer.enabled) {
return
}
alertCheer(username, amount);
return
}

if (obj.detail.listener === "tip-latest") {


let evt = obj.detail.event;
let username = evt.name;
let amount = evt.amount;
if (amount < events.tip.min || !events.tip.enabled) {
return
}
alertTip(username, amount);
return
}

if (obj.detail.listener === "subscriber-latest") {


let evt = obj.detail.event;
let username = evt.name;
let amount = evt.amount;
let bulkGifted = evt.bulkGifted;
let sender = evt.sender;
let isCommunityGift = false;
isCommunityGift = evt.isCommunityGift;

let gifted = false;


gifted = evt.gifted;

if (isCommunityGift) return;

if (bulkGifted && events.gift.enabled) {


alertBulkGift(username, amount);
} else if (gifted && events.direct.enabled) {
alertGift(sender, username);
} else if (amount > 1 && events.resub.enabled) {
alertReSub(username, amount);
} else if (events.sub.enabled) {
alertSub(username);
}
return;
}

// chat message
if (obj.detail.listener === "message") {
let data = obj.detail.event.data;

if (ignoredUsers.indexOf(data.nick) !== -1) {


return;
}
let role = check_role(data);
let name = data.displayName;
let message = attachEmotes(data);

let badges = ``;


if (displayBadges) {
for (let i = 0; i < data.badges.length; i++) {
badge = data.badges[i];
badges += `<img alt="" src="${badge.url}" class="badge"> `;
}
}

const emoteOnly = isEmote(data);

const isCommand = commands.some(prefix => data.text.startsWith(prefix));


if (isCommand && hideCommands === "yes") {
return;
}

let pn = null;

const pn_api = fetch('https://pronouns.alejo.io/api/users/' +


data.displayName.toLowerCase())
.then((response) => response.json())
.then((user) => {
if (!user.length) {
return null;
} else return user[0].pronoun_id;
});

const printAddress = async () => {


pn = await pn_api;
switch (pn) {
case "hehim":
pn = "he/him";
break
case "sheher":
pn = "she/her";
break;
}
return pn;
}

printAddress().then(pn => addMessage(name, null, role, badges, message,


emoteOnly, data.isAction, data.userId, data.msgId, pn));
}
});

function attachEmotes(message) {
let text = html_encode(message.text);
let data = message.emotes;
if (typeof message.attachment !== "undefined") {
if (typeof message.attachment.media !== "undefined") {
if (typeof message.attachment.media.image !== "undefined") {
text = `${message.text}<img src="$
{message.attachment.media.image.src}">`;
}
}
}
return text
.replace(
/([^\s]*)/gi,
function (m, key) {
let result = data.filter(emote => {
return html_encode(emote.name) === key
});
if (typeof result[0] !== "undefined") {
let url = result[0]['urls'][1];
if (provider === "twitch") {
return `<img class="emote" " src="${url}"/>`;
} else {
if (typeof result[0].coords === "undefined") {
result[0].coords = {x: 0, y: 0};
}
let x = parseInt(result[0].coords.x);
let y = parseInt(result[0].coords.y);

let width = "{emoteSize}px";


let height = "auto";

if (provider === "mixer") {


console.log(result[0]);
if (result[0].coords.width) {
width = `${result[0].coords.width}px`;
}
if (result[0].coords.height) {
height = `${result[0].coords.height}px`;
}
}
return `<div class="emote" style="width: ${width}; height:$
{height}; display: inline-block; background-image: url(${url}); background-
position: -${x}px -${y}px;"></div>`;
}
} else return key;

}
);
}

function html_encode(e) {
return e.replace(/[<>"^]/g, function (e) {
return "&#" + e.charCodeAt(0) + ";";
});
}

// message render
function addMessage(name, reply, badge, badges, message, isEmote, isAction, userId,
msgId, pn) {

totalMsg += 1;

const actionClass = isAction ? "action" : "";


const emoteOnly = isEmote ? "emote-only" : "";

let pn_none = ""


if (!displayPronouns || pn == null) {
pn_none = "style='display: none'"
}
const mentions = message.match(/@\S+/g)
if (mentions) {
for (var i = 0; i < mentions.length; i++) {
message = message.replace(mentions[i], `<p style="color: #FFDEE6">$
{mentions[i]}</p>`)
}
}

let roleIcon, broadcasterClass;

broadcasterClass = '';
let broadcasterBorder = '';
let broadcasterFill = '';
let broadcasterUsername = '';

role = badge[0]
switch (role) {
case "broadcaster":
roleIcon = `
<div class="icon-role__broadcaster">
<svg width="15" height="15" viewBox="0 0 15 15" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path d="M10.125 5.53125V10.7812C10.125 11.0133 10.0328 11.2359
9.86872 11.4C9.70462 11.5641 9.48206 11.6562 9.25 11.6562H3.125C2.83773 11.6562
2.55328 11.5997 2.28788 11.4897C2.02248 11.3798 1.78133 11.2187 1.5782
11.0155C1.16797 10.6053 0.9375 10.0489 0.9375 9.46875V4.21875C0.9375 3.98669
1.02969 3.76413 1.19378 3.60003C1.35788 3.43594 1.58044 3.34375 1.8125
3.34375H7.9375C8.51766 3.34375 9.07406 3.57422 9.4843 3.98445C9.89453 4.39469
10.125 4.95109 10.125 5.53125ZM13.8438 4.49766C13.7778 4.45758 13.7022 4.43638
13.625 4.43638C13.5478 4.43638 13.4722 4.45758 13.4062 4.49766L11.2188
5.74453C11.1517 5.78326 11.0961 5.83911 11.0576 5.90637C11.0192 5.97362 10.9993
6.04988 11 6.12734V8.87266C10.9993 8.95012 11.0192 9.02637 11.0576 9.09363C11.0961
9.16089 11.1517 9.21674 11.2188 9.25547L13.4062 10.5023C13.4729 10.5406 13.5482
10.5613 13.625 10.5625C13.7019 10.562 13.7774 10.5413 13.8438 10.5023C13.9108
10.4649 13.9665 10.4102 14.005 10.3437C14.0435 10.2773 14.0634 10.2018 14.0625
10.125V4.875C14.0634 4.79824 14.0435 4.72267 14.005 4.65626C13.9665 4.58984 13.9108
4.53505 13.8438 4.49766Z" fill="#FFFFFF"/>
</svg>
</div>
`
broadcasterClass = 'broadcaster-fill';
broadcasterFill = 'broadcaster-fill';
broadcasterUsername = 'username__broadcaster';
broadcasterBorder = 'style="border-top-right: solid 6px #FFFFFF !
important;"'
break
case "moderator":
roleIcon = `
<div class="icon-role">
<svg width="15" height="15" viewBox="0 0 15 15" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M11.4219 12.8594C11.2448 12.8594 11.0755 12.8255 10.9141
12.7578C10.7526 12.6901 10.6042 12.5885 10.4688 12.4531L6.98437 8.9375C6.74479
9.02083 6.50521 9.08854 6.26562 9.14062C6.02604 9.19271 5.78125 9.21875 5.53125
9.21875C4.52083 9.21875 3.66146 8.86719 2.95312 8.16406C2.24479 7.46094 1.89062
6.60417 1.89062 5.59375C1.89062 5.27083 1.93229 4.95573 2.01562 4.64844C2.09896
4.34115 2.21875 4.05208 2.375 3.78125L4.64063 6.04688L6.07813 4.70313L3.75
2.375C4.02083 2.21875 4.30729 2.09635 4.60937 2.00781C4.91146 1.91927 5.21875 1.875
5.53125 1.875C6.5625 1.875 7.4401 2.23698 8.16406 2.96094C8.88802 3.6849 9.25
4.5625 9.25 5.59375C9.25 5.84375 9.22396 6.08854 9.17187 6.32812C9.11979 6.56771
9.05208 6.80729 8.96875 7.04687L12.4219 10.5C12.5573 10.6354 12.6589 10.7891
12.7266 10.9609C12.7943 11.1328 12.8281 11.3125 12.8281 11.5C12.8281 11.6875
12.7917 11.8672 12.7188 12.0391C12.6458 12.2109 12.5365 12.3594 12.3906
12.4844C12.2448 12.6094 12.0911 12.7031 11.9297 12.7656C11.7682 12.8281 11.599
12.8594 11.4219 12.8594Z"
fill="#FFFFFF" />
</svg>
</div>
`
break
case "vip":
roleIcon = `
<div class="icon-role">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M5.22078 4.88542L6.75203 1.75H7.24787L8.77912
4.88542H5.22078ZM6.63537 11.8125L1.47287 5.61458H6.63537V11.8125ZM7.36454
11.8125V5.61458H12.527L7.36454 11.8125ZM9.59579 4.88542L8.06453 1.75H10.5437C10.709
1.75 10.8621 1.79375 11.0031 1.88125C11.144 1.96875 11.2534 2.08542 11.3312
2.23125L12.6437 4.88542H9.59579ZM1.3562 4.88542L2.6687 2.23125C2.74648 2.08542
2.85585 1.96875 2.99683 1.88125C3.1378 1.79375 3.29092 1.75 3.4562
1.75H5.93537L4.40412 4.88542H1.3562Z"
fill="#FFFFFF" />
</svg>
</div>
`
break
case "artist":
roleIcon = ``
break
case "subscriber":
roleIcon = `
<div class="icon-role">
<svg width="13" height="11" viewBox="0 0 13 11" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M11.7829 1.33822C11.4863 1.00543 11.1246 0.737114
10.7201 0.549909C10.3156 0.362704 9.8769 0.260603 9.4313 0.24994C8.98608 0.240181
8.54348 0.320399 8.13001 0.485787C7.71654 0.651175 7.34071 0.898329 7.02505
1.21244L6.50004 1.73197L6.08989 1.32728C4.81567 0.0475964 2.73755 -0.0617786
1.46333 1.09213C1.13172 1.38961 0.864266 1.75161 0.677335 2.15599C0.490403 2.56036
0.387917 2.99862 0.376144 3.44395C0.364371 3.88929 0.443558 4.33235 0.608862
4.74604C0.774167 5.15973 1.02211 5.53535 1.33755 5.84994L5.88208 10.3945C5.96293
10.4762 6.05918 10.541 6.16525 10.5852C6.27132 10.6295 6.38511 10.6523 6.50004
10.6523C6.61498 10.6523 6.72877 10.6295 6.83484 10.5852C6.94091 10.541 7.03716
10.4762 7.11801 10.3945L11.5477 5.96478C12.8274 4.69057 12.9313 2.61244 11.7829
1.33822Z"
fill="#FFFFFF" />
</svg>
</div>
`
break;
default:
roleIcon = ``
break
}

name_ = name.concat("");

let fullMsg = `
<div data-sender="${userId}" data-msgid="${msgId}" class="message-row" id="msg-
${totalMsg}">

<div class="message-wrap">

<div class="user-box">

${roleIcon}

<div ${broadcasterUsername} class="username">


<span class="username-text">${name}</span>
<span ${pn_none} class="divider"></span>
<span ${pn_none} class="pronouns">${pn}</span>
</div>

<div class="user-box__love-gerak">
<svg width="25.95" height="23.02"
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 25.95 23.02">
<defs>
<linearGradient id="myGradient" x1="0%" y1="0%"
x2="0%" y2="100%">
<stop offset="0%" style="stop-color:rgb(255,
209, 230);stop-opacity:1" />
<stop offset="100%" style="stop-
color:rgb(207, 33, 102);stop-opacity:1" />
</linearGradient>
</defs>
<path

d="m.63,4.39C-.07,6.08-.19,7.96.3,9.72c.78,3.34,6.13,12.65,7.76,13.24s11.64-
3.14,14.41-5.23c1.5-1.05,2.61-2.56,3.16-4.31,1.13-3.53-.68-7.34-4.14-8.69-3.39-
1.23-6.93,1.83-7.43,1.64S12.93,1.64,9.39.36C5.86-.81,2.03.95.63,4.39Z"
fill="url(#myGradient)" />
</svg>
</div>

</div>

<div class="message-box">

<div class="message ${emoteOnly}">


<p>${message}</p>
</div>

</div>
</div>
`

const element = $.parseHTML(fullMsg);

if (hideAfter !== 999) {


$(element).appendTo('.main-container').delay(hideAfter * 1000).animate({
opacity: 0
}, 'fast', function () {
$(element).remove();
});
} else {
$(element).appendTo('.main-container');
}

// Removes messages if the total number


// of messages goes over the limit
if (totalMsg > msgLimit) {
removeRow();
}
}

function appendAlert(block) {
let alertTemplate = `
<div class="message-row" id="msg-${totalMsg}">

<div class="alert-wrap">

<div class="background">
<svg width="764px" height="157px" id="gift-box-love"
xmlns="http://www.w3.org/2000/svg" viewBox="-40 0 674.48 157.66">
<defs>
<style>
.ranting {
fill: #f07fb5;
opacity: 0.4;
}
</style>
</defs>
<path class="ranting" d="m436.54,108.7c-3.71-
7.12-13.27-11.65-21.38-12.06,4.3-6.89,6.06-17.32,2.35-24.43-3.08-5.82-8.36-10.17-
14.66-12.09-6.26-1.98-13.04-1.37-18.84,1.7-7.48,3.9-11.3,12.16-13.86,18.83l-
16.24,46.3c-.33,1.07.27,2.21,1.33,2.55l47.26,13.19c6.93,1.72,15.89,3.32,23.37-.58,1
2.12-6.32,16.88-21.24,10.66-33.41Z"/>
<path class="ranting" d="m32.27,39.88c-
4.94,4.22-6.78,12.59-5.63,19.07-6.22-2.14-14.77-1.63-19.71,2.6-4.03,3.49-6.51,8.45-
6.87,13.77-.42,5.3,1.3,10.54,4.77,14.56,4.44,5.19,11.65,6.7,17.38,7.5l39.49,4.39c.9
1.06,1.69-.61,1.77-1.52l1.8-39.7c.1-5.78-.27-13.14-4.71-18.34-7.2-8.42-19.83-9.46-
28.31-2.33Z"/>
<path class="ranting" d="m296.08,40.5c-22.88-
7.25-52.7,3.31-70.75,19.54-5.41-23.66-23.7-49.47-46.58-56.72-18.81-5.84-39.17-3.93-
56.56,5.32-17.43,9-30.52,24.62-36.34,43.36-
7.62,24.05,1.43,49.73,10.37,69.13,15.35,33.32,67.09,91.01,67.09,91.01,1.57,2.96,5.2
2,4.12,8.21,2.6,0,0,92.42-12,124.16-30.4,18.48-10.71,40.67-26.49,48.3-50.54,12.35-
38.98-9.03-80.62-47.9-93.3Z"/>
</svg>
</div>

${block}

</div>
</div>
`

let element;
element = $.parseHTML(alertTemplate);

if (hideAfter !== 999) {


$(element).appendTo('.main-container').delay(hideAfter * 1000).animate({
opacity: 0
}, 'fast', function () {
$(element).remove();
});
} else {
$(element).appendTo('.main-container');
}

// Removes messages if the total number


// of messages goes over the limit
if (totalMsg > msgLimit) {
removeRow();
}
}

function alertSub(username) {
totalMsg += 1;
let block_to_append = `
<div class="alert-message">

<div class="header">
<div class="heart-bubble">
<svg width="29.38" height="21.34" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 29.38 21.34">
<defs>
<style>
.cls-1 {
fill: #ef4c76;
stroke-width: 0px;
}
</style>
</defs>
<path class="cls-1" d="M24.63,21.34c-9.12-6.75-21.33-1.08-21.33-
1.08L0,6.27C13.25,15.98,14.69,0,14.69,0c2.73,16.5,14.69,6.55,14.69,6.55l-
4.75,14.79Z"/>
</svg>
</div>

<div class="username">
<p class="alert-username">${username}</p>
</div>
</div>

<p>Thank you for the sub, love you!</p>

</div>
`

appendAlert(block_to_append)
}
function alertReSub(username, amount) {
totalMsg += 1;
let block_to_append = `
<div class="alert-message">

<div class="header">
<div class="heart-bubble">
<svg width="19.46" height="16.59" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 19.46 16.59">
<defs>
<style>
.cls-1 {
fill: #ef4c76;
stroke-width: 0px;
}
</style>
</defs>
<path class="cls-1" d="M18.19,1.74c-.47-.53-1.05-.96-1.69-
1.26C15.85.18,15.15.02,14.44,0c-.71-.02-1.42.11-2.07.38-.66.26-1.26.66-
1.76,1.16l-.84.83-.65-.65C7.08-.32,3.77-.5,1.74,1.34c-.53.47-.96,1.05-
1.25,1.7C.18,3.69.02,4.38,0,5.09c-.02.71.11,1.42.37,2.08.26.66.66,1.26,1.16,1.76l7.
25,7.25c.13.13.28.23.45.3.17.07.35.11.53.11s.36-.04.53-.11c.17-.07.32-.17.45-.3l7.0
6-7.06c2.04-2.03,2.21-5.35.38-7.38Z"/>
</svg>
</div>

<div class="username">
<p class="alert-username">${username}</p>
</div>
</div>

<p>Resubscribed for ${amount} months!</p>

</div>
`

appendAlert(block_to_append)
}

function alertBulkGift(username, amount) {


totalMsg += 1;
let block_to_append = `
<div class="alert-message">

<div class="header">
<div class="heart-bubble">
<svg width="20" height="19.88" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 19.88">
<defs>
<style>
.cls-1 {
fill-rule: evenodd;
}

.cls-1, .cls-2 {
fill: #ef4c76;
stroke-width: 0px;
}
</style>
</defs>
<rect class="cls-2" y="4.88" width="20" height="3.75"/>
<path class="cls-1" d="M15.82,12.1c.39.36.39.93,0,1.29-.39.36-
1.03.36-1.42,0l-3.79-3.43h-1.24l-3.79,3.43c-.39.36-1.03.36-
1.43,0-.39-.35-.39-.93,0-1.29l2.37-2.14-5.26-.08v10h17.5v-10l-5.3.08,2.37,2.14Z"/>
<path class="cls-1" d="M14.91,0c-1.45,0-3.28,1.05-4.95,2.82-1.67-
1.77-3.5-2.82-4.94-2.82-.74,0-1.37.28-1.83.8-.75.85-.85,2.53-.37,4.13h2.45s-.74-
1.26-.54-2.36c.02-.02.1-.06.28-.06.72,0,2.38.85,3.82,2.42h2.31c1.45-1.58,3.02-
2.42,3.77-2.42.22,0,.28.06.28.06.15,1.42-.54,2.36-.54,2.36h2.55c.48-1.6.29-
3.28-.46-4.13-.45-.52-1.09-.8-1.82-.8Z"/>
</svg>
</div>

<div class="username">
<p class="alert-username">${username}</p>
</div>
</div>

<p>Gifted ${amount} subs to the community!</p>

</div>
`

appendAlert(block_to_append)
}

function alertGift(sender, target) {


totalMsg += 1;
let block_to_append = `
<div class="alert-message">

<div class="header">
<div class="heart-bubble">
<svg width="20" height="19.88" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 19.88">
<defs>
<style>
.cls-1 {
fill-rule: evenodd;
}

.cls-1, .cls-2 {
fill: #ef4c76;
stroke-width: 0px;
}
</style>
</defs>
<rect class="cls-2" y="4.88" width="20" height="3.75"/>
<path class="cls-1" d="M15.82,12.1c.39.36.39.93,0,1.29-.39.36-
1.03.36-1.42,0l-3.79-3.43h-1.24l-3.79,3.43c-.39.36-1.03.36-
1.43,0-.39-.35-.39-.93,0-1.29l2.37-2.14-5.26-.08v10h17.5v-10l-5.3.08,2.37,2.14Z"/>
<path class="cls-1" d="M14.91,0c-1.45,0-3.28,1.05-4.95,2.82-1.67-
1.77-3.5-2.82-4.94-2.82-.74,0-1.37.28-1.83.8-.75.85-.85,2.53-.37,4.13h2.45s-.74-
1.26-.54-2.36c.02-.02.1-.06.28-.06.72,0,2.38.85,3.82,2.42h2.31c1.45-1.58,3.02-
2.42,3.77-2.42.22,0,.28.06.28.06.15,1.42-.54,2.36-.54,2.36h2.55c.48-1.6.29-
3.28-.46-4.13-.45-.52-1.09-.8-1.82-.8Z"/>
</svg>
</div>

<div class="username">
<p class="alert-username">${sender}</p>
</div>
</div>

<p>Gifted ${target} a sub!</p>

</div>
`

appendAlert(block_to_append)
}

function alertCheer(username, amount) {


totalMsg += 1;
let block_to_append = `
<div class="alert-message">

<div class="header">
<div class="heart-bubble">
<svg width="15.82" height="23" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 15.82 23">
<defs>
<style>
.cls-1 {
fill: #ef4c76;
stroke-width: 0px;
}
</style>
</defs>
<polygon class="cls-1" points="3.35 1.19 0 17.59 8.64 18.51 3.35
1.19"/>
<polygon class="cls-1" points=".42 18.23 10.02 23 8.83 19.12 .42
18.23"/>
<polygon class="cls-1" points="10.49 22.54 15.52 14.76 9.43 19.07
10.49 22.54"/>
<polygon class="cls-1" points="15.82 13.83 3.61 0 9.25 18.48 15.82
13.83"/>
</svg>
</div>

<div class="username">
<p class="alert-username">${username}</p>
</div>
</div>

<p>Thank you for ${amount} bits!</p>

</div>
`

appendAlert(block_to_append)
}
function alertTip(username, amount) {
totalMsg += 1;
let block_to_append = `
<div class="alert-message">

<div class="header">
<div class="heart-bubble">
<svg width="18" height="21" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 18 21">
<defs>
<style>
.cls-1 {
fill: #ef4c76;
stroke-width: 0px;
}
</style>
</defs>
<path class="cls-1" d="M17.81,11.82c-.18-.64-.46-1.19-.82-
1.63-.37-.44-.79-.81-1.26-1.11-.47-.29-.98-.52-1.52-.68-.54-.16-1.07-.28-1.59-.36s-
1.01-.13-1.47-.14c-.46-.02-.86-.03-
1.18-.03-.03-.16-.07-.36-.11-.61-.05-.24-.11-.55-.18-.93.35.03.74.05,1.18.06.44.02.
88.03,1.33.05.45.01.87.02,1.27.03.4,0,.71.01.95.03.21-.74.31-1.41.31-
2.02,0-.61-.07-1.29-.2-2.03-.35-.24-.79-.43-1.32-.56s-1.09-.21-1.68-.25c-.58-.04-
1.16-.03-1.73.01-.57.04-1.05.12-
1.44.23-.07-.24-.14-.54-.21-.9-.07-.36-.19-.68-.37-.97-.3,0-.61.03-.92.11-.32.08-.5
8.19-.77.34-.05.32-.03.67.05,1.05s.13.68.15.9c-.45.1-.95.23-1.47.4-.53.17-1.05.38-
1.57.63-.52.25-1,.55-1.45.88-.45.34-.82.72-
1.13,1.16-.3.44-.5.93-.6,1.49-.1.55-.05,1.17.14,1.86.19.67.47,1.22.85,1.64.38.42.8.
74,1.29.97.48.23,1,.39,1.54.48.55.09,1.08.15,1.61.18.53.02,1.03.03,1.5.02.47,0,.87.
02,1.2.08.07.34.14.67.22.99.08.32.16.65.22.99-.76-.05-1.4-.08-
1.91-.09-.52,0-.97-.02-1.37-.03-.4-.01-.78-.03-1.14-.04-.36-.01-.77-.05-
1.22-.11-.2.27-.35.6-.44.98-.09.38-.15.78-.16,1.2-.01.42,0,.84.05,1.26.05.42.11.8.2
,1.15.48.28,1.04.48,1.67.59.63.11,1.27.17,1.91.18.65.01,1.27-.01,1.86-.07.59-.06,1.
08-.12,1.46-.18l.17-.05c.02.07.04.19.08.35.03.16.06.34.1.53.04.19.08.37.12.54.04.17
.07.28.09.36l.07.26c.28.06.6.04.97-.07.36-.11.68-.24.93-.39.11-.26.18-.56.2-.9.02-.
34,0-.69-.08-
1.05l.56-.16c.36-.1.76-.25,1.21-.43.44-.18.89-.41,1.33-.68.45-.27.86-.59,1.24-.95.3
9-.36.71-.77.96-1.23.25-.45.42-.96.49-1.5.08-.54.03-1.14-.16-
1.78ZM6.62,7.84c-.24-.02-.47-.04-.69-.08-.22-.03-.41-.08-.59-.14-.17-.06-.27-.14-.3
-.24-.03-.1.04-.2.21-.29.17-.09.36-.18.59-.25.23-.07.45-.13.67-.18.22-.04.37-.08.46
-.1.03.16.05.29.07.39.02.09.03.18.04.26,0,.08.02.16.04.25.02.1.04.23.08.41-.16,0-.3
5-.01-.59-.03ZM13.21,13.12c-.08.12-.19.23-.33.32-.14.09-.28.17-.42.23-.14.06-.26.1-
.35.13-.13.04-.26.07-.4.1-.14.03-.27.06-.41.1l-.37-
1.72.3-.09c.16-.03.35-.05.56-.05.21,0,.42,0,.63.04.21.03.39.08.55.17s.26.22.31.39c.
04.13.01.25-.07.38Z"/>
</svg>
</div>

<div class="username">
<p class="alert-username">${username}</p>
</div>
</div>

<p>Thank you for ${events.tip.currency}${amount}</p>

</div>
`
appendAlert(block_to_append)
}

// helper functions to emotes


function attachEmotes(message) {
let text = html_encode(message.text);
let data = message.emotes;
if (data[0]) {
hasEmotes = "has-emotes"
} else {
hasEmotes = ""
}
let isEmoteOnly = isEmote(message)
if (typeof message.attachment !== "undefined") {
if (typeof message.attachment.media !== "undefined") {
if (typeof message.attachment.media.image !== "undefined") {
text = `${message.text}<img src="$
{message.attachment.media.image.src}">`;
}
}
}
return text
.replace(
/([^\s]*)/gi,
function (m, key) {
let result = data.filter(emote => {
return html_encode(emote.name) === key
});
if (typeof result[0] !== "undefined") {
let url;
if (isEmoteOnly) {
url = result[0]['urls'][4];
} else {
url = result[0]['urls'][1];
}
if (provider === "twitch") {
return `<img class="emote" src="${url}"/>`;
} else {
if (typeof result[0].coords === "undefined") {
result[0].coords = {
x: 0,
y: 0
};
}
let x = parseInt(result[0].coords.x);
let y = parseInt(result[0].coords.y);

let width = "28px";


let height = "auto";

if (provider === "mixer") {


if (result[0].coords.width) {
width = `${result[0].coords.width}px`;
}
if (result[0].coords.height) {
height = `${result[0].coords.height}px`;
}
}
return `<div class="emote" style="width: ${width}; height:$
{height}; display: inline-block; background-image: url(${url}); background-
position: -${x}px -${y}px;"></div>`;
}
} else return key;

}
);
}

function html_encode(e) {
return e.replace(/[<>"^]/g, function (e) {
return "&#" + e.charCodeAt(0) + ";";
});
}

function check_role(data) {
let role
let badges = data.tags.badges;
if (badges.includes('broadcaster')) {
role = 'broadcaster'
} else if (badges.includes('moderator')) {
role = 'moderator'
} else if (badges.includes('vip')) {
role = 'vip'
} else if (badges.includes('artist-badge')) {
role = 'artist'
} else if (badges.includes('subscriber')) {
role = 'subscriber'
}

let isSub = false


if (badges.includes('subscriber')) {
isSub = true
}

return [role, isSub]


}

function removeRow() {
if (!$(removeSelector).length) {
return;
}

$(removeSelector).stop(true)

$(removeSelector).animate({
opacity: 0
}, 'fast', function () {
$(removeSelector).remove();
});
}

function isEmote(data) {
let msg = data.text;
msg = msg.replace(/\s\s+/g, ' ');
let msg_split = msg.split(" ");

let emotes = data.emotes;


let emoteOnly = true;
const emote_names = emotes.map((e) => e.name);

for (let i = 0; i < msg_split.length; i++) {


if (!emote_names.includes(msg_split[i])) {
emoteOnly = false
}
}
return emoteOnly;
}

function getRandomInt(max) {
return Math.floor(Math.random() * max);
}

You might also like