restructuring
This commit is contained in:
173
config.json
173
config.json
@@ -30,21 +30,25 @@
|
|||||||
{
|
{
|
||||||
"sceneItem": "ttas-segments",
|
"sceneItem": "ttas-segments",
|
||||||
"activity": "TTAS Segments !ttas",
|
"activity": "TTAS Segments !ttas",
|
||||||
|
"name": "TTAS Segments",
|
||||||
"chatName": "TTAS Segments"
|
"chatName": "TTAS Segments"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"sceneItem": "room-grind",
|
"sceneItem": "room-grind",
|
||||||
"activity": "TTAS Room Grind !ttas",
|
"activity": "TTAS Room Grind !ttas",
|
||||||
|
"name": "TTAS Room Grind",
|
||||||
"chatName": "TTAS Room Grind"
|
"chatName": "TTAS Room Grind"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"sceneItem": "gold-segments",
|
"sceneItem": "gold-segments",
|
||||||
"activity": "Any% NMG Gold Segments",
|
"activity": "Any% NMG Gold Segments",
|
||||||
|
"name": "NMG Golds",
|
||||||
"chatName": "NMG Golds"
|
"chatName": "NMG Golds"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"sceneItem": "personal-bests",
|
"sceneItem": "personal-bests",
|
||||||
"activity": "Past Personal Bests",
|
"activity": "Past Personal Bests",
|
||||||
|
"name": "Personal Bests",
|
||||||
"chatName": "Personal Bests"
|
"chatName": "Personal Bests"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -52,13 +56,16 @@
|
|||||||
},
|
},
|
||||||
"initialQueueSize": 3,
|
"initialQueueSize": 3,
|
||||||
"videoSceneName": "fgfm",
|
"videoSceneName": "fgfm",
|
||||||
|
"commercialSceneName": "commercial",
|
||||||
"videoPollSize": 5,
|
"videoPollSize": 5,
|
||||||
"currentActivitySceneItemName": "now-showing-txt",
|
"currentActivitySceneItemName": "now-showing-txt",
|
||||||
|
"commercialInterval": 60,
|
||||||
"vods": [
|
"vods": [
|
||||||
{
|
{
|
||||||
"id": "ot-seg-escape",
|
"id": "ot-seg-escape",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "Escape (OTTAS Seg)",
|
||||||
"chatName": "Escape (OTTAS Seg)",
|
"chatName": "Escape (OTTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\01-escape.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\01-escape.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -73,6 +80,7 @@
|
|||||||
"id": "ot-seg-eastern",
|
"id": "ot-seg-eastern",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "Eastern (OTTAS Seg)",
|
||||||
"chatName": "Eastern (OTTAS Seg)",
|
"chatName": "Eastern (OTTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\02-eastern.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\02-eastern.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -87,6 +95,7 @@
|
|||||||
"id": "ot-seg-desert",
|
"id": "ot-seg-desert",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "Desert (OTTAS Seg)",
|
||||||
"chatName": "Desert (OTTAS Seg)",
|
"chatName": "Desert (OTTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\03-desert.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\03-desert.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -101,6 +110,7 @@
|
|||||||
"id": "ot-seg-hera",
|
"id": "ot-seg-hera",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "Hera (OTTAS Seg)",
|
||||||
"chatName": "Hera (OTTAS Seg)",
|
"chatName": "Hera (OTTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\04-hera.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\04-hera.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -115,6 +125,7 @@
|
|||||||
"id": "ot-seg-atower",
|
"id": "ot-seg-atower",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "ATower (OTTAS Seg)",
|
||||||
"chatName": "ATower (OTTAS Seg)",
|
"chatName": "ATower (OTTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\05-atower.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\05-atower.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -129,6 +140,7 @@
|
|||||||
"id": "ot-seg-pod",
|
"id": "ot-seg-pod",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "PoD (OTTAS Seg)",
|
||||||
"chatName": "PoD (OTTAS Seg)",
|
"chatName": "PoD (OTTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\06-pod.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\06-pod.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -143,6 +155,7 @@
|
|||||||
"id": "ot-seg-thieves",
|
"id": "ot-seg-thieves",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "Thieves (OTTAS Seg)",
|
||||||
"chatName": "Thieves (OTTAS Seg)",
|
"chatName": "Thieves (OTTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\07-thieves.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\07-thieves.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -157,6 +170,7 @@
|
|||||||
"id": "ot-seg-skull",
|
"id": "ot-seg-skull",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "Skull (OTTAS Seg)",
|
||||||
"chatName": "Skull (OTTAS Seg)",
|
"chatName": "Skull (OTTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\08-skull.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\08-skull.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -171,6 +185,7 @@
|
|||||||
"id": "ot-seg-ice",
|
"id": "ot-seg-ice",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "Ice (OTTAS Seg)",
|
||||||
"chatName": "Ice (OTTAS Seg)",
|
"chatName": "Ice (OTTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\09-ice.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\09-ice.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -185,6 +200,7 @@
|
|||||||
"id": "ot-seg-swamp",
|
"id": "ot-seg-swamp",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "Swamp (OTTAS Seg)",
|
||||||
"chatName": "Swamp (OTTAS Seg)",
|
"chatName": "Swamp (OTTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\10-swamp.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\10-swamp.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -199,6 +215,7 @@
|
|||||||
"id": "ot-seg-mire",
|
"id": "ot-seg-mire",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "Mire (OTTAS Seg)",
|
||||||
"chatName": "Mire (OTTAS Seg)",
|
"chatName": "Mire (OTTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\11-mire.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\11-mire.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -213,6 +230,7 @@
|
|||||||
"id": "ot-seg-trock",
|
"id": "ot-seg-trock",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "TRock (OTTAS Seg)",
|
||||||
"chatName": "TRock (OTTAS Seg)",
|
"chatName": "TRock (OTTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\12-trock.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\12-trock.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -227,6 +245,7 @@
|
|||||||
"id": "ot-seg-gtower",
|
"id": "ot-seg-gtower",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "GTower (OTTAS Seg)",
|
||||||
"chatName": "GTower (OTTAS Seg)",
|
"chatName": "GTower (OTTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\13-gtower.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\13-gtower.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -241,6 +260,7 @@
|
|||||||
"id": "ot-seg-ganon",
|
"id": "ot-seg-ganon",
|
||||||
"category": "Optimal TTAS Segment",
|
"category": "Optimal TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "Ganon (TTAS Seg)",
|
||||||
"chatName": "Ganon (TTAS Seg)",
|
"chatName": "Ganon (TTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\14-ganon.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\Risky\\final-versions-timed\\14-ganon.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -255,6 +275,7 @@
|
|||||||
"id": "st-seg-escape",
|
"id": "st-seg-escape",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "Escape (STTAS Seg)",
|
||||||
"chatName": "Escape (STTAS Seg)",
|
"chatName": "Escape (STTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\01-escape.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\01-escape.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -269,6 +290,7 @@
|
|||||||
"id": "st-seg-eastern",
|
"id": "st-seg-eastern",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "Eastern (STTAS Seg)",
|
||||||
"chatName": "Eastern (STTAS Seg)",
|
"chatName": "Eastern (STTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\02-eastern.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\02-eastern.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -283,6 +305,7 @@
|
|||||||
"id": "st-seg-desert",
|
"id": "st-seg-desert",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "Desert (STTAS Seg)",
|
||||||
"chatName": "Desert (STTAS Seg)",
|
"chatName": "Desert (STTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\03-desert.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\03-desert.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -297,6 +320,7 @@
|
|||||||
"id": "st-seg-hera",
|
"id": "st-seg-hera",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "Hera (STTAS Seg)",
|
||||||
"chatName": "Hera (STTAS Seg)",
|
"chatName": "Hera (STTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\04-hera.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\04-hera.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -311,6 +335,7 @@
|
|||||||
"id": "st-seg-atower",
|
"id": "st-seg-atower",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "Agah Tower (STTAS Seg)",
|
||||||
"chatName": "Agah Tower (STTAS Seg)",
|
"chatName": "Agah Tower (STTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\05-atower.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\05-atower.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -325,6 +350,7 @@
|
|||||||
"id": "st-seg-pod",
|
"id": "st-seg-pod",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "PoD (STTAS Seg)",
|
||||||
"chatName": "PoD (STTAS Seg)",
|
"chatName": "PoD (STTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\06-pod.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\06-pod.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -339,6 +365,7 @@
|
|||||||
"id": "st-seg-thieves",
|
"id": "st-seg-thieves",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "Thieves (STTAS Seg)",
|
||||||
"chatName": "Thieves (STTAS Seg)",
|
"chatName": "Thieves (STTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\07-thieves.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\07-thieves.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -353,6 +380,7 @@
|
|||||||
"id": "st-seg-skull",
|
"id": "st-seg-skull",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "Skull (STTAS Seg)",
|
||||||
"chatName": "Skull (STTAS Seg)",
|
"chatName": "Skull (STTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\08-skull.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\08-skull.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -367,6 +395,7 @@
|
|||||||
"id": "st-seg-ice",
|
"id": "st-seg-ice",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "Ice (STTAS Seg)",
|
||||||
"chatName": "Ice (STTAS Seg)",
|
"chatName": "Ice (STTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\09-ice.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\09-ice.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -381,6 +410,7 @@
|
|||||||
"id": "st-seg-swamp",
|
"id": "st-seg-swamp",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "Swamp (STTAS Seg)",
|
||||||
"chatName": "Swamp (STTAS Seg)",
|
"chatName": "Swamp (STTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\10-swamp.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\10-swamp.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -395,6 +425,7 @@
|
|||||||
"id": "st-seg-mire",
|
"id": "st-seg-mire",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "Mire (STTAS Seg)",
|
||||||
"chatName": "Mire (STTAS Seg)",
|
"chatName": "Mire (STTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\11-mire.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\11-mire.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -409,6 +440,7 @@
|
|||||||
"id": "st-seg-trock",
|
"id": "st-seg-trock",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "TRock (STTAS Seg)",
|
||||||
"chatName": "TRock (STTAS Seg)",
|
"chatName": "TRock (STTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\12-trock.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\12-trock.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -423,6 +455,7 @@
|
|||||||
"id": "st-seg-gtower",
|
"id": "st-seg-gtower",
|
||||||
"category": "Safe TTAS Segment",
|
"category": "Safe TTAS Segment",
|
||||||
"label": false,
|
"label": false,
|
||||||
|
"name": "GTower (STTAS Seg)",
|
||||||
"chatName": "GTower (STTAS Seg)",
|
"chatName": "GTower (STTAS Seg)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\13-gtower.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\ttas\\RTA\\final-versions-timed\\13-gtower.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -437,6 +470,7 @@
|
|||||||
"id": "nmg-gold-escape",
|
"id": "nmg-gold-escape",
|
||||||
"category": "Any% NMG Gold Segment",
|
"category": "Any% NMG Gold Segment",
|
||||||
"label": "Any% NMG Gold Segment: Escape (5:53.2) [2018-02-24]",
|
"label": "Any% NMG Gold Segment: Escape (5:53.2) [2018-02-24]",
|
||||||
|
"name": "Escape (NMG Gold)",
|
||||||
"chatName": "Escape (NMG Gold)",
|
"chatName": "Escape (NMG Gold)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\01-[553.2]-2018-02-24-escape.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\01-[553.2]-2018-02-24-escape.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -451,6 +485,7 @@
|
|||||||
"id": "nmg-gold-eastern",
|
"id": "nmg-gold-eastern",
|
||||||
"category": "Any% NMG Gold Segment",
|
"category": "Any% NMG Gold Segment",
|
||||||
"label": "Any% NMG Gold Segment: Eastern (5:00.12) [2018-06-25]",
|
"label": "Any% NMG Gold Segment: Eastern (5:00.12) [2018-06-25]",
|
||||||
|
"name": "Eastern (NMG Gold)",
|
||||||
"chatName": "Eastern (NMG Gold)",
|
"chatName": "Eastern (NMG Gold)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\02-[500.12]-2018-06-25-eastern.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\02-[500.12]-2018-06-25-eastern.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -465,6 +500,7 @@
|
|||||||
"id": "nmg-gold-desert",
|
"id": "nmg-gold-desert",
|
||||||
"category": "Any% NMG Gold Segment",
|
"category": "Any% NMG Gold Segment",
|
||||||
"label": "Any% NMG Gold Segment: Desert (6:10.32) [2018-06-02]",
|
"label": "Any% NMG Gold Segment: Desert (6:10.32) [2018-06-02]",
|
||||||
|
"name": "Desert (NMG Gold)",
|
||||||
"chatName": "Desert (NMG Gold)",
|
"chatName": "Desert (NMG Gold)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\03-[610.32]-2018-06-02-desert.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\03-[610.32]-2018-06-02-desert.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -479,6 +515,7 @@
|
|||||||
"id": "nmg-gold-hera",
|
"id": "nmg-gold-hera",
|
||||||
"category": "Any% NMG Gold Segment",
|
"category": "Any% NMG Gold Segment",
|
||||||
"label": "Any% NMG Gold Segment: Hera (5:28.83) [2018-06-01]",
|
"label": "Any% NMG Gold Segment: Hera (5:28.83) [2018-06-01]",
|
||||||
|
"name": "Hera (NMG Gold)",
|
||||||
"chatName": "Hera (NMG Gold)",
|
"chatName": "Hera (NMG Gold)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\04-[528.83]-2018-06-01-hera.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\04-[528.83]-2018-06-01-hera.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -493,20 +530,22 @@
|
|||||||
"id": "nmg-gold-atower",
|
"id": "nmg-gold-atower",
|
||||||
"category": "Any% NMG Gold Segment",
|
"category": "Any% NMG Gold Segment",
|
||||||
"label": "Any% NMG Gold Segment: Agah Tower (5:13.45) [2018-09-07]",
|
"label": "Any% NMG Gold Segment: Agah Tower (5:13.45) [2018-09-07]",
|
||||||
|
"name": "Agah Tower (NMG Gold)",
|
||||||
"chatName": "Agah Tower (NMG Gold)",
|
"chatName": "Agah Tower (NMG Gold)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\05a-[513.45]-2018-09-07-atower.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\05a-[513.45]-2018-09-07-atower.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
"crop.left": 0,
|
"crop.left": 0,
|
||||||
"position.x": 320,
|
"position.x": 320,
|
||||||
"scale.x": 960
|
"scale.x": 960
|
||||||
},
|
},
|
||||||
"sceneItem": "4x3ph",
|
"sceneItem": "4x3ph",
|
||||||
"length": 315
|
"length": 314
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "nmg-gold-pod",
|
"id": "nmg-gold-pod",
|
||||||
"category": "Any% NMG Gold Segment",
|
"category": "Any% NMG Gold Segment",
|
||||||
"label": "Any% NMG Gold Segment: Palace of Darkness (6:11.15) [2018-05-27]",
|
"label": "Any% NMG Gold Segment: Palace of Darkness (6:11.15) [2018-05-27]",
|
||||||
|
"name": "PoD (NMG Gold)",
|
||||||
"chatName": "PoD (NMG Gold)",
|
"chatName": "PoD (NMG Gold)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\06-[611.15]-2018-05-27-pod.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\06-[611.15]-2018-05-27-pod.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -521,6 +560,7 @@
|
|||||||
"id": "nmg-gold-thieves",
|
"id": "nmg-gold-thieves",
|
||||||
"category": "Any% NMG Gold Segment",
|
"category": "Any% NMG Gold Segment",
|
||||||
"label": "Any% NMG Gold Segment: Thieves Town (7:08.37) [2018-07-01]",
|
"label": "Any% NMG Gold Segment: Thieves Town (7:08.37) [2018-07-01]",
|
||||||
|
"name": "Thieves (NMG Gold)",
|
||||||
"chatName": "Thieves (NMG Gold)",
|
"chatName": "Thieves (NMG Gold)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\07-[708.37]-2018-07-01-thieves.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\07-[708.37]-2018-07-01-thieves.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -535,6 +575,7 @@
|
|||||||
"id": "nmg-gold-skull",
|
"id": "nmg-gold-skull",
|
||||||
"category": "Any% NMG Gold Segment",
|
"category": "Any% NMG Gold Segment",
|
||||||
"label": "Any% NMG Gold Segment: Skull Woods (5:24.28) [2018-06-02]",
|
"label": "Any% NMG Gold Segment: Skull Woods (5:24.28) [2018-06-02]",
|
||||||
|
"name": "Skull (NMG Gold)",
|
||||||
"chatName": "Skull (NMG Gold)",
|
"chatName": "Skull (NMG Gold)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\08-[524.28]-2018-06-02-skull.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\08-[524.28]-2018-06-02-skull.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -549,20 +590,22 @@
|
|||||||
"id": "nmg-gold-ice",
|
"id": "nmg-gold-ice",
|
||||||
"category": "Any% NMG Gold Segment",
|
"category": "Any% NMG Gold Segment",
|
||||||
"label": "Any% NMG Gold Segment: Ice Palace (6:18.13) [2018-09-08]",
|
"label": "Any% NMG Gold Segment: Ice Palace (6:18.13) [2018-09-08]",
|
||||||
|
"name": "Ice (NMG Gold)",
|
||||||
"chatName": "Ice (NMG Gold)",
|
"chatName": "Ice (NMG Gold)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\09-[618.13]-2018-09-08-ice.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\09-[618.13]-2018-09-08-ice.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
"crop.left": 0,
|
"crop.left": 0,
|
||||||
"position.x": 320,
|
"position.x": 320,
|
||||||
"scale.x": 960
|
"scale.x": 960
|
||||||
},
|
},
|
||||||
"sceneItem": "4x3ph",
|
"sceneItem": "4x3ph",
|
||||||
"length": 382
|
"length": 379
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "nmg-gold-swamp",
|
"id": "nmg-gold-swamp",
|
||||||
"category": "Any% NMG Gold Segment",
|
"category": "Any% NMG Gold Segment",
|
||||||
"label": "Any% NMG Gold Segment: Swamp Palace (6:51.87) [2018-06-10]",
|
"label": "Any% NMG Gold Segment: Swamp Palace (6:51.87) [2018-06-10]",
|
||||||
|
"name": "Swamp (NMG Gold)",
|
||||||
"chatName": "Swamp (NMG Gold)",
|
"chatName": "Swamp (NMG Gold)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\10-[651.87]-2018-06-10-swamp.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\10-[651.87]-2018-06-10-swamp.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -577,6 +620,7 @@
|
|||||||
"id": "nmg-gold-mire",
|
"id": "nmg-gold-mire",
|
||||||
"category": "Any% NMG Gold Segment",
|
"category": "Any% NMG Gold Segment",
|
||||||
"label": "Any% NMG Gold Segment: Misery Mire (7:07.17) [2018-06-10]",
|
"label": "Any% NMG Gold Segment: Misery Mire (7:07.17) [2018-06-10]",
|
||||||
|
"name": "Mire (NMG Gold)",
|
||||||
"chatName": "Mire (NMG Gold)",
|
"chatName": "Mire (NMG Gold)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\11-[707.17]-2018-06-10-mire.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\11-[707.17]-2018-06-10-mire.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -591,6 +635,7 @@
|
|||||||
"id": "nmg-gold-trock",
|
"id": "nmg-gold-trock",
|
||||||
"category": "Any% NMG Gold Segment",
|
"category": "Any% NMG Gold Segment",
|
||||||
"label": "Any% NMG Gold Segment: Turtle Rock (7:07.34) [2018-06-25]",
|
"label": "Any% NMG Gold Segment: Turtle Rock (7:07.34) [2018-06-25]",
|
||||||
|
"name": "TRock (NMG Gold)",
|
||||||
"chatName": "TRock (NMG Gold)",
|
"chatName": "TRock (NMG Gold)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\12-[707.34]-2018-06-25-trock.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\12-[707.34]-2018-06-25-trock.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -605,6 +650,7 @@
|
|||||||
"id": "nmg-gold-gtower",
|
"id": "nmg-gold-gtower",
|
||||||
"category": "Any% NMG Gold Segment",
|
"category": "Any% NMG Gold Segment",
|
||||||
"label": "Any% NMG Gold Segment: Ganon's Tower (7:09.85) [2018-08-19]",
|
"label": "Any% NMG Gold Segment: Ganon's Tower (7:09.85) [2018-08-19]",
|
||||||
|
"name": "GTower (NMG Gold)",
|
||||||
"chatName": "GTower (NMG Gold)",
|
"chatName": "GTower (NMG Gold)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\13-[709.85]-2018-08-19-gtower.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\13-[709.85]-2018-08-19-gtower.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -619,6 +665,7 @@
|
|||||||
"id": "nmg-gold-ganon",
|
"id": "nmg-gold-ganon",
|
||||||
"category": "Any% NMG Gold Segment",
|
"category": "Any% NMG Gold Segment",
|
||||||
"label": "Any% NMG Gold Segment: Ganon (1:43.06) [2018-05-30]",
|
"label": "Any% NMG Gold Segment: Ganon (1:43.06) [2018-05-30]",
|
||||||
|
"name": "Ganon (NMG Gold)",
|
||||||
"chatName": "Ganon (NMG Gold)",
|
"chatName": "Ganon (NMG Gold)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\14-[143.06]-2018-05-30-ganon.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\gold-segments\\any%-nmg-nsq\\720p\\timed\\14-[143.06]-2018-05-30-ganon.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -633,6 +680,7 @@
|
|||||||
"id": "pb-100-ahp",
|
"id": "pb-100-ahp",
|
||||||
"category": "Personal Best",
|
"category": "Personal Best",
|
||||||
"label": "Personal Best: 100% All Heart Pieces (1:19:12) [2017-12-22]",
|
"label": "Personal Best: 100% All Heart Pieces (1:19:12) [2017-12-22]",
|
||||||
|
"name": "100% MG AHP (PB)",
|
||||||
"chatName": "100% MG AHP (PB)",
|
"chatName": "100% MG AHP (PB)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\personal-bests\\100%-mg-ahp\\2017-12-22-100mg-11912.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\personal-bests\\100%-mg-ahp\\2017-12-22-100mg-11912.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -647,6 +695,7 @@
|
|||||||
"id": "pb-ab",
|
"id": "pb-ab",
|
||||||
"category": "Personal Best",
|
"category": "Personal Best",
|
||||||
"label": "Personal Best: All Bosses No EG (1:09:23) [2017-11-20]",
|
"label": "Personal Best: All Bosses No EG (1:09:23) [2017-11-20]",
|
||||||
|
"name": "All Bosses (PB)",
|
||||||
"chatName": "All Bosses (PB)",
|
"chatName": "All Bosses (PB)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\personal-bests\\all-bosses\\2017-11-20-ab-10923.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\personal-bests\\all-bosses\\2017-11-20-ab-10923.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -661,6 +710,7 @@
|
|||||||
"id": "pb-ad",
|
"id": "pb-ad",
|
||||||
"category": "Personal Best",
|
"category": "Personal Best",
|
||||||
"label": "Personal Best: All Dungeons No EG/DW/WW (1:14:59) [2017-11-19]",
|
"label": "Personal Best: All Dungeons No EG/DW/WW (1:14:59) [2017-11-19]",
|
||||||
|
"name": "All Dungeons (PB)",
|
||||||
"chatName": "All Dungeons (PB)",
|
"chatName": "All Dungeons (PB)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\personal-bests\\all-dungeons\\2017-11-19-ad-11459.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\personal-bests\\all-dungeons\\2017-11-19-ad-11459.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -675,6 +725,7 @@
|
|||||||
"id": "pb-any-nmg",
|
"id": "pb-any-nmg",
|
||||||
"category": "Personal Best",
|
"category": "Personal Best",
|
||||||
"label": "Personal Best: Any% NMG No S+Q (1:26:24) [2018-05-27]",
|
"label": "Personal Best: Any% NMG No S+Q (1:26:24) [2018-05-27]",
|
||||||
|
"name": "Any% NMG (PB)",
|
||||||
"chatName": "Any% NMG (PB)",
|
"chatName": "Any% NMG (PB)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\personal-bests\\any%-nmg-nsq\\2018-05-27-nmg-12624.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\personal-bests\\any%-nmg-nsq\\2018-05-27-nmg-12624.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -689,6 +740,7 @@
|
|||||||
"id": "pb-any-no-eg",
|
"id": "pb-any-no-eg",
|
||||||
"category": "Personal Best",
|
"category": "Personal Best",
|
||||||
"label": "Personal Best: Any% No EG (30:28) [2018-09-09]",
|
"label": "Personal Best: Any% No EG (30:28) [2018-09-09]",
|
||||||
|
"name": "Any% No EG (PB)",
|
||||||
"chatName": "Any% No EG (PB)",
|
"chatName": "Any% No EG (PB)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\personal-bests\\any%-no-eg\\2018-09-09-no-eg-3028.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\personal-bests\\any%-no-eg\\2018-09-09-no-eg-3028.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -703,6 +755,7 @@
|
|||||||
"id": "pb-master-sword",
|
"id": "pb-master-sword",
|
||||||
"category": "Personal Best",
|
"category": "Personal Best",
|
||||||
"label": "Personal Best: Master Sword NMG (22:23) [2018-08-23]",
|
"label": "Personal Best: Master Sword NMG (22:23) [2018-08-23]",
|
||||||
|
"name": "Master Sword (PB)",
|
||||||
"chatName": "Master Sword (PB)",
|
"chatName": "Master Sword (PB)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\personal-bests\\master-sword\\2018-08-23-master-sword-2223.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\personal-bests\\master-sword\\2018-08-23-master-sword-2223.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -717,6 +770,7 @@
|
|||||||
"id": "pb-ms",
|
"id": "pb-ms",
|
||||||
"category": "Personal Best",
|
"category": "Personal Best",
|
||||||
"label": "Personal Best: Mirror Shield NMG (50:32) [2017-06-20]",
|
"label": "Personal Best: Mirror Shield NMG (50:32) [2017-06-20]",
|
||||||
|
"name": "Mirror Shield (PB)",
|
||||||
"chatName": "Mirror Shield (PB)",
|
"chatName": "Mirror Shield (PB)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\personal-bests\\mirror-shield\\2017-06-20-mirror-shield-5032.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\personal-bests\\mirror-shield\\2017-06-20-mirror-shield-5032.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -731,6 +785,7 @@
|
|||||||
"id": "pb-ms-no-eg",
|
"id": "pb-ms-no-eg",
|
||||||
"category": "Personal Best",
|
"category": "Personal Best",
|
||||||
"label": "Personal Best: Mirror Shield No EG (11:38) [2017-07-02]",
|
"label": "Personal Best: Mirror Shield No EG (11:38) [2017-07-02]",
|
||||||
|
"name": "Mirror Shield No EG (PB)",
|
||||||
"chatName": "Mirror Shield No EG (PB)",
|
"chatName": "Mirror Shield No EG (PB)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\personal-bests\\mirror-shield-no-eg\\2017-07-02-mirror-shield-no-eg-1138.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\personal-bests\\mirror-shield-no-eg\\2017-07-02-mirror-shield-no-eg-1138.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -745,6 +800,7 @@
|
|||||||
"id": "pb-rbo",
|
"id": "pb-rbo",
|
||||||
"category": "Personal Best",
|
"category": "Personal Best",
|
||||||
"label": "Personal Best: Reverse Boss Order (1:18:13) [2017-12-01]",
|
"label": "Personal Best: Reverse Boss Order (1:18:13) [2017-12-01]",
|
||||||
|
"name": "Reverse Boss Order (PB)",
|
||||||
"chatName": "Reverse Boss Order (PB)",
|
"chatName": "Reverse Boss Order (PB)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\personal-bests\\rbo\\2017-12-01-rbo-11813.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\personal-bests\\rbo\\2017-12-01-rbo-11813.mp4",
|
||||||
"sceneItemProperties": {
|
"sceneItemProperties": {
|
||||||
@@ -759,6 +815,7 @@
|
|||||||
"id": "pb-100-nmg",
|
"id": "pb-100-nmg",
|
||||||
"category": "Personal Best",
|
"category": "Personal Best",
|
||||||
"label": "Personal Best: 100% NMG (1:49:30) [2017-01-31]",
|
"label": "Personal Best: 100% NMG (1:49:30) [2017-01-31]",
|
||||||
|
"name": "100% NMG (PB)",
|
||||||
"chatName": "100% NMG (PB)",
|
"chatName": "100% NMG (PB)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\personal-bests\\100%\\2017-01-31-hundo-14930.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\personal-bests\\100%\\2017-01-31-hundo-14930.mp4",
|
||||||
"sceneItem": "legacyph",
|
"sceneItem": "legacyph",
|
||||||
@@ -768,11 +825,119 @@
|
|||||||
"id": "pb-dg",
|
"id": "pb-dg",
|
||||||
"category": "Personal Best",
|
"category": "Personal Best",
|
||||||
"label": "Personal Best: Defeat Ganon (13:41) [2017-02-20]",
|
"label": "Personal Best: Defeat Ganon (13:41) [2017-02-20]",
|
||||||
|
"name": "Defeat Ganon (PB)",
|
||||||
"chatName": "Defeat Ganon (PB)",
|
"chatName": "Defeat Ganon (PB)",
|
||||||
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\personal-bests\\defeat-ganon\\2017-02-20_12-55-40-defeat-ganon-1341.mp4",
|
"filePath": "Y:\\media\\videos\\ALttP\\my-vids\\personal-bests\\defeat-ganon\\2017-02-20_12-55-40-defeat-ganon-1341.mp4",
|
||||||
"sceneItem": "legacyph",
|
"sceneItem": "legacyph",
|
||||||
"length": 868
|
"length": 868
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"memes": [
|
||||||
|
{
|
||||||
|
"id": "archery",
|
||||||
|
"name": "archery",
|
||||||
|
"filePath": "Y:\\media\\videos\\ALttP\\memes\\archery-contest.mp4",
|
||||||
|
"sceneItem": "meme1",
|
||||||
|
"length": 27
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "69blazeit",
|
||||||
|
"name": "69blazeit",
|
||||||
|
"filePath": "Y:\\media\\videos\\ALttP\\memes\\69BlazeIt.mp4",
|
||||||
|
"sceneItem": "meme1",
|
||||||
|
"length": 92
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "rpgfarm",
|
||||||
|
"name": "rpgfarm",
|
||||||
|
"filePath": "Y:\\media\\videos\\ALttP\\memes\\2016-07-24-1424-06-rpg-race-sniped.mp4",
|
||||||
|
"sceneItem": "meme1",
|
||||||
|
"length": 144
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "emmapeg",
|
||||||
|
"name": "emmapeg",
|
||||||
|
"filePath": "Y:\\media\\videos\\ALttP\\memes\\emma-pegging.mp4",
|
||||||
|
"sceneItem": "meme1",
|
||||||
|
"length": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "handy",
|
||||||
|
"name": "handy",
|
||||||
|
"filePath": "Y:\\media\\videos\\ALttP\\memes\\handy-in-the-mothhole.mp4",
|
||||||
|
"sceneItem": "meme1",
|
||||||
|
"length": 39
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "bodyguard",
|
||||||
|
"name": "bodyguard",
|
||||||
|
"filePath": "Y:\\media\\videos\\ALttP\\memes\\heroic-pop.mp4",
|
||||||
|
"sceneItem": "meme1",
|
||||||
|
"length": 14
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "whowillitbe",
|
||||||
|
"name": "whowillitbe",
|
||||||
|
"filePath": "Y:\\media\\videos\\ALttP\\memes\\its-gonna-be-may.mp4",
|
||||||
|
"sceneItem": "meme1",
|
||||||
|
"length": 30
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "mindblown",
|
||||||
|
"name": "mindblown",
|
||||||
|
"filePath": "Y:\\media\\videos\\ALttP\\memes\\mindblowing-and-lifechanging.mp4",
|
||||||
|
"sceneItem": "meme1",
|
||||||
|
"length": 55
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "nerd-nookie",
|
||||||
|
"name": "nerd-nookie",
|
||||||
|
"filePath": "Y:\\media\\videos\\ALttP\\memes\\nerd-bizkit.mp4",
|
||||||
|
"sceneItem": "meme1",
|
||||||
|
"length": 27
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "curling",
|
||||||
|
"name": "curling",
|
||||||
|
"filePath": "Y:\\media\\videos\\ALttP\\curling-bored-janitors.mp4",
|
||||||
|
"sceneItem": "meme1",
|
||||||
|
"length": 16
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "airplane",
|
||||||
|
"name": "airplane",
|
||||||
|
"filePath": "Y:\\media\\videos\\ALttP\\emetaPlane.mp4",
|
||||||
|
"sceneItem": "meme1",
|
||||||
|
"length": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hard-things",
|
||||||
|
"name": "hard-things",
|
||||||
|
"filePath": "Y:\\media\\videos\\ALttP\\questions-about-hard-things.mp4",
|
||||||
|
"sceneItem": "meme1",
|
||||||
|
"length": 39
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "18arrows",
|
||||||
|
"name": "18arrows",
|
||||||
|
"filePath": "Y:\\media\\videos\\ALttP\\screevo-18-arrows-fine.mp4",
|
||||||
|
"sceneItem": "meme1",
|
||||||
|
"length": 41
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "quake",
|
||||||
|
"name": "quake",
|
||||||
|
"filePath": "Y:\\media\\videos\\ALttP\\trock-indoor-quake.mp4",
|
||||||
|
"sceneItem": "meme1",
|
||||||
|
"length": 17
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "imout",
|
||||||
|
"name": "imout",
|
||||||
|
"filePath": "Y:\\media\\videos\\ALttP\\water-tektite-imout.mp4",
|
||||||
|
"sceneItem": "meme1",
|
||||||
|
"length": 7
|
||||||
|
}
|
||||||
|
],
|
||||||
"debug": false
|
"debug": false
|
||||||
}
|
}
|
||||||
@@ -15,4 +15,7 @@ TODO:
|
|||||||
☐ Start/stop stream automation
|
☐ Start/stop stream automation
|
||||||
☐ Move vods to their own config
|
☐ Move vods to their own config
|
||||||
☐ Tool to output list of video ID's / descriptions
|
☐ Tool to output list of video ID's / descriptions
|
||||||
☐ Support viewer skip voting
|
☐ Support viewer skip voting
|
||||||
|
|
||||||
|
960x540
|
||||||
|
896x504
|
||||||
636
fgfm.js
636
fgfm.js
@@ -12,10 +12,12 @@ const util = require('./lib/util');
|
|||||||
let config = require('./config.json');
|
let config = require('./config.json');
|
||||||
const snesGames = require('./conf/snesgames.json');
|
const snesGames = require('./conf/snesgames.json');
|
||||||
const twitchChannel = config.twitch.channels[0].toLowerCase();
|
const twitchChannel = config.twitch.channels[0].toLowerCase();
|
||||||
|
const randSort = () => { return 0.5 - Math.random() };
|
||||||
|
|
||||||
let videoQueue = recentlyPlayed = [];
|
let videoQueue = recentlyPlayed = [];
|
||||||
let currentVideo;
|
let currentVideo;
|
||||||
let videoTimer;
|
let videoTimer;
|
||||||
|
let lastCommercialShown;
|
||||||
|
|
||||||
// Connect to OBS Websocket
|
// Connect to OBS Websocket
|
||||||
const obs = new OBSWebSocket();
|
const obs = new OBSWebSocket();
|
||||||
@@ -25,8 +27,8 @@ obs.connect({ address: config.obs.websocket.address, password: config.obs.websoc
|
|||||||
console.log(`Success! We're connected to OBS!`);
|
console.log(`Success! We're connected to OBS!`);
|
||||||
return twitchInit(config, obs);
|
return twitchInit(config, obs);
|
||||||
})
|
})
|
||||||
.then(data => {
|
.then(twitch => {
|
||||||
return streamInit(config, obs, data);
|
return streamInit(config, obs, twitch);
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
@@ -37,7 +39,7 @@ obs.on('error', err => {
|
|||||||
console.error(`OBS socket error: ${JSON.stringify(err)}`);
|
console.error(`OBS socket error: ${JSON.stringify(err)}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Initialize Twitch chat hooks
|
// Initialize Twitch chat
|
||||||
const twitchInit = (config, obs) => {
|
const twitchInit = (config, obs) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
console.log('Connecting to Twitch...');
|
console.log('Connecting to Twitch...');
|
||||||
@@ -61,169 +63,6 @@ const twitchInit = (config, obs) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Set up event listeners for Twitch
|
// Set up event listeners for Twitch
|
||||||
twitchChat.addListener('message', (from, to, message) => {
|
|
||||||
// Ignore everything from blacklisted users
|
|
||||||
if (config.twitch.blacklistedUsers.includes(from)) return;
|
|
||||||
|
|
||||||
// Listen for commands that start with the designated prefix
|
|
||||||
if (message.startsWith(config.twitch.cmdPrefix)) {
|
|
||||||
let commandParts = message.slice(config.twitch.cmdPrefix.length).split(' ');
|
|
||||||
let commandNoPrefix = commandParts[0] || '';
|
|
||||||
|
|
||||||
// Listen for specific commands from admins
|
|
||||||
if (config.twitch.admins.includes(from) || from === config.twitch.username.toLowerCase()) {
|
|
||||||
|
|
||||||
// SHOW/HIDE SOURCE
|
|
||||||
if (commandNoPrefix === 'show' || commandNoPrefix === 'hide') {
|
|
||||||
|
|
||||||
let newVisibility = (commandNoPrefix === 'show');
|
|
||||||
let visibleTerm = (newVisibility ? 'visible' : 'hidden');
|
|
||||||
|
|
||||||
let target = commandParts[1] || false;
|
|
||||||
if (!target) {
|
|
||||||
twitchChat.say(to, `A scene item name is required!`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let sceneItem = {"item": target};
|
|
||||||
|
|
||||||
let sceneOrGroup = commandParts[2] || false;
|
|
||||||
if (sceneOrGroup !== false) {
|
|
||||||
sceneItem["scene-name"] = sceneOrGroup;
|
|
||||||
}
|
|
||||||
|
|
||||||
obs.getSceneItemProperties(sceneItem)
|
|
||||||
.then(data => {
|
|
||||||
if (data.visible === newVisibility) {
|
|
||||||
twitchChat.say(to, `This scene item is already ${visibleTerm}. DerpHam`);
|
|
||||||
} else {
|
|
||||||
sceneItem.visible = newVisibility;
|
|
||||||
obs.setSceneItemProperties(sceneItem)
|
|
||||||
.then(res => {
|
|
||||||
twitchChat.say(to, `${target} is now ${visibleTerm}.`);
|
|
||||||
})
|
|
||||||
.catch(console.error);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
twitchChat.say(to, JSON.stringify(err));
|
|
||||||
});
|
|
||||||
// TOGGLE SOURCE VISIBILITY
|
|
||||||
} else if (commandNoPrefix === 't') {
|
|
||||||
let target = commandParts[1] || false;
|
|
||||||
if (!target) {
|
|
||||||
twitchChat.say(to, `A scene item name is required!`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let sceneItem = {"item": target};
|
|
||||||
|
|
||||||
obs.getSceneItemProperties(sceneItem)
|
|
||||||
.then(data => {
|
|
||||||
let newVisibility = !data.visible;
|
|
||||||
let visibleTerm = (newVisibility ? 'visible' : 'hidden');
|
|
||||||
|
|
||||||
sceneItem.visible = newVisibility;
|
|
||||||
obs.setSceneItemProperties(sceneItem)
|
|
||||||
.then(res => {
|
|
||||||
twitchChat.say(to, `${target} is now ${visibleTerm}.`);
|
|
||||||
})
|
|
||||||
.catch(console.error);
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
twitchChat.say(to, JSON.stringify(err));
|
|
||||||
});
|
|
||||||
// SWAP -- Hide one source, show another
|
|
||||||
} else if (commandNoPrefix === 'swap') {
|
|
||||||
// hide first argument, show second argument
|
|
||||||
let targetToHide = commandParts[1] || false;
|
|
||||||
let targetToShow = commandParts[2] || false;
|
|
||||||
if (targetToHide === false || targetToShow == false) {
|
|
||||||
twitchChat.say(to, `Format: ${config.twitch.cmdPrefix}swap <item-to-hide> <item-to-show>`);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
obs.setSceneItemProperties({"item": targetToHide, "visible": false})
|
|
||||||
.then(res => {
|
|
||||||
obs.setSceneItemProperties({"item": targetToShow, "visible": true});
|
|
||||||
})
|
|
||||||
.catch(console.error);
|
|
||||||
// Black Box "Everybody Wow" "commercial"
|
|
||||||
} else if (commandNoPrefix === 'auw') {
|
|
||||||
obs.setCurrentScene({"scene-name": "commercial"})
|
|
||||||
.then(res => {
|
|
||||||
// show the video
|
|
||||||
return obs.setSceneItemProperties({"item": "everybody-wow", "scene-name": "commercial", "visible": true});
|
|
||||||
})
|
|
||||||
.then(res => {
|
|
||||||
// mute songrequest audio
|
|
||||||
editorChat.say(to, '!volume 0');
|
|
||||||
// show owen
|
|
||||||
obs.setSceneItemProperties({"item": "owen", "scene-name": "commercial", "visible": true});
|
|
||||||
// tell chat what's up
|
|
||||||
twitchChat.say(to, 'Everybody OwenWow');
|
|
||||||
// swap back to fgfm scene after the video ends
|
|
||||||
setTimeout(() => {
|
|
||||||
// hide video
|
|
||||||
obs.setSceneItemProperties({"item": "everybody-wow", "scene-name": "commercial", "visible": false})
|
|
||||||
// hide owen
|
|
||||||
obs.setSceneItemProperties({"item": "owen", "scene-name": "commercial", "visible": false});
|
|
||||||
// unmute songrequest audio
|
|
||||||
editorChat.say(to, '!volume 50');
|
|
||||||
// swap back to fgfm
|
|
||||||
obs.setCurrentScene({"scene-name": "fgfm"});
|
|
||||||
}, 248000);
|
|
||||||
})
|
|
||||||
.catch(console.error);
|
|
||||||
// SWITCH SCENES
|
|
||||||
} else if (commandNoPrefix === 'switch') {
|
|
||||||
|
|
||||||
let target = commandParts[1] || false;
|
|
||||||
if (!target) {
|
|
||||||
twitchChat.say(to, `A scene name is required!`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
obs.getCurrentScene()
|
|
||||||
.then(data => {
|
|
||||||
if (data.name === target) {
|
|
||||||
twitchChat.say(to, `That scene is already active! DerpHam`);
|
|
||||||
} else {
|
|
||||||
obs.setCurrentScene({"scene-name": target})
|
|
||||||
.then(() => {twitchChat.say(to, `${target} is now active`)})
|
|
||||||
.catch(console.error);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(console.error);
|
|
||||||
// SET ON-SCREEN ACTIVITY
|
|
||||||
} else if (commandNoPrefix === 'setactivity') {
|
|
||||||
let target = commandParts.slice(1).join(' ');
|
|
||||||
if (!target) {
|
|
||||||
twitchChat.say(to, `Please provide a new activity`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
obs.setTextGDIPlusProperties({"source": config.currentActivitySceneItemName, "scene-name": config.videoSceneName, "render": true, "text": target})
|
|
||||||
.then(res => {
|
|
||||||
twitchChat.say(to, `Activity updated!`);
|
|
||||||
return;
|
|
||||||
})
|
|
||||||
.catch(console.error);
|
|
||||||
// REBOOT
|
|
||||||
} else if (commandNoPrefix === 'reboot') {
|
|
||||||
console.log('Received request from admin to reboot...');
|
|
||||||
twitchChat.say(to, 'Rebooting...');
|
|
||||||
process.exit(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Listen for commands from everyone else
|
|
||||||
if (commandNoPrefix === 'rngames') {
|
|
||||||
twitchChat.say(to, snesGames.sort( () => { return 0.5 - Math.random() } ).slice(0, 10).join(' | '));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
twitchChat.addListener('error', message => {
|
twitchChat.addListener('error', message => {
|
||||||
if (message.command != 'err_unknowncommand') {
|
if (message.command != 'err_unknowncommand') {
|
||||||
console.error('error from Twitch IRC Server: ', message);
|
console.error('error from Twitch IRC Server: ', message);
|
||||||
@@ -252,7 +91,7 @@ const twitchInit = (config, obs) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
twitchChat.addListener('motd', motd => {
|
twitchChat.addListener('motd', motd => {
|
||||||
console.log(`Received MOTD: ${motd}`);
|
//console.log(`Received MOTD: ${motd}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
resolve({"botChat": twitchChat, "editorChat": editorChat});
|
resolve({"botChat": twitchChat, "editorChat": editorChat});
|
||||||
@@ -263,20 +102,88 @@ 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...`);
|
||||||
videoQueue = config.vods.sort( () => { return 0.5 - Math.random() } ).slice(0, config.initialQueueSize);
|
videoQueue = config.vods.sort(randSort).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(' | ')}`);
|
||||||
currentVideo = videoQueue.shift();
|
|
||||||
|
|
||||||
// Pick the next video in the queue (or shuffle if queue is empty)
|
// Shows a video in the given scene and triggers a callback when it's finished
|
||||||
|
const playVideoInScene = (video, scene, callback) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// set the file path
|
||||||
|
obs.setSourceSettings({"sourceName": video.sceneItem, "sourceSettings": {"local_file": video.filePath}})
|
||||||
|
// show the video
|
||||||
|
.then(data => obs.setSceneItemProperties({"item": video.sceneItem, "scene-name": scene, "visible": true}))
|
||||||
|
// trigger callback when the video is over, but resolve promise immediately with the timer
|
||||||
|
.then(data => {
|
||||||
|
resolve(setTimeout(() => {callback(data)}, video.length*1000));
|
||||||
|
})
|
||||||
|
.catch(reject);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Show a gameplay vod
|
||||||
|
const showVideo = video => {
|
||||||
|
console.log(`Showing video: ${video.chatName}`);
|
||||||
|
|
||||||
|
let handleVideoFinish = () => {
|
||||||
|
obs.setSceneItemProperties({"item": video.sceneItem, "scene-name": config.videoSceneName, "visible": false})
|
||||||
|
.then(data => {nextVideo()});
|
||||||
|
.catch(console.error);
|
||||||
|
};
|
||||||
|
|
||||||
|
obs.setCurrentScene({"scene": config.videoSceneName})
|
||||||
|
.then(res => {
|
||||||
|
playVideoInScene(video, config.videoSceneName, handleVideoFinish)
|
||||||
|
.then(timer => {
|
||||||
|
// track timer so we can cancel callback later on if necessary
|
||||||
|
videoTimer = timer;
|
||||||
|
|
||||||
|
// update activity label and show/hide appropriately
|
||||||
|
if (video.hasOwnProperty('label') && video.label !== false) {
|
||||||
|
obs.setTextGDIPlusProperties({"source": config.currentActivitySceneItemName, "scene-name": config.videoSceneName, "render": true, "text": video.label});
|
||||||
|
} else {
|
||||||
|
obs.setSceneItemProperties({"item": config.currentActivitySceneItemName, "scene-name": config.videoSceneName, "visible": false});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(console.error);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Picks the next video in the queue (shuffles if empty)
|
||||||
|
// Also handles "commercial breaks"
|
||||||
const nextVideo = () => {
|
const nextVideo = () => {
|
||||||
// add currentVideo.id to recentlyPlayed list, remove oldest video if cap is hit
|
// Show a "commercial break" if it's been long enough since the last one
|
||||||
|
let secondsSinceLastCommercial = (Date.now() - lastCommercialShown) / 1000;
|
||||||
|
console.log(`It has been ${secondsSinceLastCommercial} seconds since the last commercial`);
|
||||||
|
/* if (secondsSinceLastCommercial >= config.commercialInterval) {
|
||||||
|
console.log(`Showing commercial now...`);
|
||||||
|
// @TODO: Add a random chance here for it to be "everybody wow"
|
||||||
|
let commercial = config.memes.sort(randSort)[0];
|
||||||
|
obs.setCurrentScene({"scene": config.commercialSceneName})
|
||||||
|
.then(res => {
|
||||||
|
return playVideoInScene(commercial, config.commercialSceneName, () => {
|
||||||
|
// hide video
|
||||||
|
obs.setSceneItemProperties({"item": commercial.sceneItem, "scene-name": config.commercialSceneName, "visible": false})
|
||||||
|
// unmute songrequest audio
|
||||||
|
editorChat.say(to, '!volume 50');
|
||||||
|
// show next video in queue
|
||||||
|
lastCommercialShown = Date.now();
|
||||||
|
nextVideo();
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
// mute songrequest audio
|
||||||
|
editorChat.say(to, '!volume 0');
|
||||||
|
});;
|
||||||
|
.catch(console.error);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// Keep track of recently played videos
|
||||||
if (recentlyPlayed.length === 3) {
|
if (recentlyPlayed.length === 3) {
|
||||||
recentlyPlayed.shift();
|
recentlyPlayed.shift();
|
||||||
}
|
}
|
||||||
recentlyPlayed.push(currentVideo.id);
|
recentlyPlayed.push(currentVideo.id);
|
||||||
|
|
||||||
// @TODO: Add a random chance here for room grind to be played for an amount of time
|
// @TODO: Add a random chance here for room grind to be played for an amount of time
|
||||||
|
|
||||||
|
|
||||||
// play the next video in the queue, or pick one at random if the queue is empty
|
// play the next video in the queue, or pick one at random if the queue is empty
|
||||||
if (videoQueue.length > 0) {
|
if (videoQueue.length > 0) {
|
||||||
@@ -286,130 +193,226 @@ const streamInit = (config, obs, twitch) => {
|
|||||||
let freshVods = config.vods.filter(e => {
|
let freshVods = config.vods.filter(e => {
|
||||||
return !recentlyPlayed.includes(e.id);
|
return !recentlyPlayed.includes(e.id);
|
||||||
});
|
});
|
||||||
currentVideo = freshVods.sort( () => { return 0.5 - Math.random() } ).slice(0, 1).shift();
|
currentVideo = freshVods.sort(randSort).slice(0, 1).shift();
|
||||||
}
|
}
|
||||||
showVideo(currentVideo);
|
showVideo(currentVideo);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Show a video and hide it when finished
|
lastCommercialShown = Date.now();
|
||||||
const showVideo = video => {
|
|
||||||
console.log(`Showing video: ${video.chatName}`);
|
|
||||||
// set the file path
|
|
||||||
obs.setSourceSettings({"sourceName": video.sceneItem, "sourceSettings": {"local_file": video.filePath}})
|
|
||||||
.then(data => {
|
|
||||||
// show the video
|
|
||||||
return obs.setSceneItemProperties({"item": video.sceneItem, "scene-name": config.videoSceneName, "visible": true});
|
|
||||||
})
|
|
||||||
.then(data => {
|
|
||||||
// update activity label and show/hide appropriately
|
|
||||||
if (video.label !== false) {
|
|
||||||
return obs.setTextGDIPlusProperties({"source": config.currentActivitySceneItemName, "scene-name": config.videoSceneName, "render": true, "text": video.label});
|
|
||||||
} else {
|
|
||||||
return obs.setSceneItemProperties({"item": config.currentActivitySceneItemName, "scene-name": config.videoSceneName, "visible": false});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then(data => {
|
|
||||||
// hide this video when it's finished and play the next video
|
|
||||||
videoTimer = setTimeout(() => {
|
|
||||||
obs.setSceneItemProperties({"item": video.sceneItem, "scene-name": config.videoSceneName, "visible": false})
|
|
||||||
.then(data => {
|
|
||||||
nextVideo();
|
|
||||||
});
|
|
||||||
}, video.length*1000)
|
|
||||||
})
|
|
||||||
.catch(console.error);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
// grab the first video in the queue and show it
|
||||||
|
currentVideo = videoQueue.shift();
|
||||||
showVideo(currentVideo);
|
showVideo(currentVideo);
|
||||||
|
|
||||||
console.log(`Initializing stream timers...`);
|
// Twitch Chat Commands
|
||||||
|
|
||||||
let userVotes = currentChoices = [];
|
|
||||||
let rockTheVote = () => {};
|
|
||||||
let rtvInterval = setInterval(() => {rockTheVote()}, 300000);
|
|
||||||
|
|
||||||
let videoVoteJob = new schedule.Job(() => {
|
|
||||||
// Tally votes from previous election (if there was one), add the winner to the queue
|
|
||||||
let winner;
|
|
||||||
if (currentChoices.length > 0) {
|
|
||||||
if (userVotes.length === 0) {
|
|
||||||
// choose a random element from currentChoices
|
|
||||||
winner = util.randElement(currentChoices);
|
|
||||||
console.log(`VIDEO CHOSEN RANDOMLY: ${winner.chatName}`);
|
|
||||||
twitch.botChat.say(twitchChannel, `No Votes Logged -- Next Video Chosen at Random: ${winner.chatName}`);
|
|
||||||
} else {
|
|
||||||
// tally and sort votes
|
|
||||||
let voteTallies = [];
|
|
||||||
util.asyncForEach(userVotes, vote => {
|
|
||||||
tallyIndex = voteTallies.findIndex(e => e.id === vote.vote);
|
|
||||||
if (tallyIndex !== -1) {
|
|
||||||
voteTallies[tallyIndex].count++;
|
|
||||||
} else {
|
|
||||||
voteTallies.push({id: vote.vote, count: 1});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
voteTallies.sort((a, b) => {
|
|
||||||
if (a.count < b.count) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (a.count > b.count) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
// a must be equal to b
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`Voting Results: ${JSON.stringify(voteTallies)}`);
|
|
||||||
winner = currentChoices[voteTallies[0].id-1];
|
|
||||||
console.log(`WINNER OF THE VOTE: ${winner.chatName}`);
|
|
||||||
twitch.botChat.say(twitchChannel, `Winner of the Video Vote: ${winner.chatName}`);
|
|
||||||
|
|
||||||
// clear user votes
|
|
||||||
userVotes = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
videoQueue.push(winner);
|
|
||||||
}
|
|
||||||
|
|
||||||
// choose more random videos from config.vods (that aren't already in the queue)
|
|
||||||
let vodsNotInQueue = config.vods.filter(e => {
|
|
||||||
let inQueue = videoQueue.findIndex(q => q.id === e.id) !== -1;
|
|
||||||
return !inQueue;
|
|
||||||
});
|
|
||||||
currentChoices = vodsNotInQueue.sort( () => { return 0.5 - Math.random() } ).slice(0, config.videoPollSize);
|
|
||||||
|
|
||||||
// Poll the chat
|
|
||||||
let chatChoices = currentChoices.map((c, i) => {
|
|
||||||
return `[${i+1}] ${c.chatName}`;
|
|
||||||
});
|
|
||||||
|
|
||||||
rockTheVote = () => {
|
|
||||||
twitch.botChat.say(twitchChannel, `Vote for which video you'd like to add to the queue using ${config.twitch.cmdPrefix}vote #: ${chatChoices.join(' | ')}`)
|
|
||||||
};
|
|
||||||
clearInterval(rtvInterval);
|
|
||||||
rockTheVote();
|
|
||||||
rtvInterval = setInterval(() => {rockTheVote()}, 300000);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Twitch Chat Commands for Video Queue Control
|
|
||||||
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;
|
||||||
|
|
||||||
// Listen for commands that start with the designated prefix
|
// Listen for commands that start with the designated prefix
|
||||||
if (message.startsWith(config.twitch.cmdPrefix)) {
|
if (message.startsWith(config.twitch.cmdPrefix)) {
|
||||||
|
|
||||||
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
|
// ADMIN COMMANDS
|
||||||
if (config.twitch.admins.includes(from) || from === config.twitch.username.toLowerCase()) {
|
if (config.twitch.admins.includes(from) || from === config.twitch.username.toLowerCase()) {
|
||||||
|
|
||||||
|
// SHOW/HIDE SOURCE
|
||||||
|
if (commandNoPrefix === 'show' || commandNoPrefix === 'hide') {
|
||||||
|
|
||||||
|
let newVisibility = (commandNoPrefix === 'show');
|
||||||
|
let visibleTerm = (newVisibility ? 'visible' : 'hidden');
|
||||||
|
|
||||||
|
let target = commandParts[1] || false;
|
||||||
|
if (!target) {
|
||||||
|
twitch.botChat.say(to, `A scene item name is required!`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let sceneItem = {"item": target};
|
||||||
|
|
||||||
|
let sceneOrGroup = commandParts[2] || false;
|
||||||
|
if (sceneOrGroup !== false) {
|
||||||
|
sceneItem["scene-name"] = sceneOrGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
obs.getSceneItemProperties(sceneItem)
|
||||||
|
.then(data => {
|
||||||
|
if (data.visible === newVisibility) {
|
||||||
|
twitch.botChat.say(to, `This scene item is already ${visibleTerm}. DerpHam`);
|
||||||
|
} else {
|
||||||
|
sceneItem.visible = newVisibility;
|
||||||
|
obs.setSceneItemProperties(sceneItem)
|
||||||
|
.then(res => {
|
||||||
|
twitch.botChat.say(to, `${target} is now ${visibleTerm}.`);
|
||||||
|
})
|
||||||
|
.catch(console.error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
twitch.botChat.say(to, JSON.stringify(err));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// TOGGLE SOURCE VISIBILITY
|
||||||
|
} else if (commandNoPrefix === 't') {
|
||||||
|
let target = commandParts[1] || false;
|
||||||
|
if (!target) {
|
||||||
|
twitch.botChat.say(to, `A scene item name is required!`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let sceneItem = {"item": target};
|
||||||
|
|
||||||
|
obs.getSceneItemProperties(sceneItem)
|
||||||
|
.then(data => {
|
||||||
|
let newVisibility = !data.visible;
|
||||||
|
let visibleTerm = (newVisibility ? 'visible' : 'hidden');
|
||||||
|
|
||||||
|
sceneItem.visible = newVisibility;
|
||||||
|
obs.setSceneItemProperties(sceneItem)
|
||||||
|
.then(res => {
|
||||||
|
twitch.botChat.say(to, `${target} is now ${visibleTerm}.`);
|
||||||
|
})
|
||||||
|
.catch(console.error);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
twitch.botChat.say(to, JSON.stringify(err));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// SWAP -- Hide one source, show another
|
||||||
|
} else if (commandNoPrefix === 'swap') {
|
||||||
|
// hide first argument, show second argument
|
||||||
|
let targetToHide = commandParts[1] || false;
|
||||||
|
let targetToShow = commandParts[2] || false;
|
||||||
|
if (targetToHide === false || targetToShow == false) {
|
||||||
|
twitch.botChat.say(to, `Format: ${config.twitch.cmdPrefix}swap <item-to-hide> <item-to-show>`);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
obs.setSceneItemProperties({"item": targetToHide, "visible": false})
|
||||||
|
.then(res => {
|
||||||
|
obs.setSceneItemProperties({"item": targetToShow, "visible": true});
|
||||||
|
})
|
||||||
|
.catch(console.error);
|
||||||
|
|
||||||
|
|
||||||
|
// Black Box "Everybody Wow" config.commercialSceneName
|
||||||
|
} else if (commandNoPrefix === 'auw') {
|
||||||
|
obs.setCurrentScene({"scene-name": config.commercialSceneName})
|
||||||
|
.then(res => {
|
||||||
|
// show the video
|
||||||
|
return obs.setSceneItemProperties({"item": "everybody-wow", "scene-name": config.commercialSceneName, "visible": true});
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
// mute songrequest audio
|
||||||
|
editorChat.say(to, '!volume 0');
|
||||||
|
// show owen
|
||||||
|
obs.setSceneItemProperties({"item": "owen", "scene-name": config.commercialSceneName, "visible": true});
|
||||||
|
// tell chat what's up
|
||||||
|
twitch.botChat.say(to, 'Everybody OwenWow');
|
||||||
|
// swap back to fgfm scene after the video ends
|
||||||
|
setTimeout(() => {
|
||||||
|
// hide video
|
||||||
|
obs.setSceneItemProperties({"item": "everybody-wow", "scene-name": config.commercialSceneName, "visible": false})
|
||||||
|
// hide owen
|
||||||
|
obs.setSceneItemProperties({"item": "owen", "scene-name": config.commercialSceneName, "visible": false});
|
||||||
|
// unmute songrequest audio
|
||||||
|
editorChat.say(to, '!volume 50');
|
||||||
|
// swap back to fgfm
|
||||||
|
obs.setCurrentScene({"scene-name": "fgfm"});
|
||||||
|
}, 246000);
|
||||||
|
})
|
||||||
|
.catch(console.error);
|
||||||
|
|
||||||
|
|
||||||
|
// memes on-demand
|
||||||
|
} else if (commandNoPrefix === 'meme') {
|
||||||
|
obs.setCurrentScene({"scene-name": config.commercialSceneName})
|
||||||
|
/*.then(res => {
|
||||||
|
// show the video
|
||||||
|
return obs.setSceneItemProperties({"item": "everybody-wow", "scene-name": config.commercialSceneName, "visible": true});
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
// mute songrequest audio
|
||||||
|
editorChat.say(to, '!volume 0');
|
||||||
|
// show owen
|
||||||
|
obs.setSceneItemProperties({"item": "owen", "scene-name": config.commercialSceneName, "visible": true});
|
||||||
|
// tell chat what's up
|
||||||
|
twitch.botChat.say(to, 'Everybody OwenWow');
|
||||||
|
// swap back to fgfm scene after the video ends
|
||||||
|
setTimeout(() => {
|
||||||
|
// hide video
|
||||||
|
obs.setSceneItemProperties({"item": "everybody-wow", "scene-name": config.commercialSceneName, "visible": false})
|
||||||
|
// hide owen
|
||||||
|
obs.setSceneItemProperties({"item": "owen", "scene-name": config.commercialSceneName, "visible": false});
|
||||||
|
// unmute songrequest audio
|
||||||
|
editorChat.say(to, '!volume 50');
|
||||||
|
// swap back to fgfm
|
||||||
|
obs.setCurrentScene({"scene-name": "fgfm"});
|
||||||
|
}, 246000);*/
|
||||||
|
})
|
||||||
|
.catch(console.error);
|
||||||
|
|
||||||
|
|
||||||
|
// SWITCH SCENES
|
||||||
|
} else if (commandNoPrefix === 'switch') {
|
||||||
|
|
||||||
|
let target = commandParts[1] || false;
|
||||||
|
if (!target) {
|
||||||
|
twitch.botChat.say(to, `A scene name is required!`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
obs.getCurrentScene()
|
||||||
|
.then(data => {
|
||||||
|
if (data.name === target) {
|
||||||
|
twitch.botChat.say(to, `That scene is already active! DerpHam`);
|
||||||
|
} else {
|
||||||
|
obs.setCurrentScene({"scene-name": target})
|
||||||
|
.then(() => {twitch.botChat.say(to, `${target} is now active`)})
|
||||||
|
.catch(console.error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(console.error);
|
||||||
|
|
||||||
|
|
||||||
|
// SET ON-SCREEN ACTIVITY
|
||||||
|
} else if (commandNoPrefix === 'setactivity') {
|
||||||
|
let target = commandParts.slice(1).join(' ');
|
||||||
|
if (!target) {
|
||||||
|
twitch.botChat.say(to, `Please provide a new activity`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
obs.setTextGDIPlusProperties({"source": config.currentActivitySceneItemName, "scene-name": config.videoSceneName, "render": true, "text": target})
|
||||||
|
.then(res => {
|
||||||
|
twitch.botChat.say(to, `Activity updated!`);
|
||||||
|
return;
|
||||||
|
})
|
||||||
|
.catch(console.error);
|
||||||
|
|
||||||
|
|
||||||
|
// REBOOT
|
||||||
|
} else if (commandNoPrefix === 'reboot') {
|
||||||
|
console.log('Received request from admin to reboot...');
|
||||||
|
twitch.botChat.say(to, 'Rebooting...');
|
||||||
|
process.exit(0);
|
||||||
|
|
||||||
|
|
||||||
// SKIP
|
// SKIP
|
||||||
if (commandNoPrefix === 'skip') {
|
} else if (commandNoPrefix === 'skip') {
|
||||||
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 => {
|
||||||
nextVideo();
|
nextVideo();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// ADD
|
// ADD
|
||||||
} else if (commandNoPrefix === 'add') {
|
} else if (commandNoPrefix === 'add') {
|
||||||
let requestedVideoId = commandParts[1] || false;
|
let requestedVideoId = commandParts[1] || false;
|
||||||
@@ -435,10 +438,14 @@ const streamInit = (config, obs, twitch) => {
|
|||||||
videoQueue.push(config.vods[vodIndex]);
|
videoQueue.push(config.vods[vodIndex]);
|
||||||
twitch.botChat.say(to, `${config.vods[vodIndex].chatName} has been added to the queue [${videoQueue.length}]`);
|
twitch.botChat.say(to, `${config.vods[vodIndex].chatName} has been added to the queue [${videoQueue.length}]`);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
// START VOTE
|
// START VOTE
|
||||||
} else if (commandNoPrefix === 'startvote') {
|
} else if (commandNoPrefix === 'startvote') {
|
||||||
videoVoteJob.reschedule("*/15 * * * *");
|
videoVoteJob.reschedule("*/15 * * * *");
|
||||||
twitch.botChat.say(to, `Voting has been started. Next run: ${videoVoteJob.nextInvocation()}`);
|
twitch.botChat.say(to, `Voting has been started. Next run: ${videoVoteJob.nextInvocation()}`);
|
||||||
|
|
||||||
|
|
||||||
// PAUSE VOTE
|
// PAUSE VOTE
|
||||||
} else if (commandNoPrefix === 'pausevote') {
|
} else if (commandNoPrefix === 'pausevote') {
|
||||||
clearInterval(rtvInterval);
|
clearInterval(rtvInterval);
|
||||||
@@ -479,6 +486,8 @@ 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
|
// QUEUE STATUS
|
||||||
} else if (commandNoPrefix === 'queue') {
|
} else if (commandNoPrefix === 'queue') {
|
||||||
if (videoQueue.length > 0) {
|
if (videoQueue.length > 0) {
|
||||||
@@ -489,9 +498,13 @@ 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
|
// 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
|
// NEXT VIDEO
|
||||||
} else if (commandNoPrefix === 'next') {
|
} else if (commandNoPrefix === 'next') {
|
||||||
if (videoQueue.length > 0) {
|
if (videoQueue.length > 0) {
|
||||||
@@ -499,6 +512,8 @@ 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!`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// VIDEO REQUEST
|
// VIDEO REQUEST
|
||||||
} else if (commandNoPrefix === 'vr') {
|
} else if (commandNoPrefix === 'vr') {
|
||||||
let requestedVideoId = commandParts[1] || false;
|
let requestedVideoId = commandParts[1] || false;
|
||||||
@@ -524,12 +539,85 @@ const streamInit = (config, obs, twitch) => {
|
|||||||
videoQueue.push(config.vods[vodIndex]);
|
videoQueue.push(config.vods[vodIndex]);
|
||||||
twitch.botChat.say(to, `${config.vods[vodIndex].chatName} has been added to the queue [${videoQueue.length}]`);
|
twitch.botChat.say(to, `${config.vods[vodIndex].chatName} has been added to the queue [${videoQueue.length}]`);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// RNGAMES
|
||||||
|
} else if (commandNoPrefix === 'rngames') {
|
||||||
|
twitch.botChat.say(to, snesGames.sort(randSort).slice(0, 10).join(' | '));
|
||||||
}
|
}
|
||||||
////////////////
|
////////////////
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
resolve(videoQueue);
|
console.log(`Initializing stream timers...`);
|
||||||
|
|
||||||
|
let userVotes = currentChoices = [];
|
||||||
|
let rockTheVote = () => {};
|
||||||
|
let rtvInterval = setInterval(() => {rockTheVote()}, 300000);
|
||||||
|
|
||||||
|
let videoVoteJob = new schedule.Job(() => {
|
||||||
|
// Tally votes from previous election (if there was one), add the winner to the queue
|
||||||
|
let winner;
|
||||||
|
if (currentChoices.length > 0) {
|
||||||
|
if (userVotes.length === 0) {
|
||||||
|
// choose a random element from currentChoices
|
||||||
|
winner = util.randElement(currentChoices);
|
||||||
|
console.log(`VIDEO CHOSEN RANDOMLY: ${winner.chatName}`);
|
||||||
|
twitch.botChat.say(twitchChannel, `No Votes Logged -- Next Video Chosen at Random: ${winner.chatName}`);
|
||||||
|
} else {
|
||||||
|
// tally and sort votes
|
||||||
|
let voteTallies = [];
|
||||||
|
await util.asyncForEach(userVotes, async (vote) => {
|
||||||
|
tallyIndex = voteTallies.findIndex(e => e.id === vote.vote);
|
||||||
|
if (tallyIndex !== -1) {
|
||||||
|
voteTallies[tallyIndex].count++;
|
||||||
|
} else {
|
||||||
|
voteTallies.push({id: vote.vote, count: 1});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
voteTallies.sort((a, b) => {
|
||||||
|
if (a.count < b.count) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (a.count > b.count) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// a must be equal to b
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`Voting Results: ${JSON.stringify(voteTallies)}`);
|
||||||
|
winner = currentChoices[voteTallies[0].id-1];
|
||||||
|
console.log(`WINNER OF THE VOTE: ${winner.chatName}`);
|
||||||
|
twitch.botChat.say(twitchChannel, `Winner of the Video Vote: ${winner.chatName}`);
|
||||||
|
|
||||||
|
// clear user votes
|
||||||
|
userVotes = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
videoQueue.push(winner);
|
||||||
|
}
|
||||||
|
|
||||||
|
// choose more random videos from config.vods (that aren't already in the queue)
|
||||||
|
let vodsNotInQueue = config.vods.filter(e => {
|
||||||
|
let inQueue = videoQueue.findIndex(q => q.id === e.id) !== -1;
|
||||||
|
return !inQueue;
|
||||||
|
});
|
||||||
|
currentChoices = vodsNotInQueue.sort(randSort).slice(0, config.videoPollSize);
|
||||||
|
|
||||||
|
// Poll the chat
|
||||||
|
let chatChoices = currentChoices.map((c, i) => {
|
||||||
|
return `[${i+1}] ${c.chatName}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
rockTheVote = () => {
|
||||||
|
twitch.botChat.say(twitchChannel, `Vote for which video you'd like to add to the queue using ${config.twitch.cmdPrefix}vote #: ${chatChoices.join(' | ')}`)
|
||||||
|
};
|
||||||
|
clearInterval(rtvInterval);
|
||||||
|
rockTheVote();
|
||||||
|
rtvInterval = setInterval(() => {rockTheVote()}, 300000);
|
||||||
|
});
|
||||||
|
|
||||||
|
resolve();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user