Repository: streamlink/streamlink
Pull request #1953 (2018-07-22 13:01:17)

plugins.younow: Fix for session error and plugin cleanup
- Fixed `self.session.http` issues
- added title and author
- better error msg
- plugin cleanup / flake8


Patch:
diff --git a/src/streamlink/plugins/younow.py b/src/streamlink/plugins/younow.py
index 1ddd3a95..075d67f5 100644
--- a/src/streamlink/plugins/younow.py
+++ b/src/streamlink/plugins/younow.py
@@ -1,53 +1,86 @@
-"""Plugin for younow.com by WeinerRinkler"""
-
+import logging
 import re
 
-from streamlink.plugin import Plugin, PluginError
+from streamlink.exceptions import PluginError
+from streamlink.plugin import Plugin
+from streamlink.plugin.api import validate
 from streamlink.stream import RTMPStream
 
-jsonapi = "https://api.younow.com/php/api/broadcast/info/curId=0/user="
+log = logging.getLogger(__name__)
+
+
+class YouNow(Plugin):
 
-# http://younow.com/channel/
-_url_re = re.compile(r"http(s)?://(\w+.)?younow.com/(?P<channel>[^/&?]+)")
+    user_api_url = "https://api.younow.com/php/api/broadcast/info/curId=0/user={0}"
 
+    _url_re = re.compile(r"https?://(?:\w+\.)?younow\.com/(?P<channel>[^/&?]+)")
 
-def getStreamURL(channel):
-    url = jsonapi + channel
-    res = self.session.http.get(url)
-    streamerinfo = self.session.http.json(res)
-    # print(streamerinfo)
+    _user_schema = validate.Schema(
+        {
+            "errorCode": int,
+            "media": {
+                "host": validate.text,
+                "app": validate.text,
+                "stream": validate.text
+            },
+            "title": validate.text,
+            "username": validate.text
+        }
+    )
 
-    if not any("media" in s for s in streamerinfo):
-        print("User offline or invalid")
-        return
-    else:
-        streamdata = streamerinfo['media']
-        # print(streamdata)
-        streamurl = "rtmp://" + streamdata['host'] + streamdata['app'] + "/" + streamdata['stream']
-        #print (streamurl)
+    _error_schema = validate.Schema(
+        {
+            "errorCode": int,
+            "errorMsg": validate.text
+        }
+    )
 
-    return streamurl
+    _api_schema = validate.Schema(
+        validate.any(_user_schema, _error_schema)
+    )
 
+    author = None
+    title = None
 
-class younow(Plugin):
     @classmethod
-    def can_handle_url(self, url):
-        return _url_re.match(url)
+    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)
+    def get_author(self):
+        if self.author is None:
+            self.get_api_data()
+        return self.author
+
+    def get_title(self):
+        if self.title is None:
+            self.get_api_data()
+        return self.title
+
+    def get_api_data(self):
+        match = self._url_re.match(self.url)
         channel = match.group("channel")
 
-        streamurl = getStreamURL(channel)
-        if not streamurl:
-            return
-        streams = {}
-        streams["live"] = RTMPStream(self.session, {
-            "rtmp": streamurl,
-            "live": True
-        })
+        res = self.session.http.get(self.user_api_url.format(channel))
+        data = self.session.http.json(res, schema=self._api_schema)
+        log.trace("{0!r}".format(data))
+
+        if data["errorCode"] != 0:
+            raise PluginError("{0} - {1}".format(data["errorCode"], data["errorMsg"]))
+
+        self.author = data["username"]
+        self.title = data["title"]
 
-        return streams
+        return data
+
+    def _get_streams(self):
+        data = self.get_api_data()
+        params = {
+            "rtmp": "rtmp://{0}{1}/{2}".format(data["media"]["host"],
+                                               data["media"]["app"],
+                                               data["media"]["stream"]),
+            "live": True
+        }
+        return {"live": RTMPStream(self.session, params=params)}
 
 
-__plugin__ = younow
+__plugin__ = YouNow


Test patch:
diff --git a/tests/plugins/test_younow.py b/tests/plugins/test_younow.py
index 1a446521..1763dd17 100644
--- a/tests/plugins/test_younow.py
+++ b/tests/plugins/test_younow.py
@@ -1,19 +1,19 @@
 import unittest
 
-from streamlink.plugins.younow import younow
+from streamlink.plugins.younow import YouNow
 
 
-class TestPluginyounow(unittest.TestCase):
+class TestPluginYouNow(unittest.TestCase):
     def test_can_handle_url(self):
         should_match = [
             'https://www.younow.com/example',
         ]
         for url in should_match:
-            self.assertTrue(younow.can_handle_url(url))
+            self.assertTrue(YouNow.can_handle_url(url))
 
     def test_can_handle_url_negative(self):
         should_not_match = [
             'https://example.com/index.html',
         ]
         for url in should_not_match:
-            self.assertFalse(younow.can_handle_url(url))
+            self.assertFalse(YouNow.can_handle_url(url))