diff options
| -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): | 
