diff options
author | RaNaN <Mast3rRaNaN@hotmail.de> | 2010-12-22 14:25:56 +0100 |
---|---|---|
committer | RaNaN <Mast3rRaNaN@hotmail.de> | 2010-12-22 14:25:56 +0100 |
commit | 052d09687627999b91b45a8c0224aa9de4769924 (patch) | |
tree | 0ed3dd7cc49cd43fd2ce4c1b1573a13265daefb6 /module/plugins | |
parent | refactoring part 1: deprecation warnings, reduced debug, cookie compatibility (diff) | |
download | pyload-052d09687627999b91b45a8c0224aa9de4769924.tar.xz |
cleaned request factory
Diffstat (limited to 'module/plugins')
-rw-r--r-- | module/plugins/AccountManager.py | 179 | ||||
-rw-r--r-- | module/plugins/PluginManager.py | 329 |
2 files changed, 508 insertions, 0 deletions
diff --git a/module/plugins/AccountManager.py b/module/plugins/AccountManager.py new file mode 100644 index 000000000..ab35334fc --- /dev/null +++ b/module/plugins/AccountManager.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: RaNaN +""" + +from os.path import exists +from shutil import copy + +from module.PullEvents import AccountUpdateEvent + +ACC_VERSION = 1 + +######################################################################## +class AccountManager(): + """manages all accounts""" + + #---------------------------------------------------------------------- + def __init__(self, core): + """Constructor""" + + self.core = core + + self.accounts = {} # key = ( plugin ) + self.plugins = {} + + self.initAccountPlugins() + + self.loadAccounts() + + self.saveAccounts() # save to add categories to conf + + #---------------------------------------------------------------------- + def getAccountPlugin(self, plugin): + """get account instance for plugin or None if anonymous""" + if self.accounts.has_key(plugin): + if not self.plugins.has_key(plugin): + self.plugins[plugin] = self.core.pluginManager.getAccountPlugin(plugin)(self, self.accounts[plugin]) + + return self.plugins[plugin] + else: + return None + + def getAccountPlugins(self): + """ get all account instances""" + + plugins = [] + for plugin in self.accounts.keys(): + plugins.append(self.getAccountPlugin(plugin)) + + return plugins + #---------------------------------------------------------------------- + def loadAccounts(self): + """loads all accounts available""" + + if not exists("accounts.conf"): + f = open("accounts.conf", "wb") + f.write("version: " + str(ACC_VERSION)) + f.close() + + f = open("accounts.conf", "rb") + content = f.readlines() + version = content[0].split(":")[1].strip() if content else "" + f.close() + + if not version or int(version) < ACC_VERSION: + copy("accounts.conf", "accounts.backup") + f = open("accounts.conf", "wb") + f.write("version: " + str(ACC_VERSION)) + f.close() + self.core.log.warning(_("Account settings deleted, due to new config format.")) + return + + + + plugin = "" + name = "" + + for line in content[1:]: + line = line.strip() + + if not line: continue + if line.startswith("#"): continue + if line.startswith("version"): continue + + if line.endswith(":") and line.count(":") == 1: + plugin = line[:-1] + self.accounts[plugin] = {} + + elif line.startswith("@"): + option = line[1:].split() + self.accounts[plugin][name]["options"][option[0]] = [] if len(option) < 2 else ([option[1]] if len(option) < 3 else option[1:]) + + elif ":" in line: + name, sep, pw = line.partition(":") + self.accounts[plugin][name] = {"password": pw, "options": {}, "valid": True} + #---------------------------------------------------------------------- + def saveAccounts(self): + """save all account information""" + + f = open("accounts.conf", "wb") + f.write("version: " + str(ACC_VERSION) + "\n") + + for plugin, accounts in self.accounts.iteritems(): + f.write("\n") + f.write(plugin+":\n") + + for name,data in accounts.iteritems(): + f.write("\n\t%s:%s\n" % (name,data["password"]) ) + for option, values in data["options"].iteritems(): + f.write("\t@%s %s\n" % (option, " ".join(values))) + + f.close() + + + #---------------------------------------------------------------------- + def initAccountPlugins(self): + """init names""" + for name in self.core.pluginManager.getAccountPlugins(): + self.accounts[name] = {} + + #---------------------------------------------------------------------- + def updateAccount(self, plugin , user, password=None, options={}): + """add or update account""" + if self.accounts.has_key(plugin): + p = self.getAccountPlugin(plugin) + p.updateAccounts(user, password, options) + #since accounts is a ref in plugin self.accounts doesnt need to be updated here + + self.saveAccounts() + p.getAllAccounts(force=True) + self.core.scheduler.addJob(0, self.core.accountManager.getAccountInfos) + + #---------------------------------------------------------------------- + def removeAccount(self, plugin, user): + """remove account""" + + if self.accounts.has_key(plugin): + p = self.getAccountPlugin(plugin) + p.removeAccount(user) + + self.saveAccounts() + p.getAllAccounts(force=True) + self.core.scheduler.addJob(0, self.core.accountManager.getAccountInfos) + + + def getAccountInfos(self, force=True, refresh=False): + data = {} + + if refresh: + self.core.scheduler.addJob(0, self.core.accountManager.getAccountInfos) + force = False + + for p in self.accounts.keys(): + if self.accounts[p]: + p = self.getAccountPlugin(p) + data[p.__name__] = p.getAllAccounts(force) + else: + data[p] = [] + e = AccountUpdateEvent() + self.core.pullManager.addEvent(e) + return data + + def sendChange(self): + e = AccountUpdateEvent() + self.core.pullManager.addEvent(e) diff --git a/module/plugins/PluginManager.py b/module/plugins/PluginManager.py new file mode 100644 index 000000000..3f11c067b --- /dev/null +++ b/module/plugins/PluginManager.py @@ -0,0 +1,329 @@ +# -*- coding: utf-8 -*- + +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: mkaay, RaNaN +""" + +import re +import sys + +from os import listdir +from os import makedirs + +from os.path import isfile +from os.path import join +from os.path import exists +from os.path import abspath + +from sys import version_info +from itertools import chain + +try: + from ast import literal_eval +except ImportError: # python 2.5 + from module.SafeEval import safe_eval as literal_eval + + +IGNORE = ["FreakshareNet"] +#ignore this plugins in homefolder, add deleted plugins here + +class PluginManager(): + def __init__(self, core): + self.core = core + + #self.config = self.core.config + self.log = core.log + + self.crypterPlugins = {} + self.containerPlugins = {} + self.hosterPlugins = {} + self.captchaPlugins = {} + self.accountPlugins = {} + self.hookPlugins = {} + + self.createHomeDirs() + + self.createIndex() + + #@TODO plugin updater + #---------------------------------------------------------------------- + def createHomeDirs(self): + """create homedirectories containing plugins""" + #@TODO implement... + pass + + def createIndex(self): + """create information for all plugins available""" + + sys.path.append(abspath("")) + + if not exists("userplugins"): + makedirs("userplugins") + if not exists(join("userplugins", "__init__.py")): + f = open(join("userplugins", "__init__.py"), "wb") + f.close() + + self.rePattern = re.compile(r'__pattern__.*=.*r("|\')([^"\']+)') + self.reVersion = re.compile(r'__version__.*=.*("|\')([0-9.]+)') + self.reConfig = re.compile(r'__config__.*=.*\[([^\]]+)', re.MULTILINE) + + self.crypterPlugins = self.parse(_("Crypter"), "crypter", pattern=True) + self.containerPlugins = self.parse(_("Container"), "container", pattern=True) + self.hosterPlugins = self.parse(_("Hoster") ,"hoster", pattern=True) + + self.captchaPlugins = self.parse(_("Captcha"), "captcha") + self.accountPlugins = self.parse(_("Account"), "accounts", create=True) + self.hookPlugins = self.parse(_("Hook"), "hooks") + + self.log.debug(_("created index of plugins")) + + def parse(self, typ, folder, create=False, pattern=False, home={}): + """ + returns dict with information + home contains parsed plugins from module. + + { + name : {path, version, config, (pattern, re), (plugin, class)} + } + + """ + plugins = {} + if home: + pfolder = join("userplugins", folder) + if not exists(pfolder): + makedirs(pfolder) + if not exists(join(pfolder, "__init__.py")): + f = open(join(pfolder, "__init__.py"), "wb") + f.close() + + else: + pfolder = join(pypath, "module", "plugins", folder) + + for f in listdir(pfolder): + if (isfile(join(pfolder, f)) and f.endswith(".py") or f.endswith("_25.pyc") or f.endswith("_26.pyc") or f.endswith("_27.pyc")) and not f.startswith("_"): + data = open(join(pfolder, f)) + content = data.read() + data.close() + + if f.endswith("_25.pyc") and not version_info[0:2] == (2, 5): + continue + elif f.endswith("_26.pyc") and not version_info[0:2] == (2, 6): + continue + elif f.endswith("_27.pyc") and not version_info[0:2] == (2, 7): + continue + + name = f[:-3] + if name[-1] == "." : name = name[:-4] + + + version = self.reVersion.findall(content) + if version: + version = float(version[0][1]) + else: + version = 0 + + if home and home.has_key(name): + if home[name]["v"] >= version: + continue + + + plugins[name] = {} + plugins[name]["v"] = version + + + module = f.replace(".pyc","").replace(".py","") + if home: + if name in IGNORE: + del plugins[name] + continue + path = "userplugins.%s.%s" % (folder, module) + else: + path = "module.plugins.%s.%s" % (folder, module) + + plugins[name]["name"] = module + plugins[name]["path"] = path + + + if pattern: + pattern = self.rePattern.findall(content) + + if pattern: + pattern = pattern[0][1] + else: + pattern = "^unmachtable$" + + plugins[name]["pattern"] = pattern + + try: + plugins[name]["re"] = re.compile(pattern) + except: + self.log.error(_("%s has invalid pattern.") % name) + + + config = self.reConfig.findall(content) + + if config: + config = literal_eval(config[0].strip().replace("\n", "").replace("\r", "")) + if type(config[0]) == tuple: + config = [list(x) for x in config] + else: + config = [list(config)] + + if folder == "hooks": + config.append( ["load", "bool", "Load on startup", True if name not in ("XMPPInterface", "MultiHome") else False] ) + + for item in config: + self.core.config.addPluginConfig([name]+item) + + if not home: + temp = self.parse(typ, folder, create, pattern, plugins) + plugins.update(temp) + + return plugins + + #---------------------------------------------------------------------- + def parseUrls(self, urls): + """parse plugins for given list of urls""" + + last = None + res = [] # tupels of (url, plugin) + + for url in urls: + if type(url) not in (str, unicode, buffer): continue + found = False + + if last and last[1]["re"].match(url): + res.append((url, last[0])) + continue + + for name, value in chain(self.crypterPlugins.iteritems(), self.hosterPlugins.iteritems(), self.containerPlugins.iteritems() ): + if value["re"].match(url): + res.append((url, name)) + last = (name, value) + found = True + break + + if not found: + res.append((url, "BasePlugin")) + + return res + + #---------------------------------------------------------------------- + def getPlugin(self, name): + """return plugin module from hoster|decrypter|container""" + plugin = None + + if self.containerPlugins.has_key(name): + plugin = self.containerPlugins[name] + if self.crypterPlugins.has_key(name): + plugin = self.crypterPlugins[name] + if self.hosterPlugins.has_key(name): + plugin = self.hosterPlugins[name] + + + if plugin.has_key("module"): + return plugin["module"] + + plugin["module"] = __import__(plugin["path"], globals(), locals(), [plugin["name"]] , -1) + + return plugin["module"] + + + #---------------------------------------------------------------------- + def getCaptchaPlugin(self, name): + """return captcha modul if existent""" + if self.captchaPlugins.has_key(name): + plugin = self.captchaPlugins[name] + if plugin.has_key("class"): + return plugin["class"] + + module = __import__(plugin["path"], globals(), locals(), [plugin["name"]] , -1) + plugin["class"] = getattr(module, name) + + return plugin["class"] + + return None + #---------------------------------------------------------------------- + def getAccountPlugin(self, name): + """return account class if existent""" + if self.accountPlugins.has_key(name): + plugin = self.accountPlugins[name] + if plugin.has_key("class"): + return plugin["class"] + + module = __import__(plugin["path"], globals(), locals(), [plugin["name"]] , -1) + plugin["class"] = getattr(module, plugin["name"]) + + return plugin["class"] + + return None + + #---------------------------------------------------------------------- + def getAccountPlugins(self): + """return list of account plugin names""" + res = [] + + for name in self.accountPlugins.keys(): + res.append(name) + + return res + #---------------------------------------------------------------------- + def getHookPlugins(self): + """return list of hook classes""" + + classes = [] + + for name, value in self.hookPlugins.iteritems(): + if value.has_key("class"): + classes.append(value["class"]) + continue + + if not self.core.config.getPlugin(name, "load"): + continue + + try: + module = __import__(value["path"], globals(), locals(), [value["name"]] , -1) + except Exception, e: + self.log.error(_("Error importing %(name)s: %(msg)s") % {"name": name, "msg": str(e) }) + self.log.error(_("You should fix dependicies or deactivate load on startup.")) + continue + + pluginClass = getattr(module, name) + + value["class"] = pluginClass + + classes.append(pluginClass) + + return classes + + +if __name__ == "__main__": + _ = lambda x : x + pypath = "/home/christian/Projekte/pyload-0.4/module/plugins" + + from time import time + + p = PluginManager(None) + + a = time() + + test = [ "http://www.youtube.com/watch?v=%s" % x for x in range(0,100) ] + print p.parseUrls(test) + + b = time() + + print b-a ,"s" + |