Repository: streamlink/streamlink

Issue:
tv3cat
### Checklist

- [x] This is a bug report.
- [ ] This is a feature request.
- [ ] This is a plugin (improvement) request.
- [ ] I have read the contribution guidelines.

### Description

Links Live:
http://www.ccma.cat/tv3/directe/tv3/
http://www.ccma.cat/tv3/directe/324/
http://www.ccma.cat/tv3/directe/33/
http://www.ccma.cat/tv3/directe/esport3/


Channels 324 / Esport3 / 33 / TV3:
```
streamlink.exe http://www.ccma.cat/tv3/directe/esport3/ best --player ffplay -l debug
[console][debug] OS:         Windows 7
[console][debug] Python:     3.5.2
[console][debug] Streamlink: 0.13.0
[console][debug] Requests(2.18.4), Socks(1.6.7), Websocket(0.48.0)
[console][info] Found matching plugin tv3cat for URL http://www.ccma.cat/tv3/directe/esport3/
error: Unable to validate JSON: Unable to validate key 'media': Unable to validate result: Unable to validate key 'url': Unable to validate URL attribute 'scheme': 'https' does not equal 'http' or Unable to validate result: Type of [{'geo':
 'CATALUNYA', 'format': 'HLS', 'url': 'https://ccma-tva-cat-cellnex-live-hls.secure.footprint.net/cat/ngrp:es3_web/playlist.m3u8'}, {'geo': 'ESPANYA', 'format':
 'HLS', 'url': 'https://ccma-tva-es-cellnex-live-hls.secure.footprint.net/es/ngrp:es3_web/playlist.m3u8'}, {'geo': 'TOTS', 'format': 'HLS', 'url': 'https://ccma-tva-int-cellnex-live-hls.secure.footprint.net/int/ngrp:es3_web/playlist.m3u8'}]
 should be 'dict' but is 'list'

streamlink.exe http://www.ccma.cat/tv3/directe/33/ best --player ffplay -l debug
[console][debug] OS:         Windows 7
[console][debug] Python:     3.5.2
[console][debug] Streamlink: 0.13.0
[console][debug] Requests(2.18.4), Socks(1.6.7), Websocket(0.48.0)
[console][info] Found matching plugin tv3cat for URL http://www.ccma.cat/tv3/directe/33/
error: Unable to validate JSON: Unable to validate key 'media': Unable to validate result: Unable to validate key 'url': Unable to validate URL attribute 'scheme': 'https' does not equal 'http' or Unable to validate result: Type of [{'format': 'HLS', 'url': 'https://ccma-tva-cat-cellnex-live-hls.secure.footprint.net/cat/ngrp:c33_web/playlist.m3u8', 'geo': 'CATALUNYA'}, {'format': 'HLS', 'url': 'https://ccma-tva-es-cellnex-live-hls.secure.footprint.net/es/ngrp:c33_web/playlist.m3u8', 'geo': 'ESPANYA'}, {'format': 'HLS', 'url': 'https://ccma-tva-int-cellnex-live-hls.secure.footprint.net/int/ngrp:c33_web/playlist.m3u8', 'geo': 'TOTS'}]
 should be 'dict' but is 'list'

streamlink.exe http://www.ccma.cat/tv3/directe/324/ best --player ffplay -l debug
[console][debug] OS:         Windows 7
[console][debug] Python:     3.5.2
[console][debug] Streamlink: 0.13.0
[console][debug] Requests(2.18.4), Socks(1.6.7), Websocket(0.48.0)
[console][info] Found matching plugin tv3cat for URL http://www.ccma.cat/tv3/directe/324/
error: Unable to validate JSON: Unable to validate key 'media': Type of {'geo':
'TOTS', 'url': 'https://ccma-tva-int-cellnex-live-hls.secure.footprint.net/int/ngrp:324_web/playlist.m3u8', 'format': 'HLS'} should be 'list' but is 'dict' or Unable to validate result: Unable to validate key 'url': Unable to validate URL attribute 'scheme': 'https' does not equal 'http'

streamlink.exe http://www.ccma.cat/tv3/directe/tv3/ best --player ffplay -l debug
[console][debug] OS:         Windows 7
[console][debug] Python:     3.5.2
[console][debug] Streamlink: 0.13.0
[console][debug] Requests(2.18.4), Socks(1.6.7), Websocket(0.48.0)
[console][info] Found matching plugin tv3cat for URL http://www.ccma.cat/tv3/directe/tv3/
error: Unable to validate JSON: Unable to validate key 'media': Unable to validate result: Unable to validate key 'url': Unable to validate URL attribute 'scheme': 'https' does not equal 'http' or Unable to validate result: Type of [{'geo':
 'CATALUNYA', 'url': 'https://ccma-tva-cat-cellnex-live-hls.secure.footprint.net/cat/ngrp:tv3_web/playlist.m3u8', 'format': 'HLS'}, {'geo': 'ESPANYA', 'url': 'https://ccma-tva-es-cellnex-live-hls.secure.footprint.net/es/ngrp:tv3_web/playlist.m3u8', 'format': 'HLS'}, {'geo': 'TOTS', 'url': 'https://ccma-tva-int-cellnex-live-hls.secure.footprint.net/int/ngrp:tv3_web/playlist.m3u8', 'format': 'HLS'}]
 should be 'dict' but is 'list'

```


