From 425535d9b36b32a49b0199794f919bc52b2babe9 Mon Sep 17 00:00:00 2001 From: Darius Rapalis Date: Wed, 28 Jun 2023 23:53:11 +0300 Subject: [PATCH] Pushing original code --- css.txt | 532 +++++++++++++++++++++++ data.txt | 1 + fields.txt | 135 ++++++ html.txt | 2 + js.txt | 1185 ++++++++++++++++++++++++++++++++++++++++++++++++++++ widget.ini | 14 + 6 files changed, 1869 insertions(+) create mode 100644 css.txt create mode 100644 data.txt create mode 100644 fields.txt create mode 100644 html.txt create mode 100644 js.txt create mode 100644 widget.ini diff --git a/css.txt b/css.txt new file mode 100644 index 0000000..c2786e6 --- /dev/null +++ b/css.txt @@ -0,0 +1,532 @@ +/* Copyright (C) 2023 Max @sigmacw_ and Matt @mattsquare_. + * + * You may not distribute this code without obtaining explicit permission + * from Max @sigmacw_ and Matt @mattsquare_. + * + * All rights reserved. + */ + +* { + font-family: 'Quicksand'; + letter-spacing: 2px; + font-size: 18px; + font-weight: 800; +} + +p { + margin: 0; +} + +.badges { + display: flex; +} + +.badges img { + width: 16px; + margin-right: 5px; +} + +.pronouns { + text-transform: uppercase; +} + +.emote { + display: inline-flex; + justify-content: center; + align-items: center; + vertical-align: middle; + height: 28px; +} + +.emote-only img { + height: 60px; + width: auto; +} + +.white-border { + background: #FFDEE6 !important; + stroke: #FFDEE6 !important; +} + +.white-fill { + fill: #FFDEE6 !important; +} + +.main-container { + display: flex; + height: 95%; + width: 90%; + flex-direction: column; + justify-content: flex-end; + position: absolute; + bottom: 40px; +} + +.message-wrap { + transform: scaleY(0); + transform-origin: bottom left; + animation: scaleIn 0.5s ease 0.2s forwards; + width: 100%; +} + +/* MESSAGE BOX STYLES */ + +.message-row { + display: flex; + margin-bottom: 32px; + position: relative; +} + +.regular { + position: absolute; + top: 18px; + z-index: 0; +} + +.message-box { + display: flex; + width: 100%; + padding: 16px 32px; + background: linear-gradient(to bottom, #491824, #67192C); + color: #FFAEC2; + border-radius: 16px; + border: solid 4px #FF4976; + box-sizing: border-box; + border-top: none; + border-left: none; + border-bottom: none; + justify-content: space-between; +} + +.message-box .heart { + align-self: center; + margin-left: 16px; +} + +.message-box__top-right { + display: flex; + align-items: center; + justify-content: flex-end; + flex-direction: row; + width: 32px; + position: absolute; + top: 33px; + right: 0; + z-index: 3; +} + +.message-box__top-left{ + display: flex; + align-items: center; + justify-content: flex-start; + flex-direction: row; + width: 32px; + position: absolute; + top: -1px; + left: 0; + z-index: 3; +} + +.message-box__bottom-left { + display: flex; + align-items: center; + justify-content: flex-start; + flex-direction: row; + width: 32px; + position: absolute; + bottom: 0; + left: 0; + z-index: 3; +} + +.message-box__bottom-right { + display: flex; + align-items: center; + justify-content: flex-end; + flex-direction: row; + width: 32px; + position: absolute; + bottom: 0; + right: 0; + z-index: 3; +} + +.bottom-border { + display: flex; + width: 100%; + align-items: center; + position: absolute; + left: 0px; + bottom: -6px; + height: fit-content; +} + +.bottom-border svg#corner { + min-width: 20px; + position: absolute; + bottom: 6px; + left: -1px; +} + +.bottom-border svg#heart { + margin: 0px 16px 0 36px; + min-width: 18px; +} + +.bottom-border .separator-1 { + height: 4px; + background: #FF4976; + border-radius: 10px; + width: 100%; +} + +.bottom-border .separator-2 { + height: 4px; + background: #FF4976; + border-radius: 10px; + width: 100%; + margin-right: 16px; +} + +/* USER BOX STYLES */ + +.user-box { + display: flex; + position: relative; + top: 4px; + left: -2px; +} + +.icon-role { + min-width: 35px; + min-height: 35px; + display: flex; + background: #FFDEE6; + border-radius: 64px; + justify-content: center; + align-items: center; + margin-right: 8px; + position: relative; + z-index: 2; +} + +.username { + padding: 6px 32px; + background: #FFDEE6; + border-radius: 64px; + display: flex; + color: #FF4976; + align-items: center; + width: fit-content; + max-width: 40%; +} + +.username .username-text { + overflow: hidden; + text-overflow: ellipsis; +} + +.username .divider { + margin: 0 10px; + width: 4px; + height: 4px; + min-width: 4px; + background: #FF4976; + border-radius: 64px; +} + +.username .pronouns { + font-size: 12px; +} + +.top-border { + display: flex; + width: 100%; + margin-right: 14px; + margin-left: 0; + align-items: center; + position: relative; + top: 13.5px; +} + +.top-border svg { + margin: 0px 16px; + min-width: 18px; +} + +.top-border .separator-1 { + height: 4px; + background: #FF4976; + border-radius: 10px; + width: 100%; +} + +.top-border .separator-2 { + height: 4px; + background: #FF4976; + border-radius: 10px; + width: 100%; +} + +/* ALERT STYLING */ + +.alert-wrap { + background: linear-gradient(to top, #FF5F84, #FF4976); + border-radius: 16px; + overflow: hidden; + position: relative; + display: flex; + padding: 24px 32px; + justify-content: space-between; + align-items: center; + border: solid 4px #FFAEC2; + transform: scaleY(0); + transform-origin: bottom left; + animation: scaleIn 0.5s ease 0.2s forwards; + width: 100%; + border-top: none; + border-bottom: none; + border-left: none; +} + +.alert-wrap .background { + position: absolute; + left: auto; + right: auto; +} + +.alert-borders { + transform: scaleY(0); + transform-origin: bottom left; + animation: scaleIn 0.5s ease 0.2s forwards; + width: 100%; + height: 100%; + position: absolute; + z-index: 2; +} + +.alert-message { + display: flex; + flex-direction: column; +} + +.alert-message .header { + display: flex; + align-items: center; + margin-bottom: 8px; + align-self: center; +} + +.alert-message .header .heart-bubble { + width: 35px; + height: 35px; + display: flex; + align-items: center; + justify-content: center; + background: #FFDEE6; + border-radius: 64px; +} + +.alert-message .header .chevron { + margin: 0 16px; +} + +.alert-message > p { + color: white; + text-align: center; +} + +.alert-username { + overflow: hidden; + text-overflow: ellipsis; +} + +.alert-wrap__top-right { + display: flex; + align-items: center; + justify-content: flex-end; + flex-direction: row; + width: 32px; + position: absolute; + top: -1px; + right: 0; + z-index: 3; +} + +.alert-wrap__top-left{ + display: flex; + align-items: center; + justify-content: flex-start; + flex-direction: row; + width: 32px; + position: absolute; + top: -1px; + left: 0; + z-index: 3; +} + +.alert-wrap__bottom-left { + display: flex; + align-items: center; + justify-content: flex-start; + flex-direction: row; + width: 32px; + position: absolute; + bottom: 0; + left: 0; + z-index: 3; +} + +.alert-wrap__bottom-right { + display: flex; + align-items: center; + justify-content: flex-end; + flex-direction: row; + width: 32px; + position: absolute; + bottom: 0; + right: 0; + z-index: 3; +} + +.alert-top-border { + display: flex; + width: 100%; + margin-right: 16px; + align-items: center; + position: absolute; + top: -7px; + z-index: 3; +} + +.alert-top-border svg { + margin: 0px 16px; + min-width: 18px; +} + +.alert-top-border .separator-1 { + height: 4px; + background: #FFAEC2; + border-radius: 10px; + width: 25%; + margin-left: 16px; +} + +.alert-top-border .separator-2 { + height: 4px; + background: #FFAEC2; + border-radius: 10px; + width: 100%; +} + +.alert-top-border .separator-3 { + height: 4px; + background: #FFAEC2; + border-radius: 10px; + width: 25%; + margin-right: 16px; +} + +.alert-bottom-border { + display: flex; + width: 100%; + align-items: center; + position: absolute; + left: 0px; + bottom: -6px; + height: fit-content; + z-index: 3; +} + +.alert-bottom-border svg#heart { + margin: 0px 16px 0 16px; + min-width: 18px; +} + +.alert-bottom-border .separator-1 { + height: 4px; + background: #FFAEC2; + border-radius: 10px; + width: 100%; + margin-left: 16px; +} + +.alert-bottom-border .separator-2 { + height: 4px; + background: #FFAEC2; + border-radius: 10px; + width: 50%; + margin-right: 16px; +} + +.alert-left-border { + display: flex; + flex-direction: column; + align-items: center; + position: absolute; + left: -7px; + bottom: 0px; + height: 100%; + z-index: 3; +} + +.alert-left-border svg#heart { + margin: 16px 0; + min-height: 18px; +} + +.alert-left-border .separator-1 { + height: 100%; + background: #FFAEC2; + border-radius: 10px; + width: 4px; + margin-top: 16px; +} + +.alert-left-border .separator-2 { + height: 50%; + background: #FFAEC2; + border-radius: 10px; + width: 4px; + margin-bottom: 16px; +} + +/* ANIMATION DECLARATIONS */ + +@keyframes scaleIn { + 0% { + transform: scale(0); + } + + 60% { + transform: scale(110%) + } + + 100% { + transform: scale(100%) + } +} + +@keyframes swing { + + 0%, + 100% { + transform: rotate(3deg); + } + + 50% { + transform: rotate(-3deg); + } +} + +@keyframes rollIn { + 0% { + opacity: 0; + transform: translateY(40px); + } + + 100% { + opacity: 1; + transform: translateY(0); + } +} \ No newline at end of file diff --git a/data.txt b/data.txt new file mode 100644 index 0000000..d1dfa08 --- /dev/null +++ b/data.txt @@ -0,0 +1 @@ +{"eventsLimit":5,"includeFollowers":"yes","includeRedemptions":"yes","includeHosts":"yes","minHost":1,"includeRaids":"yes","minRaid":1,"includeSubs":"yes","includeTips":"yes","minTip":1,"includeCheers":"yes","minCheer":1,"direction":"top","textOrder":"nameFirst","fadeoutTime":999,"fontColor":"rgb(255, 255, 255)","theme":"texture","backgroundOpacity":50,"backgroundColor":"rgba(36, 6, 73, 0.15)","iconColor":"rgb(255, 255, 255, 255)","locale":"en-US","displayPronouns":true,"messagesLimit":15,"hideAfter":999,"hideCommands":"yes","ignoredUsers":"StreamElements","ignoredCommands":"!,?","tipEnabled":true,"tipMin":0,"tipCurrency":"$","subEnabled":true,"resubEnabled":true,"giftEnabled":true,"directEnabled":true,"cheerEnabled":true,"cheerMin":0,"testMessage":"Test message","testMessage1":"Test message 2","testMessage2":"Test message 3","testMessageName":"mattsquare_","testMessageText":"Happy Valentine's Day!","testMessage3":"Test message 4"} \ No newline at end of file diff --git a/fields.txt b/fields.txt new file mode 100644 index 0000000..5aa89ff --- /dev/null +++ b/fields.txt @@ -0,0 +1,135 @@ +{ + "displayPronouns": { + "label": "Show Pronouns", + "group": "Display Settings", + "type": "checkbox", + "value": false + }, + "messagesLimit": { + "type": "number", + "label": "Message Limit", + "value": 15, + "group": "Display Settings" + }, + "hideAfter": { + "type": "number", + "label": "Hide after seconds (999 to disable)", + "value": 999, + "group": "Display Settings" + }, + "hideCommands": { + "label": "Hide messages with ! (commands)", + "type": "dropdown", + "value": "yes", + "options": { + "yes": "Yes", + "no": "No" + }, + "group": "Display Settings" + }, + "ignoredUsers": { + "label": "Ignored users (comma separated)", + "type": "text", + "value": "StreamElements", + "group": "Display Settings" + }, + "ignoredCommands": { + "label": "Ignored commands (comma separated)", + "type": "text", + "value": "!,?", + "group": "Display Settings" + }, + "tipEnabled": { + "type": "checkbox", + "label": "Display tips in chat", + "value": true, + "group": "Tips" + }, + "tipMin": { + "type": "number", + "label": "Minimum tip", + "value": 0, + "group": "Tips" + }, + "tipCurrency": { + "type": "text", + "label": "Tip currency", + "value": "$", + "group": "Tips" + }, + "subEnabled": { + "type": "checkbox", + "label": "Display subs in chat", + "value": true, + "group": "Subs" + }, + "resubEnabled": { + "type": "checkbox", + "label": "Display resubs in chat", + "value": true, + "group": "Subs" + }, + "giftEnabled": { + "type": "checkbox", + "label": "Display gift subs in chat", + "value": true, + "group": "Subs" + }, + "directEnabled": { + "type": "checkbox", + "label": "Display direct gifts in chat", + "value": true, + "group": "Subs" + }, + "cheerEnabled": { + "type": "checkbox", + "label": "Display cheers in chat", + "value": true, + "group": "Cheers" + }, + "cheerMin": { + "type": "number", + "label": "Minimum cheers", + "value": 0, + "group": "Cheers" + }, + + "testMessage": { + "type": "button", + "label": "Test broadcaster message", + "value": "Test message", + "group": "Debug" + }, + "testMessage1": { + "type": "button", + "label": "Test moderator message", + "value": "Test message 2", + "group": "Debug" + }, + "testMessage2": { + "type": "button", + "label": "Test subscriber message", + "value": "Test message 3", + "group": "Debug" + }, + "testMessageName": { + "label": "Username", + "type": "text", + "value": "Test", + "group": "Debug" + }, + + "testMessageText": { + "label": "Message content", + "type": "text", + "value": "Test", + "group": "Debug" + }, + + "testMessage3": { + "type": "button", + "label": "Test regular message", + "value": "Test message 4", + "group": "Debug" + } +} \ No newline at end of file diff --git a/html.txt b/html.txt new file mode 100644 index 0000000..2adb35c --- /dev/null +++ b/html.txt @@ -0,0 +1,2 @@ + +
\ No newline at end of file diff --git a/js.txt b/js.txt new file mode 100644 index 0000000..6585cc0 --- /dev/null +++ b/js.txt @@ -0,0 +1,1185 @@ +/* Copyright (C) 2023 Max @sigmacw_ and Matt @mattsquare_. + * + * You may not distribute this code without obtaining explicit permission + * from Max @sigmacw_ and Matt @mattsquare_. + * + * All rights reserved. + */ + +let ver = "1.0" + +// Defining useful 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 = true +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; + displayPronouns = fieldData.displayPronouns; + + 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 it out - only 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 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 alert are here too! Chat can send you their love-letters.", + isAction: !1, + emotes: [], + msgId: "" + }, + renderedText: 'Test message. ' + } + } + }); + + 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: "To celebrate, a Free to Use, Valentine's themed, hearty chat widget.", + isAction: !1, + emotes: [], + msgId: "" + }, + renderedText: 'Test message. ' + } + } + }); + + 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: "Test message. Kappa", + isAction: !1, + emotes: [], + msgId: "" + }, + renderedText: 'Test message. ' + } + } + }); + test_reg.detail.event.data.text = fieldData.testMessageText; + + // Grabbing the service used for chatbox (Twitch, YouTube, Mixer) + 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) + ")" + + // Setting up the list of users whose messages will be ignored + ignoredUsers = fieldData.ignoredUsers.toLowerCase() + .replace(" ", "").split(","); + commands = fieldData.ignoredCommands.toLowerCase() + .replace(" ", "").split(","); +}); + +// Listen 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 + } + } + + // Check for events that correspond to 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; + } + + // Check if the event is a 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 += ` `; + } + } + + 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 "aeaer": + pn = "ae/aer"; + break; + case "eem": + pn = "e/em"; + break; + case "faefaer": + pn = "fae/faer"; + break; + case "hehim": + pn = "he/him"; + break; + case "heshe": + pn = "he/she"; + break; + case "hethem": + pn = "he/they"; + break; + case "itits": + pn = "it/its"; + break; + case "perper": + pn = "per/per"; + break; + case "sheher": + pn = "she/her"; + break; + case "shethem": + pn = "she/they"; + break; + case "theythem": + pn = "they/them"; + break; + case "vever": + pn = "ve/ver"; + break; + case "xexem": + pn = "xe/xem"; + break; + case "ziehir": + pn = "zie/hir"; + break; + default: + break; + } + return pn; + } + + printAddress().then(pn => addMessage(name, null, role, badges, message, emoteOnly, data.isAction, data.userId, data.msgId, pn)); + } +}); + +// A function that renders the message in DOM +function addMessage(name, reply, badge, badges, message, isEmote, isAction, userId, msgId, pn) { + // Advance the counter of total messages by 1 to keep track + // of how many there are at any point + totalMsg += 1; + // Define a CSS class for a certain action + 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], `

${mentions[i]}

`) + } + } + + let roleIcon, broadcasterClass; + + broadcasterClass = ''; + let broadcasterBorder = ''; + let broadcasterFill = ''; + + role = badge[0] + switch (role) { + case "broadcaster": + roleIcon = ` +
+ + + +
+ ` + broadcasterClass = 'white-border'; + broadcasterFill = 'white-fill'; + broadcasterBorder = 'style="border-right: solid 4px #FFDEE6 !important;"' + break + case "moderator": + roleIcon = ` +
+ + + +
+ ` + break + case "vip": + roleIcon = ` +
+ + + +
+ ` + break + case "artist": + roleIcon = `` + break + case "subscriber": + roleIcon = ` +
+ + + +
+ ` + break; + default: + roleIcon = `` + break + } + + name_ = name.concat(""); + + let fullMsg = ` +
+ +
+ +
+ +
+ + + +
+ + ${roleIcon} + +
+ ${name} + + ${pn} +
+ +
+ + + + +
+ + + + + +
+
+ +
+ +
+ +
+ +
+ + + +
+ +
+ + + +
+ +
+

${message}

+
+ +
+ + + +
+ +
+ + + + + + + + +
+
+ +
+ +
+ +
+ ` + + 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 = ` +
+ +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+
+ + + + + +
+ + + + + +
+
+ +
+
+ + + + + +
+
+ +
+
+ + + + + +
+
+ +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ + ${block} + +
+ + + +
+ +
+ +
+ ` + + 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 = ` +
+ +
+
+ + + +
+
+ + + +
+ +
+

${username}

+
+
+ +

Thank you for the sub!

+ +
+ ` + + appendAlert(block_to_append) +} + +function alertReSub(username, amount) { + totalMsg += 1; + let block_to_append = ` +
+ +
+
+ + + +
+
+ + + +
+ +
+

${username}

+
+
+ +

Resubscribed for ${amount} months!

+ +
+ ` + + appendAlert(block_to_append) +} + +function alertBulkGift(username, amount) { + totalMsg += 1; + let block_to_append = ` +
+ +
+
+ + + +
+
+ + + +
+ +
+

${username}

+
+
+ +

Gifted ${amount} subs to the community!

+ +
+ ` + + appendAlert(block_to_append) +} + +function alertGift(sender, target) { + totalMsg += 1; + let block_to_append = ` +
+ +
+
+ + + +
+
+ + + +
+ +
+

${sender}

+
+
+ +

Gifted ${target} a sub!

+ +
+ ` + + appendAlert(block_to_append) +} + +function alertCheer(username, amount) { + totalMsg += 1; + let block_to_append = ` +
+ +
+
+ + + +
+
+ + + +
+ +
+

${username}

+
+
+ +

Thank you for ${amount} bits!

+ +
+ ` + + appendAlert(block_to_append) +} + +function alertTip(username, amount) { + totalMsg += 1; + let block_to_append = ` +
+ +
+
+ + + +
+
+ + + +
+ +
+

${username}

+
+
+ +

Thank you for ${events.tip.currency}${amount}

+ +
+ ` + + appendAlert(block_to_append) +} + +// A set of helper functions to handle 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}`; + } + } + } + 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 ``; + } 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 `
`; + } + } 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); +} \ No newline at end of file diff --git a/widget.ini b/widget.ini new file mode 100644 index 0000000..120d944 --- /dev/null +++ b/widget.ini @@ -0,0 +1,14 @@ +[HTML] +path = "html.txt" + +[CSS] +path = "css.txt" + +[JS] +path = "js.txt" + +[FIELDS] +path = "fields.txt" + +[DATA] +path = "data.txt"