Repository: streamlink/streamlink
Pull request #986 (2017-06-04 23:51:45)

Add support for radio.net
This PR provides support for [radio.net](http://radio.net) (and its locale versions radio.(at|dk|de|fr|it|pt|se|es|pl). radio.net offers free and legal access to radio stations from all over the world.


Patch:
diff --git a/docs/plugin_matrix.rst b/docs/plugin_matrix.rst
index df725172..01c40d4c 100644
--- a/docs/plugin_matrix.rst
+++ b/docs/plugin_matrix.rst
@@ -114,7 +114,7 @@ googledrive         - docs.google.com    --    Yes
 gulli               replay.gulli.fr      Yes   Yes   Streams may be geo-restricted to France.
 hitbox              - hitbox.tv          Yes   Yes
                     - smashcast.tv
-huajiao             huajiao.com          Yes   No    
+huajiao             huajiao.com          Yes   No
 huomao              huomao.com           Yes   No
 huya                huya.com             Yes   No    Temporarily only HLS streams available.
 ine                 ine.com              ---   Yes
@@ -154,6 +154,16 @@ pluzz               - france.tv          Yes   Yes   Streams may be geo-restrict
                     - zouzous.fr
 		    - france3-reg.. [8]_
 powerapp            powerapp.com.tr      Yes   No
+radionet            - radio.net          Yes   --
+                    - radio.at
+		    - radio.de
+		    - radio.dk
+		    - radio.es
+		    - radio.fr
+		    - radio.it
+		    - radio.pl
+		    - radio.pt
+		    - radio.se
 raiplay             raiplay.it           Yes   No    Most streams are geo-restricted to Italy.
 rtlxl               rtlxl.nl             No    Yes   Streams may be geo-restricted to The Netherlands. Livestreams not supported.
 rte                 rte.ie/player        Yes   Yes
diff --git a/src/streamlink/plugins/radionet.py b/src/streamlink/plugins/radionet.py
new file mode 100644
index 00000000..7fe91937
--- /dev/null
+++ b/src/streamlink/plugins/radionet.py
@@ -0,0 +1,58 @@
+import re
+
+from streamlink.plugin import Plugin
+from streamlink.plugin.api import http
+from streamlink.plugin.api import validate
+from streamlink.stream import HTTPStream
+from streamlink.utils import parse_json
+
+
+class RadioNet(Plugin):
+    _url_re = re.compile(r"https?://(\w+)\.radio\.(net|at|de|dk|es|fr|it|pl|pt|se)")
+    _stream_data_re = re.compile(r'\bstation\s*:\s*(\{.+\}),?\s*')
+
+    _stream_schema = validate.Schema(
+        validate.transform(_stream_data_re.search),
+        validate.any(
+            None,
+            validate.all(
+                validate.get(1),
+                validate.transform(parse_json),
+                {
+                    'stationType': validate.text,
+                    'streamUrls': validate.all([{
+                        'bitRate': int,
+                        'streamUrl': validate.url()
+                    }])
+                },
+            )
+        )
+    )
+
+    @classmethod
+    def can_handle_url(cls, url):
+        return cls._url_re.match(url)
+
+    def _get_streams(self):
+        streams = http.get(self.url, schema=self._stream_schema)
+        if streams is None:
+            return
+
+        # Ignore non-radio streams (podcasts...)
+        if streams['stationType'] != 'radio_station':
+            return
+
+        stream_urls = []
+        for stream in streams['streamUrls']:
+            if stream['streamUrl'] in stream_urls:
+                continue
+
+            if stream['bitRate'] > 0:
+                bitrate = '{}k'.format(stream['bitRate'])
+            else:
+                bitrate = 'live'
+            yield bitrate, HTTPStream(self.session, stream['streamUrl'])
+            stream_urls.append(stream['streamUrl'])
+
+
+__plugin__ = RadioNet


Test patch:
diff --git a/tests/test_plugin_radionet.py b/tests/test_plugin_radionet.py
new file mode 100644
index 00000000..fe75a97f
--- /dev/null
+++ b/tests/test_plugin_radionet.py
@@ -0,0 +1,24 @@
+import unittest
+
+from streamlink.plugins.radionet import RadioNet
+
+
+class TestPluginRadioNet(unittest.TestCase):
+    def test_can_handle_url(self):
+        # should match
+        self.assertTrue(RadioNet.can_handle_url("http://radioparadise.radio.net/"))
+        self.assertTrue(RadioNet.can_handle_url("http://oe1.radio.at/"))
+        self.assertTrue(RadioNet.can_handle_url("http://deutschlandfunk.radio.de/"))
+        self.assertTrue(RadioNet.can_handle_url("http://rneradionacional.radio.es/"))
+        self.assertTrue(RadioNet.can_handle_url("http://franceinfo.radio.fr/"))
+        self.assertTrue(RadioNet.can_handle_url("https://drp1bagklog.radio.dk/"))
+        self.assertTrue(RadioNet.can_handle_url("http://rairadiouno.radio.it/"))
+        self.assertTrue(RadioNet.can_handle_url("http://program1jedynka.radio.pl/"))
+        self.assertTrue(RadioNet.can_handle_url("http://rtpantena1983fm.radio.pt/"))
+        self.assertTrue(RadioNet.can_handle_url("http://sverigesp1.radio.se/"))
+
+        # shouldn't match
+        self.assertFalse(RadioNet.can_handle_url("http://radio.net/"))
+        self.assertFalse(RadioNet.can_handle_url("http://radio.com/"))
+        self.assertFalse(RadioNet.can_handle_url("http://www.tvcatchup.com/"))
+        self.assertFalse(RadioNet.can_handle_url("http://www.youtube.com/"))