diff options
| author | 2015-04-13 17:20:59 +0200 | |
|---|---|---|
| committer | 2015-04-13 17:20:59 +0200 | |
| commit | e00ef98491f79ae8aa972ae1473dae4a7b78c07e (patch) | |
| tree | 31be0c7cdcebb61525bcc387bcf15d265a1c494a /pyload/plugin | |
| parent | Fix except (diff) | |
| download | pyload-e00ef98491f79ae8aa972ae1473dae4a7b78c07e.tar.xz | |
Cleanup
Diffstat (limited to 'pyload/plugin')
51 files changed, 237 insertions, 5 deletions
| diff --git a/pyload/plugin/Account.py b/pyload/plugin/Account.py index 6a3eddc5b..09dd90ad0 100644 --- a/pyload/plugin/Account.py +++ b/pyload/plugin/Account.py @@ -63,6 +63,8 @@ class Account(Base):      @lock + +      def _login(self, user, data):          # set timestamp for login          self.timestamps[user] = time() @@ -137,6 +139,8 @@ class Account(Base):      @lock + +      def getAccountInfo(self, name, force=False):          """retrieve account infos for an user, do **not** overwrite this method!\\          just use it to retrieve infos in hoster plugins. see `loadAccountInfo` @@ -295,6 +299,8 @@ class Account(Base):      @lock + +      def checkLogin(self, user):          """ checks if user is still logged in """          if user in self.timestamps: diff --git a/pyload/plugin/Addon.py b/pyload/plugin/Addon.py index 1f4730851..35f010f29 100644 --- a/pyload/plugin/Addon.py +++ b/pyload/plugin/Addon.py @@ -16,6 +16,7 @@ class Expose(object):  def threaded(fn): +      def run(*args,**kwargs):          addonManager.startThread(fn, *args, **kwargs) @@ -111,6 +112,7 @@ class Addon(Base):          if has_method(self.__class__, "unload"):              self.unload() +      def unload(self):  # Deprecated, use method deactivate() instead          pass @@ -121,11 +123,14 @@ class Addon(Base):      # Event methods - overwrite these if needed + +      def activate(self):          """ called when addon was activated """          if has_method(self.__class__, "coreReady"):              self.coreReady() +      def coreReady(self):  # Deprecated, use method activate() instead          pass @@ -135,6 +140,7 @@ class Addon(Base):          if has_method(self.__class__, "coreExiting"):              self.coreExiting() +      def coreExiting(self):  # Deprecated, use method exit() instead          pass diff --git a/pyload/plugin/Extractor.py b/pyload/plugin/Extractor.py index 80f123a52..decb332fd 100644 --- a/pyload/plugin/Extractor.py +++ b/pyload/plugin/Extractor.py @@ -36,17 +36,23 @@ class Extractor:      @classmethod + +      def isArchive(cls, filename):          name = os.path.basename(filename).lower()          return any(name.endswith(ext) for ext in cls.EXTENSIONS)      @classmethod + +      def isMultipart(cls, filename):          return False      @classmethod + +      def isUsable(cls):          """ Check if system statisfy dependencies          :return: boolean @@ -55,6 +61,8 @@ class Extractor:      @classmethod + +      def getTargets(cls, files_ids):          """ Filter suited targets from list of filename id tuple list          :param files_ids: List of filepathes @@ -111,6 +119,7 @@ class Extractor:          """          raise NotImplementedError +      def verify(self):          """Testing with Extractors buildt-in method          Raises error if password is needed, integrity is questionable or else. diff --git a/pyload/plugin/OCR.py b/pyload/plugin/OCR.py index df32b9f23..df5eeea1f 100644 --- a/pyload/plugin/OCR.py +++ b/pyload/plugin/OCR.py @@ -26,21 +26,26 @@ class OCR(Base):      __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""" @@ -51,6 +56,7 @@ 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, pagesegmode=None):          # tmpTif = tempfile.NamedTemporaryFile(suffix=".tif")          try: @@ -113,15 +119,18 @@ 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 @@ -132,6 +141,7 @@ class OCR(Base):                  else:                      self.pixels[x, y] = 0 +      def clean(self, allowed):          pixels = self.pixels @@ -177,6 +187,7 @@ class OCR(Base):          self.pixels = pixels +      def derotate_by_average(self):          """rotate by checking each angle and guess most suitable""" @@ -250,6 +261,7 @@ class OCR(Base):          self.pixels = pixels +      def split_captcha_letters(self):          captcha = self.image          started = False @@ -289,6 +301,7 @@ 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 c14155751..cedab3b4f 100644 --- a/pyload/plugin/Plugin.py +++ b/pyload/plugin/Plugin.py @@ -61,38 +61,49 @@ class Base(object):          #: Core instance          self.core = core +      def _log(self, type, args):          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 @@ -103,10 +114,13 @@ class Base(object):          self.core.config.setPlugin(self.getPluginConfSection(), option, value)      #: Deprecated method + +      def getConf(self, option):          """ see `getConfig` """          return self.core.config.getPlugin(self.getPluginConfSection(), option) +      def getConfig(self, option):          """ Returns config value for current plugin @@ -115,24 +129,29 @@ 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) @@ -158,6 +177,7 @@ class Plugin(Base):      info = {}  #: file info dict +      def __init__(self, pyfile):          Base.__init__(self, pyfile.m.core) @@ -224,22 +244,27 @@ class Plugin(Base):          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 @@ -255,16 +280,19 @@ 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: @@ -278,11 +306,13 @@ 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` @@ -300,6 +330,7 @@ class Plugin(Base):          if reconnect is not None:              self.setReconnect(reconnect) +      def wait(self, seconds=None, reconnect=None):          """ waits the time previously set """ @@ -345,16 +376,19 @@ 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" @@ -365,18 +399,21 @@ 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 @@ -392,16 +429,19 @@ 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 @@ -472,6 +512,7 @@ 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 @@ -539,6 +580,7 @@ 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 @@ -628,6 +670,7 @@ 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` @@ -668,12 +711,14 @@ 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 @@ -705,6 +750,7 @@ 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/account/NoPremiumPl.py b/pyload/plugin/account/NoPremiumPl.py index cbbc937b5..ac0e64cd4 100644 --- a/pyload/plugin/account/NoPremiumPl.py +++ b/pyload/plugin/account/NoPremiumPl.py @@ -31,6 +31,7 @@ class NoPremiumPl(Account):      _usr = None      _pwd = None +      def loadAccountInfo(self, name, req):          self._req = req          try: @@ -53,6 +54,7 @@ class NoPremiumPl(Account):                      "premium": premium                  }) +      def login(self, user, data, req):          self._usr = user          self._pwd = hashlib.sha1(hashlib.md5(data["password"]).hexdigest()).hexdigest() @@ -68,6 +70,7 @@ class NoPremiumPl(Account):          data['usr'] = self._usr          data['pwd'] = self._pwd +      def createAuthQuery(self):          query = self._api_query          query["username"] = self._usr @@ -75,6 +78,7 @@ class NoPremiumPl(Account):          return query +      def runAuthQuery(self):          data = self._req.load(self._api_url, post=self.createAuthQuery()) diff --git a/pyload/plugin/account/OboomCom.py b/pyload/plugin/account/OboomCom.py index 17239bda2..17d81428c 100644 --- a/pyload/plugin/account/OboomCom.py +++ b/pyload/plugin/account/OboomCom.py @@ -9,11 +9,13 @@ except ImportError:      from beaker.crypto.pbkdf2 import pbkdf2      from binascii import b2a_hex      class PBKDF2(object): +          def __init__(self, passphrase, salt, iterations=1000):              self.passphrase = passphrase              self.salt = salt              self.iterations = iterations +          def hexread(self, octets):              return b2a_hex(pbkdf2(self.passphrase, self.salt, self.iterations, octets)) diff --git a/pyload/plugin/account/PremiumTo.py b/pyload/plugin/account/PremiumTo.py index 01369554f..fcd856ea7 100644 --- a/pyload/plugin/account/PremiumTo.py +++ b/pyload/plugin/account/PremiumTo.py @@ -15,7 +15,6 @@ class PremiumTo(Account):                         ("stickell", "l.stickell@yahoo.it")] -      def loadAccountInfo(self, user, req):          traffic = req.load("http://premium.to/api/straffic.php",                             get={'username': self.username, 'password': self.password}) diff --git a/pyload/plugin/account/RapideoPl.py b/pyload/plugin/account/RapideoPl.py index dddb22781..d40c76cb5 100644 --- a/pyload/plugin/account/RapideoPl.py +++ b/pyload/plugin/account/RapideoPl.py @@ -31,6 +31,7 @@ class RapideoPl(Account):      _usr = None      _pwd = None +      def loadAccountInfo(self, name, req):          self._req = req          try: @@ -53,6 +54,7 @@ class RapideoPl(Account):                      "premium": premium                  }) +      def login(self, user, data, req):          self._usr = user          self._pwd = hashlib.md5(data["password"]).hexdigest() @@ -67,6 +69,7 @@ class RapideoPl(Account):          data['usr'] = self._usr          data['pwd'] = self._pwd +      def createAuthQuery(self):          query = self._api_query          query["username"] = self._usr @@ -74,6 +77,7 @@ class RapideoPl(Account):          return query +      def runAuthQuery(self):          data = self._req.load(self._api_url, post=self.createAuthQuery()) diff --git a/pyload/plugin/account/SmoozedCom.py b/pyload/plugin/account/SmoozedCom.py index 3d0756021..7f4beb7d9 100644 --- a/pyload/plugin/account/SmoozedCom.py +++ b/pyload/plugin/account/SmoozedCom.py @@ -10,11 +10,13 @@ except ImportError:      from beaker.crypto.pbkdf2 import pbkdf2      from binascii import b2a_hex      class PBKDF2(object): +          def __init__(self, passphrase, salt, iterations=1000):              self.passphrase = passphrase              self.salt = salt              self.iterations = iterations +          def hexread(self, octets):              return b2a_hex(pbkdf2(self.passphrase, self.salt, self.iterations, octets)) diff --git a/pyload/plugin/addon/AndroidPhoneNotify.py b/pyload/plugin/addon/AndroidPhoneNotify.py index 8332f668d..3fb291e11 100644 --- a/pyload/plugin/addon/AndroidPhoneNotify.py +++ b/pyload/plugin/addon/AndroidPhoneNotify.py @@ -75,6 +75,8 @@ class AndroidPhoneNotify(Addon):      @Expose + +      def notify(self,                 event,                 msg="", diff --git a/pyload/plugin/addon/AntiVirus.py b/pyload/plugin/addon/AntiVirus.py index 3866014ee..c6628a684 100644 --- a/pyload/plugin/addon/AntiVirus.py +++ b/pyload/plugin/addon/AntiVirus.py @@ -43,6 +43,8 @@ class AntiVirus(Addon):      @Expose      @threaded + +      def scan(self, pyfile, thread):          file     = fs_encode(pyfile.plugin.lastDownload)          filename = os.path.basename(pyfile.plugin.lastDownload) diff --git a/pyload/plugin/addon/ClickNLoad.py b/pyload/plugin/addon/ClickNLoad.py index b6448598a..6a3d5d662 100644 --- a/pyload/plugin/addon/ClickNLoad.py +++ b/pyload/plugin/addon/ClickNLoad.py @@ -48,6 +48,8 @@ class ClickNLoad(Addon):      @threaded + +      def proxy(self, ip, webport, cnlport):          time.sleep(10)  #@TODO: Remove in 0.4.10 (implement addon delay on startup) @@ -61,6 +63,8 @@ class ClickNLoad(Addon):      @threaded + +      def _server(self, ip, webport, cnlport):          try:              dock_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) diff --git a/pyload/plugin/addon/DeleteFinished.py b/pyload/plugin/addon/DeleteFinished.py index f8f42da1e..c0a2e8752 100644 --- a/pyload/plugin/addon/DeleteFinished.py +++ b/pyload/plugin/addon/DeleteFinished.py @@ -23,6 +23,8 @@ class DeleteFinished(Addon):      ## overwritten methods ## + +      def setup(self):          self.interval = self.MIN_CHECK_INTERVAL @@ -59,6 +61,8 @@ class DeleteFinished(Addon):      ## own methods ##      @style.queue + +      def deleteFinished(self, mode):          self.c.execute('DELETE FROM packages WHERE NOT EXISTS(SELECT 1 FROM links WHERE package=packages.id AND status NOT IN (%s))' % mode)          self.c.execute('DELETE FROM links WHERE NOT EXISTS(SELECT 1 FROM packages WHERE id=links.package)') @@ -70,6 +74,8 @@ class DeleteFinished(Addon):      ## event managing ## + +      def addEvent(self, event, func):          """Adds an event listener for event name"""          if event in self.manager.events: diff --git a/pyload/plugin/addon/ExtractArchive.py b/pyload/plugin/addon/ExtractArchive.py index d94c0ca18..a52b55f0a 100644 --- a/pyload/plugin/addon/ExtractArchive.py +++ b/pyload/plugin/addon/ExtractArchive.py @@ -14,6 +14,7 @@ if sys.version_info < (2, 7) and os.name != "nt":      import errno      import subprocess +      def _eintr_retry_call(func, *args):          while True:              try: @@ -26,6 +27,8 @@ if sys.version_info < (2, 7) and os.name != "nt":      # unsued timeout option for older python version + +      def wait(self, timeout=0):          """Wait for child process to terminate.  Returns returncode          attribute.""" @@ -190,6 +193,8 @@ class ExtractArchive(Addon):      @threaded + +      def extractQueued(self, thread):          packages = self.queue.get()          while packages: @@ -206,6 +211,8 @@ class ExtractArchive(Addon):      @Expose + +      def extractPackage(self, *ids):          """ Extract packages with given id"""          for id in ids: @@ -231,6 +238,8 @@ class ExtractArchive(Addon):      @Expose + +      def extract(self, ids, thread=None):  #@TODO: Use pypack, not pid to improve method usability          if not ids:              return False @@ -503,6 +512,8 @@ class ExtractArchive(Addon):      @Expose + +      def getPasswords(self, reload=True):          """ List of saved passwords """          if reload: @@ -528,6 +539,8 @@ class ExtractArchive(Addon):      @Expose + +      def addPassword(self, password):          """  Adds a password to saved list"""          try: diff --git a/pyload/plugin/addon/IRCInterface.py b/pyload/plugin/addon/IRCInterface.py index 1246c91fa..73998b674 100644 --- a/pyload/plugin/addon/IRCInterface.py +++ b/pyload/plugin/addon/IRCInterface.py @@ -199,6 +199,7 @@ class IRCInterface(Thread, Addon):          #### Events +      def event_pass(self, args):          return [] diff --git a/pyload/plugin/addon/MergeFiles.py b/pyload/plugin/addon/MergeFiles.py index dfc5f41d4..e7da4a82a 100644 --- a/pyload/plugin/addon/MergeFiles.py +++ b/pyload/plugin/addon/MergeFiles.py @@ -26,6 +26,8 @@ class MergeFiles(Addon):      @threaded + +      def packageFinished(self, pack):          files = {}          fid_dict = {} diff --git a/pyload/plugin/addon/MultiHome.py b/pyload/plugin/addon/MultiHome.py index 458ddbeca..057764a1e 100644 --- a/pyload/plugin/addon/MultiHome.py +++ b/pyload/plugin/addon/MultiHome.py @@ -43,6 +43,7 @@ class MultiHome(Addon):          requestFactory = self.core.requestFactory          oldGetRequest = requestFactory.getRequest +          def getRequest(pluginName, account=None):              iface = self.bestInterface(pluginName, account)              if iface: diff --git a/pyload/plugin/addon/SkipRev.py b/pyload/plugin/addon/SkipRev.py index 5209da615..e55d98056 100644 --- a/pyload/plugin/addon/SkipRev.py +++ b/pyload/plugin/addon/SkipRev.py @@ -25,6 +25,8 @@ class SkipRev(Addon):      @staticmethod + +      def _setup(self):          self.pyfile.plugin._setup()          if self.pyfile.hasStatus("skipped"): diff --git a/pyload/plugin/addon/UpdateManager.py b/pyload/plugin/addon/UpdateManager.py index 023884029..c7c7ec047 100644 --- a/pyload/plugin/addon/UpdateManager.py +++ b/pyload/plugin/addon/UpdateManager.py @@ -50,12 +50,14 @@ class UpdateManager(Addon):      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()} @@ -67,6 +69,7 @@ class UpdateManager(Addon):          else:              self.checkonstart = False +      def periodical(self):          if self.core.debug:              if self.getConfig('reloadplugins'): @@ -80,6 +83,8 @@ class UpdateManager(Addon):              self.update()      @Expose + +      def autoreloadPlugins(self):          """ reload and reindex all modified plugins """          modules = filter( @@ -108,6 +113,7 @@ 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() @@ -117,6 +123,8 @@ class UpdateManager(Addon):      @Expose      @threaded + +      def update(self):          """ check for updates """ @@ -127,6 +135,7 @@ class UpdateManager(Addon):          else:              self.core.api.unpauseServer() +      def _update(self):          data = self.server_response() @@ -156,6 +165,7 @@ class UpdateManager(Addon):          #  2 = Plugins updated, but restart required          return exitcode +      def _updatePlugins(self, data):          """ check for plugin updates """ @@ -266,6 +276,8 @@ class UpdateManager(Addon):          return exitcode      @Expose + +      def removePlugins(self, type_plugins):          """ delete plugins from disk """ diff --git a/pyload/plugin/addon/WindowsPhoneNotify.py b/pyload/plugin/addon/WindowsPhoneNotify.py index b1d1c8b0f..f7a5e6ec1 100644 --- a/pyload/plugin/addon/WindowsPhoneNotify.py +++ b/pyload/plugin/addon/WindowsPhoneNotify.py @@ -82,6 +82,8 @@ class WindowsPhoneNotify(Addon):      @Expose + +      def notify(self,                 event,                 msg="", diff --git a/pyload/plugin/captcha/AdYouLike.py b/pyload/plugin/captcha/AdYouLike.py index 83fc4e1a3..a29524bcc 100644 --- a/pyload/plugin/captcha/AdYouLike.py +++ b/pyload/plugin/captcha/AdYouLike.py @@ -18,6 +18,7 @@ class AdYouLike(Captcha):      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: @@ -37,6 +38,7 @@ 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): @@ -68,6 +70,7 @@ 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 :"}}, diff --git a/pyload/plugin/captcha/ReCaptcha.py b/pyload/plugin/captcha/ReCaptcha.py index 004a86bf9..9c75c2212 100644 --- a/pyload/plugin/captcha/ReCaptcha.py +++ b/pyload/plugin/captcha/ReCaptcha.py @@ -24,6 +24,7 @@ class ReCaptcha(Captcha):      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: @@ -42,6 +43,7 @@ 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): @@ -63,6 +65,7 @@ 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}) @@ -79,6 +82,7 @@ class ReCaptcha(Captcha):          return self.result(server, challenge), challenge +      def result(self, server, challenge):          result = self.plugin.decryptCaptcha("%simage" % server,                                              get={'c': challenge}, @@ -90,6 +94,7 @@ 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) @@ -109,6 +114,7 @@ class ReCaptcha(Captcha):          return vers, language, jsh +      def _prepareTimeAndRpc(self):          self.plugin.req.load("http://www.google.com/recaptcha/api2/demo") @@ -124,6 +130,7 @@ class ReCaptcha(Captcha):          return millis, rpc +      def _challenge_v2(self, key, parent=None):          if parent is None:              try: diff --git a/pyload/plugin/extractor/SevenZip.py b/pyload/plugin/extractor/SevenZip.py index 71b288ab0..7cf6aee35 100644 --- a/pyload/plugin/extractor/SevenZip.py +++ b/pyload/plugin/extractor/SevenZip.py @@ -38,6 +38,8 @@ class SevenZip(UnRar):      @classmethod + +      def isUsable(cls):          if os.name == "nt":              cls.CMD = os.path.join(pypath, "7z.exe") @@ -68,7 +70,6 @@ class SevenZip(UnRar):              raise CRCError(err) -      def check(self, password):          p = self.call_cmd("l", "-slt", fs_encode(self.filename))          out, err = p.communicate() diff --git a/pyload/plugin/extractor/UnRar.py b/pyload/plugin/extractor/UnRar.py index cad58ff4f..32d33bc51 100644 --- a/pyload/plugin/extractor/UnRar.py +++ b/pyload/plugin/extractor/UnRar.py @@ -49,6 +49,8 @@ class UnRar(Extractor):      @classmethod + +      def isUsable(cls):          if os.name == "nt":              try: @@ -80,6 +82,8 @@ class UnRar(Extractor):      @classmethod + +      def isMultipart(cls, filename):          return True if cls.re_multipart.search(filename) else False diff --git a/pyload/plugin/extractor/UnZip.py b/pyload/plugin/extractor/UnZip.py index b4fa637f0..5e93064c2 100644 --- a/pyload/plugin/extractor/UnZip.py +++ b/pyload/plugin/extractor/UnZip.py @@ -25,6 +25,8 @@ class UnZip(Extractor):      @classmethod + +      def isUsable(cls):          return sys.version_info[:2] >= (2, 6) diff --git a/pyload/plugin/hook/BypassCaptcha.py b/pyload/plugin/hook/BypassCaptcha.py index 141ac7282..01359f3d3 100644 --- a/pyload/plugin/hook/BypassCaptcha.py +++ b/pyload/plugin/hook/BypassCaptcha.py @@ -123,6 +123,8 @@ class BypassCaptcha(Hook):      @threaded + +      def _processCaptcha(self, task):          c = task.captchaFile          try: diff --git a/pyload/plugin/hook/Captcha9Kw.py b/pyload/plugin/hook/Captcha9Kw.py index 9cb8e7928..b388de444 100644 --- a/pyload/plugin/hook/Captcha9Kw.py +++ b/pyload/plugin/hook/Captcha9Kw.py @@ -61,6 +61,8 @@ class Captcha9kw(Hook):      @threaded + +      def _processCaptcha(self, task):          try:              with open(task.captchaFile, 'rb') as f: diff --git a/pyload/plugin/hook/CaptchaBrotherhood.py b/pyload/plugin/hook/CaptchaBrotherhood.py index eff005d14..a4a461517 100644 --- a/pyload/plugin/hook/CaptchaBrotherhood.py +++ b/pyload/plugin/hook/CaptchaBrotherhood.py @@ -160,6 +160,8 @@ class CaptchaBrotherhood(Hook):      @threaded + +      def _processCaptcha(self, task):          c = task.captchaFile          try: diff --git a/pyload/plugin/hook/DeathByCaptcha.py b/pyload/plugin/hook/DeathByCaptcha.py index 4b77c8718..3688a68d0 100644 --- a/pyload/plugin/hook/DeathByCaptcha.py +++ b/pyload/plugin/hook/DeathByCaptcha.py @@ -206,6 +206,8 @@ class DeathByCaptcha(Hook):      @threaded + +      def _processCaptcha(self, task):          c = task.captchaFile          try: diff --git a/pyload/plugin/hook/ExpertDecoders.py b/pyload/plugin/hook/ExpertDecoders.py index 2e2982d2d..b34309d25 100644 --- a/pyload/plugin/hook/ExpertDecoders.py +++ b/pyload/plugin/hook/ExpertDecoders.py @@ -46,6 +46,8 @@ class ExpertDecoders(Hook):      @threaded + +      def _processCaptcha(self, task):          task.data['ticket'] = ticket = uuid4()          result = None diff --git a/pyload/plugin/hook/ImageTyperz.py b/pyload/plugin/hook/ImageTyperz.py index ca5e02559..717077790 100644 --- a/pyload/plugin/hook/ImageTyperz.py +++ b/pyload/plugin/hook/ImageTyperz.py @@ -141,6 +141,8 @@ class ImageTyperz(Hook):      @threaded + +      def _processCaptcha(self, task):          c = task.captchaFile          try: diff --git a/pyload/plugin/hoster/FilerNet.py b/pyload/plugin/hoster/FilerNet.py index 7cefa6d9f..f9b38e8cb 100644 --- a/pyload/plugin/hoster/FilerNet.py +++ b/pyload/plugin/hoster/FilerNet.py @@ -33,6 +33,7 @@ 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: diff --git a/pyload/plugin/hoster/GigapetaCom.py b/pyload/plugin/hoster/GigapetaCom.py index 803f37897..adbdc2396 100644 --- a/pyload/plugin/hoster/GigapetaCom.py +++ b/pyload/plugin/hoster/GigapetaCom.py @@ -51,7 +51,6 @@ class GigapetaCom(SimpleHoster):              self.fail(_("No valid captcha code entered")) -      def checkErrors(self):          if "All threads for IP" in self.html:              self.logDebug("Your IP is already downloading a file") diff --git a/pyload/plugin/hoster/Keep2ShareCc.py b/pyload/plugin/hoster/Keep2ShareCc.py index 4285bedb9..59e5f5c79 100644 --- a/pyload/plugin/hoster/Keep2ShareCc.py +++ b/pyload/plugin/hoster/Keep2ShareCc.py @@ -86,6 +86,8 @@ class Keep2ShareCc(SimpleHoster):                  self.error(_("Free download link not found"))          self.link = m.group(1) + +      def handleCaptcha(self):          post_data = {'free'               : 1,                       'freeDownloadRequest': 1, diff --git a/pyload/plugin/hoster/KingfilesNet.py b/pyload/plugin/hoster/KingfilesNet.py index af1d49390..5f4207d11 100644 --- a/pyload/plugin/hoster/KingfilesNet.py +++ b/pyload/plugin/hoster/KingfilesNet.py @@ -28,10 +28,12 @@ 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/LinksnappyCom.py b/pyload/plugin/hoster/LinksnappyCom.py index 2cb14dd51..3f2cf9821 100644 --- a/pyload/plugin/hoster/LinksnappyCom.py +++ b/pyload/plugin/hoster/LinksnappyCom.py @@ -51,6 +51,8 @@ class LinksnappyCom(MultiHoster):      @staticmethod + +      def _get_host(url):          host = urlsplit(url).netloc          return re.search(r'[\w-]+\.\w+$', host).group(0) diff --git a/pyload/plugin/hoster/LuckyShareNet.py b/pyload/plugin/hoster/LuckyShareNet.py index e124c5b94..6dff7d517 100644 --- a/pyload/plugin/hoster/LuckyShareNet.py +++ b/pyload/plugin/hoster/LuckyShareNet.py @@ -42,6 +42,8 @@ class LuckyShareNet(SimpleHoster):      # TODO: There should be a filesize limit for free downloads      # TODO: Some files could not be downloaded in free mode + +      def handleFree(self, pyfile):          rep = self.load(r"http://luckyshare.net/download/request/type/time/file/" + self.info['pattern']['ID'], decode=True) diff --git a/pyload/plugin/hoster/MyfastfileCom.py b/pyload/plugin/hoster/MyfastfileCom.py index c6bf4c227..57041d6cd 100644 --- a/pyload/plugin/hoster/MyfastfileCom.py +++ b/pyload/plugin/hoster/MyfastfileCom.py @@ -19,7 +19,6 @@ class MyfastfileCom(MultiHoster):      __authors     = [("stickell", "l.stickell@yahoo.it")] -      def setup(self):          self.chunkLimit = -1 diff --git a/pyload/plugin/hoster/PornhostCom.py b/pyload/plugin/hoster/PornhostCom.py index 819612fcf..f6a63117c 100644 --- a/pyload/plugin/hoster/PornhostCom.py +++ b/pyload/plugin/hoster/PornhostCom.py @@ -27,6 +27,8 @@ class PornhostCom(Hoster):      # Old interface + +      def download_html(self):          url = self.pyfile.url          self.html = self.load(url) diff --git a/pyload/plugin/hoster/ShareonlineBiz.py b/pyload/plugin/hoster/ShareonlineBiz.py index dcdeca168..608ee73b3 100644 --- a/pyload/plugin/hoster/ShareonlineBiz.py +++ b/pyload/plugin/hoster/ShareonlineBiz.py @@ -37,6 +37,8 @@ class ShareonlineBiz(SimpleHoster):      @classmethod + +      def getInfo(cls, url="", html=""):          info = {'name': urlparse(unquote(url)).path.split('/')[-1] or _("Unknown"), 'size': 0, 'status': 3 if url else 1, 'url': url} diff --git a/pyload/plugin/hoster/UploadedTo.py b/pyload/plugin/hoster/UploadedTo.py index 7031d0ab2..7660ec3ad 100644 --- a/pyload/plugin/hoster/UploadedTo.py +++ b/pyload/plugin/hoster/UploadedTo.py @@ -32,6 +32,8 @@ class UploadedTo(SimpleHoster):      @classmethod + +      def apiInfo(cls, url="", get={}, post={}):          info = super(UploadedTo, cls).apiInfo(url) diff --git a/pyload/plugin/hoster/WebshareCz.py b/pyload/plugin/hoster/WebshareCz.py index 11b7b37b0..673dfaac5 100644 --- a/pyload/plugin/hoster/WebshareCz.py +++ b/pyload/plugin/hoster/WebshareCz.py @@ -21,6 +21,8 @@ class WebshareCz(SimpleHoster):      @classmethod + +      def getInfo(cls, url="", html=""):          info = super(WebshareCz, cls).getInfo(url, html) diff --git a/pyload/plugin/hoster/ZDF.py b/pyload/plugin/hoster/ZDF.py index c02eadc23..6f17df61a 100644 --- a/pyload/plugin/hoster/ZDF.py +++ b/pyload/plugin/hoster/ZDF.py @@ -23,6 +23,8 @@ class ZDF(Hoster):      @staticmethod + +      def video_key(video):          return (              int(video.findtext("videoBitrate", "0")), @@ -31,12 +33,16 @@ class ZDF(Hoster):      @staticmethod + +      def video_valid(video):          return video.findtext("url").startswith("http") and video.findtext("url").endswith(".mp4") and \                 video.findtext("facets/facet").startswith("progressive")      @staticmethod + +      def get_id(url):          return int(re.search(r"\D*(\d{4,})\D*", url).group(1)) diff --git a/pyload/plugin/hoster/ZippyshareCom.py b/pyload/plugin/hoster/ZippyshareCom.py index 5bd25d8c1..91a636f0a 100644 --- a/pyload/plugin/hoster/ZippyshareCom.py +++ b/pyload/plugin/hoster/ZippyshareCom.py @@ -65,6 +65,7 @@ class ZippyshareCom(SimpleHoster):          # meant to be populated with the initialization of all the DOM elements found in the scripts          initScripts = set() +          def replElementById(element):              id   = element.group(1) # id might be either 'x' (a real id) or x (a variable)              attr = element.group(4)  # attr might be None diff --git a/pyload/plugin/internal/BasePlugin.py b/pyload/plugin/internal/BasePlugin.py index 996dc8e76..1ddfee122 100644 --- a/pyload/plugin/internal/BasePlugin.py +++ b/pyload/plugin/internal/BasePlugin.py @@ -24,6 +24,8 @@ class BasePlugin(Hoster):      @classmethod + +      def getInfo(cls, url="", html=""):  #@TODO: Move to hoster class in 0.4.10          url   = unquote(url)          url_p = urlparse(url) diff --git a/pyload/plugin/internal/DeadCrypter.py b/pyload/plugin/internal/DeadCrypter.py index daa7e1a0d..c66a1b5e3 100644 --- a/pyload/plugin/internal/DeadCrypter.py +++ b/pyload/plugin/internal/DeadCrypter.py @@ -16,6 +16,8 @@ class DeadCrypter(_Crypter):      @classmethod + +      def apiInfo(cls, url="", get={}, post={}):          api = super(DeadCrypter, self).apiInfo(url, get, post)          api['status'] = 1 diff --git a/pyload/plugin/internal/DeadHoster.py b/pyload/plugin/internal/DeadHoster.py index 2e57decdb..5f00d0128 100644 --- a/pyload/plugin/internal/DeadHoster.py +++ b/pyload/plugin/internal/DeadHoster.py @@ -16,6 +16,8 @@ class DeadHoster(_Hoster):      @classmethod + +      def apiInfo(cls, url="", get={}, post={}):          api = super(DeadHoster, self).apiInfo(url, get, post)          api['status'] = 1 diff --git a/pyload/plugin/internal/SimpleCrypter.py b/pyload/plugin/internal/SimpleCrypter.py index ba5cb991c..f6c5aa5e2 100644 --- a/pyload/plugin/internal/SimpleCrypter.py +++ b/pyload/plugin/internal/SimpleCrypter.py @@ -49,7 +49,6 @@ class SimpleCrypter(Crypter, SimpleHoster):      and its loadPage method: -        def loadPage(self, page_n):            return the html of the page number page_n      """ diff --git a/pyload/plugin/internal/SimpleHoster.py b/pyload/plugin/internal/SimpleHoster.py index 79b3cac1a..b32cb60c0 100644 --- a/pyload/plugin/internal/SimpleHoster.py +++ b/pyload/plugin/internal/SimpleHoster.py @@ -311,12 +311,16 @@ class SimpleHoster(Hoster):      @classmethod + +      def parseInfos(cls, urls):  #@TODO: Built-in in 0.4.10 core (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   = urllib.unquote(url)          url_p = urlparse.urlparse(url) @@ -328,6 +332,8 @@ class SimpleHoster(Hoster):                  'url': url}      @classmethod + +      def getInfo(cls, url="", html=""):          info   = cls.apiInfo(url)          online = False if info['status'] != 2 else True @@ -406,9 +412,11 @@ 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 @@ -442,12 +450,14 @@ 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() @@ -487,6 +497,7 @@ class SimpleHoster(Hoster):              else:                  raise Fail(e) +      def downloadLink(self, link, disposition=True):          if link and isinstance(link, basestring):              self.correctCaptcha() @@ -498,6 +509,7 @@ class SimpleHoster(Hoster):              self.download(link, ref=False, disposition=disposition) +      def checkFile(self, rules={}):          if self.cTask and not self.lastDownload:              self.invalidCaptcha() @@ -538,6 +550,7 @@ 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")) @@ -582,6 +595,7 @@ class SimpleHoster(Hoster):          self.info.pop('error', None) +      def checkStatus(self, getinfo=True):          if not self.info or getinfo:              self.logDebug("Update file info...") @@ -604,6 +618,7 @@ 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...") @@ -631,6 +646,7 @@ 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() @@ -641,11 +657,14 @@ 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) @@ -655,9 +674,11 @@ 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")) @@ -668,6 +689,7 @@ 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")) @@ -680,6 +702,7 @@ 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) @@ -693,9 +716,11 @@ 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 @@ -711,6 +736,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          """getConfig with default value - sublass may not implements all config options"""          try: @@ -719,6 +745,7 @@ class SimpleHoster(Hoster):          except KeyError:              return default +      def retryFree(self):          if not self.premium:              return @@ -729,8 +756,11 @@ class SimpleHoster(Hoster):          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 d2d5fb0dd..4cef261df 100644 --- a/pyload/plugin/internal/XFSHoster.py +++ b/pyload/plugin/internal/XFSHoster.py @@ -52,10 +52,12 @@ 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: @@ -84,6 +86,7 @@ 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) @@ -111,9 +114,11 @@ class XFSHoster(SimpleHoster):          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")) @@ -171,6 +176,7 @@ 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: @@ -223,6 +229,7 @@ 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 {}) @@ -268,6 +275,7 @@ class XFSHoster(SimpleHoster):          return inputs +      def handleCaptcha(self, inputs):          m = re.search(self.CAPTCHA_PATTERN, self.html)          if m: | 
