diff options
Diffstat (limited to 'module/plugins/internal/SimpleHoster.py')
-rw-r--r-- | module/plugins/internal/SimpleHoster.py | 110 |
1 files changed, 69 insertions, 41 deletions
diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index 5a32ac943..c1982ee67 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -1,9 +1,11 @@ # -*- coding: utf-8 -*- +import mimetypes +import os import re +from datetime import datetime, timedelta from inspect import isclass -from os.path import exists from time import time from urllib import unquote from urlparse import urljoin, urlparse @@ -106,7 +108,13 @@ def parseFileInfo(plugin, url="", html=""): info = plugin.getInfo(url, html) res = info['name'], info['size'], info['status'], info['url'] else: - res = urlparse(unquote(url)).path.split('/')[-1] or _("Unknown"), 0, 3, url + url = unquote(url) + res = ((urlparse(url).path.split('/')[-1] + or urlparse(url).query.split('=', 1)[::-1][0].split('&', 1)[0] + or _("Unknown")), + 0, + 3 if url else 8, + url) return res @@ -114,10 +122,15 @@ def parseFileInfo(plugin, url="", html=""): #@TODO: Remove in 0.4.10 #@NOTE: Every plugin must have own parseInfos classmethod to work with 0.4.10 def create_getInfo(plugin): + + def generator(list): + for x in list: + yield x + if hasattr(plugin, "parseInfos"): - fn = lambda urls: [(info['name'], info['size'], info['status'], info['url']) for info in plugin.parseInfos(urls)] + fn = lambda urls: generator((info['name'], info['size'], info['status'], info['url']) for info in plugin.parseInfos(urls)) else: - fn = lambda urls: [parseFileInfo(url) for url in urls] + fn = lambda urls: generator(parseFileInfo(url) for url in urls) return fn @@ -127,35 +140,58 @@ def timestamp(): #@TODO: Move to hoster class in 0.4.10 -def directLink(self, url, resumable=False): - link = "" +def fileUrl(self, url, follow_location=False): + link = "" + redirect = 1 + + if isinstance(follow_location, int): + redirect = max(follow_location, 1) + + elif follow_location: + redirect = 5 + + for i in xrange(redirect): + self.logDebug("Redirect #%d to: %s" % (i, url)) - for i in xrange(5 if resumable else 1): header = self.load(url, ref=True, cookies=True, just_header=True, decode=True) if 'content-disposition' in header: link = url - elif 'location' in header and header['location']: + elif 'location' in header and header['location'].strip(): location = header['location'] if not urlparse(location).scheme: - p = urlparse(url) - base = "%s://%s" % (p.scheme, p.netloc) - location = urljoin(base, location) + url_p = urlparse(url) + baseurl = "%s://%s" % (url_p.scheme, url_p.netloc) + location = urljoin(baseurl, location) + + if 'code' in header and header['code'] == 302: + link = location - if resumable: + if follow_location: url = location - self.logDebug("Redirect #%d to: %s" % (++i, location)) continue - elif 'code' in header and header['code'] == 302: - link = location + else: + extension = os.path.splitext(urlparse(url).path.split('/')[-1])[-1] - elif 'content-type' in header and header['content-type'] and "html" not in header['content-type']: - link = url + if 'content-type' in header and header['content-type'].strip(): + mimetype = header['content-type'].split(';')[0].strip() + + elif extension: + mimetype = mimetypes.guess_extension(extension, False)[0] or "application/octet-stream" + + else: + mimetype = "" + + if mimetype and (link or 'html' not in mimetype): + link = url + else: + link = "" break + else: self.logError(_("Too many redirects")) @@ -183,7 +219,7 @@ def secondsToMidnight(gmt=0): class SimpleHoster(Hoster): __name__ = "SimpleHoster" __type__ = "hoster" - __version__ = "0.94" + __version__ = "1.01" __pattern__ = r'^unmatchable$' @@ -247,7 +283,7 @@ class SimpleHoster(Hoster): MULTI_HOSTER = False #: Set to True to leech other hoster link (as defined in handleMulti method) LOGIN_ACCOUNT = False #: Set to True to require account login - directLink = directLink #@TODO: Remove in 0.4.10 + directLink = fileUrl #@TODO: Remove in 0.4.10 @classmethod @@ -328,9 +364,6 @@ class SimpleHoster(Hoster): else: online = True - if not info['pattern']: - info.pop('pattern', None) - if online: info['status'] = 2 @@ -351,6 +384,9 @@ class SimpleHoster(Hoster): hashtype = info['pattern']['T'] if 'T' in info['pattern'] else "hash" info[hashtype] = info['pattern']['H'] + if not info['pattern']: + info.pop('pattern', None) + return info @@ -439,9 +475,9 @@ class SimpleHoster(Hoster): self.invalidCaptcha() self.retry(10, reason=_("Wrong captcha")) - elif not self.lastDownload or not exists(fs_encode(self.lastDownload)): + elif not self.lastDownload or not os.path.exists(fs_encode(self.lastDownload)): self.lastDownload = "" - self.fail(self.pyfile.error or _("No file downloaded")) + self.error(self.pyfile.error or _("No file downloaded")) else: rules = {'empty file': re.compile(r'\A\Z'), @@ -553,7 +589,7 @@ class SimpleHoster(Hoster): def handleDirect(self, pyfile): - link = self.directLink(pyfile.url, self.resumeDownload) + link = self.fileUrl(pyfile.url, self.resumeDownload) if link: self.logInfo(_("Direct download link detected")) @@ -571,16 +607,12 @@ class SimpleHoster(Hoster): if not hasattr(self, 'LINK_FREE_PATTERN'): self.logError(_("Free download not implemented")) - try: - m = re.search(self.LINK_FREE_PATTERN, self.html) - if m is None: - self.error(_("Free download link not found")) - + m = re.search(self.LINK_FREE_PATTERN, self.html) + if m is None: + self.error(_("Free download link not found")) + else: self.link = m.group(1) - except Exception, e: - self.fail(e) - def handlePremium(self, pyfile): if not hasattr(self, 'LINK_PREMIUM_PATTERN'): @@ -588,16 +620,12 @@ class SimpleHoster(Hoster): self.logDebug("Handled as free download") self.handleFree(pyfile) - try: - m = re.search(self.LINK_PREMIUM_PATTERN, self.html) - if m is None: - self.error(_("Premium download link not found")) - + m = re.search(self.LINK_PREMIUM_PATTERN, self.html) + if m is None: + self.error(_("Premium download link not found")) + else: self.link = m.group(1) - except Exception, e: - self.fail(e) - def longWait(self, wait_time=None, max_tries=3): if wait_time and isinstance(wait_time, (int, long, float)): |