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.
Files changed (3) hide show
  1. package/README.md +1 -2
  2. package/package.json +1 -1
  3. package/session.js +236 -3
package/README.md CHANGED
@@ -1,5 +1,4 @@
1
- [![Docker release](https://img.shields.io/docker/v/tonywagner/mlbserver)](https://hub.docker.com/r/tonywagner/mlbserver)
2
- [![NPM release](https://img.shields.io/npm/v/mlbserver)](https://www.npmjs.com/package/mlbserver)
1
+ [![GitHub release](https://img.shields.io/github/release/tonywagner/mlbserver.svg)](https://github.com/tonywagner/mlbserver/releases)
3
2
  ![License](https://img.shields.io/badge/license-MIT-blue)
4
3
  [![Contributors](https://img.shields.io/github/contributors/tonywagner/mlbserver.svg)](https://github.com/tonywagner/mlbserver/graphs/contributors)
5
4
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mlbserver",
3
- "version": "2024.07.25-3",
3
+ "version": "2024.07.25",
4
4
  "description": "",
5
5
  "repository": {
6
6
  "type": "git",
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
- await this.getSession()
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
- await this.getSession()
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 += ' <sub-title lang="en">' + subtitle + '</sub-title>' + "\n"
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" +