diff options
author | Christopher Rosell <chrippa@tanuki.se> | 2012-08-25 15:14:56 +0200 |
---|---|---|
committer | Christopher Rosell <chrippa@tanuki.se> | 2012-08-25 15:14:56 +0200 |
commit | b854a388135782a80ce00329aa0f4e1e32d47bec (patch) | |
tree | 83ba2bf18b2a81fa860e2f3d996acba612be0792 | |
parent | 91363e5628dd30e34ab254c619246a298333f8bc (diff) |
livestreamer.plugins.gomtv: A few tweaks and fixes.
- Python 3.x compatible.
- Fix cookie handling.
- Remove unused methods and variables.
- Coding style tweaks.
-rw-r--r-- | src/livestreamer/compat.py | 9 | ||||
-rw-r--r-- | src/livestreamer/plugins/gomtv.py | 149 |
2 files changed, 80 insertions, 78 deletions
diff --git a/src/livestreamer/compat.py b/src/livestreamer/compat.py index 61711fb..f023bd8 100644 --- a/src/livestreamer/compat.py +++ b/src/livestreamer/compat.py @@ -7,10 +7,11 @@ is_win32 = os.name == "nt" if is_py2: input = raw_input stdout = sys.stdout + _str = str str = unicode def bytes(b, enc="ascii"): - return str(b) + return _str(b) elif is_py3: bytes = bytes @@ -25,9 +26,13 @@ except ImportError: try: from urllib.parse import urlparse, parse_qs, urlencode + import http.cookies as cookies + import http.cookiejar as cookiejar except ImportError: from urlparse import urlparse, parse_qs from urllib import urlencode + import Cookie as cookies + import cookielib as cookiejar __all__ = ["is_py2", "is_py3", "is_win32", "input", "stdout", "str", - "bytes", "urllib", "urlparse", "parse_qs"] + "bytes", "urllib", "urlparse", "parse_qs", "cookies", "cookiejar"] diff --git a/src/livestreamer/plugins/gomtv.py b/src/livestreamer/plugins/gomtv.py index b2aa494..3c8562c 100644 --- a/src/livestreamer/plugins/gomtv.py +++ b/src/livestreamer/plugins/gomtv.py @@ -1,7 +1,6 @@ -''' -This is derived from https://github.com/sjp/GOMstreamer - -and carries the following licence +""" +This plugin is derived from https://github.com/sjp/GOMstreamer +and carries the following license. Copyright 2010 Simon Potter, Tomas Herman Copyright 2011 Simon Potter @@ -20,16 +19,15 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -''' -from livestreamer.compat import str, bytes, urlencode +""" + +from livestreamer.compat import str, bytes, urlencode, urllib, cookies, cookiejar from livestreamer.plugins import Plugin, PluginError, NoStreamsError from livestreamer.stream import HTTPStream -from livestreamer.utils import urlget, urllib +from livestreamer.utils import urlget from livestreamer.options import Options import xml.dom.minidom, re -import cookielib -import Cookie class GomTV(Plugin): options = Options({ @@ -42,27 +40,22 @@ class GomTV(Plugin): def can_handle_url(self, url): return "gomtv.net" in url - def _get_streams(self): options = self.options # Setting urllib up so that we can store cookies - self.cookiejar = cookielib.LWPCookieJar() + self.cookiejar = cookiejar.LWPCookieJar() self.opener = urllib.build_opener(urllib.HTTPCookieProcessor(self.cookiejar)) if options.get("cookie"): - self.authenticate(cookie=options.get("cookie")) + self.authenticate(cookies=options.get("cookie")) else: self.authenticate(options.get("username"), options.get("password")) streams = {} qualities = ["HQ", "SQ", "HQTest", "SQTest"] - streamChoice = "both" response = self.grabLivePage(self.url) - goxUrls = [] - validGoxFound = False - failedGoxAll = False for quality in qualities: urls = self.parseHTML(response, quality) @@ -71,132 +64,136 @@ class GomTV(Plugin): goxFile = urlget(url, opener=self.opener) # The response for the GOX XML if an incorrect stream quality is chosen is 1002. - if (goxFile != '1002' and goxFile != ''): + if goxFile != b"1002" and len(goxFile) > 0: streamUrl = self.parseStreamURL(goxFile) req = urllib.Request(streamUrl, headers={"User-Agent": "KPeerClient"}) streams[quality] = HTTPStream(self.session, req) - validGoxFound = True return streams - def authenticate(self, username=None, password=None, cookie=None): - if (username is None or password is None) and cookie is None: + def authenticate(self, username=None, password=None, cookies=None): + if (username is None or password is None) and cookies is None: raise PluginError("GOMTV.net Requires a username and password or cookie") - - - if cookie is not None: - name,value = cookie.split("=") - - c = cookielib.Cookie(version=0, name=name, value=value, - port=None, port_specified=False, domain='gomtv.net', - domain_specified=False, domain_initial_dot=False, path='/', - path_specified=True, secure=False, expires=None, discard=True, - comment=None, comment_url=None, rest={'HttpOnly': None}, - rfc2109=False) - self.cookiejar.set_cookie(c) + + + if cookies is not None: + for cookie in cookies.split(";"): + try: + name, value = cookie.split("=") + except ValueError: + continue + + c = cookiejar.Cookie(version=0, name=name, value=value, + port=None, port_specified=False, domain="gomtv.net", + domain_specified=False, domain_initial_dot=False, path="/", + path_specified=True, secure=False, expires=None, discard=True, + comment=None, comment_url=None, rest={"HttpOnly": None}, + rfc2109=False) + self.cookiejar.set_cookie(c) else: values = { - 'cmd': 'login', - 'rememberme': '1', - 'mb_username': username, - 'mb_password': password - } - data = urlencode(values) - # Now expects to log in only via the website. Thanks chrippa. - headers = {'Referer': 'http://www.gomtv.net/'} - request = urllib.Request('https://ssl.gomtv.net/userinfo/loginProcess.gom', data, headers) + "cmd": "login", + "rememberme": "1", + "mb_username": username, + "mb_password": password + } + data = bytes(urlencode(values), "ascii") + headers = {"Referer": "http://www.gomtv.net/"} + request = urllib.Request("https://ssl.gomtv.net/userinfo/loginProcess.gom", data, headers) urlget(request, opener=self.opener) - - req = urllib.Request('http://www.gomtv.net/forum/list.gom?m=my') - if 'Please need login' in urlget(req, opener=self.opener): - raise PluginError("Authentication failed") - # The real response that we want are the cookies, so returning None is fine. - return + req = urllib.Request("http://www.gomtv.net/forum/list.gom?m=my") + if b"Please need login" in urlget(req, opener=self.opener): + raise PluginError("Authentication failed") def getEventLivePageURL(self, gomtvLiveURL, response): match = re.search(' \"(.*)\";', response) - assert match, 'Event Live Page URL not found' - return urljoin(gomtvLiveURL, match.group(1)) - def getSeasonURL(self, gomtvURL): - # Getting season url from the 'Go Live!' button on the main page. - match = re.search('.*liveicon"><a href="([^"]*)"', urlget(gomtvURL, opener=self.opener)) - assert match, 'golive_btn href not found' - return match.group(1) + if not match: + raise PluginError("Event Live Page URL not found") + + return urljoin(gomtvLiveURL, match.group(1)) def grabLivePage(self, gomtvLiveURL): response = urlget(gomtvLiveURL, opener=self.opener) + # If a special event occurs, we know that the live page response # will just be some JavaScript that redirects the browser to the # real live page. We assume that the entireity of this JavaScript # is less than 200 characters long, and that real live pages are # more than that. + if len(response) < 200: # Grabbing the real live page URL gomtvLiveURL = self.getEventLivePageURL(gomtvLiveURL, response) response = urlget(gomtvLiveURL, opener=self.opener) + return response def parseHTML(self, response, quality): urlFromHTML = None + # Parsing through the live page for a link to the gox XML file. # Quality is simply passed as a URL parameter e.g. HQ, SQ, SQTest try: - patternHTML = r'[^/]+var.+(http://www.gomtv.net/gox[^;]+;)' + patternHTML = b"[^/]+var.+(http://www.gomtv.net/gox[^;]+;)" urlFromHTML = re.search(patternHTML, response).group(1) - urlFromHTML = re.sub(r'\" \+ playType \+ \"', quality, urlFromHTML) + urlFromHTML = re.sub(b'\" \+ playType \+ \"', bytes(quality, "utf8"), urlFromHTML) except AttributeError: - pass + raise PluginError("Unable to find the majority of the GOMtv XML URL on the Live page.") # Finding the title of the stream, probably not necessary but # done for completeness try: - patternTitle = r'this\.title[^;]+;' + patternTitle = b"this\.title[^;]+;" titleFromHTML = re.search(patternTitle, response).group(0) - titleFromHTML = re.search(r'\"(.*)\"', titleFromHTML).group(0) - titleFromHTML = re.sub(r'"', '', titleFromHTML) - urlFromHTML = re.sub(r'"\+ tmpThis.title[^;]+;', titleFromHTML, urlFromHTML) + titleFromHTML = re.search(b'\"(.*)\"', titleFromHTML).group(0) + titleFromHTML = re.sub(b'"', b"", titleFromHTML) + urlFromHTML = re.sub(b'"\+ tmpThis.title[^;]+;', titleFromHTML, urlFromHTML) except AttributeError: - pass + raise PluginError("Unable to find the stream title on the Live page.") # Check for multiple streams going at the same time, and extract the conid and the title # Those streams have the class "live_now" - patternLive = r'<a\shref=\"/live/index.gom\?conid=(?P<conid>\d+)\"\sclass=\"live_now\"\stitle=\"(?P<title>[^\"]+)' + patternLive = b'<a\shref=\"/live/index.gom\?conid=(?P<conid>\d+)\"\sclass=\"live_now\"\stitle=\"(?P<title>[^\"]+)' live_streams = re.findall(patternLive, response) if len(live_streams) > 1: liveUrls = [] - options = range(len(live_streams)) - for i in options: + for stream in live_streams: # Modify the urlFromHTML according to the user - singleUrlFromHTML = re.sub(r'conid=\d+', 'conid=' + live_streams[i][0], urlFromHTML) - singleTitleHTML = '+'.join(live_streams[i][1].split(' ')) - singleUrlFromHTML = re.sub(r'title=[\w|.|+]*', 'title=' + singleTitleHTML, singleUrlFromHTML) - liveUrls.append(singleUrlFromHTML) + singleUrlFromHTML = re.sub(b"conid=\d+", b"conid=" + stream[0], urlFromHTML) + singleTitleHTML = b"+".join(stream[0].split(b" ")) + singleUrlFromHTML = re.sub(b"title=[\w|.|+]*", b"title=" + singleTitleHTML, singleUrlFromHTML) + liveUrls.append(str(singleUrlFromHTML, "utf8")) + return liveUrls else: if urlFromHTML is None: return [] else: - return [urlFromHTML] + return [str(urlFromHTML, "utf8")] def parseStreamURL(self, response): # Grabbing the gomcmd URL try: - streamPattern = r'<REF href="([^"]*)"\s*/>' + streamPattern = b'<REF href="([^"]*)"\s*/>' regexResult = re.search(streamPattern, response).group(1) except AttributeError: - return None + raise PluginError("Unable to find the gomcmd URL in the GOX XML file.") + regexResult = str(regexResult, "utf8") + regexResult = regexResult.replace("&", "&") regexResult = urllib.unquote(regexResult) - regexResult = re.sub(r'&', '&', regexResult) + # SQ and SQTest streams can be gomp2p links, with actual stream address passed as a parameter. - if regexResult.startswith('gomp2p://'): - regexResult, n = re.subn(r'^.*LiveAddr=', '', regexResult) + if regexResult.startswith("gomp2p://"): + regexResult, n = re.subn("^.*LiveAddr=", "", regexResult) + # Cosmetics, getting rid of the HTML entity, we don't # need either of the " character or " - regexResult = regexResult.replace('"', '') + regexResult = regexResult.replace(""", "") + return regexResult __plugin__ = GomTV |