summaryrefslogtreecommitdiffstats
path: root/pyload/plugins/base
diff options
context:
space:
mode:
authorGravatar Walter Purcaro <vuolter@gmail.com> 2014-11-15 07:26:01 +0100
committerGravatar Walter Purcaro <vuolter@gmail.com> 2014-11-15 07:26:01 +0100
commiteb61d1bb0a30fd32f99b93f847346c610fbc91d2 (patch)
treef889dd1b19c0496f3f88c478445165abd98f9c7a /pyload/plugins/base
parent[HTTPRequest] Raise Fail if write response fails (diff)
downloadpyload-eb61d1bb0a30fd32f99b93f847346c610fbc91d2.tar.xz
Update plugins after merging
Diffstat (limited to 'pyload/plugins/base')
-rw-r--r--pyload/plugins/base/Account.py305
-rw-r--r--pyload/plugins/base/Addon.py150
-rw-r--r--pyload/plugins/base/Captcha.py49
-rw-r--r--pyload/plugins/base/Container.py64
-rw-r--r--pyload/plugins/base/Crypter.py107
-rw-r--r--pyload/plugins/base/Hook.py166
-rw-r--r--pyload/plugins/base/Hoster.py21
-rw-r--r--pyload/plugins/base/OCR.py314
-rw-r--r--pyload/plugins/base/__init__.py0
9 files changed, 0 insertions, 1176 deletions
diff --git a/pyload/plugins/base/Account.py b/pyload/plugins/base/Account.py
deleted file mode 100644
index acb5c7d8b..000000000
--- a/pyload/plugins/base/Account.py
+++ /dev/null
@@ -1,305 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from random import choice
-from time import time
-from traceback import print_exc
-from threading import RLock
-
-from pyload.plugins.Plugin import Base
-from pyload.utils import compare_time, parseFileSize, lock
-
-
-class WrongPassword(Exception):
- pass
-
-
-class Account(Base):
- """
- Base class for every Account plugin.
- 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.03"
-
- __description__ = """Base account plugin"""
- __license__ = "GPLv3"
- __authors__ = [("mkaay", "mkaay@mkaay.de")]
-
-
- #: after that time (in minutes) pyload will relogin the account
- login_timeout = 10 * 60
- #: after that time (in minutes) account data will be reloaded
- info_threshold = 10 * 60
-
-
- def __init__(self, manager, accounts):
- Base.__init__(self, manager.core)
-
- self.manager = manager
- self.accounts = {}
- self.infos = {} #: cache for account information
- self.lock = RLock()
- self.timestamps = {}
-
- 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
-
- :param user: loginname
- :param data: data dictionary
- :param req: `Request` instance
- """
- pass
-
-
- @lock
- def _login(self, user, data):
- # set timestamp for login
- self.timestamps[user] = time()
-
- req = self.getAccountRequest(user)
- try:
- self.login(user, data, req)
- except WrongPassword:
- self.logWarning(
- _("Could not login with account %(user)s | %(msg)s") % {"user": user,
- "msg": _("Wrong Password")})
- success = data['valid'] = False
- except Exception, e:
- self.logWarning(
- _("Could not login with account %(user)s | %(msg)s") % {"user": user,
- "msg": e})
- success = data['valid'] = False
- if self.core.debug:
- print_exc()
- else:
- success = True
- finally:
- if req:
- req.close()
- return success
-
-
- def relogin(self, user):
- req = self.getAccountRequest(user)
- if req:
- req.cj.clear()
- req.close()
- if user in self.infos:
- del self.infos[user] #delete old information
-
- 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 """
-
- if user in self.accounts:
- self.accounts[user]['valid'] = True #do not remove or accounts will not login
- if password:
- self.accounts[user]['password'] = password
- self.relogin(user)
- return True
- if options:
- before = self.accounts[user]['options']
- self.accounts[user]['options'].update(options)
- return self.accounts[user]['options'] != before
- else:
- self.accounts[user] = {"password": password, "options": options, "valid": True}
- self._login(user, self.accounts[user])
- return True
-
-
- def removeAccount(self, user):
- if user in self.accounts:
- del self.accounts[user]
- if user in self.infos:
- del self.infos[user]
- 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!\\
- just use it to retrieve infos in hoster plugins. see `loadAccountInfo`
-
- :param name: username
- :param force: reloads cached account information
- :return: dictionary with information
- """
- data = Account.loadAccountInfo(self, name)
-
- if force or name not in self.infos:
- self.logDebug("Get Account Info for %s" % name)
- req = self.getAccountRequest(name)
-
- try:
- infos = self.loadAccountInfo(name, req)
- if not type(infos) == dict:
- raise Exception("Wrong return format")
- except Exception, e:
- infos = {"error": str(e)}
- print_exc()
-
- if req:
- req.close()
-
- self.logDebug("Account Info: %s" % infos)
-
- infos['timestamp'] = time()
- self.infos[name] = infos
- elif "timestamp" in self.infos[name] and self.infos[name][
- "timestamp"] + self.info_threshold * 60 < time():
- self.logDebug("Reached timeout for account data")
- self.scheduleRefresh(name)
-
- 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
-
- :param name:
- :param req: `Request` instance
- :return:
- """
- 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()
- if not user:
- return None
-
- req = self.core.requestFactory.getRequest(self.__name__, user)
- return req
-
-
- def getAccountCookies(self, user=None):
- if not user:
- user, data = self.selectAccount()
- if not user:
- return None
-
- 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 = []
- for user, data in self.accounts.iteritems():
- if not data['valid']: continue
-
- if "time" in data['options'] and data['options']['time']:
- time_data = ""
- try:
- time_data = data['options']['time'][0]
- start, end = time_data.split("-")
- if not compare_time(start.split(":"), end.split(":")):
- continue
- except:
- self.logWarning(_("Your Time %s has wrong format, use: 1:22-3:44") % time_data)
-
- if user in self.infos:
- if "validuntil" in self.infos[user]:
- if self.infos[user]['validuntil'] > 0 and time() > self.infos[user]['validuntil']:
- continue
- if "trafficleft" in self.infos[user]:
- if self.infos[user]['trafficleft'] == 0:
- continue
-
- usable.append((user, data))
-
- 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)
-
-
- 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)
-
- 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)
-
- 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 """
- if user in self.timestamps:
- if self.login_timeout > 0 and self.timestamps[user] + self.login_timeout * 60 < time():
- self.logDebug("Reached login timeout for %s" % user)
- return self.relogin(user)
- else:
- return True
- else:
- return False
diff --git a/pyload/plugins/base/Addon.py b/pyload/plugins/base/Addon.py
deleted file mode 100644
index 2dfeba83c..000000000
--- a/pyload/plugins/base/Addon.py
+++ /dev/null
@@ -1,150 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from traceback import print_exc
-
-from pyload.plugins.Plugin import Base
-
-
-class Expose(object):
- """ used for decoration to declare rpc services """
-
- def __new__(cls, f, *args, **kwargs):
- addonManager.addRPC(f.__module__, f.func_name, f.func_doc)
- return f
-
-
-def threaded(f):
-
- def run(*args,**kwargs):
- addonManager.startThread(f, *args, **kwargs)
- return run
-
-
-class Addon(Base):
- """
- Base class for addon plugins.
- """
- __name__ = "Addon"
- __type__ = "addon"
- __version__ = "0.2"
-
- __config__ = [("name", "type", "desc", "default")]
-
- __description__ = """Interface for addon"""
- __authors__ = [("mkaay", "mkaay@mkaay.de"),
- ("RaNaN", "RaNaN@pyload.org")]
-
-
- #: automatically register event listeners for functions, attribute will be deleted dont use it yourself
- event_map = None
-
- # Alternative to event_map
- #: List of events the plugin can handle, name the functions exactly like eventname.
- event_list = None # dont make duplicate entries in event_map
-
- #: periodic call interval in secondc
- interval = 60
-
-
- def __init__(self, core, manager):
- Base.__init__(self, core)
-
- #: Provide information in dict here, usable by API `getInfo`
- self.info = None
-
- #: Callback of periodical job task, used by AddonManager
- self.cb = None
-
- #: `AddonManager`
- self.manager = manager
-
- #register events
- if self.event_map:
- for event, funcs in self.event_map.iteritems():
- if type(funcs) in (list, tuple):
- for f in funcs:
- self.manager.addEvent(event, getattr(self,f))
- else:
- self.manager.addEvent(event, getattr(self,funcs))
-
- #delete for various reasons
- self.event_map = None
-
- if self.event_list:
- for f in self.event_list:
- self.manager.addEvent(f, getattr(self,f))
-
- self.event_list = None
-
- self.setup()
- self.initPeriodical()
-
-
- def initPeriodical(self):
- if self.interval >=1:
- self.cb = self.core.scheduler.addJob(0, self._periodical, threaded=False)
-
- def _periodical(self):
- try:
- if self.isActivated(): self.periodical()
- except Exception, e:
- self.logError(_("Error executing addon: %s") % e)
- if self.core.debug:
- print_exc()
-
- self.cb = self.core.scheduler.addJob(self.interval, self._periodical, threaded=False)
-
-
- def __repr__(self):
- return "<Addon %s>" % self.__name__
-
- def setup(self):
- """ more init stuff if needed """
- pass
-
- def unload(self):
- """ called when addon was deactivated """
- pass
-
- def isActivated(self):
- """ checks if addon is activated"""
- return self.config.getPlugin(self.__name__, "activated")
-
-
- #event methods - overwrite these if needed
- 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/Captcha.py b/pyload/plugins/base/Captcha.py
deleted file mode 100644
index 86b073710..000000000
--- a/pyload/plugins/base/Captcha.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugins.Plugin import Plugin
-
-
-class Captcha(Plugin):
- __name__ = "Captcha"
- __version__ = "0.09"
-
- __description__ = """Base captcha service plugin"""
- __authors__ = [("pyLoad Team", "admin@pyload.org")]
-
-
- key = None
-
- KEY_PATTERN = None
-
-
- def __init__(self, plugin):
- self.plugin = plugin
-
-
- def detect_key(self, html=None):
- if not html:
- if hasattr(self.plugin, "html") and self.plugin.html:
- html = self.plugin.html
- else:
- errmsg = "%s html missing" % self.__name__
- self.plugin.fail(errmsg)
- raise TypeError(errmsg)
-
- m = re.search(self.KEY_PATTERN, html)
- if m:
- self.key = m.group("KEY")
- self.plugin.logDebug("%s key: %s" % (self.__name__, self.key))
- return self.key
- else:
- self.plugin.logDebug("%s key not found" % self.__name__)
- return None
-
-
- def challenge(self, key=None):
- raise NotImplementedError
-
-
- def result(self, server, challenge):
- raise NotImplementedError
diff --git a/pyload/plugins/base/Container.py b/pyload/plugins/base/Container.py
deleted file mode 100644
index 1bb2e204b..000000000
--- a/pyload/plugins/base/Container.py
+++ /dev/null
@@ -1,64 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from os import remove
-from os.path import basename, exists
-
-from pyload.plugins.base.Crypter import Crypter
-from pyload.utils import safe_join
-
-
-class Container(Crypter):
- __name__ = "Container"
- __type__ = "container"
- __version__ = "0.01"
-
- __pattern__ = None
- __config__ = [] #: [("name", "type", "desc", "default")]
-
- __description__ = """Base container decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("mkaay", "mkaay@mkaay.de")]
-
-
- def preprocessing(self, thread):
- """prepare"""
-
- self.setup()
- self.thread = thread
-
- self.loadToDisk()
-
- self.decrypt(self.pyfile)
- self.deleteTmp()
-
- self.createPackages()
-
-
- def loadToDisk(self):
- """loads container to disk if its stored remotely and overwrite url,
- or check existent on several places at disk"""
-
- if self.pyfile.url.startswith("http"):
- 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)
- 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)
- if not exists(self.pyfile.url):
- if exists(safe_join(pypath, self.pyfile.url)):
- self.pyfile.url = safe_join(pypath, self.pyfile.url)
- else:
- self.fail(_("File not exists"))
-
-
- def deleteTmp(self):
- if self.pyfile.name.startswith("tmp_"):
- remove(self.pyfile.url)
diff --git a/pyload/plugins/base/Crypter.py b/pyload/plugins/base/Crypter.py
deleted file mode 100644
index 0a79300dd..000000000
--- a/pyload/plugins/base/Crypter.py
+++ /dev/null
@@ -1,107 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugins.Plugin import Plugin
-from module.utils import save_path
-
-
-class Crypter(Plugin):
- __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"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- 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 = []
-
- 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()
-
-
- def decrypt(self, pyfile):
- 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 """
-
- 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: %s" % name,
- "%d links" % len(links),
- "Saved to folder: %s" % folder if folder else "Saved to download folder")
-
- links = map(lambda x: x.decode("utf-8"), links)
-
- pid = self.core.api.addPackage(name, links, package_queue)
-
- if package_password:
- self.core.api.setPackageData(pid, {"password": package_password})
-
- setFolder = lambda x: self.core.api.setPackageData(pid, {"folder": x or ""}) #: Workaround to do not break API addPackage method
-
- 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
deleted file mode 100644
index 5cd528b7e..000000000
--- a/pyload/plugins/base/Hook.py
+++ /dev/null
@@ -1,166 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from traceback import print_exc
-
-from pyload.plugins.Plugin import Base
-
-
-class Expose(object):
- """ used for decoration to declare rpc services """
-
- def __new__(cls, f, *args, **kwargs):
- addonManager.addRPC(f.__module__, f.func_name, f.func_doc)
- return f
-
-
-def threaded(f):
-
- def run(*args,**kwargs):
- addonManager.startThread(f, *args, **kwargs)
- return run
-
-
-class Hook(Base):
- """
- Base class for hook plugins.
- """
- __name__ = "Hook"
- __type__ = "hook"
- __version__ = "0.03"
-
- __config__ = [] #: [("name", "type", "desc", "default")]
-
- __description__ = """Interface for hook"""
- __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
- event_map = None
-
- # Alternative to event_map
- #: List of events the plugin can handle, name the functions exactly like eventname.
- event_list = None # dont make duplicate entries in event_map
-
- #: periodic call interval in secondc
- interval = 60
-
-
- def __init__(self, core, manager):
- Base.__init__(self, core)
-
- #: Provide information in dict here, usable by API `getInfo`
- self.info = {}
-
- #: Callback of periodical job task, used by AddonManager
- self.cb = None
-
- #: `AddonManager`
- self.manager = manager
-
- #register events
- if self.event_map:
- for event, funcs in self.event_map.iteritems():
- if type(funcs) in (list, tuple):
- for f in funcs:
- self.manager.addEvent(event, getattr(self,f))
- else:
- self.manager.addEvent(event, getattr(self,funcs))
-
- #delete for various reasons
- self.event_map = None
-
- if self.event_list:
- for f in self.event_list:
- self.manager.addEvent(f, getattr(self,f))
-
- self.event_list = None
-
- self.setup()
- self.initPeriodical()
-
-
- def initPeriodical(self):
- if self.interval >=1:
- self.cb = self.core.scheduler.addJob(0, self._periodical, threaded=False)
-
-
- def _periodical(self):
- try:
- if self.isActivated(): self.periodical()
- except Exception, e:
- self.logError(_("Error executing hook: %s") % e)
- if self.core.debug:
- print_exc()
-
- self.cb = self.core.scheduler.addJob(self.interval, self._periodical, threaded=False)
-
-
- 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")
-
-
- #event methods - overwrite these if needed
- 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
deleted file mode 100644
index a89727ba7..000000000
--- a/pyload/plugins/base/Hoster.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugins.Plugin import Plugin
-
-
-def getInfo(self):
- #result = [ .. (name, size, status, url) .. ]
- return
-
-
-class Hoster(Plugin):
- __name__ = "Hoster"
- __type__ = "hoster"
- __version__ = "0.02"
-
- __pattern__ = None
- __config__ = [] #: [("name", "type", "desc", "default")]
-
- __description__ = """Base hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("mkaay", "mkaay@mkaay.de")]
diff --git a/pyload/plugins/base/OCR.py b/pyload/plugins/base/OCR.py
deleted file mode 100644
index c3a47e7ef..000000000
--- a/pyload/plugins/base/OCR.py
+++ /dev/null
@@ -1,314 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import with_statement
-
-try:
- from PIL import Image, GifImagePlugin, JpegImagePlugin, PngImagePlugin, TiffImagePlugin
-except ImportError:
- import Image, GifImagePlugin, JpegImagePlugin, PngImagePlugin, TiffImagePlugin
-
-import logging
-import subprocess
-
-from os.path import abspath, join
-
-
-class OCR(object):
- __name__ = "OCR"
- __type__ = "ocr"
- __version__ = "0.1"
-
- __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 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"""
-
- popen = subprocess.Popen(command, bufsize=-1, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- popen.wait()
- output = popen.stdout.read() + " | " + popen.stderr.read()
- popen.stdout.close()
- 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")
- 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(tmpTif.name, 'TIFF')
-
- if os.name == "nt":
- tessparams = [join(pypath, "tesseract", "tesseract.exe")]
- else:
- tessparams = ['tesseract']
-
- tessparams.extend([abspath(tmpTif.name), abspath(tmpTxt.name).replace(".txt", "")] )
-
- if subset and (digits or lowercase or uppercase):
- #tmpSub = tempfile.NamedTemporaryFile(suffix=".subset")
- tmpSub = open(join("tmp", "tmpSub_%s.subset" % self.__name__), "wb")
- tmpSub.write("tessedit_char_whitelist ")
- if digits:
- tmpSub.write("0123456789")
- if lowercase:
- tmpSub.write("abcdefghijklmnopqrstuvwxyz")
- if uppercase:
- tmpSub.write("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
- tmpSub.write("\n")
- tessparams.append("nobatch")
- tessparams.append(abspath(tmpSub.name))
- tmpSub.close()
-
- self.logger.debug("run tesseract")
- self.run(tessparams)
- self.logger.debug("read txt")
-
- try:
- with open(tmpTxt.name, 'r') as f:
- self.result_captcha = f.read().replace("\n", "")
- except:
- self.result_captcha = ""
-
- self.logger.debug(self.result_captcha)
- try:
- 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
- for x in xrange(w):
- for y in xrange(h):
- if self.pixels[x, y] > limit:
- self.pixels[x, y] = 255
- else:
- self.pixels[x, y] = 0
-
-
- def clean(self, allowed):
- pixels = self.pixels
-
- w, h = self.image.size
-
- for x in xrange(w):
- for y in xrange(h):
- if pixels[x, y] == 255:
- continue
- # No point in processing white pixels since we only want to remove black pixel
- count = 0
-
- try:
- if pixels[x - 1, y - 1] != 255:
- count += 1
- if pixels[x - 1, y] != 255:
- count += 1
- if pixels[x - 1, y + 1] != 255:
- count += 1
- if pixels[x, y + 1] != 255:
- count += 1
- if pixels[x + 1, y + 1] != 255:
- count += 1
- if pixels[x + 1, y] != 255:
- count += 1
- if pixels[x + 1, y - 1] != 255:
- count += 1
- if pixels[x, y - 1] != 255:
- count += 1
- except:
- pass
-
- # not enough neighbors are dark pixels so mark this pixel
- # to be changed to white
- if count < allowed:
- pixels[x, y] = 1
-
- # second pass: this time set all 1's to 255 (white)
- for x in xrange(w):
- for y in xrange(h):
- if pixels[x, y] == 1:
- pixels[x, y] = 255
-
- self.pixels = pixels
-
-
- def derotate_by_average(self):
- """rotate by checking each angle and guess most suitable"""
-
- w, h = self.image.size
- pixels = self.pixels
-
- for x in xrange(w):
- for y in xrange(h):
- if pixels[x, y] == 0:
- pixels[x, y] = 155
-
- highest = {}
- counts = {}
-
- for angle in xrange(-45, 45):
-
- tmpimage = self.image.rotate(angle)
-
- pixels = tmpimage.load()
-
- w, h = self.image.size
-
- for x in xrange(w):
- for y in xrange(h):
- if pixels[x, y] == 0:
- pixels[x, y] = 255
-
- count = {}
-
- for x in xrange(w):
- count[x] = 0
- for y in xrange(h):
- if pixels[x, y] == 155:
- count[x] += 1
-
- sum = 0
- cnt = 0
-
- for x in count.values():
- if x != 0:
- sum += x
- cnt += 1
-
- avg = sum / cnt
- counts[angle] = cnt
- highest[angle] = 0
- for x in count.values():
- if x > highest[angle]:
- highest[angle] = x
-
- highest[angle] = highest[angle] - avg
-
- hkey = 0
- hvalue = 0
-
- for key, value in highest.iteritems():
- if value > hvalue:
- hkey = key
- hvalue = value
-
- self.image = self.image.rotate(hkey)
- pixels = self.image.load()
-
- for x in xrange(w):
- for y in xrange(h):
- if pixels[x, y] == 0:
- pixels[x, y] = 255
-
- if pixels[x, y] == 155:
- pixels[x, y] = 0
-
- self.pixels = pixels
-
-
- def split_captcha_letters(self):
- captcha = self.image
- started = False
- letters = []
- width, height = captcha.size
- bottomY, topY = 0, height
- pixels = captcha.load()
-
- for x in xrange(width):
- black_pixel_in_col = False
- for y in xrange(height):
- if pixels[x, y] != 255:
- if not started:
- started = True
- firstX = x
- lastX = x
-
- if y > bottomY:
- bottomY = y
- if y < topY:
- topY = y
- if x > lastX:
- lastX = x
-
- black_pixel_in_col = True
-
- if black_pixel_in_col is False and started is True:
- rect = (firstX, topY, lastX, bottomY)
- new_captcha = captcha.crop(rect)
-
- w, h = new_captcha.size
- if w > 5 and h > 5:
- letters.append(new_captcha)
-
- started = False
- bottomY, topY = 0, height
-
- return letters
-
-
- def correct(self, values, var=None):
- if var:
- result = var
- else:
- result = self.result_captcha
-
- for key, item in values.iteritems():
-
- if key.__class__ == str:
- result = result.replace(key, item)
- else:
- for expr in key:
- result = result.replace(expr, item)
-
- if var:
- return result
- else:
- self.result_captcha = result
diff --git a/pyload/plugins/base/__init__.py b/pyload/plugins/base/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/pyload/plugins/base/__init__.py
+++ /dev/null