diff options
Diffstat (limited to 'pyload/plugins/base')
-rw-r--r-- | pyload/plugins/base/Account.py | 62 | ||||
-rw-r--r-- | pyload/plugins/base/Container.py | 20 | ||||
-rw-r--r-- | pyload/plugins/base/Crypter.py | 85 | ||||
-rw-r--r-- | pyload/plugins/base/Hook.py | 30 | ||||
-rw-r--r-- | pyload/plugins/base/Hoster.py | 10 | ||||
-rw-r--r-- | pyload/plugins/base/OCR.py | 46 |
6 files changed, 180 insertions, 73 deletions
diff --git a/pyload/plugins/base/Account.py b/pyload/plugins/base/Account.py index 687803d2e..acb5c7d8b 100644 --- a/pyload/plugins/base/Account.py +++ b/pyload/plugins/base/Account.py @@ -19,12 +19,13 @@ class Account(Base): Just overwrite `login` and cookies will be stored and account becomes accessible in\ associated hoster plugin. Plugin should also provide `loadAccountInfo` """ - __name__ = "Account" - __type__ = "account" - __version__ = "0.3" + __name__ = "Account" + __type__ = "account" + __version__ = "0.03" __description__ = """Base account plugin""" - __authors__ = [("mkaay", "mkaay@mkaay.de")] + __license__ = "GPLv3" + __authors__ = [("mkaay", "mkaay@mkaay.de")] #: after that time (in minutes) pyload will relogin the account @@ -38,16 +39,19 @@ class Account(Base): self.manager = manager self.accounts = {} - self.infos = {} # cache for account information + self.infos = {} #: cache for account information self.lock = RLock() - self.timestamps = {} - self.setAccounts(accounts) + self.init() + self.setAccounts(accounts) + + def init(self): pass + def login(self, user, data, req): """login into account, the cookies will be saved so user can be recognized @@ -57,6 +61,7 @@ class Account(Base): """ pass + @lock def _login(self, user, data): # set timestamp for login @@ -84,6 +89,7 @@ class Account(Base): req.close() return success + def relogin(self, user): req = self.getAccountRequest(user) if req: @@ -94,12 +100,14 @@ class Account(Base): return self._login(user, self.accounts[user]) + def setAccounts(self, accounts): self.accounts = accounts for user, data in self.accounts.iteritems(): self._login(user, data) self.infos[user] = {} + def updateAccounts(self, user, password=None, options={}): """ updates account and return true if anything changed """ @@ -118,6 +126,7 @@ class Account(Base): self._login(user, self.accounts[user]) return True + def removeAccount(self, user): if user in self.accounts: del self.accounts[user] @@ -126,6 +135,7 @@ class Account(Base): if user in self.timestamps: del self.timestamps[user] + @lock def getAccountInfo(self, name, force=False): """retrieve account infos for an user, do **not** overwrite this method!\\ @@ -164,10 +174,12 @@ class Account(Base): data.update(self.infos[name]) return data + def isPremium(self, user): info = self.getAccountInfo(user) return info['premium'] + def loadAccountInfo(self, name, req=None): """this should be overwritten in account plugin,\ and retrieving account information for user @@ -176,22 +188,22 @@ class Account(Base): :param req: `Request` instance :return: """ - return { - "validuntil": None, # -1 for unlimited - "login": name, - #"password": self.accounts[name]['password'], #@XXX: security - "options": self.accounts[name]['options'], - "valid": self.accounts[name]['valid'], - "trafficleft": None, # in kb, -1 for unlimited - "maxtraffic": None, - "premium": True, #useful for free accounts - "timestamp": 0, #time this info was retrieved - "type": self.__name__, - } + return {"validuntil": None, #: -1 for unlimited + "login": name, + # "password": self.accounts[name]['password'], #: commented due security reason + "options": self.accounts[name]['options'], + "valid": self.accounts[name]['valid'], + "trafficleft": None, #: in kb, -1 for unlimited + "maxtraffic": None, + "premium": None, + "timestamp": 0, #: time this info was retrieved + "type": self.__name__} + def getAllAccounts(self, force=False): return [self.getAccountInfo(user, force) for user, data in self.accounts.iteritems()] + def getAccountRequest(self, user=None): if not user: user, data = self.selectAccount() @@ -201,6 +213,7 @@ class Account(Base): req = self.core.requestFactory.getRequest(self.__name__, user) return req + def getAccountCookies(self, user=None): if not user: user, data = self.selectAccount() @@ -210,9 +223,11 @@ class Account(Base): cj = self.core.requestFactory.getCookieJar(self.__name__, user) return cj + def getAccountData(self, user): return self.accounts[user] + def selectAccount(self): """ returns an valid account name and data""" usable = [] @@ -242,15 +257,19 @@ class Account(Base): if not usable: return None, None return choice(usable) + def canUse(self): return False if self.selectAccount() == (None, None) else True + def parseTraffic(self, string): #returns kbyte - return parseFileSize(string) / 1024 + return parseFileSize(string) + def wrongPassword(self): raise WrongPassword + def empty(self, user): if user in self.infos: self.logWarning(_("Account %s has not enough traffic, checking again in 30min") % user) @@ -258,6 +277,7 @@ class Account(Base): self.infos[user].update({"trafficleft": 0}) self.scheduleRefresh(user, 30 * 60) + def expired(self, user): if user in self.infos: self.logWarning(_("Account %s is expired, checking again in 1h") % user) @@ -265,11 +285,13 @@ class Account(Base): self.infos[user].update({"validuntil": time() - 1}) self.scheduleRefresh(user, 60 * 60) + def scheduleRefresh(self, user, time=0, force=True): """ add task to refresh account info to sheduler """ self.logDebug("Scheduled Account refresh for %s in %s seconds." % (user, time)) self.core.scheduler.addJob(time, self.getAccountInfo, [user, force]) + @lock def checkLogin(self, user): """ checks if user is still logged in """ diff --git a/pyload/plugins/base/Container.py b/pyload/plugins/base/Container.py index 40cc25195..1bb2e204b 100644 --- a/pyload/plugins/base/Container.py +++ b/pyload/plugins/base/Container.py @@ -10,14 +10,16 @@ from pyload.utils import safe_join class Container(Crypter): - __name__ = "Container" - __type__ = "container" - __version__ = "0.1" + __name__ = "Container" + __type__ = "container" + __version__ = "0.01" __pattern__ = None + __config__ = [] #: [("name", "type", "desc", "default")] __description__ = """Base container decrypter plugin""" - __authors__ = [("mkaay", "mkaay@mkaay.de")] + __license__ = "GPLv3" + __authors__ = [("mkaay", "mkaay@mkaay.de")] def preprocessing(self, thread): @@ -42,9 +44,11 @@ class Container(Crypter): self.pyfile.name = re.findall("([^\/=]+)", self.pyfile.url)[-1] content = self.load(self.pyfile.url) self.pyfile.url = safe_join(self.config['general']['download_folder'], self.pyfile.name) - f = open(self.pyfile.url, "wb" ) - f.write(content) - f.close() + try: + with open(self.pyfile.url, "wb") as f: + f.write(content) + except IOError, e: + self.fail(str(e)) else: self.pyfile.name = basename(self.pyfile.url) @@ -52,7 +56,7 @@ class Container(Crypter): if exists(safe_join(pypath, self.pyfile.url)): self.pyfile.url = safe_join(pypath, self.pyfile.url) else: - self.fail(_("File not exists.")) + self.fail(_("File not exists")) def deleteTmp(self): diff --git a/pyload/plugins/base/Crypter.py b/pyload/plugins/base/Crypter.py index 8d269c75d..0a79300dd 100644 --- a/pyload/plugins/base/Crypter.py +++ b/pyload/plugins/base/Crypter.py @@ -1,35 +1,47 @@ # -*- coding: utf-8 -*- from pyload.plugins.Plugin import Plugin +from module.utils import save_path class Crypter(Plugin): - __name__ = "Crypter" - __type__ = "crypter" - __version__ = "0.1" + __name__ = "Crypter" + __type__ = "crypter" + __version__ = "0.05" __pattern__ = None + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), #: Overrides core.config['general']['folder_per_package'] + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Base decrypter plugin""" - __authors__ = [("mkaay", "mkaay@mkaay.de")] + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - def __init__(self, pyfile): - Plugin.__init__(self, pyfile) + html = None #: last html loaded + + def __init__(self, pyfile): #: Put all packages here. It's a list of tuples like: ( name, [list of links], folder ) self.packages = [] #: List of urls, pyLoad will generate packagenames self.urls = [] - self.multiDL = True - self.limitDL = 0 + Plugin.__init__(self, pyfile) def process(self, pyfile): """ main method """ + self.decrypt(pyfile) + + if self.urls: + self.generatePackages() + + elif not self.packages: + self.error(_("No link extracted"), "decrypt") + self.createPackages() @@ -37,24 +49,59 @@ class Crypter(Plugin): raise NotImplementedError + def generatePackages(self): + """ generate new packages from self.urls """ + + packages = map(lambda name, links: (name, links, None), self.core.api.generatePackages(self.urls).iteritems()) + self.packages.extend(packages) + + def createPackages(self): """ create new packages from self.packages """ - for pack in self.packages: + package_folder = self.pyfile.package().folder + package_password = self.pyfile.package().password + package_queue = self.pyfile.package().queue + + folder_per_package = self.config['general']['folder_per_package'] + try: + use_subfolder = self.getConfig('use_subfolder') + except: + use_subfolder = folder_per_package + try: + subfolder_per_package = self.getConfig('subfolder_per_package') + except: + subfolder_per_package = True + + for pack in self.packages: name, links, folder = pack - self.logDebug("Parsed package %(name)s with %(len)d links" % {"name": name, "len": len(links)}) + self.logDebug("Parsed package: %s" % name, + "%d links" % len(links), + "Saved to folder: %s" % folder if folder else "Saved to download folder") - links = [x.decode("utf-8") for x in links] + links = map(lambda x: x.decode("utf-8"), links) - pid = self.api.addPackage(name, links, self.pyfile.package().queue) + pid = self.core.api.addPackage(name, links, package_queue) - if name != folder is not None: - self.api.setPackageData(pid, {"folder": folder}) #: Due to not break API addPackage method right now - self.logDebug("Set package %(name)s folder to %(folder)s" % {"name": name, "folder": folder}) + if package_password: + self.core.api.setPackageData(pid, {"password": package_password}) - if self.pyfile.package().password: - self.api.setPackageData(pid, {"password": self.pyfile.package().password}) + setFolder = lambda x: self.core.api.setPackageData(pid, {"folder": x or ""}) #: Workaround to do not break API addPackage method - if self.urls: - self.api.generateAndAddPackages(self.urls) + if use_subfolder: + if not subfolder_per_package: + setFolder(package_folder) + self.logDebug("Set package %(name)s folder to: %(folder)s" % {"name": name, "folder": folder}) + + elif not folder_per_package or name != folder: + if not folder: + folder = name.replace("http://", "").replace(":", "").replace("/", "_").replace("\\", "_") + + folder = save_path(folder) #@TODO: move to core code + + setFolder(folder) + self.logDebug("Set package %(name)s folder to: %(folder)s" % {"name": name, "folder": folder}) + + elif folder_per_package: + setFolder(None) diff --git a/pyload/plugins/base/Hook.py b/pyload/plugins/base/Hook.py index 718802ad8..5cd528b7e 100644 --- a/pyload/plugins/base/Hook.py +++ b/pyload/plugins/base/Hook.py @@ -24,15 +24,16 @@ class Hook(Base): """ Base class for hook plugins. """ - __name__ = "Hook" - __type__ = "hook" - __version__ = "0.2" + __name__ = "Hook" + __type__ = "hook" + __version__ = "0.03" - __config__ = [("name", "type", "desc", "default")] + __config__ = [] #: [("name", "type", "desc", "default")] __description__ = """Interface for hook""" - __authors__ = [("mkaay", "mkaay@mkaay.de"), - ("RaNaN", "RaNaN@pyload.org")] + __license__ = "GPLv3" + __authors__ = [("mkaay", "mkaay@mkaay.de"), + ("RaNaN", "RaNaN@pyload.org")] #: automatically register event listeners for functions, attribute will be deleted dont use it yourself @@ -50,7 +51,7 @@ class Hook(Base): Base.__init__(self, core) #: Provide information in dict here, usable by API `getInfo` - self.info = None + self.info = {} #: Callback of periodical job task, used by AddonManager self.cb = None @@ -84,6 +85,7 @@ class Hook(Base): if self.interval >=1: self.cb = self.core.scheduler.addJob(0, self._periodical, threaded=False) + def _periodical(self): try: if self.isActivated(): self.periodical() @@ -98,14 +100,17 @@ class Hook(Base): def __repr__(self): return "<Hook %s>" % self.__name__ + def setup(self): """ more init stuff if needed """ pass + def unload(self): """ called when hook was deactivated """ pass + def isActivated(self): """ checks if hook is activated""" return self.config.getPlugin(self.__name__, "activated") @@ -115,36 +120,47 @@ class Hook(Base): def coreReady(self): pass + def coreExiting(self): pass + def downloadPreparing(self, pyfile): pass + def downloadFinished(self, pyfile): pass + def downloadFailed(self, pyfile): pass + def packageFinished(self, pypack): pass + def beforeReconnecting(self, ip): pass + def afterReconnecting(self, ip): pass + def periodical(self): pass + def newCaptchaTask(self, task): """ new captcha task for the plugin, it MUST set the handler and timeout or will be ignored """ pass + def captchaCorrect(self, task): pass + def captchaInvalid(self, task): pass diff --git a/pyload/plugins/base/Hoster.py b/pyload/plugins/base/Hoster.py index 8f0bdb727..a89727ba7 100644 --- a/pyload/plugins/base/Hoster.py +++ b/pyload/plugins/base/Hoster.py @@ -9,11 +9,13 @@ def getInfo(self): class Hoster(Plugin): - __name__ = "Hoster" - __type__ = "hoster" - __version__ = "0.1" + __name__ = "Hoster" + __type__ = "hoster" + __version__ = "0.02" __pattern__ = None + __config__ = [] #: [("name", "type", "desc", "default")] __description__ = """Base hoster plugin""" - __authors__ = [("mkaay", "mkaay@mkaay.de")] + __license__ = "GPLv3" + __authors__ = [("mkaay", "mkaay@mkaay.de")] diff --git a/pyload/plugins/base/OCR.py b/pyload/plugins/base/OCR.py index 5ce85aef6..c3a47e7ef 100644 --- a/pyload/plugins/base/OCR.py +++ b/pyload/plugins/base/OCR.py @@ -14,29 +14,34 @@ from os.path import abspath, join class OCR(object): - __name__ = "OCR" - __type__ = "ocr" + __name__ = "OCR" + __type__ = "ocr" __version__ = "0.1" __description__ = """OCR base plugin""" - __authors__ = [("pyLoad Team", "admin@pyload.org")] + __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 unload(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""" @@ -47,28 +52,32 @@ class OCR(object): 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): - #self.logger.debug("create tmp tif") - #tmp = tempfile.NamedTemporaryFile(suffix=".tif") - tmp = open(join("tmp", "tmpTif_%s.tif" % self.__name__), "wb") - tmp.close() - #self.logger.debug("create tmp txt") - #tmpTxt = tempfile.NamedTemporaryFile(suffix=".txt") - tmpTxt = open(join("tmp", "tmpTxt_%s.txt" % self.__name__), "wb") - tmpTxt.close() + #tmpTif = tempfile.NamedTemporaryFile(suffix=".tif") + try: + tmpTif = open(join("tmp", "tmpTif_%s.tif" % self.__name__), "wb") + tmpTif.close() + + #tmpTxt = tempfile.NamedTemporaryFile(suffix=".txt") + tmpTxt = open(join("tmp", "tmpTxt_%s.txt" % self.__name__), "wb") + tmpTxt.close() + + except IOError, e: + self.logError(e) + return self.logger.debug("save tiff") - self.image.save(tmp.name, 'TIFF') + self.image.save(tmpTif.name, 'TIFF') if os.name == "nt": tessparams = [join(pypath, "tesseract", "tesseract.exe")] else: tessparams = ['tesseract'] - tessparams.extend([abspath(tmp.name), abspath(tmpTxt.name).replace(".txt", "")]) + tessparams.extend([abspath(tmpTif.name), abspath(tmpTxt.name).replace(".txt", "")] ) if subset and (digits or lowercase or uppercase): - #self.logger.debug("create temp subset config") #tmpSub = tempfile.NamedTemporaryFile(suffix=".subset") tmpSub = open(join("tmp", "tmpSub_%s.subset" % self.__name__), "wb") tmpSub.write("tessedit_char_whitelist ") @@ -95,22 +104,25 @@ class OCR(object): self.logger.debug(self.result_captcha) try: - os.remove(tmp.name) + os.remove(tmpTif.name) os.remove(tmpTxt.name) if subset and (digits or lowercase or uppercase): os.remove(tmpSub.name) except: 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 @@ -121,6 +133,7 @@ class OCR(object): else: self.pixels[x, y] = 0 + def clean(self, allowed): pixels = self.pixels @@ -166,6 +179,7 @@ class OCR(object): self.pixels = pixels + def derotate_by_average(self): """rotate by checking each angle and guess most suitable""" @@ -239,6 +253,7 @@ class OCR(object): self.pixels = pixels + def split_captcha_letters(self): captcha = self.image started = False @@ -278,6 +293,7 @@ class OCR(object): return letters + def correct(self, values, var=None): if var: result = var |