summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2012-01-08 14:44:59 +0100
committerGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2012-01-08 14:44:59 +0100
commitbac28b7740aae772636d8b90e291d9c17dfd59a7 (patch)
tree08b6bd4f00cf27819f06d24f363d633b852f50a3
parentsome cleanups (diff)
downloadpyload-bac28b7740aae772636d8b90e291d9c17dfd59a7.tar.xz
new MultiHoster hook
-rw-r--r--module/HookManager.py23
-rw-r--r--module/PyFile.py7
-rw-r--r--module/plugins/AccountManager.py18
-rw-r--r--module/plugins/Hook.py4
-rw-r--r--module/plugins/MultiHoster.py12
-rw-r--r--module/plugins/PluginManager.py37
-rw-r--r--module/plugins/accounts/RealdebridCom.py22
-rw-r--r--module/plugins/hooks/ClickAndLoad.py2
-rw-r--r--module/plugins/hooks/MultiHoster.py100
-rw-r--r--module/plugins/hooks/RealdebridCom.py24
-rw-r--r--module/plugins/hoster/RealdebridCom.py5
-rw-r--r--module/plugins/internal/MultiHoster.py85
-rw-r--r--module/threads/DownloadThread.py4
-rw-r--r--module/threads/InfoThread.py4
-rw-r--r--module/web/pyload_app.py4
15 files changed, 179 insertions, 172 deletions
diff --git a/module/HookManager.py b/module/HookManager.py
index b915341e3..3691fe3ed 100644
--- a/module/HookManager.py
+++ b/module/HookManager.py
@@ -28,6 +28,9 @@ from module.threads.HookThread import HookThread
from module.plugins.PluginManager import literal_eval
from utils import lock, to_string
+def class_name(p):
+ return p.rpartition(".")[2]
+
class HookManager:
""" Manages hooks, loading, unloading. """
@@ -68,7 +71,7 @@ class HookManager:
print_exc()
def addRPC(self, plugin, func, doc):
- plugin = plugin.rpartition(".")[2]
+ plugin = class_name(plugin)
doc = doc.strip() if doc else ""
if plugin in self.methods:
@@ -141,6 +144,7 @@ class HookManager:
# active the hook in new thread
start_new_thread(plugin.activate, tuple())
+ self.registerEvents()
@lock
def deactivateHook(self, plugin):
@@ -168,6 +172,8 @@ class HookManager:
if plugin.isActivated():
self.call(plugin, "activate")
+ self.registerEvents()
+
def deactivateHooks(self):
""" Called when core is shutting down """
self.log.info(_("Deactivating Plugins..."))
@@ -219,10 +225,21 @@ class HookManager:
return info
def addEventListener(self, plugin, func, event):
- pass
+ plugin = class_name(plugin)
+ if plugin not in self.events:
+ self.events[plugin] = []
+ self.events[plugin].append((func, event))
+
+ def registerEvents(self):
+ for name, plugin in self.plugins.iteritems():
+ if name in self.events:
+ for func, event in self.events[name]:
+ self.addEvent(event, getattr(plugin, func))
+ # clean up
+ del self.events[name]
def addConfigHandler(self, plugin, func):
- pass
+ pass #TODO
def addEvent(self, *args):
self.core.eventManager.addEvent(*args)
diff --git a/module/PyFile.py b/module/PyFile.py
index b446fde65..0c4c20705 100644
--- a/module/PyFile.py
+++ b/module/PyFile.py
@@ -51,7 +51,7 @@ class PyFile(object):
"""
__slots__ = ("m", "id", "url", "name", "size", "_size", "status", "pluginname", "packageid",
"error", "order", "lock", "plugin", "waitUntil", "active", "abort", "statusname",
- "reconnected", "progress", "maxprogress", "pluginmodule", "pluginclass")
+ "reconnected", "progress", "maxprogress", "pluginclass")
def __init__(self, manager, id, url, name, size, status, error, pluginname, package, order):
self.m = manager
@@ -91,14 +91,13 @@ class PyFile(object):
size = property(lambda self: self._size, setSize)
def __repr__(self):
- return "PyFile %s: %s@%s" % (self.id, self.name, self.pluginname)
+ return "<PyFile %s: %s@%s>" % (self.id, self.name, self.pluginname)
@lock
def initPlugin(self):
""" inits plugin instance """
if not self.plugin:
- self.pluginmodule = self.m.core.pluginManager.getPlugin(self.pluginname)
- self.pluginclass = getattr(self.pluginmodule, self.m.core.pluginManager.getPluginName(self.pluginname))
+ self.pluginclass = self.m.core.pluginManager.getPlugin(self.pluginname)
self.plugin = self.pluginclass(self)
@lock
diff --git a/module/plugins/AccountManager.py b/module/plugins/AccountManager.py
index 00dd2ccc6..c610d10e0 100644
--- a/module/plugins/AccountManager.py
+++ b/module/plugins/AccountManager.py
@@ -48,6 +48,12 @@ class AccountManager:
return
+ def iterAccounts(self):
+ """ yields login, account for all accounts"""
+ for name, data in self.accounts.iteritems():
+ for login, account in data.iteritems():
+ yield login, account
+
def saveAccounts(self):
"""save all account information"""
@@ -71,6 +77,9 @@ class AccountManager:
self.accounts[plugin][loginname] = klass(self, loginname, password, options)
+ def getAccount(self, plugin, user):
+ return self.accounts[plugin].get(user, None)
+
@lock
def updateAccount(self, plugin, user, password=None, options={}):
"""add or update account"""
@@ -84,7 +93,7 @@ class AccountManager:
self.createAccount(plugin, user, password, options)
self.saveAccounts()
- self.sendChange()
+ self.sendChange(plugin, user)
@lock
def removeAccount(self, plugin, user):
@@ -92,7 +101,7 @@ class AccountManager:
if plugin in self.accounts and user in self.accounts[plugin]:
del self.accounts[plugin][user]
self.core.db.removeAccount(plugin, user)
- self.sendChange()
+ self.core.eventManager.dispatchEvent("accountDeleted", plugin, user)
else:
self.core.log.debug("Remove non existing account %s %s" % (plugin, user))
@@ -128,6 +137,5 @@ class AccountManager:
for acc in p.itervalues():
acc.getAccountInfo(True)
-
- def sendChange(self):
- self.core.eventManager.dispatchEvent("accountsUpdated") \ No newline at end of file
+ def sendChange(self, plugin, name):
+ self.core.eventManager.dispatchEvent("accountUpdated", plugin, name) \ No newline at end of file
diff --git a/module/plugins/Hook.py b/module/plugins/Hook.py
index 6e2057f03..c0ce7d99c 100644
--- a/module/plugins/Hook.py
+++ b/module/plugins/Hook.py
@@ -98,6 +98,7 @@ class Hook(Base):
self.event_list = None
self.initPeriodical()
+ self.init()
self.setup()
def initPeriodical(self):
@@ -122,6 +123,9 @@ class Hook(Base):
""" checks if hook is activated"""
return self.getConfig("activated")
+ def init(self):
+ pass
+
def setup(self):
""" more init stuff if needed """
pass
diff --git a/module/plugins/MultiHoster.py b/module/plugins/MultiHoster.py
index 047b9155e..abbc14466 100644
--- a/module/plugins/MultiHoster.py
+++ b/module/plugins/MultiHoster.py
@@ -33,7 +33,7 @@ class MultiHoster(Account):
# Timestamp
self.ts = 0
- Account.__init__(*args, **kwargs)
+ Account.__init__(self, *args, **kwargs)
def loadHosterList(self, req):
"""Load list of supported hoster
@@ -63,11 +63,11 @@ class MultiHoster(Account):
req.close()
for rep in self.replacements:
- if rep[0] in self.hosters:
- self.hosters.remove(rep[0])
- if rep[1] not in self.hosters:
- self.hosters.append(rep[1])
+ if rep[0] in self.hoster:
+ self.hoster.remove(rep[0])
+ if rep[1] not in self.hoster:
+ self.hoster.append(rep[1])
self.ts = time()
- return self.hosters \ No newline at end of file
+ return self.hoster \ No newline at end of file
diff --git a/module/plugins/PluginManager.py b/module/plugins/PluginManager.py
index e00c1e1f5..c345f765f 100644
--- a/module/plugins/PluginManager.py
+++ b/module/plugins/PluginManager.py
@@ -58,7 +58,6 @@ class PluginManager:
self.plugins = {}
self.modules = {} # cached modules
- self.names = {} # overwritten names
self.history = [] # match history to speedup parsing (type, name)
self.createIndex()
@@ -262,27 +261,19 @@ class PluginManager:
return ptype, self.plugins[ptype][name]
return None, None
- def getPlugin(self, name, original=False):
- """return plugin module from hoster|decrypter"""
+ def getPluginModule(self, name):
+ """ Decprecated: return plugin module from hoster|crypter"""
+ self.log.debug("Deprecated method: .getPluginModule()")
type, plugin = self.findPlugin(name)
-
- if not plugin:
- self.log.warning("Plugin %s not found." % name)
- name = "BasePlugin"
-
- if (type, name) in self.modules and not original:
- return self.modules[(type, name)]
-
return self.loadModule(type, name)
- def getPluginName(self, name):
- """ used to obtain new name if other plugin was injected"""
+ def getPluginClass(self, name):
+ """ return plugin class from hoster|crypter, always the not overwritten one """
type, plugin = self.findPlugin(name)
+ return self.loadClass(type, name)
- if (type, name) in self.names:
- return self.names[(type, name)]
-
- return name
+ # MultiHoster will overwrite this
+ getPlugin = getPluginClass
def loadModule(self, type, name):
""" Returns loaded module for plugin
@@ -309,18 +300,6 @@ class PluginManager:
module = self.loadModule(type, name)
if module: return getattr(module, name)
- def injectPlugin(self, type, name, module, new_name):
- """ Overwrite a plugin with a other module. used by Multihoster """
- self.modules[(type, name)] = module
- self.names[(type, name)] = new_name
-
- def restoreState(self, type, name):
- """ Restore the state of a plugin after injecting """
- if (type, name) in self.modules:
- del self.modules[(type, name)]
- if (type, name) in self.names:
- del self.names[(type, name)]
-
def find_module(self, fullname, path=None):
#redirecting imports if necesarry
if fullname.startswith(self.ROOT) or fullname.startswith(self.USERROOT): #seperate pyload plugins
diff --git a/module/plugins/accounts/RealdebridCom.py b/module/plugins/accounts/RealdebridCom.py
index 3137987a9..4a2cf9368 100644
--- a/module/plugins/accounts/RealdebridCom.py
+++ b/module/plugins/accounts/RealdebridCom.py
@@ -1,15 +1,18 @@
-from module.plugins.Account import Account
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from module.plugins.MultiHoster import MultiHoster
import xml.dom.minidom as dom
-class RealdebridCom(Account):
+class RealdebridCom(MultiHoster):
__name__ = "RealdebridCom"
- __version__ = "0.4"
+ __version__ = "0.5"
__type__ = "account"
__description__ = """Real-Debrid.com account plugin"""
__author_name__ = ("Devirex, Hazzard")
__author_mail__ = ("naibaf_11@yahoo.de")
- def loadAccountInfo(self, user, req):
+ def loadAccountInfo(self, req):
page = req.load("http://real-debrid.com/api/account.php")
xml = dom.parseString(page)
account_info = {"validuntil": int(xml.getElementsByTagName("expiration")[0].childNodes[0].nodeValue),
@@ -17,9 +20,16 @@ class RealdebridCom(Account):
return account_info
- def login(self, user, data, req):
- page = req.load("https://real-debrid.com/ajax/login.php?user=%s&pass=%s" % (user, data["password"]))
+ def login(self, req):
+ page = req.load("https://real-debrid.com/ajax/login.php?user=%s&pass=%s" % (self.loginname, self.password))
#page = req.load("https://real-debrid.com/login.html", post={"user": user, "pass": data["password"]}, cookies=True)
if "Your login informations are incorrect" in page:
self.wrongPassword()
+
+
+ def loadHosterList(self, req):
+ https = "https" if self.getConfig("https") else "http"
+ page = req.load(https + "://real-debrid.com/api/hosters.php").replace("\"","").strip()
+
+ return[x.strip() for x in page.split(",") if x.strip()] \ No newline at end of file
diff --git a/module/plugins/hooks/ClickAndLoad.py b/module/plugins/hooks/ClickAndLoad.py
index 97e5cd57d..fc32d0da8 100644
--- a/module/plugins/hooks/ClickAndLoad.py
+++ b/module/plugins/hooks/ClickAndLoad.py
@@ -32,7 +32,7 @@ class ClickAndLoad(Hook):
__author_name__ = ("RaNaN", "mkaay")
__author_mail__ = ("RaNaN@pyload.de", "mkaay@mkaay.de")
- def coreReady(self):
+ def activate(self):
self.port = int(self.core.config['webinterface']['port'])
if self.core.config['webinterface']['activated']:
try:
diff --git a/module/plugins/hooks/MultiHoster.py b/module/plugins/hooks/MultiHoster.py
new file mode 100644
index 000000000..1f40a4ddd
--- /dev/null
+++ b/module/plugins/hooks/MultiHoster.py
@@ -0,0 +1,100 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import re
+from types import MethodType
+
+from module.plugins.MultiHoster import MultiHoster as MultiHosterAccount, normalize
+from module.plugins.Hook import Hook, AddEventListener
+from module.plugins.PluginManager import PluginTuple
+
+class MultiHoster(Hook):
+ __version__ = "0.1"
+ __description__ = "Gives ability to use MultiHoster services. You need to add your account first."
+ __config__ = [("activated", "bool", "Activated", True)]
+ __author_mail__ = ("pyLoad Team",)
+ __author_mail__ = ("support@pyload.org",)
+
+ #TODO: multiple accounts - multihoster / config options
+
+ def init(self):
+
+ # overwritten plugins
+ self.plugins = {}
+
+ def addHoster(self, account):
+
+ self.logDebug("New MultiHoster %s" % account.__name__)
+
+ pluginMap = {}
+ for name in self.core.pluginManager.getPlugins("hoster").keys():
+ pluginMap[name.lower()] = name
+
+ supported = []
+ new_supported = []
+
+ for hoster in account.getHosterList():
+ name = normalize(hoster)
+
+ if name in pluginMap:
+ supported.append(pluginMap[name])
+ else:
+ new_supported.append(hoster)
+
+ if not supported and not new_supported:
+ account.logError(_("No Hoster loaded"))
+ return
+
+ klass = self.core.pluginManager.getPluginClass(account.__name__)
+
+ # inject plugin plugin
+ account.logDebug("Overwritten Hosters: %s" % ", ".join(sorted(supported)))
+ for hoster in supported:
+ self.plugins[hoster] = klass
+
+ account.logDebug("New Hosters: %s" % ", ".join(sorted(new_supported)))
+
+ # create new regexp
+ regexp = r".*(%s).*" % "|".join([klass.__pattern__] + [x.replace(".", "\\.") for x in new_supported])
+
+ # recreate plugin tuple for new regexp
+ hoster = self.core.pluginManager.getPlugins("hoster")
+ p = hoster[account.__name__]
+ new = PluginTuple(p.version, re.compile(regexp), p.deps, p.user, p.path)
+ hoster[account.__name__] = new
+
+
+
+ @AddEventListener("accountDeleted")
+ def refreshAccounts(self, plugin=None, user=None):
+
+ self.plugins = {}
+ for name, account in self.core.accountManager.iterAccounts():
+ if isinstance(account, MultiHosterAccount) and account.isUsable():
+ self.addHoster(account)
+
+ @AddEventListener("accountUpdated")
+ def refreshAccount(self, plugin, user):
+
+ account = self.core.accountManager.getAccount(plugin, user)
+ if isinstance(account, MultiHosterAccount) and account.isUsable():
+ self.addHoster(account)
+
+ def activate(self):
+ self.refreshAccounts()
+
+ # new method for plugin manager
+ def getPlugin(self2, name):
+ if name in self.plugins:
+ return self.plugins[name]
+ return self2.getPluginClass(name)
+
+ pm = self.core.pluginManager
+ pm.getPlugin = MethodType(getPlugin, pm, object)
+
+
+ def deactivate(self):
+ #restore state
+ pm = self.core.pluginManager
+ pm.getPlugin = pm.getPluginClass
+
diff --git a/module/plugins/hooks/RealdebridCom.py b/module/plugins/hooks/RealdebridCom.py
deleted file mode 100644
index c57e3de52..000000000
--- a/module/plugins/hooks/RealdebridCom.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.network.RequestFactory import getURL
-from module.plugins.internal.MultiHoster import MultiHoster
-
-class RealdebridCom(MultiHoster):
- __name__ = "RealdebridCom"
- __version__ = "0.4"
- __type__ = "hook"
-
- __config__ = [("activated", "bool", "Activated", "False"),
- ("https", "bool", "Enable HTTPS", "False")]
-
- __description__ = """Real-Debrid.com hook plugin"""
- __author_name__ = ("Devirex, Hazzard")
- __author_mail__ = ("naibaf_11@yahoo.de")
-
- replacements = [("freakshare.net", "freakshare.com")]
-
- def getHoster(self):
- https = "https" if self.getConfig("https") else "http"
- page = getURL(https + "://real-debrid.com/api/hosters.php").replace("\"","").strip()
-
- return[x.strip() for x in page.split(",") if x.strip()] \ No newline at end of file
diff --git a/module/plugins/hoster/RealdebridCom.py b/module/plugins/hoster/RealdebridCom.py
index 62c09aaa8..376ae3414 100644
--- a/module/plugins/hoster/RealdebridCom.py
+++ b/module/plugins/hoster/RealdebridCom.py
@@ -8,12 +8,11 @@ from random import randrange
from module.plugins.Hoster import Hoster
class RealdebridCom(Hoster):
- __name__ = "RealdebridCom"
__version__ = "0.41"
- __type__ = "hoster"
-
__pattern__ = r"https?://.*real-debrid\..*"
__description__ = """Real-Debrid.com hoster plugin"""
+ __config__ = [("https", "bool", _("Enable HTTPS"), False)]
+
__author_name__ = ("Devirex, Hazzard")
__author_mail__ = ("naibaf_11@yahoo.de")
diff --git a/module/plugins/internal/MultiHoster.py b/module/plugins/internal/MultiHoster.py
deleted file mode 100644
index 2252c4460..000000000
--- a/module/plugins/internal/MultiHoster.py
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import re
-
-from module.utils import remove_chars
-from module.plugins.Hook import Hook
-from module.plugins.PluginManager import PluginTuple
-
-class MultiHoster(Hook):
- """
- Generic MultiHoster plugin
- """
-
- interval = 0
- hosters = []
- replacements = []
- supported = []
-
- def getHosterCached(self):
- if not self.hosters:
-
- try:
- self.hosters = self.getHoster()
- except Exception, e:
- self.logError(e)
- return []
-
- for rep in self.replacements:
- if rep[0] in self.hosters:
- self.hosters.remove(rep[0])
- if rep[1] not in self.hosters:
- self.hosters.append(rep[1])
-
- return self.hosters
-
-
- def getHoster(self):
- """Load list of supported hoster
-
- :return: List of domain names
- """
- raise NotImplementedError
-
- def coreReady(self):
- pluginMap = {}
- for name in self.core.pluginManager.getPlugins("hoster").keys():
- pluginMap[name.lower()] = name
-
- new_supported = []
-
- for hoster in self.getHosterCached():
- name = remove_chars(hoster.lower(), "-.")
-
- if name in pluginMap:
- self.supported.append(pluginMap[name])
- else:
- new_supported.append(hoster)
-
- if not self.supported and not new_supported:
- self.logError(_("No Hoster loaded"))
- return
-
- module = self.core.pluginManager.getPlugin(self.__name__)
- klass = getattr(module, self.__name__)
-
- # inject plugin plugin
- self.logDebug("Overwritten Hosters: %s" % ", ".join(sorted(self.supported)))
- for hoster in self.supported:
- self.core.pluginManager.injectPlugin("hoster", hoster, module, self.__name__)
-
- self.logDebug("New Hosters: %s" % ", ".join(sorted(new_supported)))
-
- # create new regexp
- regexp = r".*(%s).*" % "|".join([klass.__pattern__] + [x.replace(".", "\\.") for x in new_supported])
-
- hoster = self.core.pluginManager.getPlugins("hoster")
- p = hoster[self.__name__]
- new = PluginTuple(p.version, re.compile(regexp), p.deps, p.user, p.path)
- hoster[self.__name__] = new
-
-
- def deactivate(self):
- for hoster in self.supported:
- self.core.pluginManager.restoreState("hoster", hoster) \ No newline at end of file
diff --git a/module/threads/DownloadThread.py b/module/threads/DownloadThread.py
index e140703d5..c151831a3 100644
--- a/module/threads/DownloadThread.py
+++ b/module/threads/DownloadThread.py
@@ -156,7 +156,7 @@ class DownloadThread(BaseThread):
self.log.error("pycurl error %s: %s" % (code, msg))
if self.core.debug:
print_exc()
- self.writeDebugReport(pyfile.pluginname, pyfile)
+ self.writeDebugReport(pyfile.plugin.__name__, pyfile)
self.core.hookManager.downloadFailed(pyfile)
@@ -186,7 +186,7 @@ class DownloadThread(BaseThread):
if self.core.debug:
print_exc()
- self.writeDebugReport(pyfile.pluginname, pyfile)
+ self.writeDebugReport(pyfile.plugin.__name__, pyfile)
self.core.hookManager.downloadFailed(pyfile)
self.clean(pyfile)
diff --git a/module/threads/InfoThread.py b/module/threads/InfoThread.py
index 5f21d487c..7db85803a 100644
--- a/module/threads/InfoThread.py
+++ b/module/threads/InfoThread.py
@@ -40,8 +40,8 @@ class InfoThread(BaseThread):
#directly write to database
if self.pid > -1:
for pluginname, urls in plugins.iteritems():
- plugin = self.m.core.pluginManager.getPlugin(pluginname, True)
- klass = getattr(plugin, pluginname)
+ plugin = self.m.core.pluginManager.getPluginModule(pluginname)
+ klass = self.m.core.pluginManager.getPluginClass(pluginname)
if has_method(klass, "getInfo"):
self.fetchForPlugin(pluginname, klass, urls, self.updateDB)
self.m.core.files.save()
diff --git a/module/web/pyload_app.py b/module/web/pyload_app.py
index f73defb45..fffa19b48 100644
--- a/module/web/pyload_app.py
+++ b/module/web/pyload_app.py
@@ -246,10 +246,10 @@ def config():
conf_menu = []
plugin_menu = []
- for section, data in conf.getBaseSections():
+ for section, data in sorted(conf.getBaseSections()):
conf_menu.append((section, data.name))
- for section, data in conf.getPluginSections():
+ for section, data in sorted(conf.getPluginSections()):
plugin_menu.append((section, data.name))
accs = PYLOAD.getAccounts(False)