Repository: streamlink/streamlink

Issue:
younow.com is broken
They have changed the API url to this one: 
`https://api.younow.com/php/api/broadcast/info/curId=0/user=`
in:
https://github.com/streamlink/streamlink/blob/master/src/streamlink/plugins/younow.py#L9

It still needs rtmpdump.exe, so it will give you the following error, related to #56
`[cli][error] Could not open stream: Unable to find rtmpdump.exe command`
#81 fixes it, and the plugin works fine.

Comments:

Patch:
diff --git a/docs/plugin_matrix.rst b/docs/plugin_matrix.rst
index d90da1ff..4cd211c0 100644
--- a/docs/plugin_matrix.rst
+++ b/docs/plugin_matrix.rst
@@ -12,6 +12,7 @@ is limited.
 =================== ==================== ===== ===== ===========================
 Name                URL(s)               Live  VOD   Notes
 =================== ==================== ===== ===== ===========================
+adultswim           adultswim.com        Yes   No    Streams may be geo-restricted, VOD streams are encrypted
 afreeca             afreecatv.com        Yes   No
 afreecatv           afreeca.tv           Yes   No
 aftonbladet         aftonbladet.se       Yes   Yes
diff --git a/src/streamlink/plugins/adultswim.py b/src/streamlink/plugins/adultswim.py
new file mode 100644
index 00000000..abe15b82
--- /dev/null
+++ b/src/streamlink/plugins/adultswim.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+import re
+from pprint import pprint
+
+from streamlink.plugin import Plugin
+from streamlink.plugin.api import http, validate
+from streamlink.stream import HLSStream
+from streamlink.utils import parse_json
+
+
+class AdultSwim(Plugin):
+    _user_agent = (
+        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) "
+        "Chrome/43.0.2357.65 Safari/537.36")
+    API_URL = "http://www.adultswim.com/videos/api/v2/videos/{id}?fields=stream"
+
+    _url_re = re.compile(r"http://www\.adultswim\.com/videos/streams/(.*)")
+    _stream_data_re = re.compile(r".*AS_INITIAL_DATA = (\{.*?});.*", re.M | re.DOTALL)
+
+    _page_data_schema = validate.Schema({
+        u"streams": {
+            validate.text: {
+                u"stream": validate.text
+            }
+        }
+    })
+
+    _api_schema = validate.Schema({
+        u'status': u'ok',
+        u'data': {
+            u'stream': {
+                u'assets': [
+                    {
+                        u'url': validate.url()
+                    }
+                ]
+            }
+        }
+    })
+
+    @classmethod
+    def can_handle_url(cls, url):
+        match = AdultSwim._url_re.match(url)
+        return match is not None
+
+    def _get_streams(self):
+        # get the page
+        res = http.get(self.url, headers={"User-Agent": self._user_agent})
+        # find the big blob of stream info in the page
+        stream_data = self._stream_data_re.match(res.text)
+        stream_name = AdultSwim._url_re.match(self.url).group(1) or "live-stream"
+
+        if stream_data:
+            # parse the stream info as json
+            stream_info = parse_json(stream_data.group(1), schema=self._page_data_schema)
+            # get the stream ID
+            stream_id = stream_info[u"streams"][stream_name][u"stream"]
+
+            if stream_id:
+                api_url = self.API_URL.format(id=stream_id)
+
+                res = http.get(api_url, headers={"User-Agent": self._user_agent})
+                stream_data = http.json(res, schema=self._api_schema)
+
+                for asset in stream_data[u'data'][u'stream'][u'assets']:
+                    for n, s in HLSStream.parse_variant_playlist(self.session, asset[u"url"]).items():
+                        yield n, s
+
+            else:
+                self.logger.error("Couldn't find the stream ID for this stream: {}".format(stream_name))
+        else:
+            self.logger.error("Couldn't find the stream data for this stream: {}".format(stream_name))
+
+__plugin__ = AdultSwim
diff --git a/src/streamlink/plugins/goodgame.py b/src/streamlink/plugins/goodgame.py
index 75979026..14557b77 100644
--- a/src/streamlink/plugins/goodgame.py
+++ b/src/streamlink/plugins/goodgame.py
@@ -14,6 +14,7 @@ QUALITIES = {
 
 _url_re = re.compile("https://(?:www\.)?goodgame.ru/channel/(?P<user>\w+)")
 _stream_re = re.compile(r'var src = "([^"]+)";')
+_ddos_re = re.compile(r'document.cookie="(__DDOS_[^;]+)')
 
 class GoodGame(Plugin):
     @classmethod
@@ -31,6 +32,11 @@ class GoodGame(Plugin):
         }
         res = http.get(self.url, headers=headers)
 
+        match = _ddos_re.search(res.text)
+        if match:
+            headers["Cookie"] = match.group(1)
+            res = http.get(self.url, headers=headers)
+
         match = _stream_re.search(res.text)
         if not match:
             return
diff --git a/src/streamlink/plugins/younow.py b/src/streamlink/plugins/younow.py
index a3d8149b..320b37b0 100644
--- a/src/streamlink/plugins/younow.py
+++ b/src/streamlink/plugins/younow.py
@@ -6,7 +6,7 @@ from streamlink.plugin import Plugin, PluginError
 from streamlink.plugin.api import http
 from streamlink.stream import RTMPStream
 
-jsonapi= "http://www.younow.com/php/api/broadcast/info/curId=0/user="
+jsonapi= "https://api.younow.com/php/api/broadcast/info/curId=0/user="
 
 # http://younow.com/channel/
 _url_re = re.compile("http(s)?://(\w+.)?younow.com/(?P<channel>[^/&?]+)")


Test patch:
diff --git a/tests/test_plugin_adultswim.py b/tests/test_plugin_adultswim.py
new file mode 100644
index 00000000..2fba0fa2
--- /dev/null
+++ b/tests/test_plugin_adultswim.py
@@ -0,0 +1,16 @@
+import unittest
+
+from streamlink.plugins.adultswim import AdultSwim
+
+
+class TestPluginAdultSwim(unittest.TestCase):
+    def test_can_handle_url(self):
+        # should match
+        self.assertTrue(AdultSwim.can_handle_url("http://www.adultswim.com/videos/streams/toonami"))
+        self.assertTrue(AdultSwim.can_handle_url("http://www.adultswim.com/videos/streams/"))
+        self.assertTrue(AdultSwim.can_handle_url("http://www.adultswim.com/videos/streams/last-stream-on-the-left"))
+
+        # shouldn't match
+        self.assertFalse(AdultSwim.can_handle_url("http://www.adultswim.com/videos/specials/the-adult-swim-golf-classic-extended/"))
+        self.assertFalse(AdultSwim.can_handle_url("http://www.tvcatchup.com/"))
+        self.assertFalse(AdultSwim.can_handle_url("http://www.youtube.com/"))