diff --git a/.utilities/settings-page-builder/script.js b/.utilities/settings-page-builder/script.js
index 0b5cfa3..3984ea4 100644
--- a/.utilities/settings-page-builder/script.js
+++ b/.utilities/settings-page-builder/script.js
@@ -1,14 +1,52 @@
+// Search paramaters
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
-
const settingsJson = urlParams.get("settingsJson") || "";
+// Connect to Streamer.bot and get list of actions
+const sbServerAddress = '127.0.0.1';
+const sbServerPort = '8080';
+const client = new StreamerbotClient({
+ host: sbServerAddress,
+ port: sbServerPort,
+
+ onConnect: (data) => {
+ console.log(`Streamer.bot successfully connected to ${sbServerAddress}:${sbServerPort}`)
+ console.debug(data);
+
+ // Get list of actions
+ GetSBActions();
+ },
+
+ onDisconnect: () => {
+ console.error(`Streamer.bot disconnected from ${sbServerAddress}:${sbServerPort}`)
+ }
+});
+
+async function GetSBActions() {
+ const response = await client.getActions();
+
+ console.debug(response);
+
+ const datalistElement = document.createElement('datalist');
+ datalistElement.id = 'streamer-bot-actions';
+
+ for (const action of response.actions)
+ {
+ const option = document.createElement('option');
+ option.value = action.name;
+ datalistElement.appendChild(option);
+ }
+
+ document.body.appendChild(datalistElement);
+}
+
document.addEventListener('DOMContentLoaded', () => {
+
const settingsContent = document.getElementById('settings-content');
const saveButton = document.getElementById('save-settings');
fetch(settingsJson)
- //fetch('../../multichat-overlay/settings/settings.json')
.then(response => response.json())
.then(data => {
const groupedSettings = {};
@@ -33,12 +71,15 @@ document.addEventListener('DOMContentLoaded', () => {
groupedSettings[groupName].forEach(setting => {
const settingItem = document.createElement('div');
settingItem.classList.add('setting-item');
+ settingItem.id = `item-${setting.id}`;
const labelDescriptionDiv = document.createElement('div');
- const label = document.createElement('label');
- label.textContent = setting.label;
- labelDescriptionDiv.appendChild(label);
+ if (setting.label) {
+ const label = document.createElement('label');
+ label.textContent = setting.label;
+ labelDescriptionDiv.appendChild(label);
+ }
if (setting.description) {
const description = document.createElement('p');
@@ -74,6 +115,7 @@ document.addEventListener('DOMContentLoaded', () => {
// Add event listener to the switchDiv
labelDiv.addEventListener('click', () => {
checkBoxElement.checked = !checkBoxElement.checked;
+ UpdateSettingItemVisibility();
});
inputElement = labelDiv;
break;
@@ -106,6 +148,37 @@ document.addEventListener('DOMContentLoaded', () => {
inputElement.max = setting.max;
inputElement.step = setting.step;
break;
+ case 'sb-actions':
+ inputElement = document.createElement('input');
+ inputElement.type = 'text';
+ inputElement.placeholder = 'Type to search...';
+ inputElement.id = setting.id; //Added setting ID
+ inputElement.value = setting.defaultValue;
+ inputElement.setAttribute('list', 'streamer-bot-actions');
+ inputElement.autocomplete = 'off';
+ break;
+ case 'button':
+ inputElement = document.createElement('button');
+ inputElement.id = setting.id; //Added setting ID
+ inputElement.textContent = setting.label;
+
+ inputElement.addEventListener('click', () => {
+ window.parent.callFunction(setting.callFunction);
+
+ const defaultBackgroundColor = "#2e2e2e";
+ const defaultTextColor = "white";
+
+ inputElement.style.transitionDuration = '0s'
+ inputElement.style.backgroundColor = "#2196f3"
+ inputElement.style.color = "#ffffff";
+
+ setTimeout(() => {
+ inputElement.style.transitionDuration = '0.2s'
+ inputElement.style.backgroundColor = defaultBackgroundColor;
+ inputElement.style.color = defaultTextColor;
+ }, 100);
+ });
+ break;
default:
inputElement = document.createElement('input');
inputElement.type = 'text';
@@ -114,30 +187,53 @@ document.addEventListener('DOMContentLoaded', () => {
}
inputElement.addEventListener('input', function (event) {
- SendDateToParent(data);
+ SendDataToParent(data);
});
settingItemContent.appendChild(inputElement);
- settingItem.appendChild(labelDescriptionDiv);
- settingItem.appendChild(settingItemContent);
+ if (setting.type == 'button')
+ {
+ settingItem.style.display = 'block'
+ settingItem.appendChild(settingItemContent);
+ }
+ else
+ {
+ settingItem.appendChild(labelDescriptionDiv);
+ settingItem.appendChild(settingItemContent);
+ }
+
groupDiv.appendChild(settingItem);
});
settingsContent.appendChild(groupDiv);
}
+ function UpdateSettingItemVisibility() {
+ data.settings.forEach(setting => {
+ if (setting.hideIf)
+ {
+ if (!document.getElementById(setting.hideIf).checked)
+ document.getElementById(`item-${setting.id}`).style.display = 'none'
+ else
+ document.getElementById(`item-${setting.id}`).style.display = 'flex'
+ }
+ });
+ }
+
+ UpdateSettingItemVisibility();
+
// saveButton.addEventListener('click', () => {
- // SendDateToParent(data);
+ // SendDataToParent(data);
// });
- SendDateToParent(data);
+ SendDataToParent(data);
})
.catch(error => console.error('Error loading settings:', error));
});
// In the iframe's JavaScript:
-function SendDateToParent(data) {
+function SendDataToParent(data) {
const settings = {};
data.settings.forEach(setting => {
let inputElement = document.getElementById(setting.id);
@@ -183,12 +279,6 @@ saveButton.addEventListener('click', () => {
}, 3000);
});
-widgetURLBox.addEventListener('click', () => {
- let loadSettingsBox = document.getElementById('mommy-milkers');
- loadSettingsBox.style.visibility = 'visible';
- loadSettingsBox.style.opacity = 1;
-});
-
function CloseSettings() {
let loadSettingsBox = document.getElementById('mommy-milkers');
loadSettingsBox.style.visibility = 'hidden';
@@ -198,12 +288,11 @@ function CloseSettings() {
function LoadSettings() {
let loadURLBox = document.getElementById('load-url');
const url = new URL(loadURLBox.value);
-
+
url.searchParams.forEach((value, key) => {
const inputElement = document.getElementById(key);
- if (inputElement != null)
- {
+ if (inputElement != null) {
if (inputElement.type == 'checkbox')
inputElement.checked = value.toLocaleLowerCase() == 'true';
else
@@ -230,8 +319,15 @@ function GetWidgetURL() {
}
return result;
+ //return 'D:/Projects/GitHub Projects/nutty.gg/multistream-alerts/index.html'
}
function OpenMembershipPage() {
- window.open("https://nutty.gg/supporters/sign_in", '_blank').focus();
+ window.open("https://nutty.gg/supporters/sign_in", '_blank').focus();
+}
+
+function OpenLoadSettingsPopup() {
+ let loadSettingsBox = document.getElementById('mommy-milkers');
+ loadSettingsBox.style.visibility = 'visible';
+ loadSettingsBox.style.opacity = 1;
}
\ No newline at end of file
diff --git a/.utilities/settings-page-builder/style.css b/.utilities/settings-page-builder/style.css
index 692dc42..6a05854 100644
--- a/.utilities/settings-page-builder/style.css
+++ b/.utilities/settings-page-builder/style.css
@@ -2,10 +2,12 @@
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial, sans-serif;
font-size: 16px;
color: white;
+ --accent-color: #2196f3;
}
body {
background-color: #181818;
+ margin: 0px 20px;
}
body::-webkit-scrollbar {
@@ -63,7 +65,7 @@ body::-webkit-scrollbar-thumb:hover {
.setting-group {
margin-bottom: 20px;
/* border: 1px solid #ddd; */
- padding: 15px;
+ padding-bottom: 15px;
border-radius: 5px;
}
@@ -97,7 +99,7 @@ h2 {
font-weight: 300;
/* color: #666; */
opacity: 0.6;
- margin-bottom: 0;
+ margin: 0;
}
a {
@@ -126,6 +128,7 @@ input[type="number"] {
-moz-box-sizing: border-box;
box-sizing: border-box;
}
+
#widget-url:hover {
cursor: pointer;
}
@@ -195,11 +198,11 @@ input:focus {
}
input:checked+.slider {
- background-color: #2196F3;
+ background-color: var(--accent-color);
}
input:focus+.slider {
- box-shadow: 0 0 1px #2196F3;
+ box-shadow: 0 0 1px var(--accent-color);
}
input:checked+.slider:before {
@@ -227,7 +230,7 @@ button {
border-radius: 0.5em;
padding: 10px 20px;
width: 100%;
- transition: all 0.2s ease;
+ transition: all 0.2s ease-in-out;
}
button:hover {
@@ -270,5 +273,5 @@ button:hover {
}
#load-settings {
- background-color: #2196F3;
+ background-color: var(--accent-color);
}
\ No newline at end of file
diff --git a/multistream-alerts/index.html b/multistream-alerts/index.html
index 3e6224c..8609f93 100644
--- a/multistream-alerts/index.html
+++ b/multistream-alerts/index.html
@@ -24,7 +24,7 @@

-
+
nutty
diff --git a/multistream-alerts/script.js b/multistream-alerts/script.js
index 8d1dcbb..ff3fb7a 100644
--- a/multistream-alerts/script.js
+++ b/multistream-alerts/script.js
@@ -28,48 +28,103 @@ let alertQueue = [];
// OPTIONS //
/////////////
-const showPlatform = GetBooleanParam("showPlatform", true);
+// const showPlatform = GetBooleanParam("showPlatform", true);
+// const showAvatar = GetBooleanParam("showAvatar", true);
+// const showTimestamps = GetBooleanParam("showTimestamps", true);
+// const showBadges = GetBooleanParam("showBadges", true);
+// const showPronouns = GetBooleanParam("showPronouns", true);
+// const showUsername = GetBooleanParam("showUsername", true);
+// const showMessage = GetBooleanParam("showMessage", true);
+// const font = urlParams.get("font") || "";
+// const fontSize = urlParams.get("fontSize") || "30";
+// const lineSpacing = urlParams.get("lineSpacing") || "1.7";
+// const background = urlParams.get("background") || "#000000";
+// const opacity = urlParams.get("opacity") || "0.85";
+
+// const hideAfter = GetIntParam("hideAfter", 0);
+// const excludeCommands = GetBooleanParam("excludeCommands", true);
+// const ignoreChatters = urlParams.get("ignoreChatters") || "";
+// const scrollDirection = GetIntParam("scrollDirection", 1);
+// const inlineChat = GetBooleanParam("inlineChat", false);
+// const imageEmbedPermissionLevel = GetIntParam("imageEmbedPermissionLevel", 20);
+
+// const showTwitchMessages = GetBooleanParam("showTwitchMessages", true);
+// const showTwitchAnnouncements = GetBooleanParam("showTwitchAnnouncements", true);
+// const showTwitchSubs = GetBooleanParam("showTwitchSubs", true);
+// const showTwitchChannelPointRedemptions = GetBooleanParam("showTwitchChannelPointRedemptions", true);
+// const showTwitchRaids = GetBooleanParam("showTwitchRaids", true);
+// const showTwitchSharedChat = GetIntParam("showTwitchSharedChat", 2);
+
+// const twitchFollowTrigger = urlParams.get("twitchFollowTrigger") || "";
+
+// const showYouTubeMessages = GetBooleanParam("showYouTubeMessages", true);
+// const showYouTubeSuperChats = GetBooleanParam("showYouTubeSuperChats", true);
+// const showYouTubeSuperStickers = GetBooleanParam("showYouTubeSuperStickers", true);
+// const showYouTubeMemberships = GetBooleanParam("showYouTubeMemberships", true);
+
+// const showStreamlabsDonations = GetBooleanParam("showStreamlabsDonations", true)
+// const showStreamElementsTips = GetBooleanParam("showStreamElementsTips", true);
+// const showPatreonMemberships = GetBooleanParam("showPatreonMemberships", true);
+// const showKofiDonations = GetBooleanParam("showKofiDonations", true);
+// const showTipeeeStreamDonations = GetBooleanParam("showTipeeeStreamDonations", true);
+// const showFourthwallAlerts = GetBooleanParam("showFourthwallAlerts", true);
+
+// const animationSpeed = GetIntParam("animationSpeed", 8000);
+
+// const furryMode = GetBooleanParam("furryMode", false);
+
+// Appearance
const showAvatar = GetBooleanParam("showAvatar", true);
-const showTimestamps = GetBooleanParam("showTimestamps", true);
-const showBadges = GetBooleanParam("showBadges", true);
-const showPronouns = GetBooleanParam("showPronouns", true);
-const showUsername = GetBooleanParam("showUsername", true);
-const showMessage = GetBooleanParam("showMessage", true);
const font = urlParams.get("font") || "";
-const fontSize = urlParams.get("fontSize") || "30";
-const lineSpacing = urlParams.get("lineSpacing") || "1.7";
-const background = urlParams.get("background") || "#000000";
-const opacity = urlParams.get("opacity") || "0.85";
+const fontSize = GetIntParam("fontSize", 30);
+const useCustomBackground = GetBooleanParam("useCustomBackground", true);
+const background = urlParams.get("background") || "";
+const opacity = GetIntParam("opacity", 0.85);
-const hideAfter = GetIntParam("hideAfter", 0);
-const excludeCommands = GetBooleanParam("excludeCommands", true);
-const ignoreChatters = urlParams.get("ignoreChatters") || "";
-const scrollDirection = GetIntParam("scrollDirection", 1);
-const inlineChat = GetBooleanParam("inlineChat", false);
-const imageEmbedPermissionLevel = GetIntParam("imageEmbedPermissionLevel", 20);
+// General
+const hideAfter = GetIntParam("hideAfter", 8);
+const showAnimation = urlParams.get("showAnimation") || "";
+const hideAnimation = urlParams.get("hideAnimation") || "";
+const alignment = urlParams.get("alignment") || "";
+const showMesesages = GetBooleanParam("showMesesages", true);
-const showTwitchMessages = GetBooleanParam("showTwitchMessages", true);
-const showTwitchAnnouncements = GetBooleanParam("showTwitchAnnouncements", true);
+// Which Twitch alerts do you want to see?
+const showTwitchFollows = GetBooleanParam("showTwitchFollows", false);
+const twitchFollowAction = urlParams.get("twitchFollowAction") || "";
const showTwitchSubs = GetBooleanParam("showTwitchSubs", true);
+const twitchSubAction = urlParams.get("twitchSubAction") || "";
const showTwitchChannelPointRedemptions = GetBooleanParam("showTwitchChannelPointRedemptions", true);
+const twitchChannelPointRedemptionAction = urlParams.get("twitchChannelPointRedemptionAction") || "";
+const showTwitchCheers = GetBooleanParam("showTwitchCheers", true);
+const twitchCheerAction = urlParams.get("twitchCheerAction") || "";
const showTwitchRaids = GetBooleanParam("showTwitchRaids", true);
-const showTwitchSharedChat = GetIntParam("showTwitchSharedChat", 2);
+const twitchRaidAction = urlParams.get("twitchRaidAction") || "";
-const showYouTubeMessages = GetBooleanParam("showYouTubeMessages", true);
+// Which YouTube alerts do you want to see?
const showYouTubeSuperChats = GetBooleanParam("showYouTubeSuperChats", true);
+const youtubeSuperChatAction = urlParams.get("youtubeSuperChatAction") || "";
const showYouTubeSuperStickers = GetBooleanParam("showYouTubeSuperStickers", true);
+const youtubeSuperStickerAction = urlParams.get("youtubeSuperStickerAction") || "";
const showYouTubeMemberships = GetBooleanParam("showYouTubeMemberships", true);
+const youtubeMembershipAction = urlParams.get("youtubeMembershipAction") || "";
-const showStreamlabsDonations = GetBooleanParam("showStreamlabsDonations", true)
-const showStreamElementsTips = GetBooleanParam("showStreamElementsTips", true);
-const showPatreonMemberships = GetBooleanParam("showPatreonMemberships", true);
-const showKofiDonations = GetBooleanParam("showKofiDonations", true);
-const showTipeeeStreamDonations = GetBooleanParam("showTipeeeStreamDonations", true);
-const showFourthwallAlerts = GetBooleanParam("showFourthwallAlerts", true);
+// Which donation alerts do you want to see?
+const showStreamlabsDonations = GetBooleanParam("showStreamlabsDonations", false);
+const streamlabsDonationAction = urlParams.get("streamlabsDonationAction") || "";
+const showStreamElementsTips = GetBooleanParam("showStreamElementsTips", false);
+const streamelementsTipAction = urlParams.get("streamelementsTipAction") || "";
+const showPatreonMemberships = GetBooleanParam("showPatreonMemberships", false);
+const patreonMembershipActions = urlParams.get("patreonMembershipActions") || "";
+const showKofiDonations = GetBooleanParam("showKofiDonations", false);
+const kofiDonationAction = urlParams.get("kofiDonationAction") || "";
+const showTipeeeStreamDonations = GetBooleanParam("showTipeeeStreamDonations", false);
+const tipeeestreamDonationAction = urlParams.get("tipeeestreamDonationAction") || "";
+const showFourthwallAlerts = GetBooleanParam("showFourthwallAlerts", false);
+const fourthwallAlertAction = urlParams.get("fourthwallAlertAction") || "";
-const animationSpeed = GetIntParam("animationSpeed", 8000);
-
-const furryMode = GetBooleanParam("furryMode", false);
+// Set avatar visibility
+if (!showAvatar)
+ avatarElement.style.display = 'none';
// Set fonts for the widget
document.body.style.fontFamily = font;
@@ -124,7 +179,7 @@ const client = new StreamerbotClient({
client.on('Twitch.Cheer', (response) => {
console.debug(response.data);
- TwitchChatMessage(response.data);
+ TwitchCheer(response.data);
})
client.on('Twitch.Sub', (response) => {
@@ -248,6 +303,59 @@ client.on('Fourthwall.GiftDrawEnded', (response) => {
// MULTICHAT OVERLAY //
///////////////////////
+async function TwitchCheer(data) {
+ if (!showTwitchSubs)
+ return;
+
+ // Set the text
+ const username = data.message.displayName;
+ const bits = data.bits;
+ let message = data.message.message;
+
+ // Render avatars
+ const avatarURL = await GetAvatar(username);
+
+ // Render emotes
+ for (i in data.emotes) {
+ const 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');
+ message = message.replace(regex, emoteElement);
+ }
+
+ // Render cheermotes
+ for (i in data.cheerEmotes) {
+ const bits = data.cheerEmotes[i].bits;
+ const imageUrl = data.cheerEmotes[i].imageUrl;
+ const name = data.cheerEmotes[i].name;
+ const cheerEmoteElement = `
`;
+ const bitsElements = `${bits}`
+ message = message.replace(new RegExp(`\\b${name}${bits}\\b`, 'i'), cheerEmoteElement + bitsElements);
+ }
+
+ UpdateAlertBox(
+ 'twitch',
+ avatarURL,
+ `${username}`,
+ `cheered ${bits} bits`,
+ '',
+ username,
+ message
+ );
+}
+
async function TwitchSub(data) {
if (!showTwitchSubs)
return;
@@ -380,7 +488,7 @@ async function TwitchRaid(data) {
// Set the text
const username = data.from_broadcaster_user_login;
const viewers = data.viewers;
-
+
UpdateAlertBox(
'twitch',
avatarURL,
@@ -388,7 +496,9 @@ async function TwitchRaid(data) {
`is raiding with a party of ${viewers}`,
'',
username,
- ''
+ '',
+ twitchFollowAction,
+ data
);
}
@@ -1142,12 +1252,12 @@ function GetWinnersList(gifts) {
// return furryWords.join('');
// }
-function UpdateAlertBox(platform, avatarURL, headerText, descriptionText, attributeText, username, message) {
+async function UpdateAlertBox(platform, avatarURL, headerText, descriptionText, attributeText, username, message, sbAction, sbData) {
// Check if the widget is in the middle of an animation
// If any alerts are requested while the animation is playing, it should be added to the alert queue
if (widgetLocked) {
console.debug("Animation is progress, added alert to queue");
- let data = { platform: platform, avatarURL: avatarURL, headerText: headerText, descriptionText: descriptionText, attributeText: attributeText, message: message };
+ let data = { platform: platform, avatarURL: avatarURL, headerText: headerText, descriptionText: descriptionText, attributeText: attributeText, username: username, message: message, sbAction: sbAction, sbData: sbData};
alertQueue.push(data);
return;
}
@@ -1173,8 +1283,16 @@ function UpdateAlertBox(platform, avatarURL, headerText, descriptionText, attrib
messageLabel.innerHTML = message != null ? `${message}` : '';
theContentThatShowsLastInsteadOfFirst.style.opacity = 0;
- alertBox.style.height = theContentThatShowsFirstInsteadOfSecond.offsetHeight + 40 + "px";
- alertBox.style.animation = 'slideInFromTop 0.5s ease-out forwards';
+ theContentThatShowsFirstInsteadOfSecond.style.display = 'flex';
+ alertBox.style.maxHeight = theContentThatShowsFirstInsteadOfSecond.offsetHeight + "px";
+ alertBox.style.minHeight = theContentThatShowsFirstInsteadOfSecond.offsetHeight + "px";
+ alertBox.style.animation = 'slideInFromRight 0.5s ease-out forwards';
+
+ // Run the Streamer.bot action if there is one
+ if (sbAction) {
+ console.debug('Running Streamer.bot action: ' + sbAction);
+ await client.doAction({name: sbAction}, sbData);
+ }
// (1) Set timeout (5 seconds)
// (2) Set the message label
@@ -1183,29 +1301,51 @@ function UpdateAlertBox(platform, avatarURL, headerText, descriptionText, attrib
// (a) Add in the CSS animation when this is working
setTimeout(() => {
alertBox.style.transition = 'all 0.5s ease-in-out';
- alertBox.style.height = theContentThatShowsLastInsteadOfFirst.offsetHeight + 40 + "px";
theContentThatShowsFirstInsteadOfSecond.style.opacity = 0;
+
+ theContentThatShowsFirstInsteadOfSecond.style.position = 'absolute';
+ theContentThatShowsLastInsteadOfFirst.style.display = 'inline-block';
+ alertBox.style.maxHeight = theContentThatShowsLastInsteadOfFirst.offsetHeight + "px";
+ alertBox.style.minHeight = 'none';
theContentThatShowsLastInsteadOfFirst.style.opacity = 1;
-
+
setTimeout(() => {
- alertBox.style.animation = 'slideBackUp 0.5s ease-out forwards';
+ alertBox.style.animation = 'slideOffRight 0.5s ease-out forwards';
setTimeout(() => {
- alertBox.style.transition = '';
+ alertBox.style.maxHeight = '0px';
theContentThatShowsFirstInsteadOfSecond.style.opacity = 1;
theContentThatShowsLastInsteadOfFirst.style.opacity = 0;
- alertBox.style.height = '0px';
+ theContentThatShowsFirstInsteadOfSecond.style.position = 'relative';
+ theContentThatShowsLastInsteadOfFirst.style.display = 'none';
widgetLocked = false;
if (alertQueue.length > 0) {
console.debug("Pulling next alert from the queue");
let data = alertQueue.shift();
- UpdateAlertBox(data.platform, data.avatarURL, data.headerText, data.descriptionText, data.attributeText, data.message)
+ UpdateAlertBox(data.platform, data.avatarURL, data.headerText, data.descriptionText, data.attributeText, data.username, data.message, data.sbAction, data.sbData);
}
}, 1000);
- }, messageLabel.innerText.trim() != '' ? animationSpeed : 0);
+ }, message ? hideAfter * 1000 : 0);
+ }, hideAfter * 1000);
- }, animationSpeed);
+}
+////////////////////
+// TEST FUNCTIONS //
+////////////////////
+
+async function testWidget()
+{
+ UpdateAlertBox(
+ 'twitch',
+ await GetAvatar('nutty'),
+ `nutty`,
+ `subscribed with Tier 3`,
+ '',
+ `nutty`,
+ `O-oooooooooo AAAAE-A-A-I-A-U- JO-oooooooooooo AAE-O-A-A-U-U-A- E-eee-ee-eee AAAAE-A-E-I-E-A-JO-ooo-oo-oo-oo EEEEO-A-AAA-AAAA`
+ //``
+ );
}
diff --git a/multistream-alerts/settings/index.html b/multistream-alerts/settings/index.html
index 7ddcb25..aebc55b 100644
--- a/multistream-alerts/settings/index.html
+++ b/multistream-alerts/settings/index.html
@@ -1,5 +1,4 @@
-
@@ -50,15 +49,10 @@
-
-
-
-
-
-
+
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/multistream-alerts/settings/script.js b/multistream-alerts/settings/script.js
index 45fcbf9..c62f79e 100644
--- a/multistream-alerts/settings/script.js
+++ b/multistream-alerts/settings/script.js
@@ -1,5 +1,6 @@
let settingsContainer = document.getElementById('settings-container');
settingsContainer.src = `../../.utilities/settings-page-builder?settingsJson=${window.location.href}/settings.json`
+//settingsContainer.src = `../../.utilities/settings-page-builder?settingsJson=../../multistream-alerts/settings/settings.json`
console.log(settingsContainer.src);
function reloadWidget(data) {
@@ -26,4 +27,10 @@ function getParentUrl() {
}
return parentUrl;
+}
+
+function callFunction(functionName) {
+ console.debug(`Calling ${functionName}`);
+ let widget = document.getElementById("widget");
+ widget.contentWindow[functionName]();
}
\ No newline at end of file
diff --git a/multistream-alerts/settings/settings.json b/multistream-alerts/settings/settings.json
index 36599eb..030dd8e 100644
--- a/multistream-alerts/settings/settings.json
+++ b/multistream-alerts/settings/settings.json
@@ -1,5 +1,13 @@
{
"settings": [
+ {
+ "id": "testWidgetButton",
+ "label": "Send Test Alert",
+ "description": "",
+ "type": "button",
+ "callFunction": "testWidget",
+ "group": "Test Alerts"
+ },
{
"id": "showAvatar",
"label": "Show Avatar",
@@ -56,7 +64,7 @@
{
"id": "hideAfter",
"label": "Hide After",
- "description": "Alerts will show for X seconds",
+ "description": "Alerts will hide for X seconds",
"type": "number",
"min": 1,
"max": 120,
@@ -151,18 +159,19 @@
},
{
"id": "showTwitchFollows",
- "label": "New Follows",
+ "label": "New Followers",
"description": "",
"type": "checkbox",
- "defaultValue": true,
+ "defaultValue": false,
"group": "Which Twitch alerts do you want to see?"
},
{
- "id": "showTwitchCheers",
- "label": "Cheers",
- "description": "",
- "type": "checkbox",
- "defaultValue": true,
+ "id": "twitchFollowAction",
+ "label": "",
+ "description": "Also run this Streamer.bot Action",
+ "type": "sb-actions",
+ "defaultValue": "",
+ "hideIf": "showTwitchFollows",
"group": "Which Twitch alerts do you want to see?"
},
{
@@ -173,6 +182,15 @@
"defaultValue": true,
"group": "Which Twitch alerts do you want to see?"
},
+ {
+ "id": "twitchSubAction",
+ "label": "",
+ "description": "Also run this Streamer.bot Action",
+ "type": "sb-actions",
+ "defaultValue": "",
+ "hideIf": "showTwitchSubs",
+ "group": "Which Twitch alerts do you want to see?"
+ },
{
"id": "showTwitchChannelPointRedemptions",
"label": "Channel Point Redemptions",
@@ -181,6 +199,32 @@
"defaultValue": true,
"group": "Which Twitch alerts do you want to see?"
},
+ {
+ "id": "twitchChannelPointRedemptionAction",
+ "label": "",
+ "description": "Also run this Streamer.bot Action",
+ "type": "sb-actions",
+ "defaultValue": "",
+ "hideIf": "showTwitchChannelPointRedemptions",
+ "group": "Which Twitch alerts do you want to see?"
+ },
+ {
+ "id": "showTwitchCheers",
+ "label": "Cheers",
+ "description": "",
+ "type": "checkbox",
+ "defaultValue": true,
+ "group": "Which Twitch alerts do you want to see?"
+ },
+ {
+ "id": "twitchCheerAction",
+ "label": "",
+ "description": "Also run Streamer.bot Action",
+ "type": "sb-actions",
+ "defaultValue": "",
+ "hideIf": "showTwitchCheers",
+ "group": "Which Twitch alerts do you want to see?"
+ },
{
"id": "showTwitchRaids",
"label": "Raids",
@@ -189,6 +233,15 @@
"defaultValue": true,
"group": "Which Twitch alerts do you want to see?"
},
+ {
+ "id": "twitchRaidAction",
+ "label": "",
+ "description": "Also run this Streamer.bot Action",
+ "type": "sb-actions",
+ "defaultValue": "",
+ "hideIf": "showTwitchRaids",
+ "group": "Which Twitch alerts do you want to see?"
+ },
{
"id": "showYouTubeSuperChats",
"label": "Super Chats",
@@ -197,6 +250,15 @@
"defaultValue": true,
"group": "Which YouTube alerts do you want to see?"
},
+ {
+ "id": "youtubeSuperChatAction",
+ "label": "",
+ "description": "Also run this Streamer.bot Action",
+ "type": "sb-actions",
+ "defaultValue": "",
+ "hideIf": "showYouTubeSuperChats",
+ "group": "Which YouTube alerts do you want to see?"
+ },
{
"id": "showYouTubeSuperStickers",
"label": "Super Stickers",
@@ -205,6 +267,15 @@
"defaultValue": true,
"group": "Which YouTube alerts do you want to see?"
},
+ {
+ "id": "youtubeSuperStickerAction",
+ "label": "",
+ "description": "Also run this Streamer.bot Action",
+ "type": "sb-actions",
+ "defaultValue": "",
+ "hideIf": "showYouTubeSuperStickers",
+ "group": "Which YouTube alerts do you want to see?"
+ },
{
"id": "showYouTubeMemberships",
"label": "Memberships",
@@ -213,12 +284,30 @@
"defaultValue": true,
"group": "Which YouTube alerts do you want to see?"
},
+ {
+ "id": "youtubeMembershipAction",
+ "label": "",
+ "description": "Also run this Streamer.bot Action",
+ "type": "sb-actions",
+ "defaultValue": "",
+ "hideIf": "showYouTubeMemberships",
+ "group": "Which YouTube alerts do you want to see?"
+ },
{
"id": "showStreamlabsDonations",
"label": "Streamlabs Tips",
"description": "
Click to connect",
"type": "checkbox",
- "defaultValue": true,
+ "defaultValue": false,
+ "group": "Which donation alerts do you want to see?"
+ },
+ {
+ "id": "streamlabsDonationAction",
+ "label": "",
+ "description": "Also run this Streamer.bot Action",
+ "type": "sb-actions",
+ "defaultValue": "",
+ "hideIf": "showStreamlabsDonations",
"group": "Which donation alerts do you want to see?"
},
{
@@ -226,7 +315,16 @@
"label": "StreamElements Tips",
"description": "
Click to connect",
"type": "checkbox",
- "defaultValue": true,
+ "defaultValue": false,
+ "group": "Which donation alerts do you want to see?"
+ },
+ {
+ "id": "streamelementsTipAction",
+ "label": "",
+ "description": "Also run this Streamer.bot Action",
+ "type": "sb-actions",
+ "defaultValue": "",
+ "hideIf": "showStreamElementsTips",
"group": "Which donation alerts do you want to see?"
},
{
@@ -234,7 +332,16 @@
"label": "Patreon Memberships",
"description": "
Click to connect",
"type": "checkbox",
- "defaultValue": true,
+ "defaultValue": false,
+ "group": "Which donation alerts do you want to see?"
+ },
+ {
+ "id": "patreonMembershipActions",
+ "label": "",
+ "description": "Also run this Streamer.bot Action",
+ "type": "sb-actions",
+ "defaultValue": "",
+ "hideIf": "showPatreonMemberships",
"group": "Which donation alerts do you want to see?"
},
{
@@ -242,7 +349,16 @@
"label": "Ko-fi Donations",
"description": "
Click to connect",
"type": "checkbox",
- "defaultValue": true,
+ "defaultValue": false,
+ "group": "Which donation alerts do you want to see?"
+ },
+ {
+ "id": "kofiDonationAction",
+ "label": "",
+ "description": "Also run this Streamer.bot Action",
+ "type": "sb-actions",
+ "defaultValue": "",
+ "hideIf": "showKofiDonations",
"group": "Which donation alerts do you want to see?"
},
{
@@ -250,7 +366,16 @@
"label": "TipeeeStream Donations",
"description": "
Click to connect",
"type": "checkbox",
- "defaultValue": true,
+ "defaultValue": false,
+ "group": "Which donation alerts do you want to see?"
+ },
+ {
+ "id": "tipeeestreamDonationAction",
+ "label": "",
+ "description": "Also run this Streamer.bot Action",
+ "type": "sb-actions",
+ "defaultValue": "",
+ "hideIf": "showTipeeeStreamDonations",
"group": "Which donation alerts do you want to see?"
},
{
@@ -258,7 +383,16 @@
"label": "Fourthwall Alerts",
"description": "
Click to connect",
"type": "checkbox",
- "defaultValue": true,
+ "defaultValue": false,
+ "group": "Which donation alerts do you want to see?"
+ },
+ {
+ "id": "fourthwallAlertAction",
+ "label": "",
+ "description": "Also run this Streamer.bot Action",
+ "type": "sb-actions",
+ "defaultValue": "",
+ "hideIf": "showFourthwallAlerts",
"group": "Which donation alerts do you want to see?"
}
]
diff --git a/multistream-alerts/style.css b/multistream-alerts/style.css
index 0a31fed..59bc810 100644
--- a/multistream-alerts/style.css
+++ b/multistream-alerts/style.css
@@ -1,9 +1,9 @@
* {
margin: 0;
padding: 0;
- --margin: 20px;
- /* --border-radius: 20px; */
- font-size: 30px;
+ --margin: 0.5em;
+ --border-radius: 1em;
+ /* font-size: 30px; */
/* --line-spacing: 1.7em; */
}
@@ -37,12 +37,14 @@ html {
}
#mainContainer {
- display: block;
position: absolute;
width: 100%;
height: 100%;
padding: calc(2 * var(--margin));
box-sizing: border-box;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-end;
}
#alertBox {
@@ -53,10 +55,10 @@ html {
overflow: hidden;
box-sizing: border-box;
/* text-align: center; */
- position: relative;
+ /* position: relative; */
/* transition: all 1s ease-in-out; */
- min-height: 0px;
- height: 0px;
+ /* min-height: 0px;
+ max-height: 0px; */
}
/* #alertBox::before {
@@ -79,21 +81,25 @@ html {
display: flex;
align-items: center;
z-index: 1;
- position: absolute;
- left: var(--margin);
- top: var(--margin);
+ /* position: absolute; */
+ /* left: var(--margin);
+ top: var(--margin); */
transition: inherit;
+ padding: var(--margin);
+ display: none;
}
#theContentThatShowsLastInsteadOfFirst {
- position: absolute;
- display: block;
+ /* position: absolute; */
+ display: inline-block;
align-items: center;
z-index: 0;
- position: absolute;
- left: var(--margin);
- top: var(--margin);
+ /* position: absolute; */
+ /* left: var(--margin);
+ top: var(--margin); */
+ padding: var(--margin);
transition: inherit;
+ display: none;
}
#avatar {
@@ -146,6 +152,19 @@ html {
border-radius: 0.5em;
}
+.emote {
+ height: 1.5em;
+ margin: 1px;
+ transform: translate(0px, 0.4em);
+}
+
+.bits {
+ background: #adadad46;
+ border-radius: calc(var(--border-radius) / 2);
+ font-size: 0.7em;
+ padding: 5px 10px;
+}
+
#message {
width: calc(100% - 2 * var(--margin));
z-index: 0;
@@ -167,7 +186,7 @@ html {
}
}
-@keyframes slideBackUp {
+@keyframes slideOffUp {
0% {
transform: translateY(0);
opacity: 1;
@@ -191,7 +210,7 @@ html {
}
}
-@keyframes slideBackDown {
+@keyframes slideOffDown {
0% {
transform: translateY(0);
opacity: 1;
@@ -215,7 +234,7 @@ html {
}
}
-@keyframes slideBackLeft {
+@keyframes slideOffLeft {
0% {
transform: translateX(0);
opacity: 1;
@@ -239,7 +258,7 @@ html {
}
}
-@keyframes slideBackRight {
+@keyframes slideOffRight {
0% {
transform: translateX(0);
opacity: 1;