mlbserver 2024.8.2 → 2024.10.0-8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +184 -36
- package/package.json +1 -1
- package/session.js +229 -79
package/index.js
CHANGED
|
@@ -23,20 +23,21 @@ const sessionClass = require('./session.js')
|
|
|
23
23
|
const VALID_DATES = [ 'today', 'yesterday' ]
|
|
24
24
|
const YESTERDAY_UTC_HOURS = 14 // UTC hours (EST + 4) to change home page default date from yesterday to today
|
|
25
25
|
const VALID_MEDIA_TYPES = [ 'Video', 'Audio', 'Spanish' ]
|
|
26
|
-
const VALID_LINK_TYPES = [ 'Embed', 'Stream', 'Chromecast', 'Advanced' ]
|
|
26
|
+
const VALID_LINK_TYPES = [ 'Embed', 'Stream', 'Chromecast', 'Advanced', 'Download' ]
|
|
27
27
|
const VALID_START_FROM = [ 'Beginning', 'Live' ]
|
|
28
28
|
const VALID_CONTROLS = [ 'Show', 'Hide' ]
|
|
29
29
|
const VALID_INNING_HALF = [ '', 'top', 'bottom' ]
|
|
30
30
|
const VALID_INNING_NUMBER = [ '', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12' ]
|
|
31
31
|
const VALID_SCORES = [ 'Hide', 'Show' ]
|
|
32
|
-
const VALID_RESOLUTIONS = [ 'adaptive', '720p60', '720p', '540p', '504p', '360p', 'none'
|
|
32
|
+
const VALID_RESOLUTIONS = [ 'adaptive', '720p60', '720p', '540p', '504p', '360p', 'none' ]
|
|
33
33
|
const DEFAULT_MULTIVIEW_RESOLUTION = '504p'
|
|
34
34
|
// Corresponding andwidths to display for above resolutions
|
|
35
35
|
const DISPLAY_BANDWIDTHS = [ '', '6600k', '4160k', '2950k', '2120k', '1400k', '' ]
|
|
36
|
-
const VALID_AUDIO_TRACKS = [ 'all', 'English', '
|
|
37
|
-
const DISPLAY_AUDIO_TRACKS = [ 'all', 'TV', 'Radio', '
|
|
36
|
+
const VALID_AUDIO_TRACKS = [ 'all', 'English', 'Home Radio', 'Casa Radio', 'Away Radio', 'Visita Radio', 'Park', 'none' ]
|
|
37
|
+
const DISPLAY_AUDIO_TRACKS = [ 'all', 'TV', 'Radio', 'Spa.', 'Away Rad.', 'Away Sp.', 'Park', 'none' ]
|
|
38
38
|
const DEFAULT_MULTIVIEW_AUDIO_TRACK = 'English'
|
|
39
39
|
const VALID_SKIP = [ 'off', 'breaks', 'idle time', 'pitches', 'commercials' ]
|
|
40
|
+
const DEFAULT_SKIP_ADJUST = 0
|
|
40
41
|
const VALID_PAD = [ 'off', 'on' ]
|
|
41
42
|
const VALID_FORCE_VOD = [ 'off', 'on' ]
|
|
42
43
|
const VALID_SCAN_MODES = [ 'off', 'on' ]
|
|
@@ -221,6 +222,8 @@ app.get('/clearcache', async function(req, res) {
|
|
|
221
222
|
|
|
222
223
|
session.log('Clearing cache...')
|
|
223
224
|
session.clear_cache()
|
|
225
|
+
session.log('Clearing session...')
|
|
226
|
+
session.clear_session_data()
|
|
224
227
|
session = new sessionClass(argv)
|
|
225
228
|
|
|
226
229
|
let server = 'http://' + req.headers.host
|
|
@@ -338,10 +341,12 @@ app.get('/stream.m3u8', async function(req, res) {
|
|
|
338
341
|
if ( gamePk ) {
|
|
339
342
|
options.gamePk = gamePk
|
|
340
343
|
|
|
344
|
+
let skip_adjust = parseInt(req.query.skip_adjust) || DEFAULT_SKIP_ADJUST
|
|
345
|
+
|
|
341
346
|
let skip_type = VALID_SKIP.indexOf(options.skip)
|
|
342
347
|
// for skip other than commercial skip, look up markers
|
|
343
348
|
if ( skip_type != 4 ) {
|
|
344
|
-
await session.getSkipMarkers(gamePk, skip_type, options.inning_number, options.inning_half, streamURL, streamURLToken)
|
|
349
|
+
await session.getSkipMarkers(gamePk, skip_type, options.inning_number, options.inning_half, streamURL, streamURLToken, skip_adjust)
|
|
345
350
|
}
|
|
346
351
|
}
|
|
347
352
|
}
|
|
@@ -455,6 +460,7 @@ function getMasterPlaylist(streamURL, req, res, options = {}) {
|
|
|
455
460
|
let inning_half = options.inning_half || VALID_INNING_HALF[0]
|
|
456
461
|
let inning_number = options.inning_number || VALID_INNING_NUMBER[0]
|
|
457
462
|
let skip = options.skip || VALID_SKIP[0]
|
|
463
|
+
let skip_adjust = options.skip_adjust || DEFAULT_SKIP_ADJUST
|
|
458
464
|
let pad = options.pad || VALID_PAD[0]
|
|
459
465
|
let gamePk = options.gamePk || false
|
|
460
466
|
|
|
@@ -530,19 +536,20 @@ function getMasterPlaylist(streamURL, req, res, options = {}) {
|
|
|
530
536
|
// we'll append to this and output track(s) at the end of this code block
|
|
531
537
|
let audio_output = ''
|
|
532
538
|
|
|
533
|
-
// default TV audio
|
|
539
|
+
// default TV audio, or park sounds
|
|
534
540
|
if ( !line.includes(',URI=') ) {
|
|
535
|
-
if ( audio_track == VALID_AUDIO_TRACKS[1] ) {
|
|
541
|
+
if ( (audio_track == VALID_AUDIO_TRACKS[1]) || (audio_track == VALID_AUDIO_TRACKS[6]) ) {
|
|
536
542
|
return line
|
|
537
543
|
} else if ( audio_track == VALID_AUDIO_TRACKS[0] ) {
|
|
538
544
|
audio_output += line
|
|
539
545
|
}
|
|
540
546
|
} else {
|
|
541
|
-
if ( (audio_track == VALID_AUDIO_TRACKS[0]) || (audio_track == VALID_AUDIO_TRACKS[2]) || (audio_track == VALID_AUDIO_TRACKS[3]) ) {
|
|
542
|
-
// if user specified home radio or home Spanish audio track, check if this one matches
|
|
543
|
-
if ( (audio_track == VALID_AUDIO_TRACKS[2]) || (audio_track == VALID_AUDIO_TRACKS[3]) ) {
|
|
547
|
+
if ( (audio_track == VALID_AUDIO_TRACKS[0]) || (audio_track == VALID_AUDIO_TRACKS[2]) || (audio_track == VALID_AUDIO_TRACKS[3]) || (audio_track == VALID_AUDIO_TRACKS[4]) || (audio_track == VALID_AUDIO_TRACKS[5]) ) {
|
|
548
|
+
// if user specified home/away radio or home/away Spanish audio track, check if this one matches
|
|
549
|
+
if ( (audio_track == VALID_AUDIO_TRACKS[2]) || (audio_track == VALID_AUDIO_TRACKS[3]) || (audio_track == VALID_AUDIO_TRACKS[4]) || (audio_track == VALID_AUDIO_TRACKS[5]) ) {
|
|
544
550
|
if ( line.includes('NAME="'+audio_track+'"') || line.includes('NAME="'+audio_track.substring(0,audio_track.length-1)+'"') ) {
|
|
545
551
|
audio_track_matched = true
|
|
552
|
+
line = line.replace('DEFAULT=NO','DEFAULT=YES')
|
|
546
553
|
line = line.replace('AUTOSELECT=NO','AUTOSELECT=YES')
|
|
547
554
|
if ( !line.includes(',DEFAULT=YES') ) line = line.replace('AUTOSELECT=YES','AUTOSELECT=YES,DEFAULT=YES')
|
|
548
555
|
} else {
|
|
@@ -559,6 +566,7 @@ function getMasterPlaylist(streamURL, req, res, options = {}) {
|
|
|
559
566
|
if ( inning_half != VALID_INNING_HALF[0] ) newurl += '&inning_half=' + inning_half
|
|
560
567
|
if ( inning_number != VALID_INNING_NUMBER[0] ) newurl += '&inning_number=' + inning_number
|
|
561
568
|
if ( skip != VALID_SKIP[0] ) newurl += '&skip=' + skip
|
|
569
|
+
if ( skip_adjust != DEFAULT_SKIP_ADJUST ) newurl += '&skip_adjust=' + skip_adjust
|
|
562
570
|
if ( pad != VALID_PAD[0] ) newurl += '&pad=' + pad
|
|
563
571
|
if ( gamePk ) newurl += '&gamePk=' + gamePk
|
|
564
572
|
newurl += content_protect + referer_parameter + token_parameter
|
|
@@ -626,8 +634,10 @@ function getMasterPlaylist(streamURL, req, res, options = {}) {
|
|
|
626
634
|
if ( inning_half != VALID_INNING_HALF[0] ) newurl += '&inning_half=' + inning_half
|
|
627
635
|
if ( inning_number != VALID_INNING_NUMBER[0] ) newurl += '&inning_number=' + inning_number
|
|
628
636
|
if ( skip != VALID_SKIP[0] ) newurl += '&skip=' + skip
|
|
637
|
+
if ( skip_adjust != DEFAULT_SKIP_ADJUST ) newurl += '&skip_adjust=' + skip_adjust
|
|
629
638
|
if ( pad != VALID_PAD[0] ) newurl += '&pad=' + pad
|
|
630
639
|
if ( gamePk ) newurl += '&gamePk=' + gamePk
|
|
640
|
+
if ( audio_track == VALID_AUDIO_TRACKS[6] ) newurl += '&park_audio=true'
|
|
631
641
|
newurl += content_protect + referer_parameter + token_parameter
|
|
632
642
|
return '/playlist?url='+newurl
|
|
633
643
|
}
|
|
@@ -681,8 +691,10 @@ app.get('/playlist', async function(req, res) {
|
|
|
681
691
|
var inning_half = req.query.inning_half || VALID_INNING_HALF[0]
|
|
682
692
|
var inning_number = req.query.inning_number || VALID_INNING_NUMBER[0]
|
|
683
693
|
var skip = req.query.skip || VALID_SKIP[0]
|
|
694
|
+
var skip_adjust = req.query.skip_adjust || DEFAULT_SKIP_ADJUST
|
|
684
695
|
var pad = req.query.pad || VALID_PAD[0]
|
|
685
696
|
var gamePk = req.query.gamePk || false
|
|
697
|
+
var park_audio = req.query.park_audio || false
|
|
686
698
|
|
|
687
699
|
var req = function () {
|
|
688
700
|
var headers = {}
|
|
@@ -807,6 +819,11 @@ app.get('/playlist', async function(req, res) {
|
|
|
807
819
|
newline += '?url='+encodeURIComponent(url.resolve(u, line.trim())) + content_protect + referer_parameter + token_parameter
|
|
808
820
|
if ( key ) newline += '&key='+encodeURIComponent(key) + '&iv='+encodeURIComponent(iv)
|
|
809
821
|
|
|
822
|
+
// park audio
|
|
823
|
+
if ( park_audio ) {
|
|
824
|
+
newline = 'download.html?park_audio=true&src=' + encodeURIComponent('http://127.0.0.1:' + session.data.port + newline) + content_protect
|
|
825
|
+
}
|
|
826
|
+
|
|
810
827
|
return newline
|
|
811
828
|
})
|
|
812
829
|
.filter(function(line) {
|
|
@@ -1045,10 +1062,10 @@ app.get('/gamechangerplaylist', async function(req, res) {
|
|
|
1045
1062
|
}
|
|
1046
1063
|
session.temp_cache.gamechanger[id].lastAccess = gamechangerAccess
|
|
1047
1064
|
|
|
1048
|
-
if ( !session.temp_cache.gamechanger.start || (gamechangerAccess < session.temp_cache.gamechanger.start) || !session.temp_cache.gamechanger.end || (gamechangerAccess > session.temp_cache.gamechanger.end) ) {
|
|
1065
|
+
/*if ( !session.temp_cache.gamechanger.start || (gamechangerAccess < session.temp_cache.gamechanger.start) || !session.temp_cache.gamechanger.end || (gamechangerAccess > session.temp_cache.gamechanger.end) ) {
|
|
1049
1066
|
session.log(game_changer_title + 'outside of games starting/ending, skipping')
|
|
1050
1067
|
respond(GAMECHANGER_RESPONSE_HEADERS, res, Buffer.from(''))
|
|
1051
|
-
} else {
|
|
1068
|
+
} else {*/
|
|
1052
1069
|
let streamURL
|
|
1053
1070
|
let streamURLToken
|
|
1054
1071
|
let discontinuity = false
|
|
@@ -1164,7 +1181,7 @@ app.get('/gamechangerplaylist', async function(req, res) {
|
|
|
1164
1181
|
respond(GAMECHANGER_RESPONSE_HEADERS, res, Buffer.from(session.temp_cache.gamechanger[id].playlist[resolution]))
|
|
1165
1182
|
}
|
|
1166
1183
|
}
|
|
1167
|
-
}
|
|
1184
|
+
//}
|
|
1168
1185
|
}
|
|
1169
1186
|
|
|
1170
1187
|
return req()
|
|
@@ -1329,6 +1346,10 @@ app.get('/', async function(req, res) {
|
|
|
1329
1346
|
if ( req.query.skip ) {
|
|
1330
1347
|
skip = req.query.skip
|
|
1331
1348
|
}
|
|
1349
|
+
var skip_adjust = DEFAULT_SKIP_ADJUST
|
|
1350
|
+
if ( req.query.skip_adjust ) {
|
|
1351
|
+
skip_adjust = req.query.skip_adjust
|
|
1352
|
+
}
|
|
1332
1353
|
var pad = VALID_PAD[0]
|
|
1333
1354
|
if ( req.query.pad ) {
|
|
1334
1355
|
pad = req.query.pad
|
|
@@ -1361,16 +1382,16 @@ app.get('/', async function(req, res) {
|
|
|
1361
1382
|
body += '</style><script type="text/javascript">' + "\n";
|
|
1362
1383
|
|
|
1363
1384
|
// Define option variables in page
|
|
1364
|
-
body += 'var date="' + gameDate + '";var level="' + level + '";var org="' + org + '";var mediaType="' + mediaType + '";var resolution="' + resolution + '";var audio_track="' + audio_track + '";var force_vod="' + force_vod + '";var inning_half="' + inning_half + '";var inning_number="' + inning_number + '";var skip="' + skip + '";var pad="' + pad + '";var linkType="' + linkType + '";var startFrom="' + startFrom + '";var scores="' + scores + '";var controls="' + controls + '";var scan_mode="' + scan_mode + '";var content_protect="' + content_protect + '";' + "\n"
|
|
1385
|
+
body += 'var date="' + gameDate + '";var level="' + level + '";var org="' + org + '";var mediaType="' + mediaType + '";var resolution="' + resolution + '";var audio_track="' + audio_track + '";var force_vod="' + force_vod + '";var inning_half="' + inning_half + '";var inning_number="' + inning_number + '";var skip="' + skip + '";var skip_adjust="' + skip_adjust + '";var pad="' + pad + '";var linkType="' + linkType + '";var startFrom="' + startFrom + '";var scores="' + scores + '";var controls="' + controls + '";var scan_mode="' + scan_mode + '";var content_protect="' + content_protect + '";' + "\n"
|
|
1365
1386
|
|
|
1366
1387
|
// Reload function, called after options change
|
|
1367
|
-
body += 'var defaultDate="' + today + '";var curDate=new Date();var utcHours=curDate.getUTCHours();if ((utcHours >= ' + todayUTCHours + ') && (utcHours < ' + YESTERDAY_UTC_HOURS + ')){defaultDate="' + yesterday + '"}function reload(){var newurl="/?";if (date != defaultDate){var urldate=date;if (date == "' + today + '"){urldate="today"}else if (date == "' + yesterday + '"){urldate="yesterday"}newurl+="date="+urldate+"&"}if (level != "' + default_level + '"){newurl+="level="+encodeURIComponent(level)+"&"}if (org != "All"){newurl+="org="+encodeURIComponent(org)+"&"}if (mediaType != "' + VALID_MEDIA_TYPES[0] + '"){newurl+="mediaType="+mediaType+"&"}if (mediaType=="Video"){if (resolution != "' + VALID_RESOLUTIONS[0] + '"){newurl+="resolution="+resolution+"&"}if (audio_track != "' + VALID_AUDIO_TRACKS[0] + '"){newurl+="audio_track="+encodeURIComponent(audio_track)+"&"}else if (resolution == "none"){newurl+="audio_track="+encodeURIComponent("' + VALID_AUDIO_TRACKS[2] + '")+"&"}if (inning_half != "' + VALID_INNING_HALF[0] + '"){newurl+="inning_half="+inning_half+"&"}if (inning_number != "' + VALID_INNING_NUMBER[0] + '"){newurl+="inning_number="+inning_number+"&"}if (skip != "' + VALID_SKIP[0] + '"){newurl+="skip="+skip+"&";}}if (pad != "' + VALID_PAD[0] + '"){newurl+="pad="+pad+"&";}if (linkType != "' + VALID_LINK_TYPES[0] + '"){newurl+="linkType="+linkType+"&"}if (linkType=="' + VALID_LINK_TYPES[0] + '"){if (startFrom != "' + VALID_START_FROM[0] + '"){newurl+="startFrom="+startFrom+"&"}if (controls != "' + VALID_CONTROLS[0] + '"){newurl+="controls="+controls+"&"}}if (linkType=="Stream"){if (force_vod != "' + VALID_FORCE_VOD[0] + '"){newurl+="force_vod="+force_vod+"&"}}if (scores != "' + VALID_SCORES[0] + '"){newurl+="scores="+scores+"&"}if (scan_mode != "' + session.data.scan_mode + '"){newurl+="scan_mode="+scan_mode+"&"}if (content_protect != ""){newurl+="content_protect="+content_protect+"&"}window.location=newurl.substring(0,newurl.length-1)}' + "\n"
|
|
1388
|
+
body += 'var defaultDate="' + today + '";var curDate=new Date();var utcHours=curDate.getUTCHours();if ((utcHours >= ' + todayUTCHours + ') && (utcHours < ' + YESTERDAY_UTC_HOURS + ')){defaultDate="' + yesterday + '"}function reload(){var newurl="/?";if (date != defaultDate){var urldate=date;if (date == "' + today + '"){urldate="today"}else if (date == "' + yesterday + '"){urldate="yesterday"}newurl+="date="+urldate+"&"}if (level != "' + default_level + '"){newurl+="level="+encodeURIComponent(level)+"&"}if (org != "All"){newurl+="org="+encodeURIComponent(org)+"&"}if (mediaType != "' + VALID_MEDIA_TYPES[0] + '"){newurl+="mediaType="+mediaType+"&"}if (mediaType=="Video"){if (resolution != "' + VALID_RESOLUTIONS[0] + '"){newurl+="resolution="+resolution+"&"}if (audio_track != "' + VALID_AUDIO_TRACKS[0] + '"){newurl+="audio_track="+encodeURIComponent(audio_track)+"&"}else if (resolution == "none"){newurl+="audio_track="+encodeURIComponent("' + VALID_AUDIO_TRACKS[2] + '")+"&"}if (inning_half != "' + VALID_INNING_HALF[0] + '"){newurl+="inning_half="+inning_half+"&"}if (inning_number != "' + VALID_INNING_NUMBER[0] + '"){newurl+="inning_number="+inning_number+"&"}if (skip != "' + VALID_SKIP[0] + '"){newurl+="skip="+skip+"&";if (skip_adjust != "' + DEFAULT_SKIP_ADJUST + '"){newurl+="skip_adjust="+skip_adjust+"&"}}}if (pad != "' + VALID_PAD[0] + '"){newurl+="pad="+pad+"&";}if (linkType != "' + VALID_LINK_TYPES[0] + '"){newurl+="linkType="+linkType+"&"}if (linkType=="' + VALID_LINK_TYPES[0] + '"){if (startFrom != "' + VALID_START_FROM[0] + '"){newurl+="startFrom="+startFrom+"&"}if (controls != "' + VALID_CONTROLS[0] + '"){newurl+="controls="+controls+"&"}}if (linkType=="Stream"){if (force_vod != "' + VALID_FORCE_VOD[0] + '"){newurl+="force_vod="+force_vod+"&"}}if (scores != "' + VALID_SCORES[0] + '"){newurl+="scores="+scores+"&"}if (scan_mode != "' + session.data.scan_mode + '"){newurl+="scan_mode="+scan_mode+"&"}if (content_protect != ""){newurl+="content_protect="+content_protect+"&"}window.location=newurl.substring(0,newurl.length-1)}' + "\n"
|
|
1368
1389
|
|
|
1369
1390
|
// Ajax function for multiview and highlights
|
|
1370
1391
|
body += 'function makeGETRequest(url, callback){var request=new XMLHttpRequest();request.onreadystatechange=function(){if (request.readyState==4 && request.status==200){callback(request.responseText)}};request.open("GET", url);request.send();}' + "\n"
|
|
1371
1392
|
|
|
1372
1393
|
// Multiview functions
|
|
1373
|
-
body += 'var excludeTeams=[];function parsemultiviewresponse(responsetext){if (responsetext == "started"){setTimeout(function(){document.getElementById("startmultiview").innerHTML="Restart";document.getElementById("stopmultiview").innerHTML="Stop"},15000)}else if (responsetext == "stopped"){setTimeout(function(){document.getElementById("stopmultiview").innerHTML="Stopped";document.getElementById("startmultiview").innerHTML="Start"},3000)}else{alert(responsetext)}}function addmultiview(e, teams=[], excludes=[]){var newvalue=e.value;for(var i=1;i<=4;i++){var valuefound = false;var oldvalue="";if(!e.checked){oldvalue=e.value;newvalue=""}if ((document.getElementById("multiview" + i).value == oldvalue) || ((oldvalue != "") && (document.getElementById("multiview" + i).value.startsWith(oldvalue)))){if ((newvalue != "") && (excludes.length > 0)){newvalue+="&excludeTeams="+excludeTeams.toString()}document.getElementById("multiview" + i).value=newvalue;valuefound=true;break}}if(e.checked && !valuefound){e.checked=false}for(var i=0;i<teams.length;i++){if(e.checked){excludeTeams.push(teams[i])}else{var index=excludeTeams.indexOf(teams[i]);if (index !== -1){excludeTeams.splice(index,1)}}}}function startmultiview(e){var count=0;var getstr="";for(var i=1;i<=4;i++){if (document.getElementById("multiview"+i).value != ""){count++;getstr+="streams="+encodeURIComponent(document.getElementById("multiview"+i).value)+"&sync="+encodeURIComponent(document.getElementById("sync"+i).value)+"' + content_protect_b + '"+"&"}}if((count >= 1) && (count <= 4)){if (document.getElementById("faster").checked){getstr+="faster=true&dvr=true&"}else if (document.getElementById("dvr").checked){getstr+="dvr=true&"}if (document.getElementById("reencode").checked){getstr+="reencode=true&"}if (document.getElementById("park_audio").checked){getstr+="park_audio=true&"}if (document.getElementById("audio_url").value != ""){getstr+="audio_url="+encodeURIComponent(document.getElementById("audio_url").value)+"&";if (document.getElementById("audio_url_seek").value != "0"){getstr+="audio_url_seek="+encodeURIComponent(document.getElementById("audio_url_seek").value)}}e.innerHTML="starting...";makeGETRequest("/multiview?"+getstr, parsemultiviewresponse)}else{alert("Multiview requires between 1-4 streams to be selected")}return false}function stopmultiview(e){e.innerHTML="stopping...";makeGETRequest("/multiview", parsemultiviewresponse);return false}' + "\n"
|
|
1394
|
+
body += 'var excludeTeams=[];function parsemultiviewresponse(responsetext){if (responsetext == "started"){setTimeout(function(){document.getElementById("startmultiview").innerHTML="Restart";document.getElementById("stopmultiview").innerHTML="Stop"},15000)}else if (responsetext == "stopped"){setTimeout(function(){document.getElementById("stopmultiview").innerHTML="Stopped";document.getElementById("startmultiview").innerHTML="Start"},3000)}else{alert(responsetext)}}function addmultiview(e, teams=[], excludes=[]){var newvalue=e.value;for(var i=1;i<=4;i++){var valuefound = false;var oldvalue="";if(!e.checked){oldvalue=e.value;newvalue=""}if ((document.getElementById("multiview" + i).value == oldvalue) || ((oldvalue != "") && (document.getElementById("multiview" + i).value.startsWith(oldvalue)))){if ((newvalue != "") && (excludes.length > 0)){newvalue+="&excludeTeams="+excludeTeams.toString()}document.getElementById("multiview" + i).value=newvalue;valuefound=true;break}}if(e.checked && !valuefound){e.checked=false}for(var i=0;i<teams.length;i++){if(e.checked){excludeTeams.push(teams[i])}else{var index=excludeTeams.indexOf(teams[i]);if (index !== -1){excludeTeams.splice(index,1)}}}}function startmultiview(e){var count=0;var getstr="";for(var i=1;i<=4;i++){if (document.getElementById("multiview"+i).value != ""){count++;getstr+="streams="+encodeURIComponent(document.getElementById("multiview"+i).value)+"&sync="+encodeURIComponent(document.getElementById("sync"+i).value)+"' + content_protect_b + '"+"&"}}if((count >= 1) && (count <= 4)){if (document.getElementById("faster").checked){getstr+="faster=true&dvr=true&"}else if (document.getElementById("dvr").checked){getstr+="dvr=true&"}if (document.getElementById("reencode").checked){getstr+="reencode=true&"}if (document.getElementById("park_audio").checked){getstr+="park_audio=true&"}if (document.getElementById("audio_url").value != ""){getstr+="audio_url="+encodeURIComponent(document.getElementById("audio_url").value)+"&";if (document.getElementById("audio_url_seek").value != "0"){getstr+="audio_url_seek="+encodeURIComponent(document.getElementById("audio_url_seek").value)}}e.innerHTML="starting...";makeGETRequest("/multiview?"+getstr, parsemultiviewresponse)}else{alert("Multiview requires between 1-4 streams to be selected")}return false}function stopmultiview(e){e.innerHTML="stopping...";makeGETRequest("/multiview' + content_protect_a + '", parsemultiviewresponse);return false}' + "\n"
|
|
1374
1395
|
|
|
1375
1396
|
// Function to switch URLs to stream URLs, where necessary
|
|
1376
1397
|
body += 'function stream_substitution(url){return url.replace(/\\/([a-zA-Z]+\.html)/,"/stream.m3u8")}' + "\n"
|
|
@@ -1417,7 +1438,7 @@ app.get('/', async function(req, res) {
|
|
|
1417
1438
|
}
|
|
1418
1439
|
body += '</p>' + "\n"
|
|
1419
1440
|
|
|
1420
|
-
body += '<p><span class="tooltip">Link Type<span class="tooltiptext">Embed will play in your browser (with AirPlay support), Stream will give you a stream URL to open directly in media players like Kodi or VLC, Chromecast is a desktop browser-based casting site,
|
|
1441
|
+
body += '<p><span class="tooltip">Link Type<span class="tooltiptext">Embed will play in your browser (with AirPlay support), Stream will give you a stream URL to open directly in media players like Kodi or VLC, Chromecast is a desktop browser-based casting site, Advanced will play in your desktop browser with some extra tools and debugging information (Advanced may require you to disable insecure / mixed content blocking in your browser), and Download will prompt your browser to save the stream to a TS (Transport Stream) file.<br><br>NOTE: Chromecast may not be able to resolve local domain names; if so, you can simply access this page (and thus the streams) using an IP address instead.</span></span>: '
|
|
1421
1442
|
for (var i = 0; i < VALID_LINK_TYPES.length; i++) {
|
|
1422
1443
|
body += '<button '
|
|
1423
1444
|
if ( linkType == VALID_LINK_TYPES[i] ) body += 'class="default" '
|
|
@@ -1484,7 +1505,7 @@ app.get('/', async function(req, res) {
|
|
|
1484
1505
|
if ( mediaType == VALID_MEDIA_TYPES[0] ) {
|
|
1485
1506
|
mediaType = 'MLBTV'
|
|
1486
1507
|
} else if ( mediaType == VALID_MEDIA_TYPES[2] ) {
|
|
1487
|
-
mediaType = VALID_MEDIA_TYPES[1]
|
|
1508
|
+
//mediaType = VALID_MEDIA_TYPES[1]
|
|
1488
1509
|
language = 'es'
|
|
1489
1510
|
}
|
|
1490
1511
|
if ( mediaType == VALID_MEDIA_TYPES[1] ) {
|
|
@@ -1518,11 +1539,13 @@ app.get('/', async function(req, res) {
|
|
|
1518
1539
|
if ( resolution != VALID_RESOLUTIONS[0] ) querystring += '&resolution=' + resolution
|
|
1519
1540
|
if ( linkType == VALID_LINK_TYPES[1] ) {
|
|
1520
1541
|
if ( force_vod != VALID_FORCE_VOD[0] ) querystring += '&force_vod=' + force_vod
|
|
1542
|
+
} else if ( linkType == VALID_LINK_TYPES[4] ) {
|
|
1543
|
+
querystring += '&filename=' + gameDate + ' MLB Network'
|
|
1521
1544
|
}
|
|
1522
1545
|
querystring += content_protect_b
|
|
1523
1546
|
multiviewquerystring += content_protect_b
|
|
1524
1547
|
body += '<a href="' + thislink + querystring + '">MLB Network</a>'
|
|
1525
|
-
body += '<input type="checkbox" value="' +
|
|
1548
|
+
body += '<input type="checkbox" value="http://127.0.0.1:' + session.data.port + '/stream.m3u8' + multiviewquerystring + '" onclick="addmultiview(this)">'
|
|
1526
1549
|
body += '</td></tr>' + "\n"
|
|
1527
1550
|
} // end entitlements check
|
|
1528
1551
|
} // end country check
|
|
@@ -1546,7 +1569,7 @@ app.get('/', async function(req, res) {
|
|
|
1546
1569
|
}*/
|
|
1547
1570
|
|
|
1548
1571
|
if ( (gameDate >= today) && cache_data.dates && cache_data.dates[0] && cache_data.dates[0].games && (cache_data.dates[0].games.length > 0) ) {
|
|
1549
|
-
blackouts = await session.get_blackout_games(cache_data.dates[0].
|
|
1572
|
+
blackouts = await session.get_blackout_games(cache_data.dates[0].date, true)
|
|
1550
1573
|
}
|
|
1551
1574
|
|
|
1552
1575
|
// Big Inning
|
|
@@ -1574,11 +1597,13 @@ app.get('/', async function(req, res) {
|
|
|
1574
1597
|
if ( resolution != VALID_RESOLUTIONS[0] ) querystring += '&resolution=' + resolution
|
|
1575
1598
|
if ( linkType == VALID_LINK_TYPES[1] ) {
|
|
1576
1599
|
if ( force_vod != VALID_FORCE_VOD[0] ) querystring += '&force_vod=' + force_vod
|
|
1600
|
+
} else if ( linkType == VALID_LINK_TYPES[4] ) {
|
|
1601
|
+
querystring += '&filename=' + gameDate + ' Big Inning'
|
|
1577
1602
|
}
|
|
1578
1603
|
querystring += content_protect_b
|
|
1579
1604
|
multiviewquerystring += content_protect_b
|
|
1580
1605
|
body += '<a href="' + thislink + querystring + '">Big Inning</a>'
|
|
1581
|
-
body += '<input type="checkbox" value="' +
|
|
1606
|
+
body += '<input type="checkbox" value="http://127.0.0.1:' + session.data.port + '/stream.m3u8' + multiviewquerystring + '" onclick="addmultiview(this)">'
|
|
1582
1607
|
} else {
|
|
1583
1608
|
body += 'Big Inning'
|
|
1584
1609
|
}
|
|
@@ -1605,8 +1630,11 @@ app.get('/', async function(req, res) {
|
|
|
1605
1630
|
if ( linkType != VALID_LINK_TYPES[1] ) {
|
|
1606
1631
|
streamURL = thislink + '?src=' + encodeURIComponent(streamURL) + '&startFrom=' + VALID_START_FROM[1] + content_protect_b
|
|
1607
1632
|
}
|
|
1633
|
+
if ( linkType == VALID_LINK_TYPES[4] ) {
|
|
1634
|
+
streamURL += '&filename=' + gameDate + ' Game Changer'
|
|
1635
|
+
}
|
|
1608
1636
|
body += '<a href="' + streamURL + '">Game Changer</a>'
|
|
1609
|
-
body += '<input type="checkbox" value="' + multiviewquerystring + '" onclick="addmultiview(this, [], excludeTeams)">'
|
|
1637
|
+
body += '<input type="checkbox" value="http://127.0.0.1:' + session.data.port + multiviewquerystring + '" onclick="addmultiview(this, [], excludeTeams)">'
|
|
1610
1638
|
} else {
|
|
1611
1639
|
body += 'Game Changer'
|
|
1612
1640
|
}
|
|
@@ -1624,14 +1652,18 @@ app.get('/', async function(req, res) {
|
|
|
1624
1652
|
let awayteam = cache_data.dates[0].games[j].teams['away'].team.abbreviation
|
|
1625
1653
|
let awayteam_abbr
|
|
1626
1654
|
if ( cache_data.dates[0].games[j].teams['away'].team.sport.name != 'Major League Baseball' ) {
|
|
1627
|
-
awayteam = cache_data.dates[0].games[j].teams['away'].team.shortName
|
|
1655
|
+
awayteam = cache_data.dates[0].games[j].teams['away'].team.shortName
|
|
1656
|
+
let parentOrgName = cache_data.dates[0].games[j].teams['away'].team.parentOrgName
|
|
1657
|
+
if (parentOrgName != 'Office of the Commissioner') awayteam += ' (' + session.getParent(parentOrgName) + ')'
|
|
1628
1658
|
awayteam_abbr = cache_data.dates[0].games[j].teams['away'].team.abbreviation
|
|
1629
1659
|
awayteam_level = session.getLevelNameFromSportId(cache_data.dates[0].games[j].teams['away'].team.sport.id)
|
|
1630
1660
|
}
|
|
1631
1661
|
let hometeam = cache_data.dates[0].games[j].teams['home'].team.abbreviation
|
|
1632
1662
|
let hometeam_abbr
|
|
1633
1663
|
if ( cache_data.dates[0].games[j].teams['home'].team.sport.name != 'Major League Baseball' ) {
|
|
1634
|
-
hometeam = cache_data.dates[0].games[j].teams['home'].team.shortName
|
|
1664
|
+
hometeam = cache_data.dates[0].games[j].teams['home'].team.shortName
|
|
1665
|
+
let parentOrgName = cache_data.dates[0].games[j].teams['home'].team.parentOrgName
|
|
1666
|
+
if (parentOrgName != 'Office of the Commissioner') hometeam += ' (' + session.getParent(parentOrgName) + ')'
|
|
1635
1667
|
hometeam_abbr = cache_data.dates[0].games[j].teams['home'].team.abbreviation
|
|
1636
1668
|
hometeam_level = session.getLevelNameFromSportId(cache_data.dates[0].games[j].teams['home'].team.sport.id)
|
|
1637
1669
|
}
|
|
@@ -1726,8 +1758,11 @@ app.get('/', async function(req, res) {
|
|
|
1726
1758
|
state += "<br/>" + detailedState
|
|
1727
1759
|
}
|
|
1728
1760
|
|
|
1761
|
+
var filename = gameDate + ' ' + teams + ' '
|
|
1762
|
+
|
|
1729
1763
|
if ( cache_data.dates[0].games[j].doubleHeader != 'N' ) {
|
|
1730
1764
|
state += "<br/>Game " + cache_data.dates[0].games[j].gameNumber
|
|
1765
|
+
filename += 'Game ' + cache_data.dates[0].games[j].gameNumber + ' '
|
|
1731
1766
|
}
|
|
1732
1767
|
if ( cache_data.dates[0].games[j].description ) {
|
|
1733
1768
|
state += "<br/>" + cache_data.dates[0].games[j].description
|
|
@@ -1824,7 +1859,11 @@ app.get('/', async function(req, res) {
|
|
|
1824
1859
|
startTime.setMinutes(startTime.getMinutes()-30)
|
|
1825
1860
|
if ( (currentTime >= startTime) ) {
|
|
1826
1861
|
let querystring
|
|
1827
|
-
|
|
1862
|
+
if ( cache_data.dates[0].games[j].teams['home'].team.league.id == session.getLidomId() ) {
|
|
1863
|
+
querystring = '?event=' + encodeURIComponent(cache_data.dates[0].games[j].teams['home'].team.clubName.toUpperCase())
|
|
1864
|
+
} else {
|
|
1865
|
+
querystring = '?gamePk=' + gamePk
|
|
1866
|
+
}
|
|
1828
1867
|
let multiviewquerystring = querystring + '&resolution=' + DEFAULT_MULTIVIEW_RESOLUTION
|
|
1829
1868
|
if ( resolution != VALID_RESOLUTIONS[0] ) querystring += '&resolution=' + resolution
|
|
1830
1869
|
if ( linkType == VALID_LINK_TYPES[0] ) {
|
|
@@ -1835,7 +1874,7 @@ app.get('/', async function(req, res) {
|
|
|
1835
1874
|
if ( inning_half != VALID_INNING_HALF[0] ) querystring += '&inning_half=' + inning_half
|
|
1836
1875
|
if ( inning_number != VALID_INNING_NUMBER[0] ) querystring += '&inning_number=' + relative_inning
|
|
1837
1876
|
if ( skip != VALID_SKIP[0] ) querystring += '&skip=' + skip
|
|
1838
|
-
|
|
1877
|
+
if ( skip_adjust != DEFAULT_SKIP_ADJUST ) querystring += '&skip_adjust=' + skip_adjust
|
|
1839
1878
|
}
|
|
1840
1879
|
if ( pad != VALID_PAD[0] ) querystring += '&pad=' + pad
|
|
1841
1880
|
if ( linkType == VALID_LINK_TYPES[1] ) {
|
|
@@ -1844,11 +1883,13 @@ app.get('/', async function(req, res) {
|
|
|
1844
1883
|
if ( currentTime < endTime ) {
|
|
1845
1884
|
if ( force_vod != VALID_FORCE_VOD[0] ) querystring += '&force_vod=' + force_vod
|
|
1846
1885
|
}
|
|
1886
|
+
} else if ( linkType == VALID_LINK_TYPES[4] ) {
|
|
1887
|
+
querystring += '&filename=' + filename + broadcastName
|
|
1847
1888
|
}
|
|
1848
1889
|
querystring += content_protect_b
|
|
1849
1890
|
multiviewquerystring += content_protect_b
|
|
1850
1891
|
body += '<a href="' + thislink + querystring + '">' + broadcastName + '</a>'
|
|
1851
|
-
body += '<input type="checkbox" value="' +
|
|
1892
|
+
body += '<input type="checkbox" value="http://127.0.0.1:' + session.data.port + '/stream.m3u8' + multiviewquerystring + '" onclick="addmultiview(this)">'
|
|
1852
1893
|
} else {
|
|
1853
1894
|
body += broadcastName
|
|
1854
1895
|
}
|
|
@@ -1898,8 +1939,6 @@ app.get('/', async function(req, res) {
|
|
|
1898
1939
|
body += ' (~' + blackouts[gamePk].blackoutExpiry.toLocaleString('en-US', { hour: 'numeric', minute: 'numeric', hour12: true }) + ')'
|
|
1899
1940
|
}
|
|
1900
1941
|
body += '</span></span>'
|
|
1901
|
-
} else if ( (station == 'FOX') ) {
|
|
1902
|
-
body += '<span class="tooltip">' + teamabbr + '<span class="tooltiptext">Regional FOX game</span></span>'
|
|
1903
1942
|
} else {
|
|
1904
1943
|
body += teamabbr
|
|
1905
1944
|
}
|
|
@@ -1927,6 +1966,7 @@ app.get('/', async function(req, res) {
|
|
|
1927
1966
|
if ( inning_half != VALID_INNING_HALF[0] ) querystring += '&inning_half=' + inning_half
|
|
1928
1967
|
if ( inning_number != VALID_INNING_NUMBER[0] ) querystring += '&inning_number=' + relative_inning
|
|
1929
1968
|
if ( skip != VALID_SKIP[0] ) querystring += '&skip=' + skip
|
|
1969
|
+
if ( skip_adjust != DEFAULT_SKIP_ADJUST ) querystring += '&skip_adjust=' + skip_adjust
|
|
1930
1970
|
if ( (inning_half != VALID_INNING_HALF[0]) || (inning_number != VALID_INNING_NUMBER[0]) || (skip != VALID_SKIP[0]) ) {
|
|
1931
1971
|
querystring += '&gamePk=' + cache_data.dates[0].games[j].gamePk
|
|
1932
1972
|
}
|
|
@@ -1938,6 +1978,8 @@ app.get('/', async function(req, res) {
|
|
|
1938
1978
|
if ( broadcast.mediaState.mediaStateCode == 'MEDIA_ON' ) {
|
|
1939
1979
|
if ( force_vod != VALID_FORCE_VOD[0] ) querystring += '&force_vod=' + force_vod
|
|
1940
1980
|
}
|
|
1981
|
+
} else if ( linkType == VALID_LINK_TYPES[4] ) {
|
|
1982
|
+
querystring += '&filename=' + filename + station
|
|
1941
1983
|
}
|
|
1942
1984
|
querystring += content_protect_b
|
|
1943
1985
|
multiviewquerystring += content_protect_b
|
|
@@ -1949,7 +1991,7 @@ app.get('/', async function(req, res) {
|
|
|
1949
1991
|
body += stationlink
|
|
1950
1992
|
}
|
|
1951
1993
|
if ( mediaType == 'MLBTV' ) {
|
|
1952
|
-
body += '<input type="checkbox" value="' +
|
|
1994
|
+
body += '<input type="checkbox" value="http://127.0.0.1:' + session.data.port + '/stream.m3u8' + multiviewquerystring + '" onclick="addmultiview(this, [\'' + awayteam + '\', \'' + hometeam + '\'])">'
|
|
1953
1995
|
}
|
|
1954
1996
|
if ( resumeStatus ) {
|
|
1955
1997
|
body += '('
|
|
@@ -2053,6 +2095,9 @@ app.get('/', async function(req, res) {
|
|
|
2053
2095
|
if ( skip == VALID_SKIP[i] ) body += 'class="default" '
|
|
2054
2096
|
body += 'onclick="skip=\'' + VALID_SKIP[i] + '\';reload()">' + VALID_SKIP[i] + '</button> '
|
|
2055
2097
|
}
|
|
2098
|
+
if ( skip != VALID_SKIP[0] ) {
|
|
2099
|
+
body += '<br><span class="tooltip">Skip Adjust<span class="tooltiptext">Seconds to adjust the skip time video segments, if necessary. Try a negative number if the plays are ending before the video segments begin; use a positive number if the video segments are ending before the play happens.</span></span>: <input type="number" id="skip_adjust" value="' + skip_adjust + '" step="1" onchange="setTimeout(function(){skip_adjust=document.getElementById(\'skip_adjust\').value;reload()},750)" onblur="skip_adjust=this.value;reload()" style="vertical-align:top;font-size:.8em;width:3em"/>'
|
|
2100
|
+
}
|
|
2056
2101
|
body += '</p>' + "\n"
|
|
2057
2102
|
}
|
|
2058
2103
|
|
|
@@ -2081,7 +2126,7 @@ app.get('/', async function(req, res) {
|
|
|
2081
2126
|
body += '<input type="checkbox" id="reencode"/> <span class="tooltip">Re-encode all audio<span class="tooltiptext">Uses more CPU. Generally only necessary if you need the multiview stream to continue after one of the individual streams has ended. (Any streams with sync adjustments above will automatically be re-encoded, regardless of this setting.)</span></span><br/>' + "\n"
|
|
2082
2127
|
body += '<input type="checkbox" id="park_audio"/> <span class="tooltip">Park audio: filter out announcers<span class="tooltiptext">Implies re-encoding all audio. If this is enabled, an extra audio filter is applied to remove the announcer voices.</span></span><br/>' + "\n"
|
|
2083
2128
|
body += '<hr><span class="tooltip">Alternate audio URL and sync<span class="tooltiptext">Optional: you can also include a separate audio-only URL as an additional alternate audio track. Archive games will likely require a very large negative sync value, as the radio broadcasts may not be trimmed like the video archives.</span></span>:<br/><textarea id="audio_url" rows=2 cols=60 oninput="this.value=stream_substitution(this.value)"></textarea><input id="audio_url_seek" type="number" value="0" style="vertical-align:top;font-size:.8em;width:4em"/>'
|
|
2084
|
-
body += '<hr>Watch: <a href="/embed.html?src=' + encodeURIComponent(multiview_server + multiview_url_path) + '">Embed</a> | <a href="' + multiview_server + multiview_url_path + '">Stream</a> | <a href="/chromecast.html?src=' + encodeURIComponent(multiview_server + multiview_url_path) + '">Chromecast</a> | <a href="/advanced.html?src=' + encodeURIComponent(multiview_server + multiview_url_path) + '">Advanced</a><br/><span class="tinytext">
|
|
2129
|
+
body += '<hr>Watch: <a href="/embed.html?src=' + encodeURIComponent(multiview_server + multiview_url_path) + content_protect_b + '">Embed</a> | <a href="' + multiview_server + multiview_url_path + content_protect_b + '">Stream</a> | <a href="/chromecast.html?src=' + encodeURIComponent(multiview_server + multiview_url_path) + content_protect_b + '">Chromecast</a> | <a href="/advanced.html?src=' + encodeURIComponent(multiview_server + multiview_url_path) + content_protect_b + '">Advanced</a> | <a href="/download.html?src=' + encodeURIComponent(multiview_server + multiview_url_path) + content_protect_b + '&filename=' + gameDate + ' Multiview">Download</a><br/><span class="tinytext">Kodi STRM files: <a href="/kodi.strm?src=' + encodeURIComponent(multiview_server + multiview_url_path) + content_protect_b + '">Matrix/19+</a> (<a href="/kodi.strm?version=18&src=' + encodeURIComponent(multiview_server + multiview_url_path) + content_protect_b + '">Leia/18</a>)</span>'
|
|
2085
2130
|
body += '</td></tr></table><br/>' + "\n"
|
|
2086
2131
|
}
|
|
2087
2132
|
|
|
@@ -2215,7 +2260,7 @@ app.get('/', async function(req, res) {
|
|
|
2215
2260
|
body += '<p><span class="tooltip">Bookmarklets for MLB.com<span class="tooltiptext">If you watch at MLB.com, drag these bookmarklets to your bookmarks toolbar and use them to hide parts of the interface.</span></span>: <a href="javascript:(function(){let x=document.querySelector(\'#mlbtv-stats-panel\');if(x.style.display==\'none\'){x.style.display=\'initial\';}else{x.style.display=\'none\';}})();">Boxscore</a> | <a href="javascript:(function(){let x=document.querySelector(\'.mlbtv-header-container\');if(x.style.display==\'none\'){let y=document.querySelector(\'.mlbtv-players-container\');y.style.display=\'none\';x.style.display=\'initial\';setTimeout(function(){y.style.display=\'initial\';},15);}else{x.style.display=\'none\';}})();">Scoreboard</a> | <a href="javascript:(function(){let x=document.querySelector(\'.mlbtv-container--footer\');if(x.style.display==\'none\'){let y=document.querySelector(\'.mlbtv-players-container\');y.style.display=\'none\';x.style.display=\'initial\';setTimeout(function(){y.style.display=\'initial\';},15);}else{x.style.display=\'none\';}})();">Linescore</a> | <a href="javascript:(function(){let x=document.querySelector(\'#mlbtv-stats-panel\');if(x.style.display==\'none\'){x.style.display=\'initial\';}else{x.style.display=\'none\';}x=document.querySelector(\'.mlbtv-header-container\');if(x.style.display==\'none\'){x.style.display=\'initial\';}else{x.style.display=\'none\';}x=document.querySelector(\'.mlbtv-container--footer\');if(x.style.display==\'none\'){let y=document.querySelector(\'.mlbtv-players-container\');y.style.display=\'none\';x.style.display=\'initial\';setTimeout(function(){y.style.display=\'initial\';},15);}else{x.style.display=\'none\';}})();">All</a></p>' + "\n"
|
|
2216
2261
|
|
|
2217
2262
|
// Print version
|
|
2218
|
-
body += '<p class="tinytext">Version ' + version + ' (<a href="/clearcache">clear cache</a>)</p>' + "\n"
|
|
2263
|
+
body += '<p class="tinytext">Version ' + version + ' (<a href="/clearcache">clear session and cache</a>)</p>' + "\n"
|
|
2219
2264
|
|
|
2220
2265
|
// Datepicker functions
|
|
2221
2266
|
body += '<script>var datePicker=document.getElementById("gameDate");function changeDate(e){date=datePicker.value;reload()}function removeDate(e){datePicker.removeEventListener("change",changeDate,false);datePicker.addEventListener("blur",changeDate,false);if(e.keyCode===13){date=datePicker.value;reload()}}datePicker.addEventListener("change",changeDate,false);datePicker.addEventListener("keypress",removeDate,false)</script>' + "\n"
|
|
@@ -2321,7 +2366,7 @@ app.get('/advanced.html', async function(req, res) {
|
|
|
2321
2366
|
}
|
|
2322
2367
|
session.debuglog('advanced embed src : ' + video_url)
|
|
2323
2368
|
|
|
2324
|
-
res.redirect('
|
|
2369
|
+
res.redirect('https://hls-js-dev.netlify.app/demo/?src=' + encodeURIComponent(video_url))
|
|
2325
2370
|
})
|
|
2326
2371
|
|
|
2327
2372
|
// Listen for Chromecast request, redirect to chromecast.link player
|
|
@@ -2710,13 +2755,19 @@ function start_multiview_stream(streams, sync, dvr, faster, reencode, park_audio
|
|
|
2710
2755
|
audio_reencoded = []
|
|
2711
2756
|
for (var i=0; i<audio_present.length; i++) {
|
|
2712
2757
|
//let audio_input = audio_present[i] + ':a:m:language:en?'
|
|
2713
|
-
let audio_input = audio_present[i] + ':a:
|
|
2758
|
+
let audio_input = audio_present[i] + ':a:'
|
|
2759
|
+
let video_url = streams[audio_present[i]]
|
|
2760
|
+
if ( video_url.includes('audio_track=English') || !video_url.includes('audio_track=') ) {
|
|
2761
|
+
audio_input += '0'
|
|
2762
|
+
} else {
|
|
2763
|
+
audio_input += '1'
|
|
2764
|
+
}
|
|
2714
2765
|
let filter = ''
|
|
2715
2766
|
// Optionally apply sync adjustments
|
|
2716
2767
|
if ( sync[audio_present[i]] ) {
|
|
2717
2768
|
if ( sync[audio_present[i]] > 0 ) {
|
|
2718
2769
|
session.log('delaying audio for stream ' + (audio_present[i]+1) + ' by ' + sync[audio_present[i]] + ' seconds')
|
|
2719
|
-
filter = 'adelay=' + (sync[i] * 1000) + ','
|
|
2770
|
+
filter = 'adelay=' + (sync[i] * 1000) + ':all=1,'
|
|
2720
2771
|
} else if ( sync[audio_present[i]] < 0 ) {
|
|
2721
2772
|
session.log('trimming audio for stream ' + (audio_present[i]+1) + ' by ' + sync[audio_present[i]] + ' seconds')
|
|
2722
2773
|
filter = 'atrim=start=' + (sync[audio_present[i]] * -1) + 's,'
|
|
@@ -2747,7 +2798,13 @@ function start_multiview_stream(streams, sync, dvr, faster, reencode, park_audio
|
|
|
2747
2798
|
if ( audio_reencoded.indexOf(audio_present[i]) > -1 ) {
|
|
2748
2799
|
audio_output = '[out' + i + ']'
|
|
2749
2800
|
} else {
|
|
2750
|
-
audio_output = audio_present[i] + ':a:
|
|
2801
|
+
audio_output = audio_present[i] + ':a:'
|
|
2802
|
+
let video_url = streams[audio_present[i]]
|
|
2803
|
+
if ( video_url.includes('audio_track=English') || !video_url.includes('audio_track=') ) {
|
|
2804
|
+
audio_output += '0'
|
|
2805
|
+
} else {
|
|
2806
|
+
audio_output += '1'
|
|
2807
|
+
}
|
|
2751
2808
|
}
|
|
2752
2809
|
ffmpeg_command.addOutputOption('-map', audio_output)
|
|
2753
2810
|
var_stream_map += ' a:' + i + ',agroup:aac,language:ENG'
|
|
@@ -2898,3 +2955,94 @@ app.get('/kodi.strm', async function(req, res) {
|
|
|
2898
2955
|
res.end('kodi.strm request error, check log')
|
|
2899
2956
|
}
|
|
2900
2957
|
})
|
|
2958
|
+
|
|
2959
|
+
// Listen for download requests
|
|
2960
|
+
app.get('/download.html', async function(req, res) {
|
|
2961
|
+
if ( ! (await protect(req, res)) ) return
|
|
2962
|
+
|
|
2963
|
+
try {
|
|
2964
|
+
if ( req.query.park_audio ) {
|
|
2965
|
+
session.debuglog('parkaudio', req)
|
|
2966
|
+
} else {
|
|
2967
|
+
session.requestlog('download', req)
|
|
2968
|
+
}
|
|
2969
|
+
|
|
2970
|
+
let server = 'http://' + req.headers.host
|
|
2971
|
+
|
|
2972
|
+
let video_url = '/stream.m3u8'
|
|
2973
|
+
if ( req.query.src ) {
|
|
2974
|
+
video_url = req.query.src
|
|
2975
|
+
} else {
|
|
2976
|
+
let urlArray = req.url.split('?')
|
|
2977
|
+
if ( (urlArray.length == 2) ) {
|
|
2978
|
+
video_url += '?' + urlArray[1]
|
|
2979
|
+
}
|
|
2980
|
+
video_url = server + video_url
|
|
2981
|
+
}
|
|
2982
|
+
session.debuglog('download src : ' + video_url)
|
|
2983
|
+
|
|
2984
|
+
ffmpeg_command = ffmpeg({ timeout: 432000 })
|
|
2985
|
+
|
|
2986
|
+
// park audio
|
|
2987
|
+
if ( req.query.park_audio ) {
|
|
2988
|
+
ffmpeg_command.complexFilter([{
|
|
2989
|
+
filter: 'pan=stereo|c0=c0|c1=-1*c1',
|
|
2990
|
+
inputs: '0:a:0',
|
|
2991
|
+
outputs: 'out0'
|
|
2992
|
+
}])
|
|
2993
|
+
|
|
2994
|
+
// Set input stream, minimize ffmpeg startup latency, re-encode audio to mono, and copy source PTS values
|
|
2995
|
+
ffmpeg_command.input(video_url)
|
|
2996
|
+
.addInputOption('-fflags', 'nobuffer')
|
|
2997
|
+
.addInputOption('-probesize', '32')
|
|
2998
|
+
.addInputOption('-analyzeduration', '0')
|
|
2999
|
+
.addOutputOption('-map', '0:v:0')
|
|
3000
|
+
.addOutputOption('-map', '[out0]')
|
|
3001
|
+
.addOutputOption('-c:v', 'copy')
|
|
3002
|
+
.addOutputOption('-c:a', 'aac')
|
|
3003
|
+
.addOutputOption('-ac:a:0', '1')
|
|
3004
|
+
.addOutputOption('-copyts')
|
|
3005
|
+
.addOutputOption('-muxpreload', '0')
|
|
3006
|
+
.addOutputOption('-muxdelay', '0')
|
|
3007
|
+
} else {
|
|
3008
|
+
// Set input stream
|
|
3009
|
+
ffmpeg_command.input(video_url)
|
|
3010
|
+
.addOutputOption('-c', 'copy')
|
|
3011
|
+
}
|
|
3012
|
+
|
|
3013
|
+
ffmpeg_command.addOutputOption('-f', 'mpegts')
|
|
3014
|
+
.output(res)
|
|
3015
|
+
.on('start', function(commandLine) {
|
|
3016
|
+
session.debuglog('download command started')
|
|
3017
|
+
if ( argv.debug || argv.ffmpeg_logging ) {
|
|
3018
|
+
session.debuglog('download command: ' + commandLine)
|
|
3019
|
+
}
|
|
3020
|
+
})
|
|
3021
|
+
.on('error', function(err, stdout, stderr) {
|
|
3022
|
+
session.debuglog('download command stopped: ' + err.message)
|
|
3023
|
+
if ( stdout ) session.log(stdout)
|
|
3024
|
+
if ( stderr ) session.log(stderr)
|
|
3025
|
+
})
|
|
3026
|
+
.on('end', function() {
|
|
3027
|
+
session.debuglog('download command ended')
|
|
3028
|
+
})
|
|
3029
|
+
|
|
3030
|
+
if ( argv.ffmpeg_logging ) {
|
|
3031
|
+
session.log('ffmpeg output logging enabled')
|
|
3032
|
+
ffmpeg_command.on('stderr', function(stderrLine) {
|
|
3033
|
+
session.log(stderrLine);
|
|
3034
|
+
})
|
|
3035
|
+
}
|
|
3036
|
+
|
|
3037
|
+
var download_headers = {}
|
|
3038
|
+
if ( req.query.filename ) {
|
|
3039
|
+
download_headers['Content-Disposition'] = 'attachment; filename="' + req.query.filename + '.ts"'
|
|
3040
|
+
}
|
|
3041
|
+
res.writeHead(200, download_headers)
|
|
3042
|
+
|
|
3043
|
+
ffmpeg_command.run()
|
|
3044
|
+
} catch (e) {
|
|
3045
|
+
session.log('download request error : ' + e.message)
|
|
3046
|
+
res.end('')
|
|
3047
|
+
}
|
|
3048
|
+
})
|
package/package.json
CHANGED
package/session.js
CHANGED
|
@@ -32,7 +32,12 @@ const AFFILIATE_TEAM_IDS = { 'ATL': '430,431,432,478', 'AZ': '419,516,2310,5368'
|
|
|
32
32
|
const ESPN_SUNDAY_NIGHT_BLACKOUT_COUNTRIES = ["Angola", "Anguilla", "Antigua and Barbuda", "Argentina", "Aruba", "Australia", "Bahamas", "Barbados", "Belize", "Belize", "Benin", "Bermuda", "Bolivia", "Bonaire", "Botswana", "Brazil", "British Virgin Islands", "Burkina Faso", "Burundi", "Cameroon", "Cape Verde", "Cayman Islands", "Central African Republic", "Chad", "Chile", "Colombia", "Comoros", "Cook Islands", "Costa Rica", "Cote d'Ivoire", "Curacao", "Democratic Republic of the Congo", "Djibouti", "Dominica", "Dominican Republic", "Ecuador", "El Salvador", "England", "Equatorial Guinea", "Eritrea", "Eswatini", "Ethiopia", "Falkland Islands", "Falkland Islands", "Fiji", "French Guiana", "French Guiana", "French Polynesia", "Gabon", "Ghana", "Grenada", "Guadeloupe", "Guatemala", "Guinea", "Guinea Bissau", "Guyana", "Guyana", "Haiti", "Honduras", "Ireland", "Jamaica", "Kenya", "Kiribati", "Lesotho", "Liberia", "Madagascar", "Malawi", "Mali", "Marshall Islands", "Martinique", "Mayotte", "Mexico", "Micronesia", "Montserrat", "Mozambique", "Namibia", "Netherlands", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Niue", "Northern Ireland", "Palau Islands", "Panama", "Paraguay", "Peru", "Republic of Ireland", "Reunion", "Rwanda", "Saba", "Saint Maarten", "Samoa", "Sao Tome & Principe", "Scotland", "Senegal", "Seychelles", "Sierra Leone", "Solomon Islands", "Somalia", "South Africa", "St. Barthelemy", "St. Eustatius", "St. Kitts and Nevis", "St. Lucia", "St. Martin", "St. Vincent and the Grenadines", "Sudan", "Surinam", "Suriname", "Tahiti", "Tanzania & Zanzibar", "The Gambia", "The Republic of Congo", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Turks and Caicos Islands", "Tuvalu", "Uganda", "Uruguay", "Venezuela", "Wales", "Zambia", "Zimbabwe"]
|
|
33
33
|
|
|
34
34
|
// First is default level, last should be All (also used as default org)
|
|
35
|
-
const LEVELS = { 'MLB': '1', 'AAA': '11', 'AA': '12', 'A+': '13', 'A': '14', 'All': '1,11,12,13,14' }
|
|
35
|
+
const LEVELS = { 'MLB': '1', 'AAA': '11', 'AA': '12', 'A+': '13', 'A': '14', 'WINTER': '17', 'All': '1,11,12,13,14,17' }
|
|
36
|
+
|
|
37
|
+
// Winter Leagues
|
|
38
|
+
const AFL_ID = '119'
|
|
39
|
+
const LIDOM_ID = '131'
|
|
40
|
+
const WINTER_LEAGUES = [AFL_ID, LIDOM_ID]
|
|
36
41
|
|
|
37
42
|
// These are the events to ignore, if we're skipping breaks
|
|
38
43
|
const BREAK_TYPES = ['Game Advisory', 'Pitching Substitution', 'Offensive Substitution', 'Defensive Sub', 'Defensive Switch', 'Runner Placed On Base']
|
|
@@ -1109,6 +1114,10 @@ class sessionClass {
|
|
|
1109
1114
|
return LEVELS
|
|
1110
1115
|
}
|
|
1111
1116
|
|
|
1117
|
+
getLidomId() {
|
|
1118
|
+
return LIDOM_ID
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1112
1121
|
getLevelNameFromSportId(sportId) {
|
|
1113
1122
|
let sportIds = Object.values(LEVELS)
|
|
1114
1123
|
for (var i=0; i<sportIds.length; i++) {
|
|
@@ -1201,6 +1210,17 @@ class sessionClass {
|
|
|
1201
1210
|
this.save_cache_data()
|
|
1202
1211
|
}
|
|
1203
1212
|
|
|
1213
|
+
setBlackoutsCacheExpiry(cache_name, expiryDate) {
|
|
1214
|
+
if ( !this.cache.blackouts ) {
|
|
1215
|
+
this.cache.blackouts={}
|
|
1216
|
+
}
|
|
1217
|
+
if ( !this.cache.blackouts[cache_name] ) {
|
|
1218
|
+
this.cache.blackouts[cache_name] = {}
|
|
1219
|
+
}
|
|
1220
|
+
this.cache.blackouts[cache_name].blackoutsCacheExpiry = expiryDate
|
|
1221
|
+
this.save_cache_data()
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1204
1224
|
setDateCacheExpiry(cache_name, expiryDate) {
|
|
1205
1225
|
if ( !this.cache.dates ) {
|
|
1206
1226
|
this.cache.dates={}
|
|
@@ -1663,6 +1683,7 @@ class sessionClass {
|
|
|
1663
1683
|
this.data.loginToken = obj.access_token
|
|
1664
1684
|
this.data.loginTokenExpiry = new Date(new Date().getTime() + obj.expires_in * 1000)
|
|
1665
1685
|
this.save_session_data()
|
|
1686
|
+
await this.getSession()
|
|
1666
1687
|
return this.data.loginToken
|
|
1667
1688
|
} else {
|
|
1668
1689
|
this.log('getLoginToken response failure')
|
|
@@ -1673,6 +1694,53 @@ class sessionClass {
|
|
|
1673
1694
|
}
|
|
1674
1695
|
}
|
|
1675
1696
|
|
|
1697
|
+
// API call
|
|
1698
|
+
async getOktaId() {
|
|
1699
|
+
this.debuglog('getOktaId')
|
|
1700
|
+
if ( !this.data.oktaId ) {
|
|
1701
|
+
this.debuglog('need to get oktaId')
|
|
1702
|
+
// get a sample playback token from which to extract the base64-encoded okta_id
|
|
1703
|
+
let token
|
|
1704
|
+
|
|
1705
|
+
// use any currently cached playback token
|
|
1706
|
+
try {
|
|
1707
|
+
this.debuglog('getOktaId attempting to use cached playback token')
|
|
1708
|
+
let mediaIds = Object.keys(this.cache.media)
|
|
1709
|
+
for (var i=0; i<mediaIds.length; i++) {
|
|
1710
|
+
if ( this.cache.media[mediaIds[i]].streamURLToken && (this.cache.media[mediaIds[i]].streamURLToken != '') ) {
|
|
1711
|
+
this.debuglog('getOktaId using cached playback token')
|
|
1712
|
+
token = this.cache.media[mediaIds[i]].streamURLToken
|
|
1713
|
+
break
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
} catch(e) {
|
|
1717
|
+
this.debuglog('getOktaId failed to use cached playback token')
|
|
1718
|
+
}
|
|
1719
|
+
|
|
1720
|
+
// otherwise, get a new playback token for a past free game
|
|
1721
|
+
if ( !token ) {
|
|
1722
|
+
this.debuglog('getOktaId getting new playback token')
|
|
1723
|
+
let streamInfo = await this.getStreamURL('b7f0fff7-266f-4171-aa2d-af7988dc9302')
|
|
1724
|
+
token = streamInfo.streamURLToken
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1727
|
+
if ( token ) {
|
|
1728
|
+
this.debuglog('getOktaId using token ' + token)
|
|
1729
|
+
let encoded_okta_id = token.split('_')[1]
|
|
1730
|
+
let okta_id = Buffer.from(encoded_okta_id + '==', 'base64').toString('ascii')
|
|
1731
|
+
this.debuglog('getOktaId extracted okta_id ' + okta_id)
|
|
1732
|
+
this.data.oktaId = okta_id
|
|
1733
|
+
this.save_session_data()
|
|
1734
|
+
return this.data.oktaId
|
|
1735
|
+
} else {
|
|
1736
|
+
this.debuglog('failed to get oktaId')
|
|
1737
|
+
}
|
|
1738
|
+
} else {
|
|
1739
|
+
this.debuglog('using cached oktaId')
|
|
1740
|
+
return this.data.oktaId
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1676
1744
|
// get mediaId for a live channel request
|
|
1677
1745
|
async getMediaId(team, level, mediaType, mediaDate, gameNumber, includeBlackouts) {
|
|
1678
1746
|
try {
|
|
@@ -1714,7 +1782,7 @@ class sessionClass {
|
|
|
1714
1782
|
let nationalCount = 0
|
|
1715
1783
|
let freeCount = 0
|
|
1716
1784
|
let blackouts = {}
|
|
1717
|
-
if ( includeBlackouts == 'false' ) blackouts = await this.get_blackout_games(cache_data.dates[0].
|
|
1785
|
+
if ( includeBlackouts == 'false' ) blackouts = await this.get_blackout_games(cache_data.dates[0].date, true)
|
|
1718
1786
|
|
|
1719
1787
|
for (var j = 0; j < cache_data.dates[0].games.length; j++) {
|
|
1720
1788
|
if ( mediaInfo.mediaId || mediaInfo.gamePk ) break
|
|
@@ -1729,10 +1797,10 @@ class sessionClass {
|
|
|
1729
1797
|
this.debuglog('checking game ' + cache_data.dates[0].games[j].teams['home'].team.abbreviation + '@' + cache_data.dates[0].games[j].teams['away'].team.abbreviation)
|
|
1730
1798
|
|
|
1731
1799
|
// check that that game involves the requested team, or if we've requested a national or free game
|
|
1732
|
-
if ( ((team.toUpperCase() == home_team) && (LEVELS[level.toUpperCase()] == home_level)) || ((team.toUpperCase() == away_team) && (LEVELS[level.toUpperCase()] == away_level)) || (team.toUpperCase().indexOf('NATIONAL.') == 0) || ((team.toUpperCase().startsWith('FREE.') && cache_data.dates[0].games[j].broadcasts && cache_data.dates[0].games[j].broadcasts[0] && (cache_data.dates[0].games[j].broadcasts[0].freeGame == true))) ) {
|
|
1800
|
+
if ( ((team.toUpperCase() == home_team) && (LEVELS[level.toUpperCase()] == home_level)) || ((team.toUpperCase() == away_team) && (LEVELS[level.toUpperCase()] == away_level)) || ((team.toUpperCase().indexOf('NATIONAL.') == 0) && (home_level == LEVELS['MLB'])) || ((team.toUpperCase().startsWith('FREE.') && cache_data.dates[0].games[j].broadcasts && cache_data.dates[0].games[j].broadcasts[0] && (cache_data.dates[0].games[j].broadcasts[0].freeGame == true))) ) {
|
|
1733
1801
|
|
|
1734
1802
|
// Check if Winter League / MiLB game first
|
|
1735
|
-
if ( (
|
|
1803
|
+
if ( (home_level != LEVELS['MLB']) && (mediaType == 'MLBTV') ) {
|
|
1736
1804
|
this.debuglog('matched non-MLB team for ' + cache_data.dates[0].games[j].teams['home'].team.abbreviation + '@' + cache_data.dates[0].games[j].teams['away'].team.abbreviation)
|
|
1737
1805
|
if ( cache_data.dates[0].games[j].broadcasts ) {
|
|
1738
1806
|
let broadcastName = 'N/A'
|
|
@@ -1946,7 +2014,7 @@ class sessionClass {
|
|
|
1946
2014
|
cache_name += '.' + team_ids
|
|
1947
2015
|
}
|
|
1948
2016
|
//let data_url = 'https://bdfed.stitch.mlbinfra.com/bdfed/transform-mlb-scoreboard?stitch_env=prod&sortTemplate=2&sportId=1&sportId=17&startDate=' + dateString + '&endDate=' + dateString + '&gameType=E&&gameType=S&&gameType=R&&gameType=F&&gameType=D&&gameType=L&&gameType=W&&gameType=A&language=en&leagueId=104&leagueId=103&leagueId=131&contextTeamId='
|
|
1949
|
-
let data_url = '
|
|
2017
|
+
let data_url = 'https://statsapi.mlb.com/api/v1/schedule?sportId=' + level_ids
|
|
1950
2018
|
if ( team_ids != '' ) {
|
|
1951
2019
|
data_url += '&teamId=' + team_ids
|
|
1952
2020
|
}
|
|
@@ -1954,7 +2022,7 @@ class sessionClass {
|
|
|
1954
2022
|
if ( team && !team.toUpperCase().startsWith('NATIONAL.') && !team.toUpperCase().startsWith('FREE.') ) {
|
|
1955
2023
|
this.debuglog('getDayData for team ' + team + ' on date ' + dateString)
|
|
1956
2024
|
cache_name = team.toUpperCase() + dateString
|
|
1957
|
-
data_url = '
|
|
2025
|
+
data_url = 'https://statsapi.mlb.com/api/v1/schedule?sportId=1&teamId=' + TEAM_IDS[team.toUpperCase()] + '&startDate=' + dateString + '&endDate=' + dateString + '&hydrate=team,broadcasts(all)'
|
|
1958
2026
|
} else {
|
|
1959
2027
|
this.debuglog('getDayData for level(s) ' + level_ids + ' on date ' + dateString)
|
|
1960
2028
|
}
|
|
@@ -2056,7 +2124,7 @@ class sessionClass {
|
|
|
2056
2124
|
let endDate = new Date(startDate)
|
|
2057
2125
|
endDate.setDate(endDate.getDate()+20)
|
|
2058
2126
|
endDate = endDate.toISOString().substring(0,10)
|
|
2059
|
-
let data_url = '
|
|
2127
|
+
let data_url = 'https://statsapi.mlb.com/api/v1/schedule?sportId=' + level_ids
|
|
2060
2128
|
if ( team_ids != '' ) {
|
|
2061
2129
|
data_url += '&teamId=' + team_ids
|
|
2062
2130
|
}
|
|
@@ -2181,13 +2249,14 @@ class sessionClass {
|
|
|
2181
2249
|
|
|
2182
2250
|
let gameIndexes_obj = {}
|
|
2183
2251
|
|
|
2252
|
+
let blackouts = {}
|
|
2253
|
+
if ( includeBlackouts == 'false' ) blackouts = await this.get_blackout_games()
|
|
2254
|
+
|
|
2184
2255
|
for (var i = 0; i < cache_data.dates.length; i++) {
|
|
2185
2256
|
this.debuglog('getTVData processing date ' + cache_data.dates[i].date)
|
|
2186
2257
|
let dateIndex = {MLBTV:i,Free:i,Audio:i}
|
|
2187
2258
|
let gameCounter = {MLBTV:0,Free:0,Audio:0}
|
|
2188
2259
|
|
|
2189
|
-
let blackouts = {}
|
|
2190
|
-
if ( includeBlackouts == 'false' ) blackouts = await this.get_blackout_games(cache_data.dates[i].games)
|
|
2191
2260
|
let gameIndexes = await this.get_first_and_last_games(cache_data.dates[i].games, blackouts)
|
|
2192
2261
|
// store gameIndexes for gamechanger/multiview reference later
|
|
2193
2262
|
gameIndexes_obj[cache_data.dates[i].date] = gameIndexes
|
|
@@ -2208,6 +2277,7 @@ class sessionClass {
|
|
|
2208
2277
|
continue
|
|
2209
2278
|
} else {
|
|
2210
2279
|
for (var k = 0; k < cache_data.dates[i].games[j].broadcasts.length; k++) {
|
|
2280
|
+
let league_id = cache_data.dates[i].games[j].teams['home'].team.league.id
|
|
2211
2281
|
let team = cache_data.dates[i].games[j].teams['home'].team.abbreviation
|
|
2212
2282
|
let team_id = cache_data.dates[i].games[j].teams['home'].team.id.toString()
|
|
2213
2283
|
let opponent_team_id = cache_data.dates[i].games[j].teams['away'].team.id.toString()
|
|
@@ -2219,9 +2289,16 @@ class sessionClass {
|
|
|
2219
2289
|
let channelid = mediaType + '.' + sportId + '.' + team
|
|
2220
2290
|
//let logo = server + '/image.svg?teamId=' + team_id
|
|
2221
2291
|
let logo = 'https://www.mlbstatic.com/team-logos/share/' + team_id + '.jpg'
|
|
2222
|
-
if ( this.protection.content_protect ) logo += '&content_protect=' + this.protection.content_protect
|
|
2292
|
+
//if ( this.protection.content_protect ) logo += '&content_protect=' + this.protection.content_protect
|
|
2293
|
+
if ( league_id == LIDOM_ID ) {
|
|
2294
|
+
let lidom_abbr = cache_data.dates[i].games[j].teams['home'].team.name.replace(/[^A-Z]/g, '').toLowerCase()
|
|
2295
|
+
logo = 'https://pizarra.multimediard.com/ac/' + lidom_abbr + '.png'
|
|
2296
|
+
}
|
|
2223
2297
|
let streamMediaType = 'Video'
|
|
2224
2298
|
let stream = server + '/stream.m3u8?team=' + encodeURIComponent(team) + '&mediaType=' + streamMediaType
|
|
2299
|
+
if ( league_id == LIDOM_ID ) {
|
|
2300
|
+
stream = server + '/stream.m3u8?event=' + encodeURIComponent(cache_data.dates[i].games[j].teams['home'].team.clubName.toUpperCase()) + '&mediaType=' + streamMediaType
|
|
2301
|
+
}
|
|
2225
2302
|
stream += '&level=' + encodeURIComponent(this.getLevelNameFromSportId(sportId))
|
|
2226
2303
|
stream += '&resolution=' + resolution
|
|
2227
2304
|
if ( this.protection.content_protect ) stream += '&content_protect=' + this.protection.content_protect
|
|
@@ -2229,13 +2306,23 @@ class sessionClass {
|
|
|
2229
2306
|
channels[channelid] = await this.create_channel_object(channelid, logo, stream, mediaType)
|
|
2230
2307
|
|
|
2231
2308
|
let title = 'Minor League Baseball'
|
|
2309
|
+
if ( WINTER_LEAGUES.includes(league_id.toString()) ) {
|
|
2310
|
+
title = cache_data.dates[i].games[j].teams['home'].team.league.name
|
|
2311
|
+
}
|
|
2232
2312
|
|
|
2233
2313
|
let away_team = cache_data.dates[i].games[j].teams['away'].team.name
|
|
2234
2314
|
let home_team = cache_data.dates[i].games[j].teams['home'].team.name
|
|
2235
2315
|
let subtitle = away_team + ' at ' + home_team
|
|
2236
2316
|
|
|
2237
2317
|
if (includeTeamsInTitles == 'true') {
|
|
2238
|
-
|
|
2318
|
+
if ( league_id == AFL_ID ) {
|
|
2319
|
+
title = 'AFL'
|
|
2320
|
+
} else if ( league_id == LIDOM_ID ) {
|
|
2321
|
+
title = 'LIDOM'
|
|
2322
|
+
} else {
|
|
2323
|
+
title = 'MiLB'
|
|
2324
|
+
}
|
|
2325
|
+
title += ': ' + subtitle
|
|
2239
2326
|
}
|
|
2240
2327
|
|
|
2241
2328
|
let description = cache_data.dates[i].games[j].teams['home'].team.league.name + '. '
|
|
@@ -2528,7 +2615,7 @@ class sessionClass {
|
|
|
2528
2615
|
this.debuglog('getTVData processing MLB Network')
|
|
2529
2616
|
let logo = 'https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcQRgC2JdbtFplKjfhXm5_vzpkUQ3XyDT91SEnHmuB0p5tReQ3Ez'
|
|
2530
2617
|
let channelid = mediaType + '.MLBN'
|
|
2531
|
-
if ( this.protection.content_protect ) logo += '&content_protect=' + this.protection.content_protect
|
|
2618
|
+
//if ( this.protection.content_protect ) logo += '&content_protect=' + this.protection.content_protect
|
|
2532
2619
|
let stream = server + '/stream.m3u8?event=mlbn&mediaType=Video&resolution=' + resolution
|
|
2533
2620
|
if ( this.protection.content_protect ) stream += '&content_protect=' + this.protection.content_protect
|
|
2534
2621
|
if ( pipe == 'true' ) stream = await this.convert_stream_to_pipe(stream, channelid)
|
|
@@ -2559,7 +2646,7 @@ class sessionClass {
|
|
|
2559
2646
|
this.debuglog('getTVData processing Big Inning')
|
|
2560
2647
|
let logo = 'https://img.mlbstatic.com/mlb-images/image/private/ar_16:9,g_auto,q_auto:good,w_372,c_fill,f_jpg/mlb/uwr8vepua4t1fe8uwyki'
|
|
2561
2648
|
let channelid = mediaType + '.BIGINNING'
|
|
2562
|
-
if ( this.protection.content_protect ) logo += '&content_protect=' + this.protection.content_protect
|
|
2649
|
+
//if ( this.protection.content_protect ) logo += '&content_protect=' + this.protection.content_protect
|
|
2563
2650
|
let stream = server + '/stream.m3u8?event=biginning&mediaType=Video&resolution=' + resolution
|
|
2564
2651
|
if ( this.protection.content_protect ) stream += '&content_protect=' + this.protection.content_protect
|
|
2565
2652
|
if ( pipe == 'true' ) stream = await this.convert_stream_to_pipe(stream, channelid)
|
|
@@ -2770,7 +2857,7 @@ class sessionClass {
|
|
|
2770
2857
|
let currentDate = new Date()
|
|
2771
2858
|
if ( !fs.existsSync(cache_file) || !this.cache || !this.cache.gameday || !this.cache.gameday[cache_name] || !this.cache.gameday[cache_name].gamedayCacheExpiry || (currentDate > new Date(this.cache.gameday[cache_name].gamedayCacheExpiry)) ) {
|
|
2772
2859
|
let reqObj = {
|
|
2773
|
-
url: '
|
|
2860
|
+
url: 'https://statsapi.mlb.com/api/v1.1/game/' + gamePk + '/feed/live',
|
|
2774
2861
|
headers: {
|
|
2775
2862
|
'User-agent': USER_AGENT,
|
|
2776
2863
|
'Origin': 'https://www.mlb.com',
|
|
@@ -2829,6 +2916,9 @@ class sessionClass {
|
|
|
2829
2916
|
if ( streamURLToken ) {
|
|
2830
2917
|
variant_url += '&streamURLToken=' + encodeURIComponent(streamURLToken)
|
|
2831
2918
|
}
|
|
2919
|
+
if ( this.protection.content_protect ) {
|
|
2920
|
+
variant_url += '&content_protect=' + this.protection.content_protect
|
|
2921
|
+
}
|
|
2832
2922
|
let reqObj = {
|
|
2833
2923
|
url: variant_url
|
|
2834
2924
|
}
|
|
@@ -2853,10 +2943,12 @@ class sessionClass {
|
|
|
2853
2943
|
}
|
|
2854
2944
|
|
|
2855
2945
|
// Get skip markers into temporary cache
|
|
2856
|
-
async getSkipMarkers(gamePk, skip_type, start_inning, start_inning_half, streamURL, streamURLToken) {
|
|
2946
|
+
async getSkipMarkers(gamePk, skip_type, start_inning, start_inning_half, streamURL, streamURLToken, skip_adjust) {
|
|
2857
2947
|
try {
|
|
2858
2948
|
this.debuglog('getSkipMarkers')
|
|
2859
2949
|
|
|
2950
|
+
if ( skip_adjust != 0 ) this.log('manual adjustment of ' + skip_adjust + ' seconds being applied')
|
|
2951
|
+
|
|
2860
2952
|
if ( !this.temp_cache[gamePk] ) {
|
|
2861
2953
|
this.temp_cache[gamePk] = {}
|
|
2862
2954
|
}
|
|
@@ -2972,6 +3064,8 @@ class sessionClass {
|
|
|
2972
3064
|
// then we'll add the skip marker
|
|
2973
3065
|
// otherwise we'll ignore it and move on to the next one
|
|
2974
3066
|
if ( ((break_end - break_start) >= MINIMUM_BREAK_DURATION) && ((skip_type != 1) || (current_inning != previous_inning) || (current_inning_half != previous_inning_half)) ) {
|
|
3067
|
+
if ( break_start > 0 ) break_start += skip_adjust
|
|
3068
|
+
break_end += skip_adjust
|
|
2975
3069
|
skip_markers.push({'break_start': break_start, 'break_end': break_end})
|
|
2976
3070
|
total_skip_time += break_end - break_start
|
|
2977
3071
|
previous_inning = current_inning
|
|
@@ -3486,71 +3580,122 @@ class sessionClass {
|
|
|
3486
3580
|
return regional_fox_games_exist
|
|
3487
3581
|
}
|
|
3488
3582
|
|
|
3583
|
+
// get blackouts data for a day
|
|
3584
|
+
async getBlackoutsData(dateString, endDate) {
|
|
3585
|
+
try {
|
|
3586
|
+
let cache_data
|
|
3587
|
+
let cache_name = 'b' + dateString
|
|
3588
|
+
let data_url = 'https://mastapi.mobile.mlbinfra.com/api/epg/v3/search?exp=MLB&date=' + dateString
|
|
3589
|
+
let utcHours = 10
|
|
3590
|
+
if ( dateString == 'guide' ) {
|
|
3591
|
+
cache_name = 'bweek'
|
|
3592
|
+
this.debuglog('getBlackoutsData for week')
|
|
3593
|
+
let startDate = this.liveDate(utcHours)
|
|
3594
|
+
let endDate = new Date(startDate)
|
|
3595
|
+
endDate.setDate(endDate.getDate()+20)
|
|
3596
|
+
endDate = endDate.toISOString().substring(0,10)
|
|
3597
|
+
data_url = 'https://mastapi.mobile.mlbinfra.com/api/epg/v3/search?exp=MLB&startDate=' + startDate + '&endDate=' + endDate
|
|
3598
|
+
} else {
|
|
3599
|
+
this.debuglog('getBlackoutsData for ' + dateString)
|
|
3600
|
+
}
|
|
3601
|
+
let cache_file = path.join(this.CACHE_DIRECTORY, cache_name+'.json')
|
|
3602
|
+
let currentDate = new Date()
|
|
3603
|
+
if ( !fs.existsSync(cache_file) || !this.cache || !this.cache.blackouts || !this.cache.blackouts[cache_name] || !this.cache.blackouts[cache_name].blackoutsCacheExpiry || (currentDate > new Date(this.cache.blackouts[cache_name].blackoutsCacheExpiry)) ) {
|
|
3604
|
+
let reqObj = {
|
|
3605
|
+
url: data_url,
|
|
3606
|
+
headers: {
|
|
3607
|
+
'Accept': '*/*',
|
|
3608
|
+
'Accept-Language': 'en-US,en;q=0.9',
|
|
3609
|
+
'Content-Type': 'application/json',
|
|
3610
|
+
'Origin': 'https://www.mlb.com',
|
|
3611
|
+
'Referer': 'https://www.mlb.com/',
|
|
3612
|
+
'User-Agent': USER_AGENT
|
|
3613
|
+
}
|
|
3614
|
+
}
|
|
3615
|
+
if ( (this.credentials.account_username.length > 0) && (this.credentials.account_password.length > 0) ) {
|
|
3616
|
+
let access_token = await this.getLoginToken()
|
|
3617
|
+
let okta_id = await this.getOktaId()
|
|
3618
|
+
if ( access_token && okta_id ) {
|
|
3619
|
+
reqObj.headers['authorization'] = 'Bearer ' + access_token
|
|
3620
|
+
reqObj.headers['x-okta-id'] = okta_id
|
|
3621
|
+
}
|
|
3622
|
+
}
|
|
3623
|
+
var response = await this.httpGet(reqObj, false)
|
|
3624
|
+
if ( response && this.isValidJson(response) ) {
|
|
3625
|
+
//this.debuglog(response)
|
|
3626
|
+
cache_data = JSON.parse(response)
|
|
3627
|
+
this.save_json_cache_file(cache_name, cache_data)
|
|
3628
|
+
|
|
3629
|
+
// Default cache period is 1 day from now
|
|
3630
|
+
let today = this.liveDate()
|
|
3631
|
+
let tomorrowDate = new Date(today)
|
|
3632
|
+
tomorrowDate.setDate(tomorrowDate.getDate()+1)
|
|
3633
|
+
tomorrowDate.setHours(tomorrowDate.getHours()+utcHours)
|
|
3634
|
+
let cacheExpiry = tomorrowDate
|
|
3635
|
+
|
|
3636
|
+
// finally save the setting
|
|
3637
|
+
this.setBlackoutsCacheExpiry(cache_name, cacheExpiry)
|
|
3638
|
+
} else {
|
|
3639
|
+
this.log('error : invalid json from url ' + reqObj.url)
|
|
3640
|
+
}
|
|
3641
|
+
} else {
|
|
3642
|
+
this.debuglog('using cached date data')
|
|
3643
|
+
cache_data = this.readFileToJson(cache_file)
|
|
3644
|
+
}
|
|
3645
|
+
if (cache_data) {
|
|
3646
|
+
return cache_data
|
|
3647
|
+
}
|
|
3648
|
+
} catch(e) {
|
|
3649
|
+
this.log('getBlackoutsData error : ' + e.message)
|
|
3650
|
+
}
|
|
3651
|
+
}
|
|
3652
|
+
|
|
3489
3653
|
// get all blackout games for a date
|
|
3490
|
-
async get_blackout_games(
|
|
3654
|
+
async get_blackout_games(gameDate='guide', calculate_expiries=false) {
|
|
3491
3655
|
this.debuglog('get_blackout_games')
|
|
3492
3656
|
let blackouts = {}
|
|
3493
3657
|
|
|
3494
|
-
let
|
|
3658
|
+
let cache_data
|
|
3659
|
+
cache_data = await this.getBlackoutsData(gameDate)
|
|
3660
|
+
|
|
3661
|
+
if ( cache_data && cache_data.results && (cache_data.results.length > 0) ) {
|
|
3662
|
+
for (var j = 0; j < cache_data.results.length; j++) {
|
|
3663
|
+
let game = cache_data.results[j]
|
|
3664
|
+
let game_pk = game.gamePk
|
|
3665
|
+
this.debuglog('get_blackout_games checking game ' + game_pk)
|
|
3666
|
+
if ( game.blackedOutVideo ) {
|
|
3667
|
+
this.debuglog('get_blackout_games found blackout')
|
|
3668
|
+
let blackout_type = ''
|
|
3669
|
+
// local/national blackout label disabled, as all were returning local
|
|
3670
|
+
/*if ( game.videoStatusCodes.includes('2') ) {
|
|
3671
|
+
this.debuglog('get_blackout_games found national blackout')
|
|
3672
|
+
blackout_type = 'National/International'
|
|
3673
|
+
} else {
|
|
3674
|
+
this.debuglog('get_blackout_games found local blackout')
|
|
3675
|
+
blackout_type = 'Local'
|
|
3676
|
+
}*/
|
|
3677
|
+
blackouts[game_pk] = { blackout_type: blackout_type }
|
|
3678
|
+
} else if ( !game.entitledVideo && (game.videoStatusCodes[0] == '3') ) {
|
|
3679
|
+
this.debuglog('get_blackout_games found non-entitled MVPD required blackout')
|
|
3680
|
+
blackouts[game_pk] = { blackout_type: '' }
|
|
3681
|
+
}
|
|
3495
3682
|
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
// International blackouts according to https://www.mlb.com/live-stream-games/help-center/blackouts-available-games
|
|
3508
|
-
if ( usa_blackout && (broadcast.callSign == 'FOX') ) {
|
|
3509
|
-
if ( !regional_fox_games_exist && (games[j].seriesDescription == 'Regular Season') ) {
|
|
3510
|
-
regional_fox_games_exist = await this.check_regional_fox_games(games)
|
|
3511
|
-
}
|
|
3512
|
-
if ( !regional_fox_games_exist || (regional_fox_games_exist == 'false') ) {
|
|
3513
|
-
this.debuglog('get_blackout_games found non-regional FOX game')
|
|
3514
|
-
blackouts[game_pk] = { blackout_type:'National' }
|
|
3515
|
-
break
|
|
3516
|
-
}
|
|
3517
|
-
// Apple TV+ games are blacked out everywhere
|
|
3518
|
-
} else if ( broadcast.callSign == 'Apple TV+' ) {
|
|
3519
|
-
this.debuglog('get_blackout_games found Apple TV+ blackout')
|
|
3520
|
-
blackouts[game_pk] = { blackout_type:'Full International' }
|
|
3521
|
-
// ESPN Sunday Night games are blacked out in a list of countries
|
|
3522
|
-
} else if ( (broadcast.callSign == 'ESPN') && (new Date(games[j].gameDate).getDay() == 0) && ESPN_SUNDAY_NIGHT_BLACKOUT_COUNTRIES.includes(this.credentials.country) ) {
|
|
3523
|
-
this.debuglog('get_blackout_games found ESPN blackout')
|
|
3524
|
-
blackouts[game_pk] = { blackout_type:'Partial International' }
|
|
3525
|
-
// games with an "-INT" variant are postseason games, blacked out in USA and Canada
|
|
3526
|
-
} else if ( broadcast.callSign.endsWith('-INT') && (usa_blackout || (this.credentials.country == 'Canada')) ) {
|
|
3527
|
-
this.debuglog('get_blackout_games found national blackout')
|
|
3528
|
-
blackouts[game_pk] = { blackout_type:'National' }
|
|
3529
|
-
} else if ( usa_blackout ) {
|
|
3530
|
-
this.debuglog('get_blackout_games found USA blackout')
|
|
3531
|
-
blackouts[game_pk] = { blackout_type:'National' }
|
|
3532
|
-
}
|
|
3533
|
-
break
|
|
3534
|
-
// check local blackouts
|
|
3535
|
-
} else {
|
|
3536
|
-
this.debuglog('get_blackout_games checking local game')
|
|
3537
|
-
let awayteam = games[j].teams['away'].team.abbreviation
|
|
3538
|
-
let hometeam = games[j].teams['home'].team.abbreviation
|
|
3539
|
-
if ( (games[j].seriesDescription != 'Spring Training') && (this.credentials.blackout_teams.includes(hometeam) || this.credentials.blackout_teams.includes(awayteam)) ) {
|
|
3540
|
-
this.debuglog('get_blackout_games found local blackout')
|
|
3541
|
-
blackouts[game_pk] = { blackout_type:'Local' }
|
|
3683
|
+
// add blackout expiry, if requested
|
|
3684
|
+
if ( blackouts[game_pk] && calculate_expiries && await this.check_game_time(game.gameData) ) {
|
|
3685
|
+
this.debuglog('get_blackout_games calculating blackout expiry')
|
|
3686
|
+
let date_cache_data = await this.getDayData(gameDate)
|
|
3687
|
+
if ( date_cache_data.dates && date_cache_data.dates[0] && date_cache_data.dates[0].games && (date_cache_data.dates[0].games.length > 0) ) {
|
|
3688
|
+
for (var k = 0; k < date_cache_data.dates[0].games.length; k++) {
|
|
3689
|
+
if ( game_pk == date_cache_data.dates[0].games[k].gamePk ) {
|
|
3690
|
+
this.debuglog('get_blackout_games found matching game')
|
|
3691
|
+
let blackoutExpiry = await this.get_blackout_expiry(date_cache_data.dates[0].games[k])
|
|
3692
|
+
this.debuglog('get_blackout_games calculated blackout expiry as ' + blackoutExpiry)
|
|
3693
|
+
blackouts[game_pk].blackoutExpiry = blackoutExpiry
|
|
3542
3694
|
break
|
|
3543
3695
|
}
|
|
3544
3696
|
}
|
|
3545
|
-
break
|
|
3546
3697
|
}
|
|
3547
3698
|
}
|
|
3548
|
-
|
|
3549
|
-
// add blackout expiry, if requested
|
|
3550
|
-
if ( blackouts[game_pk] && calculate_expiries && await this.check_game_time(games[j]) ) {
|
|
3551
|
-
let blackoutExpiry = await this.get_blackout_expiry(games[j])
|
|
3552
|
-
blackouts[game_pk].blackoutExpiry = blackoutExpiry
|
|
3553
|
-
}
|
|
3554
3699
|
}
|
|
3555
3700
|
}
|
|
3556
3701
|
|
|
@@ -3566,7 +3711,7 @@ class sessionClass {
|
|
|
3566
3711
|
let start
|
|
3567
3712
|
let end
|
|
3568
3713
|
if ( cache_data.dates && cache_data.dates[0] && cache_data.dates[0].games && (cache_data.dates[0].games.length > 0) ) {
|
|
3569
|
-
blackouts = await this.get_blackout_games(
|
|
3714
|
+
blackouts = await this.get_blackout_games(today)
|
|
3570
3715
|
this.debuglog('Game changer blackouts ' + JSON.stringify(blackouts))
|
|
3571
3716
|
|
|
3572
3717
|
let gameIndexes = await this.get_first_and_last_games(cache_data.dates[0].games, blackouts)
|
|
@@ -3621,8 +3766,8 @@ class sessionClass {
|
|
|
3621
3766
|
cacheExpiry.setSeconds(cacheExpiry.getSeconds()+9)
|
|
3622
3767
|
this.temp_cache.gamechangerCacheExpiry = cacheExpiry
|
|
3623
3768
|
let reqObj = {
|
|
3624
|
-
//url: '
|
|
3625
|
-
url: '
|
|
3769
|
+
//url: 'https://gd2.mlb.com/components/game/mlb/year_' + this.temp_cache.gamechanger.dateString + '/master_scoreboard.json',
|
|
3770
|
+
url: 'https://statsapi.mlb.com/api/v1/schedule?sportId=1&startDate=' + this.temp_cache.gamechanger.date + '&endDate=' + this.temp_cache.gamechanger.date + '&hydrate=broadcasts(all),linescore,team,flags,gameInfo',
|
|
3626
3771
|
headers: {
|
|
3627
3772
|
'User-Agent': USER_AGENT,
|
|
3628
3773
|
'Origin': 'https://www.mlb.com',
|
|
@@ -4066,7 +4211,7 @@ class sessionClass {
|
|
|
4066
4211
|
let firstGameIndex
|
|
4067
4212
|
for (var j = 0; j < games.length; j++) {
|
|
4068
4213
|
let gamePk = games[j].gamePk.toString()
|
|
4069
|
-
if ( games[j].gameDate && !blackouts[gamePk] && !games[j].rescheduleDate && !games[j].status.startTimeTBD && games[j].broadcasts && (await this.count_broadcasts(games[j].broadcasts, 'MLBTV') > 0) ) {
|
|
4214
|
+
if ( games[j].gameDate && (games[j].teams.home.team.sport.id == 1) && (games[j].teams.away.team.sport.id == 1) && !blackouts[gamePk] && !games[j].rescheduleDate && !games[j].status.startTimeTBD && games[j].broadcasts && (await this.count_broadcasts(games[j].broadcasts, 'MLBTV') > 0) ) {
|
|
4070
4215
|
this.debuglog('get_first_and_last_games first : ' + j + ' ' + gamePk + ' at ' + games[j].gameDate)
|
|
4071
4216
|
firstGameIndex = j
|
|
4072
4217
|
break
|
|
@@ -4075,7 +4220,7 @@ class sessionClass {
|
|
|
4075
4220
|
let lastGameIndex
|
|
4076
4221
|
for (var j = (games.length-1); j >= 0; j--) {
|
|
4077
4222
|
let gamePk = games[j].gamePk.toString()
|
|
4078
|
-
if ( games[j].gameDate && !blackouts[gamePk] && !games[j].rescheduleDate && games[j].broadcasts && (await this.count_broadcasts(games[j].broadcasts, 'MLBTV') > 0) ) {
|
|
4223
|
+
if ( games[j].gameDate && (games[j].teams.home.team.sport.id == 1) && (games[j].teams.away.team.sport.id == 1) && !blackouts[gamePk] && !games[j].rescheduleDate && games[j].broadcasts && (await this.count_broadcasts(games[j].broadcasts, 'MLBTV') > 0) ) {
|
|
4079
4224
|
this.debuglog('get_first_and_last_games last : ' + j + ' ' + gamePk + ' at ' + games[j].gameDate)
|
|
4080
4225
|
lastGameIndex = j
|
|
4081
4226
|
break
|
|
@@ -4134,8 +4279,8 @@ class sessionClass {
|
|
|
4134
4279
|
return scheduledInnings
|
|
4135
4280
|
}
|
|
4136
4281
|
|
|
4137
|
-
async check_game_time(
|
|
4138
|
-
if ( !
|
|
4282
|
+
async check_game_time(gameData) {
|
|
4283
|
+
if ( !gameData.resumeGameDate && !gameData.resumedFromDate && (gameData.startTimeTBD == false) ) {
|
|
4139
4284
|
return true
|
|
4140
4285
|
} else {
|
|
4141
4286
|
return false
|
|
@@ -4144,20 +4289,25 @@ class sessionClass {
|
|
|
4144
4289
|
|
|
4145
4290
|
async get_blackout_expiry(game) {
|
|
4146
4291
|
let scheduledInnings = await this.get_scheduled_innings(game)
|
|
4147
|
-
|
|
4148
|
-
|
|
4292
|
+
this.debuglog('get_blackout_expiry scheduledInnings ' + scheduledInnings)
|
|
4293
|
+
// avg 9 inning game was 2:39 in 2023, or 17.66 minutes per inning
|
|
4294
|
+
let gameDurationMinutes = 17.66 * scheduledInnings
|
|
4149
4295
|
// default to assuming the scheduled game time is the first pitch time
|
|
4150
4296
|
let firstPitch = new Date(game.gameDate)
|
|
4297
|
+
this.debuglog('get_blackout_expiry gameDate ' + firstPitch)
|
|
4151
4298
|
if ( game.gameInfo ) {
|
|
4152
4299
|
// check if firstPitch has been updated with a valid time (later than the scheduled game time)
|
|
4153
4300
|
if ( game.gameInfo.firstPitch && (game.gameInfo.firstPitch >= game.gameDate) ) {
|
|
4154
4301
|
firstPitch = new Date(game.gameInfo.firstPitch)
|
|
4302
|
+
this.debuglog('get_blackout_expiry firstPitch ' + firstPitch)
|
|
4155
4303
|
// for completed games, get the duration too
|
|
4156
4304
|
if ( game.gameInfo.gameDurationMinutes ) {
|
|
4157
4305
|
gameDurationMinutes = game.gameInfo.gameDurationMinutes
|
|
4306
|
+
this.debuglog('get_blackout_expiry gameDurationMinutes ' + gameDurationMinutes)
|
|
4158
4307
|
// add any delays
|
|
4159
4308
|
if ( game.gameInfo.delayDurationMinutes ) {
|
|
4160
4309
|
gameDurationMinutes += game.gameInfo.delayDurationMinutes
|
|
4310
|
+
this.debuglog('get_blackout_expiry delayDurationMinutes ' + game.gameInfo.delayDurationMinutes)
|
|
4161
4311
|
}
|
|
4162
4312
|
}
|
|
4163
4313
|
}
|