Discussion:

Resolving patch:
diff --git a/src/streamlink/plugins/tv3cat.py b/src/streamlink/plugins/tv3cat.py
--- a/src/streamlink/plugins/tv3cat.py
+++ b/src/streamlink/plugins/tv3cat.py
@@ -1,4 +1,5 @@
 #!/usr/bin/env python
+import logging
 import re
 
 from streamlink.plugin import Plugin
@@ -6,46 +7,40 @@
 from streamlink.stream import HLSStream
 from streamlink.plugin.api import validate
 
-STREAM_INFO_URL = "http://dinamics.ccma.cat/pvideo/media.jsp?media=video&version=0s&idint={ident}&profile=pc&desplacament=0"
-_url_re = re.compile(r"http://(?:www.)?ccma.cat/tv3/directe/(.+?)/")
-_media_schema = validate.Schema({
-    "geo": validate.text,
-    "url": validate.url(scheme=validate.any("http"))
-})
-_channel_schema = validate.Schema({
-    "media": validate.any([_media_schema], _media_schema)
-})
+log = logging.getLogger(__name__)
 
 
 class TV3Cat(Plugin):
+    _url_re = re.compile(r"http://(?:www.)?ccma.cat/tv3/directe/(.+?)/")
+    _stream_info_url = "http://dinamics.ccma.cat/pvideo/media.jsp?media=video&version=0s&idint={ident}&profile=pc&desplacament=0"
+    _media_schema = validate.Schema({
+        "geo": validate.text,
+        "url": validate.url(scheme=validate.any("http", "https"))
+    })
+    _channel_schema = validate.Schema({
+        "media": validate.any([_media_schema], _media_schema)},
+        validate.get("media"),
+        # If there is only one item, it's not a list ... silly
+        validate.transform(lambda x: x if isinstance(x, list) else [x])
+    )
+
     @classmethod
-    def can_handle_url(self, url):
-        match = _url_re.match(url)
-        return match
+    def can_handle_url(cls, url):
+        return cls._url_re.match(url) is not None
 
     def _get_streams(self):
-
-        match = _url_re.match(self.url)
+        match = self._url_re.match(self.url)
         if match:
             ident = match.group(1)
-            data_url = STREAM_INFO_URL.format(ident=ident)
-
-            # find the region, default to TOTS (international)
-            res = http.get(self.url)
-            geo_data = re.search(r'data-geo="([A-Z]+?)"', res.text)
-            geo = geo_data and geo_data.group(1) or "TOTS"
-
-            stream_data = http.json(http.get(data_url), schema=_channel_schema)
-
-            # If there is only one item, it's not a list ... silly
-            if isinstance(stream_data['media'], list):
-                stream_infos = stream_data['media']
-            else:
-                stream_infos = [stream_data['media']]
+            data_url = self._stream_info_url.format(ident=ident)
+            stream_infos = http.json(http.get(data_url), schema=self._channel_schema)
 
             for stream in stream_infos:
-                if stream['geo'] == geo:
-                    return HLSStream.parse_variant_playlist(self.session, stream['url'])
+                try:
+                    return HLSStream.parse_variant_playlist(self.session, stream['url'], name_fmt="{pixels}_{bitrate}")
+                except:
+                    log.debug("Failed to get streams for: {0}".format(stream['geo']))
+                    pass
 
 
 __plugin__ = TV3Cat


Test patch: