convert to sugoi web services
This commit is contained in:
@@ -1,65 +1,24 @@
|
|||||||
<h1 align="center">Improved Twitch Subathon Countdown</h1>
|
# Improved Twitch Subathon Countdown
|
||||||
<p align="center">This is a Twitch Subathon Countdown originally by JayexDesigns.</p>
|
This is a Twitch Subathon Countdown originally by JayexDesigns.
|
||||||
<p align="center">The CSS Code is updated by Johnnycyan. The JS Files are updated by leabdd and danilotitato to add functionalities.</p>
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
<h2>Description</h2>
|
The CSS Code is updated by Johnnycyan.
|
||||||
<p>A subathon timer that increases when someone subscribes, donates money, donates bits or purchases streamloots chests.</p>
|
|
||||||
<p>Added is a Timer that gets saved (in localStorage) and can be reset.</p>
|
|
||||||
<p>When you open the index.html you get to chose between "Reset" or "Start".</p>
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
<h2>Shortcuts</h2>
|
The JS Files have been re-written by SugoiDogo.
|
||||||
<p>To pause the Timer: CTRL+ALT+P</p>
|
|
||||||
<p>To enable/disable Happy Hour: CTRL+ALT+H</p>
|
|
||||||
<p>To enable/disable Random Hour: CTRL+ALT+R</p>
|
|
||||||
<p>Shortcuts can be changed in config.js</p>
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
<h2>Preview</h2>
|
## Description
|
||||||
<h3 align="center"><img width="90%" src="./preview.webp"></h3>
|
A subathon timer that increases when someone subscribes, donates to your charity, donates bits, follows or raids.
|
||||||
<br/>
|
|
||||||
|
|
||||||
<h2>Usage</h2>
|
## Usage
|
||||||
<p>After cloning this repository you'll have to edit the "config.js" file with any plain text editor, then change the value of the variables according to what you want:</p>
|
Go to the [config page](https://sugoidogo.github.io/twitch-subathon-countdown/config.html), authorize the timer, and configure to your liking.
|
||||||
|
|
||||||
<h3>Twitch</h3>
|
## Support
|
||||||
<p>To get your Subs and Bits you just have to add your Channel Name.</p>
|
See [my github profile](https://github.com/sugoidogo)
|
||||||
|
|
||||||
<h3>Streamlabs Token</h3>
|
## Missing Features
|
||||||
<p>To get the token you'll have to go to the API settings tab of your <a href="https://streamlabs.com/dashboard#/settings/api-settings">Streamlabs dashboard</a> then click on API Tokens, copy your socket API token and finally paste the code on the "streamlabs_token" variable in the "config.js" file.</p>
|
The original version of this overlay included support for events from StreamElements, StreamLabs, and Streamloots,
|
||||||
<img src="./auth_streamlabs.png">
|
and the version this is forked from included additional features by leabdd and danilotitato,
|
||||||
|
such as Random Happy Hour and Bulk Events.
|
||||||
<h3>StreamElements Token</h3>
|
This fork is an almost total re-write of the core JS code behind the timer,
|
||||||
<p>To get the token you'll have to go to your <a href="https://streamelements.com/dashboard/account/channels">StreamElements channels dashboard</a>, then click on show secrets, copy the Overlay token and paste the code on the "streamelements_token" variable in the "config.js" file.</p>
|
so those features will also have to be re-written to be included in this fork.
|
||||||
<img src="./auth_streamelements.png">
|
Future versions of this timer will include a plug-in loader,
|
||||||
|
allowing additional features and event sources to be added without additional forking.
|
||||||
<h3>Streamloots Token</h3>
|
|
||||||
<p>To get the token you'll have to go to your Streamloots creator dashboard, then to alerts & widgets, then go to alerts, then copy the last part of the alerts url and finally paste the code on the "streamloots_token" variable in the "config.js" file.</p>
|
|
||||||
<img src="./auth_streamloots.png">
|
|
||||||
|
|
||||||
<h3>Initial Time</h3>
|
|
||||||
<p>You can set the initial time of the timer by setting the hours, minutes and seconds to be added when the timer is created.</p>
|
|
||||||
|
|
||||||
<h3>Random Happy Hour</h3>
|
|
||||||
<p>If this is true, you can turn enable Happy or Random Hour with the Shortcut. If it is false, the feature is disabled and cant be enabled.</p>
|
|
||||||
<p>You have to set the Happy Hour time values manually.</p>
|
|
||||||
<p>Random Hour has a bell curve which can be edited in the config. It multiplies the normal time by a random amount for each sub.</p>
|
|
||||||
<p>If enabled randHappy it can randomly activate the Happy Hour. It will last for one hour, but can be turned off manually with the Shortkey.</p>
|
|
||||||
<p>In the Config you can set a specific Date and Time. At that a Happy Hour will happen. scheduleHappy needs to be turned on.</p>
|
|
||||||
|
|
||||||
<h3>Bulk</h3>
|
|
||||||
<p>This enables that multiple Subs get added to the timer at once.</p>
|
|
||||||
<p>For Example when a user gifts 10 Subs.</p>
|
|
||||||
|
|
||||||
<h3>Full control on what to use</h3>
|
|
||||||
<p>You can enable and disable if you want to add time for Subscriptions, Bits, Donations or Chests.</p>
|
|
||||||
|
|
||||||
<h3>Other Values</h3>
|
|
||||||
<p>Change the other values to set the amount of seconds that will be added for the subscriptions, donations... And the minimum donation amounts to trigger the countdown increase.</p>
|
|
||||||
|
|
||||||
<h3>Add To OBS</h3>
|
|
||||||
<p>To add it to OBS you just have to drag the "index.html" file to the sources section or add a browser source that points to the "index.html" file.</p>
|
|
||||||
|
|
||||||
<h2>Known Problems</h2>
|
|
||||||
<p2>Only Streamelements Token in config.js does not add time for Subscriptions. Emulate with the Overlay Editor does work.</p>
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 78 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 70 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 20 KiB |
@@ -1,80 +0,0 @@
|
|||||||
// Happy Hour
|
|
||||||
var happy_hour = true // set to true or false, to enable/disable the happy hours function
|
|
||||||
var random_hour = true
|
|
||||||
var randHappy = false // only works if happy_hour = true
|
|
||||||
var scheduleHappy = false // only works if happy_hour = true
|
|
||||||
|
|
||||||
// needs scheduleHappy to be true
|
|
||||||
var scheduleHappyDay = 5 // Weekdays from 0 to 6 from Sunday to Saturday | Default 5 is Friday
|
|
||||||
var scheduleHappyHour = 18 // Hours in 24 format UTC Time | Default 18 is 20:00 CEST
|
|
||||||
|
|
||||||
// Bulk (if you want multiple subs to add to a big sum or each alone)
|
|
||||||
var bulk_enabled = false
|
|
||||||
|
|
||||||
//Shortcuts
|
|
||||||
var pauseShort = "ctrl+alt+p"
|
|
||||||
var happyHourShort = "ctrl+alt+h"
|
|
||||||
var randomHourShort = "ctrl+alt+r"
|
|
||||||
|
|
||||||
// Login Data
|
|
||||||
var twitch_channel_name = ""
|
|
||||||
var streamlabs_token = ""
|
|
||||||
var streamelements_token = ""
|
|
||||||
var streamloots_token = ""
|
|
||||||
|
|
||||||
// Initial Counter Config
|
|
||||||
var initialHoursConfig = 2
|
|
||||||
var initialMinutesConfig = 0
|
|
||||||
var initialSecondsConfig = 0
|
|
||||||
|
|
||||||
// Sync Time, amount of seconds it waits after the timer hit 0 to stop it. Useful for last Second Subs.
|
|
||||||
var syncTime = 2 // Default 2 seconds.
|
|
||||||
|
|
||||||
// Enable/Disable Subs, Bits, Donations, Chests
|
|
||||||
var subEnable = true
|
|
||||||
var bitEnable = false
|
|
||||||
var donationEnable = false
|
|
||||||
var chestEnable = false
|
|
||||||
|
|
||||||
// General Twitch, Streamlabs And StreamElements Config
|
|
||||||
var seconds_added_per_sub_prime = 60
|
|
||||||
var seconds_added_per_sub_tier1 = 60
|
|
||||||
var seconds_added_per_sub_tier2 = 180
|
|
||||||
var seconds_added_per_sub_tier3 = 480
|
|
||||||
|
|
||||||
var seconds_added_per_resub_prime = 60
|
|
||||||
var seconds_added_per_resub_tier1 = 60
|
|
||||||
var seconds_added_per_resub_tier2 = 180
|
|
||||||
var seconds_added_per_resub_tier3 = 480
|
|
||||||
|
|
||||||
var seconds_added_per_giftsub_tier1 = 60
|
|
||||||
var seconds_added_per_giftsub_tier2 = 180
|
|
||||||
var seconds_added_per_giftsub_tier3 = 480
|
|
||||||
|
|
||||||
var min_amount_of_bits = 50
|
|
||||||
var seconds_added_per_bits = 30
|
|
||||||
|
|
||||||
// Streamlabs And StreamElements Config
|
|
||||||
var min_donation_amount = 1
|
|
||||||
var seconds_added_per_donation = 30
|
|
||||||
|
|
||||||
// Streamloots Config
|
|
||||||
var min_amount_of_chests = 1
|
|
||||||
var seconds_added_per_chests = 30
|
|
||||||
|
|
||||||
|
|
||||||
// General Twitch, Streamlabs And StreamElements Config for Happy Hour
|
|
||||||
var factor_t1 = 1.5
|
|
||||||
var factor_t2 = 1.75
|
|
||||||
var factor_t3 = 2.0
|
|
||||||
var factor_bits = 1.5
|
|
||||||
var factor_donations = 1.5
|
|
||||||
|
|
||||||
|
|
||||||
// General Twitch, Streamlabs And StreamElements Config for Random Hour
|
|
||||||
// [min, max, skew]
|
|
||||||
var range_t1 = [0.1, 3, 1]
|
|
||||||
var range_t2 = [0.1, 3, 2]
|
|
||||||
var range_t3 = [0.1, 3, 3]
|
|
||||||
var range_bits = [0.1, 3, 1]
|
|
||||||
var range_donations = [0.1, 3, 1]
|
|
||||||
+22
-172
@@ -2,7 +2,8 @@
|
|||||||
font-family: 'Ubuntu', sans-serif !important;
|
font-family: 'Ubuntu', sans-serif !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
body, body * {
|
body,
|
||||||
|
body * {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: 'Manrope', sans-serif;
|
font-family: 'Manrope', sans-serif;
|
||||||
@@ -13,16 +14,12 @@ body {
|
|||||||
height: 100vh;
|
height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--background-color: #A020F0;
|
--background-color: #A020F0;
|
||||||
--shadow-color: #00000090;
|
--shadow-color: #00000090;
|
||||||
--text-color: #FFFFFF;
|
--text-color: #FFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#container {
|
#container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
@@ -30,63 +27,17 @@ body {
|
|||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
/*background-color: var(--background-color);*/
|
/*background-color: var(--background-color);*/
|
||||||
background-image:
|
background-image:
|
||||||
-webkit-linear-gradient(-45deg,
|
-webkit-linear-gradient(-45deg,
|
||||||
transparent 33%, rgba(0, 0, 0, .1) 33%,
|
transparent 33%, rgba(0, 0, 0, .1) 33%,
|
||||||
rgba(0,0, 0, .1) 66%, transparent 66%),
|
rgba(0, 0, 0, .1) 66%, transparent 66%),
|
||||||
-webkit-linear-gradient(top,
|
-webkit-linear-gradient(top,
|
||||||
rgba(255, 255, 255, .25),
|
rgba(255, 255, 255, .25),
|
||||||
rgba(0, 0, 0, .25)),
|
rgba(0, 0, 0, .25)),
|
||||||
-webkit-linear-gradient(left, #0074cc, #a700cc);
|
-webkit-linear-gradient(left, #0074cc, #a700cc);
|
||||||
box-shadow: 0 0 1.25rem 0.5rem var(--shadow-color);
|
box-shadow: 0 0 1.25rem 0.5rem var(--shadow-color);
|
||||||
width: 500px;
|
width: 500px;
|
||||||
height: 180px;
|
height: 180px;
|
||||||
border-radius: 30px;
|
border-radius: 30px;
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
#SpecialHourText {
|
|
||||||
opacity: 0;
|
|
||||||
font-size: 2.5rem;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* #HappyHourDeactive {
|
|
||||||
visibility: hidden;
|
|
||||||
font-size: 3rem;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#HappyHourError {
|
|
||||||
visibility: hidden;
|
|
||||||
font-size: 3rem;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
height: 100%;
|
|
||||||
} */
|
|
||||||
|
|
||||||
#SpecialHourHTML {
|
|
||||||
top:-200px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
#startPage {
|
|
||||||
position: absolute;
|
|
||||||
align-items: center;
|
|
||||||
top: 75%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
/*background-color: var(--background-color);*/
|
|
||||||
width: 150px;
|
|
||||||
height: 50px;
|
|
||||||
border-radius: 30px;
|
|
||||||
background:none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#textDiv {
|
#textDiv {
|
||||||
@@ -96,79 +47,6 @@ body {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
|
||||||
border-radius: 30px;
|
|
||||||
box-shadow: 0 0 1.25rem 0.5rem var(--shadow-color);
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
height: 100%;
|
|
||||||
width: 150px;
|
|
||||||
height: 50px;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
color:white;
|
|
||||||
/*background-image:
|
|
||||||
-webkit-linear-gradient(-45deg,
|
|
||||||
transparent 33%, rgba(0, 0, 0, .1) 33%,
|
|
||||||
rgba(0,0, 0, .1) 66%, transparent 66%),
|
|
||||||
-webkit-linear-gradient(top,
|
|
||||||
rgba(255, 255, 255, .25),
|
|
||||||
rgba(0, 0, 0, .25)),
|
|
||||||
-webkit-linear-gradient(left, #0074cc, #a700cc);*/
|
|
||||||
background:none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#firstButtonDiv, #secondButtonDiv {
|
|
||||||
background-image:
|
|
||||||
-webkit-linear-gradient(-45deg,
|
|
||||||
transparent 33%, rgba(0, 0, 0, .1) 33%,
|
|
||||||
rgba(0,0, 0, .1) 66%, transparent 66%),
|
|
||||||
-webkit-linear-gradient(top,
|
|
||||||
rgba(255, 255, 255, .25),
|
|
||||||
rgba(0, 0, 0, .25)),
|
|
||||||
-webkit-linear-gradient(left, #0074cc, #a700cc);
|
|
||||||
width: 150px;
|
|
||||||
height: 50px;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
#firstButtonDiv:hover, #secondButtonDiv:hover {
|
|
||||||
background-image:
|
|
||||||
-webkit-linear-gradient(-45deg,
|
|
||||||
transparent 33%, rgba(0, 0, 0, .1) 33%,
|
|
||||||
rgba(0,0, 0, .1) 66%, transparent 66%),
|
|
||||||
-webkit-linear-gradient(top,
|
|
||||||
rgba(255, 255, 255, .25),
|
|
||||||
rgba(0, 0, 0, .25)),
|
|
||||||
-webkit-linear-gradient(left, #0061ac, #8e00ad)!important;
|
|
||||||
}
|
|
||||||
|
|
||||||
#firstButtonDiv, #secondButtonDiv {
|
|
||||||
border-radius: 30px;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
height: 100%;
|
|
||||||
width: 150px;
|
|
||||||
height: 50px;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
color:white;
|
|
||||||
background-image:
|
|
||||||
-webkit-linear-gradient(-45deg,
|
|
||||||
transparent 33%, rgba(0, 0, 0, .1) 33%,
|
|
||||||
rgba(0,0, 0, .1) 66%, transparent 66%),
|
|
||||||
-webkit-linear-gradient(top,
|
|
||||||
rgba(255, 255, 255, .25),
|
|
||||||
rgba(0, 0, 0, .25)),
|
|
||||||
-webkit-linear-gradient(left, #0074cc, #a700cc);
|
|
||||||
}
|
|
||||||
|
|
||||||
#secondButtonDiv {
|
|
||||||
margin-top:10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
p {
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
font-size: 5.8rem;
|
font-size: 5.8rem;
|
||||||
@@ -176,54 +54,26 @@ p {
|
|||||||
text-shadow: 0px 0px 10px var(--shadow-color);
|
text-shadow: 0px 0px 10px var(--shadow-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas {
|
|
||||||
width: 500px;
|
|
||||||
height: 180px;
|
|
||||||
border-radius: 20px;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
z-index: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.addedTime {
|
.addedTime {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
opacity: 0;
|
|
||||||
display: none;
|
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 3.25rem;
|
font-size: 3.25rem;
|
||||||
/*color: var(--background-color);*/
|
color: white;
|
||||||
color:white;
|
animation: slidefadeout 2s ease-out;
|
||||||
transition: top 1s ease-out, opacity .5s ease-out;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gold {
|
@keyframes slidefadeout {
|
||||||
position: absolute;
|
0% {
|
||||||
top: 50%;
|
opacity: 1;
|
||||||
left: 50%;
|
top: 50%;
|
||||||
transform: translate(-50%, -50%);
|
}
|
||||||
opacity: 0;
|
100% {
|
||||||
display: none;
|
opacity: 0;
|
||||||
z-index: 5;
|
top: 25%;
|
||||||
font-weight: 400;
|
}
|
||||||
font-size: 3.25rem;
|
}
|
||||||
/*color: var(--background-color);*/
|
|
||||||
color:gold;
|
|
||||||
background: linear-gradient(to right, #BF953F, #FCF6BA, #B38728, #FBF5B7, #AA771C);
|
|
||||||
-webkit-background-clip: text;
|
|
||||||
-webkit-text-fill-color: transparent;
|
|
||||||
transition: top 1s ease-out, opacity .5s ease-out;
|
|
||||||
text-shadow:none !important;
|
|
||||||
}
|
|
||||||
-30
@@ -11,41 +11,11 @@
|
|||||||
<title>Subathon Timer</title>
|
<title>Subathon Timer</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="startPage">
|
|
||||||
<div id="firstButtonDiv">
|
|
||||||
<button id="resetBtn" class="button">Reset</button>
|
|
||||||
</div>
|
|
||||||
<div id="secondButtonDiv">
|
|
||||||
<button id="startBtn" class="button">Start</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="container" class="timer">
|
<div id="container" class="timer">
|
||||||
<div id="textDiv">
|
<div id="textDiv">
|
||||||
<p id="timeText">00:00:00</p>
|
<p id="timeText">00:00:00</p>
|
||||||
</div>
|
</div>
|
||||||
<div id="SpecialHourHTML">
|
|
||||||
<p id="SpecialHourText">Happy Hour Activated!</p>
|
|
||||||
<!-- <p id="SpecialHourDeactive">Happy Hour Deactivated :(</p>
|
|
||||||
<p id="SpecialHourError">Happy Hour not available D:</p> -->
|
|
||||||
</div>
|
|
||||||
<canvas id="canvas"></canvas>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="js/lib/mousetrap.min.js"></script>
|
|
||||||
<script src='https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js' type='text/javascript'></script>
|
|
||||||
<script src='js/lib/tmi.min.js'></script>
|
|
||||||
<script src="js/lib/generalFunc.js"></script>
|
|
||||||
<script src="js/lib/timeFunc.js"></script>
|
|
||||||
|
|
||||||
<script src="config.js"></script>
|
|
||||||
<script src="js/script.js"></script>
|
<script src="js/script.js"></script>
|
||||||
|
|
||||||
<script src="js/api/twitch.js"></script>
|
|
||||||
<!-- <script src="js/api/streamlabs.js"></script> -->
|
|
||||||
<script src="js/api/streamelements.js"></script>
|
|
||||||
<!-- <script src="js/api/streamloots.js"></script> -->
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
if (streamelements_token !== "") {
|
|
||||||
var streamElementsSocket;
|
|
||||||
const streamElementsConnect = () => {
|
|
||||||
streamElementsSocket = undefined;
|
|
||||||
streamElementsSocket = io('https://realtime.streamelements.com', {
|
|
||||||
transports: ['websocket']
|
|
||||||
});
|
|
||||||
|
|
||||||
streamElementsSocket.on('connect', onConnect);
|
|
||||||
streamElementsSocket.on('disconnect', onDisconnect);
|
|
||||||
streamElementsSocket.on('authenticated', onAuthenticated);
|
|
||||||
streamElementsSocket.on('unauthorized', console.error);
|
|
||||||
streamElementsSocket.on('event:test', onEvent);
|
|
||||||
streamElementsSocket.on('event', onEvent);
|
|
||||||
streamElementsSocket.on('event:update', onEvent);
|
|
||||||
streamElementsSocket.on('event:reset', onEvent);
|
|
||||||
|
|
||||||
function onConnect() {
|
|
||||||
logMessage("StreamElements", "Socket Connected");
|
|
||||||
streamElementsSocket.emit('authenticate', {method: 'apikey', token: streamelements_token});
|
|
||||||
}
|
|
||||||
|
|
||||||
function onDisconnect() {
|
|
||||||
logMessage("StreamElements", "Socket Disconnected");
|
|
||||||
streamElementsConnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
function onAuthenticated(data) {
|
|
||||||
const {
|
|
||||||
channelId
|
|
||||||
} = data;
|
|
||||||
logMessage("StreamElements", `Channel ${channelId} Connected`);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onEvent(data) {
|
|
||||||
logObject("StreamElements", data);
|
|
||||||
if (!countdownEnded) {
|
|
||||||
let factor_t1_local = (happy_hour_active ? factor_t1 : 1) * (random_hour_active ? randomBellSkew(...range_t1): 1);
|
|
||||||
let factor_t2_local = (happy_hour_active ? factor_t2 : 1) * (random_hour_active ? randomBellSkew(...range_t2): 1);
|
|
||||||
let factor_t3_local = (happy_hour_active ? factor_t3 : 1) * (random_hour_active ? randomBellSkew(...range_t3): 1);
|
|
||||||
let factor_bits_local = (happy_hour_active ? factor_bits : 1) * (random_hour_active ? randomBellSkew(...range_bits): 1);
|
|
||||||
let factor_donations_local = (happy_hour_active ? factor_donations : 1) * (random_hour_active ? randomBellSkew(...range_donations): 1);
|
|
||||||
|
|
||||||
if ((data['listener'] === "subscriber-latest") && subEnable) {
|
|
||||||
if (data['event']['gifted'] || data['event']['bulkGifted']) {
|
|
||||||
let amount;
|
|
||||||
if (data['event']['gifted']) amount = 1;
|
|
||||||
else amount = data['event']['amount'];
|
|
||||||
if (data['event']['tier'] == "prime" || data['event']['tier'] == "1000") {
|
|
||||||
addTime(endingTime, seconds_added_per_giftsub_tier1 * amount * factor_t1_local);
|
|
||||||
logMessage("StreamElements", `Added ${seconds_added_per_giftsub_tier1 * amount * factor_t1_local} Seconds Because ${data['event']['name']} Gifted ${amount} Tier 1 Subs`);
|
|
||||||
}
|
|
||||||
else if (data['event']['tier'] == "2000") {
|
|
||||||
addTime(endingTime, seconds_added_per_giftsub_tier2 * amount * factor_t2_local);
|
|
||||||
logMessage("StreamElements", `Added ${seconds_added_per_giftsub_tier2 * amount * factor_t2_local} Seconds Because ${data['event']['name']} Gifted ${amount} Tier 2 Subs`);
|
|
||||||
}
|
|
||||||
else if (data['event']['tier'] == "3000") {
|
|
||||||
addTime(endingTime, seconds_added_per_giftsub_tier3 * amount * factor_t3_local);
|
|
||||||
logMessage("StreamElements", `Added ${seconds_added_per_giftsub_tier3 * amount * factor_t3_local} Seconds Because ${data['event']['name']} Gifted ${amount} Tier 3 Subs`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (data['event']['amount'] != "1") {
|
|
||||||
if (data['event']['tier'] == "prime") {
|
|
||||||
addTime(endingTime, seconds_added_per_resub_prime * factor_t1_local);
|
|
||||||
logMessage("StreamElements", `Added ${seconds_added_per_resub_prime * factor_t1_local} Seconds Because ${data['event']['name']} ReSubscribed With Prime`);
|
|
||||||
}
|
|
||||||
else if (data['event']['tier'] == "1000") {
|
|
||||||
addTime(endingTime, seconds_added_per_resub_tier1 * factor_t1_local);
|
|
||||||
logMessage("StreamElements", `Added ${seconds_added_per_resub_tier1 * factor_t1_local} Seconds Because ${data['event']['name']} ReSubscribed With Tier 1`);
|
|
||||||
}
|
|
||||||
else if (data['event']['tier'] == "2000") {
|
|
||||||
addTime(endingTime, seconds_added_per_resub_tier2 * factor_t2_local);
|
|
||||||
logMessage("StreamElements", `Added ${seconds_added_per_resub_tier2 * factor_t2_local} Seconds Because ${data['event']['name']} ReSubscribed With Tier 2`);
|
|
||||||
}
|
|
||||||
else if (data['event']['tier'] == "3000") {
|
|
||||||
addTime(endingTime, seconds_added_per_resub_tier3 * factor_t3_local);
|
|
||||||
logMessage("StreamElements", `Added ${seconds_added_per_resub_tier3 * factor_t3_local} Seconds Because ${data['event']['name']} ReSubscribed With Tier 3`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (data['event']['tier'] == "prime") {
|
|
||||||
addTime(endingTime, seconds_added_per_sub_prime * factor_t1_local);
|
|
||||||
logMessage("StreamElements", `Added ${seconds_added_per_sub_prime * factor_t1_local} Seconds Because ${data['event']['name']} Subscribed With Prime`);
|
|
||||||
}
|
|
||||||
else if (data['event']['tier'] == "1000") {
|
|
||||||
addTime(endingTime, seconds_added_per_sub_tier1 * factor_t1_local);
|
|
||||||
logMessage("StreamElements", `Added ${seconds_added_per_sub_tier1 * factor_t1_local} Seconds Because ${data['event']['name']} Subscribed With Tier 1`);
|
|
||||||
}
|
|
||||||
else if (data['event']['tier'] == "2000") {
|
|
||||||
addTime(endingTime, seconds_added_per_sub_tier2 * factor_t2_local);
|
|
||||||
logMessage("StreamElements", `Added ${seconds_added_per_sub_tier2 * factor_t2_local} Seconds Because ${data['event']['name']} Subscribed With Tier 2`);
|
|
||||||
}
|
|
||||||
else if (data['event']['tier'] == "3000") {
|
|
||||||
addTime(endingTime, seconds_added_per_sub_tier3 * factor_t3_local);
|
|
||||||
logMessage("StreamElements", `Added ${seconds_added_per_sub_tier3 * factor_t3_local} Seconds Because ${data['event']['name']} Subscribed With Tier 3`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!users.includes(data['event']['name'])) {
|
|
||||||
users.push(data['event']['name']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if ((data['listener'] === "cheer-latest") && bitEnable) {
|
|
||||||
if (data['event']['amount'] >= min_amount_of_bits) {
|
|
||||||
let times = Math.floor(data['event']['amount']/min_amount_of_bits);
|
|
||||||
addTime(endingTime, seconds_added_per_bits * times * factor_bits_local);
|
|
||||||
logMessage("StreamElements", `Added ${seconds_added_per_bits * times * factor_bits_local} Seconds Because ${data['event']['name']} Donated ${data['event']['amount']} Bits`);
|
|
||||||
if (!users.includes(data['event']['name'])) {
|
|
||||||
users.push(data['event']['name']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if ((data['listener'] === "tip-latest") && donationEnable) {
|
|
||||||
if (data['event']['amount'] >= min_donation_amount) {
|
|
||||||
let times = Math.floor(data['event']['amount']/min_donation_amount);
|
|
||||||
addTime(endingTime, seconds_added_per_donation * times * factor_donations_local);
|
|
||||||
logMessage("StreamElements", `Added ${seconds_added_per_donation * times * factor_donations_local} Seconds Because ${data['event']['name']} Donated ${data['event']['amount']}$`);
|
|
||||||
if (!users.includes(data['event']['name'])) {
|
|
||||||
users.push(data['event']['name']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
streamElementsConnect();
|
|
||||||
}
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
if (streamlabs_token !== "") {
|
|
||||||
socket = io(`https://sockets.streamlabs.com?token=${streamlabs_token}`, {transports: ['websocket']});
|
|
||||||
|
|
||||||
socket.on("connect", () => {
|
|
||||||
logMessage("Streamlabs", "Socket Connected");
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on("event", (event) => {
|
|
||||||
logObject("Streamlabs", event);
|
|
||||||
let factor_t1_local = (happy_hour_active ? factor_t1 : 1) * (random_hour_active ? randomBellSkew(...range_t1): 1);
|
|
||||||
let factor_t2_local = (happy_hour_active ? factor_t2 : 1) * (random_hour_active ? randomBellSkew(...range_t2): 1);
|
|
||||||
let factor_t3_local = (happy_hour_active ? factor_t3 : 1) * (random_hour_active ? randomBellSkew(...range_t3): 1);
|
|
||||||
let factor_bits_local = (happy_hour_active ? factor_bits : 1) * (random_hour_active ? randomBellSkew(...range_bits): 1);
|
|
||||||
let factor_donations_local = (happy_hour_active ? factor_donations : 1) * (random_hour_active ? randomBellSkew(...range_donations): 1);
|
|
||||||
|
|
||||||
if (event.type == "subscription" && !event.message[0].gifter) {
|
|
||||||
if (!countdownEnded && subEnable) {
|
|
||||||
if (event.message[0].sub_plan == "1000") {
|
|
||||||
addTime(endingTime, seconds_added_per_sub_tier1 * factor_t1_local);
|
|
||||||
logMessage("Streamlabs", `Added ${seconds_added_per_sub_tier1 * factor_t1_local} Seconds Because ${event.message[0].name} Subscribed With Tier 1`);
|
|
||||||
}
|
|
||||||
else if (event.message[0].sub_plan == "2000") {
|
|
||||||
addTime(endingTime, seconds_added_per_sub_tier2 * factor_t2_local);
|
|
||||||
logMessage("Streamlabs", `Added ${seconds_added_per_sub_tier2 * factor_t2_local} Seconds Because ${event.message[0].name} Subscribed With Tier 2`);
|
|
||||||
}
|
|
||||||
else if (event.message[0].sub_plan == "3000") {
|
|
||||||
addTime(endingTime, seconds_added_per_sub_tier3 * factor_t3_local);
|
|
||||||
logMessage("Streamlabs", `Added ${seconds_added_per_sub_tier3 * factor_t3_local} Seconds Because ${event.message[0].name} Subscribed With Tier 3`);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
addTime(endingTime, seconds_added_per_sub_prime * factor_t1_local);
|
|
||||||
logMessage("Streamlabs", `Added ${seconds_added_per_sub_prime * factor_t1_local} Seconds Because ${event.message[0].name} Subscribed With Prime`);
|
|
||||||
}
|
|
||||||
if (!users.includes(event.message[0].name)) {
|
|
||||||
users.push(event.message[0].name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (event.type == "resub" && !event.message[0].gifter) {
|
|
||||||
if (!countdownEnded && subEnable) {
|
|
||||||
if (event.message[0].sub_plan == "1000") {
|
|
||||||
addTime(endingTime, seconds_added_per_resub_tier1 * factor_t1_local);
|
|
||||||
logMessage("Streamlabs", `Added ${seconds_added_per_resub_tier1 * factor_t1_local} Seconds Because ${event.message[0].name} ReSubscribed With Tier 1`);
|
|
||||||
}
|
|
||||||
else if (event.message[0].sub_plan == "2000") {
|
|
||||||
addTime(endingTime, seconds_added_per_resub_tier2 * factor_t2_local);
|
|
||||||
logMessage("Streamlabs", `Added ${seconds_added_per_resub_tier2 * factor_t2_local} Seconds Because ${event.message[0].name} ReSubscribed With Tier 2`);
|
|
||||||
}
|
|
||||||
else if (event.message[0].sub_plan == "3000") {
|
|
||||||
addTime(endingTime, seconds_added_per_resub_tier3 * factor_t3_local);
|
|
||||||
logMessage("Streamlabs", `Added ${seconds_added_per_resub_tier3 * factor_t3_local} Seconds Because ${event.message[0].name} ReSubscribed With Tier 3`);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
addTime(endingTime, seconds_added_per_resub_prime * factor_t1_local);
|
|
||||||
logMessage("Streamlabs", `Added ${seconds_added_per_resub_prime * factor_t1_local} Seconds Because ${event.message[0].name} ReSubscribed With Prime`);
|
|
||||||
}
|
|
||||||
if (!users.includes(event.message[0].name)) {
|
|
||||||
users.push(event.message[0].name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (event.message[0].gifter) {
|
|
||||||
if (!countdownEnded && subEnable) {
|
|
||||||
if (event.message[0].sub_plan == "1000") {
|
|
||||||
addTime(endingTime, seconds_added_per_giftsub_tier1 * factor_t1_local);
|
|
||||||
logMessage("Streamlabs", `Added ${seconds_added_per_giftsub_tier1 * factor_t1_local} Seconds Because ${event.message[0].gifter} Gifted A Tier 1 Sub`);
|
|
||||||
}
|
|
||||||
else if (event.message[0].sub_plan == "2000") {
|
|
||||||
addTime(endingTime, seconds_added_per_giftsub_tier2 * factor_t2_local);
|
|
||||||
logMessage("Streamlabs", `Added ${seconds_added_per_giftsub_tier2 * factor_t2_local} Seconds Because ${event.message[0].gifter} Gifted A Tier 2 Sub`);
|
|
||||||
}
|
|
||||||
else if (event.message[0].sub_plan == "3000") {
|
|
||||||
addTime(endingTime, seconds_added_per_giftsub_tier3 * factor_t3_local);
|
|
||||||
logMessage("Streamlabs", `Added ${seconds_added_per_giftsub_tier3 * factor_t3_local} Seconds Because ${event.message[0].gifter} Gifted A Tier 3 Sub`);
|
|
||||||
}
|
|
||||||
if (!users.includes(event.message[0].name)) {
|
|
||||||
users.push(event.message[0].name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (event.type == "donation") {
|
|
||||||
if (!countdownEnded && donationEnable) {
|
|
||||||
let dono = parseInt(event.message[0].amount);
|
|
||||||
let currency = event.message[0].currency;
|
|
||||||
if (dono >= min_donation_amount) {
|
|
||||||
let times = Math.floor(dono/min_donation_amount);
|
|
||||||
addTime(endingTime, seconds_added_per_donation * times * factor_donations_local);
|
|
||||||
logMessage("Streamlabs", `Added ${seconds_added_per_donation * times} Seconds Because ${event.message[0].name} Donated ${dono} ${currency}`);
|
|
||||||
if (!users.includes(event.message[0].name)) {
|
|
||||||
users.push(event.message[0].name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (event.type == "bits") {
|
|
||||||
if (!countdownEnded && donationEnable) {
|
|
||||||
let bits = parseInt(event.message[0].amount);
|
|
||||||
if (bits >= min_amount_of_bits) {
|
|
||||||
let times = Math.floor(bits/min_amount_of_bits);
|
|
||||||
addTime(endingTime, seconds_added_per_bits * times);
|
|
||||||
logMessage("Streamlabs", `Added ${seconds_added_per_bits * times * factor_bits_local} Seconds Because ${event.message[0].name} Donated ${bits} Bits`);
|
|
||||||
if (!users.includes(event.message[0].name)) {
|
|
||||||
users.push(event.message[0].name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on("disconnect", () => {
|
|
||||||
logMessage("Streamlabs", "Socket Disconnected");
|
|
||||||
socket.connect();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
if (streamloots_token !== "") {
|
|
||||||
evtSourceStreamLoots = new EventSource(`https://widgets.streamloots.com/alerts/${streamloots_token}/media-stream`);
|
|
||||||
logMessage("Streamloots", "Event Source Created");
|
|
||||||
|
|
||||||
evtSourceStreamLoots.onmessage = async (event) => {
|
|
||||||
data = await JSON.parse(event.data);
|
|
||||||
logObject("Streamloots", data);
|
|
||||||
if (data.data.type == "purchase") {
|
|
||||||
if (!countdownEnded && chestEnable) {
|
|
||||||
if(!happy_hour_active){
|
|
||||||
let chests;
|
|
||||||
if (typeof(data.data.fields[0].value) == "number") {
|
|
||||||
chests = data.data.fields[0].value;
|
|
||||||
if (chests >= min_amount_of_chests) {
|
|
||||||
let times = Math.floor(chests/min_amount_of_chests);
|
|
||||||
addTime(endingTime, seconds_added_per_chests * times);
|
|
||||||
logMessage("Streamloots", `Added ${seconds_added_per_chests * times} Seconds Because ${data.data.fields[1].value} Bought ${chests} Chests`);
|
|
||||||
if (!users.includes(data.data.fields[1].value)) {
|
|
||||||
users.push(data.data.fields[1].value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
chests = data.data.fields[1].value;
|
|
||||||
if (chests >= min_amount_of_chests) {
|
|
||||||
let times = Math.floor(chests/min_amount_of_chests);
|
|
||||||
addTime(endingTime, seconds_added_per_chests * times);
|
|
||||||
logMessage("Streamloots", `Added ${seconds_added_per_chests * times} Seconds Because ${data.data.fields[0].value} Gifted ${chests} Chests`);
|
|
||||||
if (!users.includes(data.data.fields[0].value)) {
|
|
||||||
users.push(data.data.fields[0].value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(happy_hour_active){
|
|
||||||
let chests;
|
|
||||||
if (typeof(data.data.fields[0].value) == "number") {
|
|
||||||
chests = data.data.fields[0].value;
|
|
||||||
if (chests >= min_amount_of_chests) {
|
|
||||||
let times = Math.floor(chests/min_amount_of_chests);
|
|
||||||
addTime(endingTime, seconds_added_per_chests_happy * times);
|
|
||||||
logMessage("Streamloots", `Added ${seconds_added_per_chests_happy * times} Seconds Because ${data.data.fields[1].value} Bought ${chests} Chests`);
|
|
||||||
if (!users.includes(data.data.fields[1].value)) {
|
|
||||||
users.push(data.data.fields[1].value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
chests = data.data.fields[1].value;
|
|
||||||
if (chests >= min_amount_of_chests) {
|
|
||||||
let times = Math.floor(chests/min_amount_of_chests);
|
|
||||||
addTime(endingTime, seconds_added_per_chests_happy * times);
|
|
||||||
logMessage("Streamloots", `Added ${seconds_added_per_chests_happy * times} Seconds Because ${data.data.fields[0].value} Gifted ${chests} Chests`);
|
|
||||||
if (!users.includes(data.data.fields[0].value)) {
|
|
||||||
users.push(data.data.fields[0].value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
if (twitch_channel_name !== "") {
|
|
||||||
const client = new tmi.client({
|
|
||||||
connection: {
|
|
||||||
reconnect: true,
|
|
||||||
secure: true,
|
|
||||||
},
|
|
||||||
channels: [twitch_channel_name],
|
|
||||||
});
|
|
||||||
|
|
||||||
client.connect();
|
|
||||||
logMessage("Twitch", `Client Connected`);
|
|
||||||
|
|
||||||
client.on('subscription', (channel, username, methods, message, userstate) => {
|
|
||||||
if (!countdownEnded && subEnable) {
|
|
||||||
let factor_t1_local = (happy_hour_active ? factor_t1 : 1) * (random_hour_active ? randomBellSkew(...range_t1): 1);
|
|
||||||
let factor_t2_local = (happy_hour_active ? factor_t2 : 1) * (random_hour_active ? randomBellSkew(...range_t2): 1);
|
|
||||||
let factor_t3_local = (happy_hour_active ? factor_t3 : 1) * (random_hour_active ? randomBellSkew(...range_t3): 1);
|
|
||||||
|
|
||||||
switch (methods['plan']) {
|
|
||||||
case "Prime":
|
|
||||||
addTime(endingTime, seconds_added_per_sub_prime * factor_t1_local);
|
|
||||||
logMessage("Twitch", `Added ${seconds_added_per_sub_prime * factor_t1_local} Seconds Because ${username} Subscribed With Prime`);
|
|
||||||
break;
|
|
||||||
case "1000":
|
|
||||||
addTime(endingTime, seconds_added_per_sub_tier1 * factor_t1_local);
|
|
||||||
logMessage("Twitch", `Added ${seconds_added_per_sub_tier1 * factor_t1_local} Seconds Because ${username} Subscribed With Tier 1`);
|
|
||||||
break;
|
|
||||||
case "2000":
|
|
||||||
addTime(endingTime, seconds_added_per_sub_tier2 * factor_t2_local);
|
|
||||||
logMessage("Twitch", `Added ${seconds_added_per_sub_tier2 * factor_t2_local} Seconds Because ${username} Subscribed With Tier 2`);
|
|
||||||
break;
|
|
||||||
case "3000":
|
|
||||||
addTime(endingTime, seconds_added_per_sub_tier3 * factor_t3_local);
|
|
||||||
logMessage("Twitch", `Added ${seconds_added_per_sub_tier3 * factor_t3_local} Seconds Because ${username} Subscribed With Tier 3`);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!users.includes(username)) {
|
|
||||||
users.push(username);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on('resub', (channel, username, months, message, userstate, methods) => {
|
|
||||||
if (!countdownEnded && subEnable) {
|
|
||||||
let factor_t1_local = (happy_hour_active ? factor_t1 : 1) * (random_hour_active ? randomBellSkew(...range_t1): 1);
|
|
||||||
let factor_t2_local = (happy_hour_active ? factor_t2 : 1) * (random_hour_active ? randomBellSkew(...range_t2): 1);
|
|
||||||
let factor_t3_local = (happy_hour_active ? factor_t3 : 1) * (random_hour_active ? randomBellSkew(...range_t3): 1);
|
|
||||||
|
|
||||||
switch (methods['plan']) {
|
|
||||||
case "Prime":
|
|
||||||
addTime(endingTime, seconds_added_per_resub_prime * factor_t1_local);
|
|
||||||
logMessage("Twitch", `Added ${seconds_added_per_resub_prime * factor_t1_local} Seconds Because ${username} ReSubscribed With Prime`);
|
|
||||||
break;
|
|
||||||
case "1000":
|
|
||||||
addTime(endingTime, seconds_added_per_resub_tier1 * factor_t1_local);
|
|
||||||
logMessage("Twitch", `Added ${seconds_added_per_resub_tier1 * factor_t1_local} Seconds Because ${username} ReSubscribed With Tier 1`);
|
|
||||||
break;
|
|
||||||
case "2000":
|
|
||||||
addTime(endingTime, seconds_added_per_resub_tier2 * factor_t2_local);
|
|
||||||
logMessage("Twitch", `Added ${seconds_added_per_resub_tier2 * factor_t2_local} Seconds Because ${username} ReSubscribed With Tier 2`);
|
|
||||||
break;
|
|
||||||
case "3000":
|
|
||||||
addTime(endingTime, seconds_added_per_resub_tier3 * factor_t3_local);
|
|
||||||
logMessage("Twitch", `Added ${seconds_added_per_resub_tier3 * factor_t3_local} Seconds Because ${username} ReSubscribed With Tier 3`);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!users.includes(username)) {
|
|
||||||
users.push(username);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on('subgift', (channel, username, months, recipient, methods, userstate) => {
|
|
||||||
if (!countdownEnded && subEnable) {
|
|
||||||
let factor_t1_local = (happy_hour_active ? factor_t1 : 1) * (random_hour_active ? randomBellSkew(...range_t1): 1);
|
|
||||||
let factor_t2_local = (happy_hour_active ? factor_t2 : 1) * (random_hour_active ? randomBellSkew(...range_t2): 1);
|
|
||||||
let factor_t3_local = (happy_hour_active ? factor_t3 : 1) * (random_hour_active ? randomBellSkew(...range_t3): 1);
|
|
||||||
|
|
||||||
switch (methods['plan']) {
|
|
||||||
case "Prime":
|
|
||||||
addTime(endingTime, seconds_added_per_giftsub_prime * factor_t1_local);
|
|
||||||
logMessage("Twitch", `Added ${seconds_added_per_giftsub_prime * factor_t1_local} Seconds Because ${username} gifted Sub With Prime`);
|
|
||||||
break;
|
|
||||||
case "1000":
|
|
||||||
addTime(endingTime, seconds_added_per_giftsub_tier1 * factor_t1_local);
|
|
||||||
logMessage("Twitch", `Added ${seconds_added_per_giftsub_tier1 * factor_t1_local} Seconds Because ${username} gifted Sub With Tier 1`);
|
|
||||||
break;
|
|
||||||
case "2000":
|
|
||||||
addTime(endingTime, seconds_added_per_giftsub_tier2 * factor_t2_local);
|
|
||||||
logMessage("Twitch", `Added ${seconds_added_per_giftsub_tier2 * factor_t2_local} Seconds Because ${username} gifted Sub With Tier 2`);
|
|
||||||
break;
|
|
||||||
case "3000":
|
|
||||||
addTime(endingTime, seconds_added_per_giftsub_tier3 * factor_t3_local);
|
|
||||||
logMessage("Twitch", `Added ${seconds_added_per_giftsub_tier3 * factor_t3_local} Seconds Because ${username} gifted Sub With Tier 3`);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!users.includes(username)) {
|
|
||||||
users.push(username);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on('cheer', (channel, userstate, message) => {
|
|
||||||
if (!countdownEnded && bitEnable) {
|
|
||||||
let factor_bits_local = (happy_hour_active ? factor_bits : 1) * (random_hour_active ? randomBellSkew(...range_bits): 1);
|
|
||||||
|
|
||||||
if (userstate.bits >= min_amount_of_bits) {
|
|
||||||
let times = Math.floor(userstate.bits/min_amount_of_bits);
|
|
||||||
addTime(endingTime, seconds_added_per_bits * times * factor_bits_local);
|
|
||||||
logMessage("Twitch", `Added ${seconds_added_per_bits * times} Seconds Because ${userstate['display-name']} Donated ${userstate.bits} Bits`);
|
|
||||||
if (!users.includes(userstate['display-name'])) {
|
|
||||||
users.push(userstate['display-name']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
const sleep = (ms) => {
|
|
||||||
return new Promise(resolve => setTimeout(resolve, ms));
|
|
||||||
};
|
|
||||||
|
|
||||||
const randomInRange = (min, max) => {
|
|
||||||
return Math.floor(Math.random() * (max - min)) + min;
|
|
||||||
};
|
|
||||||
|
|
||||||
const randomBellSkew = (min, max, skew) => {
|
|
||||||
let u = 0, v = 0;
|
|
||||||
while(u === 0) u = Math.random() //Converting [0,1) to (0,1)
|
|
||||||
while(v === 0) v = Math.random()
|
|
||||||
let num = Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v )
|
|
||||||
|
|
||||||
num = num / 10.0 + 0.5 // Translate to 0 -> 1
|
|
||||||
if (num > 1 || num < 0)
|
|
||||||
num = randomBellSkew(min, max, skew) // resample between 0 and 1 if out of range
|
|
||||||
|
|
||||||
else{
|
|
||||||
num = Math.pow(num, skew) // Skew
|
|
||||||
num *= max - min // Stretch to fill range
|
|
||||||
num += min // offset to min
|
|
||||||
}
|
|
||||||
|
|
||||||
return num
|
|
||||||
}
|
|
||||||
|
|
||||||
const logMessage = (module, message) => {
|
|
||||||
console.log(`[${module}]: ${message}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
const logObject = (module, object) => {
|
|
||||||
console.log(`[${module}]: `, object);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
Vendored
-11
@@ -1,11 +0,0 @@
|
|||||||
/* mousetrap v1.6.5 craig.is/killing/mice */
|
|
||||||
(function(q,u,c){function v(a,b,g){a.addEventListener?a.addEventListener(b,g,!1):a.attachEvent("on"+b,g)}function z(a){if("keypress"==a.type){var b=String.fromCharCode(a.which);a.shiftKey||(b=b.toLowerCase());return b}return n[a.which]?n[a.which]:r[a.which]?r[a.which]:String.fromCharCode(a.which).toLowerCase()}function F(a){var b=[];a.shiftKey&&b.push("shift");a.altKey&&b.push("alt");a.ctrlKey&&b.push("ctrl");a.metaKey&&b.push("meta");return b}function w(a){return"shift"==a||"ctrl"==a||"alt"==a||
|
|
||||||
"meta"==a}function A(a,b){var g,d=[];var e=a;"+"===e?e=["+"]:(e=e.replace(/\+{2}/g,"+plus"),e=e.split("+"));for(g=0;g<e.length;++g){var m=e[g];B[m]&&(m=B[m]);b&&"keypress"!=b&&C[m]&&(m=C[m],d.push("shift"));w(m)&&d.push(m)}e=m;g=b;if(!g){if(!p){p={};for(var c in n)95<c&&112>c||n.hasOwnProperty(c)&&(p[n[c]]=c)}g=p[e]?"keydown":"keypress"}"keypress"==g&&d.length&&(g="keydown");return{key:m,modifiers:d,action:g}}function D(a,b){return null===a||a===u?!1:a===b?!0:D(a.parentNode,b)}function d(a){function b(a){a=
|
|
||||||
a||{};var b=!1,l;for(l in p)a[l]?b=!0:p[l]=0;b||(x=!1)}function g(a,b,t,f,g,d){var l,E=[],h=t.type;if(!k._callbacks[a])return[];"keyup"==h&&w(a)&&(b=[a]);for(l=0;l<k._callbacks[a].length;++l){var c=k._callbacks[a][l];if((f||!c.seq||p[c.seq]==c.level)&&h==c.action){var e;(e="keypress"==h&&!t.metaKey&&!t.ctrlKey)||(e=c.modifiers,e=b.sort().join(",")===e.sort().join(","));e&&(e=f&&c.seq==f&&c.level==d,(!f&&c.combo==g||e)&&k._callbacks[a].splice(l,1),E.push(c))}}return E}function c(a,b,c,f){k.stopCallback(b,
|
|
||||||
b.target||b.srcElement,c,f)||!1!==a(b,c)||(b.preventDefault?b.preventDefault():b.returnValue=!1,b.stopPropagation?b.stopPropagation():b.cancelBubble=!0)}function e(a){"number"!==typeof a.which&&(a.which=a.keyCode);var b=z(a);b&&("keyup"==a.type&&y===b?y=!1:k.handleKey(b,F(a),a))}function m(a,g,t,f){function h(c){return function(){x=c;++p[a];clearTimeout(q);q=setTimeout(b,1E3)}}function l(g){c(t,g,a);"keyup"!==f&&(y=z(g));setTimeout(b,10)}for(var d=p[a]=0;d<g.length;++d){var e=d+1===g.length?l:h(f||
|
|
||||||
A(g[d+1]).action);n(g[d],e,f,a,d)}}function n(a,b,c,f,d){k._directMap[a+":"+c]=b;a=a.replace(/\s+/g," ");var e=a.split(" ");1<e.length?m(a,e,b,c):(c=A(a,c),k._callbacks[c.key]=k._callbacks[c.key]||[],g(c.key,c.modifiers,{type:c.action},f,a,d),k._callbacks[c.key][f?"unshift":"push"]({callback:b,modifiers:c.modifiers,action:c.action,seq:f,level:d,combo:a}))}var k=this;a=a||u;if(!(k instanceof d))return new d(a);k.target=a;k._callbacks={};k._directMap={};var p={},q,y=!1,r=!1,x=!1;k._handleKey=function(a,
|
|
||||||
d,e){var f=g(a,d,e),h;d={};var k=0,l=!1;for(h=0;h<f.length;++h)f[h].seq&&(k=Math.max(k,f[h].level));for(h=0;h<f.length;++h)f[h].seq?f[h].level==k&&(l=!0,d[f[h].seq]=1,c(f[h].callback,e,f[h].combo,f[h].seq)):l||c(f[h].callback,e,f[h].combo);f="keypress"==e.type&&r;e.type!=x||w(a)||f||b(d);r=l&&"keydown"==e.type};k._bindMultiple=function(a,b,c){for(var d=0;d<a.length;++d)n(a[d],b,c)};v(a,"keypress",e);v(a,"keydown",e);v(a,"keyup",e)}if(q){var n={8:"backspace",9:"tab",13:"enter",16:"shift",17:"ctrl",
|
|
||||||
18:"alt",20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"ins",46:"del",91:"meta",93:"meta",224:"meta"},r={106:"*",107:"+",109:"-",110:".",111:"/",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},C={"~":"`","!":"1","@":"2","#":"3",$:"4","%":"5","^":"6","&":"7","*":"8","(":"9",")":"0",_:"-","+":"=",":":";",'"':"'","<":",",">":".","?":"/","|":"\\"},B={option:"alt",command:"meta","return":"enter",
|
|
||||||
escape:"esc",plus:"+",mod:/Mac|iPod|iPhone|iPad/.test(navigator.platform)?"meta":"ctrl"},p;for(c=1;20>c;++c)n[111+c]="f"+c;for(c=0;9>=c;++c)n[c+96]=c.toString();d.prototype.bind=function(a,b,c){a=a instanceof Array?a:[a];this._bindMultiple.call(this,a,b,c);return this};d.prototype.unbind=function(a,b){return this.bind.call(this,a,function(){},b)};d.prototype.trigger=function(a,b){if(this._directMap[a+":"+b])this._directMap[a+":"+b]({},a);return this};d.prototype.reset=function(){this._callbacks={};
|
|
||||||
this._directMap={};return this};d.prototype.stopCallback=function(a,b){if(-1<(" "+b.className+" ").indexOf(" mousetrap ")||D(b,this.target))return!1;if("composedPath"in a&&"function"===typeof a.composedPath){var c=a.composedPath()[0];c!==a.target&&(b=c)}return"INPUT"==b.tagName||"SELECT"==b.tagName||"TEXTAREA"==b.tagName||b.isContentEditable};d.prototype.handleKey=function(){return this._handleKey.apply(this,arguments)};d.addKeycodes=function(a){for(var b in a)a.hasOwnProperty(b)&&(n[b]=a[b]);p=null};
|
|
||||||
d.init=function(){var a=d(u),b;for(b in a)"_"!==b.charAt(0)&&(d[b]=function(b){return function(){return a[b].apply(a,arguments)}}(b))};d.init();q.Mousetrap=d;"undefined"!==typeof module&&module.exports&&(module.exports=d);"function"===typeof define&&define.amd&&define(function(){return d})}})("undefined"!==typeof window?window:null,"undefined"!==typeof window?document:null);
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
timeFunc = {
|
|
||||||
addHours(time, h) {
|
|
||||||
time.setTime(time.getTime() + (h * 60 * 60 * 1000));
|
|
||||||
return time;
|
|
||||||
},
|
|
||||||
|
|
||||||
addMinutes(time, m) {
|
|
||||||
time.setTime(time.getTime() + (m * 60 * 1000));
|
|
||||||
return time;
|
|
||||||
},
|
|
||||||
|
|
||||||
addSeconds (time, s) {
|
|
||||||
time.setTime(time.getTime() + (s * 1000));
|
|
||||||
return time;
|
|
||||||
},
|
|
||||||
|
|
||||||
getHours(time) {
|
|
||||||
let hours;
|
|
||||||
if (typeof time !== 'number') {
|
|
||||||
hours = time.getHours().toString();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
hours = Math.floor(time / (1000 * 60 * 60)).toString();
|
|
||||||
}
|
|
||||||
hours = (hours.length < 2) ? `0${hours}` : hours;
|
|
||||||
return hours;
|
|
||||||
},
|
|
||||||
|
|
||||||
getMinutes(time) {
|
|
||||||
let minutes;
|
|
||||||
if (typeof time !== 'number') {
|
|
||||||
minutes = time.getMinutes().toString();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
minutes = Math.floor((time % (1000 * 60 * 60)) / (1000 * 60)).toString();
|
|
||||||
}
|
|
||||||
minutes = (minutes.length < 2) ? `0${minutes}` : minutes;
|
|
||||||
return minutes;
|
|
||||||
},
|
|
||||||
|
|
||||||
getSeconds(time) {
|
|
||||||
let seconds;
|
|
||||||
if (typeof time !== 'number') {
|
|
||||||
seconds = time.getSeconds().toString();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
seconds = Math.floor((time % (1000 * 60)) / 1000).toString();
|
|
||||||
}
|
|
||||||
seconds = (seconds.length < 2) ? `0${seconds}` : seconds;
|
|
||||||
return seconds;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Vendored
-1
File diff suppressed because one or more lines are too long
+330
-264
@@ -1,296 +1,362 @@
|
|||||||
const timeText = document.getElementById("timeText");
|
const client_id='ib2n7v7mur7ab2mcxv7rjju2ctsyoi'
|
||||||
|
const message_ids=[]
|
||||||
|
const timer=document.querySelector('#timeText')
|
||||||
|
let tba,tokens,pubsub,ping_tid,pong_tid,eventsub,sse,time_started,time_passed,time_total,config,localforage
|
||||||
|
/** @type WebSocket */
|
||||||
|
let irc
|
||||||
|
|
||||||
var initialHours;
|
window.onanimationend=function(event){
|
||||||
var initialMinutes;
|
event.target.remove()
|
||||||
var initialSeconds;
|
|
||||||
var paused = false;
|
|
||||||
var happy_hour_active = false;
|
|
||||||
var random_hour_active = false;
|
|
||||||
let countdownEnded = false;
|
|
||||||
let countdownUpdater = null;
|
|
||||||
|
|
||||||
var initialHoursLocal = window.localStorage.getItem('initialHours')
|
|
||||||
if (initialHoursLocal !== null) {
|
|
||||||
initialHours = initialHoursLocal;
|
|
||||||
logMessage("Core", "Found initialHours in localStorage.")
|
|
||||||
} else {
|
|
||||||
initialHours = initialHoursConfig;
|
|
||||||
}
|
|
||||||
var initialMinutesLocal = window.localStorage.getItem('initialMinutes')
|
|
||||||
if (initialMinutesLocal !== null) {
|
|
||||||
initialMinutes = initialMinutesLocal;
|
|
||||||
logMessage("Core", "Found initialMinutes in localStorage.")
|
|
||||||
} else {
|
|
||||||
initialMinutes = initialMinutesConfig;
|
|
||||||
}
|
|
||||||
var initialSecondsLocal = window.localStorage.getItem('initialSeconds')
|
|
||||||
if (initialSecondsLocal !== null) {
|
|
||||||
initialSeconds = initialSecondsLocal;
|
|
||||||
logMessage("Core", "Found initialSeconds in localStorage.")
|
|
||||||
} else {
|
|
||||||
initialSeconds = initialSecondsConfig;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resetBtn.addEventListener("click", function(){
|
window.onload=async function(){
|
||||||
|
// init localforage
|
||||||
if (happy_hour_active) specialHourHandler('Happy');
|
localforage=(await import('https://cdn.jsdelivr.net/npm/localforage/+esm')).default
|
||||||
if (random_hour_active) specialHourHandler('Random');
|
localforage=localforage.createInstance({name:'sugoi-subathon-countdown'})
|
||||||
countdownEnded = false;
|
// init timer display
|
||||||
|
time_started=await localforage.getItem('time_started')
|
||||||
initialHours = initialHoursConfig;
|
time_passed=await localforage.getItem('time_passed')
|
||||||
initialMinutes = initialMinutesConfig;
|
time_total=await localforage.getItem('time_total')
|
||||||
initialSeconds = initialSecondsConfig;
|
updateTime()
|
||||||
|
// init twitch api tokens
|
||||||
let timeNow = new Date(Date.now());
|
tba=await import('https://tba.sugoidogo.com/tba.mjs')
|
||||||
|
tokens=await tba.get_tokens(client_id)
|
||||||
endingTime = timeFunc.addHours(timeNow, initialHours);
|
// load user config
|
||||||
endingTime = timeFunc.addMinutes(timeNow, initialMinutes);
|
load_config()
|
||||||
endingTime = timeFunc.addSeconds(timeNow, initialSeconds);
|
// init event sources
|
||||||
|
init_irc()
|
||||||
|
init_pubsub()
|
||||||
|
init_eventsub()
|
||||||
|
}
|
||||||
|
|
||||||
window.localStorage.removeItem('initialHours');
|
function handle_event(event_name,event_amount=1){
|
||||||
window.localStorage.removeItem('initialMinutes');
|
if(!config[event_name+'-time-enabled']){
|
||||||
window.localStorage.removeItem('initialSeconds');
|
return false
|
||||||
|
}
|
||||||
|
add_time(parseReadableTimeIntoMilliseconds(config[event_name+'-time'])*event_amount)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
logMessage("Core", "Timer Reset.");
|
function reset(){
|
||||||
});
|
localforage.removeItem('time_started')
|
||||||
|
localforage.removeItem('time_passed')
|
||||||
|
time_started=null
|
||||||
|
time_passed=null
|
||||||
|
time_total=parseReadableTimeIntoMilliseconds(config['start-time'])
|
||||||
|
localforage.setItem('time_total',time_total)
|
||||||
|
}
|
||||||
|
|
||||||
startBtn.addEventListener("click", function(){
|
function load_config(){
|
||||||
|
return fetch('https://ts.sugoidogo.com/config.json',{headers:tokens.auth_headers})
|
||||||
if (paused){
|
.then(response=>response.json())
|
||||||
var initialHoursLocal = window.localStorage.getItem('initialHours')
|
.then(json=>{
|
||||||
if (initialHoursLocal !== null) {
|
config=json
|
||||||
initialHours = initialHoursLocal;
|
if(!time_started && !time_passed){
|
||||||
logMessage("Core", "Found initialHours in localStorage.")
|
reset()
|
||||||
} else {
|
|
||||||
initialHours = initialHoursConfig;
|
|
||||||
}
|
}
|
||||||
var initialMinutesLocal = window.localStorage.getItem('initialMinutes')
|
})
|
||||||
if (initialMinutesLocal !== null) {
|
}
|
||||||
initialMinutes = initialMinutesLocal;
|
|
||||||
logMessage("Core", "Found initialMinutes in localStorage.")
|
function add_time(time){
|
||||||
} else {
|
if(config['max-time-enabled']){
|
||||||
initialMinutes = initialMinutesConfig;
|
const new_time=time_total+time
|
||||||
}
|
const max_time=parseReadableTimeIntoMilliseconds(config['max-time'])
|
||||||
var initialSecondsLocal = window.localStorage.getItem('initialSeconds')
|
if(new_time>max_time){
|
||||||
if (initialSecondsLocal !== null) {
|
time=max_time-time_total
|
||||||
initialSeconds = initialSecondsLocal;
|
|
||||||
logMessage("Core", "Found initialSeconds in localStorage.")
|
|
||||||
} else {
|
|
||||||
initialSeconds = initialSecondsConfig;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let addedTime=document.createElement('p')
|
||||||
let timeNow = new Date(Date.now());
|
let timeString=parseMillisecondsIntoReadableTime(time)
|
||||||
|
if(time>0){
|
||||||
document.getElementById("startPage").style.visibility = "hidden";
|
timeString='+'+timeString
|
||||||
document.getElementById("container").style.visibility = "visible";
|
|
||||||
|
|
||||||
endingTime = timeFunc.addHours(timeNow, initialHours);
|
|
||||||
endingTime = timeFunc.addMinutes(timeNow, initialMinutes);
|
|
||||||
endingTime = timeFunc.addSeconds(timeNow, initialSeconds);
|
|
||||||
|
|
||||||
paused = false;
|
|
||||||
|
|
||||||
countdownUpdater = setInterval(() => {
|
|
||||||
getNextTime();
|
|
||||||
}, 1);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
Mousetrap.bind(pauseShort, function(e) {
|
|
||||||
paused = true;
|
|
||||||
logMessage("Core", "Timer was paused");
|
|
||||||
document.getElementById("startPage").style.visibility = "visible";
|
|
||||||
document.getElementById("container").style.visibility = "hidden";
|
|
||||||
clearInterval(countdownUpdater);
|
|
||||||
});
|
|
||||||
|
|
||||||
Mousetrap.bind(happyHourShort, async function(e){
|
|
||||||
specialHourHandler('Happy');
|
|
||||||
});
|
|
||||||
|
|
||||||
Mousetrap.bind(randomHourShort, async function(e){
|
|
||||||
specialHourHandler('Random');
|
|
||||||
});
|
|
||||||
|
|
||||||
async function specialHourHandler(type){
|
|
||||||
if ((type === 'Happy' && happy_hour) || (type === 'Random' && random_hour)){
|
|
||||||
specialHourFunc(type)
|
|
||||||
}
|
}
|
||||||
else {
|
if(time==0){
|
||||||
logMessage("Core", `${type} Hour is not available`)
|
timeString='Timer Maxed!'
|
||||||
document.getElementById("SpecialHourText").innerHTML = `${type} Hour error`;
|
|
||||||
document.getElementById("SpecialHourText").animate({opacity: [ 0, 1 ], easing: [ 'ease-in', 'ease-out' ],}, 500);
|
|
||||||
document.getElementById("SpecialHourText").style.opacity = "1";
|
|
||||||
document.getElementById("SpecialHourHTML").animate({top: [ "-200px", "-250px" ], easing: [ 'ease-in', 'ease-out' ],}, 500);
|
|
||||||
document.getElementById("SpecialHourHTML").style.top = "-250px";
|
|
||||||
await sleep(5000)
|
|
||||||
document.getElementById("SpecialHourText").animate({opacity: [ 1, 0 ], easing: [ 'ease-in', 'ease-out' ],}, 500);
|
|
||||||
document.getElementById("SpecialHourText").style.opacity = "0";
|
|
||||||
}
|
}
|
||||||
|
addedTime.innerHTML=timeString
|
||||||
|
addedTime.className='addedTime'
|
||||||
|
document.body.appendChild(addedTime);
|
||||||
|
time_total+=time
|
||||||
|
localforage.setItem('time_total',time_total)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function specialHourFunc(type){
|
function start(){
|
||||||
let activate = ((type === 'Happy' && !happy_hour_active) || (type === 'Random' && !random_hour_active));
|
time_started=Date.now()
|
||||||
let toggleText = activate ? 'Activated' : 'Deactivated';
|
localforage.setItem('time_started',time_started)
|
||||||
|
|
||||||
logMessage("Core", `${type} Hour ${toggleText}`);
|
|
||||||
|
|
||||||
if (type === 'Happy') happy_hour_active = activate;
|
|
||||||
if (type === 'Random') random_hour_active = activate;
|
|
||||||
|
|
||||||
let animation = (happy_hour_active || random_hour_active) ? ', url(https://drive.google.com/uc?id=1oduFlPg84O1DliM5FsLvJJsnwZ4m1Vpm)' : '';
|
|
||||||
|
|
||||||
document.getElementById("SpecialHourText").innerHTML = `${type} Hour ${toggleText}!`;
|
|
||||||
document.getElementById("SpecialHourText").animate({opacity: [ 0, 1 ], easing: [ 'ease-in', 'ease-out' ],}, 500);
|
|
||||||
document.getElementById("SpecialHourText").style.opacity = "1";
|
|
||||||
|
|
||||||
document.getElementById("SpecialHourHTML").animate({top: [ "-200px", "-250px" ], easing: [ 'ease-in', 'ease-out' ],}, 500);
|
|
||||||
document.getElementById("SpecialHourHTML").style.top = "-250px";
|
|
||||||
|
|
||||||
document.getElementById("container").style.backgroundImage = `-webkit-linear-gradient(-45deg, transparent 33%, rgba(0, 0, 0, .1) 33%, rgba(0,0, 0, .1) 66%, transparent 66%), -webkit-linear-gradient(top, rgba(255, 255, 255, .25), rgba(0, 0, 0, .25))${animation}, -webkit-linear-gradient(left, #0074cc, #a700cc)`;
|
|
||||||
|
|
||||||
await sleep(activate ? 5000 : 10000);
|
|
||||||
|
|
||||||
document.getElementById("SpecialHourText").animate({opacity: [ 1, 0 ], easing: [ 'ease-in', 'ease-out' ],}, 500);
|
|
||||||
document.getElementById("SpecialHourText").style.opacity = "0";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let users = [];
|
function pause(){
|
||||||
let time;
|
time_passed+=Date.now()-time_started
|
||||||
|
time_started=null
|
||||||
let endingTime = new Date(Date.now());
|
localforage.removeItem('time_started')
|
||||||
endingTime = timeFunc.addHours(endingTime, initialHours);
|
localforage.setItem('time_passed',time_passed)
|
||||||
endingTime = timeFunc.addMinutes(endingTime, initialMinutes);
|
|
||||||
endingTime = timeFunc.addSeconds(endingTime, initialSeconds);
|
|
||||||
|
|
||||||
function getRandomInt(min, max) {
|
|
||||||
min = Math.ceil(min);
|
|
||||||
max = Math.floor(max);
|
|
||||||
return Math.floor(Math.random() * (max - min)) + min;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var randomHappyBool = false
|
// https://stackoverflow.com/a/33909506
|
||||||
var scheduleHappyBool = false
|
function parseMillisecondsIntoReadableTime(milliseconds){
|
||||||
|
let negative=false
|
||||||
const getNextTime = () => {
|
if(milliseconds<0){
|
||||||
|
milliseconds=Math.abs(milliseconds)
|
||||||
let currentTime = new Date(Date.now());
|
negative=true
|
||||||
let differenceTime = endingTime - currentTime;
|
|
||||||
time = `${timeFunc.getHours(differenceTime)}:${timeFunc.getMinutes(differenceTime)}:${timeFunc.getSeconds(differenceTime)}`;
|
|
||||||
if (differenceTime <= 0) {
|
|
||||||
time = "00:00:00";
|
|
||||||
if (differenceTime <= (syncTime * 1000 * -1)) {
|
|
||||||
clearInterval(countdownUpdater);
|
|
||||||
countdownEnded = true;
|
|
||||||
logMessage("Core", "Timer Ended");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!paused){
|
|
||||||
window.localStorage.setItem('initialHours', timeFunc.getHours(differenceTime));
|
|
||||||
window.localStorage.setItem('initialMinutes', timeFunc.getMinutes(differenceTime));
|
|
||||||
window.localStorage.setItem('initialSeconds', timeFunc.getSeconds(differenceTime));
|
|
||||||
|
|
||||||
if (randHappy && happy_hour && !randomHappyBool){
|
//Get hours from milliseconds
|
||||||
randomHappyBool = true
|
var hours = milliseconds / (1000*60*60);
|
||||||
setTimeout(randomHappy,1000)
|
var absoluteHours = Math.floor(hours);
|
||||||
}
|
var h = absoluteHours > 9 ? absoluteHours : '0' + absoluteHours;
|
||||||
if (scheduleHappy && happy_hour && !scheduleHappyBool){
|
|
||||||
scheduleHappyBool = true
|
|
||||||
scheduleHappyFunc()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
timeText.innerText = time;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
function randomHappy(){
|
//Get remainder from hours and convert to minutes
|
||||||
if (!happy_hour_active){
|
var minutes = (hours - absoluteHours) * 60;
|
||||||
if ((getRandomInt(0,10000) == 127)){
|
var absoluteMinutes = Math.floor(minutes);
|
||||||
logMessage("RandomHappy","It's not rigged!")
|
var m = absoluteMinutes > 9 ? absoluteMinutes : '0' + absoluteMinutes;
|
||||||
specialHourFunc()
|
|
||||||
setTimeout(specialHourFunc, 3600000)
|
//Get remainder from minutes and convert to seconds
|
||||||
}
|
var seconds = (minutes - absoluteMinutes) * 60;
|
||||||
setTimeout(randomHappy,1000)
|
var absoluteSeconds = Math.floor(seconds);
|
||||||
|
var s = absoluteSeconds > 9 ? absoluteSeconds : '0' + absoluteSeconds;
|
||||||
|
|
||||||
|
let time = h + ':' + m + ':' + s;
|
||||||
|
|
||||||
|
if(negative){
|
||||||
|
time='-'+time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return time
|
||||||
}
|
}
|
||||||
|
|
||||||
function scheduleHappyFunc(){
|
function parseReadableTimeIntoMilliseconds(readableTime){
|
||||||
let now = new Date()
|
let negative=false
|
||||||
if (now.getDay() == scheduleHappyDay){
|
if(readableTime.startsWith('-')){
|
||||||
if (now.getUTCHours() == scheduleHappyHour){
|
negative=true
|
||||||
if (now.getUTCMinutes() == 00){
|
readableTime=readableTime.substring(1)
|
||||||
logMessage("Schedule","It's time!")
|
}
|
||||||
specialHourFunc()
|
const [seconds,minutes,hours]=readableTime.split(':').reverse()
|
||||||
setTimeout(specialHourFunc, 3600000)
|
let time=((hours||0)*1000*60*60)+((minutes||0)*1000*60)+((seconds||0)*1000)
|
||||||
setTimeout(scheduleHappyFunc, 36000000)
|
if(negative){
|
||||||
|
time=0-time
|
||||||
|
}
|
||||||
|
return time
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateTime(){
|
||||||
|
let time_remaining=time_total
|
||||||
|
if(time_passed){
|
||||||
|
time_remaining-=time_passed
|
||||||
|
}
|
||||||
|
if(time_started){
|
||||||
|
time_remaining-=Date.now()-time_started
|
||||||
|
}
|
||||||
|
timer.innerHTML=parseMillisecondsIntoReadableTime(time_remaining)
|
||||||
|
requestAnimationFrame(updateTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
function init_pubsub(){
|
||||||
|
if(pong_tid){
|
||||||
|
clearTimeout(pong_tid)
|
||||||
|
pong_tid=null
|
||||||
|
}
|
||||||
|
if(ping_tid){
|
||||||
|
clearTimeout(ping_tid)
|
||||||
|
ping_tid=null
|
||||||
|
}
|
||||||
|
if(pubsub){
|
||||||
|
pubsub.close()
|
||||||
|
}
|
||||||
|
pubsub=new WebSocket('wss://pubsub-edge.twitch.tv')
|
||||||
|
pubsub.onopen=function(){
|
||||||
|
pubsub.send(JSON.stringify({
|
||||||
|
"type":"LISTEN",
|
||||||
|
"data":{
|
||||||
|
"auth_token":tokens.access_token,
|
||||||
|
"topics":[
|
||||||
|
"channel-bits-events-v2."+tokens.user_id,
|
||||||
|
"channel-subscribe-events-v1."+tokens.user_id
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
pubsub.onmessage=function(event){
|
||||||
|
let message=JSON.parse(event.data)
|
||||||
|
console.debug(message)
|
||||||
|
switch(message.type){
|
||||||
|
case 'RESPONSE':{
|
||||||
|
if(message.error){
|
||||||
|
throw message.error
|
||||||
|
}
|
||||||
|
pubsub_ping()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'PONG':{
|
||||||
|
clearTimeout(pong_tid)
|
||||||
|
pong_tid=null
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'RECONNECT':{
|
||||||
|
init_pubsub()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'AUTH_REVOKED':{
|
||||||
|
location.reload()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'MESSAGE':{
|
||||||
|
message=message.data.message
|
||||||
|
if('sub_plan' in message){
|
||||||
|
handle_event('sub'+message.sub_plan)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if('bits_used' in message){
|
||||||
|
handle_bits('bit',message.bits_used)
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var firstSub = true;
|
function pubsub_ping(){
|
||||||
var endingTimeBeforeCounter;
|
pubsub.send(JSON.stringify({'type':'PING'}))
|
||||||
var addedTimeCounter;
|
const time=Math.floor(Math.random() * (5*60*1000))
|
||||||
var timeoutID;
|
ping_tid=setTimeout(pubsub_ping,time)
|
||||||
|
pong_tid=setTimeout(init_pubsub,20000)
|
||||||
const addTime = async (time, s) => {
|
|
||||||
let addedTime = Math.floor(s);
|
|
||||||
if (!bulk_enabled) {
|
|
||||||
endingTimeBeforeCounter = time;
|
|
||||||
addedTimeCounter = addedTime;
|
|
||||||
addTimeInternal();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (firstSub) {
|
|
||||||
firstSub = false;
|
|
||||||
endingTimeBeforeCounter = time;
|
|
||||||
addedTimeCounter = addedTime;
|
|
||||||
} else {
|
|
||||||
addedTimeCounter += addedTime;
|
|
||||||
window.clearTimeout(timeoutID);
|
|
||||||
}
|
|
||||||
timeoutID = window.setTimeout(addTimeInternal, 1000);
|
|
||||||
};
|
|
||||||
|
|
||||||
const addTimeInternal = async () => {
|
|
||||||
let time = endingTimeBeforeCounter;
|
|
||||||
let s = addedTimeCounter;
|
|
||||||
addedTimeCounter = 0;
|
|
||||||
firstSub = true;
|
|
||||||
|
|
||||||
let addedTime = document.createElement("p");
|
|
||||||
|
|
||||||
happy_hour_active ? addedTime.classList = "gold" : addedTime.classList = "addedTime";
|
|
||||||
|
|
||||||
addedTime.innerText = `+${s}s`;
|
|
||||||
document.body.appendChild(addedTime);
|
|
||||||
addedTime.style.display = "block";
|
|
||||||
await sleep(50);
|
|
||||||
addedTime.style.left = `${randomInRange(35, 65)}%`;
|
|
||||||
addedTime.style.top = `${randomInRange(15, 40)}%`;
|
|
||||||
addedTime.style.opacity = "1";
|
|
||||||
while (s > 0){
|
|
||||||
timeStep = s > 60 ? s/30 : 2
|
|
||||||
endingTime = timeFunc.addSeconds(time, timeStep)
|
|
||||||
await sleep(50);
|
|
||||||
s -= timeStep
|
|
||||||
}
|
|
||||||
await sleep(200);
|
|
||||||
addedTime.style.opacity = "0";
|
|
||||||
await sleep(200);
|
|
||||||
addedTime.remove();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const testAddTime = (times, delay, s) => {
|
function init_eventsub(){
|
||||||
let addTimeInterval = setInterval(async () => {
|
eventsub=new WebSocket('wss://eventsub.wss.twitch.tv/ws')
|
||||||
if (times > 0) {
|
eventsub.onmessage=function(event){
|
||||||
await sleep(randomInRange(50, delay-50));
|
let message=JSON.parse(event.data)
|
||||||
addTime(endingTime, s);
|
console.debug(message)
|
||||||
--times;
|
if(message.metadata.message_id in message_ids){
|
||||||
|
return
|
||||||
|
}else{
|
||||||
|
message_ids.push(message.metadata.message_id)
|
||||||
}
|
}
|
||||||
else {
|
switch(message.metadata.message_type){
|
||||||
clearInterval(addTimeInterval);
|
case 'session_welcome':{
|
||||||
|
let session_id=message.payload.session.id
|
||||||
|
const headers={'content-type':'application/json'}
|
||||||
|
Object.assign(headers,tokens.auth_headers)
|
||||||
|
const url=new URL('https://api.twitch.tv/helix/eventsub/subscriptions')
|
||||||
|
subscriptions=[
|
||||||
|
{
|
||||||
|
"type": "channel.follow",
|
||||||
|
"version": "2",
|
||||||
|
"condition": {
|
||||||
|
"broadcaster_user_id": tokens.user_id,
|
||||||
|
"moderator_user_id": tokens.user_id
|
||||||
|
},
|
||||||
|
"transport": {
|
||||||
|
"method": "websocket",
|
||||||
|
"session_id": session_id,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "channel.raid",
|
||||||
|
"version": "1",
|
||||||
|
"condition": {
|
||||||
|
"to_broadcaster_user_id": tokens.user_id
|
||||||
|
},
|
||||||
|
"transport": {
|
||||||
|
"method": "websocket",
|
||||||
|
"session_id": session_id,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "channel.charity_campaign.donate",
|
||||||
|
"version": "1",
|
||||||
|
"condition": {
|
||||||
|
"broadcaster_user_id": tokens.user_id
|
||||||
|
},
|
||||||
|
"transport": {
|
||||||
|
"method": "websocket",
|
||||||
|
"session_id": session_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
for(const subscription of subscriptions){
|
||||||
|
fetch(url,{
|
||||||
|
headers:headers,
|
||||||
|
method:"POST",
|
||||||
|
body:JSON.stringify(subscription)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'notification':{
|
||||||
|
switch(message.metadata.subscription_type){
|
||||||
|
case 'channel.follow':{
|
||||||
|
handle_event('follow')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'channel.raid':{
|
||||||
|
handle_event('raid')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'channel.charity_campaign.donate':{
|
||||||
|
handle_event('charity',message.event.amount.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, delay);
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
function ircSend(message){
|
||||||
|
console.debug('< '+message)
|
||||||
|
irc.send(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function init_irc(){
|
||||||
|
if(irc){
|
||||||
|
irc.close()
|
||||||
|
}
|
||||||
|
irc=new WebSocket('wss://irc-ws.chat.twitch.tv:443')
|
||||||
|
irc.onclose=init_irc
|
||||||
|
irc.onopen=function(){
|
||||||
|
ircSend('CAP REQ twitch.tv/tags')
|
||||||
|
ircSend('PASS oauth:'+tokens.access_token)
|
||||||
|
ircSend('NICK '+tokens.login)
|
||||||
|
ircSend('JOIN #'+tokens.login)
|
||||||
|
}
|
||||||
|
irc.onmessage=function(event){
|
||||||
|
console.log(event)
|
||||||
|
for(let data of event.data.split('\r\n')){
|
||||||
|
console.debug('> '+data)
|
||||||
|
/** @type string */
|
||||||
|
data=data.split(':')
|
||||||
|
const tags=data.shift()
|
||||||
|
const type=data.shift()
|
||||||
|
const message=data.join(':')
|
||||||
|
console.debug(tags,type,message)
|
||||||
|
if(!message){
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if(!(tags.includes('broadcaster') || tags.includes('moderator'))){
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const command=message.split(' ')
|
||||||
|
console.debug(command)
|
||||||
|
if(command.shift()!='!subathon'){
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
switch(command.shift()){
|
||||||
|
case 'start':{
|
||||||
|
start()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'pause':{
|
||||||
|
pause()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'reset':{
|
||||||
|
reset()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'add':{
|
||||||
|
add_time(parseReadableTimeIntoMilliseconds(command.shift()))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 10 MiB |
Reference in New Issue
Block a user