diff --git a/twitch-ad-countdown-timer/index.html b/twitch-ad-countdown-timer/index.html new file mode 100644 index 0000000..e3e8d75 --- /dev/null +++ b/twitch-ad-countdown-timer/index.html @@ -0,0 +1,28 @@ + + + + + + + + + + + +
Connecting...
+
+
+
+ Ad +    + 1 of 3 • + 1:20 +
+
+
Ads starting in...
+
69
+
+
+ + + \ No newline at end of file diff --git a/twitch-ad-countdown-timer/script.js b/twitch-ad-countdown-timer/script.js new file mode 100644 index 0000000..191ecf1 --- /dev/null +++ b/twitch-ad-countdown-timer/script.js @@ -0,0 +1,397 @@ +//////////////// +// PARAMETERS // +//////////////// + +const queryString = window.location.search; +const urlParams = new URLSearchParams(queryString); + +let sbDebugMode = true; +const sbServerAddress = urlParams.get("address") || "127.0.0.1"; +const sbServerPort = urlParams.get("port") || "8080"; + +/////////////////// +// PAGE ELEMENTS // +/////////////////// + +const timerBar = document.getElementById('timer-bar'); +const adLabel = document.getElementById('ad-label'); +const timerLabel = document.getElementById('timer-label'); +const adsRemainingLabel = document.getElementById('ads-remaining-label'); +const timeRemainingLabel = document.getElementById('time-remaining-label'); +const upcomingAdWarningContainer = document.getElementById('upcoming-ad-warning-container'); +const countdownLabel = document.getElementById('countdown-label'); + +///////////// +// OPTIONS // +///////////// + +// Appearance +const barColor = urlParams.get("barColor") || "#FFCC00"; +const barThickness = GetIntParam("barThickness", 4); +const barPosition = urlParams.get("barPosition") || "bottom"; +const timerColor = urlParams.get("timerColor") || "#FFCC00"; +const timerPosition = urlParams.get("timerPosition") || "top-left"; + +// General +const showUpcomingAdWarning = GetBooleanParam("showUpcomingAdWarning", true); +const warningSeconds = GetIntParam("warningSeconds", 10); + +///////////////// +// GLOBAL VARS // +///////////////// + +let singleAdLength = 30; +let timerBarLocked = false; +let timerLabelLocked = false; +let upcomingAdWarningLocked = false; + +///////////////// +// PAGEE SETUP // +///////////////// + +// Set the colors +timerBar.style.background = barColor; +adLabel.style.background = timerColor; + +// Set the position of the bar +switch (barPosition) { + case "none": + timerBar.style.display = "none"; + break; + case "bottom": + timerBar.style.height = barThickness + "px"; + timerBar.style.bottom = "0px"; + timerBar.style.left = "0px"; + break; + + case "top": + timerBar.style.height = barThickness + "px"; + timerBar.style.top = "0px"; + timerBar.style.left = "0px"; + break; + + case "left": + timerBar.style.width = barThickness + "px"; + timerBar.style.bottom = "0px"; + timerBar.style.left = "0px"; + break; + + case "right": + timerBar.style.width = barThickness + "px"; + timerBar.style.bottom = "0px"; + timerBar.style.right = "0px"; + break; +} + +// Set the position of the timer +switch (timerPosition) { + case "none": + timerLabel.style.display = "none"; + break; + case "top-left": + timerLabel.style.top = "0px"; + timerLabel.style.left = "0px"; + break; + case "top-right": + timerLabel.style.top = "0px"; + timerLabel.style.right = "0px"; + break; + case "bottom-left": + timerLabel.style.bottom = "0px"; + timerLabel.style.left = "0px"; + break; + case "bottom-right": + timerLabel.style.bottom = "0px"; + timerLabel.style.right = "0px"; + break; +} + + + +///////////////////////// +// STREAMER.BOT CLIENT // +///////////////////////// + +const client = new StreamerbotClient({ + host: sbServerAddress, + port: sbServerPort, + + onConnect: (data) => { + console.log(`Streamer.bot successfully connected to ${sbServerAddress}:${sbServerPort}`) + console.debug(data); + SetConnectionStatus(true); + }, + + onDisconnect: () => { + console.error(`Streamer.bot disconnected from ${sbServerAddress}:${sbServerPort}`) + SetConnectionStatus(false); + } +}); + +client.on('Twitch.AdRun', (response) => { + console.debug(response.data); + TwitchAdRun(response.data); +}) + +client.on('Twitch.UpcomingAd', (response) => { + console.debug(response.data); + TwitchUpcomingAd(response.data); +}) + + + +///////////////////// +// TWITCH AD TIMER // +///////////////////// + +function TwitchAdRun(data) { + const duration = data.length_seconds; + + TimerBarAnimation(duration); + TimerLabelAnimation(duration); +} + +function TwitchUpcomingAd(data) { + // TODO: Need to scrape UpcomingAd data to continue this + const warningMinute = 5; + + const delayStart = warningMinute * 60 - warningSeconds; + + setTimeout(() => { + UpcomingAdWarning(warningSeconds); + }, delayStart * 1000); +} + +function TimerBarAnimation(duration) { + // Check if the widget is in the middle of an animation + if (timerBarLocked) + return; + + timerBarLocked = true; + + // If the bar is top/bottom, animate horizontally + // If the bar is left/right, animate vertically + switch (barPosition) { + case "bottom": + case "top": + timerBar.style.transition = 'width 0.5s ease-in-out'; + timerBar.style.width = '100%'; + setTimeout(() => { + timerBar.style.transition = `width ${duration}s linear`; + timerBar.style.width = '0%'; + }, 500); + break; + + case "left": + case "right": + timerBar.style.transition = 'height 0.5s ease-in-out'; + timerBar.style.height = '100%'; + setTimeout(() => { + timerBar.style.transition = `height ${duration}s linear`; + timerBar.style.height = '0%'; + }, 500); + break; + } + + // Unlock the widget + setTimeout(() => { + timerBarLocked = false; + }, duration * 1000); +} + +function TimerLabelAnimation(duration) { + // Check if the widget is in the middle of an animation + if (timerLabelLocked) + return; + + timerLabelLocked = true; + + // Calculate starting time + let startingTime = duration % singleAdLength; + if (startingTime == 0) + startingTime = singleAdLength; + + // Estimate how many ads there should be + let adsTotal = Math.ceil(duration / singleAdLength); + let adsRemaining = 1; + + function updateTimer() { + // Show the labels BEFORE decrementing + adsRemainingLabel.innerText = `${adsRemaining} of ${adsTotal} • `; + timeRemainingLabel.innerText = startingTime.toString().toHHMMSS(); + timerLabel.style.opacity = 1; + + // Decrement time + startingTime--; + + // Check for transitions + if (startingTime < 0 && adsRemaining < adsTotal) { + adsRemaining++; + startingTime = singleAdLength - 1; // -1 since 1 second has already passed + } + + if (startingTime < 0 && adsRemaining === adsTotal) { + clearInterval(timerThingy); + timerLabel.style.opacity = 0; + } + } + + // Run immediately + updateTimer(); + + // Then every second + var timerThingy = setInterval(updateTimer, 1000); + + // Unlock the widget + setTimeout(() => { + timerLabelLocked = false; + }, duration * 1000); +} + +function UpcomingAdWarning(warningSeconds) { + if (!showUpcomingAdWarning) + return; + + // Check if the widget is in the middle of an animation + if (upcomingAdWarningLocked) + return; + + upcomingAdWarningLocked = true; + + let width = upcomingAdWarningContainer.getBoundingClientRect().width; + + // Set the starting position of the countdown box + upcomingAdWarningContainer.style.right = -width + "px"; + countdownLabel.innerHTML = warningSeconds; + + // Slide the countdown box on screen + upcomingAdWarningContainer.style.right = "0px"; + + // Start the countdown timer + let startingTime = warningSeconds; + + var timerThingy = setInterval(function () { + startingTime--; + countdownLabel.innerText = startingTime; + if (startingTime == 0) { + clearInterval(timerThingy); + upcomingAdWarningContainer.style.right = -width + "px"; + return; + } + }, 1000) + + // Unlock the widget + setTimeout(() => { + upcomingAdWarningLocked = false; + }, warningSeconds * 1000); +} + + + +////////////////////// +// HELPER FUNCTIONS // +////////////////////// + +function GetBooleanParam(paramName, defaultValue) { + const urlParams = new URLSearchParams(window.location.search); + const paramValue = urlParams.get(paramName); + + if (paramValue === null) { + return defaultValue; // Parameter not found + } + + const lowercaseValue = paramValue.toLowerCase(); // Handle case-insensitivity + + if (lowercaseValue === 'true') { + return true; + } else if (lowercaseValue === 'false') { + return false; + } else { + return paramValue; // Return original string if not 'true' or 'false' + } +} + +function GetIntParam(paramName, defaultValue) { + const urlParams = new URLSearchParams(window.location.search); + const paramValue = urlParams.get(paramName); + + if (paramValue === null) { + return defaultValue; // or undefined, or a default value, depending on your needs + } + + console.log(paramValue); + + const intValue = parseInt(paramValue, 10); // Parse as base 10 integer + + if (isNaN(intValue)) { + return null; // or handle the error in another way, e.g., throw an error + } + + return intValue; +} + +String.prototype.toHHMMSS = function () { + var sec_num = parseInt(this, 10); // don't forget the second param + var hours = Math.floor(sec_num / 3600); + var minutes = Math.floor((sec_num - (hours * 3600)) / 60); + var seconds = sec_num - (hours * 3600) - (minutes * 60); + + if (hours < 10) { hours = "0" + hours; } + //if (minutes < 10) {minutes = "0"+minutes;} + if (seconds < 10) { seconds = "0" + seconds; } + //return hours+':'+minutes+':'+seconds; + return minutes + ':' + seconds; +} + +function IsNullOrWhitespace(str) { + return /^\s*$/.test(str); +} + +//////////////////// +// TEST FUNCTIONS // +//////////////////// + +function testAd() { + const data = { + "length_seconds": 15, + "timestamp": "0001-01-01T00:00:00", + "is_automatic": true, + "requester_user_id": "54983562", + "requester_user_login": "nutty", + "requester_user_name": "nutty", + "is_test": false + } + + TwitchAdRun(data) +} + +function testUpcomingAdWarning() { + UpcomingAdWarning(10); +} + + + + +/////////////////////////////////// +// STREAMER.BOT WEBSOCKET STATUS // +/////////////////////////////////// + +// This function sets the visibility of the Streamer.bot status label on the overlay +function SetConnectionStatus(connected) { + let statusContainer = document.getElementById("statusContainer"); + if (connected) { + statusContainer.style.background = "#2FB774"; + statusContainer.innerText = "Connected!"; + statusContainer.style.opacity = 1; + setTimeout(() => { + statusContainer.style.transition = "all 2s ease"; + statusContainer.style.opacity = 0; + }, 10); + } + else { + statusContainer.style.background = "#D12025"; + statusContainer.innerText = "Connecting..."; + statusContainer.style.transition = ""; + statusContainer.style.opacity = 1; + } +} \ No newline at end of file diff --git a/twitch-ad-timer/settings/index.html b/twitch-ad-countdown-timer/settings/index.html similarity index 100% rename from twitch-ad-timer/settings/index.html rename to twitch-ad-countdown-timer/settings/index.html diff --git a/twitch-ad-timer/settings/script.js b/twitch-ad-countdown-timer/settings/script.js similarity index 100% rename from twitch-ad-timer/settings/script.js rename to twitch-ad-countdown-timer/settings/script.js diff --git a/twitch-ad-countdown-timer/settings/settings.json b/twitch-ad-countdown-timer/settings/settings.json new file mode 100644 index 0000000..fdb7e26 --- /dev/null +++ b/twitch-ad-countdown-timer/settings/settings.json @@ -0,0 +1,140 @@ +{ + "settings": [ + { + "id": "testAd", + "label": "Send Test Ad", + "description": "", + "type": "button", + "callFunction": "testAd", + "group": "" + }, + { + "id": "testUpcomingAdWarning", + "label": "Send Test Upcoming Ad Warning", + "description": "", + "type": "button", + "callFunction": "testUpcomingAdWarning", + "group": "" + }, + { + "id": "barColor", + "label": "Bar Color", + "description": "", + "type": "color", + "defaultValue": "#FFCC00", + "group": "Appearance" + }, + { + "id": "barThickness", + "label": "Bar Thickness", + "description": "", + "type": "number", + "defaultValue": "4", + "min": 1, + "group": "Appearance" + }, + { + "id": "barPosition", + "label": "Bar Position", + "description": "", + "type": "select", + "options": [ + { + "value": "none", + "label": "None" + }, + { + "value": "bottom", + "label": "Bottom" + }, + { + "value": "top", + "label": "Top" + }, + { + "value": "left", + "label": "Left" + }, + { + "value": "right", + "label": "Right" + } + ], + "defaultValue": "bottom", + "group": "Appearance" + }, + { + "id": "timerColor", + "label": "Timer Color", + "description": "", + "type": "color", + "defaultValue": "#FFCC00", + "group": "Appearance" + }, + { + "id": "timerPosition", + "label": "Timer Position", + "description": "", + "type": "select", + "options": [ + { + "value": "none", + "label": "None" + }, + { + "value": "top-left", + "label": "Top Left" + }, + { + "value": "top-right", + "label": "Top Right" + }, + { + "value": "bottom-left", + "label": "Bottom Left" + }, + { + "value": "bottom-right", + "label": "Bottom Right" + } + ], + "defaultValue": "top-left", + "group": "Appearance" + }, + { + "id": "showUpcomingAdWarning", + "label": "Show Upcoming Ad Warning", + "description": "", + "type": "checkbox", + "defaultValue": true, + "group": "General" + }, + { + "id": "warningSeconds", + "label": "Warning Time", + "description": "Warn X seconds before ad", + "type": "number", + "defaultValue": "10", + "min": 1, + "max": 300, + "showIf": "showUpcomingAdWarning", + "group": "General" + }, + { + "id": "address", + "label": "Address", + "description": "Streamer.bot Websocket Server Address", + "type": "text", + "defaultValue": "127.0.0.1", + "group": "Advanced" + }, + { + "id": "port", + "label": "Port", + "description": "Streamer.bot Websocket Server Port", + "type": "text", + "defaultValue": "8080", + "group": "Advanced" + } + ] +} \ No newline at end of file diff --git a/twitch-ad-timer/style.css b/twitch-ad-countdown-timer/style.css similarity index 72% rename from twitch-ad-timer/style.css rename to twitch-ad-countdown-timer/style.css index 57bf3ae..b42d350 100644 --- a/twitch-ad-timer/style.css +++ b/twitch-ad-countdown-timer/style.css @@ -3,14 +3,20 @@ padding: 0; } +body { + overflow: hidden; +} + +html { + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial, sans-serif; + /* color: white; + text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.5); + overflow-wrap: break-word; */ +} + #statusContainer { - text-transform: uppercase; - font-family: 'Metropolis'; - font-style: italic; - font-weight: bold; + font-weight: 500; font-size: 30px; - width: 400px; - max-width: fit-content; text-align: center; background-color: #D12025; color: white; @@ -22,25 +28,28 @@ transform: translate(-50%, -50%); } -#hugeTittiesContainer { - font-family: 'Metropolis'; - font-weight: bold; - background-color: rgba(0, 0, 0, .4); - padding: 12px; - border-radius: 10px; - position: absolute; - margin: 50px; - opacity: 0; - display: table; -} - -#timerBar { +#timer-bar { width: 0px; + height: 0px; background-color: #ffcc00; position: absolute; } -#adLabel { +#timer-label { + font-family: 'Metropolis'; + font-weight: bold; + background-color: rgba(0, 0, 0, .4); + color: white; + padding: 12px; + border-radius: 10px; + position: absolute; + margin: 50px; + display: table; + opacity: 0; + transition: opacity 0.5s linear; +} + +#ad-label { font-size: 20px; font-weight: bold; max-width: fit-content; @@ -53,17 +62,7 @@ display: table-cell; } -#timerLabel { - font-size: 20px; - max-width: fit-content; - text-align: center; - display: inline-block; - color: white; - padding: 10px 0px 10px 10px; - display: table-cell; -} - -#midRollContainer { +#upcoming-ad-warning-container { font-family: 'Metropolis'; font-size: 20px; max-width: fit-content; @@ -77,9 +76,10 @@ position: absolute; bottom: 15%; right: -100%; + transition: right 0.5s ease-in-out; } -#midRollCountdownContainer { +#countdown-label { font-size: 40px; font-weight: bold; margin: 10px 0px 0px 0px; diff --git a/twitch-ad-timer/index.html b/twitch-ad-timer/index.html deleted file mode 100644 index 7d541eb..0000000 --- a/twitch-ad-timer/index.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - -
Connecting...
-
-
-
-
-
- Ad -
-
- -
-
-
-
Ads starting in...
-
-
- - - - \ No newline at end of file diff --git a/twitch-ad-timer/script.js b/twitch-ad-timer/script.js deleted file mode 100644 index 513f5e4..0000000 --- a/twitch-ad-timer/script.js +++ /dev/null @@ -1,340 +0,0 @@ -//////////////// -// PARAMETERS // -//////////////// - -const queryString = window.location.search; -const urlParams = new URLSearchParams(queryString); - -let sbDebugMode = true; -const sbServerAddress = urlParams.get("address") || "127.0.0.1"; -const sbServerPort = urlParams.get("port") || "8080"; -const lineThickness = urlParams.get("lineThickness") || 4; -const barPosition = urlParams.get("barPosition") || "bottom"; // none, bottom, top, left, right -const timerPosition = urlParams.get("timerPosition") || "topLeft"; // none, topLeft, topRight, bottomLeft, bottomRight -const showMidRollCountdown = urlParams.get("timerPosition") || true; - -///////////////// -// GLOBAL VARS // -///////////////// - -let ws; -let singleAdLength = 30; - - - -/////////////////////////////////// -// SRTEAMER.BOT WEBSOCKET SERVER // -/////////////////////////////////// - -// This is the main function that connects to the Streamer.bot websocket server -function connectws() { - if ("WebSocket" in window) { - ws = new WebSocket("ws://" + sbServerAddress + ":" + sbServerPort + "/"); - - // Reconnect - ws.onclose = function () { - SetConnectionStatus(false); - setTimeout(connectws, 5000); - }; - - // Connect - ws.onopen = async function () { - SetConnectionStatus(true); - - console.log("Subscribe to events"); - ws.send( - JSON.stringify({ - request: "Subscribe", - id: "subscribe-events-id", - events: { - // This is the list of Streamer.bot websocket events to subscribe to - // See full list of events here: - // https://wiki.streamer.bot/en/Servers-Clients/WebSocket-Server/Requests - twitch: [ - "AdRun", - "AdMidRoll" - ] - } - }) - ); - - ws.onmessage = function (event) { - // Grab message and parse JSON - const msg = event.data; - const wsdata = JSON.parse(msg); - - if (typeof wsdata.event == "undefined") { - return; - } - - // Print data to log for debugging purposes - if (sbDebugMode) - { - console.log(wsdata.data); - console.log(wsdata.event.type); - } - - // Check for events to trigger - // See documentation for all events here: - // https://wiki.streamer.bot/en/Servers-Clients/WebSocket-Server/Events - switch (wsdata.event.source) { - - // Twitch Events - case 'Twitch': - switch (wsdata.event.type) { - case ('AdRun'): - AdRun(wsdata.data); - break; - case ('AdMidRoll'): - AdMidRoll(wsdata.data); - break; - } - break; - - } - }; - } - } -} - - - -/////////////////////// -// TWITCH AD OVERLAY // -/////////////////////// - -function AdRun(data) { - if (data.length_seconds <= 0) - { - TimerBarAnimation(singleAdLength); - HugeTittiesAnimation(singleAdLength); - } - else - { - TimerBarAnimation(data.length_seconds); - HugeTittiesAnimation(data.length_seconds); - } -} - -function AdMidRoll(data) { - if (!showMidRollCountdown) - return; - - //MidRollAnimation(data.length); - MidRollAnimation(5); -} - -function TimerBarAnimation(adLength) { - let timerBar = document.getElementById("timerBar"); - - switch (barPosition) { - case "none": - timerBar.style.display = "none"; - break; - case "bottom": - timerBar.style.height = lineThickness + "px"; - timerBar.style.bottom = "0px"; - timerBar.style.left = "0px"; - - // Start Animation - tl = new TimelineMax(); - tl - .to(timerBar, 0.5, { width: window.innerWidth + "px", ease: Cubic.ease }) - .to(timerBar, adLength, { width: "0px", ease: Linear.easeNone }) - break; - - case "top": - timerBar.style.height = lineThickness + "px"; - timerBar.style.top = "0px"; - timerBar.style.left = "0px"; - - // Start Animation - tl = new TimelineMax(); - tl - .to(timerBar, 0.5, { width: window.innerWidth + "px", ease: Cubic.ease }) - .to(timerBar, adLength, { width: "0px", ease: Linear.easeNone }) - break; - - case "left": - timerBar.style.width = lineThickness + "px"; - timerBar.style.bottom = "0px"; - timerBar.style.left = "0px"; - - // Start Animation - tl = new TimelineMax(); - tl - .to(timerBar, 0.5, { height: window.innerHeight + "px", ease: Cubic.ease }) - .to(timerBar, adLength, { height: "0px", ease: Linear.easeNone }) - break; - - case "right": - timerBar.style.width = lineThickness + "px"; - timerBar.style.bottom = "0px"; - timerBar.style.right = "0px"; - - // Start Animation - tl = new TimelineMax(); - tl - .to(timerBar, 0.5, { height: window.innerHeight + "px", ease: Cubic.ease }) - .to(timerBar, adLength, { height: "0px", ease: Linear.easeNone }) - break; - } -} - -function HugeTittiesAnimation(adLength) { - - let hugeTittiesContainer = document.getElementById("hugeTittiesContainer"); - - switch (timerPosition) { - case "none": - hugeTittiesContainer.style.display = "none"; - break; - case "topLeft": - hugeTittiesContainer.style.top = "0px"; - hugeTittiesContainer.style.left = "0px"; - break; - case "topRight": - hugeTittiesContainer.style.top = "0px"; - hugeTittiesContainer.style.right = "0px"; - break; - case "bottomLeft": - hugeTittiesContainer.style.bottom = "0px"; - hugeTittiesContainer.style.left = "0px"; - break; - case "bottomRight": - hugeTittiesContainer.style.bottom = "0px"; - hugeTittiesContainer.style.right = "0px"; - break; - } - - // Calculate starting time - let startingTime = adLength % singleAdLength; - if (startingTime == 0) - startingTime = singleAdLength; - - // Estimate how many ads there should be - let adsTotal = Math.ceil(adLength / singleAdLength); - let adsRemaining = 1; - - // Start the countdown timer - let adsRemainingContainer = document.getElementById("adsRemainingContainer"); - let timerContainer = document.getElementById("timerContainer"); - - var timerThingy = setInterval(function () { - startingTime--; - if (startingTime == 0 && adsRemaining < adsTotal) { - adsRemaining++; - startingTime = singleAdLength; - } - if (startingTime == 0 && adsRemaining == adsTotal) { - clearInterval(timerThingy); - SetVisibility(false); - return; - } - adsRemainingContainer.innerText = adsRemaining + " of " + adsTotal; - timerContainer.innerText = startingTime.toString().toHHMMSS(); - - // Show the widget - SetVisibility(true); - }, 1000) -} - -function MidRollAnimation(countdownLength) { - let midRollContainer = document.getElementById("midRollContainer"); - let midRollCountdownContainer = document.getElementById("midRollCountdownContainer"); - let width = midRollContainer.getBoundingClientRect().width; - - // Set the starting position of the countdown box - midRollContainer.style.right = -width + "px"; - midRollCountdownContainer.innerHTML = countdownLength; - - // Slide the countdown box on screen - ShowMidRollCountdown(true); - - // Start the countdown timer - let startingTime = countdownLength; - - var timerThingy = setInterval(function () { - startingTime--; - midRollCountdownContainer.innerText = startingTime; - if (startingTime == 0) { - clearInterval(timerThingy); - ShowMidRollCountdown(false); - return; - } - }, 1000) -} - -function SetVisibility(isVisible) { - let hugeTittiesContainer = document.getElementById("hugeTittiesContainer"); - - var tl = new TimelineMax(); - tl - .to(hugeTittiesContainer, 0.5, { opacity: isVisible, ease: Linear.easeNone }); -} - -function ShowMidRollCountdown(isVisible) { - let midRollContainer = document.getElementById("midRollContainer"); - let width = midRollContainer.getBoundingClientRect().width; - - var tl = new TimelineMax(); - - if (isVisible) - { - tl - .to(midRollContainer, 0.5, { right: "-10px", ease: Power1.easeInOut }) - } - else - { - tl - .to(midRollContainer, 0.5, { right: -width + "px", ease: Power1.easeInOut }) - } -} - - - -////////////////////// -// HELPER FUNCTIONS // -////////////////////// - -String.prototype.toHHMMSS = function () { - var sec_num = parseInt(this, 10); // don't forget the second param - var hours = Math.floor(sec_num / 3600); - var minutes = Math.floor((sec_num - (hours * 3600)) / 60); - var seconds = sec_num - (hours * 3600) - (minutes * 60); - - if (hours < 10) { hours = "0" + hours; } - //if (minutes < 10) {minutes = "0"+minutes;} - if (seconds < 10) { seconds = "0" + seconds; } - //return hours+':'+minutes+':'+seconds; - return minutes + ':' + seconds; -} - -function IsNullOrWhitespace(str) { - return /^\s*$/.test(str); -} - - - -/////////////////////////////////// -// STREAMER.BOT WEBSOCKET STATUS // -/////////////////////////////////// - -function SetConnectionStatus(connected) { - let statusContainer = document.getElementById("statusContainer"); - if (connected) { - statusContainer.style.background = "#2FB774"; - statusContainer.innerText = "Connected!"; - var tl = new TimelineMax(); - tl - .to(statusContainer, 2, { opacity: 0, ease: Linear.easeNone }) - //.call(removeElement, [div]); - } - else { - statusContainer.style.background = "#D12025"; - statusContainer.innerText = "Connecting..."; - statusContainer.style.opacity = 1; - } -} - -connectws(); \ No newline at end of file diff --git a/twitch-ad-timer/settings/settings.json b/twitch-ad-timer/settings/settings.json deleted file mode 100644 index 888bd57..0000000 --- a/twitch-ad-timer/settings/settings.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "settings": [ - { - "id": "address", - "label": "Address", - "description": "Streamer.bot Websocket Server Address", - "type": "text", - "defaultValue": "127.0.0.1", - "group": "Advanced" - }, - { - "id": "port", - "label": "Port", - "description": "Streamer.bot Websocket Server Port", - "type": "text", - "defaultValue": "8080", - "group": "Advanced" - } - ] -} \ No newline at end of file