mlbserver 2025.7.18 → 2025.7.21
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 +159 -5
- package/package.json +1 -1
- package/session.js +33 -25
package/index.js
CHANGED
|
@@ -194,8 +194,19 @@ if (argv.http_root) {
|
|
|
194
194
|
req.url = req.url.substr(http_root.length, (req.url.length - http_root.length))
|
|
195
195
|
app.route(req, res);
|
|
196
196
|
} catch (e) {
|
|
197
|
-
session.log('http_root request error : ' + e.message)
|
|
198
|
-
res.end('http_root request error, check log')
|
|
197
|
+
session.log('http_root get request error : ' + e.message)
|
|
198
|
+
res.end('http_root get request error, check log')
|
|
199
|
+
}
|
|
200
|
+
})
|
|
201
|
+
app.post(http_root + '/*', async function(req, res) {
|
|
202
|
+
if ( ! (await protect(req, res)) ) return
|
|
203
|
+
|
|
204
|
+
try {
|
|
205
|
+
req.url = req.url.substr(http_root.length, (req.url.length - http_root.length))
|
|
206
|
+
app.route(req, res);
|
|
207
|
+
} catch (e) {
|
|
208
|
+
session.log('http_root post request error : ' + e.message)
|
|
209
|
+
res.end('http_root post request error, check log')
|
|
199
210
|
}
|
|
200
211
|
})
|
|
201
212
|
}
|
|
@@ -1736,7 +1747,11 @@ app.get('/', async function(req, res) {
|
|
|
1736
1747
|
let multiviewquerystring = '/gamechanger.m3u8?resolution=' + DEFAULT_MULTIVIEW_RESOLUTION + content_protect_b
|
|
1737
1748
|
streamURL += content_protect_a
|
|
1738
1749
|
if ( resolution != VALID_RESOLUTIONS[0] ) streamURL += '&resolution=' + resolution
|
|
1739
|
-
|
|
1750
|
+
// force Video.js embed player for Game Changer
|
|
1751
|
+
if ( linkType == VALID_LINK_TYPES[0] ) {
|
|
1752
|
+
let mylink = http_root + '/embed-videojs.html'
|
|
1753
|
+
streamURL = mylink + '?src=' + encodeURIComponent(streamURL) + '&startFrom=' + VALID_START_FROM[1] + content_protect_b
|
|
1754
|
+
} else if ( linkType != VALID_LINK_TYPES[1] ) {
|
|
1740
1755
|
streamURL = thislink + '?src=' + encodeURIComponent(streamURL) + '&startFrom=' + VALID_START_FROM[1] + content_protect_b
|
|
1741
1756
|
}
|
|
1742
1757
|
if ( linkType == VALID_LINK_TYPES[4] ) {
|
|
@@ -1755,7 +1770,11 @@ app.get('/', async function(req, res) {
|
|
|
1755
1770
|
let multiviewquerystring = '/gamechanger.m3u8?streamFinder=on&resolution=' + DEFAULT_MULTIVIEW_RESOLUTION + content_protect_b
|
|
1756
1771
|
streamURL += content_protect_b
|
|
1757
1772
|
if ( resolution != VALID_RESOLUTIONS[0] ) streamURL += '&resolution=' + resolution
|
|
1758
|
-
|
|
1773
|
+
// force Video.js embed player for Stream Finder
|
|
1774
|
+
if ( linkType == VALID_LINK_TYPES[0] ) {
|
|
1775
|
+
let mylink = http_root + '/embed-videojs.html'
|
|
1776
|
+
streamURL = mylink + '?src=' + encodeURIComponent(streamURL) + '&startFrom=' + VALID_START_FROM[1] + content_protect_b
|
|
1777
|
+
} else if ( linkType != VALID_LINK_TYPES[1] ) {
|
|
1759
1778
|
streamURL = thislink + '?src=' + encodeURIComponent(streamURL) + '&startFrom=' + VALID_START_FROM[1] + content_protect_b
|
|
1760
1779
|
}
|
|
1761
1780
|
if ( linkType == VALID_LINK_TYPES[4] ) {
|
|
@@ -2462,7 +2481,142 @@ app.options('*', function(req, res) {
|
|
|
2462
2481
|
return
|
|
2463
2482
|
})
|
|
2464
2483
|
|
|
2484
|
+
// Listen for Video.js embed request, respond with embedded Video.js player
|
|
2485
|
+
// used for Game Changer and Stream Finder
|
|
2486
|
+
app.get('/embed-videojs.html', async function(req, res) {
|
|
2487
|
+
if ( ! (await protect(req, res)) ) return
|
|
2488
|
+
|
|
2489
|
+
session.requestlog('embed-videojs.html', req)
|
|
2490
|
+
|
|
2491
|
+
let startFrom = VALID_START_FROM[0]
|
|
2492
|
+
if ( req.query.startFrom ) {
|
|
2493
|
+
startFrom = req.query.startFrom
|
|
2494
|
+
}
|
|
2495
|
+
let controls = VALID_CONTROLS[0]
|
|
2496
|
+
if ( req.query.controls ) {
|
|
2497
|
+
controls = req.query.controls
|
|
2498
|
+
}
|
|
2499
|
+
|
|
2500
|
+
let video_url = http_root + '/stream.m3u8'
|
|
2501
|
+
if ( req.query.src ) {
|
|
2502
|
+
video_url = req.query.src
|
|
2503
|
+
} else if ( req.query.msrc ) {
|
|
2504
|
+
video_url += '?'
|
|
2505
|
+
if ( req.query.content_protect ) {
|
|
2506
|
+
video_url += 'content_protect=' + req.query.content_protect + '&'
|
|
2507
|
+
}
|
|
2508
|
+
video_url += 'src=' + req.query.msrc
|
|
2509
|
+
} else {
|
|
2510
|
+
let urlArray = req.url.split('?')
|
|
2511
|
+
if ( (urlArray.length == 2) ) {
|
|
2512
|
+
video_url += '?' + urlArray[1]
|
|
2513
|
+
}
|
|
2514
|
+
}
|
|
2515
|
+
session.debuglog('embed-videojs src : ' + video_url)
|
|
2516
|
+
|
|
2517
|
+
let content_protect = ''
|
|
2518
|
+
if ( session.protection.content_protect ) {
|
|
2519
|
+
content_protect = '?content_protect=' + session.protection.content_protect
|
|
2520
|
+
}
|
|
2521
|
+
|
|
2522
|
+
var body = `<html>
|
|
2523
|
+
<head>
|
|
2524
|
+
<meta charset="UTF-8">
|
|
2525
|
+
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
|
|
2526
|
+
<title>` + appname + ` player</title>
|
|
2527
|
+
<link rel="icon" href="favicon.svg` + content_protect + `">
|
|
2528
|
+
<style type="text/css">
|
|
2529
|
+
body {
|
|
2530
|
+
background-color:black;
|
|
2531
|
+
color:lightgrey;
|
|
2532
|
+
font-family:Arial,Helvetica,sans-serif;
|
|
2533
|
+
}
|
|
2534
|
+
.video-wrapper {
|
|
2535
|
+
height: 94vh;
|
|
2536
|
+
display: flex;
|
|
2537
|
+
align-items: center;
|
|
2538
|
+
justify-content: center;
|
|
2539
|
+
overflow: hidden;
|
|
2540
|
+
}
|
|
2541
|
+
button {
|
|
2542
|
+
color:lightgray;
|
|
2543
|
+
background-color:black;
|
|
2544
|
+
}
|
|
2545
|
+
</style>
|
|
2546
|
+
<script>
|
|
2547
|
+
function goBack() {
|
|
2548
|
+
var prevPage=window.location.href;
|
|
2549
|
+
window.history.go(-1);
|
|
2550
|
+
setTimeout(function(){if(window.location.href==prevPage){window.location.href="` + http_root + '/' + content_protect + `"}}, 500);
|
|
2551
|
+
}
|
|
2552
|
+
</script>
|
|
2553
|
+
<link href="https://vjs.zencdn.net/8.23.3/video-js.css" rel="stylesheet" />
|
|
2554
|
+
</head>
|
|
2555
|
+
<body onkeydown="myKeyPress(event)">
|
|
2556
|
+
<div class="video-wrapper">
|
|
2557
|
+
<video id="video" class="video-js vjs-fill"`
|
|
2558
|
+
if ( controls == VALID_CONTROLS[0] ) {
|
|
2559
|
+
body += ' controls'
|
|
2560
|
+
}
|
|
2561
|
+
body += ` muted>
|
|
2562
|
+
<source
|
|
2563
|
+
src="` + video_url + `"
|
|
2564
|
+
type="application/x-mpegURL">
|
|
2565
|
+
</video>
|
|
2566
|
+
</div>
|
|
2567
|
+
<script src="https://vjs.zencdn.net/8.23.3/video.min.js"></script>
|
|
2568
|
+
<script>
|
|
2569
|
+
var player = videojs('video', {
|
|
2570
|
+
"liveui": true,
|
|
2571
|
+
"playbackRates": [0.5, 1, 1.25, 1.5, 2]
|
|
2572
|
+
});
|
|
2573
|
+
function changeTime(skipAmount) {
|
|
2574
|
+
player.currentTime(player.currentTime() + parseInt(skipAmount));
|
|
2575
|
+
}
|
|
2576
|
+
var skipAmounts = ['-30s', '-10s', '+10s', '+30s', '+90s', '+120s'];
|
|
2577
|
+
for (var i=0; i<skipAmounts.length; i++) {
|
|
2578
|
+
player.getChild('ControlBar').addChild('button', {
|
|
2579
|
+
controlText: skipAmounts[i],
|
|
2580
|
+
className: 'vjs-visible-text',
|
|
2581
|
+
clickHandler: function(event) {
|
|
2582
|
+
changeTime(this.controlText());
|
|
2583
|
+
}
|
|
2584
|
+
});
|
|
2585
|
+
}
|
|
2586
|
+
player.ready(function() {
|
|
2587
|
+
`;
|
|
2588
|
+
|
|
2589
|
+
if ( startFrom != VALID_START_FROM[1] ) {
|
|
2590
|
+
body += `this.currentTime(0);
|
|
2591
|
+
`;
|
|
2592
|
+
}
|
|
2593
|
+
|
|
2594
|
+
body += `this.play();
|
|
2595
|
+
});
|
|
2596
|
+
function changeRate(x) {
|
|
2597
|
+
let newrate = parseFloat((player.playbackRate() + x).toFixed(1));
|
|
2598
|
+
player.playbackRate(newrate);
|
|
2599
|
+
}
|
|
2600
|
+
function myKeyPress(e) {
|
|
2601
|
+
if (e.key=="ArrowRight") {
|
|
2602
|
+
changeTime(10);
|
|
2603
|
+
} else if (e.key=="ArrowLeft") {
|
|
2604
|
+
changeTime(-10);
|
|
2605
|
+
} else if (e.key=="ArrowUp") {
|
|
2606
|
+
changeRate(0.1);
|
|
2607
|
+
} else if (e.key=="ArrowDown") {
|
|
2608
|
+
changeRate(-0.1);
|
|
2609
|
+
}
|
|
2610
|
+
}
|
|
2611
|
+
</script>
|
|
2612
|
+
<p><button onclick="goBack()">Back</button></p>
|
|
2613
|
+
</body>
|
|
2614
|
+
</html>`
|
|
2615
|
+
res.end(body)
|
|
2616
|
+
})
|
|
2617
|
+
|
|
2465
2618
|
// Listen for embed request, respond with embedded hls.js player
|
|
2619
|
+
// used for everything except Game Changer and Stream Finder
|
|
2466
2620
|
app.get('/embed.html', async function(req, res) {
|
|
2467
2621
|
if ( ! (await protect(req, res)) ) return
|
|
2468
2622
|
|
|
@@ -3288,7 +3442,7 @@ app.post('/upload', async function(req, res) {
|
|
|
3288
3442
|
|
|
3289
3443
|
req.on('body', function(body) {
|
|
3290
3444
|
session.parse_stream_finder_settings(body)
|
|
3291
|
-
let response = '<p><b>SUCCESS!</b></p><p>Your Stream Finder settings have been saved in mlbserver.</p><p>Select the Stream Finder stream to use them, or <a href="
|
|
3445
|
+
let response = '<p><b>SUCCESS!</b></p><p>Your Stream Finder settings have been saved in mlbserver.</p><p>Select the Stream Finder stream to use them, or <a href="' + http_root + '/#streamfinder">click here</a> to replace them with new settings.</p>'
|
|
3292
3446
|
res.end(response)
|
|
3293
3447
|
})
|
|
3294
3448
|
} catch (e) {
|
package/package.json
CHANGED
package/session.js
CHANGED
|
@@ -4074,9 +4074,9 @@ class sessionClass {
|
|
|
4074
4074
|
|
|
4075
4075
|
setCurrentGame(cur_game_pk, game, team_data, game_changer_title, priority) {
|
|
4076
4076
|
if ( cur_game_pk != game.game_pk ) {
|
|
4077
|
-
this.debuglog(game_changer_title + '
|
|
4078
|
-
return {'game_pk': game.game_pk, 'cur_batter': game.batter}
|
|
4077
|
+
this.debuglog(game_changer_title + 'set current game to ' + this.getCurrentGame(game, team_data) + ' due to ' + priority.type + ' ' + priority.data)
|
|
4079
4078
|
}
|
|
4079
|
+
return {'game_pk': game.game_pk, 'cur_batter': game.batter}
|
|
4080
4080
|
}
|
|
4081
4081
|
|
|
4082
4082
|
sleep(ms) {
|
|
@@ -4133,11 +4133,7 @@ class sessionClass {
|
|
|
4133
4133
|
for (var i=0; i<cache_data.dates[0].games.length; i++) {
|
|
4134
4134
|
let game = cache_data.dates[0].games[i]
|
|
4135
4135
|
|
|
4136
|
-
let gamePk = game.gamePk.toString()
|
|
4137
|
-
let broadcast_count = await this.count_broadcasts(game.broadcasts, 'MLBTV')
|
|
4138
|
-
if ( this.temp_cache.gamechanger.blackouts[gamePk] && this.temp_cache.gamechanger.blackouts[gamePk].blackout_feeds && (this.temp_cache.gamechanger.blackouts[gamePk].blackout_feeds.length == broadcast_count) ) {
|
|
4139
|
-
continue
|
|
4140
|
-
}
|
|
4136
|
+
let gamePk = game.gamePk.toString()
|
|
4141
4137
|
|
|
4142
4138
|
if (!game.linescore) {
|
|
4143
4139
|
continue
|
|
@@ -4163,9 +4159,12 @@ class sessionClass {
|
|
|
4163
4159
|
if (game.linescore.outs) {
|
|
4164
4160
|
outs = game.linescore.outs
|
|
4165
4161
|
}
|
|
4166
|
-
let status = '
|
|
4167
|
-
|
|
4168
|
-
|
|
4162
|
+
let status = 'unknown'
|
|
4163
|
+
let broadcast_count = await this.count_broadcasts(game.broadcasts, 'MLBTV')
|
|
4164
|
+
if ( this.temp_cache.gamechanger.blackouts[gamePk] && this.temp_cache.gamechanger.blackouts[gamePk].blackout_feeds && (this.temp_cache.gamechanger.blackouts[gamePk].blackout_feeds.length == broadcast_count) ) {
|
|
4165
|
+
status = 'blackout'
|
|
4166
|
+
} else if ( game.status && game.status.detailedState ) {
|
|
4167
|
+
status = game.status.detailedState
|
|
4169
4168
|
}
|
|
4170
4169
|
let half = 1
|
|
4171
4170
|
if ( game.linescore.inningHalf && (game.linescore.inningHalf == 'Bottom') ) {
|
|
@@ -4283,6 +4282,8 @@ class sessionClass {
|
|
|
4283
4282
|
}
|
|
4284
4283
|
})
|
|
4285
4284
|
}
|
|
4285
|
+
|
|
4286
|
+
this.debuglog(game_changer_title + 'games ' + JSON.stringify(games))
|
|
4286
4287
|
|
|
4287
4288
|
let active_games = []
|
|
4288
4289
|
let same_batter = 'N'
|
|
@@ -4299,18 +4300,22 @@ class sessionClass {
|
|
|
4299
4300
|
let gamePk = game.gamePk.toString()
|
|
4300
4301
|
|
|
4301
4302
|
if ( !team_data[game.teams.away.team.id.toString()] || !team_data[game.teams.home.team.id.toString()] ) {
|
|
4303
|
+
this.debuglog(game_changer_title + 'invalid team(s) in game ' + gamePk)
|
|
4302
4304
|
continue
|
|
4303
4305
|
}
|
|
4304
4306
|
|
|
4305
4307
|
if ( game.linescore.outs == 3 ) {
|
|
4308
|
+
this.debuglog(game_changer_title + 'end of half inning in game ' + gamePk)
|
|
4306
4309
|
continue
|
|
4307
4310
|
}
|
|
4308
4311
|
|
|
4309
4312
|
if ( game.linescore.inningState && !['Top', 'Bottom'].includes(game.linescore.inningState) ) {
|
|
4313
|
+
this.debuglog(game_changer_title + 'between innings in game ' + gamePk)
|
|
4310
4314
|
continue
|
|
4311
4315
|
}
|
|
4312
4316
|
|
|
4313
|
-
if ( !game.status || (game.status != '
|
|
4317
|
+
if ( !game.status || (game.status != 'In Progress') ) {
|
|
4318
|
+
this.debuglog(game_changer_title + 'non-active game ' + gamePk)
|
|
4314
4319
|
continue
|
|
4315
4320
|
}
|
|
4316
4321
|
|
|
@@ -4319,6 +4324,7 @@ class sessionClass {
|
|
|
4319
4324
|
for (var j=0; j<this.stream_finder_settings.ignore.length; j++) {
|
|
4320
4325
|
let ignore_team = this.stream_finder_settings.ignore[j]
|
|
4321
4326
|
if ( (ignore_team == game.teams.away.team.id.toString()) || (ignore_team == game.teams.home.team.id.toString()) ) {
|
|
4327
|
+
this.debuglog(game_changer_title + 'ignoring team in game ' + gamePk)
|
|
4322
4328
|
ignore = true
|
|
4323
4329
|
break
|
|
4324
4330
|
}
|
|
@@ -4330,10 +4336,10 @@ class sessionClass {
|
|
|
4330
4336
|
|
|
4331
4337
|
if ( this.temp_cache.gamechanger[id].break_expiries[gamePk] ) {
|
|
4332
4338
|
if ( this.temp_cache.gamechanger[id].break_expiries[gamePk] > now ) {
|
|
4333
|
-
this.debuglog(game_changer_title + '
|
|
4339
|
+
this.debuglog(game_changer_title + 'pitching change in progress in game ' + gamePk)
|
|
4334
4340
|
continue
|
|
4335
4341
|
} else {
|
|
4336
|
-
this.debuglog(game_changer_title + '
|
|
4342
|
+
this.debuglog(game_changer_title + 'pitching change complete in game ' + gamePk)
|
|
4337
4343
|
this.removeBreakExpiry(id, gamePk)
|
|
4338
4344
|
}
|
|
4339
4345
|
}
|
|
@@ -4351,14 +4357,13 @@ class sessionClass {
|
|
|
4351
4357
|
this.temp_cache.gamechanger[id].cur_pitchers[gamePk] = {}
|
|
4352
4358
|
}
|
|
4353
4359
|
if ( !this.temp_cache.gamechanger[id].cur_pitchers[gamePk][pitching_team_id] ) {
|
|
4360
|
+
this.debuglog(game_changer_title + 'storing pitcher ' + game.linescore.defense.pitcher.id + ' for team ' + pitching_team_id + ' in game ' + gamePk)
|
|
4354
4361
|
this.temp_cache.gamechanger[id].cur_pitchers[gamePk][pitching_team_id] = game.linescore.defense.pitcher.id
|
|
4355
|
-
} else {
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
continue
|
|
4361
|
-
}
|
|
4362
|
+
} else if ( game.linescore.defense.pitcher.id != this.temp_cache.gamechanger[id].cur_pitchers[gamePk][pitching_team_id] ) {
|
|
4363
|
+
this.debuglog(game_changer_title + 'pitching change begun in game ' + gamePk)
|
|
4364
|
+
this.setBreakExpiry(id, gamePk)
|
|
4365
|
+
this.temp_cache.gamechanger[id].cur_pitchers[gamePk][pitching_team_id] = game.linescore.defense.pitcher.id
|
|
4366
|
+
continue
|
|
4362
4367
|
}
|
|
4363
4368
|
}
|
|
4364
4369
|
|
|
@@ -4391,6 +4396,7 @@ class sessionClass {
|
|
|
4391
4396
|
|
|
4392
4397
|
// Flag to stay on current game if same batter is still at bat
|
|
4393
4398
|
if ( (game.gamePk == this.temp_cache.gamechanger[id].cur_game_pk) && (game.linescore.offense.batter.id == this.temp_cache.gamechanger[id].cur_batter) && (game.linescore.outs < 3) && ((game.linescore.balls && ![0,4].includes(game.linescore.balls)) || (game.linescore.strikes && ![0,3].includes(game.linescore.strikes))) ) {
|
|
4399
|
+
this.debuglog(game_changer_title + 'same batter is up in current game ' + gamePk)
|
|
4394
4400
|
same_batter = 'Y'
|
|
4395
4401
|
}
|
|
4396
4402
|
|
|
@@ -4425,7 +4431,7 @@ class sessionClass {
|
|
|
4425
4431
|
}
|
|
4426
4432
|
|
|
4427
4433
|
if ( !this.temp_cache.gamechanger[id].cur_game_pk && (active_games.length == 0) ) {
|
|
4428
|
-
this.debuglog(game_changer_title + '
|
|
4434
|
+
this.debuglog(game_changer_title + 'no active games')
|
|
4429
4435
|
return
|
|
4430
4436
|
}
|
|
4431
4437
|
|
|
@@ -4438,14 +4444,16 @@ class sessionClass {
|
|
|
4438
4444
|
return b.LI - a.LI;
|
|
4439
4445
|
})
|
|
4440
4446
|
|
|
4441
|
-
this.debuglog(game_changer_title + '
|
|
4442
|
-
this.debuglog(game_changer_title + '
|
|
4443
|
-
this.debuglog(game_changer_title + '
|
|
4447
|
+
this.debuglog(game_changer_title + 'active games ' + JSON.stringify(games))
|
|
4448
|
+
this.debuglog(game_changer_title + 'current pitchers ' + JSON.stringify(this.temp_cache.gamechanger[id].cur_pitchers))
|
|
4449
|
+
this.debuglog(game_changer_title + 'pitching changes ' + JSON.stringify(this.temp_cache.gamechanger[id].break_expiries))
|
|
4450
|
+
this.debuglog(game_changer_title + 'same batter? ' + same_batter)
|
|
4444
4451
|
|
|
4445
4452
|
let game_pk = null
|
|
4446
4453
|
let game_info = null
|
|
4447
4454
|
if ( this.stream_finder_settings.priority ) {
|
|
4448
4455
|
for (const [key, priority] of Object.entries(this.stream_finder_settings.priority)) {
|
|
4456
|
+
this.debuglog(game_changer_title + 'checking priority ' + JSON.stringify(priority))
|
|
4449
4457
|
if ( (same_batter == 'N') || (priority.immediate == 'Y') ) {
|
|
4450
4458
|
for (var i=0; i<games.length; i++) {
|
|
4451
4459
|
let game = games[i]
|
|
@@ -4564,7 +4572,7 @@ class sessionClass {
|
|
|
4564
4572
|
if (game_pk != this.temp_cache.gamechanger[id].cur_game_pk) {
|
|
4565
4573
|
// delay untested, disabled
|
|
4566
4574
|
/*if ( this.temp_cache.gamechanger[id].cur_game_pk && this.stream_finder_settings.delay && (parseInt(this.stream_finder_settings.delay) > 0) ) {
|
|
4567
|
-
this.debuglog(game_changer_title + '
|
|
4575
|
+
this.debuglog(game_changer_title + 'delaying switch by ' + this.stream_finder_settings.delay)
|
|
4568
4576
|
await this.sleep(this.stream_finder_settings.delay)
|
|
4569
4577
|
}*/
|
|
4570
4578
|
this.log(game_changer_title + 'loading game ' + game_pk)
|