class Triggers(object): """Match/action triggers for a server. """ def __init__(self, commandFunc): self.runCommand = commandFunc self.triggers = OrderedDict() self.thr = None self._q = [] def __hash__(self): """For sets. """ return hash(self.triggers) def __eq__(self, other): """Makes comparison for equality work reasonably. """ return self.triggers == other.triggers def __ne__(self, other): """Makes comparison for equality work reasonably. """ return not self.__eq__(other) def get(self, name): """Get and/or make the trigger object for the given name. """ if not self.triggers.get(name): self.triggers[name] = Trigger(self, name) return self.triggers[name] def addMatch(self, triggerName, matchSpec, matchName=""): """Add one match to a trigger. triggerName should uniquely identify a set of matches and associated actions, to separate them from any other match/action sets. matchSpec should be a ParmLine where the event and parameter values are regexps. matchName can name the match arbitrarily. """ trigger = self.get(triggerName) trigger.addMatch(matchSpec, matchName) def addAction(self, triggerName, actionSpec, actionName=""): """Add one action to a trigger. triggerName should uniquely identify a set of matches and associated actions, to separate them from any other match/action sets. actionSpec should be an action to perform. actionName can name the action arbitrarily. """ trigger = self.get(triggerName) trigger.addAction(actionSpec, actionName) def apply(self, parmline): """Apply actions where there is a match. As many match/action sets as match will have their actions applied. """ # config file triggers first. [trigger.apply(parmline) for trigger in self.triggers.values()] # Then custom code triggers if any. trigger_cc.apply(self.server, parmline, self.runCommand) @classmethod def loadCustomCode(cls): """Load custom trigger code if it exists. """ reload(trigger_cc) def queue(self, parmline): """Queues a trigger check instead of applying it immediately. """ self._q.append(parmline) if not self.thr: thr = threading.Thread(target=self._queueWatch) thr.daemon = True thr.start() def _queueWatch(self): """Watch the queue for things to do. Runs in its own thread as started by queue(). """ while True: if not self._q: sleep(0.5) continue parmline = self._q.pop(0) self.apply(parmline)