summaryrefslogtreecommitdiffstats
path: root/module/plugins/Base.py
diff options
context:
space:
mode:
authorGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2012-03-20 14:57:45 +0100
committerGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2012-03-20 14:57:45 +0100
commit50d4df8b4d48b855bd18e9922355b7f3f2b4da4e (patch)
tree6301b05677a90cf86f131d5a7ae3f879b38e84d2 /module/plugins/Base.py
parentrenamed hooks to addons, new filemanager and database, many new api methods (diff)
downloadpyload-50d4df8b4d48b855bd18e9922355b7f3f2b4da4e.tar.xz
captcha decrypting for all plugin types, new interaction manager
Diffstat (limited to 'module/plugins/Base.py')
-rw-r--r--module/plugins/Base.py118
1 files changed, 107 insertions, 11 deletions
diff --git a/module/plugins/Base.py b/module/plugins/Base.py
index b846bbd60..61fa211f4 100644
--- a/module/plugins/Base.py
+++ b/module/plugins/Base.py
@@ -18,8 +18,11 @@
"""
import sys
+from time import time, sleep
+from random import randint
+
from module.utils import decode
-from module.utils.fs import exists, makedirs, join
+from module.utils.fs import exists, makedirs, join, remove
# TODO
# more attributes if needed
@@ -32,6 +35,9 @@ class Fail(Exception):
class Retry(Exception):
""" raised when start again from beginning """
+class Abort(Exception):
+ """ raised when aborted """
+
class Base(object):
"""
The Base plugin class with all shared methods and every possible attribute for plugin definition.
@@ -83,6 +89,9 @@ class Base(object):
#: :class:`InteractionManager`
self.im = core.interactionManager
+ #: last interaction task
+ self.task = None
+
def logInfo(self, *args, **kwargs):
""" Print args to log at specific level
@@ -118,11 +127,7 @@ class Base(object):
getattr(self.log, level)("%s: %s" % (self.__name__, sep.join(strings)))
def setConfig(self, option, value):
- """ Set config value for current plugin
-
- :param option:
- :param value:
- """
+ """ Set config value for current plugin """
self.core.config.set(self.__name__, option, value)
def getConf(self, option):
@@ -130,11 +135,7 @@ class Base(object):
return self.core.config.get(self.__name__, option)
def getConfig(self, option):
- """ Returns config value for current plugin
-
- :param option:
- :return:
- """
+ """ Returns config value for current plugin """
return self.getConf(option)
def setStorage(self, key, value):
@@ -167,6 +168,14 @@ class Base(object):
sys.stdout = sys._stdout
embed()
+ def abort(self):
+ """ Check if plugin is in an abort state, is overwritten by subtypes"""
+ return False
+
+ def checkAbort(self):
+ """ Will be overwriten to determine if control flow should be aborted """
+ if self.abort: raise Abort()
+
def load(self, url, get={}, post={}, ref=True, cookies=True, just_header=False, decode=False):
"""Load content at url and returns it
@@ -180,6 +189,7 @@ class Base(object):
:return: Loaded content
"""
if not hasattr(self, "req"): raise Exception("Plugin type does not have Request attribute.")
+ self.checkAbort()
res = self.req.load(url, get, post, ref, cookies, just_header, decode=decode)
@@ -225,6 +235,92 @@ class Base(object):
return res
+ def invalidTask(self):
+ if self.task:
+ self.task.invalid()
+
+ def invalidCaptcha(self):
+ self.logDebug("Deprecated method .invalidCaptcha, use .invalidTask")
+ self.invalidTask()
+
+ def correctTask(self):
+ if self.task:
+ self.task.correct()
+
+ def correctCaptcha(self):
+ self.logDebug("Deprecated method .correctCaptcha, use .correctTask")
+ self.correctTask()
+
+ def decryptCaptcha(self, url, get={}, post={}, cookies=False, forceUser=False, imgtype='jpg',
+ result_type='textual'):
+ """ Loads a captcha and decrypts it with ocr, plugin, user input
+
+ :param url: url of captcha image
+ :param get: get part for request
+ :param post: post part for request
+ :param cookies: True if cookies should be enabled
+ :param forceUser: if True, ocr is not used
+ :param imgtype: Type of the Image
+ :param result_type: 'textual' if text is written on the captcha\
+ or 'positional' for captcha where the user have to click\
+ on a specific region on the captcha
+
+ :return: result of decrypting
+ """
+
+ img = self.load(url, get=get, post=post, cookies=cookies)
+
+ id = ("%.2f" % time())[-6:].replace(".", "")
+ temp_file = open(join("tmp", "tmpCaptcha_%s_%s.%s" % (self.__name__, id, imgtype)), "wb")
+ temp_file.write(img)
+ temp_file.close()
+
+ name = "%sOCR" % self.__name__
+ has_plugin = name in self.core.pluginManager.getPlugins("internal")
+
+ if self.core.captcha:
+ OCR = self.core.pluginManager.loadClass("internal", name)
+ else:
+ OCR = None
+
+ if OCR and not forceUser:
+ sleep(randint(3000, 5000) / 1000.0)
+ self.checkAbort()
+
+ ocr = OCR()
+ result = ocr.get_captcha(temp_file.name)
+ else:
+ task = self.im.newCaptchaTask(img, imgtype, temp_file.name, result_type)
+ self.task = task
+ self.im.handleTask(task)
+
+ while task.isWaiting():
+ if self.abort():
+ self.im.removeTask(task)
+ raise Abort()
+ sleep(1)
+
+ #TODO
+ self.im.removeTask(task)
+
+ 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)
+ elif not task.result:
+ self.fail(_("No captcha result obtained in appropiate time by any of the plugins."))
+
+ result = task.result
+ self.log.debug("Received captcha result: %s" % str(result))
+
+ if not self.core.debug:
+ try:
+ remove(temp_file.name)
+ except:
+ pass
+
+ return result
+
def fail(self, reason):
""" fail and give reason """
raise Fail(reason) \ No newline at end of file