Repository: streamlink/streamlink
Pull request #3296 (2020-10-26 21:05:11)

plugins.zdf_mediathek: also support 3sat mediathek
3sat and ZDF mediathek essentially are the same, only the URLs and the API
URLs differ. So support 3sat URLs and check the URL to decide whether to
use the ZDF or 3sat API. Everything else is identical.



Patch:
diff --git a/src/streamlink/plugins/twitch.py b/src/streamlink/plugins/twitch.py
index b534b003..d4bf53ee 100644
--- a/src/streamlink/plugins/twitch.py
+++ b/src/streamlink/plugins/twitch.py
@@ -297,7 +297,7 @@ class TwitchAPI(object):
                 validate.get("sig"),
                 validate.get("token")
             ))
-        ))
+        ), player_type="frontpage")
 
     def token(self, tokenstr):
         return parse_json(tokenstr, schema=validate.Schema(
diff --git a/src/streamlink/plugins/zdf_mediathek.py b/src/streamlink/plugins/zdf_mediathek.py
index fed3b3b7..60f20e68 100644
--- a/src/streamlink/plugins/zdf_mediathek.py
+++ b/src/streamlink/plugins/zdf_mediathek.py
@@ -1,5 +1,6 @@
 import logging
 import re
+from urllib.parse import urlparse, urlunparse
 
 from streamlink.plugin import Plugin
 from streamlink.plugin.api import validate
@@ -9,8 +10,6 @@ from streamlink.utils.url import url_concat
 
 log = logging.getLogger(__name__)
 
-API_URL = "https://api.zdf.de"
-
 QUALITY_WEIGHTS = {
     "hd": 720,
     "veryhigh": 480,
@@ -29,7 +28,7 @@ STREAMING_TYPES = {
 }
 
 _url_re = re.compile(r"""
-    http(s)?://(\w+\.)?zdf.de/
+    http(s)?://(\w+\.)?(zdf\.de|3sat\.de)/
 """, re.VERBOSE | re.IGNORECASE)
 _api_json_re = re.compile(r'''data-zdfplayer-jsb=["'](?P<json>{.+?})["']''', re.S)
 
@@ -140,10 +139,13 @@ class zdf_mediathek(Plugin):
         res = self.session.http.get(zdf_json['content'], headers=headers)
         document = self.session.http.json(res, schema=_documents_schema)
 
+        document_url_p = urlparse(zdf_json['content'])
+        api_url = urlunparse((document_url_p.scheme, document_url_p.netloc, "", "", "", ""))
+
         content = document["mainVideoContent"]
         target = content["http://zdf.de/rels/target"]
         template = target["http://zdf.de/rels/streams/ptmd-template"]
-        stream_request_url = url_concat(API_URL, template.format(playerId="ngplayer_2_3").replace(" ", ""))
+        stream_request_url = url_concat(api_url, template.format(playerId="ngplayer_2_3").replace(" ", ""))
 
         res = self.session.http.get(stream_request_url, headers=headers)
         res = self.session.http.json(res, schema=_schema)


Test patch:
diff --git a/tests/plugins/test_zdf_mediathek.py b/tests/plugins/test_zdf_mediathek.py
index 0d006310..848cbb9b 100644
--- a/tests/plugins/test_zdf_mediathek.py
+++ b/tests/plugins/test_zdf_mediathek.py
@@ -16,6 +16,7 @@ class TestPluginzdf_mediathek(unittest.TestCase):
             'https://www.zdf.de/dokumentation/zdfinfo-doku/zdfinfo-live-beitrag-100.html',
             'https://www.zdf.de/comedy/heute-show/videos/diy-hazel-habeck-100.html',
             'https://www.zdf.de/nachrichten/heute-sendungen/so-wird-das-wetter-102.html',
+            'https://www.3sat.de/wissen/nano',
         ]
         for url in should_match:
             self.assertTrue(zdf_mediathek.can_handle_url(url))