summaryrefslogtreecommitdiffstats
path: root/pyload/plugins/base
diff options
context:
space:
mode:
Diffstat (limited to 'pyload/plugins/base')
-rw-r--r--pyload/plugins/base/Account.py62
-rw-r--r--pyload/plugins/base/Container.py20
-rw-r--r--pyload/plugins/base/Crypter.py85
-rw-r--r--pyload/plugins/base/Hook.py30
-rw-r--r--pyload/plugins/base/Hoster.py10
-rw-r--r--pyload/plugins/base/OCR.py46
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