#!/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 re 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 findAliasCommand(s, alias): r = re.compile(r'(^|\[)\s*%s' % s) return bool(r.search(alias)) dollarRe = re.compile(r'\$(\d+)') def findBiggestDollar(alias): dollars = dollarRe.findall(alias) dollars.sort() if dollars: return int(dollars[-1]) else: return None def makeNewAlias(name, alias): if findAliasCommand(name, alias): raise RecursiveAlias doChannel = alias.find('$channel') != -1 biggestDollar = findBiggestDollar(alias) doDollars = bool(biggestDollar) if biggestDollar is not None: biggestDollar = int(biggestDollar) def f(self, irc, msg, args): alias_ = alias if doChannel: channel = privmsgs.getChannel(msg, args) alias_ = alias.replace('$channel', channel) if doDollars: debug.printf(args) args = privmsgs.getArgs(args, needed=biggestDollar) if biggestDollar == 1: args = (args,) debug.printf(args) def replace(m): debug.printf(m.group(1)) idx = int(m.group(1)) debug.printf(args[idx-1]) return args[idx-1] debug.printf(alias_) alias_ = dollarRe.sub(replace, alias_) debug.printf(alias_) debug.printf(alias_) self.Proxy(irc, msg, callbacks.tokenize(alias_)) f.__doc__ ='\n\nAlias for %r'%(biggestDollar,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 try: f = makeNewAlias(name, alias) 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: