mlbserver 2023.4.5 → 2023.4.20
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/README.md +1 -1
- package/index.js +106 -49
- package/package.json +1 -1
- package/session.js +91 -1
package/README.md
CHANGED
package/index.js
CHANGED
|
@@ -37,7 +37,7 @@ const VALID_AUDIO_TRACKS = [ 'all', 'English', 'English Radio', 'Radio Española
|
|
|
37
37
|
const DISPLAY_AUDIO_TRACKS = [ 'all', 'TV', 'Radio', 'Spanish', 'Alt.', 'Alt. Spanish', 'none' ]
|
|
38
38
|
const ALTERNATE_AUDIO_TRACKS = [ VALID_AUDIO_TRACKS[4], VALID_AUDIO_TRACKS[5] ]
|
|
39
39
|
const DEFAULT_MULTIVIEW_AUDIO_TRACK = 'English'
|
|
40
|
-
const VALID_SKIP = [ 'off', 'breaks', 'idle time', 'pitches' ]
|
|
40
|
+
const VALID_SKIP = [ 'off', 'breaks', 'idle time', 'pitches', 'commercials' ]
|
|
41
41
|
const VALID_PAD = [ 'off', 'on' ]
|
|
42
42
|
const VALID_FORCE_VOD = [ 'off', 'on' ]
|
|
43
43
|
const VALID_SCAN_MODES = [ 'off', 'on' ]
|
|
@@ -248,7 +248,7 @@ app.get('/stream.m3u8', async function(req, res) {
|
|
|
248
248
|
let options = {}
|
|
249
249
|
let includeBlackouts = 'false'
|
|
250
250
|
let urlArray = req.url.split('?')
|
|
251
|
-
if ( (urlArray.length == 1) || ((session.data.scan_mode == VALID_SCAN_MODES[1]) && req.query.team) || (!req.query.team && !req.query.src && !req.query.highlight_src && !req.query.event && !req.query.gamePk && !req.query.id && !req.query.mediaId && !req.query.contentId) ) {
|
|
251
|
+
if ( (urlArray.length == 1) || ((session.data.scan_mode == VALID_SCAN_MODES[1]) && req.query.team) || (!req.query.team && !req.query.src && !req.query.highlight_src && !req.query.eventURL && !req.query.event && !req.query.gamePk && !req.query.id && !req.query.mediaId && !req.query.contentId) ) {
|
|
252
252
|
// load a sample encrypted HLS stream
|
|
253
253
|
session.log('loading sample stream')
|
|
254
254
|
options.resolution = VALID_RESOLUTIONS[0]
|
|
@@ -366,7 +366,17 @@ app.get('/stream.m3u8', async function(req, res) {
|
|
|
366
366
|
options.contentId = contentId
|
|
367
367
|
|
|
368
368
|
let skip_type = VALID_SKIP.indexOf(options.skip)
|
|
369
|
-
|
|
369
|
+
// for commercial skip, just use the gdfp playlists and skip the ad inserts
|
|
370
|
+
if ( skip_type == 4 ) {
|
|
371
|
+
let new_streamURL = streamURL.replace('master_desktop_complete', 'master_desktop_complete_gdfp')
|
|
372
|
+
if ( new_streamURL == streamURL ) {
|
|
373
|
+
new_streamURL = streamURL.replace('master_desktop', 'master_desktop_gdfp')
|
|
374
|
+
}
|
|
375
|
+
session.debuglog('skipping commercials using gdfp playlist ' + new_streamURL)
|
|
376
|
+
streamURL = new_streamURL
|
|
377
|
+
} else {
|
|
378
|
+
await session.getSkipMarkers(contentId, skip_type, options.inning_number, options.inning_half)
|
|
379
|
+
}
|
|
370
380
|
}
|
|
371
381
|
}
|
|
372
382
|
|
|
@@ -660,6 +670,16 @@ function getMasterPlaylist(streamURL, req, res, options = {}) {
|
|
|
660
670
|
return
|
|
661
671
|
}
|
|
662
672
|
|
|
673
|
+
// Pass through any remaining caption tracks
|
|
674
|
+
if ( line.startsWith('#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="English",DEFAULT=YES,AUTOSELECT=YES,FORCED=NO,LANGUAGE="eng",URI="') ) {
|
|
675
|
+
var parsed = line.match(',URI="([^"]+)"')
|
|
676
|
+
if ( parsed[1] ) {
|
|
677
|
+
newurl = '/playlist?url='+encodeURIComponent(url.resolve(streamURL, parsed[1].trim()))
|
|
678
|
+
return '#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="English",DEFAULT=YES,AUTOSELECT=YES,FORCED=NO,LANGUAGE="eng",URI="' + newurl + '"'
|
|
679
|
+
}
|
|
680
|
+
return
|
|
681
|
+
}
|
|
682
|
+
|
|
663
683
|
if (line[0] === '#') {
|
|
664
684
|
return line
|
|
665
685
|
}
|
|
@@ -755,7 +775,22 @@ app.get('/playlist', async function(req, res) {
|
|
|
755
775
|
content_protect = '&content_protect=' + session.protection.content_protect
|
|
756
776
|
}
|
|
757
777
|
|
|
758
|
-
if
|
|
778
|
+
// if skipping commercials, filter the playlist to remove ad insertion domains
|
|
779
|
+
if ( skip == 'commercials' ) {
|
|
780
|
+
session.debuglog('filtering commercial breaks')
|
|
781
|
+
let new_body = []
|
|
782
|
+
for (var i=0; i<body.length; i++) {
|
|
783
|
+
if ( body[i].includes('dai.google.com') ) {
|
|
784
|
+
new_body.pop()
|
|
785
|
+
if ( new_body[new_body.length-1] != '#EXT-X-DISCONTINUITY' ) {
|
|
786
|
+
new_body.push('#EXT-X-DISCONTINUITY')
|
|
787
|
+
}
|
|
788
|
+
} else {
|
|
789
|
+
new_body.push(body[i])
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
body = new_body
|
|
793
|
+
} else if ( (contentId) && ((inning_half != VALID_INNING_HALF[0]) || (inning_number != VALID_INNING_NUMBER[0]) || (skip != VALID_SKIP[0])) && (typeof session.temp_cache[contentId] !== 'undefined') && (typeof session.temp_cache[contentId].skip_markers !== 'undefined') ) {
|
|
759
794
|
session.debuglog('pulling skip markers from temporary cache')
|
|
760
795
|
skip_markers = session.temp_cache[contentId].skip_markers
|
|
761
796
|
} else {
|
|
@@ -1238,10 +1273,12 @@ app.get('/', async function(req, res) {
|
|
|
1238
1273
|
} else if ( level_ids == '1' ) {
|
|
1239
1274
|
team_ids = session.getTeamIds()
|
|
1240
1275
|
for (let i=0; i<session.credentials.fav_teams.length; i++) {
|
|
1241
|
-
if (
|
|
1242
|
-
level_ids
|
|
1276
|
+
if ( session.credentials.fav_teams[i] != '' ) {
|
|
1277
|
+
if ( level_ids == '1' ) {
|
|
1278
|
+
level_ids = levels['All']
|
|
1279
|
+
}
|
|
1280
|
+
team_ids += ',' + AFFILIATE_TEAM_IDS[session.credentials.fav_teams[i]]
|
|
1243
1281
|
}
|
|
1244
|
-
team_ids += ',' + AFFILIATE_TEAM_IDS[session.credentials.fav_teams[i]]
|
|
1245
1282
|
}
|
|
1246
1283
|
}
|
|
1247
1284
|
let cache_name = gameDate
|
|
@@ -1470,7 +1507,21 @@ app.get('/', async function(req, res) {
|
|
|
1470
1507
|
|
|
1471
1508
|
let blackouts = {}
|
|
1472
1509
|
|
|
1473
|
-
if ( (mediaType == 'MLBTV') && level_ids.startsWith('1,') ) {
|
|
1510
|
+
if ( (mediaType == 'MLBTV') && ((level_ids == '1') || level_ids.startsWith('1,')) ) {
|
|
1511
|
+
// Recap Rundown beginning in 2023
|
|
1512
|
+
if ( (gameDate <= yesterday) && (gameDate >= '2023-03-31') && cache_data.dates && cache_data.dates[0] && cache_data.dates[0].games && (cache_data.dates[0].games.length > 0) ) {
|
|
1513
|
+
body += '<tr><td><span class="tooltip">VOD<span class="tooltiptext">Recap Rundown plays all of a day\'s recaps in order.</span></span></td><td>'
|
|
1514
|
+
let dateArray = gameDate.split('-')
|
|
1515
|
+
let querystring = '?event=recaprundown' + parseInt(dateArray[1]).toString() + '-' + parseInt(dateArray[2]).toString() + '-' + dateArray[0].substring(2,4)
|
|
1516
|
+
if ( linkType == VALID_LINK_TYPES[0] ) {
|
|
1517
|
+
if ( controls != VALID_CONTROLS[0] ) querystring += '&controls=' + controls
|
|
1518
|
+
}
|
|
1519
|
+
if ( resolution != VALID_RESOLUTIONS[0] ) querystring += '&resolution=' + resolution
|
|
1520
|
+
querystring += content_protect_b
|
|
1521
|
+
body += '<a href="' + thislink + querystring + '">Recap Rundown</a>'
|
|
1522
|
+
body += '</td></tr>' + "\n"
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1474
1525
|
if ( (gameDate >= today) && cache_data.dates && cache_data.dates[0] && cache_data.dates[0].games && (cache_data.dates[0].games.length > 0) ) {
|
|
1475
1526
|
blackouts = await session.get_blackout_games(cache_data.dates[0].games, true)
|
|
1476
1527
|
}
|
|
@@ -1487,7 +1538,7 @@ app.get('/', async function(req, res) {
|
|
|
1487
1538
|
//big_inning = await session.generateBigInningSchedule(gameDate)
|
|
1488
1539
|
}
|
|
1489
1540
|
if ( big_inning && big_inning.start ) {
|
|
1490
|
-
body += '<tr><td>' + new Date(big_inning.start).toLocaleString('en-US', { hour: 'numeric', minute: 'numeric', hour12: true }) + ' - ' + new Date(big_inning.end).toLocaleString('en-US', { hour: 'numeric', minute: 'numeric', hour12: true }) + '</td><td>'
|
|
1541
|
+
body += '<tr><td><span class="tooltip">' + new Date(big_inning.start).toLocaleString('en-US', { hour: 'numeric', minute: 'numeric', hour12: true }) + ' - ' + new Date(big_inning.end).toLocaleString('en-US', { hour: 'numeric', minute: 'numeric', hour12: true }) + '<span class="tooltiptext">Big Inning is the live look-in and highlights show. <a href="https://www.mlb.com/live-stream-games/big-inning">See here for more information</a>.</span></span></td><td>'
|
|
1491
1542
|
let compareStart = new Date(big_inning.start)
|
|
1492
1543
|
compareStart.setMinutes(compareStart.getMinutes()-10)
|
|
1493
1544
|
let compareEnd = new Date(big_inning.end)
|
|
@@ -1514,7 +1565,7 @@ app.get('/', async function(req, res) {
|
|
|
1514
1565
|
}
|
|
1515
1566
|
|
|
1516
1567
|
// Game Changer
|
|
1517
|
-
if ( cache_data.dates && cache_data.dates[0] && cache_data.dates[0].games && (cache_data.dates[0].games.length > 1) ) {
|
|
1568
|
+
if ( (gameDate >= today) && cache_data.dates && cache_data.dates[0] && cache_data.dates[0].games && (cache_data.dates[0].games.length > 1) ) {
|
|
1518
1569
|
let gameIndexes = await session.get_first_and_last_games(cache_data.dates[0].games, blackouts)
|
|
1519
1570
|
if ( (typeof gameIndexes.firstGameIndex !== 'undefined') && (typeof gameIndexes.lastGameIndex !== 'undefined') && (gameIndexes.firstGameIndex !== gameIndexes.lastGameIndex) ) {
|
|
1520
1571
|
let compareStart = new Date(cache_data.dates[0].games[gameIndexes.firstGameIndex].gameDate)
|
|
@@ -1527,8 +1578,8 @@ app.get('/', async function(req, res) {
|
|
|
1527
1578
|
body += '<tr><td><span class="tooltip">' + compareStart.toLocaleString('en-US', { hour: 'numeric', minute: 'numeric', hour12: true }) + ' - ' + compareEnd.toLocaleString('en-US', { hour: 'numeric', minute: 'numeric', hour12: true }) + '<span class="tooltiptext">The game changer stream will automatically switch between the highest leverage active live non-blackout games, and should be available whenever there are such games available. Does not support adaptive bitrate switching, will default to best resolution if not specified.</span></span></td><td>'
|
|
1528
1579
|
if ( (currentDate >= compareStart) && (currentDate < compareEnd) ) {
|
|
1529
1580
|
let streamURL = server + '/gamechanger.m3u8'
|
|
1581
|
+
let multiviewquerystring = streamURL + '?resolution=' + DEFAULT_MULTIVIEW_RESOLUTION + content_protect_b
|
|
1530
1582
|
streamURL += content_protect_a
|
|
1531
|
-
let multiviewquerystring = streamURL + '&resolution=' + DEFAULT_MULTIVIEW_RESOLUTION
|
|
1532
1583
|
if ( resolution != VALID_RESOLUTIONS[0] ) streamURL += '&resolution=' + resolution
|
|
1533
1584
|
if ( linkType != VALID_LINK_TYPES[1] ) {
|
|
1534
1585
|
streamURL = thislink + '?src=' + encodeURIComponent(streamURL) + '&startFrom=' + VALID_START_FROM[1] + content_protect_b
|
|
@@ -1713,49 +1764,55 @@ app.get('/', async function(req, res) {
|
|
|
1713
1764
|
body += '><td>' + description + teams + pitchers + state + '</td>'
|
|
1714
1765
|
|
|
1715
1766
|
// Check if Winter League / MiLB game first
|
|
1716
|
-
if ( cache_data.dates[0].games[j].teams['home'].team.sport.id != '1' ) {
|
|
1767
|
+
if ( (cache_data.dates[0].games[j].teams['home'].team.sport.id != '1') && (mediaType == 'MLBTV') ) {
|
|
1717
1768
|
body += "<td>"
|
|
1718
1769
|
if ( cache_data.dates[0].games[j].broadcasts ) {
|
|
1770
|
+
let broadcastName = 'N/A'
|
|
1719
1771
|
for (var k = 0; k < cache_data.dates[0].games[j].broadcasts.length; k++) {
|
|
1720
|
-
if (
|
|
1772
|
+
if ( cache_data.dates[0].games[j].broadcasts[k].name != 'Audio' ) {
|
|
1773
|
+
broadcastName = mediaType
|
|
1774
|
+
break
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
if ( broadcastName == 'N/A' ) {
|
|
1778
|
+
body += broadcastName
|
|
1779
|
+
} else {
|
|
1780
|
+
// Check if game should be live
|
|
1781
|
+
if ( (cache_data.dates[0].games[j].status.detailedState != 'Postponed') && (cache_data.dates[0].games[j].status.detailedState != 'Cancelled') ) {
|
|
1721
1782
|
// Check if game should be live
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
if (
|
|
1733
|
-
if (
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
if (
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
if ( currentTime < endTime ) {
|
|
1748
|
-
if ( force_vod != VALID_FORCE_VOD[0] ) querystring += '&force_vod=' + force_vod
|
|
1749
|
-
}
|
|
1783
|
+
let currentTime = new Date()
|
|
1784
|
+
let startTime = new Date(cache_data.dates[0].games[j].gameDate)
|
|
1785
|
+
startTime.setMinutes(startTime.getMinutes()-30)
|
|
1786
|
+
if ( (currentTime >= startTime) ) {
|
|
1787
|
+
let gamePk = cache_data.dates[0].games[j].gamePk
|
|
1788
|
+
let querystring
|
|
1789
|
+
querystring = '?gamePk=' + gamePk
|
|
1790
|
+
let multiviewquerystring = querystring + '&resolution=' + DEFAULT_MULTIVIEW_RESOLUTION
|
|
1791
|
+
if ( resolution != VALID_RESOLUTIONS[0] ) querystring += '&resolution=' + resolution
|
|
1792
|
+
if ( linkType == VALID_LINK_TYPES[0] ) {
|
|
1793
|
+
if ( startFrom != VALID_START_FROM[0] ) querystring += '&startFrom=' + startFrom
|
|
1794
|
+
if ( controls != VALID_CONTROLS[0] ) querystring += '&controls=' + controls
|
|
1795
|
+
}
|
|
1796
|
+
if ( resumeStatus == false ) {
|
|
1797
|
+
if ( inning_half != VALID_INNING_HALF[0] ) querystring += '&inning_half=' + inning_half
|
|
1798
|
+
if ( inning_number != VALID_INNING_NUMBER[0] ) querystring += '&inning_number=' + relative_inning
|
|
1799
|
+
if ( skip != VALID_SKIP[0] ) querystring += '&skip=' + skip
|
|
1800
|
+
//if ( skip_adjust != DEFAULT_SKIP_ADJUST ) querystring += '&skip_adjust=' + skip_adjust
|
|
1801
|
+
}
|
|
1802
|
+
if ( pad != VALID_PAD[0] ) querystring += '&pad=' + pad
|
|
1803
|
+
if ( linkType == VALID_LINK_TYPES[1] ) {
|
|
1804
|
+
let endTime = new Date(cache_data.dates[0].games[j].gameDate)
|
|
1805
|
+
endTime.setHours(endTime.getHours()+4)
|
|
1806
|
+
if ( currentTime < endTime ) {
|
|
1807
|
+
if ( force_vod != VALID_FORCE_VOD[0] ) querystring += '&force_vod=' + force_vod
|
|
1750
1808
|
}
|
|
1751
|
-
querystring += content_protect_b
|
|
1752
|
-
multiviewquerystring += content_protect_b
|
|
1753
|
-
body += '<a href="' + thislink + querystring + '">' + cache_data.dates[0].games[j].broadcasts[k].name + '</a>'
|
|
1754
|
-
body += '<input type="checkbox" value="' + server + '/stream.m3u8' + multiviewquerystring + '" onclick="addmultiview(this)">'
|
|
1755
|
-
} else {
|
|
1756
|
-
body += cache_data.dates[0].games[j].broadcasts[k].name
|
|
1757
1809
|
}
|
|
1758
|
-
|
|
1810
|
+
querystring += content_protect_b
|
|
1811
|
+
multiviewquerystring += content_protect_b
|
|
1812
|
+
body += '<a href="' + thislink + querystring + '">' + broadcastName + '</a>'
|
|
1813
|
+
body += '<input type="checkbox" value="' + server + '/stream.m3u8' + multiviewquerystring + '" onclick="addmultiview(this)">'
|
|
1814
|
+
} else {
|
|
1815
|
+
body += broadcastName
|
|
1759
1816
|
}
|
|
1760
1817
|
}
|
|
1761
1818
|
}
|
|
@@ -1961,7 +2018,7 @@ app.get('/', async function(req, res) {
|
|
|
1961
2018
|
}
|
|
1962
2019
|
body += '</p>' + "\n"
|
|
1963
2020
|
|
|
1964
|
-
body += '<p><span class="tooltip">Skip<span class="tooltiptext">For video streams only (use the video "none" option above to apply it to audio streams): you can remove breaks, idle time,
|
|
2021
|
+
body += '<p><span class="tooltip">Skip<span class="tooltiptext">For video streams only (use the video "none" option above to apply it to audio streams): you can remove all breaks, idle time, non-action pitches, or only commercial breaks from the stream (useful to make your own "condensed games").<br/><br/>NOTE: skip timings are only generated when the stream is loaded -- so for live games, it will only skip up to the time you loaded the stream. Also, commercial break skipping will ignore inning start options (it will always start from the beginning).</span></span>: '
|
|
1965
2022
|
for (var i = 0; i < VALID_SKIP.length; i++) {
|
|
1966
2023
|
body += '<button '
|
|
1967
2024
|
if ( skip == VALID_SKIP[i] ) body += 'class="default" '
|
package/package.json
CHANGED
package/session.js
CHANGED
|
@@ -1225,6 +1225,17 @@ class sessionClass {
|
|
|
1225
1225
|
}
|
|
1226
1226
|
}
|
|
1227
1227
|
|
|
1228
|
+
setRecapRundownCacheExpiry(dateString, expiryDate) {
|
|
1229
|
+
if ( !this.cache.recapRundown ) {
|
|
1230
|
+
this.cache.recapRundown = {}
|
|
1231
|
+
}
|
|
1232
|
+
if ( !this.cache.recapRundown[dateString] ) {
|
|
1233
|
+
this.cache.recapRundown[dateString] = {}
|
|
1234
|
+
}
|
|
1235
|
+
this.cache.recapRundown[dateString].recapRundownCacheExpiry = expiryDate
|
|
1236
|
+
this.save_cache_data()
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1228
1239
|
cacheMediaId(contentId, mediaId, alternateAudioTracks) {
|
|
1229
1240
|
this.createContentCache(contentId)
|
|
1230
1241
|
this.cache.content[contentId].mediaId = mediaId
|
|
@@ -3211,6 +3222,79 @@ class sessionClass {
|
|
|
3211
3222
|
}
|
|
3212
3223
|
}
|
|
3213
3224
|
|
|
3225
|
+
// Get Recap Rundown data
|
|
3226
|
+
async getRecapRundownData(dateString) {
|
|
3227
|
+
try {
|
|
3228
|
+
this.debuglog('getRecapRundownData for ' + dateString)
|
|
3229
|
+
|
|
3230
|
+
let cache_data
|
|
3231
|
+
let cache_name = 'recaprundown' + dateString
|
|
3232
|
+
let cache_file = path.join(this.CACHE_DIRECTORY, cache_name + '.json')
|
|
3233
|
+
let currentDate = new Date()
|
|
3234
|
+
if ( !fs.existsSync(cache_file) || !this.cache || !this.cache.recapRundown || !this.cache.recapRundown[dateString] || !this.cache.recapRundown[dateString].recapRundownCacheExpiry || (currentDate > new Date(this.cache.recapRundown[dateString].recapRundownCacheExpiry)) ) {
|
|
3235
|
+
let reqObj = {
|
|
3236
|
+
url: 'https://dapi.mlbinfra.com/v2/content/en-us/videos/mlb-tv-recap-rundown-' + dateString,
|
|
3237
|
+
headers: {
|
|
3238
|
+
'Authorization': 'Bearer ' + await this.getLoginToken() || this.halt('missing loginToken'),
|
|
3239
|
+
'User-Agent': USER_AGENT,
|
|
3240
|
+
'Origin': 'https://www.mlb.com',
|
|
3241
|
+
'Referer': 'https://www.mlb.com',
|
|
3242
|
+
'Content-Type': 'application/json',
|
|
3243
|
+
'Accept-Encoding': 'gzip, deflate, br'
|
|
3244
|
+
},
|
|
3245
|
+
gzip: true
|
|
3246
|
+
}
|
|
3247
|
+
var response = await this.httpGet(reqObj, false)
|
|
3248
|
+
if ( response && this.isValidJson(response) ) {
|
|
3249
|
+
this.debuglog(response)
|
|
3250
|
+
cache_data = JSON.parse(response)
|
|
3251
|
+
this.save_json_cache_file(cache_name, cache_data)
|
|
3252
|
+
|
|
3253
|
+
// Default cache period is 5 minutes from now
|
|
3254
|
+
let fiveMinutesFromNow = new Date()
|
|
3255
|
+
fiveMinutesFromNow.setMinutes(fiveMinutesFromNow.getMinutes()+5)
|
|
3256
|
+
let cacheExpiry = fiveMinutesFromNow
|
|
3257
|
+
|
|
3258
|
+
// finally save the setting
|
|
3259
|
+
this.setRecapRundownCacheExpiry(dateString, cacheExpiry)
|
|
3260
|
+
this.save_cache_data()
|
|
3261
|
+
} else {
|
|
3262
|
+
this.log('error : invalid json from url ' + reqObj.url)
|
|
3263
|
+
return
|
|
3264
|
+
}
|
|
3265
|
+
} else {
|
|
3266
|
+
this.debuglog('using cached Recap Rundown data')
|
|
3267
|
+
cache_data = this.readFileToJson(cache_file)
|
|
3268
|
+
}
|
|
3269
|
+
if (cache_data) {
|
|
3270
|
+
return cache_data
|
|
3271
|
+
}
|
|
3272
|
+
} catch(e) {
|
|
3273
|
+
this.log('getRecapRundownData error : ' + e.message)
|
|
3274
|
+
}
|
|
3275
|
+
}
|
|
3276
|
+
|
|
3277
|
+
// Get Recap Rundown URL, used to determine the stream URL if available
|
|
3278
|
+
async getRecapRundownURL(dateString) {
|
|
3279
|
+
try {
|
|
3280
|
+
this.debuglog('getRecapRundownURL for ' + dateString)
|
|
3281
|
+
|
|
3282
|
+
let cache_data = await this.getRecapRundownData(dateString)
|
|
3283
|
+
|
|
3284
|
+
if ( cache_data && cache_data.fields && cache_data.fields.playbackScenarios && cache_data.fields.playbackScenarios && (cache_data.fields.playbackScenarios.length > 0) ) {
|
|
3285
|
+
this.debuglog('getRecapRundownURL found ' + cache_data.fields.playbackScenarios.length + ' playbackScenarios')
|
|
3286
|
+
for (var i=0; i<cache_data.fields.playbackScenarios.length; i++) {
|
|
3287
|
+
if ( cache_data.fields.playbackScenarios[i].playback && (cache_data.fields.playbackScenarios[i].playback == 'hlsCloud') && cache_data.fields.playbackScenarios[i].location ) {
|
|
3288
|
+
this.debuglog('found Recap Rundown url at ' + cache_data.fields.playbackScenarios[i].location)
|
|
3289
|
+
return cache_data.fields.playbackScenarios[i].location
|
|
3290
|
+
}
|
|
3291
|
+
}
|
|
3292
|
+
}
|
|
3293
|
+
} catch(e) {
|
|
3294
|
+
this.log('getRecapRundownURL error : ' + e.message)
|
|
3295
|
+
}
|
|
3296
|
+
}
|
|
3297
|
+
|
|
3214
3298
|
// Get event stream URL
|
|
3215
3299
|
async getEventStreamURL(eventName, gamePk=false) {
|
|
3216
3300
|
if ( gamePk ) {
|
|
@@ -3225,7 +3309,13 @@ class sessionClass {
|
|
|
3225
3309
|
if ( gamePk ) {
|
|
3226
3310
|
playbackURL = 'https://dai.tv.milb.com/api/v2/playback-info/games/' + gamePk + '/contents/14862/products/milb-carousel'
|
|
3227
3311
|
} else if ( eventName ) {
|
|
3228
|
-
|
|
3312
|
+
if ( eventName.startsWith('RECAPRUNDOWN') ) {
|
|
3313
|
+
let dateString = eventName.substring(12)
|
|
3314
|
+
this.debuglog('getEventStreamURL RecapRundown for ' + dateString)
|
|
3315
|
+
playbackURL = await this.getRecapRundownURL(dateString)
|
|
3316
|
+
} else {
|
|
3317
|
+
playbackURL = await this.getEventURL(eventName)
|
|
3318
|
+
}
|
|
3229
3319
|
}
|
|
3230
3320
|
if ( !playbackURL ) {
|
|
3231
3321
|
this.debuglog('no active event url')
|