mlbserver 2025.3.30 → 2025.4.0-1.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 +32 -29
- package/package.json +1 -1
- package/session.js +38 -110
package/index.js
CHANGED
|
@@ -44,7 +44,7 @@ const VALID_SCAN_MODES = [ 'off', 'on' ]
|
|
|
44
44
|
|
|
45
45
|
const SAMPLE_STREAM_URL = 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8'
|
|
46
46
|
|
|
47
|
-
const SECONDS_PER_SEGMENT =
|
|
47
|
+
const SECONDS_PER_SEGMENT = 4
|
|
48
48
|
|
|
49
49
|
// for favorites: text, then background, based on https://teamcolors.jim-nielsen.com/
|
|
50
50
|
const TEAM_COLORS = { 'ATH': ['003831', 'EFB21E'], 'ATL': ['13274F', 'CE1141'], 'AZ': ['E3D4AD', 'A71930'], 'BAL': ['000000', 'DF4601'], 'BOS': ['0D2B56', 'BD3039'], 'CHC': ['CC3433', '0E3386'], 'CWS': ['000000', 'C4CED4'], 'CIN': ['FFFFFF', 'C6011F'], 'CLE': ['002B5C', 'E31937'], 'COL': ['C4CED4', '333366'], 'DET': ['0C2C56', 'FFFFFF'], 'HOU': ['002D62', 'EB6E1F'], 'KC': ['C09A5B', '004687'], 'LAA': ['FFFFFF', 'BA0021'], 'LAD': ['FFFFFF', '005A9C'], 'MIA': ['0077C8', 'FF6600'], 'MIL': ['0A2351', 'B6922E'], 'MIN': ['D31145', '002B5C'], 'NYM': ['002D72', 'FF5910'], 'NYY': ['FFFFFF', '003087'], 'OAK': ['003831', 'EFB21E'], 'PHI': ['284898', 'E81828'], 'PIT': ['000000', 'FDB827'], 'STL': ['FEDB00', 'C41E3A'], 'SD': ['FEC325', '7F411C'], 'SF': ['000000', 'FD5A1E'], 'SEA': ['C4CED4', '005C5C'], 'TB': ['092C5C', '8FBCE6'], 'TEX': ['003278', 'C0111F'], 'TOR': ['FFFFFF', '134A8E'], 'WSH': ['AB0003', '11225B'] }
|
|
@@ -863,26 +863,31 @@ app.get('/playlist.m3u8', async function(req, res) {
|
|
|
863
863
|
})
|
|
864
864
|
.join('\n')+'\n'
|
|
865
865
|
|
|
866
|
+
let end_tag = '#EXT-X-ENDLIST'
|
|
866
867
|
if ( pad != VALID_PAD[0] ) {
|
|
867
868
|
let body_array = body.trim().split('\n')
|
|
868
|
-
let
|
|
869
|
-
if ( body_array[
|
|
869
|
+
let segment_index = body_array.length-1
|
|
870
|
+
if ( body_array[segment_index] == end_tag ) {
|
|
870
871
|
session.debuglog('padding archive stream with extra segments')
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
last_segment_index--
|
|
872
|
+
while ( body_array[segment_index].startsWith('#') ) {
|
|
873
|
+
segment_index--
|
|
874
874
|
}
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
let pad_lines = '#EXT-X-DISCONTINUITY' + '\n' + '#EXTINF:' + SECONDS_PER_SEGMENT + '\n' + last_segment + '\n'
|
|
878
|
-
session.debuglog(pad_lines)
|
|
875
|
+
let last_segment = body_array[segment_index]
|
|
876
|
+
body_array.pop()
|
|
879
877
|
for (i=0; i<pad; i++) {
|
|
880
|
-
|
|
878
|
+
body_array.push('#EXT-X-DISCONTINUITY')
|
|
879
|
+
body_array.push('#EXTINF:' + SECONDS_PER_SEGMENT)
|
|
880
|
+
body_array.push(last_segment)
|
|
881
881
|
}
|
|
882
|
-
|
|
882
|
+
body_array.push(end_tag)
|
|
883
|
+
body = body_array.join('\n')
|
|
884
|
+
}
|
|
885
|
+
} else if ( force_vod != VALID_FORCE_VOD[0] ) {
|
|
886
|
+
let body_array = body.trim().split('\n')
|
|
887
|
+
if ( body_array[body_array.length-1] != end_tag ) {
|
|
888
|
+
body += end_tag + '\n'
|
|
883
889
|
}
|
|
884
890
|
}
|
|
885
|
-
if ( force_vod != VALID_FORCE_VOD[0] ) body += '#EXT-X-ENDLIST' + '\n'
|
|
886
891
|
session.debuglog(body)
|
|
887
892
|
respond(response, res, Buffer.from(body))
|
|
888
893
|
})
|
|
@@ -1041,7 +1046,7 @@ app.get('/gamechanger.m3u8', async function(req, res) {
|
|
|
1041
1046
|
|
|
1042
1047
|
for ( gamechanger_resolution in GAMECHANGER_RESOLUTIONS ) {
|
|
1043
1048
|
if ( resolution == gamechanger_resolution ) {
|
|
1044
|
-
body += '#EXT-X-STREAM-INF:BANDWIDTH=' + GAMECHANGER_RESOLUTIONS[gamechanger_resolution].bandwidth + '000,RESOLUTION=' + GAMECHANGER_RESOLUTIONS[gamechanger_resolution].resolution + ',FRAME-RATE=' + GAMECHANGER_RESOLUTIONS[gamechanger_resolution].frame_rate + ',CODECS="mp4a.40.2,avc1.' + GAMECHANGER_RESOLUTIONS[gamechanger_resolution].codec + '",CLOSED-CAPTIONS="cc",AUDIO="aac"' + '\n' + '/gamechangerplaylist?id=' + id + '&resolution=' + gamechanger_resolution + includeTeams + excludeTeams + content_protect + '\n'
|
|
1049
|
+
body += '#EXT-X-STREAM-INF:BANDWIDTH=' + GAMECHANGER_RESOLUTIONS[gamechanger_resolution].bandwidth + '000,RESOLUTION=' + GAMECHANGER_RESOLUTIONS[gamechanger_resolution].resolution + ',FRAME-RATE=' + GAMECHANGER_RESOLUTIONS[gamechanger_resolution].frame_rate + ',CODECS="mp4a.40.2,avc1.' + GAMECHANGER_RESOLUTIONS[gamechanger_resolution].codec + '",CLOSED-CAPTIONS="cc",AUDIO="aac"' + '\n' + '/gamechangerplaylist.m3u8?id=' + id + '&resolution=' + gamechanger_resolution + includeTeams + excludeTeams + content_protect + '\n'
|
|
1045
1050
|
break
|
|
1046
1051
|
}
|
|
1047
1052
|
}
|
|
@@ -1055,10 +1060,10 @@ app.get('/gamechanger.m3u8', async function(req, res) {
|
|
|
1055
1060
|
|
|
1056
1061
|
|
|
1057
1062
|
// Listen for gamechanger playlist requests
|
|
1058
|
-
app.get('/gamechangerplaylist', async function(req, res) {
|
|
1063
|
+
app.get('/gamechangerplaylist.m3u8', async function(req, res) {
|
|
1059
1064
|
if ( ! (await protect(req, res)) ) return
|
|
1060
1065
|
|
|
1061
|
-
session.requestlog('gamechangerplaylist', req, true)
|
|
1066
|
+
session.requestlog('gamechangerplaylist.m3u8', req, true)
|
|
1062
1067
|
|
|
1063
1068
|
let gamechangerAccess = new Date()
|
|
1064
1069
|
|
|
@@ -1661,8 +1666,7 @@ app.get('/', async function(req, res) {
|
|
|
1661
1666
|
}
|
|
1662
1667
|
|
|
1663
1668
|
// Big Inning
|
|
1664
|
-
|
|
1665
|
-
/*var big_inning
|
|
1669
|
+
var big_inning
|
|
1666
1670
|
if ( cache_data.dates && cache_data.dates[0] && (cache_data.dates[0].date >= today) && cache_data.dates[0].games && (cache_data.dates[0].games.length > 1) && cache_data.dates[0].games[0] && (cache_data.dates[0].games[0].seriesDescription == 'Regular Season') ) {
|
|
1667
1671
|
// Scraped Big Inning schedule
|
|
1668
1672
|
big_inning = await session.getBigInningSchedule(gameDate)
|
|
@@ -1676,7 +1680,7 @@ app.get('/', async function(req, res) {
|
|
|
1676
1680
|
compareStart.setMinutes(compareStart.getMinutes()-10)
|
|
1677
1681
|
let compareEnd = new Date(big_inning.end)
|
|
1678
1682
|
compareEnd.setHours(compareEnd.getHours()+1)
|
|
1679
|
-
if ( (currentDate >= compareStart) && (currentDate < compareEnd) ) {
|
|
1683
|
+
if ( (currentDate >= compareStart) && (currentDate < compareEnd) ) {
|
|
1680
1684
|
body += '<tr><td><span class="tooltip">Big Inning<span class="tooltiptext">Big Inning is the live look-in and highlights show. <a href="https://support.mlb.com/s/article/What-Is-MLB-Big-Inning">See here for more information</a>.</span></span></td><td>'
|
|
1681
1685
|
let querystring = '?event=biginning'
|
|
1682
1686
|
let multiviewquerystring = querystring + '&resolution=' + DEFAULT_MULTIVIEW_RESOLUTION
|
|
@@ -1694,11 +1698,11 @@ app.get('/', async function(req, res) {
|
|
|
1694
1698
|
multiviewquerystring += content_protect_b
|
|
1695
1699
|
body += '<a href="' + thislink + querystring + '">Big Inning</a>'
|
|
1696
1700
|
body += '<input type="checkbox" value="http://127.0.0.1:' + session.data.port + '/stream.m3u8' + multiviewquerystring + '" onclick="addmultiview(this)">'
|
|
1697
|
-
|
|
1701
|
+
} else {
|
|
1698
1702
|
body += 'Big Inning'
|
|
1699
|
-
}
|
|
1703
|
+
}
|
|
1700
1704
|
body += '</td></tr>' + "\n"
|
|
1701
|
-
|
|
1705
|
+
}
|
|
1702
1706
|
|
|
1703
1707
|
// Game Changer
|
|
1704
1708
|
if ( (gameDate >= today) && cache_data.dates && cache_data.dates[0] && cache_data.dates[0].games && (cache_data.dates[0].games.length > 1) ) {
|
|
@@ -1713,15 +1717,15 @@ app.get('/', async function(req, res) {
|
|
|
1713
1717
|
compareEnd.setHours(compareEnd.getHours()+4)
|
|
1714
1718
|
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 720p60 resolution if not specified.</span></span></td><td>'
|
|
1715
1719
|
if ( (currentDate >= compareStart) && (currentDate < compareEnd) ) {
|
|
1716
|
-
let streamURL = server + '/gamechanger.m3u8'
|
|
1717
|
-
let multiviewquerystring = streamURL + '
|
|
1720
|
+
let streamURL = server + '/gamechanger.m3u8?'
|
|
1721
|
+
let multiviewquerystring = streamURL + 'resolution=' + DEFAULT_MULTIVIEW_RESOLUTION + content_protect_b
|
|
1718
1722
|
streamURL += content_protect_a
|
|
1719
|
-
if ( resolution != VALID_RESOLUTIONS[0] ) streamURL += '
|
|
1723
|
+
if ( resolution != VALID_RESOLUTIONS[0] ) streamURL += 'resolution=' + resolution + '&'
|
|
1720
1724
|
if ( linkType != VALID_LINK_TYPES[1] ) {
|
|
1721
|
-
streamURL = thislink + '?src=' + encodeURIComponent(streamURL) + '
|
|
1725
|
+
streamURL = thislink + '?src=' + encodeURIComponent(streamURL) + 'startFrom=' + VALID_START_FROM[1] + content_protect_b + '&'
|
|
1722
1726
|
}
|
|
1723
1727
|
if ( linkType == VALID_LINK_TYPES[4] ) {
|
|
1724
|
-
streamURL += '
|
|
1728
|
+
streamURL += 'filename=' + gameDate + ' Game Changer' + '&'
|
|
1725
1729
|
}
|
|
1726
1730
|
body += '<a href="' + streamURL + '">Game Changer</a>'
|
|
1727
1731
|
body += '<input type="checkbox" value="http://127.0.0.1:' + session.data.port + multiviewquerystring + '" onclick="addmultiview(this, [], excludeTeams)">'
|
|
@@ -2277,8 +2281,7 @@ app.get('/', async function(req, res) {
|
|
|
2277
2281
|
body += '<p><span class="tooltip">Include (or exclude) SNY<span class="tooltiptext">SNY live stream for entitled subscribers. <a href="https://support.mlb.com/s/article/SNLA-Plus-Subscription-Packages">See here for more information</a>.</span></span>: <a href="' + http_root + '/channels.m3u?mediaType=' + mediaType + '&resolution=' + resolution + '&includeTeams=sny' + content_protect_b + '">m3u</a> and <a href="' + http_root + '/guide.xml?mediaType=' + mediaType + '&includeTeams=sny' + content_protect_b + '">xml</a></p>' + "\n"
|
|
2278
2282
|
}
|
|
2279
2283
|
|
|
2280
|
-
|
|
2281
|
-
body += '<p><span class="tooltip">Include (or exclude) Big Inning<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>: <a href="' + http_root + '/channels.m3u?mediaType=' + mediaType + '&resolution=' + resolution + '&includeTeams=biginning' + content_protect_b + '">m3u</a> and <a href="' + http_root + '/guide.xml?mediaType=' + mediaType + '&includeTeams=biginning' + content_protect_b + '">xml</a><!-- and <a href="' + http_root + '/calendar.ics?mediaType=' + mediaType + '&includeTeams=biginning' + content_protect_b + '">ics</a>--></p>' + "\n"
|
|
2284
|
+
body += '<p><span class="tooltip">Include (or exclude) Big Inning<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>: <a href="' + http_root + '/channels.m3u?mediaType=' + mediaType + '&resolution=' + resolution + '&includeTeams=biginning' + content_protect_b + '">m3u</a> and <a href="' + http_root + '/guide.xml?mediaType=' + mediaType + '&includeTeams=biginning' + content_protect_b + '">xml</a> and <a href="' + http_root + '/calendar.ics?mediaType=' + mediaType + '&includeTeams=biginning' + content_protect_b + '">ics</a></p>' + "\n"
|
|
2282
2285
|
|
|
2283
2286
|
let gamechanger_resolution = resolution
|
|
2284
2287
|
if ( gamechanger_resolution == VALID_RESOLUTIONS[0] ) {
|
package/package.json
CHANGED
package/session.js
CHANGED
|
@@ -46,6 +46,8 @@ const ACTION_END_PADDING = 7
|
|
|
46
46
|
const MINIMUM_BREAK_DURATION = 5
|
|
47
47
|
// extra padding for MLB events (2025)
|
|
48
48
|
const MLB_PADDING = 39
|
|
49
|
+
// extra Game Changer padding for MLB (2025)
|
|
50
|
+
const MLB_GAMECHANGER_PADDING = 20
|
|
49
51
|
|
|
50
52
|
const LI_TABLE = {
|
|
51
53
|
1: {
|
|
@@ -1271,7 +1273,7 @@ class sessionClass {
|
|
|
1271
1273
|
this.save_cache_data()
|
|
1272
1274
|
}
|
|
1273
1275
|
|
|
1274
|
-
cacheStreamURL(mediaId, streamURL, streamURLToken='', streamURLExpiration='') {
|
|
1276
|
+
cacheStreamURL(mediaId, streamURL, streamURLToken='', streamURLExpiration='', rawStreamURL='') {
|
|
1275
1277
|
this.createMediaCache(mediaId)
|
|
1276
1278
|
this.cache.media[mediaId].streamURL = streamURL
|
|
1277
1279
|
if (streamURLToken != '') {
|
|
@@ -1284,6 +1286,7 @@ class sessionClass {
|
|
|
1284
1286
|
} else {
|
|
1285
1287
|
this.cache.media[mediaId].streamURLExpiry = new Date(streamURLExpiration)
|
|
1286
1288
|
}
|
|
1289
|
+
this.cache.media[mediaId].rawStreamURL = rawStreamURL
|
|
1287
1290
|
this.save_cache_data()
|
|
1288
1291
|
}
|
|
1289
1292
|
|
|
@@ -1574,6 +1577,9 @@ class sessionClass {
|
|
|
1574
1577
|
if ( this.cache.media && this.cache.media[mediaId] && this.cache.media[mediaId].streamURL && this.cache.media[mediaId].streamURLToken && this.cache.media[mediaId].streamURLExpiry && (Date.parse(this.cache.media[mediaId].streamURLExpiry) > new Date()) ) {
|
|
1575
1578
|
this.debuglog('using cached streamURL and token')
|
|
1576
1579
|
let streamInfo = {streamURL: this.cache.media[mediaId].streamURL, streamURLToken: this.cache.media[mediaId].streamURLToken}
|
|
1580
|
+
if ( this.cache.media[mediaId].rawStreamURL ) {
|
|
1581
|
+
streamInfo['rawStreamURL'] = this.cache.media[mediaId].rawStreamURL
|
|
1582
|
+
}
|
|
1577
1583
|
return streamInfo
|
|
1578
1584
|
} else if ( this.cache.media && this.cache.media[mediaId] && this.cache.media[mediaId].blackout && this.cache.media[mediaId].blackoutExpiry && (Date.parse(this.cache.media[mediaId].blackoutExpiry) > new Date()) ) {
|
|
1579
1585
|
this.log('mediaId recently blacked out, skipping')
|
|
@@ -1616,19 +1622,15 @@ class sessionClass {
|
|
|
1616
1622
|
if ( response.data && response.data.initPlaybackSession && response.data.initPlaybackSession.playback && response.data.initPlaybackSession.playback.url ) {
|
|
1617
1623
|
let rawStreamURL = response.data.initPlaybackSession.playback.url
|
|
1618
1624
|
this.debuglog('getStreamURL rawStreamURL : ' + rawStreamURL)
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
this.cacheStreamURL(mediaId, streamURL, streamURLToken, streamURLExpiration)
|
|
1629
|
-
let streamInfo = {streamURL: streamURL, streamURLToken: streamURLToken}
|
|
1630
|
-
return streamInfo
|
|
1631
|
-
}
|
|
1625
|
+
let streamURL = rawStreamURL.replace(/[\/]([A-Za-z0-9_]+)[\/]/, '/')
|
|
1626
|
+
let streamURLToken = response.data.initPlaybackSession.playback.token
|
|
1627
|
+
let streamURLExpiration = response.data.initPlaybackSession.playback.expiration
|
|
1628
|
+
this.debuglog('getStreamURL streamURL : ' + streamURL)
|
|
1629
|
+
this.debuglog('getStreamURL token : ' + streamURLToken)
|
|
1630
|
+
this.debuglog('getStreamURL expiration : ' + streamURLExpiration)
|
|
1631
|
+
this.cacheStreamURL(mediaId, streamURL, streamURLToken, streamURLExpiration, rawStreamURL)
|
|
1632
|
+
let streamInfo = {streamURL: streamURL, streamURLToken: streamURLToken, rawStreamURL: rawStreamURL}
|
|
1633
|
+
return streamInfo
|
|
1632
1634
|
} else {
|
|
1633
1635
|
this.log('getStreamURL streamURL not found')
|
|
1634
1636
|
return false
|
|
@@ -2710,7 +2712,7 @@ class sessionClass {
|
|
|
2710
2712
|
let description = 'Live look-ins and big moments from around the league'
|
|
2711
2713
|
|
|
2712
2714
|
// disabled Big Inning schedule scraping March 2025
|
|
2713
|
-
|
|
2715
|
+
for (var i = 0; i < cache_data.dates.length; i++) {
|
|
2714
2716
|
// Scraped Big Inning schedule
|
|
2715
2717
|
if ( (cache_data.dates[i].date >= today) && cache_data.dates[i].games && (cache_data.dates[i].games.length > 1) && cache_data.dates[i].games[0] && (cache_data.dates[i].games[0].seriesDescription == 'Regular Season') ) {
|
|
2716
2718
|
await this.getBigInningSchedule()
|
|
@@ -2741,12 +2743,12 @@ class sessionClass {
|
|
|
2741
2743
|
programs += await this.generate_xml_program(channelid, start, stop, title, description, logo, this.convertDateToAirDate(new Date(this.cache.bigInningSchedule[gameDate].start)))
|
|
2742
2744
|
}
|
|
2743
2745
|
this.debuglog('getTVData completed Big Inning for date ' + cache_data.dates[i].date)
|
|
2744
|
-
}
|
|
2746
|
+
}
|
|
2745
2747
|
|
|
2746
2748
|
// generic Big Inning guide XML
|
|
2747
|
-
let start = this.convertDateToXMLTV(new Date(cache_data.dates[0].date + ' 00:00:00'))
|
|
2749
|
+
/*let start = this.convertDateToXMLTV(new Date(cache_data.dates[0].date + ' 00:00:00'))
|
|
2748
2750
|
let stop = this.convertDateToXMLTV(new Date(cache_data.dates[cache_data.dates.length-1].date + ' 00:00:00'))
|
|
2749
|
-
programs += await this.generate_xml_program(channelid, start, stop, title, description, logo, this.convertStringToAirDate(cache_data.dates[0].date))
|
|
2751
|
+
programs += await this.generate_xml_program(channelid, start, stop, title, description, logo, this.convertStringToAirDate(cache_data.dates[0].date))*/
|
|
2750
2752
|
|
|
2751
2753
|
this.debuglog('getTVData completed Big Inning')
|
|
2752
2754
|
}
|
|
@@ -3197,17 +3199,15 @@ class sessionClass {
|
|
|
3197
3199
|
this.debuglog('getBigInningSchedule')
|
|
3198
3200
|
|
|
3199
3201
|
// temporarily disable Big Inning schedule checking until a new source URL is available
|
|
3200
|
-
this.cache.bigInningSchedule = {}
|
|
3201
|
-
return
|
|
3202
|
+
/*this.cache.bigInningSchedule = {}
|
|
3203
|
+
return*/
|
|
3202
3204
|
|
|
3203
3205
|
let currentDate = new Date()
|
|
3204
3206
|
if ( !this.cache || !this.cache.bigInningScheduleCacheExpiry || (currentDate > new Date(this.cache.bigInningScheduleCacheExpiry)) ) {
|
|
3205
3207
|
if ( !this.cache.bigInningSchedule ) this.cache.bigInningSchedule = {}
|
|
3206
3208
|
let reqObj = {
|
|
3207
|
-
|
|
3208
|
-
url: 'https://www.mlb.com/live-stream-games/help-center/subscription-access-big-inning',
|
|
3209
|
+
url: 'https://www.fubo.tv/welcome/channel/mlb-big-inning',
|
|
3209
3210
|
headers: {
|
|
3210
|
-
'authority': 'www.mlb.com',
|
|
3211
3211
|
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
|
|
3212
3212
|
'accept-language': 'en-US,en;q=0.9',
|
|
3213
3213
|
'cache-control': 'no-cache',
|
|
@@ -3230,89 +3230,15 @@ class sessionClass {
|
|
|
3230
3230
|
if ( response ) {
|
|
3231
3231
|
// disabled because it's very big!
|
|
3232
3232
|
//this.debuglog(response)
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
let
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
let year
|
|
3243
|
-
let month
|
|
3244
|
-
let day
|
|
3245
|
-
let this_datestring
|
|
3246
|
-
let add_date = 0
|
|
3247
|
-
let d
|
|
3248
|
-
|
|
3249
|
-
for (var j=1; j<cols.length; j++) {
|
|
3250
|
-
// split on closing bracket to get column text at resulting array index 0
|
|
3251
|
-
let col = cols[j].split('<')
|
|
3252
|
-
switch(j){
|
|
3253
|
-
// first column is date
|
|
3254
|
-
case 1:
|
|
3255
|
-
// split date into array
|
|
3256
|
-
// old date format (January 1, 1970) (disabled)
|
|
3257
|
-
/*parts = col[0].split(' ')
|
|
3258
|
-
year = parts[2]
|
|
3259
|
-
// get month index, zero-based
|
|
3260
|
-
month = new Date(Date.parse(parts[0] +" 1, 2021")).getMonth()
|
|
3261
|
-
day = parts[1].substring(0,parts[1].length-3)*/
|
|
3262
|
-
// new date format (01/01/70)
|
|
3263
|
-
parts = col[0].split('/')
|
|
3264
|
-
year = parts[2]
|
|
3265
|
-
if ( year.length == 2 ) {
|
|
3266
|
-
year = '20' + parts[2]
|
|
3267
|
-
}
|
|
3268
|
-
// get month index, zero-based
|
|
3269
|
-
month = parseInt(parts[0]) - 1
|
|
3270
|
-
day = parts[1]
|
|
3271
|
-
this_datestring = new Date(year, month, day).toISOString().substring(0,10)
|
|
3272
|
-
this.cache.bigInningSchedule[this_datestring] = {}
|
|
3273
|
-
// increment month index (not zero-based)
|
|
3274
|
-
month += 1
|
|
3275
|
-
break
|
|
3276
|
-
// remaining columns are times
|
|
3277
|
-
default:
|
|
3278
|
-
let hour
|
|
3279
|
-
let minute = '00'
|
|
3280
|
-
let ampm
|
|
3281
|
-
// if time has colon, split into array on that to get hour and minute parts
|
|
3282
|
-
if ( col[0].indexOf(':') > 0 ) {
|
|
3283
|
-
parts = col[0].split(':')
|
|
3284
|
-
hour = parseInt(parts[0])
|
|
3285
|
-
minute = parts[1].substring(0,2)
|
|
3286
|
-
} else {
|
|
3287
|
-
hour = parseInt(col[0].substring(0,col[0].length-2))
|
|
3288
|
-
}
|
|
3289
|
-
ampm = col[0].substring(col[0].length-2,col[0].length)
|
|
3290
|
-
// convert hour to 24-hour format
|
|
3291
|
-
if ( (ampm == 'PM') || ((hour == 12) && (ampm == 'AM')) ) {
|
|
3292
|
-
hour += 12
|
|
3293
|
-
}
|
|
3294
|
-
// these times are EDT so add 4 for UTC
|
|
3295
|
-
hour += 4
|
|
3296
|
-
// if hour is beyond 23, note we will have to add 1 day
|
|
3297
|
-
if ( hour > 23 ) {
|
|
3298
|
-
add_date = 1
|
|
3299
|
-
hour -= 24
|
|
3300
|
-
}
|
|
3301
|
-
|
|
3302
|
-
d = new Date(this_datestring + 'T' + hour.toString().padStart(2, '0') + ':' + minute.toString().padStart(2, '0') + ':00.000+00:00')
|
|
3303
|
-
d.setDate(d.getDate()+add_date)
|
|
3304
|
-
switch(j){
|
|
3305
|
-
// 2nd column is start time
|
|
3306
|
-
case 2:
|
|
3307
|
-
this.cache.bigInningSchedule[this_datestring].start = d
|
|
3308
|
-
break
|
|
3309
|
-
// 3rd column is end time
|
|
3310
|
-
case 3:
|
|
3311
|
-
this.cache.bigInningSchedule[this_datestring].end = d
|
|
3312
|
-
break
|
|
3313
|
-
}
|
|
3314
|
-
break
|
|
3315
|
-
}
|
|
3233
|
+
|
|
3234
|
+
let obj = JSON.parse(response.replace(/\\"/g, '"').match('(?<="channelPrograms":{"live":)(.+?(,"totalPages":1}))')[0])
|
|
3235
|
+
for (var i=0; i < obj.data.length; i++) {
|
|
3236
|
+
let est_date = new Date(obj.data[i].airings[0].start).toLocaleString("en-US", {timeZone: 'America/New_York'})
|
|
3237
|
+
let date_array = est_date.split(',')[0].split('/')
|
|
3238
|
+
let this_datestring = date_array[2] + '-' + date_array[0].padStart(2, '0') + '-' + date_array[1].padStart(2, '0')
|
|
3239
|
+
this.cache.bigInningSchedule[this_datestring] = {
|
|
3240
|
+
start: obj.data[i].airings[0].start,
|
|
3241
|
+
end: obj.data[i].airings[0].end
|
|
3316
3242
|
}
|
|
3317
3243
|
}
|
|
3318
3244
|
this.debuglog(JSON.stringify(this.cache.bigInningSchedule))
|
|
@@ -3499,9 +3425,9 @@ class sessionClass {
|
|
|
3499
3425
|
if ( response.data && response.data.contentCollections && (response.data.contentCollections.length > 0) && response.data.contentCollections[0].contents ) {
|
|
3500
3426
|
for (var i=0; i<response.data.contentCollections[0].contents.length; i++) {
|
|
3501
3427
|
try {
|
|
3502
|
-
let
|
|
3503
|
-
if (
|
|
3504
|
-
return
|
|
3428
|
+
let streamInfo = await this.getStreamURL(response.data.contentCollections[0].contents[i].mediaId)
|
|
3429
|
+
if ( streamInfo.rawStreamURL ) {
|
|
3430
|
+
return streamInfo.rawStreamURL
|
|
3505
3431
|
}
|
|
3506
3432
|
} catch(e) {
|
|
3507
3433
|
this.debuglog('getLinearStreamURL getStreamURL error : ' + e.message)
|
|
@@ -3610,8 +3536,10 @@ class sessionClass {
|
|
|
3610
3536
|
playbackURL = 'https://falcon.mlbinfra.com/api/v1/linear/mlbn'
|
|
3611
3537
|
} else if ( eventName.toUpperCase() == 'SNLA' ) {
|
|
3612
3538
|
playbackURL = await this.getLinearStreamURL('SNLA_LIVE')
|
|
3539
|
+
return playbackURL
|
|
3613
3540
|
} else if ( eventName.toUpperCase() == 'SNY' ) {
|
|
3614
3541
|
playbackURL = await this.getLinearStreamURL('SNY_LIVE')
|
|
3542
|
+
return playbackURL
|
|
3615
3543
|
} else {
|
|
3616
3544
|
playbackURL = await this.getEventURL(eventName)
|
|
3617
3545
|
}
|
|
@@ -4153,7 +4081,7 @@ class sessionClass {
|
|
|
4153
4081
|
|
|
4154
4082
|
if ( !this.temp_cache.gamechanger[id].games ) this.temp_cache.gamechanger[id].games = []
|
|
4155
4083
|
this.temp_cache.gamechanger[id].games.push(best_games)
|
|
4156
|
-
let maxlength = (this.gamechanger_delay + 10) / 10
|
|
4084
|
+
let maxlength = (this.gamechanger_delay + 10 + MLB_GAMECHANGER_PADDING) / 10
|
|
4157
4085
|
while ( this.temp_cache.gamechanger[id].games.length > maxlength ) {
|
|
4158
4086
|
this.temp_cache.gamechanger[id].games.shift()
|
|
4159
4087
|
}
|