summaryrefslogtreecommitdiffstats
path: root/module/interaction/EventManager.py
diff options
context:
space:
mode:
Diffstat (limited to 'module/interaction/EventManager.py')
-rw-r--r--module/interaction/EventManager.py128
1 files changed, 128 insertions, 0 deletions
diff --git a/module/interaction/EventManager.py b/module/interaction/EventManager.py
new file mode 100644
index 000000000..38faa3c46
--- /dev/null
+++ b/module/interaction/EventManager.py
@@ -0,0 +1,128 @@
+# -*- coding: utf-8 -*-
+
+from traceback import print_exc
+from time import time
+
+class EventManager:
+ """
+ Handles all Event related task, also stores an Event queue for clients, so they can retrieve them later.
+
+ **Known Events:**
+ Most hook methods exists as events. These are some additional known events.
+
+ ===================== ================ ===========================================================
+ Name Arguments Description
+ ===================== ================ ===========================================================
+ metaEvent eventName, *args Called for every event, with eventName and orginal args
+ downloadPreparing fid A download was just queued and will be prepared now.
+ downloadStarts fid A plugin will immediately starts the download afterwards.
+ linksAdded links, pid Someone just added links, you are able to modify the links.
+ allDownloadsProcessed Every link was handled, pyload would idle afterwards.
+ allDownloadsFinished Every download in queue is finished.
+ unrarFinished folder, fname An Unrar job finished
+ configChanged sec, opt, value The config was changed.
+ ===================== ================ ===========================================================
+
+ | Notes:
+ | allDownloadsProcessed is *always* called before allDownloadsFinished.
+ | configChanged is *always* called before pluginConfigChanged.
+ """
+
+ CLIENT_EVENTS = ("packageUpdated", "packageInserted", "linkUpdated", "packageDeleted")
+
+ def __init__(self, core):
+ self.core = core
+ self.log = core.log
+
+ # uuid : list of events
+ self.clients = {}
+ self.events = {"metaEvent": []}
+
+ def getEvents(self, uuid):
+ """ Get accumulated events for uuid since last call, this also registeres new client """
+ if uuid not in self.clients:
+ self.clients[uuid] = Client()
+ return self.clients[uuid].get()
+
+ def addEvent(self, event, func):
+ """Adds an event listener for event name"""
+ if event in self.events:
+ if func in self.events[event]:
+ self.log.debug("Function already registered %s" % func)
+ else:
+ self.events[event].append(func)
+ else:
+ self.events[event] = [func]
+
+ def removeEvent(self, event, func):
+ """removes previously added event listener"""
+ if event in self.events:
+ self.events[event].remove(func)
+
+ def dispatchEvent(self, event, *args):
+ """dispatches event with args"""
+ for f in self.events["metaEvent"]:
+ try:
+ f(event, *args)
+ except Exception, e:
+ self.log.warning("Error calling event handler %s: %s, %s, %s"
+ % ("metaEvent", f, args, str(e)))
+ if self.core.debug:
+ print_exc()
+
+ if event in self.events:
+ for f in self.events[event]:
+ try:
+ f(*args)
+ except Exception, e:
+ self.log.warning("Error calling event handler %s: %s, %s, %s"
+ % (event, f, args, str(e)))
+ if self.core.debug:
+ print_exc()
+
+ # append to client event queue
+ if event in self.CLIENT_EVENTS:
+ for uuid, client in self.clients.items():
+ if client.delete():
+ del self.clients[uuid]
+ else:
+ client.append(event, args)
+
+
+ def removeFromEvents(self, func):
+ """ Removes func from all known events """
+ for name, events in self.events.iteritems():
+ if func in events:
+ events.remove(func)
+
+
+
+class Client:
+
+ # delete clients after this time
+ TIMEOUT = 60 * 60
+ # max events, if this value is reached you should assume that older events were dropped
+ MAX = 30
+
+ def __init__(self):
+ self.lastActive = time()
+ self.events = []
+
+ def delete(self):
+ return self.lastActive + self.TIMEOUT < time()
+
+ def append(self, event, args):
+ ev = (event, args)
+ if ev not in self.events:
+ self.events.insert(0, ev)
+
+ del self.events[self.MAX:]
+
+
+ def get(self):
+ self.lastActive = time()
+
+ events = self.events
+ self.events = []
+
+ return [(ev, [str(x) for x in args]) for ev, args in events] \ No newline at end of file