diff options
Diffstat (limited to 'pyload/plugin')
28 files changed, 117 insertions, 224 deletions
| diff --git a/pyload/plugin/OCR.py b/pyload/plugin/OCR.py index 01ba6d534..df32b9f23 100644 --- a/pyload/plugin/OCR.py +++ b/pyload/plugin/OCR.py @@ -11,7 +11,7 @@ except ImportError:  import logging  import os  import subprocess -#import tempfile +# import tempfile  from pyload.plugin.Plugin import Base  from pyload.utils import fs_join @@ -20,32 +20,27 @@ from pyload.utils import fs_join  class OCR(Base):      __name    = "OCR"      __type    = "ocr" -    __version = "0.11" +    __version = "0.12"      __description = """OCR base plugin"""      __license     = "GPLv3"      __authors     = [("pyLoad Team", "admin@pyload.org")] -      def __init__(self):          self.logger = logging.getLogger("log") -      def load_image(self, image):          self.image = Image.open(image)          self.pixels = self.image.load()          self.result_captcha = '' -      def deactivate(self):          """delete all tmp images"""          pass -      def threshold(self, value):          self.image = self.image.point(lambda a: a * value + 10) -      def run(self, command):          """Run a command""" @@ -56,14 +51,13 @@ class OCR(Base):          popen.stderr.close()          self.logger.debug("Tesseract ReturnCode %s Output: %s" % (popen.returncode, output)) - -    def run_tesser(self, subset=False, digits=True, lowercase=True, uppercase=True): -        #tmpTif = tempfile.NamedTemporaryFile(suffix=".tif") +    def run_tesser(self, subset=False, digits=True, lowercase=True, uppercase=True, pagesegmode=None): +        # tmpTif = tempfile.NamedTemporaryFile(suffix=".tif")          try:              tmpTif = open(fs_join("tmp", "tmpTif_%s.tif" % self.__class__.__name__), "wb")              tmpTif.close() -            #tmpTxt = tempfile.NamedTemporaryFile(suffix=".txt") +            # tmpTxt = tempfile.NamedTemporaryFile(suffix=".txt")              tmpTxt = open(fs_join("tmp", "tmpTxt_%s.txt" % self.__class__.__name__), "wb")              tmpTxt.close() @@ -79,10 +73,13 @@ class OCR(Base):          else:              tessparams = ["tesseract"] -        tessparams.extend([os.path.abspath(tmpTif.name), os.path.abspath(tmpTxt.name).replace(".txt", "")] ) +        tessparams.extend([os.path.abspath(tmpTif.name), os.path.abspath(tmpTxt.name).replace(".txt", "")]) + +        if pagesegmode: +            tessparams.extend(["-psm", str(pagesegmode)])          if subset and (digits or lowercase or uppercase): -            #tmpSub = tempfile.NamedTemporaryFile(suffix=".subset") +            # tmpSub = tempfile.NamedTemporaryFile(suffix=".subset")              with open(fs_join("tmp", "tmpSub_%s.subset" % self.__class__.__name__), "wb") as tmpSub:                  tmpSub.write("tessedit_char_whitelist ") @@ -116,18 +113,15 @@ class OCR(Base):          except Exception:              pass -      def get_captcha(self, name):          raise NotImplementedError -      def to_greyscale(self):          if self.image.mode != 'L':              self.image = self.image.convert('L')          self.pixels = self.image.load() -      def eval_black_white(self, limit):          self.pixels = self.image.load()          w, h = self.image.size @@ -138,7 +132,6 @@ class OCR(Base):                  else:                      self.pixels[x, y] = 0 -      def clean(self, allowed):          pixels = self.pixels @@ -184,7 +177,6 @@ class OCR(Base):          self.pixels = pixels -      def derotate_by_average(self):          """rotate by checking each angle and guess most suitable""" @@ -258,7 +250,6 @@ class OCR(Base):          self.pixels = pixels -      def split_captcha_letters(self):          captcha = self.image          started = False @@ -298,7 +289,6 @@ class OCR(Base):          return letters -      def correct(self, values, var=None):          if var:              result = var diff --git a/pyload/plugin/Plugin.py b/pyload/plugin/Plugin.py index 6a39507fd..af70232e0 100644 --- a/pyload/plugin/Plugin.py +++ b/pyload/plugin/Plugin.py @@ -59,44 +59,38 @@ class Base(object):          #: Core instance          self.core = core -      def _log(self, type, args): -        msg = " | ".join([encode(a).strip() for a in args if a]) +        msg = " | ".join([encode(str(a)).strip() for a in args if a])          logger = getattr(self.core.log, type)          logger("%s: %s" % (self.__class__.__name__, msg or _("%s MARK" % type.upper()))) -      def logDebug(self, *args):          if self.core.debug:              return self._log("debug", args) -      def logInfo(self, *args):          return self._log("info", args) -      def logWarning(self, *args):          return self._log("warning", args) -      def logError(self, *args):          return self._log("error", args) -      def logCritical(self, *args):          return self._log("critical", args) +    def grtPluginType(self): +        return getattr(self, "_%s__type" % self.__class__.__name__)      def getPluginConfSection(self):          return "%s_%s" % (self.__class__.__name__, getattr(self, "_%s__type" % self.__class__.__name__)) -      #: Deprecated method      def setConf(self, option, value):          """ see `setConfig` """          self.setConfig(option, value) -      def setConfig(self, option, value):          """ Set config value for current plugin @@ -106,12 +100,10 @@ class Base(object):          """          self.core.config.setPlugin(self.getPluginConfSection(), option, value) -      #: Deprecated method      def getConf(self, option):          """ see `getConfig` """ -        return self.getConfig(option) - +        return self.core.config.getPlugin(self.getPluginConfSection(), option)      def getConfig(self, option):          """ Returns config value for current plugin @@ -121,29 +113,24 @@ class Base(object):          """          return self.core.config.getPlugin(self.getPluginConfSection(), option) -      def setStorage(self, key, value):          """ Saves a value persistently to the database """          self.core.db.setStorage(self.getPluginConfSection(), key, value) -      def store(self, key, value):          """ same as `setStorage` """          self.core.db.setStorage(self.getPluginConfSection(), key, value) -      def getStorage(self, key=None, default=None):          """ Retrieves saved value or dict of all saved entries if key is None """          if key:              return self.core.db.getStorage(self.getPluginConfSection(), key) or default          return self.core.db.getStorage(self.getPluginConfSection(), key) -      def retrieve(self, *args, **kwargs):          """ same as `getStorage` """          return self.getStorage(*args, **kwargs) -      def delStorage(self, key):          """ Delete entry in db """          self.core.db.delStorage(self.__class__.__name__, key) @@ -164,13 +151,11 @@ class Plugin(Base):      __description = """Base plugin"""      __license     = "GPLv3"      __authors     = [("RaNaN", "RaNaN@pyload.org"), -                       ("spoob", "spoob@pyload.org"), -                       ("mkaay", "mkaay@mkaay.de")] - +                     ("spoob", "spoob@pyload.org"), +                     ("mkaay", "mkaay@mkaay.de")]      info = {}  #: file info dict -      def __init__(self, pyfile):          Base.__init__(self, pyfile.m.core) @@ -207,10 +192,10 @@ class Plugin(Base):              self.user, data = self.account.selectAccount()              #: Browser instance, see `network.Browser`              self.req = self.account.getAccountRequest(self.user) -            self.chunkLimit = -1 # chunk limit, -1 for unlimited +            self.chunkLimit = -1  # chunk limit, -1 for unlimited              #: enables resume (will be ignored if server dont accept chunks)              self.resumeDownload = True -            self.multiDL = True  #every hoster with account should provide multiple downloads +            self.multiDL = True  # every hoster with account should provide multiple downloads              #: premium status              self.premium = self.account.isPremium(self.user)          else: @@ -219,7 +204,7 @@ class Plugin(Base):          #: associated pyfile instance, see `PyFile`          self.pyfile = pyfile -        self.thread = None # holds thread in future +        self.thread = None  # holds thread in future          #: location where the last call to download was saved          self.lastDownload = "" @@ -232,32 +217,27 @@ class Plugin(Base):          #: captcha task          self.cTask = None -        self.html = None  #@TODO: Move to hoster class in 0.4.10 +        self.html = None  # @TODO: Move to hoster class in 0.4.10          self.retries = 0          self.init() -      def getChunkCount(self):          if self.chunkLimit <= 0:              return self.core.config['download']['chunks']          return min(self.core.config['download']['chunks'], self.chunkLimit) -      def __call__(self):          return self.__class__.__name__ -      def init(self):          """initialize the plugin (in addition to `__init__`)"""          pass -      def setup(self):          """ setup for enviroment and other things, called before downloading (possibly more than one time)"""          pass -      def preprocessing(self, thread):          """ handles important things to do before starting """          self.thread = thread @@ -273,19 +253,16 @@ class Plugin(Base):          return self.process(self.pyfile) -      def process(self, pyfile):          """the 'main' method of every plugin, you **have to** overwrite it"""          raise NotImplementedError -      def resetAccount(self):          """ dont use account and retry download """          self.account = None          self.req = self.core.requestFactory.getRequest(self.__class__.__name__)          self.retry() -      def checksum(self, local_file=None):          """          return codes: @@ -299,13 +276,11 @@ class Plugin(Base):          return True, 10 -      def setReconnect(self, reconnect):          reconnect = bool(reconnect)          self.logDebug("Set wantReconnect to: %s (previous: %s)" % (reconnect, self.wantReconnect))          self.wantReconnect = reconnect -      def setWait(self, seconds, reconnect=None):          """Set a specific wait time later used with `wait` @@ -323,7 +298,6 @@ class Plugin(Base):          if reconnect is not None:              self.setReconnect(reconnect) -      def wait(self, seconds=None, reconnect=None):          """ waits the time previously set """ @@ -369,19 +343,16 @@ class Plugin(Base):          pyfile.status = status -      def fail(self, reason):          """ fail and give reason """          raise Fail(reason) -      def abort(self, reason=""):          """ abort and give reason """          if reason:              self.pyfile.error = str(reason)          raise Abort -      def error(self, reason="", type=""):          if not reason and not type:              type = "unknown" @@ -392,21 +363,18 @@ class Plugin(Base):          raise Fail(msg) -      def offline(self, reason=""):          """ fail and indicate file is offline """          if reason:              self.pyfile.error = str(reason)          raise Fail("offline") -      def tempOffline(self, reason=""):          """ fail and indicates file ist temporary offline, the core may take consequences """          if reason:              self.pyfile.error = str(reason)          raise Fail("temp. offline") -      def retry(self, max_tries=5, wait_time=1, reason=""):          """Retries and begin again from the beginning @@ -422,19 +390,16 @@ class Plugin(Base):          self.retries += 1          raise Retry(reason) -      def invalidCaptcha(self):          self.logError(_("Invalid captcha"))          if self.cTask:              self.cTask.invalid() -      def correctCaptcha(self):          self.logInfo(_("Correct captcha"))          if self.cTask:              self.cTask.correct() -      def decryptCaptcha(self, url, get={}, post={}, cookies=False, forceUser=False, imgtype='jpg',                         result_type='textual', timeout=290):          """ Loads a captcha and decrypts it with ocr, plugin, user input @@ -487,7 +452,7 @@ class Plugin(Base):              captchaManager.removeTask(task) -            if task.error and has_plugin: #ignore default error message since the user could use OCR +            if task.error and has_plugin:  # ignore default error message since the user could use OCR                  self.fail(_("Pil and tesseract not installed and no Client connected for captcha decrypting"))              elif task.error:                  self.fail(task.error) @@ -505,7 +470,6 @@ class Plugin(Base):          return result -      def load(self, url, get={}, post={}, ref=True, cookies=True, just_header=False, decode=False, follow_location=True, save_cookies=True):          """Load content at url and returns it @@ -526,7 +490,7 @@ class Plugin(Base):          if not url:              self.fail(_("No url given")) -        url = encode(url).strip()  #@NOTE: utf8 vs decode -> please use decode attribute in all future plugins +        url = encode(url).strip()  # @NOTE: utf8 vs decode -> please use decode attribute in all future plugins          if self.core.debug:              self.logDebug("Load url: " + url, *["%s=%s" % (key, val) for key, val in locals().iteritems() if key not in ("self", "url")]) @@ -552,7 +516,7 @@ class Plugin(Base):                  self.logError(e)          if just_header: -            #parse header +            # parse header              header = {"code": self.req.code}              for line in res.splitlines():                  line = line.strip() @@ -573,7 +537,6 @@ class Plugin(Base):          return res -      def download(self, url, get={}, post={}, ref=True, cookies=True, disposition=False):          """Downloads the content at url to download folder @@ -660,7 +623,6 @@ class Plugin(Base):          self.lastDownload = filename          return self.lastDownload -      def checkDownload(self, rules, api_size=0, max_size=50000, delete=True, read_size=0):          """ checks the content of the last downloaded file, re match is saved to `lastCheck` @@ -685,7 +647,7 @@ class Plugin(Base):          with open(lastDownload, "rb") as f:              content = f.read(read_size if read_size else -1) -        #produces encoding errors, better log to other file in the future? +        # produces encoding errors, better log to other file in the future?          #self.logDebug("Content: %s" % content)          for name, rule in rules.iteritems():              if isinstance(rule, basestring): @@ -701,14 +663,12 @@ class Plugin(Base):                      self.lastCheck = m                      return name -      def getPassword(self):          """ get the password the user provided in the package"""          password = self.pyfile.package().password          if not password: return ""          return password -      def checkForSameFiles(self, starting=False):          """ checks if same file was/is downloaded within same package @@ -720,10 +680,9 @@ class Plugin(Base):          for pyfile in self.core.files.cache.values():              if pyfile != self.pyfile and pyfile.name == self.pyfile.name and pyfile.package().folder == pack.folder: -                if pyfile.status in (0, 12): #finished or downloading +                if pyfile.status in (0, 12):  # finished or downloading                      raise SkipDownload(pyfile.pluginname) -                elif pyfile.status in ( -                5, 7) and starting: #a download is waiting/starting and was appenrently started before +                elif pyfile.status in (5, 7) and starting:  # a download is waiting/starting and was appenrently started before                      raise SkipDownload(pyfile.pluginname)          download_folder = self.core.config['general']['download_folder'] @@ -741,7 +700,6 @@ class Plugin(Base):              self.logDebug("File %s not skipped, because it does not exists." % self.pyfile.name) -      def clean(self):          """ clean everything and remove references """          if hasattr(self, "pyfile"): diff --git a/pyload/plugin/addon/UpdateManager.py b/pyload/plugin/addon/UpdateManager.py index 41a1d7f2c..34ef771c2 100644 --- a/pyload/plugin/addon/UpdateManager.py +++ b/pyload/plugin/addon/UpdateManager.py @@ -12,6 +12,7 @@ from operator import itemgetter  from pyload.network.RequestFactory import getURL  from pyload.plugin.Addon import Expose, Addon, threaded  from pyload.utils import fs_join +from pyload import __status_code__ as release_status  # Case-sensitive os.path.exists @@ -31,29 +32,30 @@ class UpdateManager(Addon):      __type    = "addon"      __version = "0.50" -    __config = [("activated"    , "bool", "Activated"                                , True ), -                  ("checkinterval", "int" , "Check interval in hours"                  , 8    ), -                  ("autorestart"  , "bool", "Auto-restart pyLoad when required"        , True ), -                  ("checkonstart" , "bool", "Check for updates on startup"             , True ), -                  ("checkperiod"  , "bool", "Check for updates periodically"           , True ), -                  ("reloadplugins", "bool", "Monitor plugin code changes in debug mode", True ), -                  ("nodebugupdate", "bool", "Don't update plugins in debug mode"       , False)] +    __config  = [("activated", "bool", "Activated", True), +                 ("checkinterval", "int", "Check interval in hours", 8), +                 ("autorestart", "bool", +                  "Auto-restart pyLoad when required", True), +                 ("checkonstart", "bool", "Check for updates on startup", True), +                 ("checkperiod", "bool", +                  "Check for updates periodically", True), +                 ("reloadplugins", "bool", +                  "Monitor plugin code changes in debug mode", True), +                 ("nodebugupdate", "bool", "Don't update plugins in debug mode", False)]      __description = """ Check for updates """      __license     = "GPLv3"      __authors     = [("Walter Purcaro", "vuolter@gmail.com")] -    SERVER_URL         = "http://updatemanager.pyload.org" +    SERVER_URL         = "http://updatemanager.pyload.org" if release_status == 5 else None      MIN_CHECK_INTERVAL = 3 * 60 * 60  #: 3 hours -      def activate(self):          if self.checkonstart:              self.update()          self.initPeriodical() -      def setup(self):          self.interval = 10          self.info     = {'pyload': False, 'version': None, 'plugins': False, 'last_check': time.time()} @@ -65,7 +67,6 @@ class UpdateManager(Addon):          else:              self.checkonstart = False -      def periodical(self):          if self.core.debug:              if self.getConfig('reloadplugins'): @@ -78,14 +79,13 @@ class UpdateManager(Addon):             and time.time() - max(self.MIN_CHECK_INTERVAL, self.getConfig('checkinterval') * 60 * 60) > self.info['last_check']:              self.update() -      @Expose      def autoreloadPlugins(self):          """ reload and reindex all modified plugins """          modules = filter(              lambda m: m and (m.__name__.startswith("module.plugins.") or                               m.__name__.startswith("userplugins.")) and -                             m.__name__.count(".") >= 2, sys.modules.itervalues() +            m.__name__.count(".") >= 2, sys.modules.itervalues()          )          reloads = [] @@ -108,7 +108,6 @@ class UpdateManager(Addon):          return True if self.core.pluginManager.reloadPlugins(reloads) else False -      def server_response(self):          try:              return getURL(self.SERVER_URL, get={'v': self.core.api.getServerVersion()}).splitlines() @@ -116,7 +115,6 @@ class UpdateManager(Addon):          except Exception:              self.logWarning(_("Unable to contact server to get updates")) -      @Expose      @threaded      def update(self): @@ -129,7 +127,6 @@ class UpdateManager(Addon):          else:              self.core.api.unpauseServer() -      def _update(self):          data = self.server_response() @@ -159,7 +156,6 @@ class UpdateManager(Addon):          #  2 = Plugins updated, but restart required          return exitcode -      def _updatePlugins(self, data):          """ check for plugin updates """ @@ -220,7 +216,7 @@ class UpdateManager(Addon):              plugins = getattr(self.core.pluginManager, "%sPlugins" % type) -            oldver = float(plugins[name]['v']) if name in plugins else None +            oldver = float(plugins[name]['version']) if name in plugins else None              newver = float(version)              if not oldver: @@ -230,8 +226,8 @@ class UpdateManager(Addon):              else:                  continue -            self.logInfo(_(msg) % {'type'  : type, -                                   'name'  : name, +            self.logInfo(_(msg) % {'type': type, +                                   'name': name,                                     'oldver': oldver,                                     'newver': newver})              try: @@ -239,10 +235,10 @@ class UpdateManager(Addon):                  m = VERSION.search(content)                  if m and m.group(2) == version: -                    with open(fs_join("userplugins", prefix, filename), "wb") as f: +                    with open(fs_join("userplugins", type, filename), "wb") as f:                          f.write(content) -                    updated.append((prefix, name)) +                    updated.append((type, name))                  else:                      raise Exception, _("Version mismatch") @@ -269,7 +265,6 @@ class UpdateManager(Addon):          # 2 = Plugins updated, but restart required          return exitcode -      @Expose      def removePlugins(self, type_plugins):          """ delete plugins from disk """ @@ -309,4 +304,5 @@ class UpdateManager(Addon):                          id = (type, name)                          removed.add(id) -        return list(removed)  #: return a list of the plugins successfully removed +        #: return a list of the plugins successfully removed +        return list(removed) diff --git a/pyload/plugin/captcha/AdYouLike.py b/pyload/plugin/captcha/AdYouLike.py index 42441ee86..83fc4e1a3 100644 --- a/pyload/plugin/captcha/AdYouLike.py +++ b/pyload/plugin/captcha/AdYouLike.py @@ -15,11 +15,9 @@ class AdYouLike(Captcha):      __license     = "GPLv3"      __authors     = [("Walter Purcaro", "vuolter@gmail.com")] -      AYL_PATTERN      = r'Adyoulike\.create\s*\((.+?)\)'      CALLBACK_PATTERN = r'(Adyoulike\.g\._jsonp_\d+)' -      def detect_key(self, html=None):          if not html:              if hasattr(self.plugin, "html") and self.plugin.html: @@ -39,7 +37,6 @@ class AdYouLike(Captcha):              self.logDebug("Ayl or callback not found")              return None -      def challenge(self, key=None, html=None):          if not key:              if self.detect_key(html): @@ -56,8 +53,8 @@ class AdYouLike(Captcha):          ayl = json_loads(ayl)          html = self.plugin.req.load("http://api-ayl.appspot.com/challenge", -                                    get={'key'     : ayl['adyoulike']['key'], -                                         'env'     : ayl['all']['env'], +                                    get={'key': ayl['adyoulike']['key'], +                                         'env': ayl['all']['env'],                                           'callback': callback})          try:              challenge = json_loads(re.search(callback + r'\s*\((.+?)\)', html).group(1)) @@ -71,7 +68,6 @@ class AdYouLike(Captcha):          return self.result(ayl, challenge), challenge -      def result(self, server, challenge):          # Adyoulike.g._jsonp_5579316662423138          # ({"translations":{"fr":{"instructions_visual":"Recopiez « Soonnight » ci-dessous :"}}, @@ -98,11 +94,11 @@ class AdYouLike(Captcha):              self.plugin.fail(errmsg)              raise AttributeError(errmsg) -        result = {'_ayl_captcha_engine' : "adyoulike", -                  '_ayl_env'            : server['all']['env'], -                  '_ayl_tid'            : challenge['tid'], +        result = {'_ayl_captcha_engine': "adyoulike", +                  '_ayl_env': server['all']['env'], +                  '_ayl_tid': challenge['tid'],                    '_ayl_token_challenge': challenge['token'], -                  '_ayl_response'       : response} +                  '_ayl_response': response}          self.logDebug("Result: %s" % result) diff --git a/pyload/plugin/captcha/ReCaptcha.py b/pyload/plugin/captcha/ReCaptcha.py index 4f35ed30b..410cb19de 100644 --- a/pyload/plugin/captcha/ReCaptcha.py +++ b/pyload/plugin/captcha/ReCaptcha.py @@ -18,14 +18,12 @@ class ReCaptcha(Captcha):      __description = """ReCaptcha captcha service plugin"""      __license     = "GPLv3"      __authors     = [("pyLoad Team", "admin@pyload.org"), -                       ("Walter Purcaro", "vuolter@gmail.com"), -                       ("zapp-brannigan", "fuerst.reinje@web.de")] - +                     ("Walter Purcaro", "vuolter@gmail.com"), +                     ("zapp-brannigan", "fuerst.reinje@web.de")]      KEY_V2_PATTERN = r'(?:data-sitekey=["\']|["\']sitekey["\']:\s*["\'])([\w-]+)'      KEY_V1_PATTERN = r'(?:recaptcha(?:/api|\.net)/(?:challenge|noscript)\?k=|Recaptcha\.create\s*\(\s*["\'])([\w-]+)' -      def detect_key(self, html=None):          if not html:              if hasattr(self.plugin, "html") and self.plugin.html: @@ -44,7 +42,6 @@ class ReCaptcha(Captcha):              self.logDebug("Key not found")              return None -      def challenge(self, key=None, html=None, version=None):          if not key:              if self.detect_key(html): @@ -66,7 +63,6 @@ class ReCaptcha(Captcha):              self.plugin.fail(errmsg)              raise TypeError(errmsg) -      def _challenge_v1(self, key):          html = self.plugin.req.load("http://www.google.com/recaptcha/api/challenge",                                      get={'k': key}) @@ -83,7 +79,6 @@ class ReCaptcha(Captcha):          return self.result(server, challenge), challenge -      def result(self, server, challenge):          result = self.plugin.decryptCaptcha("%simage" % server,                                              get={'c': challenge}, @@ -95,13 +90,12 @@ class ReCaptcha(Captcha):          return result -      def _collectApiInfo(self):          html = self.plugin.req.load("http://www.google.com/recaptcha/api.js")          a    = re.search(r'po.src = \'(.*?)\';', html).group(1)          vers = a.split("/")[5] -        self.logDebug("API version: %s" %vers) +        self.logDebug("API version: %s" % vers)          language = a.split("__")[1].split(".")[0] @@ -115,7 +109,6 @@ class ReCaptcha(Captcha):          return vers, language, jsh -      def _prepareTimeAndRpc(self):          self.plugin.req.load("http://www.google.com/recaptcha/api2/demo") @@ -131,7 +124,6 @@ class ReCaptcha(Captcha):          return millis, rpc -      def _challenge_v2(self, key, parent=None):          if parent is None:              try: @@ -183,7 +175,7 @@ class ReCaptcha(Captcha):          millis_captcha_loading = int(round(time.time() * 1000))          captcha_response       = self.plugin.decryptCaptcha("https://www.google.com/recaptcha/api2/payload", -                                                            get={'c':token4.group(1), 'k':key}, +                                                            get={'c': token4.group(1), 'k': key},                                                              cookies=True,                                                              forceUser=True)          response               = b64encode('{"response":"%s"}' % captcha_response) diff --git a/pyload/plugin/crypter/NCryptIn.py b/pyload/plugin/crypter/NCryptIn.py index 94808db3b..02427190e 100644 --- a/pyload/plugin/crypter/NCryptIn.py +++ b/pyload/plugin/crypter/NCryptIn.py @@ -6,7 +6,7 @@ import re  from Crypto.Cipher import AES  from pyload.plugin.Crypter import Crypter -from pyload.plugin.internal.captcha import ReCaptcha +from pyload.plugin.captcha.ReCaptcha import ReCaptcha  class NCryptIn(Crypter): diff --git a/pyload/plugin/crypter/SafelinkingNet.py b/pyload/plugin/crypter/SafelinkingNet.py index 0c93d6919..a949d17b1 100644 --- a/pyload/plugin/crypter/SafelinkingNet.py +++ b/pyload/plugin/crypter/SafelinkingNet.py @@ -6,7 +6,7 @@ from BeautifulSoup import BeautifulSoup  from pyload.utils import json_loads  from pyload.plugin.Crypter import Crypter -from pyload.plugin.internal.captcha import SolveMedia +from pyload.plugin.captcha.SolveMedia import SolveMedia  class SafelinkingNet(Crypter): diff --git a/pyload/plugin/hoster/BitshareCom.py b/pyload/plugin/hoster/BitshareCom.py index f4be88401..471951a9e 100644 --- a/pyload/plugin/hoster/BitshareCom.py +++ b/pyload/plugin/hoster/BitshareCom.py @@ -4,7 +4,7 @@ from __future__ import with_statement  import re -from pyload.plugin.internal.captcha import ReCaptcha +from pyload.plugin.captcha.ReCaptcha import ReCaptcha  from pyload.plugin.internal.SimpleHoster import SimpleHoster diff --git a/pyload/plugin/hoster/CatShareNet.py b/pyload/plugin/hoster/CatShareNet.py index 0aca297b8..f60208cc4 100644 --- a/pyload/plugin/hoster/CatShareNet.py +++ b/pyload/plugin/hoster/CatShareNet.py @@ -2,7 +2,7 @@  import re -from pyload.plugin.internal.captcha import ReCaptcha +from pyload.plugin.captcha.ReCaptcha import ReCaptcha  from pyload.plugin.internal.SimpleHoster import SimpleHoster diff --git a/pyload/plugin/hoster/CrockoCom.py b/pyload/plugin/hoster/CrockoCom.py index 55bb126cd..4bf549574 100644 --- a/pyload/plugin/hoster/CrockoCom.py +++ b/pyload/plugin/hoster/CrockoCom.py @@ -2,7 +2,7 @@  import re -from pyload.plugin.internal.captcha import ReCaptcha +from pyload.plugin.captcha.ReCaptcha import ReCaptcha  from pyload.plugin.internal.SimpleHoster import SimpleHoster diff --git a/pyload/plugin/hoster/DateiTo.py b/pyload/plugin/hoster/DateiTo.py index 6c160dfb9..251036ad2 100644 --- a/pyload/plugin/hoster/DateiTo.py +++ b/pyload/plugin/hoster/DateiTo.py @@ -2,7 +2,7 @@  import re -from pyload.plugin.internal.captcha import ReCaptcha +from pyload.plugin.captcha.ReCaptcha import ReCaptcha  from pyload.plugin.internal.SimpleHoster import SimpleHoster diff --git a/pyload/plugin/hoster/DepositfilesCom.py b/pyload/plugin/hoster/DepositfilesCom.py index 736350f0c..451adbdc0 100644 --- a/pyload/plugin/hoster/DepositfilesCom.py +++ b/pyload/plugin/hoster/DepositfilesCom.py @@ -4,7 +4,7 @@ import re  from urllib import unquote -from pyload.plugin.internal.captcha import ReCaptcha +from pyload.plugin.captcha.ReCaptcha import ReCaptcha  from pyload.plugin.internal.SimpleHoster import SimpleHoster diff --git a/pyload/plugin/hoster/DlFreeFr.py b/pyload/plugin/hoster/DlFreeFr.py index 83e7c5d77..568b6dfce 100644 --- a/pyload/plugin/hoster/DlFreeFr.py +++ b/pyload/plugin/hoster/DlFreeFr.py @@ -5,7 +5,7 @@ import re  from pyload.network.Browser import Browser  from pyload.network.CookieJar import CookieJar -from pyload.plugin.internal.captcha import AdYouLike +from pyload.plugin.captcha.AdYouLike import AdYouLike  from pyload.plugin.internal.SimpleHoster import SimpleHoster, replace_patterns  from pyload.utils import json_loads diff --git a/pyload/plugin/hoster/FilecloudIo.py b/pyload/plugin/hoster/FilecloudIo.py index 07a743292..2cbc472de 100644 --- a/pyload/plugin/hoster/FilecloudIo.py +++ b/pyload/plugin/hoster/FilecloudIo.py @@ -3,7 +3,7 @@  import re  from pyload.utils import json_loads -from pyload.plugin.internal.captcha import ReCaptcha +from pyload.plugin.captcha.ReCaptcha import ReCaptcha  from pyload.plugin.internal.SimpleHoster import SimpleHoster diff --git a/pyload/plugin/hoster/FilepostCom.py b/pyload/plugin/hoster/FilepostCom.py index 883c001ab..c5cfa1521 100644 --- a/pyload/plugin/hoster/FilepostCom.py +++ b/pyload/plugin/hoster/FilepostCom.py @@ -4,7 +4,7 @@ import re  import time  from pyload.utils import json_loads -from pyload.plugin.internal.captcha import ReCaptcha +from pyload.plugin.captcha.ReCaptcha import ReCaptcha  from pyload.plugin.internal.SimpleHoster import SimpleHoster diff --git a/pyload/plugin/hoster/FilerNet.py b/pyload/plugin/hoster/FilerNet.py index 3138780e4..7cefa6d9f 100644 --- a/pyload/plugin/hoster/FilerNet.py +++ b/pyload/plugin/hoster/FilerNet.py @@ -9,7 +9,7 @@ import re  from urlparse import urljoin -from pyload.plugin.internal.captcha import ReCaptcha +from pyload.plugin.captcha.ReCaptcha import ReCaptcha  from pyload.plugin.internal.SimpleHoster import SimpleHoster @@ -24,8 +24,7 @@ class FilerNet(SimpleHoster):      __description = """Filer.net hoster plugin"""      __license     = "GPLv3"      __authors     = [("stickell", "l.stickell@yahoo.it"), -                       ("Walter Purcaro", "vuolter@gmail.com")] - +                     ("Walter Purcaro", "vuolter@gmail.com")]      INFO_PATTERN    = r'<h1 class="page-header">Free Download (?P<N>\S+) <small>(?P<S>[\w.]+) (?P<U>[\w^_]+)</small></h1>'      OFFLINE_PATTERN = r'Nicht gefunden' @@ -34,7 +33,6 @@ class FilerNet(SimpleHoster):      LINK_FREE_PATTERN = LINK_PREMIUM_PATTERN = r'href="([^"]+)">Get download</a>' -      def handleFree(self, pyfile):          inputs = self.parseHtmlForm(input_names={'token': re.compile(r'.+')})[1]          if 'token' not in inputs: @@ -53,8 +51,8 @@ class FilerNet(SimpleHoster):          #@TODO: Check for v0.4.10          self.req.http.c.setopt(pycurl.FOLLOWLOCATION, 0)          self.load(pyfile.url, post={'recaptcha_challenge_field': challenge, -                                    'recaptcha_response_field' : response, -                                    'hash'                     : inputs['hash']}) +                                    'recaptcha_response_field': response, +                                    'hash': inputs['hash']})          self.req.http.c.setopt(pycurl.FOLLOWLOCATION, 1)          if 'location' in self.req.http.header.lower(): diff --git a/pyload/plugin/hoster/KingfilesNet.py b/pyload/plugin/hoster/KingfilesNet.py index a47defebc..af1d49390 100644 --- a/pyload/plugin/hoster/KingfilesNet.py +++ b/pyload/plugin/hoster/KingfilesNet.py @@ -2,7 +2,7 @@  import re -from pyload.plugin.internal.captcha import SolveMedia +from pyload.plugin.captcha.SolveMedia import SolveMedia  from pyload.plugin.internal.SimpleHoster import SimpleHoster @@ -17,8 +17,7 @@ class KingfilesNet(SimpleHoster):      __description = """Kingfiles.net hoster plugin"""      __license     = "GPLv3"      __authors     = [("zapp-brannigan", "fuerst.reinje@web.de"), -                       ("Walter Purcaro", "vuolter@gmail.com")] - +                     ("Walter Purcaro", "vuolter@gmail.com")]      NAME_PATTERN = r'name="fname" value="(?P<N>.+?)">'      SIZE_PATTERN = r'>Size: .+?">(?P<S>[\d.,]+) (?P<U>[\w^_]+)' @@ -29,12 +28,10 @@ class KingfilesNet(SimpleHoster):      LINK_FREE_PATTERN = r'var download_url = \'(.+)\';' -      def setup(self):          self.resumeDownload = True          self.multiDL        = True -      def handleFree(self, pyfile):          # Click the free user button          post_data = {'op'         : "download1", diff --git a/pyload/plugin/hoster/LoadTo.py b/pyload/plugin/hoster/LoadTo.py index 6616114e3..a0e4eb92e 100644 --- a/pyload/plugin/hoster/LoadTo.py +++ b/pyload/plugin/hoster/LoadTo.py @@ -6,7 +6,7 @@  import re -from pyload.plugin.internal.captcha import SolveMedia +from pyload.plugin.captcha.SolveMedia import SolveMedia  from pyload.plugin.internal.SimpleHoster import SimpleHoster diff --git a/pyload/plugin/hoster/LuckyShareNet.py b/pyload/plugin/hoster/LuckyShareNet.py index 3300f989c..7fbbbf1ea 100644 --- a/pyload/plugin/hoster/LuckyShareNet.py +++ b/pyload/plugin/hoster/LuckyShareNet.py @@ -4,7 +4,7 @@ import re  from bottle import json_loads -from pyload.plugin.internal.captcha import ReCaptcha +from pyload.plugin.captcha.ReCaptcha import ReCaptcha  from pyload.plugin.internal.SimpleHoster import SimpleHoster diff --git a/pyload/plugin/hoster/NetloadIn.py b/pyload/plugin/hoster/NetloadIn.py index 5a982a055..dcfb9dcb6 100644 --- a/pyload/plugin/hoster/NetloadIn.py +++ b/pyload/plugin/hoster/NetloadIn.py @@ -8,7 +8,7 @@ from urlparse import urljoin  from pyload.network.RequestFactory import getURL  from pyload.plugin.Hoster import Hoster  from pyload.plugin.Plugin import chunks -from pyload.plugin.captcha import ReCaptcha +from pyload.plugin.captcha.ReCaptcha import ReCaptcha  def getInfo(urls): diff --git a/pyload/plugin/hoster/OboomCom.py b/pyload/plugin/hoster/OboomCom.py index f8a9fb8bb..07c40a397 100644 --- a/pyload/plugin/hoster/OboomCom.py +++ b/pyload/plugin/hoster/OboomCom.py @@ -7,7 +7,7 @@ import re  from pyload.utils import json_loads  from pyload.plugin.Hoster import Hoster -from pyload.plugin.internal.captcha import ReCaptcha +from pyload.plugin.captcha.ReCaptcha import ReCaptcha  class OboomCom(Hoster): diff --git a/pyload/plugin/hoster/RapiduNet.py b/pyload/plugin/hoster/RapiduNet.py index 858e5fd09..4a7be110c 100644 --- a/pyload/plugin/hoster/RapiduNet.py +++ b/pyload/plugin/hoster/RapiduNet.py @@ -6,7 +6,7 @@ import time  from pycurl import HTTPHEADER  from pyload.utils import json_loads -from pyload.plugin.captcha import ReCaptcha +from pyload.plugin.captcha.ReCaptcha import ReCaptcha  from pyload.plugin.internal.SimpleHoster import SimpleHoster diff --git a/pyload/plugin/hoster/ShareonlineBiz.py b/pyload/plugin/hoster/ShareonlineBiz.py index 5d671c77a..273431f99 100644 --- a/pyload/plugin/hoster/ShareonlineBiz.py +++ b/pyload/plugin/hoster/ShareonlineBiz.py @@ -7,7 +7,7 @@ from urllib import unquote  from urlparse import urlparse  from pyload.network.RequestFactory import getURL -from pyload.plugin.captcha import ReCaptcha +from pyload.plugin.captcha.ReCaptcha import ReCaptcha  from pyload.plugin.internal.SimpleHoster import SimpleHoster diff --git a/pyload/plugin/hoster/TurbobitNet.py b/pyload/plugin/hoster/TurbobitNet.py index d8daf79f7..4c07cb84f 100644 --- a/pyload/plugin/hoster/TurbobitNet.py +++ b/pyload/plugin/hoster/TurbobitNet.py @@ -10,7 +10,7 @@ from pycurl import HTTPHEADER  from urllib import quote  from pyload.network.RequestFactory import getURL -from pyload.plugin.internal.captcha import ReCaptcha +from pyload.plugin.captcha.ReCaptcha import ReCaptcha  from pyload.plugin.internal.SimpleHoster import SimpleHoster, timestamp diff --git a/pyload/plugin/hoster/UploadableCh.py b/pyload/plugin/hoster/UploadableCh.py index 9037b0250..c030c4178 100644 --- a/pyload/plugin/hoster/UploadableCh.py +++ b/pyload/plugin/hoster/UploadableCh.py @@ -2,7 +2,7 @@  import re -from pyload.plugin.captcha import ReCaptcha +from pyload.plugin.captcha.ReCaptcha import ReCaptcha  from pyload.plugin.internal.SimpleHoster import SimpleHoster diff --git a/pyload/plugin/hoster/UpstoreNet.py b/pyload/plugin/hoster/UpstoreNet.py index f022ef2dd..544cee633 100644 --- a/pyload/plugin/hoster/UpstoreNet.py +++ b/pyload/plugin/hoster/UpstoreNet.py @@ -2,7 +2,7 @@  import re -from pyload.plugin.internal.captcha import ReCaptcha +from pyload.plugin.captcha.ReCaptcha import ReCaptcha  from pyload.plugin.internal.SimpleHoster import SimpleHoster diff --git a/pyload/plugin/internal/SimpleHoster.py b/pyload/plugin/internal/SimpleHoster.py index 60f13324f..08fef5a70 100644 --- a/pyload/plugin/internal/SimpleHoster.py +++ b/pyload/plugin/internal/SimpleHoster.py @@ -25,14 +25,14 @@ statusMap = dict((v, k) for k, v in _statusMap.iteritems())  #@TODO: Remove in 0.4.10 and redirect to self.error instead  def _error(self, reason, type): -        if not reason and not type: -            type = "unknown" +    if not reason and not type: +        type = "unknown" -        msg  = _("%s error") % type.strip().capitalize() if type else _("Error") -        msg += ": %s" % reason.strip() if reason else "" -        msg += _(" | Plugin may be out of date") +    msg  = _("%s error") % type.strip().capitalize() if type else _("Error") +    msg += ": %s" % reason.strip() if reason else "" +    msg += _(" | Plugin may be out of date") -        raise Fail(msg) +    raise Fail(msg)  #@TODO: Remove in 0.4.10 @@ -125,13 +125,13 @@ def parseFileInfo(plugin, url="", html=""):  # def create_getInfo(plugin):      # def generator(list): -        # for x in list: -            # yield x +    # for x in list: +    # yield x      # if hasattr(plugin, "parseInfos"): -        # fn = lambda urls: generator((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: generator(parseFileInfo(url) for url in urls) +    # fn = lambda urls: generator(parseFileInfo(url) for url in urls)      # return fn @@ -238,7 +238,7 @@ def secondsToMidnight(gmt=0):      if hasattr(td, 'total_seconds'):          res = td.total_seconds()      else:  #: work-around for python 2.5 and 2.6 missing datetime.timedelta.total_seconds -        res = (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6 +        res = (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10 ** 6) / 10 ** 6      return int(res) @@ -253,8 +253,7 @@ class SimpleHoster(Hoster):      __description = """Simple hoster plugin"""      __license     = "GPLv3" -    __authors     = [("Walter Purcaro", "vuolter@gmail.com"  )] - +    __authors     = [("Walter Purcaro", "vuolter@gmail.com")]      """      Info patterns should be defined by each hoster: @@ -310,27 +309,24 @@ class SimpleHoster(Hoster):      LOGIN_ACCOUNT = False  #: Set to True to require account login      DISPOSITION   = True   #: Work-around to `filename*=UTF-8` bug; remove in 0.4.10 -    directLink = getFileURL  #@TODO: Remove in 0.4.10 - +    directLink = getFileURL  # @TODO: Remove in 0.4.10      @classmethod -    def parseInfos(cls, urls):  #@TODO: Built-in in 0.4.10 core, then remove from plugins +    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.URL_REPLACEMENTS)              yield cls.getInfo(url) -      @classmethod      def apiInfo(cls, url="", get={}, post={}):          url   = unquote(url)          url_p = urlparse(url) -        return {'name'  : (url_p.path.split('/')[-1] -                           or url_p.query.split('=', 1)[::-1][0].split('&', 1)[0] -                           or url_p.netloc.split('.', 1)[0]), -                'size'  : 0, +        return {'name': (url_p.path.split('/')[-1] +                         or url_p.query.split('=', 1)[::-1][0].split('&', 1)[0] +                         or url_p.netloc.split('.', 1)[0]), +                'size': 0,                  'status': 3 if url else 8, -                'url'   : url} - +                'url': url}      @classmethod      def getInfo(cls, url="", html=""): @@ -411,19 +407,17 @@ class SimpleHoster(Hoster):          return info -      def setup(self):          self.resumeDownload = self.multiDL = self.premium -      def prepare(self): -        self.pyfile.error = ""  #@TODO: Remove in 0.4.10 +        self.pyfile.error = ""  # @TODO: Remove in 0.4.10          self.info      = {}          self.html      = "" -        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 +        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 not self.getConfig('use_premium', True):              self.retryFree() @@ -449,14 +443,12 @@ class SimpleHoster(Hoster):          self.pyfile.url = replace_patterns(self.pyfile.url, self.URL_REPLACEMENTS) -      def preload(self):          self.html = self.load(self.pyfile.url, cookies=bool(self.COOKIES), decode=not self.TEXT_ENCODING)          if isinstance(self.TEXT_ENCODING, basestring):              self.html = unicode(self.html, self.TEXT_ENCODING) -      def process(self, pyfile):          try:              self.prepare() @@ -489,14 +481,13 @@ class SimpleHoster(Hoster):              self.downloadLink(self.link, self.DISPOSITION)  #: Remove `self.DISPOSITION` in 0.4.10              self.checkFile() -        except Fail, e:  #@TODO: Move to PluginThread in 0.4.10 +        except Fail, e:  # @TODO: Move to PluginThread in 0.4.10              if self.premium:                  self.logWarning(_("Premium download failed"))                  self.retryFree()              else:                  raise Fail(e) -      def downloadLink(self, link, disposition=True):          if link and isinstance(link, basestring):              self.correctCaptcha() @@ -508,7 +499,6 @@ class SimpleHoster(Hoster):              self.download(link, ref=False, disposition=disposition) -      def checkFile(self, rules={}):          if self.cTask and not self.lastDownload:              self.invalidCaptcha() @@ -523,14 +513,14 @@ class SimpleHoster(Hoster):                                           'Html error': re.compile(r'\A(?:\s*<.+>)?((?:[\w\s]*(?:[Ee]rror|ERROR)\s*\:?)?\s*\d{3})(?:\Z|\s+)')})              if not errmsg: -                for r, p in [('Html file'    , re.compile(r'\A\s*<!DOCTYPE html')                                ), +                for r, p in [('Html file', re.compile(r'\A\s*<!DOCTYPE html')),                               ('Request error', re.compile(r'([Aa]n error occured while processing your request)'))]:                      if r not in rules:                          rules[r] = p -                for r, a in [('Error'       , "ERROR_PATTERN"       ), +                for r, a in [('Error', "ERROR_PATTERN"),                               ('Premium only', "PREMIUM_ONLY_PATTERN"), -                             ('Wait error'  , "WAIT_PATTERN"        )]: +                             ('Wait error', "WAIT_PATTERN")]:                      if r not in rules and hasattr(self, a):                          rules[r] = getattr(self, a) @@ -549,7 +539,6 @@ class SimpleHoster(Hoster):              self.logWarning("Check result: " + errmsg, "Waiting 1 minute and retry")              self.retry(3, 60, errmsg) -      def checkErrors(self):          if not self.html:              self.logWarning(_("No html code to check")) @@ -594,7 +583,6 @@ class SimpleHoster(Hoster):          self.info.pop('error', None) -      def checkStatus(self, getinfo=True):          if not self.info or getinfo:              self.logDebug("Update file info...") @@ -617,7 +605,6 @@ class SimpleHoster(Hoster):          finally:              self.logDebug("File status: %s" % statusMap[status]) -      def checkNameSize(self, getinfo=True):          if not self.info or getinfo:              self.logDebug("Update file info...") @@ -645,7 +632,6 @@ class SimpleHoster(Hoster):          self.logDebug("File name: %s" % self.pyfile.name,                        "File size: %s byte" % self.pyfile.size if self.pyfile.size > 0 else "File size: Unknown") -      def checkInfo(self):          self.checkNameSize() @@ -655,14 +641,12 @@ class SimpleHoster(Hoster):          self.checkStatus(getinfo=False) -      #: Deprecated      def getFileInfo(self):          self.info = {}          self.checkInfo()          return self.info -      def handleDirect(self, pyfile):          link = self.directLink(pyfile.url, self.resumeDownload) @@ -673,11 +657,9 @@ class SimpleHoster(Hoster):          else:              self.logDebug("Direct download link not found") -      def handleMulti(self, pyfile):  #: Multi-hoster handler          pass -      def handleFree(self, pyfile):          if not hasattr(self, 'LINK_FREE_PATTERN'):              self.logError(_("Free download not implemented")) @@ -688,7 +670,6 @@ class SimpleHoster(Hoster):          else:              self.link = m.group(1) -      def handlePremium(self, pyfile):          if not hasattr(self, 'LINK_PREMIUM_PATTERN'):              self.logError(_("Premium download not implemented")) @@ -701,7 +682,6 @@ class SimpleHoster(Hoster):          else:              self.link = m.group(1) -      def longWait(self, wait_time=None, max_tries=3):          if wait_time and isinstance(wait_time, (int, long, float)):              time_str  = "%dh %dm" % divmod(wait_time / 60, 60) @@ -715,11 +695,9 @@ class SimpleHoster(Hoster):          self.wait(wait_time, True)          self.retry(max_tries=max_tries, reason=_("Download limit reached")) -      def parseHtmlForm(self, attr_str="", input_names={}):          return parseHtmlForm(attr_str, self.html, input_names) -      def checkTrafficLeft(self):          if not self.account:              return True @@ -735,8 +713,7 @@ class SimpleHoster(Hoster):              self.logInfo(_("Filesize: %i KiB, Traffic left for user %s: %i KiB") % (size, self.user, traffic))              return size <= traffic - -    def getConfig(self, option, default=''):  #@TODO: Remove in 0.4.10 +    def getConfig(self, option, default=''):  # @TODO: Remove in 0.4.10          """getConfig with default value - sublass may not implements all config options"""          try:              return self.getConf(option) @@ -744,7 +721,6 @@ class SimpleHoster(Hoster):          except KeyError:              return default -      def retryFree(self):          if not self.premium:              return @@ -754,11 +730,9 @@ class SimpleHoster(Hoster):          self.retries = 0          raise Retry(_("Fallback to free download")) -      #@TODO: Remove in 0.4.10      def wait(self, seconds=0, reconnect=None):          return _wait(self, seconds, reconnect) -      def error(self, reason="", type="parse"):          return _error(self, reason, type) diff --git a/pyload/plugin/internal/XFSHoster.py b/pyload/plugin/internal/XFSHoster.py index e87b6b0ee..532d9bea4 100644 --- a/pyload/plugin/internal/XFSHoster.py +++ b/pyload/plugin/internal/XFSHoster.py @@ -6,7 +6,8 @@ import time  from random import random  from urlparse import urljoin, urlparse -from pyload.plugin.internal.captcha import ReCaptcha, SolveMedia +from pyload.plugin.captcha.ReCaptcha import ReCaptcha +from pyload.plugin.captcha.SolveMedia import SolveMedia  from pyload.plugin.internal.SimpleHoster import SimpleHoster, secondsToMidnight  from pyload.utils import html_unescape @@ -21,15 +22,14 @@ class XFSHoster(SimpleHoster):      __description = """XFileSharing hoster plugin"""      __license     = "GPLv3"      __authors     = [("zoidberg"      , "zoidberg@mujmail.cz"), -                       ("stickell"      , "l.stickell@yahoo.it"), -                       ("Walter Purcaro", "vuolter@gmail.com"  )] - +                     ("stickell"      , "l.stickell@yahoo.it"), +                     ("Walter Purcaro", "vuolter@gmail.com")]      HOSTER_DOMAIN = None      TEXT_ENCODING = False      DIRECT_LINK   = None -    MULTI_HOSTER  = True  #@NOTE: Should be default to False for safe, but I'm lazy... +    MULTI_HOSTER  = True  # @NOTE: Should be default to False for safe, but I'm lazy...      NAME_PATTERN = r'(Filename[ ]*:[ ]*</b>(</td><td nowrap>)?|name="fname"[ ]+value="|<[\w^_]+ class="(file)?name">)\s*(?P<N>.+?)(\s*<|")'      SIZE_PATTERN = r'(Size[ ]*:[ ]*</b>(</td><td>)?|File:.*>|</font>\s*\(|<[\w^_]+ class="size">)\s*(?P<S>[\d.,]+)\s*(?P<U>[\w^_]+)' @@ -52,12 +52,10 @@ class XFSHoster(SimpleHoster):      FORM_PATTERN    = None      FORM_INPUTS_MAP = None  #: dict passed as input_names to parseHtmlForm -      def setup(self):          self.chunkLimit     = -1 if self.premium else 1          self.resumeDownload = self.multiDL = self.premium -      def prepare(self):          """ Initialize important variables """          if not self.HOSTER_DOMAIN: @@ -86,7 +84,6 @@ class XFSHoster(SimpleHoster):          if self.DIRECT_LINK is None:              self.directDL = self.premium -      def handleFree(self, pyfile):          for i in xrange(1, 6):              self.logDebug("Getting download link: #%d" % i) @@ -112,18 +109,16 @@ class XFSHoster(SimpleHoster):              self.logError(data['op'] if 'op' in data else _("UNKNOWN"))              return "" -        self.link = 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):          if not self.account:              self.fail(_("Only registered or premium users can use url leech feature")) -        #only tested with easybytez.com +        # only tested with easybytez.com          self.html = self.load("http://www.%s/" % self.HOSTER_DOMAIN)          action, inputs = self.parseHtmlForm() @@ -166,7 +161,7 @@ class XFSHoster(SimpleHoster):          else:              self.fail(stmsg) -        #get easybytez.com link for uploaded file +        # get easybytez.com link for uploaded file          m = re.search(self.LINK_LEECH_PATTERN, self.html)          if m is None:              self.error(_("LINK_LEECH_PATTERN not found")) @@ -176,7 +171,6 @@ class XFSHoster(SimpleHoster):          if 'location' in header:  #: Direct download link              self.link = header['location'] -      def checkErrors(self):          m = re.search(self.ERROR_PATTERN, self.html)          if m is None: @@ -229,7 +223,6 @@ class XFSHoster(SimpleHoster):          else:              self.info.pop('error', None) -      def getPostParameters(self):          if self.FORM_PATTERN or self.FORM_INPUTS_MAP:              action, inputs = self.parseHtmlForm(self.FORM_PATTERN or "", self.FORM_INPUTS_MAP or {}) @@ -275,7 +268,6 @@ class XFSHoster(SimpleHoster):          return inputs -      def handleCaptcha(self, inputs):          m = re.search(self.CAPTCHA_PATTERN, self.html)          if m: | 
