shuffling, vr
This commit is contained in:
58
config.json
58
config.json
@@ -50,13 +50,13 @@
|
|||||||
],
|
],
|
||||||
"defaultPlaylist": "room-grind"
|
"defaultPlaylist": "room-grind"
|
||||||
},
|
},
|
||||||
"initialQueueSize": 10,
|
"initialQueueSize": 3,
|
||||||
"videoSceneName": "fgfm",
|
"videoSceneName": "fgfm",
|
||||||
"videoPollSize": 5,
|
"videoPollSize": 5,
|
||||||
"currentActivitySceneItemName": "now-showing-txt",
|
"currentActivitySceneItemName": "now-showing-txt",
|
||||||
"vods": [
|
"vods": [
|
||||||
{
|
{
|
||||||
"id": "ottas-seg-escape",
|
"id": "ot-seg-escape",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "Escape (OTTAS Seg)",
|
"chatName": "Escape (OTTAS Seg)",
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
"length": 352
|
"length": 352
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ottas-seg-eastern",
|
"id": "ot-seg-eastern",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "Eastern (OTTAS Seg)",
|
"chatName": "Eastern (OTTAS Seg)",
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
"length": 277
|
"length": 277
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ottas-seg-desert",
|
"id": "ot-seg-desert",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "Desert (OTTAS Seg)",
|
"chatName": "Desert (OTTAS Seg)",
|
||||||
@@ -98,7 +98,7 @@
|
|||||||
"length": 345
|
"length": 345
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ottas-seg-hera",
|
"id": "ot-seg-hera",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "Hera (OTTAS Seg)",
|
"chatName": "Hera (OTTAS Seg)",
|
||||||
@@ -112,7 +112,7 @@
|
|||||||
"length": 299
|
"length": 299
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ottas-seg-atower",
|
"id": "ot-seg-atower",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "ATower (OTTAS Seg)",
|
"chatName": "ATower (OTTAS Seg)",
|
||||||
@@ -126,7 +126,7 @@
|
|||||||
"length": 352
|
"length": 352
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ottas-seg-pod",
|
"id": "ot-seg-pod",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "PoD (OTTAS Seg)",
|
"chatName": "PoD (OTTAS Seg)",
|
||||||
@@ -140,7 +140,7 @@
|
|||||||
"length": 309
|
"length": 309
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ottas-seg-thieves",
|
"id": "ot-seg-thieves",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "Thieves (OTTAS Seg)",
|
"chatName": "Thieves (OTTAS Seg)",
|
||||||
@@ -154,7 +154,7 @@
|
|||||||
"length": 377
|
"length": 377
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ottas-seg-skull",
|
"id": "ot-seg-skull",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "Skull (OTTAS Seg)",
|
"chatName": "Skull (OTTAS Seg)",
|
||||||
@@ -168,7 +168,7 @@
|
|||||||
"length": 267
|
"length": 267
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ottas-seg-ice",
|
"id": "ot-seg-ice",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "Ice (OTTAS Seg)",
|
"chatName": "Ice (OTTAS Seg)",
|
||||||
@@ -182,7 +182,7 @@
|
|||||||
"length": 318
|
"length": 318
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ottas-seg-swamp",
|
"id": "ot-seg-swamp",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "Swamp (OTTAS Seg)",
|
"chatName": "Swamp (OTTAS Seg)",
|
||||||
@@ -196,7 +196,7 @@
|
|||||||
"length": 345
|
"length": 345
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ottas-seg-mire",
|
"id": "ot-seg-mire",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "Mire (OTTAS Seg)",
|
"chatName": "Mire (OTTAS Seg)",
|
||||||
@@ -210,7 +210,7 @@
|
|||||||
"length": 365
|
"length": 365
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ottas-seg-trock",
|
"id": "ot-seg-trock",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "TRock (OTTAS Seg)",
|
"chatName": "TRock (OTTAS Seg)",
|
||||||
@@ -224,7 +224,7 @@
|
|||||||
"length": 361
|
"length": 361
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ottas-seg-gtower",
|
"id": "ot-seg-gtower",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "GTower (OTTAS Seg)",
|
"chatName": "GTower (OTTAS Seg)",
|
||||||
@@ -238,7 +238,7 @@
|
|||||||
"length": 396
|
"length": 396
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ttas-seg-ganon",
|
"id": "ot-seg-ganon",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "Ganon (TTAS Seg)",
|
"chatName": "Ganon (TTAS Seg)",
|
||||||
@@ -252,7 +252,7 @@
|
|||||||
"length": 108
|
"length": 108
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "sttas-seg-escape",
|
"id": "st-seg-escape",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "Escape (STTAS Seg)",
|
"chatName": "Escape (STTAS Seg)",
|
||||||
@@ -266,7 +266,7 @@
|
|||||||
"length": 354
|
"length": 354
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "sttas-seg-eastern",
|
"id": "st-seg-eastern",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "Eastern (STTAS Seg)",
|
"chatName": "Eastern (STTAS Seg)",
|
||||||
@@ -280,7 +280,7 @@
|
|||||||
"length": 281
|
"length": 281
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "sttas-seg-desert",
|
"id": "st-seg-desert",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "Desert (STTAS Seg)",
|
"chatName": "Desert (STTAS Seg)",
|
||||||
@@ -294,7 +294,7 @@
|
|||||||
"length": 347
|
"length": 347
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "sttas-seg-hera",
|
"id": "st-seg-hera",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "Hera (STTAS Seg)",
|
"chatName": "Hera (STTAS Seg)",
|
||||||
@@ -308,7 +308,7 @@
|
|||||||
"length": 303
|
"length": 303
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "sttas-seg-atower",
|
"id": "st-seg-atower",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "Agah Tower (STTAS Seg)",
|
"chatName": "Agah Tower (STTAS Seg)",
|
||||||
@@ -322,7 +322,7 @@
|
|||||||
"length": 354
|
"length": 354
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "sttas-seg-pod",
|
"id": "st-seg-pod",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "PoD (STTAS Seg)",
|
"chatName": "PoD (STTAS Seg)",
|
||||||
@@ -336,7 +336,7 @@
|
|||||||
"length": 310
|
"length": 310
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "sttas-seg-thieves",
|
"id": "st-seg-thieves",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "Thieves (STTAS Seg)",
|
"chatName": "Thieves (STTAS Seg)",
|
||||||
@@ -350,7 +350,7 @@
|
|||||||
"length": 379
|
"length": 379
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "sttas-seg-skull",
|
"id": "st-seg-skull",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "Skull (STTAS Seg)",
|
"chatName": "Skull (STTAS Seg)",
|
||||||
@@ -364,7 +364,7 @@
|
|||||||
"length": 270
|
"length": 270
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "sttas-seg-ice",
|
"id": "st-seg-ice",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "Ice (STTAS Seg)",
|
"chatName": "Ice (STTAS Seg)",
|
||||||
@@ -378,7 +378,7 @@
|
|||||||
"length": 321
|
"length": 321
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "sttas-seg-swamp",
|
"id": "st-seg-swamp",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "Swamp (STTAS Seg)",
|
"chatName": "Swamp (STTAS Seg)",
|
||||||
@@ -392,7 +392,7 @@
|
|||||||
"length": 351
|
"length": 351
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "sttas-seg-mire",
|
"id": "st-seg-mire",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "Mire (STTAS Seg)",
|
"chatName": "Mire (STTAS Seg)",
|
||||||
@@ -406,7 +406,7 @@
|
|||||||
"length": 370
|
"length": 370
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "sttas-seg-trock",
|
"id": "st-seg-trock",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "TRock (STTAS Seg)",
|
"chatName": "TRock (STTAS Seg)",
|
||||||
@@ -420,7 +420,7 @@
|
|||||||
"length": 364
|
"length": 364
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "sttas-seg-gtower",
|
"id": "st-seg-gtower",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
"chatName": "GTower (STTAS Seg)",
|
"chatName": "GTower (STTAS Seg)",
|
||||||
@@ -711,7 +711,7 @@
|
|||||||
"scale.x": 1280
|
"scale.x": 1280
|
||||||
},
|
},
|
||||||
"sceneItem": "16x9ph",
|
"sceneItem": "16x9ph",
|
||||||
"length": 1349
|
"length": 1409
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "pb-ms",
|
"id": "pb-ms",
|
||||||
|
|||||||
125
twitch.js
125
twitch.js
@@ -3,19 +3,17 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// @TODO: modularize OBS and Twitch code
|
// @TODO: modularize OBS and Twitch code
|
||||||
// @TODO: Make the bot aware of what video is current active
|
|
||||||
// @TODO: Change video playlist source on an interval
|
|
||||||
// @TODO: Rotating background images (leftside)
|
// @TODO: Rotating background images (leftside)
|
||||||
// @TODO: Stream alerts for chat
|
// @TODO: Stream alerts for chat
|
||||||
// @TODO: Instead of playlists being chosen, have a database of files that can be played
|
// @TODO: Room vid requests / import
|
||||||
// dynamically load this into a single media source that hides itself after playback ends
|
// @TODO: Add random chance for room grind playlist to show for certain amount of time
|
||||||
// listen for the event of the video ending and switch the source to the next one in the queue
|
// ☐ add memes to commercial scene
|
||||||
//
|
// ☐ show commercials after a video length cap is hit -- show at conclusion of video
|
||||||
// We can have the video queue work a lot like the songrequest queue.
|
// ☐ add $setcurrent support (to update text label through obs websocket instead of chat)
|
||||||
// Instead of a new playlist being chosen every 2 hours, votes will be held for which *individual* video should be added to the queue next.
|
// ☐ update PB vod lengths to cut off before credits
|
||||||
// A list of 10 or so will be chosen at random to be voted on. The top (x) will be added to the video queue. If nothing gets voted on, something random gets added.
|
// ☐ support for $pause
|
||||||
// This will actually be easier on OBS too -- instead of having multiple playlists I have to manage within there, I can use a single media source and dynamically load whatever video gets chosen into that.
|
// ☐ remove currently playing video from vote choices
|
||||||
// I can also store whatever metadata about the video I want so I can update the labels automatically too. OpieOP
|
|
||||||
|
|
||||||
// Import modules
|
// Import modules
|
||||||
const irc = require('irc');
|
const irc = require('irc');
|
||||||
@@ -43,6 +41,7 @@ obs.connect({ address: config.obs.websocket.address, password: config.obs.websoc
|
|||||||
.catch(err => {
|
.catch(err => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Listen for errors from OBS
|
// Listen for errors from OBS
|
||||||
obs.on('error', err => {
|
obs.on('error', err => {
|
||||||
console.error('OBS socket error:', err);
|
console.error('OBS socket error:', err);
|
||||||
@@ -214,7 +213,7 @@ const twitchInit = (config, obs) => {
|
|||||||
|
|
||||||
// Listen for commands from everyone else
|
// Listen for commands from everyone else
|
||||||
if (commandNoPrefix === 'rngames') {
|
if (commandNoPrefix === 'rngames') {
|
||||||
twitchChat.say(to, snesGames.sort( function() { return 0.5 - Math.random() } ).slice(0, 10).join(' | '));
|
twitchChat.say(to, snesGames.sort( () => { return 0.5 - Math.random() } ).slice(0, 10).join(' | '));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -258,19 +257,34 @@ const twitchInit = (config, obs) => {
|
|||||||
const streamInit = (config, obs, twitch) => {
|
const streamInit = (config, obs, twitch) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
console.log(`Setting up initial video queue...`);
|
console.log(`Setting up initial video queue...`);
|
||||||
let videoQueue = config.vods.sort( function() { return 0.5 - Math.random() } ).slice(0, config.initialQueueSize);
|
let videoQueue = config.vods.sort( () => { return 0.5 - Math.random() } ).slice(0, config.initialQueueSize);
|
||||||
console.log(`Initial queue: ${videoQueue.map((c, i) => `[${i+1}] ${c.chatName}`).join(' | ')}`);
|
console.log(`Initial queue: ${videoQueue.map((c, i) => `[${i+1}] ${c.chatName}`).join(' | ')}`);
|
||||||
let currentVideo = videoQueue.shift();
|
let currentVideo = videoQueue.shift();
|
||||||
let videoTimer;
|
let videoTimer;
|
||||||
|
|
||||||
|
const nextVideo = () => {
|
||||||
|
// play the next video in the queue, or pick one at random if the queue is empty
|
||||||
|
if (videoQueue.length > 0) {
|
||||||
|
currentVideo = videoQueue.shift();
|
||||||
|
//console.log(`Playing next video in queue: ${JSON.stringify(currentVideo)}`);
|
||||||
|
} else {
|
||||||
|
currentVideo = config.vods.sort( () => { return 0.5 - Math.random() } ).slice(0, 1).shift();
|
||||||
|
//console.log(`Queue is empty, vod chosen at random for shuffle: ${JSON.stringify(currentVideo)}`);
|
||||||
|
}
|
||||||
|
showVideo(currentVideo);
|
||||||
|
};
|
||||||
|
|
||||||
const showVideo = video => {
|
const showVideo = video => {
|
||||||
|
//console.log(`Showing video: ${JSON.stringify(video)}`);
|
||||||
// set the file path
|
// set the file path
|
||||||
obs.setSourceSettings({"sourceName": video.sceneItem, "sourceSettings": {"local_file": video.filePath}})
|
obs.setSourceSettings({"sourceName": video.sceneItem, "sourceSettings": {"local_file": video.filePath}})
|
||||||
.then(data => {
|
.then(data => {
|
||||||
// show the video
|
// show the video
|
||||||
|
//console.log('local_file updated');
|
||||||
return obs.setSceneItemProperties({"item": video.sceneItem, "scene-name": config.videoSceneName, "visible": true});
|
return obs.setSceneItemProperties({"item": video.sceneItem, "scene-name": config.videoSceneName, "visible": true});
|
||||||
})
|
})
|
||||||
.then(data => {
|
.then(data => {
|
||||||
|
//console.log('scene item shown');
|
||||||
// update activity label and show/hide appropriately
|
// update activity label and show/hide appropriately
|
||||||
if (video.label !== false) {
|
if (video.label !== false) {
|
||||||
return obs.setTextGDIPlusProperties({"source": config.currentActivitySceneItemName, "scene-name": config.videoSceneName, "render": true, "text": video.label});
|
return obs.setTextGDIPlusProperties({"source": config.currentActivitySceneItemName, "scene-name": config.videoSceneName, "render": true, "text": video.label});
|
||||||
@@ -279,12 +293,12 @@ const streamInit = (config, obs, twitch) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(data => {
|
.then(data => {
|
||||||
|
//console.log('activity label updated');
|
||||||
// Set a timeout for hiding this at the end of the video and play the next video
|
// Set a timeout for hiding this at the end of the video and play the next video
|
||||||
videoTimer = setTimeout(() => {
|
videoTimer = setTimeout(() => {
|
||||||
obs.setSceneItemProperties({"item": video.sceneItem, "scene-name": config.videoSceneName, "visible": false})
|
obs.setSceneItemProperties({"item": video.sceneItem, "scene-name": config.videoSceneName, "visible": false})
|
||||||
.then(data => {
|
.then(data => {
|
||||||
currentVideo = videoQueue.shift();
|
nextVideo();
|
||||||
showVideo(currentVideo);
|
|
||||||
});
|
});
|
||||||
}, video.length*1000)
|
}, video.length*1000)
|
||||||
})
|
})
|
||||||
@@ -300,7 +314,7 @@ const streamInit = (config, obs, twitch) => {
|
|||||||
let rockTheVote = () => {};
|
let rockTheVote = () => {};
|
||||||
let rtvInterval = setInterval(() => {rockTheVote()}, 300000);
|
let rtvInterval = setInterval(() => {rockTheVote()}, 300000);
|
||||||
|
|
||||||
let videoVoteJob = schedule.scheduleJob("*/15 * * * *", () => {
|
let videoVoteJob = new schedule.Job(() => {
|
||||||
// Tally votes from previous election (if there was one), add the winner to the queue
|
// Tally votes from previous election (if there was one), add the winner to the queue
|
||||||
let winner;
|
let winner;
|
||||||
if (currentChoices.length > 0) {
|
if (currentChoices.length > 0) {
|
||||||
@@ -348,7 +362,7 @@ const streamInit = (config, obs, twitch) => {
|
|||||||
let inQueue = videoQueue.findIndex(q => q.id === e.id) !== -1;
|
let inQueue = videoQueue.findIndex(q => q.id === e.id) !== -1;
|
||||||
return !inQueue;
|
return !inQueue;
|
||||||
});
|
});
|
||||||
currentChoices = vodsNotInQueue.sort( function() { return 0.5 - Math.random() } ).slice(0, config.videoPollSize);
|
currentChoices = vodsNotInQueue.sort( () => { return 0.5 - Math.random() } ).slice(0, config.videoPollSize);
|
||||||
|
|
||||||
// Poll the chat
|
// Poll the chat
|
||||||
let chatChoices = currentChoices.map((c, i) => {
|
let chatChoices = currentChoices.map((c, i) => {
|
||||||
@@ -363,7 +377,6 @@ const streamInit = (config, obs, twitch) => {
|
|||||||
rtvInterval = setInterval(() => {rockTheVote()}, 300000);
|
rtvInterval = setInterval(() => {rockTheVote()}, 300000);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Track user votes for video queue
|
|
||||||
twitch.botChat.addListener('message', (from, to, message) => {
|
twitch.botChat.addListener('message', (from, to, message) => {
|
||||||
// Ignore everything from blacklisted users
|
// Ignore everything from blacklisted users
|
||||||
if (config.twitch.blacklistedUsers.includes(from)) return;
|
if (config.twitch.blacklistedUsers.includes(from)) return;
|
||||||
@@ -373,17 +386,55 @@ const streamInit = (config, obs, twitch) => {
|
|||||||
let commandParts = message.slice(config.twitch.cmdPrefix.length).split(' ');
|
let commandParts = message.slice(config.twitch.cmdPrefix.length).split(' ');
|
||||||
let commandNoPrefix = commandParts[0] || '';
|
let commandNoPrefix = commandParts[0] || '';
|
||||||
|
|
||||||
|
// ADMIN COMMANDS
|
||||||
if (config.twitch.admins.includes(from) || from === config.twitch.username.toLowerCase()) {
|
if (config.twitch.admins.includes(from) || from === config.twitch.username.toLowerCase()) {
|
||||||
|
// SKIP
|
||||||
if (commandNoPrefix === 'skip') {
|
if (commandNoPrefix === 'skip') {
|
||||||
|
//console.log(`admin is skipping video: ${JSON.stringify(currentVideo)}`);
|
||||||
clearTimeout(videoTimer);
|
clearTimeout(videoTimer);
|
||||||
obs.setSceneItemProperties({"item": currentVideo.sceneItem, "scene-name": config.videoSceneName, "visible": false})
|
obs.setSceneItemProperties({"item": currentVideo.sceneItem, "scene-name": config.videoSceneName, "visible": false})
|
||||||
.then(res => {
|
.then(res => {
|
||||||
currentVideo = videoQueue.shift();
|
nextVideo();
|
||||||
showVideo(currentVideo);
|
|
||||||
});
|
});
|
||||||
|
// ADD
|
||||||
|
} else if (commandNoPrefix === 'add') {
|
||||||
|
let requestedVideoId = commandParts[1] || false;
|
||||||
|
if (requestedVideoId === false) {
|
||||||
|
twitch.botChat.say(to, `Missing video ID`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure request vid isn't in the queue already
|
||||||
|
if (videoQueue.findIndex(e => e.id === requestedVideoId) !== -1) {
|
||||||
|
twitch.botChat.say(to, `That video is in the queue already!`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// search for req'd vid by id in config.vods
|
||||||
|
let vodIndex = config.vods.findIndex(e => e.id === requestedVideoId);
|
||||||
|
if (vodIndex === -1) {
|
||||||
|
twitch.botChat.say(to, `A video with that ID does not exist!`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add to queue if it exists
|
||||||
|
videoQueue.push(config.vods[vodIndex]);
|
||||||
|
twitch.botChat.say(to, `${config.vods[vodIndex].chatName} has been added to the queue [${videoQueue.length}]`);
|
||||||
|
return;
|
||||||
|
// START VOTE
|
||||||
|
} else if (commandNoPrefix === 'startvote') {
|
||||||
|
videoVoteJob.reschedule("*/15 * * * *");
|
||||||
|
twitch.botChat.say(to, `Voting has been started. Next run: ${videoVoteJob.nextInvocation()}`);
|
||||||
|
// PAUSE VOTE
|
||||||
|
} else if (commandNoPrefix === 'pausevote') {
|
||||||
|
clearInterval(rtvInterval);
|
||||||
|
videoVoteJob.cancel();
|
||||||
|
twitch.botChat.say(to, `Voting has been paused.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ALL USER COMMANDS
|
||||||
|
// VOTE FOR VIDEO
|
||||||
if (commandNoPrefix === 'vote') {
|
if (commandNoPrefix === 'vote') {
|
||||||
let userVote = commandParts[1] || false;
|
let userVote = commandParts[1] || false;
|
||||||
|
|
||||||
@@ -412,6 +463,7 @@ const streamInit = (config, obs, twitch) => {
|
|||||||
userVotes.push({"from": from, "vote": userVote});
|
userVotes.push({"from": from, "vote": userVote});
|
||||||
twitch.botChat.say(to, `@${from}, your vote has been logged!`);
|
twitch.botChat.say(to, `@${from}, your vote has been logged!`);
|
||||||
}
|
}
|
||||||
|
// QUEUE STATUS
|
||||||
} else if (commandNoPrefix === 'queue') {
|
} else if (commandNoPrefix === 'queue') {
|
||||||
if (videoQueue.length > 0) {
|
if (videoQueue.length > 0) {
|
||||||
let chatQueue = videoQueue.map((c, i) => {
|
let chatQueue = videoQueue.map((c, i) => {
|
||||||
@@ -421,8 +473,41 @@ const streamInit = (config, obs, twitch) => {
|
|||||||
} else {
|
} else {
|
||||||
twitch.botChat.say(to, `No videos currently in queue!`);
|
twitch.botChat.say(to, `No videos currently in queue!`);
|
||||||
}
|
}
|
||||||
|
// CURRENT VIDEO
|
||||||
} else if (commandNoPrefix === 'current') {
|
} else if (commandNoPrefix === 'current') {
|
||||||
twitch.botChat.say(to, `Now Playing: ${currentVideo.chatName}`);
|
twitch.botChat.say(to, `Now Playing: ${currentVideo.chatName}`);
|
||||||
|
// NEXT VIDEO
|
||||||
|
} else if (commandNoPrefix === 'next') {
|
||||||
|
if (videoQueue.length > 0) {
|
||||||
|
twitch.botChat.say(to, `Next Video: ${videoQueue[0].chatName}`);
|
||||||
|
} else {
|
||||||
|
twitch.botChat.say(to, `No videos currently in queue!`);
|
||||||
|
}
|
||||||
|
// VIDEO REQUEST
|
||||||
|
} else if (commandNoPrefix === 'vr') {
|
||||||
|
let requestedVideoId = commandParts[1] || false;
|
||||||
|
if (requestedVideoId === false) {
|
||||||
|
twitch.botChat.say(to, `Useage: ${config.twitch.cmdPrefix}vr <video-id> | Videos: https://pastebin.com/qv0wDkvB`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure request vid isn't in the queue already
|
||||||
|
if (videoQueue.findIndex(e => e.id === requestedVideoId) !== -1) {
|
||||||
|
twitch.botChat.say(to, `That video is in the queue already!`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// search for req'd vid by id in config.vods
|
||||||
|
let vodIndex = config.vods.findIndex(e => e.id === requestedVideoId);
|
||||||
|
if (vodIndex === -1) {
|
||||||
|
twitch.botChat.say(to, `A video with that ID does not exist!`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add to queue if it exists
|
||||||
|
videoQueue.push(config.vods[vodIndex]);
|
||||||
|
twitch.botChat.say(to, `${config.vods[vodIndex].chatName} has been added to the queue [${videoQueue.length}]`);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
66
vid-id-list
Executable file
66
vid-id-list
Executable file
@@ -0,0 +1,66 @@
|
|||||||
|
Request videos using $vr <video-id> where video-id is one of the following:
|
||||||
|
|
||||||
|
e.g. $vr st-seg-gtower
|
||||||
|
|
||||||
|
Optimal TTAS Segments
|
||||||
|
---------------------
|
||||||
|
ot-seg-escape
|
||||||
|
ot-seg-eastern
|
||||||
|
ot-seg-desert
|
||||||
|
ot-seg-hera
|
||||||
|
ot-seg-atower
|
||||||
|
ot-seg-pod
|
||||||
|
ot-seg-thieves
|
||||||
|
ot-seg-skull
|
||||||
|
ot-seg-ice
|
||||||
|
ot-seg-swamp
|
||||||
|
ot-seg-mire
|
||||||
|
ot-seg-trock
|
||||||
|
ot-seg-gtower
|
||||||
|
ot-seg-ganon
|
||||||
|
|
||||||
|
Safe/RTA Theory TAS Segments
|
||||||
|
----------------------------
|
||||||
|
st-seg-escape
|
||||||
|
st-seg-eastern
|
||||||
|
st-seg-desert
|
||||||
|
st-seg-hera
|
||||||
|
st-seg-atower
|
||||||
|
st-seg-pod
|
||||||
|
st-seg-thieves
|
||||||
|
st-seg-skull
|
||||||
|
st-seg-ice
|
||||||
|
st-seg-swamp
|
||||||
|
st-seg-mire
|
||||||
|
st-seg-trock
|
||||||
|
st-seg-gtower
|
||||||
|
|
||||||
|
NMG Golds
|
||||||
|
---------
|
||||||
|
nmg-gold-escape
|
||||||
|
nmg-gold-eastern
|
||||||
|
nmg-gold-desert
|
||||||
|
nmg-gold-hera
|
||||||
|
nmg-gold-atower
|
||||||
|
nmg-gold-pod
|
||||||
|
nmg-gold-thieves
|
||||||
|
nmg-gold-skull
|
||||||
|
nmg-gold-ice
|
||||||
|
nmg-gold-swamp
|
||||||
|
nmg-gold-mire
|
||||||
|
nmg-gold-trock
|
||||||
|
nmg-gold-gtower
|
||||||
|
nmg-gold-ganon
|
||||||
|
|
||||||
|
|
||||||
|
Personal Bests
|
||||||
|
--------------
|
||||||
|
pb-100-ahp
|
||||||
|
pb-ab
|
||||||
|
pb-ad
|
||||||
|
pb-any-nmg
|
||||||
|
pb-any-no-eg
|
||||||
|
pb-master-sword
|
||||||
|
pb-ms
|
||||||
|
pb-ms-no-eg
|
||||||
|
pb-rbo
|
||||||
Reference in New Issue
Block a user