diff options
author | Walter Purcaro <vuolter@gmail.com> | 2015-01-08 22:58:32 +0100 |
---|---|---|
committer | Walter Purcaro <vuolter@gmail.com> | 2015-01-08 22:58:32 +0100 |
commit | df143e902d00903f16cf32174948f636bda56e4c (patch) | |
tree | 7aab8bc13369c22b1d9486fdee44f96b7b393391 /module/plugins/internal | |
parent | Merge pull request #1013 from smoozed/stable (diff) | |
download | pyload-df143e902d00903f16cf32174948f636bda56e4c.tar.xz |
"New Year" Update: internal plugins
Diffstat (limited to 'module/plugins/internal')
-rw-r--r-- | module/plugins/internal/CaptchaService.py | 49 | ||||
-rw-r--r-- | module/plugins/internal/MultiHook.py | 158 | ||||
-rw-r--r-- | module/plugins/internal/MultiHoster.py | 15 | ||||
-rw-r--r-- | module/plugins/internal/SimpleCrypter.py | 4 | ||||
-rw-r--r-- | module/plugins/internal/SimpleDereferer.py | 6 | ||||
-rw-r--r-- | module/plugins/internal/SimpleHoster.py | 55 | ||||
-rw-r--r-- | module/plugins/internal/XFSAccount.py | 8 | ||||
-rw-r--r-- | module/plugins/internal/XFSCrypter.py | 1 | ||||
-rw-r--r-- | module/plugins/internal/XFSHoster.py | 26 |
9 files changed, 197 insertions, 125 deletions
diff --git a/module/plugins/internal/CaptchaService.py b/module/plugins/internal/CaptchaService.py index 965799e8e..b429fd6e0 100644 --- a/module/plugins/internal/CaptchaService.py +++ b/module/plugins/internal/CaptchaService.py @@ -2,6 +2,7 @@ import re +from base64 import urlsafe_b64encode from random import random from module.common.json_layer import json_loads @@ -54,14 +55,14 @@ class CaptchaService: class ReCaptcha(CaptchaService): __name__ = "ReCaptcha" - __version__ = "0.08" + __version__ = "0.09" __description__ = """ReCaptcha captcha service plugin""" __license__ = "GPLv3" __authors__ = [("pyLoad Team", "admin@pyload.org")] - KEY_PATTERN = r'recaptcha(?:/api|\.net)/(?:challenge|noscript)\?k=([\w-]+)' + KEY_PATTERN = r'(?:class="g-recaptcha"\s+data-sitekey="|recaptcha(?:/api|\.net)/(?:challenge|noscript)\?k=)([\w-]+)' KEY_AJAX_PATTERN = r'Recaptcha\.create\s*\(\s*["\']([\w-]+)' @@ -84,7 +85,7 @@ class ReCaptcha(CaptchaService): return None - def challenge(self, key=None): + def challenge(self, key=None, userverify=False): if not key: if self.detect_key(): key = self.key @@ -97,14 +98,30 @@ class ReCaptcha(CaptchaService): try: challenge = re.search("challenge : '(.+?)',", html).group(1) server = re.search("server : '(.+?)',", html).group(1) - except: + + except AttributeError: errmsg = _("ReCaptcha challenge pattern not found") self.plugin.fail(errmsg) - raise ValueError(errmsg) + raise AttributeError(errmsg) self.plugin.logDebug("ReCaptcha challenge: %s" % challenge) - return challenge, self.result(server, challenge) + response = challenge, self.result(server, challenge) + + return self.userverify(*response) if userverify else response + + + def userverify(self, challenge, result): + response = self.plugin.req.load("https://www.google.com/recaptcha/api2/userverify", + post={'c' : challenge, + 'response': urlsafe_b64encode('{"response":"%s"}' % result)}) + try: + return re.search(r'"uvresp","(.+?)"', response).group(1) + + except AttributeError: + errmsg = _("ReCaptcha userverify response not found") + self.plugin.fail(errmsg) + raise AttributeError(errmsg) def result(self, server, challenge): @@ -167,10 +184,11 @@ class AdsCaptcha(CaptchaService): try: challenge = re.search("challenge: '(.+?)',", html).group(1) server = re.search("server: '(.+?)',", html).group(1) - except: + + except AttributeError: errmsg = _("AdsCaptcha challenge pattern not found") self.plugin.fail(errmsg) - raise ValueError(errmsg) + raise AttributeError(errmsg) self.plugin.logDebug("AdsCaptcha challenge: %s" % challenge) @@ -214,10 +232,11 @@ class SolveMedia(CaptchaService): challenge = re.search(r'<input type=hidden name="adcopy_challenge" id="adcopy_challenge" value="([^"]+)">', html).group(1) server = "http://api.solvemedia.com/papi/media" - except: + + except AttributeError: errmsg = _("SolveMedia challenge pattern not found") self.plugin.fail(errmsg) - raise ValueError(errmsg) + raise AttributeError(errmsg) self.plugin.logDebug("SolveMedia challenge: %s" % challenge) @@ -286,10 +305,11 @@ class AdYouLike(CaptchaService): 'callback': callback}) try: challenge = json_loads(re.search(callback + r'\s*\((.+?)\)', html).group(1)) - except: + + except AttributeError: errmsg = _("AdYouLike challenge pattern not found") self.plugin.fail(errmsg) - raise ValueError(errmsg) + raise AttributeError(errmsg) self.plugin.logDebug("AdYouLike challenge: %s" % challenge) @@ -316,10 +336,11 @@ class AdYouLike(CaptchaService): try: instructions_visual = challenge['translations'][server['all']['lang']]['instructions_visual'] result = re.search(u'«(.+?)»', instructions_visual).group(1).strip() - except: + + except AttributeError: errmsg = _("AdYouLike result not found") self.plugin.fail(errmsg) - raise ValueError(errmsg) + raise AttributeError(errmsg) result = {'_ayl_captcha_engine' : "adyoulike", '_ayl_env' : server['all']['env'], diff --git a/module/plugins/internal/MultiHook.py b/module/plugins/internal/MultiHook.py index ea9f32673..202868175 100644 --- a/module/plugins/internal/MultiHook.py +++ b/module/plugins/internal/MultiHook.py @@ -9,12 +9,15 @@ from module.utils import remove_chars class MultiHook(Hook): __name__ = "MultiHook" __type__ = "hook" - __version__ = "0.29" + __version__ = "0.30" - __config__ = [("mode" , "all;listed;unlisted", "Use for plugins (if supported)" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed", "bool" , "Revert to standard download if download fails", False), - ("interval" , "int" , "Reload interval in hours (0 to disable)" , 12 )] + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), + ("revertfailed" , "bool" , "Revert to standard download if fails", True ), + ("retry" , "int" , "Number of retries before revert" , 10 ), + ("retryinterval" , "int" , "Retry interval in minutes" , 1 ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] __description__ = """Hook plugin for multi hoster/crypter""" __license__ = "GPLv3" @@ -22,45 +25,68 @@ class MultiHook(Hook): ("Walter Purcaro", "vuolter@gmail.com")] - MIN_INTERVAL = 12 * 60 * 60 #: reload plugins every 12h + MIN_INTERVAL = 1 * 60 * 60 - PLUGIN_REPLACEMENTS = [("1fichier.com" , "onefichier.com"), - ("2shared.com" , "twoshared.com" ), - ("4shared.com" , "fourshared.com"), - ("cloudnator.com" , "shragle.com" ), - ("easy-share.com" , "crocko.com" ), - ("fileparadox.com", "fileparadox.in"), - ("freakshare.net" , "freakshare.com"), - ("hellshare.com" , "hellshare.cz" ), - ("ifile.it" , "filecloud.io" ), - ("nowdownload.ch" , "nowdownload.sx"), - ("nowvideo.co" , "nowvideo.sx" ), - ("putlocker.com" , "firedrive.com" ), - ("share-rapid.cz" , "multishare.cz" ), - ("sharerapid.cz" , "multishare.cz" ), - ("ul.to" , "uploaded.to" ), - ("uploaded.net" , "uploaded.to" )] + DOMAIN_REPLACEMENTS = [(r'\d+.+' , "_\0" ), + (r'bayfiles\.net' , "bayfiles.com" ), + (r'cloudnator\.com' , "shragle.com" ), + (r'dfiles\.eu' , "depositfiles.com"), + (r'easy-share\.com' , "crocko.com" ), + (r'freakshare\.net' , "freakshare.com" ), + (r'hellshare\.com' , "hellshare.cz" ), + (r'ifile\.it' , "filecloud.io" ), + (r'nowdownload\.\w+', "nowdownload.sx" ), + (r'nowvideo\.\w+' , "nowvideo.sx" ), + (r'putlocker\.com' , "firedrive.com" ), + (r'share-?rapid\.cz', "multishare.cz" ), + (r'ul\.to' , "uploaded.to" ), + (r'uploaded\.net' , "uploaded.to" ), + (r'uploadhero\.co' , "uploadhero.com" ), + (r'zshares\.net' , "zshare.net" )] def setup(self): - self.account = None - self.type = self.core.pluginManager.findPlugin(self.__name__)[1] or "hoster" self.plugins = [] self.supported = [] self.new_supported = [] + self.account = None + self.pluginclass = None + self.pluginmodule = None + self.pluginname = None + self.plugintype = None - def coreReady(self): - self.account = self.core.accountManager.getAccountPlugin(self.__name__) + self._initPlugin() + + + def _initPlugin(self): + plugin, type = self.core.pluginManager.findPlugin(self.__name__) + + if not plugin: + self.logWarning("Hook plugin will be deactivated due missing plugin reference") + self.setConfig('activated', False) + else: + self.pluginname = self.__name__ + self.plugintype = type + self.pluginmodule = self.core.pluginManager.loadModule(type, self.__name__) + self.pluginclass = getattr(self.pluginmodule, self.__name__) + + + def _loadAccount(self): + self.account = self.core.accountManager.getAccountPlugin(self.pluginname) if self.account and not self.account.canUse(): self.account = None - if not self.account: - self.logWarning("MultiHook will be deactivated due missing account reference") + if not self.account and hasattr(self.pluginclass, "LOGIN_ACCOUNT") and not self.pluginclass.LOGIN_ACCOUNT: + self.logWarning("Hook plugin will be deactivated due missing account reference") self.setConfig('activated', False) + def coreReady(self): + self._loadAccount() + + def getURL(self, *args, **kwargs): #@TODO: Remove in 0.4.10 """ see HTTPRequest for argument list """ h = pyreq.getHTTPRequest(timeout=120) @@ -81,19 +107,19 @@ class MultiHook(Hook): return default - def pluginCached(self): + def pluginsCached(self): if not self.plugins: try: - pluginset = self.pluginSet(self.getHosters() if self.type == "hoster" else self.getCrypters()) + pluginset = self._pluginSet(self.getHosters() if self.plugintype == "hoster" else self.getCrypters()) except Exception, e: self.logError(e) return [] try: - configmode = self.getConfig("mode", 'all') + configmode = self.getConfig("pluginmode", 'all') if configmode in ("listed", "unlisted"): pluginlist = self.getConfig("pluginlist", '').replace('|', ',').replace(';', ',').split(',') - configset = self.pluginSet(pluginlist) + configset = self._pluginSet(pluginlist) if configmode == "listed": pluginset &= configset @@ -108,13 +134,14 @@ class MultiHook(Hook): return self.plugins - def pluginSet(self, plugins): + def _pluginSet(self, plugins): plugins = set((str(x).strip().lower() for x in plugins)) - for rep in self.PLUGIN_REPLACEMENTS: - if rep[0] in plugins: - plugins.remove(rep[0]) - plugins.add(rep[1]) + for rf, rt in self.DOMAIN_REPLACEMENTS: + regex = re.compile(rf) + for p in filter(lambda x: regex.match(x), plugins): + plugins.remove(p) + plugins.add(re.sub(rf, rt, p)) plugins.discard('') @@ -139,9 +166,7 @@ class MultiHook(Hook): def periodical(self): """reload plugin list periodically""" - self.interval = max(self.getConfig("interval", 0), self.MIN_INTERVAL) - - self.logInfo(_("Reloading supported %s list") % self.type) + self.logInfo(_("Reloading supported %s list") % self.plugintype) old_supported = self.supported @@ -158,18 +183,24 @@ class MultiHook(Hook): for plugin in old_supported: self.unloadPlugin(plugin) + if self.getConfig("reload", True): + self.interval = max(self.getConfig("reloadinterval", 12), self.MIN_INTERVAL) + else: + self.core.scheduler.removeJob(self.cb) + self.cb = None + def overridePlugins(self): excludedList = [] - if self.type == "hoster": + if self.plugintype == "hoster": pluginMap = dict((name.lower(), name) for name in self.core.pluginManager.hosterPlugins.iterkeys()) accountList = [account.type.lower() for account in self.core.api.getAccounts(False) if account.valid and account.premium] else: pluginMap = {} accountList = [name[::-1].replace("Folder"[::-1], "", 1).lower()[::-1] for name in self.core.pluginManager.crypterPlugins.iterkeys()] - for plugin in self.pluginCached(): + for plugin in self.pluginsCached(): name = remove_chars(plugin, "-.") if name in accountList: @@ -181,42 +212,39 @@ class MultiHook(Hook): self.new_supported.append(plugin) if not self.supported and not self.new_supported: - self.logError(_("No %s loaded") % self.type) + self.logError(_("No %s loaded") % self.plugintype) return - module = self.core.pluginManager.getPlugin(self.__name__) - klass = getattr(module, self.__name__) - # inject plugin plugin - self.logDebug("Overwritten %ss: %s" % (self.type, ", ".join(sorted(self.supported)))) + self.logDebug("Overwritten %ss: %s" % (self.plugintype, ", ".join(sorted(self.supported)))) for plugin in self.supported: - hdict = self.core.pluginManager.plugins[self.type][plugin] - hdict['new_module'] = module - hdict['new_name'] = self.__name__ + hdict = self.core.pluginManager.plugins[self.plugintype][plugin] + hdict['new_module'] = self.pluginmodule + hdict['new_name'] = self.pluginname if excludedList: - self.logInfo(_("%ss not overwritten: %s") % (self.type.capitalize(), ", ".join(sorted(excludedList)))) + self.logInfo(_("%ss not overwritten: %s") % (self.plugintype.capitalize(), ", ".join(sorted(excludedList)))) if self.new_supported: plugins = sorted(self.new_supported) - self.logDebug("New %ss: %s" % (self.type, ", ".join(plugins))) + self.logDebug("New %ss: %s" % (self.plugintype, ", ".join(plugins))) # create new regexp regexp = r'.*(%s).*' % "|".join([x.replace(".", "\.") for x in plugins]) - if hasattr(klass, "__pattern__") and isinstance(klass.__pattern__, basestring) and '://' in klass.__pattern__: - regexp = r'%s|%s' % (klass.__pattern__, regexp) + if hasattr(self.pluginclass, "__pattern__") and isinstance(self.pluginclass.__pattern__, basestring) and '://' in self.pluginclass.__pattern__: + regexp = r'%s|%s' % (self.pluginclass.__pattern__, regexp) self.logDebug("Regexp: %s" % regexp) - hdict = self.core.pluginManager.plugins[self.type][self.__name__] + hdict = self.core.pluginManager.plugins[self.plugintype][self.pluginname] hdict['pattern'] = regexp hdict['re'] = re.compile(regexp) def unloadPlugin(self, plugin): - hdict = self.core.pluginManager.plugins[self.type][plugin] + hdict = self.core.pluginManager.plugins[self.plugintype][plugin] if "module" in hdict: del hdict['module'] @@ -231,18 +259,24 @@ class MultiHook(Hook): self.unloadPlugin(plugin) # reset pattern - klass = getattr(self.core.pluginManager.getPlugin(self.__name__), self.__name__) - hdict = self.core.pluginManager.plugins[self.type][self.__name__] + hdict = self.core.pluginManager.plugins[self.plugintype][self.pluginname] - hdict['pattern'] = getattr(klass, "__pattern__", r'^unmatchable$') + hdict['pattern'] = getattr(self.pluginclass, "__pattern__", r'^unmatchable$') hdict['re'] = re.compile(hdict['pattern']) def downloadFailed(self, pyfile): """remove plugin override if download fails but not if file is offline/temp.offline""" - if pyfile.hasStatus("failed") and self.getConfig("revertfailed", True): - hdict = self.core.pluginManager.plugins[self.type][pyfile.pluginname] - if "new_name" in hdict and hdict['new_name'] == self.__name__: + if pyfile.status != 8 or not self.getConfig("revertfailed", True): + return + + hdict = self.core.pluginManager.plugins[self.plugintype][pyfile.pluginname] + if "new_name" in hdict and hdict['new_name'] == self.pluginname: + if pyfile.error == "MultiHook": self.logDebug("Unload MultiHook", pyfile.pluginname, hdict) self.unloadPlugin(pyfile.pluginname) pyfile.setStatus("queued") + else: + retries = max(self.getConfig("retry", 10), 0) + wait_time = max(self.getConfig("retryinterval", 1), 0) + pyfile.plugin.retry(retries, wait_time, "MultiHook") diff --git a/module/plugins/internal/MultiHoster.py b/module/plugins/internal/MultiHoster.py index 60320399a..ae06eaf4b 100644 --- a/module/plugins/internal/MultiHoster.py +++ b/module/plugins/internal/MultiHoster.py @@ -8,7 +8,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, r class MultiHoster(SimpleHoster): __name__ = "MultiHoster" __type__ = "hoster" - __version__ = "0.29" + __version__ = "0.30" __pattern__ = r'^unmatchable$' @@ -17,12 +17,14 @@ class MultiHoster(SimpleHoster): __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + CHECK_TRAFFIC = True LOGIN_ACCOUNT = True def setup(self): - self.chunkLimit = 1 - self.multiDL = self.premium + self.chunkLimit = 1 + self.multiDL = bool(self.account) + self.resumeDownload = self.premium def prepare(self): @@ -76,7 +78,8 @@ class MultiHoster(SimpleHoster): if self.premium and (not self.CHECK_TRAFFIC or self.checkTrafficLeft()): self.logDebug("Handled as premium download") self.handlePremium() - else: + + elif not self.LOGIN_ACCOUNT or (not self.CHECK_TRAFFIC or self.checkTrafficLeft()): self.logDebug("Handled as free download") self.handleFree() @@ -84,11 +87,11 @@ class MultiHoster(SimpleHoster): self.checkFile() - def handlePremium(self, pyfile=None): + def handlePremium(self, pyfile): return self.handleFree(pyfile) - def handleFree(self, pyfile=None): + def handleFree(self, pyfile): if self.premium: raise NotImplementedError else: diff --git a/module/plugins/internal/SimpleCrypter.py b/module/plugins/internal/SimpleCrypter.py index bfc473801..e16e45405 100644 --- a/module/plugins/internal/SimpleCrypter.py +++ b/module/plugins/internal/SimpleCrypter.py @@ -12,7 +12,7 @@ from module.utils import fixup class SimpleCrypter(Crypter, SimpleHoster): __name__ = "SimpleCrypter" __type__ = "crypter" - __version__ = "0.37" + __version__ = "0.38" __pattern__ = r'^unmatchable$' __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), #: Overrides core.config['general']['folder_per_package'] @@ -82,6 +82,8 @@ class SimpleCrypter(Crypter, SimpleHoster): def prepare(self): + self.pyfile.error = "" #@TODO: Remove in 0.4.10 + self.info = {} self.links = [] #@TODO: Move to hoster class in 0.4.10 diff --git a/module/plugins/internal/SimpleDereferer.py b/module/plugins/internal/SimpleDereferer.py index 04d63658e..53b80f827 100644 --- a/module/plugins/internal/SimpleDereferer.py +++ b/module/plugins/internal/SimpleDereferer.py @@ -5,13 +5,13 @@ import re from urllib import unquote from module.plugins.Crypter import Crypter -from module.plugins.internal.SimpleHoster import _isDirectLink, set_cookies +from module.plugins.internal.SimpleHoster import directLink, set_cookies class SimpleDereferer(Crypter): __name__ = "SimpleDereferer" __type__ = "crypter" - __version__ = "0.02" + __version__ = "0.03" __pattern__ = r'^unmatchable$' __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), @@ -45,7 +45,7 @@ class SimpleDereferer(Crypter): def decrypt(self, pyfile): - link = _isDirectLink(pyfile.url) + link = directLink(self, pyfile.url) if not link: try: diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index c87a6160f..991dc6240 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -10,6 +10,7 @@ from urlparse import urljoin, urlparse from module.PyFile import statusMap as _statusMap from module.network.CookieJar import CookieJar +from module.network.HTTPRequest import BadHeader from module.network.RequestFactory import getURL from module.plugins.Hoster import Hoster from module.plugins.Plugin import Fail @@ -126,7 +127,7 @@ def timestamp(): #@TODO: Move to hoster class in 0.4.10 -def _isDirectLink(self, url, resumable=False): +def directLink(self, url, resumable=False): link = "" for i in xrange(5 if resumable else 1): @@ -182,7 +183,7 @@ def secondsToMidnight(gmt=0): class SimpleHoster(Hoster): __name__ = "SimpleHoster" __type__ = "hoster" - __version__ = "0.90" + __version__ = "0.91" __pattern__ = r'^unmatchable$' @@ -244,18 +245,32 @@ class SimpleHoster(Hoster): CHECK_TRAFFIC = False #: Set to True to force checking traffic left for premium account DIRECT_LINK = None #: Set to True to looking for direct link (as defined in handleDirect method), set to None to do it if self.account is True else False 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 @classmethod - def parseInfos(cls, urls): + def parseInfos(cls, urls): #@TODO: Built-in in 0.4.10 core, then remove from plugins for url in urls: url = replace_patterns(url, cls.FILE_URL_REPLACEMENTS if hasattr(cls, "FILE_URL_REPLACEMENTS") else cls.URL_REPLACEMENTS) #@TODO: Remove FILE_URL_REPLACEMENTS check in 0.4.10 yield cls.getInfo(url) @classmethod + def apiInfo(cls, url="", get={}, post={}): + url = unquote(url) + return {'name' : (urlparse(url).path.split('/')[-1] + or urlparse(url).query.split('&', 1)[0].split('=', 1)[1] + or _("Unknown")), + 'size' : 0, + 'status': 3, + 'url' : url} + + + @classmethod def getInfo(cls, url="", html=""): - info = {'name': urlparse(unquote(url)).path.split('/')[-1] or _("Unknown"), 'size': 0, 'status': 3, 'url': url} + info = cls.apiInfo(url) online = False try: @@ -268,7 +283,7 @@ class SimpleHoster(Hoster): info['error'] = "missing url" info['status'] = 1 - else: + elif info['status'] is 3: try: html = getURL(url, cookies=cls.COOKIES, decode=not cls.TEXT_ENCODING) @@ -343,11 +358,16 @@ class SimpleHoster(Hoster): def prepare(self): + self.pyfile.error = "" #@TODO: Remove in 0.4.10 + self.info = {} self.link = "" #@TODO: Move to hoster class in 0.4.10 self.directDL = False #@TODO: Move to hoster class in 0.4.10 self.multihost = False #@TODO: Move to hoster class in 0.4.10 + if self.LOGIN_ACCOUNT and not self.account: + self.fail(_("Required account not found")) + self.req.setOption("timeout", 120) if isinstance(self.COOKIES, list): @@ -399,7 +419,7 @@ class SimpleHoster(Hoster): self.logDebug("Handled as premium download") self.handlePremium() - else: + elif not self.LOGIN_ACCOUNT or (not self.CHECK_TRAFFIC or self.checkTrafficLeft()): self.logDebug("Handled as free download") self.handleFree() @@ -420,15 +440,12 @@ class SimpleHoster(Hoster): elif not self.lastDownload or not exists(fs_encode(self.lastDownload)): self.lastDownload = "" - - errmsg = _("No file downloaded") - if 'error' in self.info: - self.fail(errmsg, self.info['error']) - else: - self.fail(errmsg) + self.fail(errmsg, self.pyfile.error or _("No file downloaded")) else: - rules = {'empty file': re.compile(r"^$")} + rules = {'empty file': re.compile(r'\A\Z'), + 'html file' : re.compile(r'\A\s*<!DOCTYPE html'), + 'html error': re.compile(r'\A\s*(<.+>)?\d{3}[^\d]*')} if hasattr(self, 'ERROR_PATTERN'): rules['error'] = re.compile(self.ERROR_PATTERN) @@ -529,7 +546,7 @@ class SimpleHoster(Hoster): def handleDirect(self, pyfile): - link = _isDirectLink(self, pyfile.url, self.resumeDownload) + link = self.directLink(pyfile.url, self.resumeDownload) if link: self.logInfo(_("Direct download link detected")) @@ -543,9 +560,9 @@ class SimpleHoster(Hoster): pass - def handleFree(self, pyfile=None): + def handleFree(self, pyfile): if not hasattr(self, 'LINK_FREE_PATTERN'): - self.fail(_("Free download not implemented")) + self.logError(_("Free download not implemented")) try: m = re.search(self.LINK_FREE_PATTERN, self.html) @@ -558,9 +575,11 @@ class SimpleHoster(Hoster): self.fail(e) - def handlePremium(self, pyfile=None): + def handlePremium(self, pyfile): if not hasattr(self, 'LINK_PREMIUM_PATTERN'): - self.fail(_("Premium download not implemented")) + self.logError(_("Premium download not implemented")) + self.logDebug("Handled as free download") + self.handleFree() try: m = re.search(self.LINK_PREMIUM_PATTERN, self.html) diff --git a/module/plugins/internal/XFSAccount.py b/module/plugins/internal/XFSAccount.py index 2784ecd0b..263d78ff8 100644 --- a/module/plugins/internal/XFSAccount.py +++ b/module/plugins/internal/XFSAccount.py @@ -12,7 +12,7 @@ from module.plugins.internal.SimpleHoster import parseHtmlForm, set_cookies class XFSAccount(Account): __name__ = "XFSAccount" __type__ = "account" - __version__ = "0.33" + __version__ = "0.34" __description__ = """XFileSharing account plugin""" __license__ = "GPLv3" @@ -35,7 +35,7 @@ class XFSAccount(Account): LEECH_TRAFFIC_PATTERN = r'Leech Traffic left:<b>.*?(?P<S>[\d.,]+|[Uu]nlimited)\s*(?:(?P<U>[\w^_]+)\s*)?</b>' LEECH_TRAFFIC_UNIT = "MB" #: used only if no group <U> was found - LOGIN_FAIL_PATTERN = r'>\s*(Incorrect Login or Password|Error<)' + LOGIN_FAIL_PATTERN = r'Incorrect Login or Password|account was banned|Error<' def __init__(self, manager, accounts): #@TODO: remove in 0.4.10 @@ -76,10 +76,10 @@ class XFSAccount(Account): self.logDebug("Valid until: %s" % validuntil) if validuntil > mktime(gmtime()): - premium = True + premium = True trafficleft = -1 else: - premium = False + premium = False validuntil = None #: registered account type (not premium) else: self.logDebug("VALID_UNTIL_PATTERN not found") diff --git a/module/plugins/internal/XFSCrypter.py b/module/plugins/internal/XFSCrypter.py index 4b57dab90..3cb837aac 100644 --- a/module/plugins/internal/XFSCrypter.py +++ b/module/plugins/internal/XFSCrypter.py @@ -16,7 +16,6 @@ class XFSCrypter(SimpleCrypter): HOSTER_DOMAIN = None - HOSTER_NAME = None URL_REPLACEMENTS = [(r'&?per_page=\d+', ""), (r'[?/&]+$', ""), (r'(.+/[^?]+)$', r'\1?'), (r'$', r'&per_page=10000')] diff --git a/module/plugins/internal/XFSHoster.py b/module/plugins/internal/XFSHoster.py index e15504d16..873df8989 100644 --- a/module/plugins/internal/XFSHoster.py +++ b/module/plugins/internal/XFSHoster.py @@ -15,7 +15,7 @@ from module.utils import html_unescape class XFSHoster(SimpleHoster): __name__ = "XFSHoster" __type__ = "hoster" - __version__ = "0.34" + __version__ = "0.35" __pattern__ = r'^unmatchable$' @@ -27,7 +27,6 @@ class XFSHoster(SimpleHoster): HOSTER_DOMAIN = None - HOSTER_NAME = None TEXT_ENCODING = False COOKIES = [(HOSTER_DOMAIN, "lang", "english")] @@ -66,9 +65,6 @@ class XFSHoster(SimpleHoster): if not self.HOSTER_DOMAIN: self.fail(_("Missing HOSTER_DOMAIN")) - if not self.HOSTER_NAME: - self.HOSTER_NAME = "".join([str.capitalize() for str in self.HOSTER_DOMAIN.split('.')]) - if not self.LINK_PATTERN: pattern = r'(https?://(www\.)?([^/]*?%s|\d+\.\d+\.\d+\.\d+)(\:\d+)?(/d/|(/files)?/\d+/\w+/).+?)["\'<]' self.LINK_PATTERN = pattern % self.HOSTER_DOMAIN.replace('.', '\.') @@ -82,10 +78,8 @@ class XFSHoster(SimpleHoster): self.directDL = bool(self.premium) - def handleFree(self, pyfile=None): - link = self.getDownloadLink() - - if link: + def downloadLink(self, link): + if link and isinstance(link, basestring): if self.captcha: self.correctCaptcha() @@ -101,11 +95,7 @@ class XFSHoster(SimpleHoster): self.fail(_("Download link not found")) - def handlePremium(self, pyfile=None): - return self.handleFree(pyfile) - - - def getDownloadLink(self): + def handleFree(self, pyfile): for i in xrange(1, 6): self.logDebug("Getting download link: #%d" % i) @@ -119,7 +109,7 @@ class XFSHoster(SimpleHoster): self.req.http.c.setopt(FOLLOWLOCATION, 0) - self.html = self.load(self.pyfile.url, post=data, ref=True, decode=True) + self.html = self.load(pyfile.url, post=data, ref=True, decode=True) self.req.http.c.setopt(FOLLOWLOCATION, 1) @@ -136,7 +126,11 @@ class XFSHoster(SimpleHoster): self.errmsg = None - return m.group(1).strip() #@TODO: Remove .strip() in 0.4.10 + self.link = m.group(1).strip() #@TODO: Remove .strip() in 0.4.10 + + + def handlePremium(self, pyfile): + return self.handleFree(pyfile) def handleMulti(self, pyfile): |