mlbserver 2022.5.30 → 2022.6.9
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 +2 -1
- package/index.js +110 -33
- package/package.json +1 -1
- package/session.js +101 -23
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# mlbserver
|
|
2
2
|
|
|
3
|
-
Current version 2022.
|
|
3
|
+
Current version 2022.06.09
|
|
4
4
|
|
|
5
5
|
Credit to https://github.com/tonycpsu/streamglob and https://github.com/mafintosh/hls-decryptor
|
|
6
6
|
|
|
@@ -34,6 +34,7 @@ Advanced command line options:
|
|
|
34
34
|
```
|
|
35
35
|
--account_username (email address, default will use stored credentials or prompt user to enter them)
|
|
36
36
|
--account_password (default will use stored credentials or prompt user to enter them)
|
|
37
|
+
--zip_code (optional, for USA blackout labels, will prompt if not set or stored)
|
|
37
38
|
--multiview_port (port for multiview streaming; defaults to 1 more than primary port, or 10000)
|
|
38
39
|
--multiview_path (where to create the folder for multiview encoded files; defaults to app directory)
|
|
39
40
|
--ffmpeg_path (path to ffmpeg binary to use for multiview encoding; default downloads a binary using ffmpeg-static)
|
package/index.js
CHANGED
|
@@ -55,6 +55,7 @@ const SECONDS_PER_SEGMENT = 5
|
|
|
55
55
|
// Advanced command line arguments:
|
|
56
56
|
// --account_username (email address, default will use stored credentials or prompt user to enter them)
|
|
57
57
|
// --account_password (default will use stored credentials or prompt user to enter them)
|
|
58
|
+
// --zip_code (optional, for USA blackout labels, will prompt if not set or stored)
|
|
58
59
|
// --multiview_port (port for multiview streaming; defaults to 1 more than primary port, or 10000)
|
|
59
60
|
// --multiview_path (where to create the folder for multiview encoded files; defaults to app directory)
|
|
60
61
|
// --ffmpeg_path (path to ffmpeg binary to use for multiview encoding; default downloads a binary using ffmpeg-static)
|
|
@@ -674,8 +675,8 @@ app.get('/playlist', async function(req, res) {
|
|
|
674
675
|
last_segment_index--
|
|
675
676
|
}
|
|
676
677
|
last_segment_inf = body_array[last_segment_index]
|
|
677
|
-
|
|
678
|
-
let pad_lines = '#EXT-X-DISCONTINUITY' + '\n' + last_segment_inf + '\n' +
|
|
678
|
+
last_segment = body_array[last_segment_index+1]
|
|
679
|
+
let pad_lines = '#EXT-X-DISCONTINUITY' + '\n' + last_segment_inf + '\n' + last_segment + '\n'
|
|
679
680
|
session.debuglog(pad_lines)
|
|
680
681
|
for (i=0; i<pad; i++) {
|
|
681
682
|
body += pad_lines
|
|
@@ -788,6 +789,7 @@ app.get('/', async function(req, res) {
|
|
|
788
789
|
let multiview_server = server.replace(':' + session.data.port, ':' + session.data.multiviewPort)
|
|
789
790
|
|
|
790
791
|
let gameDate = session.liveDate()
|
|
792
|
+
let today = gameDate
|
|
791
793
|
let todayUTCHours = session.getTodayUTCHours()
|
|
792
794
|
let curDate = new Date()
|
|
793
795
|
if ( req.query.date ) {
|
|
@@ -896,7 +898,7 @@ app.get('/', async function(req, res) {
|
|
|
896
898
|
|
|
897
899
|
// Reload function, called after options change
|
|
898
900
|
// audio_url is disabled here, now used in multiview instead
|
|
899
|
-
body += 'var defaultDate="' +
|
|
901
|
+
body += 'var defaultDate="' + today + '";var curDate=new Date();var utcHours=curDate.getUTCHours();if ((utcHours >= ' + todayUTCHours + ') && (utcHours < ' + YESTERDAY_UTC_HOURS + ')){defaultDate="' + session.yesterdayDate() + '"}function reload(){var newurl="/?";if (date != defaultDate){var urldate=date;if (date == "' + today + '"){urldate="today"}else if (date == "' + session.yesterdayDate() + '"){urldate="yesterday"}newurl+="date="+urldate+"&"}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 (audio_url != ""){newurl+="audio_url="+encodeURIComponent(audio_url)+"&"}*/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"
|
|
900
902
|
|
|
901
903
|
// Ajax function for multiview and highlights
|
|
902
904
|
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"
|
|
@@ -918,7 +920,7 @@ app.get('/', async function(req, res) {
|
|
|
918
920
|
body += '<p><span class="tooltip">Date<span class="tooltiptext">"today" lasts until ' + todayUTCHours + ' AM EST. Home page will default to yesterday between ' + todayUTCHours + ' AM - ' + (YESTERDAY_UTC_HOURS - 4) + ' AM EST.</span></span>: <input type="date" id="gameDate" value="' + gameDate + '"/> '
|
|
919
921
|
for (var i = 0; i < VALID_DATES.length; i++) {
|
|
920
922
|
body += '<button '
|
|
921
|
-
if ( ((VALID_DATES[i] == VALID_DATES[0]) && (gameDate ==
|
|
923
|
+
if ( ((VALID_DATES[i] == VALID_DATES[0]) && (gameDate == today)) || ((VALID_DATES[i] == VALID_DATES[1]) && (gameDate == session.yesterdayDate())) ) body += 'class="default" '
|
|
922
924
|
body += 'onclick="date=\'' + VALID_DATES[i] + '\';reload()">' + VALID_DATES[i] + '</button> '
|
|
923
925
|
}
|
|
924
926
|
body += '</p>' + "\n" + '<p><span class="tinytext">Updated ' + session.getCacheUpdatedDate(gameDate) + '</span></p>' + "\n"
|
|
@@ -962,7 +964,7 @@ app.get('/', async function(req, res) {
|
|
|
962
964
|
}
|
|
963
965
|
|
|
964
966
|
if ( mediaType == VALID_MEDIA_TYPES[0] ) {
|
|
965
|
-
body += '<span class="tooltip">Inning<span class="tooltiptext">For video streams only: choose the inning to start with (and the score to display, if applicable). Inning number is relative -- for example, selecting inning 7 here will show inning 7 for scheduled 9
|
|
967
|
+
body += '<span class="tooltip">Inning<span class="tooltiptext">For video streams only: choose the inning to start with (and the score to display, if applicable). Inning number is relative -- for example, selecting inning 7 here will show inning 7 for scheduled 9-inning games, but inning 5 for scheduled 7-inning games, for example. If an inning number is specified, seeking to an earlier point will not be possible. Inning 0 (zero) should be the broadcast start time, if available. Default is the beginning of the stream. To use with radio, set the video track to "None".</span></span>: '
|
|
966
968
|
body += '<select id="inning_half" onchange="inning_half=this.value;reload()">'
|
|
967
969
|
for (var i = 0; i < VALID_INNING_HALF.length; i++) {
|
|
968
970
|
body += '<option value="' + VALID_INNING_HALF[i] + '"'
|
|
@@ -1043,9 +1045,14 @@ app.get('/', async function(req, res) {
|
|
|
1043
1045
|
body += '</td></tr>' + "\n"
|
|
1044
1046
|
}
|
|
1045
1047
|
|
|
1048
|
+
let national_blackout = /(^\d{5}$)/.test(session.credentials.zip_code)
|
|
1049
|
+
|
|
1046
1050
|
for (var j = 0; j < cache_data.dates[0].games.length; j++) {
|
|
1047
1051
|
let game_started = false
|
|
1048
1052
|
|
|
1053
|
+
let blackout_type
|
|
1054
|
+
let blackout_time
|
|
1055
|
+
|
|
1049
1056
|
let awayteam = cache_data.dates[0].games[j].teams['away'].team.abbreviation
|
|
1050
1057
|
let hometeam = cache_data.dates[0].games[j].teams['home'].team.abbreviation
|
|
1051
1058
|
if ( cache_data.dates[0].games[j].teams['home'].team.sport.name == 'Winter Leagues' ) {
|
|
@@ -1070,10 +1077,14 @@ app.get('/', async function(req, res) {
|
|
|
1070
1077
|
var scheduledInnings = '9'
|
|
1071
1078
|
if ( cache_data.dates[0].games[j].linescore && cache_data.dates[0].games[j].linescore.scheduledInnings ) {
|
|
1072
1079
|
scheduledInnings = cache_data.dates[0].games[j].linescore.scheduledInnings
|
|
1080
|
+
if ( detailedState.startsWith('Completed Early') && cache_data.dates[0].games[j].linescore.currentInning ) {
|
|
1081
|
+
scheduledInnings = cache_data.dates[0].games[j].linescore.currentInning
|
|
1082
|
+
}
|
|
1073
1083
|
}
|
|
1074
1084
|
var relative_inning = (inning_number - (9 - scheduledInnings))
|
|
1075
1085
|
relative_inning = relative_inning < 0 ? 0 : relative_inning
|
|
1076
|
-
if ( (scores == VALID_SCORES[1]) && (cache_data.dates[0].games[j].gameUtils.isLive || cache_data.dates[0].games[j].gameUtils.isFinal) && !cache_data.dates[0].games[j].gameUtils.isCancelled && !cache_data.dates[0].games[j].gameUtils.isPostponed ) {
|
|
1086
|
+
//if ( (scores == VALID_SCORES[1]) && (cache_data.dates[0].games[j].gameUtils.isLive || cache_data.dates[0].games[j].gameUtils.isFinal) && !cache_data.dates[0].games[j].gameUtils.isCancelled && !cache_data.dates[0].games[j].gameUtils.isPostponed ) {
|
|
1087
|
+
if ( (scores == VALID_SCORES[1]) && (abstractGameState != 'Preview') && (detailedState != 'Postponed') ) {
|
|
1077
1088
|
let awayscore = ''
|
|
1078
1089
|
let homescore = ''
|
|
1079
1090
|
if ( (inning_number != VALID_INNING_NUMBER[0]) && cache_data.dates[0].games[j].linescore && cache_data.dates[0].games[j].linescore.innings ) {
|
|
@@ -1110,9 +1121,11 @@ app.get('/', async function(req, res) {
|
|
|
1110
1121
|
} else {
|
|
1111
1122
|
awayscore = cache_data.dates[0].games[j].teams['away'].score
|
|
1112
1123
|
homescore = cache_data.dates[0].games[j].teams['home'].score
|
|
1113
|
-
if ( cache_data.dates[0].games[j].gameUtils.isLive && !cache_data.dates[0].games[j].gameUtils.isFinal ) {
|
|
1124
|
+
//if ( cache_data.dates[0].games[j].gameUtils.isLive && !cache_data.dates[0].games[j].gameUtils.isFinal ) {
|
|
1125
|
+
if ( abstractGameState == 'Live' ) {
|
|
1114
1126
|
state = "<br/>" + cache_data.dates[0].games[j].linescore.inningHalf.substr(0,1) + cache_data.dates[0].games[j].linescore.currentInning
|
|
1115
|
-
} else if ( cache_data.dates[0].games[j].gameUtils.isFinal ) {
|
|
1127
|
+
//} else if ( cache_data.dates[0].games[j].gameUtils.isFinal ) {
|
|
1128
|
+
} else if ( abstractGameState == 'Final' ) {
|
|
1116
1129
|
state = "<br/>" + detailedState
|
|
1117
1130
|
}
|
|
1118
1131
|
if ( cache_data.dates[0].games[j].flags.perfectGame == true ) {
|
|
@@ -1122,9 +1135,11 @@ app.get('/', async function(req, res) {
|
|
|
1122
1135
|
}
|
|
1123
1136
|
}
|
|
1124
1137
|
teams = awayteam + " " + awayscore + " @ " + hometeam + " " + homescore
|
|
1125
|
-
} else if ( cache_data.dates[0].games[j].gameUtils.isCancelled || cache_data.dates[0].games[j].gameUtils.isPostponed || cache_data.dates[0].games[j].gameUtils.isSuspended ) {
|
|
1138
|
+
//} else if ( cache_data.dates[0].games[j].gameUtils.isCancelled || cache_data.dates[0].games[j].gameUtils.isPostponed || cache_data.dates[0].games[j].gameUtils.isSuspended ) {
|
|
1139
|
+
} else if ( detailedState == 'Postponed' ) {
|
|
1126
1140
|
state = "<br/>" + detailedState
|
|
1127
|
-
} else if ( cache_data.dates[0].games[j].gameUtils.isDelayed ) {
|
|
1141
|
+
//} else if ( cache_data.dates[0].games[j].gameUtils.isDelayed ) {
|
|
1142
|
+
} else if ( detailedState.startsWith('Delayed') ) {
|
|
1128
1143
|
state += "<br/>" + detailedState
|
|
1129
1144
|
}
|
|
1130
1145
|
if ( cache_data.dates[0].games[j].teams['home'].team.sport.name == 'Winter Leagues' ) {
|
|
@@ -1138,19 +1153,20 @@ app.get('/', async function(req, res) {
|
|
|
1138
1153
|
state += "<br/>" + cache_data.dates[0].games[j].description
|
|
1139
1154
|
}
|
|
1140
1155
|
if ( scheduledInnings != '9' ) {
|
|
1141
|
-
state += "<br/>" +
|
|
1156
|
+
state += "<br/>" + scheduledInnings + "-inning game"
|
|
1142
1157
|
}
|
|
1143
1158
|
var resumeStatus = false
|
|
1144
1159
|
if ( cache_data.dates[0].games[j].resumeGameDate || cache_data.dates[0].games[j].resumedFromDate ) {
|
|
1160
|
+
state += '<br/>Resum'
|
|
1145
1161
|
let resumeDate
|
|
1146
1162
|
if ( cache_data.dates[0].games[j].resumeGameDate ) {
|
|
1147
|
-
resumeDate = new Date(cache_data.dates[0].games[j].
|
|
1148
|
-
state +=
|
|
1163
|
+
resumeDate = new Date(cache_data.dates[0].games[j].resumeDate)
|
|
1164
|
+
state += 'ing on'
|
|
1149
1165
|
} else {
|
|
1150
|
-
resumeDate = new Date(cache_data.dates[0].games[j].
|
|
1151
|
-
state +=
|
|
1166
|
+
resumeDate = new Date(cache_data.dates[0].games[j].resumedFrom)
|
|
1167
|
+
state += 'ed from'
|
|
1152
1168
|
}
|
|
1153
|
-
state += resumeDate.toLocaleString('default', { month: 'long'
|
|
1169
|
+
state += '<br/>' + resumeDate.toLocaleString('default', { month: 'long', day: 'numeric' })
|
|
1154
1170
|
// Also show the status by the media links, if one of them is live
|
|
1155
1171
|
resumeStatus = 'archived'
|
|
1156
1172
|
if ( ((typeof cache_data.dates[0].games[j].content.media) != 'undefined') || ((typeof cache_data.dates[0].games[j].content.media.epg) != 'undefined') ) {
|
|
@@ -1224,13 +1240,15 @@ app.get('/', async function(req, res) {
|
|
|
1224
1240
|
if ( epgTitle == mediaType ) {
|
|
1225
1241
|
for (var x = 0; x < cache_data.dates[0].games[j].content.media.epg[k].items.length; x++) {
|
|
1226
1242
|
// check that pay TV authentication isn't required
|
|
1227
|
-
if ( (mediaType == 'MLBTV') && ((cache_data.dates[0].games[j].content.media.epg[k].items[x].mediaState != 'MEDIA_ARCHIVE') || !cache_data.dates[0].games[j].gameUtils.isFinal) && (cache_data.dates[0].games[j].content.media.epg[k].items[x].foxAuthRequired || cache_data.dates[0].games[j].content.media.epg[k].items[x].tbsAuthRequired || cache_data.dates[0].games[j].content.media.epg[k].items[x].espnAuthRequired || cache_data.dates[0].games[j].content.media.epg[k].items[x].fs1AuthRequired || cache_data.dates[0].games[j].content.media.epg[k].items[x].mlbnAuthRequired) ) {
|
|
1243
|
+
//if ( (mediaType == 'MLBTV') && ((cache_data.dates[0].games[j].content.media.epg[k].items[x].mediaState != 'MEDIA_ARCHIVE') || !cache_data.dates[0].games[j].gameUtils.isFinal) && (cache_data.dates[0].games[j].content.media.epg[k].items[x].foxAuthRequired || cache_data.dates[0].games[j].content.media.epg[k].items[x].tbsAuthRequired || cache_data.dates[0].games[j].content.media.epg[k].items[x].espnAuthRequired || cache_data.dates[0].games[j].content.media.epg[k].items[x].fs1AuthRequired || cache_data.dates[0].games[j].content.media.epg[k].items[x].mlbnAuthRequired) ) {
|
|
1244
|
+
if ( cache_data.dates[0].games[j].content.media.epg[k].items[x].foxAuthRequired || cache_data.dates[0].games[j].content.media.epg[k].items[x].tbsAuthRequired || cache_data.dates[0].games[j].content.media.epg[k].items[x].espnAuthRequired || cache_data.dates[0].games[j].content.media.epg[k].items[x].fs1AuthRequired || cache_data.dates[0].games[j].content.media.epg[k].items[x].mlbnAuthRequired ) {
|
|
1228
1245
|
continue
|
|
1229
1246
|
}
|
|
1230
1247
|
if ( ((typeof cache_data.dates[0].games[j].content.media.epg[k].items[x].mediaFeedType) == 'undefined') || (cache_data.dates[0].games[j].content.media.epg[k].items[x].mediaFeedType.indexOf('IN_MARKET_') == -1) ) {
|
|
1231
1248
|
if ( ((typeof cache_data.dates[0].games[j].content.media.epg[k].items[x].language) == 'undefined') || (cache_data.dates[0].games[j].content.media.epg[k].items[x].language == language) ) {
|
|
1232
1249
|
let teamabbr
|
|
1233
|
-
if ( (((typeof cache_data.dates[0].games[j].content.media.epg[k].items[x].mediaFeedType) != 'undefined') && (cache_data.dates[0].games[j].content.media.epg[k].items[x].mediaFeedType == 'NATIONAL')) || ((mediaType == 'MLBTV') && cache_data.dates[0].games[j].gameUtils.isPostSeason) ) {
|
|
1250
|
+
//if ( (((typeof cache_data.dates[0].games[j].content.media.epg[k].items[x].mediaFeedType) != 'undefined') && (cache_data.dates[0].games[j].content.media.epg[k].items[x].mediaFeedType == 'NATIONAL')) || ((mediaType == 'MLBTV') && cache_data.dates[0].games[j].gameUtils.isPostSeason) ) {
|
|
1251
|
+
if ( (((typeof cache_data.dates[0].games[j].content.media.epg[k].items[x].mediaFeedType) != 'undefined') && (cache_data.dates[0].games[j].content.media.epg[k].items[x].mediaFeedType == 'NATIONAL')) || ((mediaType == 'MLBTV') && (cache_data.dates[0].games[j].seriesDescription != 'Regular Season') && (cache_data.dates[0].games[j].seriesDescription != 'Spring Training')) ) {
|
|
1234
1252
|
teamabbr = 'NATIONAL'
|
|
1235
1253
|
} else {
|
|
1236
1254
|
teamabbr = hometeam
|
|
@@ -1242,15 +1260,61 @@ app.get('/', async function(req, res) {
|
|
|
1242
1260
|
if ( cache_data.dates[0].games[j].content.media.freeGame ) {
|
|
1243
1261
|
station += '*'
|
|
1244
1262
|
}
|
|
1245
|
-
|
|
1263
|
+
// estimate blackout expiration, if necessary
|
|
1264
|
+
if ( !blackout_type && (mediaType == 'MLBTV') && (gameDate >= today) && ((national_blackout && (teamabbr == 'NATIONAL')) || ((cache_data.dates[0].games[j].seriesDescription != 'Spring Training') && (session.credentials.blackout_teams.includes(awayteam) || session.credentials.blackout_teams.includes(hometeam)))) ) {
|
|
1265
|
+
if ( national_blackout && (teamabbr == 'NATIONAL') ) {
|
|
1266
|
+
blackout_type = 'National'
|
|
1267
|
+
} else {
|
|
1268
|
+
blackout_type = 'Local'
|
|
1269
|
+
}
|
|
1270
|
+
if ( (resumeStatus == false) && (cache_data.dates[0].games[j].status.startTimeTBD == false) ) {
|
|
1271
|
+
// avg 9 inning game was 3:11 in 2021, or 21.22 minutes per inning
|
|
1272
|
+
let gameDurationMinutes = 21.22 * scheduledInnings
|
|
1273
|
+
// default to assuming the scheduled game time is the first pitch time
|
|
1274
|
+
let firstPitch = new Date(cache_data.dates[0].games[j].gameDate)
|
|
1275
|
+
if ( cache_data.dates[0].games[j].gameInfo ) {
|
|
1276
|
+
// check if firstPitch has been updated with a valid time (later than the scheduled game time)
|
|
1277
|
+
if ( cache_data.dates[0].games[j].gameInfo.firstPitch && (cache_data.dates[0].games[j].gameInfo.firstPitch >= cache_data.dates[0].games[j].gameDate) ) {
|
|
1278
|
+
firstPitch = new Date(cache_data.dates[0].games[j].gameInfo.firstPitch)
|
|
1279
|
+
// for completed games, get the duration too
|
|
1280
|
+
if ( cache_data.dates[0].games[j].gameInfo.gameDurationMinutes ) {
|
|
1281
|
+
gameDurationMinutes = cache_data.dates[0].games[j].gameInfo.gameDurationMinutes
|
|
1282
|
+
// add any delays
|
|
1283
|
+
if ( cache_data.dates[0].games[j].gameInfo.delayDurationMinutes ) {
|
|
1284
|
+
gameDurationMinutes += cache_data.dates[0].games[j].gameInfo.delayDurationMinutes
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
gameDurationMinutes += 90
|
|
1290
|
+
blackout_time = firstPitch
|
|
1291
|
+
blackout_time.setMinutes(blackout_time.getMinutes()+gameDurationMinutes)
|
|
1292
|
+
}
|
|
1293
|
+
} else if ( !blackout_type ) {
|
|
1294
|
+
blackout_type = 'None'
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
// display blackout tooltip, if necessary
|
|
1298
|
+
if ( blackout_type != 'None' ) {
|
|
1299
|
+
body += '<span class="tooltip">' + teamabbr + '<span class="tooltiptext">' + blackout_type + ' video blackout until approx. 90 min. after the game'
|
|
1300
|
+
if ( blackout_time ) {
|
|
1301
|
+
body += ' (~' + blackout_time.toLocaleString('en-US', { hour: 'numeric', minute: 'numeric', hour12: true }) + ')'
|
|
1302
|
+
}
|
|
1303
|
+
body += '</span></span>'
|
|
1304
|
+
} else {
|
|
1305
|
+
body += teamabbr
|
|
1306
|
+
}
|
|
1307
|
+
body += ': '
|
|
1308
|
+
//if ( (cache_data.dates[0].games[j].content.media.epg[k].items[x].mediaState == 'MEDIA_ON') || (cache_data.dates[0].games[j].content.media.epg[k].items[x].mediaState == 'MEDIA_ARCHIVE') || cache_data.dates[0].games[j].gameUtils.isFinal ) {
|
|
1309
|
+
if ( (cache_data.dates[0].games[j].content.media.epg[k].items[x].mediaState == 'MEDIA_ON') || (cache_data.dates[0].games[j].content.media.epg[k].items[x].mediaState == 'MEDIA_ARCHIVE') || (abstractGameState == 'Final') ) {
|
|
1246
1310
|
let gameTime = new Date(cache_data.dates[0].games[j].gameDate)
|
|
1247
1311
|
gameTime.setMinutes(gameTime.getMinutes()-10)
|
|
1248
1312
|
if ( curDate >= gameTime ) {
|
|
1249
1313
|
game_started = true
|
|
1250
1314
|
}
|
|
1251
1315
|
let mediaId = cache_data.dates[0].games[j].content.media.epg[k].items[x].mediaId
|
|
1252
|
-
if ( (mediaType == 'MLBTV') && session.cache.media && session.cache.media[mediaId] && session.cache.media[mediaId].blackout && session.cache.media[mediaId].blackoutExpiry && (new Date(session.cache.media[mediaId].blackoutExpiry) > new Date()) ) {
|
|
1253
|
-
body +=
|
|
1316
|
+
if ( (mediaType == 'MLBTV') && (gameDate == today) && session.cache.media && session.cache.media[mediaId] && session.cache.media[mediaId].blackout && session.cache.media[mediaId].blackoutExpiry && (new Date(session.cache.media[mediaId].blackoutExpiry) > new Date()) ) {
|
|
1317
|
+
body += '<s>' + station + '</s>'
|
|
1254
1318
|
} else {
|
|
1255
1319
|
let querystring
|
|
1256
1320
|
querystring = '?mediaId=' + mediaId
|
|
@@ -1280,7 +1344,12 @@ app.get('/', async function(req, res) {
|
|
|
1280
1344
|
}
|
|
1281
1345
|
querystring += content_protect_b
|
|
1282
1346
|
multiviewquerystring += content_protect_b
|
|
1283
|
-
|
|
1347
|
+
stationlink = '<a href="' + thislink + querystring + '">' + station + '</a>'
|
|
1348
|
+
if ( (mediaType == 'MLBTV') && (gameDate >= today) && ((national_blackout && (teamabbr == 'NATIONAL')) || ((cache_data.dates[0].games[j].seriesDescription != 'Spring Training') && (session.credentials.blackout_teams.includes(awayteam) || session.credentials.blackout_teams.includes(hometeam)))) ) {
|
|
1349
|
+
body += '<s>' + stationlink + '</s>'
|
|
1350
|
+
} else {
|
|
1351
|
+
body += stationlink
|
|
1352
|
+
}
|
|
1284
1353
|
if ( mediaType == 'MLBTV' ) {
|
|
1285
1354
|
body += '<input type="checkbox" value="' + server + '/stream.m3u8' + multiviewquerystring + '" onclick="addmultiview(this)">'
|
|
1286
1355
|
}
|
|
@@ -1312,13 +1381,18 @@ app.get('/', async function(req, res) {
|
|
|
1312
1381
|
body += ')'
|
|
1313
1382
|
}
|
|
1314
1383
|
body += ', '
|
|
1315
|
-
// add YouTube link where available
|
|
1316
|
-
if ( (mediaType == 'MLBTV') && cache_data.dates[0].games[j].content.media.epg[k].items[x].youtube && cache_data.dates[0].games[j].content.media.epg[k].items[x].youtube.videoId ) {
|
|
1317
|
-
body += '<a href="https://www.youtube.com/watch?v=' + cache_data.dates[0].games[j].content.media.epg[k].items[x].youtube.videoId + '" target="_blank">' + station + '</a>, '
|
|
1318
|
-
}
|
|
1319
1384
|
}
|
|
1320
1385
|
} else {
|
|
1321
|
-
|
|
1386
|
+
if ( (mediaType == 'MLBTV') && (gameDate >= today) && ((national_blackout && (teamabbr == 'NATIONAL')) || ((cache_data.dates[0].games[j].seriesDescription != 'Spring Training') && (session.credentials.blackout_teams.includes(awayteam) || session.credentials.blackout_teams.includes(hometeam)))) ) {
|
|
1387
|
+
body += '<s>' + station + '</s>'
|
|
1388
|
+
} else {
|
|
1389
|
+
body += station
|
|
1390
|
+
}
|
|
1391
|
+
body += ', '
|
|
1392
|
+
}
|
|
1393
|
+
// add YouTube link where available
|
|
1394
|
+
if ( (mediaType == 'MLBTV') && cache_data.dates[0].games[j].content.media.epg[k].items[x].youtube && cache_data.dates[0].games[j].content.media.epg[k].items[x].youtube.videoId ) {
|
|
1395
|
+
body += '<a href="https://www.youtube.com/watch?v=' + cache_data.dates[0].games[j].content.media.epg[k].items[x].youtube.videoId + '" target="_blank">' + station + '</a>'
|
|
1322
1396
|
}
|
|
1323
1397
|
}
|
|
1324
1398
|
}
|
|
@@ -1329,12 +1403,10 @@ app.get('/', async function(req, res) {
|
|
|
1329
1403
|
if ( body.substr(-2) == ', ' ) {
|
|
1330
1404
|
body = body.slice(0, -2)
|
|
1331
1405
|
}
|
|
1332
|
-
if ( (mediaType == 'MLBTV') && (game_started) && cache_data.dates[0].games[j].content && cache_data.dates[0].games[j].content.summary && cache_data.dates[0].games[j].content.summary.hasHighlightsVideo ) {
|
|
1406
|
+
//if ( (mediaType == 'MLBTV') && (game_started) && cache_data.dates[0].games[j].content && cache_data.dates[0].games[j].content.summary && cache_data.dates[0].games[j].content.summary.hasHighlightsVideo ) {
|
|
1407
|
+
if ( (mediaType == 'MLBTV') && (game_started) ) {
|
|
1333
1408
|
body += '<br/><a href="javascript:showhighlights(\'' + cache_data.dates[0].games[j].gamePk + '\',\'' + gameDate + '\')">Highlights</a>'
|
|
1334
1409
|
}
|
|
1335
|
-
if ( body.substr(-2) == ', ' ) {
|
|
1336
|
-
body = body.slice(0, -2)
|
|
1337
|
-
}
|
|
1338
1410
|
}
|
|
1339
1411
|
body += "</td>"
|
|
1340
1412
|
body += "</tr>" + "\n"
|
|
@@ -1407,7 +1479,7 @@ app.get('/', async function(req, res) {
|
|
|
1407
1479
|
body += '</td></tr></table><br/>' + "\n"
|
|
1408
1480
|
}
|
|
1409
1481
|
|
|
1410
|
-
if ( (linkType == VALID_LINK_TYPES[1]) && (gameDate ==
|
|
1482
|
+
if ( (linkType == VALID_LINK_TYPES[1]) && (gameDate == today) ) {
|
|
1411
1483
|
body += '<p><span class="tooltip">Force VOD<span class="tooltiptext">For streams only: if your client does not support seeking in mlbserver live streams, turning this on will make the stream look like a VOD stream instead, allowing the client to start at the beginning and allowing the user to seek within it. You will need to reload the stream to watch/view past the current time, though.</span></span>: '
|
|
1412
1484
|
for (var i = 0; i < VALID_FORCE_VOD.length; i++) {
|
|
1413
1485
|
body += '<button '
|
|
@@ -1433,7 +1505,12 @@ app.get('/', async function(req, res) {
|
|
|
1433
1505
|
|
|
1434
1506
|
body += '<p><span class="tooltip">By team<span class="tooltiptext">Including a team will include that team\'s broadcasts, not their opponent\'s broadcasts or national TV broadcasts.</span></span>: <a href="/channels.m3u?mediaType=' + mediaType + '&resolution=' + resolution + '&includeTeams=ari,atl' + content_protect_b + '">channels.m3u</a> and <a href="/guide.xml?mediaType=' + mediaType + '&includeTeams=ari,atl' + content_protect_b + '">guide.xml</a></p>' + "\n"
|
|
1435
1507
|
|
|
1436
|
-
|
|
1508
|
+
let exclude_teams = 'ari,national'
|
|
1509
|
+
if ( session.credentials.blackout_teams.length > 0 ) {
|
|
1510
|
+
exclude_teams = session.credentials.blackout_teams.toString().toLowerCase()
|
|
1511
|
+
exclude_teams += ',national'
|
|
1512
|
+
}
|
|
1513
|
+
body += '<p><span class="tooltip">Exclude a team + national<span class="tooltiptext">This is useful for excluding games you may be blacked out from. Excluding a team will exclude every game involving that team. National refers to <a href="https://www.mlb.com/live-stream-games/national-blackout">USA national TV broadcasts</a>.</span></span>: <a href="/channels.m3u?mediaType=' + mediaType + '&resolution=' + resolution + '&excludeTeams=' + exclude_teams + content_protect_b + '">channels.m3u</a> and <a href="/guide.xml?mediaType=' + mediaType + '&excludeTeams=' + exclude_teams + content_protect_b + '">guide.xml</a></p>' + "\n"
|
|
1437
1514
|
|
|
1438
1515
|
body += '<p><span class="tooltip">Include (or exclude) LIDOM<span class="tooltiptext">Dominican Winter League, aka Liga de Beisbol Dominicano. Live stream only, does not support starting from the beginning or certain innings, skip options, etc.</span></span>: <a href="/channels.m3u?mediaType=' + mediaType + '&resolution=' + resolution + '&includeTeams=lidom' + content_protect_b + '">channels.m3u</a> and <a href="/guide.xml?mediaType=' + mediaType + '&includeTeams=lidom' + content_protect_b + '">guide.xml</a></p>' + "\n"
|
|
1439
1516
|
|
package/package.json
CHANGED
package/session.js
CHANGED
|
@@ -37,9 +37,10 @@ const TEAM_IDS = {'ARI':'109','ATL':'144','BAL':'110','BOS':'111','CHC':'112','C
|
|
|
37
37
|
const BREAK_TYPES = ['Game Advisory', 'Pitching Substitution', 'Offensive Substitution', 'Defensive Sub', 'Defensive Switch', 'Runner Placed On Base']
|
|
38
38
|
// These are the events to keep, in addition to the last event of each at-bat, if we're skipping pitches
|
|
39
39
|
const ACTION_TYPES = ['Wild Pitch', 'Passed Ball', 'Stolen Base', 'Caught Stealing', 'Pickoff', 'Error', 'Out', 'Balk', 'Defensive Indiff']
|
|
40
|
-
const EVENT_START_PADDING =
|
|
41
|
-
const
|
|
42
|
-
const
|
|
40
|
+
const EVENT_START_PADDING = 0
|
|
41
|
+
const PITCH_END_PADDING = 7
|
|
42
|
+
const ACTION_END_PADDING = 8
|
|
43
|
+
const MINIMUM_BREAK_DURATION = 5
|
|
43
44
|
|
|
44
45
|
class sessionClass {
|
|
45
46
|
// Initialize the class
|
|
@@ -132,6 +133,20 @@ class sessionClass {
|
|
|
132
133
|
if ( !this.data.linkType ) {
|
|
133
134
|
this.setLinkType('embed')
|
|
134
135
|
}
|
|
136
|
+
|
|
137
|
+
// Check if zip code was provided and if it is different from the stored one
|
|
138
|
+
if ( argv.zip_code && (argv.zip_code != this.credentials.zip_code) ) {
|
|
139
|
+
this.debuglog('updating zip code and blackout teams')
|
|
140
|
+
this.credentials.zip_code = argv.zip_code.toString()
|
|
141
|
+
this.updateBlackoutTeams()
|
|
142
|
+
} else {
|
|
143
|
+
// Prompt for zip code if it doesn't exist
|
|
144
|
+
if ( !this.credentials.zip_code ) {
|
|
145
|
+
this.debuglog('prompting for zip code')
|
|
146
|
+
this.credentials.zip_code = readlineSync.question('Enter 5-digit zip code (optional, for USA blackout labels): ').toString()
|
|
147
|
+
this.updateBlackoutTeams()
|
|
148
|
+
}
|
|
149
|
+
}
|
|
135
150
|
}
|
|
136
151
|
|
|
137
152
|
// Store the ports, used for generating URLs
|
|
@@ -1010,7 +1025,8 @@ class sessionClass {
|
|
|
1010
1025
|
continue
|
|
1011
1026
|
}
|
|
1012
1027
|
if ( ((typeof cache_data.dates[0].games[j].content.media.epg[k].items[x].mediaFeedType) == 'undefined') || (cache_data.dates[0].games[j].content.media.epg[k].items[x].mediaFeedType.indexOf('IN_MARKET_') == -1) ) {
|
|
1013
|
-
if ( (team.toUpperCase().indexOf('NATIONAL.') == 0) && ((cache_data.dates[0].games[j].content.media.epg[k].items[x][mediaFeedType] == 'NATIONAL') || ((mediaType == 'MLBTV') && cache_data.dates[0].games[j].gameUtils.isPostSeason)) ) {
|
|
1028
|
+
//if ( (team.toUpperCase().indexOf('NATIONAL.') == 0) && ((cache_data.dates[0].games[j].content.media.epg[k].items[x][mediaFeedType] == 'NATIONAL') || ((mediaType == 'MLBTV') && cache_data.dates[0].games[j].gameUtils.isPostSeason)) ) {
|
|
1029
|
+
if ( (team.toUpperCase().indexOf('NATIONAL.') == 0) && ((cache_data.dates[0].games[j].content.media.epg[k].items[x][mediaFeedType] == 'NATIONAL') || ((mediaType == 'MLBTV') && (cache_data.dates[0].games[i].seriesDescription != 'Regular Season') && (cache_data.dates[0].games[i].seriesDescription != 'Spring Training'))) ) {
|
|
1014
1030
|
nationalCount += 1
|
|
1015
1031
|
let nationalArray = team.split('.')
|
|
1016
1032
|
if ( (nationalArray.length == 2) && (nationalArray[1] == nationalCount) ) {
|
|
@@ -1141,11 +1157,12 @@ class sessionClass {
|
|
|
1141
1157
|
try {
|
|
1142
1158
|
let cache_data
|
|
1143
1159
|
let cache_name = dateString
|
|
1144
|
-
let 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='
|
|
1160
|
+
//let 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='
|
|
1161
|
+
let url = 'http://statsapi.mlb.com/api/v1/schedule?sportId=1,51&startDate=' + dateString + '&endDate=' + dateString + '&hydrate=game(content(media(epg))),probablePitcher,linescore,team,flags,gameInfo'
|
|
1145
1162
|
if ( team ) {
|
|
1146
1163
|
this.debuglog('getDayData for team ' + team + ' on date ' + dateString)
|
|
1147
1164
|
cache_name = team.toUpperCase() + dateString
|
|
1148
|
-
url = 'http://statsapi.mlb.com/api/v1/schedule?sportId=1&teamId=' + TEAM_IDS[team.toUpperCase()] + '&startDate=' + dateString + '&endDate=' + dateString + '&
|
|
1165
|
+
url = 'http://statsapi.mlb.com/api/v1/schedule?sportId=1&teamId=' + TEAM_IDS[team.toUpperCase()] + '&startDate=' + dateString + '&endDate=' + dateString + '&hydrate=team,game(content(media(epg)))'
|
|
1149
1166
|
} else {
|
|
1150
1167
|
this.debuglog('getDayData for date ' + dateString)
|
|
1151
1168
|
}
|
|
@@ -1292,6 +1309,7 @@ class sessionClass {
|
|
|
1292
1309
|
var channels = {}
|
|
1293
1310
|
var nationalChannels = {}
|
|
1294
1311
|
let prevDateIndex = {MLBTV:-1,Audio:-1}
|
|
1312
|
+
let national_blackout = /(^\d{5}$)/.test(this.credentials.zip_code)
|
|
1295
1313
|
for (var i = 0; i < cache_data.dates.length; i++) {
|
|
1296
1314
|
let dateIndex = {MLBTV:i,Audio:i}
|
|
1297
1315
|
let nationalCounter = {MLBTV:0,Audio:0}
|
|
@@ -1333,15 +1351,19 @@ class sessionClass {
|
|
|
1333
1351
|
}
|
|
1334
1352
|
if ( ((((typeof cache_data.dates[i].games[j].content.media.epg[k].items[x].mediaFeedType) == 'undefined') || (cache_data.dates[i].games[j].content.media.epg[k].items[x].mediaFeedType.indexOf('IN_MARKET_') == -1)) && (((typeof cache_data.dates[i].games[j].content.media.epg[k].items[x].language) == 'undefined') || (cache_data.dates[i].games[j].content.media.epg[k].items[x].language != 'es'))) ) {
|
|
1335
1353
|
let teamType = cache_data.dates[i].games[j].content.media.epg[k].items[x][mediaFeedType]
|
|
1336
|
-
if ( (mediaType == 'MLBTV') && cache_data.dates[i].games[j].gameUtils.isPostSeason ) {
|
|
1354
|
+
//if ( (mediaType == 'MLBTV') && cache_data.dates[i].games[j].gameUtils.isPostSeason ) {
|
|
1355
|
+
if ( (mediaType == 'MLBTV') && (cache_data.dates[i].games[j].seriesDescription != 'Regular Season') && (cache_data.dates[i].games[j].seriesDescription != 'Spring Training') ) {
|
|
1337
1356
|
teamType = 'NATIONAL'
|
|
1338
1357
|
}
|
|
1339
|
-
let team
|
|
1340
|
-
let opponent_team
|
|
1341
|
-
if ( teamType == 'NATIONAL' ) {
|
|
1342
|
-
team = cache_data.dates[i].games[j].teams['home'].team.abbreviation
|
|
1343
|
-
opponent_team = cache_data.dates[i].games[j].teams['away'].team.abbreviation
|
|
1358
|
+
let team = cache_data.dates[i].games[j].teams['home'].team.abbreviation
|
|
1359
|
+
let opponent_team = cache_data.dates[i].games[j].teams['away'].team.abbreviation
|
|
1344
1360
|
|
|
1361
|
+
// check blackout status
|
|
1362
|
+
if ( (mediaType == 'MLBTV') && ((national_blackout && (teamType == 'NATIONAL')) || ((cache_data.dates[i].games[j].seriesDescription != 'Spring Training') && (this.credentials.blackout_teams.includes(team) || this.credentials.blackout_teams.includes(opponent_team)))) ) {
|
|
1363
|
+
continue
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
if ( teamType == 'NATIONAL' ) {
|
|
1345
1367
|
if ( dateIndex[mediaTitle] > prevDateIndex[mediaTitle] ) {
|
|
1346
1368
|
prevDateIndex[mediaTitle] = dateIndex[mediaTitle]
|
|
1347
1369
|
nationalCounter[mediaTitle] = 1
|
|
@@ -1480,6 +1502,7 @@ class sessionClass {
|
|
|
1480
1502
|
var channels = {}
|
|
1481
1503
|
var programs = ""
|
|
1482
1504
|
let prevDateIndex = {MLBTV:-1,Audio:-1}
|
|
1505
|
+
let national_blackout = /(^\d{5}$)/.test(this.credentials.zip_code)
|
|
1483
1506
|
for (var i = 0; i < cache_data.dates.length; i++) {
|
|
1484
1507
|
let dateIndex = {MLBTV:i,Audio:i}
|
|
1485
1508
|
let nationalCounter = {MLBTV:0,Audio:0}
|
|
@@ -1552,15 +1575,19 @@ class sessionClass {
|
|
|
1552
1575
|
}
|
|
1553
1576
|
if ( ((((typeof cache_data.dates[i].games[j].content.media.epg[k].items[x].mediaFeedType) == 'undefined') || (cache_data.dates[i].games[j].content.media.epg[k].items[x].mediaFeedType.indexOf('IN_MARKET_') == -1)) && (((typeof cache_data.dates[i].games[j].content.media.epg[k].items[x].language) == 'undefined') || (cache_data.dates[i].games[j].content.media.epg[k].items[x].language != 'es'))) ) {
|
|
1554
1577
|
let teamType = cache_data.dates[i].games[j].content.media.epg[k].items[x][mediaFeedType]
|
|
1555
|
-
if ( (mediaType == 'MLBTV') && cache_data.dates[i].games[j].gameUtils.isPostSeason ) {
|
|
1578
|
+
//if ( (mediaType == 'MLBTV') && cache_data.dates[i].games[j].gameUtils.isPostSeason ) {
|
|
1579
|
+
if ( (mediaType == 'MLBTV') && (cache_data.dates[i].games[j].seriesDescription != 'Regular Season') && (cache_data.dates[i].games[j].seriesDescription != 'Spring Training') ) {
|
|
1556
1580
|
teamType = 'NATIONAL'
|
|
1557
1581
|
}
|
|
1558
|
-
let team
|
|
1559
|
-
let opponent_team
|
|
1560
|
-
if ( teamType == 'NATIONAL' ) {
|
|
1561
|
-
team = cache_data.dates[i].games[j].teams['home'].team.abbreviation
|
|
1562
|
-
opponent_team = cache_data.dates[i].games[j].teams['away'].team.abbreviation
|
|
1582
|
+
let team = cache_data.dates[i].games[j].teams['home'].team.abbreviation
|
|
1583
|
+
let opponent_team = cache_data.dates[i].games[j].teams['away'].team.abbreviation
|
|
1563
1584
|
|
|
1585
|
+
// check blackout status
|
|
1586
|
+
if ( (mediaType == 'MLBTV') && ((national_blackout && (teamType == 'NATIONAL')) || ((cache_data.dates[i].games[j].seriesDescription != 'Spring Training') && (this.credentials.blackout_teams.includes(team) || this.credentials.blackout_teams.includes(opponent_team)))) ) {
|
|
1587
|
+
continue
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
if ( teamType == 'NATIONAL' ) {
|
|
1564
1591
|
if ( dateIndex[mediaTitle] > prevDateIndex[mediaTitle] ) {
|
|
1565
1592
|
prevDateIndex[mediaTitle] = dateIndex[mediaTitle]
|
|
1566
1593
|
nationalCounter[mediaTitle] = 1
|
|
@@ -2030,22 +2057,26 @@ class sessionClass {
|
|
|
2030
2057
|
if ((current_inning > start_inning) || ((current_inning == start_inning) && ((current_inning_half == start_inning_half) || (current_inning_half == 'bottom')))) {
|
|
2031
2058
|
// loop through events within each play
|
|
2032
2059
|
for (var j=0; j < cache_data.liveData.plays.allPlays[i].playEvents.length; j++) {
|
|
2060
|
+
let event_end_padding = ACTION_END_PADDING
|
|
2033
2061
|
// always exclude break types
|
|
2034
2062
|
if (cache_data.liveData.plays.allPlays[i].playEvents[j].details && cache_data.liveData.plays.allPlays[i].playEvents[j].details.event && BREAK_TYPES.includes(cache_data.liveData.plays.allPlays[i].playEvents[j].details.event)) {
|
|
2035
2063
|
// if we're in the process of skipping inning breaks, treat the first break type we find as another inning break
|
|
2036
2064
|
if ((skip_type == 1) && (previous_inning > 0)) {
|
|
2037
|
-
break_start = ((new Date(cache_data.liveData.plays.allPlays[i].playEvents[j].startTime) - broadcast_start_timestamp) / 1000) +
|
|
2065
|
+
break_start = ((new Date(cache_data.liveData.plays.allPlays[i].playEvents[j].startTime) - broadcast_start_timestamp) / 1000) + event_end_padding
|
|
2038
2066
|
previous_inning = 0
|
|
2039
2067
|
}
|
|
2040
2068
|
continue
|
|
2041
2069
|
} else {
|
|
2070
|
+
if ( (j < (cache_data.liveData.plays.allPlays[i].playEvents.length - 1)) && (!cache_data.liveData.plays.allPlays[i].playEvents[j].details || !cache_data.liveData.plays.allPlays[i].playEvents[j].details.event || !ACTION_TYPES.some(v => cache_data.liveData.plays.allPlays[i].playEvents[j].details.event.includes(v))) ) {
|
|
2071
|
+
event_end_padding = PITCH_END_PADDING
|
|
2072
|
+
}
|
|
2042
2073
|
let action_index
|
|
2043
2074
|
// skip type 1 (breaks) && 2 (idle time) will look at all plays with an endTime
|
|
2044
2075
|
if ((skip_type <= 2) && cache_data.liveData.plays.allPlays[i].playEvents[j].endTime) {
|
|
2045
2076
|
action_index = j
|
|
2046
2077
|
} else if (skip_type == 3) {
|
|
2047
2078
|
// skip type 3 excludes non-action pitches (events that aren't last in the at-bat and don't fall under action types)
|
|
2048
|
-
if (
|
|
2079
|
+
if ( event_end_padding == PITCH_END_PADDING ) {
|
|
2049
2080
|
continue
|
|
2050
2081
|
} else {
|
|
2051
2082
|
// if the action is associated with another play or the event doesn't have an end time, use the previous event instead
|
|
@@ -2074,10 +2105,21 @@ class sessionClass {
|
|
|
2074
2105
|
break
|
|
2075
2106
|
}
|
|
2076
2107
|
}
|
|
2077
|
-
break_start = ((new Date(cache_data.liveData.plays.allPlays[i].playEvents[action_index].endTime) - broadcast_start_timestamp) / 1000) +
|
|
2108
|
+
break_start = ((new Date(cache_data.liveData.plays.allPlays[i].playEvents[action_index].endTime) - broadcast_start_timestamp) / 1000) + event_end_padding
|
|
2078
2109
|
// add extra padding for overturned review plays
|
|
2079
|
-
if (
|
|
2080
|
-
|
|
2110
|
+
if ( cache_data.liveData.plays.allPlays[i].reviewDetails ) {
|
|
2111
|
+
let isOverturned = cache_data.liveData.plays.allPlays[i].reviewDetails.isOverturned
|
|
2112
|
+
if ( (isOverturned == false) && cache_data.liveData.plays.allPlays[i].reviewDetails.additionalReviews && (cache_data.liveData.plays.allPlays[i].reviewDetails.additionalReviews.length > 0) ) {
|
|
2113
|
+
for (var k=0; k < cache_data.liveData.plays.allPlays[i].reviewDetails.additionalReviews.length; k++) {
|
|
2114
|
+
isOverturned = cache_data.liveData.plays.allPlays[i].reviewDetails.additionalReviews[k].isOverturned
|
|
2115
|
+
if ( isOverturned == true ) {
|
|
2116
|
+
break
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
if (isOverturned) {
|
|
2121
|
+
break_start += 40
|
|
2122
|
+
}
|
|
2081
2123
|
}
|
|
2082
2124
|
}
|
|
2083
2125
|
}
|
|
@@ -2351,6 +2393,42 @@ class sessionClass {
|
|
|
2351
2393
|
}
|
|
2352
2394
|
}
|
|
2353
2395
|
|
|
2396
|
+
// Update blackout teams
|
|
2397
|
+
async updateBlackoutTeams() {
|
|
2398
|
+
this.debuglog('getBlackoutTeams for zip code ' + this.credentials.zip_code)
|
|
2399
|
+
|
|
2400
|
+
let blackout_teams = []
|
|
2401
|
+
|
|
2402
|
+
try {
|
|
2403
|
+
if ( /(^\d{5}$)/.test(this.credentials.zip_code) ) {
|
|
2404
|
+
let reqObj = {
|
|
2405
|
+
url: 'https://content.mlb.com/data/blackouts/' + this.credentials.zip_code + '.json',
|
|
2406
|
+
headers: {
|
|
2407
|
+
'User-Agent': USER_AGENT,
|
|
2408
|
+
'Origin': 'https://www.mlb.com',
|
|
2409
|
+
'Referer': 'https://www.mlb.com/'
|
|
2410
|
+
}
|
|
2411
|
+
}
|
|
2412
|
+
var response = await this.httpGet(reqObj)
|
|
2413
|
+
if ( this.isValidJson(response) ) {
|
|
2414
|
+
this.debuglog('getBlackoutTeams response : ' + response)
|
|
2415
|
+
let obj = JSON.parse(response)
|
|
2416
|
+
if ( obj.teams ) {
|
|
2417
|
+
blackout_teams = obj.teams
|
|
2418
|
+
}
|
|
2419
|
+
} else {
|
|
2420
|
+
this.log('error : invalid json from url ' + reqObj.url)
|
|
2421
|
+
}
|
|
2422
|
+
}
|
|
2423
|
+
} catch(e) {
|
|
2424
|
+
this.log('getBlackoutTeams error : ' + e.message)
|
|
2425
|
+
}
|
|
2426
|
+
|
|
2427
|
+
this.log('setting blackout teams to ' + JSON.stringify(blackout_teams))
|
|
2428
|
+
this.credentials.blackout_teams = blackout_teams
|
|
2429
|
+
this.save_credentials()
|
|
2430
|
+
}
|
|
2431
|
+
|
|
2354
2432
|
}
|
|
2355
2433
|
|
|
2356
2434
|
module.exports = sessionClass
|