mlbserver 2024.7.25-3 → 2024.7.25
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 -2
- package/package.json +1 -1
- package/session.js +236 -3
package/README.md
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
[](https://www.npmjs.com/package/mlbserver)
|
|
1
|
+
[](https://github.com/tonywagner/mlbserver/releases)
|
|
3
2
|

|
|
4
3
|
[](https://github.com/tonywagner/mlbserver/graphs/contributors)
|
|
5
4
|
|
package/package.json
CHANGED
package/session.js
CHANGED
|
@@ -1472,11 +1472,46 @@ class sessionClass {
|
|
|
1472
1472
|
})
|
|
1473
1473
|
}
|
|
1474
1474
|
|
|
1475
|
+
// API call
|
|
1476
|
+
/*async getApiKeys() {
|
|
1477
|
+
this.debuglog('getApiKeys')
|
|
1478
|
+
let reqObj = {
|
|
1479
|
+
url: 'https://www.mlb.com/tv/g632102/',
|
|
1480
|
+
headers: {
|
|
1481
|
+
'User-agent': USER_AGENT,
|
|
1482
|
+
'Origin': 'https://www.mlb.com',
|
|
1483
|
+
'Accept-Encoding': 'gzip, deflate, br'
|
|
1484
|
+
},
|
|
1485
|
+
gzip: true
|
|
1486
|
+
}
|
|
1487
|
+
var response = await this.httpGet(reqObj)
|
|
1488
|
+
if ( response ) {
|
|
1489
|
+
// disabled because it's very big!
|
|
1490
|
+
//this.debuglog('getApiKeys response : ' + response)
|
|
1491
|
+
var parsed = response.match('"x-api-key","value":"([^"]+)"')
|
|
1492
|
+
if ( parsed[1] ) {
|
|
1493
|
+
this.data.xApiKey = parsed[1]
|
|
1494
|
+
this.save_session_data()
|
|
1495
|
+
} else {
|
|
1496
|
+
this.log('getApiKeys xApiKey parse failure')
|
|
1497
|
+
}
|
|
1498
|
+
parsed = response.match('"clientApiKey":"([^"]+)"')
|
|
1499
|
+
if ( parsed[1] ) {
|
|
1500
|
+
this.data.clientApiKey = parsed[1]
|
|
1501
|
+
this.save_session_data()
|
|
1502
|
+
} else {
|
|
1503
|
+
this.log('getApiKeys clientApiKey parse failure')
|
|
1504
|
+
}
|
|
1505
|
+
} else {
|
|
1506
|
+
this.log('getApiKeys response failure')
|
|
1507
|
+
}
|
|
1508
|
+
}*/
|
|
1509
|
+
|
|
1475
1510
|
// new API call
|
|
1476
1511
|
async getDeviceId() {
|
|
1477
1512
|
this.debuglog('getDeviceId')
|
|
1478
1513
|
if ( !this.data.deviceId ) {
|
|
1479
|
-
|
|
1514
|
+
this.getSession()
|
|
1480
1515
|
}
|
|
1481
1516
|
if ( this.data.deviceId ) {
|
|
1482
1517
|
this.debuglog('using cached deviceId')
|
|
@@ -1490,7 +1525,7 @@ class sessionClass {
|
|
|
1490
1525
|
async getSessionId() {
|
|
1491
1526
|
this.debuglog('getSessionId')
|
|
1492
1527
|
if ( !this.data.sessionId ) {
|
|
1493
|
-
|
|
1528
|
+
this.getSession()
|
|
1494
1529
|
}
|
|
1495
1530
|
if ( this.data.sessionId ) {
|
|
1496
1531
|
this.debuglog('using cached sessionId')
|
|
@@ -1616,6 +1651,204 @@ class sessionClass {
|
|
|
1616
1651
|
}
|
|
1617
1652
|
}
|
|
1618
1653
|
|
|
1654
|
+
// API call
|
|
1655
|
+
/*async getStreamURL(mediaId) {
|
|
1656
|
+
this.debuglog('getStreamURL from ' + mediaId)
|
|
1657
|
+
if ( this.cache.media && this.cache.media[mediaId] && this.cache.media[mediaId].streamURL && this.cache.media[mediaId].streamURLExpiry && (Date.parse(this.cache.media[mediaId].streamURLExpiry) > new Date()) ) {
|
|
1658
|
+
this.debuglog('using cached streamURL')
|
|
1659
|
+
return this.cache.media[mediaId].streamURL
|
|
1660
|
+
} 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()) ) {
|
|
1661
|
+
this.log('mediaId recently blacked out, skipping')
|
|
1662
|
+
} else {
|
|
1663
|
+
let playbackURL = 'https://edge.svcs.mlb.com/media/' + mediaId + '/scenarios/browser~csai'
|
|
1664
|
+
let reqObj = {
|
|
1665
|
+
url: playbackURL,
|
|
1666
|
+
simple: false,
|
|
1667
|
+
headers: {
|
|
1668
|
+
'Authorization': await this.getBamAccessToken() || this.halt('missing bamAccessToken'),
|
|
1669
|
+
'User-agent': USER_AGENT,
|
|
1670
|
+
'Accept': 'application/vnd.media-service+json; version=1',
|
|
1671
|
+
'x-bamsdk-version': BAM_SDK_VERSION,
|
|
1672
|
+
'x-bamsdk-platform': PLATFORM,
|
|
1673
|
+
'Origin': 'https://www.mlb.com',
|
|
1674
|
+
'Accept-Encoding': 'gzip, deflate, br',
|
|
1675
|
+
'Content-type': 'application/json'
|
|
1676
|
+
},
|
|
1677
|
+
gzip: true
|
|
1678
|
+
}
|
|
1679
|
+
var response = await this.httpGet(reqObj)
|
|
1680
|
+
if ( response && this.isValidJson(response) ) {
|
|
1681
|
+
this.debuglog('getStreamURL response : ' + response)
|
|
1682
|
+
let obj = JSON.parse(response)
|
|
1683
|
+
if ( obj.errors ) {
|
|
1684
|
+
this.log('getStreamURL error: ' + obj.errors[0])
|
|
1685
|
+
if ( obj.errors[0] == 'blackout' ) {
|
|
1686
|
+
this.markBlackoutError(mediaId)
|
|
1687
|
+
}
|
|
1688
|
+
return false
|
|
1689
|
+
} else {
|
|
1690
|
+
let streamURL = obj.stream.complete
|
|
1691
|
+
this.debuglog('getStreamURL : ' + streamURL)
|
|
1692
|
+
this.cacheStreamURL(mediaId, streamURL)
|
|
1693
|
+
return streamURL
|
|
1694
|
+
}
|
|
1695
|
+
} else {
|
|
1696
|
+
this.log('getStreamURL response failure')
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1700
|
+
|
|
1701
|
+
// API call
|
|
1702
|
+
async getBamAccessToken() {
|
|
1703
|
+
this.debuglog('getBamAccessToken')
|
|
1704
|
+
if ( !this.data.bamAccessToken || !this.data.bamAccessTokenExpiry || (Date.parse(this.data.bamAccessTokenExpiry) < new Date()) ) {
|
|
1705
|
+
this.debuglog('need to get new bamAccessToken')
|
|
1706
|
+
let reqObj = {
|
|
1707
|
+
url: BAM_TOKEN_URL,
|
|
1708
|
+
headers: {
|
|
1709
|
+
'Authorization': 'Bearer ' + API_KEY,
|
|
1710
|
+
'User-agent': USER_AGENT,
|
|
1711
|
+
'Accept': 'application/vnd.media-service+json; version=1',
|
|
1712
|
+
'x-bamsdk-version': BAM_SDK_VERSION,
|
|
1713
|
+
'x-bamsdk-platform': PLATFORM,
|
|
1714
|
+
'Origin': 'https://www.mlb.com',
|
|
1715
|
+
'Accept-Encoding': 'gzip, deflate, br',
|
|
1716
|
+
'Content-type': 'application/x-www-form-urlencoded'
|
|
1717
|
+
},
|
|
1718
|
+
form: {
|
|
1719
|
+
'grant_type': 'urn:ietf:params:oauth:grant-type:token-exchange',
|
|
1720
|
+
'platform': 'browser',
|
|
1721
|
+
'subject_token': await this.getEntitlementToken() || this.halt('missing EntitlementToken'),
|
|
1722
|
+
'subject_token_type': 'urn:bamtech:params:oauth:token-type:account'
|
|
1723
|
+
},
|
|
1724
|
+
gzip: true
|
|
1725
|
+
}
|
|
1726
|
+
var response = await this.httpPost(reqObj)
|
|
1727
|
+
if ( this.isValidJson(response) ) {
|
|
1728
|
+
let obj = JSON.parse(response)
|
|
1729
|
+
this.debuglog('getBamAccessToken : ' + obj.access_token)
|
|
1730
|
+
this.debuglog('getBamAccessToken expires in : ' + obj.expires_in)
|
|
1731
|
+
this.data.bamAccessToken = obj.access_token
|
|
1732
|
+
this.data.bamAccessTokenExpiry = new Date(new Date().getTime() + obj.expires_in * 1000)
|
|
1733
|
+
this.save_session_data()
|
|
1734
|
+
return this.data.bamAccessToken
|
|
1735
|
+
} else {
|
|
1736
|
+
this.log('getBamAccessToken response failure')
|
|
1737
|
+
}
|
|
1738
|
+
} else {
|
|
1739
|
+
return this.data.bamAccessToken
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
// API call
|
|
1744
|
+
async getEntitlementToken() {
|
|
1745
|
+
this.debuglog('getEntitlementToken')
|
|
1746
|
+
let reqObj = {
|
|
1747
|
+
url: 'https://media-entitlement.mlb.com/api/v3/jwt',
|
|
1748
|
+
headers: {
|
|
1749
|
+
'Authorization': 'Bearer ' + await this.getLoginToken() || this.halt('missing loginToken'),
|
|
1750
|
+
'Origin': 'https://www.mlb.com'
|
|
1751
|
+
},
|
|
1752
|
+
qs: {
|
|
1753
|
+
'os': PLATFORM,
|
|
1754
|
+
'did': await this.getDeviceId() || this.halt('missing deviceId'),
|
|
1755
|
+
'appname': 'mlbtv_web'
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
var response = await this.httpGet(reqObj)
|
|
1759
|
+
if ( response ) {
|
|
1760
|
+
this.debuglog('getEntitlementToken response : ' + response)
|
|
1761
|
+
this.debuglog('getEntitlementToken : ' + response)
|
|
1762
|
+
return response
|
|
1763
|
+
} else {
|
|
1764
|
+
this.log('getEntitlementToken response failure')
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
|
|
1768
|
+
async getDeviceId() {
|
|
1769
|
+
this.debuglog('getDeviceId')
|
|
1770
|
+
let reqObj = {
|
|
1771
|
+
url: 'https://us.edge.bamgrid.com/session',
|
|
1772
|
+
headers: {
|
|
1773
|
+
'Authorization': await this.getDeviceAccessToken() || this.halt('missing device_access_token'),
|
|
1774
|
+
'User-agent': USER_AGENT,
|
|
1775
|
+
'Origin': 'https://www.mlb.com',
|
|
1776
|
+
'Accept': 'application/vnd.session-service+json; version=1',
|
|
1777
|
+
'Accept-Encoding': 'gzip, deflate, br',
|
|
1778
|
+
'Accept-Language': 'en-US,en;q=0.5',
|
|
1779
|
+
'x-bamsdk-version': BAM_SDK_VERSION,
|
|
1780
|
+
'x-bamsdk-platform': PLATFORM,
|
|
1781
|
+
'Content-type': 'application/json',
|
|
1782
|
+
'TE': 'Trailers'
|
|
1783
|
+
},
|
|
1784
|
+
gzip: true
|
|
1785
|
+
}
|
|
1786
|
+
var response = await this.httpGet(reqObj)
|
|
1787
|
+
if ( response && this.isValidJson(response) ) {
|
|
1788
|
+
this.debuglog('getDeviceId response : ' + response)
|
|
1789
|
+
let obj = JSON.parse(response)
|
|
1790
|
+
this.debuglog('getDeviceId : ' + obj.device.id)
|
|
1791
|
+
return obj.device.id
|
|
1792
|
+
} else {
|
|
1793
|
+
this.log('getDeviceId response failure')
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1797
|
+
// API call
|
|
1798
|
+
async getDeviceAccessToken() {
|
|
1799
|
+
this.debuglog('getDeviceAccessToken')
|
|
1800
|
+
let reqObj = {
|
|
1801
|
+
url: BAM_TOKEN_URL,
|
|
1802
|
+
headers: {
|
|
1803
|
+
'Authorization': 'Bearer ' + API_KEY,
|
|
1804
|
+
'Origin': 'https://www.mlb.com'
|
|
1805
|
+
},
|
|
1806
|
+
form: {
|
|
1807
|
+
'grant_type': 'urn:ietf:params:oauth:grant-type:token-exchange',
|
|
1808
|
+
'latitude': '0',
|
|
1809
|
+
'longitude': '0',
|
|
1810
|
+
'platform': 'browser',
|
|
1811
|
+
'subject_token': await this.getDevicesAssertion() || this.halt('missing devicesAssertion'),
|
|
1812
|
+
'subject_token_type': 'urn:bamtech:params:oauth:token-type:device'
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1815
|
+
var response = await this.httpPost(reqObj)
|
|
1816
|
+
if ( this.isValidJson(response) ) {
|
|
1817
|
+
this.debuglog('getDeviceAccessToken response : ' + response)
|
|
1818
|
+
let obj = JSON.parse(response)
|
|
1819
|
+
this.debuglog('getDeviceAccessToken : ' + obj.access_token)
|
|
1820
|
+
return obj.access_token
|
|
1821
|
+
} else {
|
|
1822
|
+
this.log('getDeviceAccessToken response failure')
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1825
|
+
|
|
1826
|
+
// API call
|
|
1827
|
+
async getDevicesAssertion() {
|
|
1828
|
+
this.debuglog('getDevicesAssertion')
|
|
1829
|
+
let reqObj = {
|
|
1830
|
+
url: 'https://us.edge.bamgrid.com/devices',
|
|
1831
|
+
headers: {
|
|
1832
|
+
'Authorization': 'Bearer ' + API_KEY,
|
|
1833
|
+
'Origin': 'https://www.mlb.com'
|
|
1834
|
+
},
|
|
1835
|
+
json: {
|
|
1836
|
+
'applicationRuntime': 'firefox',
|
|
1837
|
+
'attributes': {},
|
|
1838
|
+
'deviceFamily': 'browser',
|
|
1839
|
+
'deviceProfile': 'macosx'
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
var response = await this.httpPost(reqObj)
|
|
1843
|
+
if ( response.assertion ) {
|
|
1844
|
+
this.debuglog('getDevicesAssertion response : ' + JSON.stringify(response))
|
|
1845
|
+
this.debuglog('getDevicesAssertion : ' + response.assertion)
|
|
1846
|
+
return response.assertion
|
|
1847
|
+
} else {
|
|
1848
|
+
this.log('getDevicesAssertion response failure')
|
|
1849
|
+
}
|
|
1850
|
+
}*/
|
|
1851
|
+
|
|
1619
1852
|
// API call
|
|
1620
1853
|
async getLoginToken() {
|
|
1621
1854
|
this.debuglog('getLoginToken')
|
|
@@ -4123,7 +4356,7 @@ class sessionClass {
|
|
|
4123
4356
|
let xml_output = "\n" + ' <programme channel="' + channelid + '" start="' + start + '" stop="' + stop + '">' + "\n" +
|
|
4124
4357
|
' <title lang="en">' + title + '</title>' + "\n"
|
|
4125
4358
|
if ( subtitle ) {
|
|
4126
|
-
xml_output += ' <
|
|
4359
|
+
xml_output += ' <subtitle lang="en">' + subtitle + '</subtitle>' + "\n"
|
|
4127
4360
|
}
|
|
4128
4361
|
xml_output += ' <desc lang="en">' + description.trim() + '</desc>' + "\n" +
|
|
4129
4362
|
' <category lang="en">Sports</category>' + "\n" +
|