From 630595878496c00c1867d21b2df7db72bde31757 Mon Sep 17 00:00:00 2001 From: Jeremy Fincher Date: Tue, 8 Apr 2003 07:00:39 +0000 Subject: [PATCH] Initial import. --- plugins/Alias.py | 203 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 plugins/Alias.py diff --git a/plugins/Alias.py b/plugins/Alias.py new file mode 100644 index 000000000..d7a793365 --- /dev/null +++ b/plugins/Alias.py @@ -0,0 +1,203 @@ +#!/usr/bin/env python + +### +# Copyright (c) 2002, Jeremiah Fincher +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions, and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions, and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the author of this software nor the name of +# contributors to this software may be used to endorse or promote products +# derived from this software without specific prior written consent. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +### + +""" +Allows 'aliases' for other commands. + +Commands include: + alias + unalias + freeze + unfreeze +""" + +from baseplugin import * + +import new +import copy +import traceback + +import conf +import debug +import privmsgs +import callbacks + +def configure(onStart, afterConnect, advanced): + # This will be called by setup.py to configure this module. onStart and + # afterConnect are both lists. Append to onStart the commands you would + # like to be run when the bot is started; append to afterConnect the + # commands you would like to be run when the bot has finished connecting. + from questions import expect, anything, something, yn + onStart.append('load Alias') + +class RecursiveAlias(Exception): + pass + +def findString(s, args): + n = 0 + for elt in args: + if type(elt) == list: + n += findString(s, elt) + elif elt == s: + n += 1 + return n + +def findDollars(args, soFar=None, L=None): + if soFar is None: + soFar = [] + if L is None: + L = [] + for (i, elt) in enumerate(args): + if type(elt) == list: + nextSoFar = soFar[:] + nextSoFar.append(i) + findDollars(elt, soFar=nextSoFar, L=L) + if len(elt) >= 2: + if elt[0] == '$' and elt[1:].isdigit(): + mySoFar = soFar[:] + mySoFar.append(i) + L.append((mySoFar, elt)) + return L + +def replaceDollars(dollars, aliasArgs, realArgs): + for (indexes, dollar) in dollars: + L = aliasArgs + for i in indexes[:-1]: + L = L[i] + L[indexes[-1]] = realArgs[int(dollar[1:])-1] + +def makeNewAlias(name, alias, aliasArgs): + if findString(name, aliasArgs): + raise RecursiveAlias + dollars = findDollars(aliasArgs) + numDollars = len(dollars) + def f(self, irc, msg, args): + debug.printf('%s being called' % name) + realArgs = privmsgs.getArgs(args, needed=numDollars) + myArgs = copy.deepcopy(aliasArgs) + if dollars: + replaceDollars(dollars, myArgs, realArgs) + else: + myArgs.extend(args) + self.Proxy(irc, msg, myArgs) + f.__doc__ = '\n\nAlias for %r' % alias + #f = new.function(f.func_code, f.func_globals, name) + return f + + +class Alias(callbacks.Privmsg): + def __init__(self): + callbacks.Privmsg.__init__(self) + self.frozen = set() + + def freeze(self, irc, msg, args): + """ + + 'Freezes' an alias so that no one else can change it. + """ + name = privmsgs.getArgs(args) + name = callbacks.canonicalName(name) + if hasattr(self, name) and self.isCommand(name): + self.frozen.add(name) + irc.reply(msg, conf.replySuccess) + else: + irc.error(msg, 'There is no such alias.') + freeze = privmsgs.checkCapability(freeze, 'admin') + + def unfreeze(self, irc, msg, args): + """ + + 'Unfreezes' an alias so that people can define new aliases over it. + """ + name = privmsgs.getArgs(args) + name = callbacks.canonicalName(name) + if hasattr(self, name) and self.isCommand(name): + self.frozen.discard(name) + irc.reply(msg, conf.replySuccess) + else: + irc.error(msg, 'There is no such alias.') + unfreeze = privmsgs.checkCapability(unfreeze, 'admin') + + def alias(self, irc, msg, args): + """ + + Defines an alias for the commands . The + should be in the standard [command argument [nestedcommand argument]] + format. Underscores can be used to represent arguments to the alias + itself; for instance ... + """ + try: + (name, alias) = privmsgs.getArgs(args, needed=2) + name = callbacks.canonicalName(name) + cb = irc.findCallback(name) + if cb is not None and cb != self: + irc.error(msg, 'A command with that name already exists.') + return + if name in self.frozen: + irc.error(msg, 'That alias is frozen.') + return + args = callbacks.tokenize(alias) + try: + f = makeNewAlias(name, alias, args) + except RecursiveAlias: + irc.error(msg, 'You can\'t define a recursive alias.') + debug.printf('setting attribute') + setattr(self.__class__, name, f) + irc.reply(msg, conf.replySuccess) + except Exception, e: + debug.recoverableException() + print debug.exnToString(e) + except: + print 'exception raised' + + + def unalias(self, irc, msg, args): + """ + + Removes the given alias, if unfrozen. + """ + name = privmsgs.getArgs(args) + name = callbacks.canonicalName(name) + if hasattr(self, name) and self.isCommand(name): + if name not in self.frozen: + delattr(self.__class__, name) + irc.reply(msg, conf.replySuccess) + else: + irc.error(msg, 'That alias is frozen.') + else: + irc.error(msg, 'There is no such alias.') + + + + +Class = Alias + +# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78: