mirror of
https://github.com/nuttylmao/nutty.gg.git
synced 2026-09-18 19:50:58 -04:00
Add files via upload
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="shortcut icon" href="#" />
|
||||
<link rel="stylesheet" href="./style.css" />
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@xz/fonts@1/serve/metropolis.min.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="statusContainer">Connecting...</div>
|
||||
<div id="mainContainer">
|
||||
<div id="timerBar"></div>
|
||||
</div>
|
||||
<div id="hugeTittiesContainer">
|
||||
<div id="adLabel">
|
||||
Ad
|
||||
</div>
|
||||
<div id="timerLabel">
|
||||
<span id="adsRemainingContainer"></span> • <span id="timerContainer"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="midRollContainer">
|
||||
<div id="midRollStartingInLabel">Ads starting in...</div>
|
||||
<div id="midRollCountdownContainer"></div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script src='https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/TweenMax.min.js'></script>
|
||||
<script src="./script.js"></script>
|
||||
@@ -0,0 +1,340 @@
|
||||
////////////////
|
||||
// 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();
|
||||
@@ -0,0 +1,86 @@
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#statusContainer {
|
||||
text-transform: uppercase;
|
||||
font-family: 'Metropolis';
|
||||
font-style: italic;
|
||||
font-weight: bold;
|
||||
font-size: 30px;
|
||||
width: 400px;
|
||||
max-width: fit-content;
|
||||
text-align: center;
|
||||
background-color: #D12025;
|
||||
color: white;
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
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 {
|
||||
width: 0px;
|
||||
background-color: #ffcc00;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#adLabel {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
max-width: fit-content;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
background-color: #F9BE2A;
|
||||
color: #1C1B22;
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
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 {
|
||||
font-family: 'Metropolis';
|
||||
font-size: 20px;
|
||||
max-width: fit-content;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
background-color: #000000CC;
|
||||
color: #FFFFFF;
|
||||
padding: 10px 20px;
|
||||
border-radius: 10px;
|
||||
display: table-cell;
|
||||
position: absolute;
|
||||
bottom: 15%;
|
||||
right: -100%;
|
||||
}
|
||||
|
||||
#midRollCountdownContainer {
|
||||
font-size: 40px;
|
||||
font-weight: bold;
|
||||
margin: 10px 0px 0px 0px;
|
||||
}
|
||||
Reference in New Issue
Block a user