From b854a388135782a80ce00329aa0f4e1e32d47bec Mon Sep 17 00:00:00 2001 From: Christopher Rosell Date: Sat, 25 Aug 2012 15:14:56 +0200 Subject: livestreamer.plugins.gomtv: A few tweaks and fixes. - Python 3.x compatible. - Fix cookie handling. - Remove unused methods and variables. - Coding style tweaks. --- src/livestreamer/compat.py | 9 ++- 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">\d+)\"\sclass=\"live_now\"\stitle=\"(?P[^\"]+)' + 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 -- cgit v1.2.3