Repository: streamlink/streamlink
Pull request #2981 (2020-05-17 16:41:49)

plugins.olympicchannel: fix/rewrite

codecov[bot]: # [Codecov](https://codecov.io/gh/streamlink/streamlink/pull/2981?src=pr&el=h1) Report
> Merging [#2981](https://codecov.io/gh/streamlink/streamlink/pull/2981?src=pr&el=desc) into [master](https://codecov.io/gh/streamlink/streamlink/commit/a547b3ebd8a74f8bbf99feb58ef2aa55b5da960e&el=desc) will **increase** coverage by `0.04%`.
> The diff coverage is `54.54%`.


```diff
@@            Coverage Diff             @@
##           master    #2981      +/-   ##
==========================================
+ Coverage   52.57%   52.62%   +0.04%     
==========================================
  Files         251      251              
  Lines       15769    15767       -2     
==========================================
+ Hits         8291     8297       +6     
+ Misses       7478     7470       -8     
```


Patch:
diff --git a/src/streamlink/plugins/olympicchannel.py b/src/streamlink/plugins/olympicchannel.py
index 955a3547..94e4bc62 100644
--- a/src/streamlink/plugins/olympicchannel.py
+++ b/src/streamlink/plugins/olympicchannel.py
@@ -1,62 +1,57 @@
 import re
+from time import time
+import logging
+import json
 
 from streamlink.plugin import Plugin
 from streamlink.plugin.api import validate
 from streamlink.stream import HLSStream
+from streamlink.compat import urlparse, urljoin
+
+log = logging.getLogger(__name__)
 
 
 class OlympicChannel(Plugin):
-    _url_re = re.compile(r"http(?:s)?://(\w+)\.?olympicchannel.com/../(?P<type>tv|playback)/(livestream-.\d|.*)/")
-    _live_api_url = "https://www.olympicchannel.com{0}api/v2/metadata/{1}"
-    _stream_get_url = "https://www.olympicchannel.com/en/proxy/viewings/"
-    _stream_api_schema = validate.Schema({
-        u'status': u'ok',
-        u'primary': validate.url(),
-        validate.optional(u'backup'): validate.url()
-    })
+    _url_re = re.compile(r"https?://(\w+\.)olympicchannel.com/../(?P<type>live|video|original-series|films)/?(?:\w?|[-\w]+)")
+    _tokenizationApiDomainUrl = """"tokenizationApiDomainUrl" content="/OcsTokenization/api/v1/tokenizedUrl">"""
+    _live_api_path = "/OcsTokenization/api/v1/tokenizedUrl?url={url}&domain={netloc}&_ts={time}"
+
+    _api_schema = validate.Schema(
+        validate.text,
+        validate.transform(lambda v: json.loads(v)),
+        validate.url()
+    )
+    _video_url_re = re.compile(r""""video_url"\scontent\s*=\s*"(?P<value>[^"]+)""")
+    _video_url_schema = validate.Schema(
+        validate.contains(_tokenizationApiDomainUrl),
+        validate.transform(_video_url_re.search),
+        validate.any(None, validate.get("value")),
+        validate.url()
+    )
 
     @classmethod
     def can_handle_url(cls, url):
         return cls._url_re.match(url)
 
     def _get_vod_streams(self):
-        page = self.session.http.get(self.url)
-        asset = re.search(r'asse_.{32}', str(page._content)).group(0)
-        post_data = '{"asset_url":"/api/assets/%s/"}' % asset
-        stream_data = self.session.http.json(self.session.http.post(self._stream_get_url, data=post_data))
-        return HLSStream.parse_variant_playlist(self.session, stream_data['objects'][0]['level3']['streaming_url'])
-
-    def _get_live_streams(self, lang, path):
-        """
-        Get the live stream in a particular language
-        :param lang:
-        :param path:
-        :return:
-        """
-        res = self.session.http.get(self._live_api_url.format(lang, path))
-        live_res = self.session.http.json(res)['default']['uid']
-        post_data = '{"channel_url":"/api/channels/%s/"}' % live_res
-        try:
-            stream_data = self.session.http.json(self.session.http.post(self._stream_get_url, data=post_data))['stream_url']
-        except BaseException:
-            stream_data = self.session.http.json(self.session.http.post(self._stream_get_url, data=post_data))['channel_url']
-        return HLSStream.parse_variant_playlist(self.session, stream_data)
+        stream_url = self.session.http.get(self.url, schema=self._video_url_schema)
+        return HLSStream.parse_variant_playlist(self.session, stream_url)
+
+    def _get_live_streams(self):
+        video_url = self.session.http.get(self.url, schema=self._video_url_schema)
+        parsed = urlparse(video_url)
+        api_url = urljoin(self.url, self._live_api_path.format(url=video_url,
+                          netloc="{0}://{1}".format(parsed.scheme, parsed.netloc), time=int(time())))
+        stream_url = self.session.http.get(api_url, schema=self._api_schema)
+        return HLSStream.parse_variant_playlist(self.session, stream_url)
 
     def _get_streams(self):
-        """
-        Find the streams for OlympicChannel
-        :return:
-        """
         match = self._url_re.match(self.url)
         type_of_stream = match.group('type')
-        lang = re.search(r"/../", self.url).group(0)
-
-        if type_of_stream == 'tv':
-            path = re.search(r"tv/.*-\d/$", self.url).group(0)
 
-            return self._get_live_streams(lang, path)
-        elif type_of_stream == 'playback':
-            path = re.search(r"/playback/.*/$", self.url).group(0)
+        if type_of_stream == 'live':
+            return self._get_live_streams()
+        elif type_of_stream in ('video', 'original-series', 'films'):
             return self._get_vod_streams()
 
 
diff --git a/src/streamlink/plugins/tvplayer.py b/src/streamlink/plugins/tvplayer.py
index e21803f7..8a783f70 100644
--- a/src/streamlink/plugins/tvplayer.py
+++ b/src/streamlink/plugins/tvplayer.py
@@ -78,7 +78,7 @@ class TVPlayer(Plugin):
         if res_schema["response"]["stream"] is None:
             res = self.session.http.get(
                 self.stream_url,
-                params=dict(key=key),
+                params=dict(key=key, platform="chrome"),
                 headers={
                     "Token": token,
                     "Token-Expiry": expiry,


Test patch:
diff --git a/tests/plugins/test_olympicchannel.py b/tests/plugins/test_olympicchannel.py
index 28e55fc9..9832a7b3 100644
--- a/tests/plugins/test_olympicchannel.py
+++ b/tests/plugins/test_olympicchannel.py
@@ -5,10 +5,17 @@ from streamlink.plugins.olympicchannel import OlympicChannel
 
 class TestPluginOlympicChannel(unittest.TestCase):
     def test_can_handle_url(self):
-        # should match
-        self.assertTrue(OlympicChannel.can_handle_url("https://www.olympicchannel.com/en/playback/listen-up-olympic-dreamers/"))
-        self.assertTrue(OlympicChannel.can_handle_url("https://www.olympicchannel.com/en/tv/overflow-6/"))
-        self.assertTrue(OlympicChannel.can_handle_url("https://www.olympicchannel.com/en/tv/livestream-5/"))
+        urls = (
+            "https://www.olympicchannel.com/en/video/detail/stefanidi-husband-coach-krier-relationship/",
+            "https://www.olympicchannel.com/en/live/",
+            "https://www.olympicchannel.com/en/live/video/detail/olympic-ceremonies-channel/",
+            "https://www.olympicchannel.com/de/video/detail/stefanidi-husband-coach-krier-relationship/",
+            "https://www.olympicchannel.com/de/original-series/detail/body/body-season-season-1/episodes/"
+            "treffen-sie-aaron-wheelz-fotheringham-den-paten-des-rollstuhl-extremsports/",
+        )
+        for url in urls:
+            # should match
+            self.assertTrue(OlympicChannel.can_handle_url(url))
 
         # shouldn't match
         self.assertFalse(OlympicChannel.can_handle_url("https://www.olympicchannel.com/en/"))