Added the new buttkicking enable/disable.

This commit is contained in:
Jeremy Fincher 2004-07-29 09:46:22 +00:00
parent 17f15da7f7
commit 61793a489c
7 changed files with 143 additions and 72 deletions

View File

@ -288,45 +288,6 @@ class Admin(privmsgs.CapabilityCheckingPrivmsg):
if not inAtLeastOneChannel:
irc.replySuccess()
def disable(self, irc, msg, args):
"""<command>
Disables the command <command> for all non-owner users.
"""
command = privmsgs.getArgs(args)
if command in ('enable', 'identify'):
irc.error('You can\'t disable %s!' % command)
else:
try:
capability = ircdb.makeAntiCapability(command)
except ValueError:
irc.error('%r is not a valid command.' % command)
return
if command in conf.supybot.defaultCapabilities():
conf.supybot.defaultCapabilities().remove(command)
conf.supybot.defaultCapabilities().add(capability)
irc.replySuccess()
def enable(self, irc, msg, args):
"""<command>
Re-enables the command <command> for all non-owner users.
"""
command = privmsgs.getArgs(args)
command = command.lower()
L = []
for capability in conf.supybot.defaultCapabilities():
if ircdb.isAntiCapability(capability):
nonAntiCapability = ircdb.unAntiCapability(capability)
if nonAntiCapability.lower() == command:
L.append(capability)
if L:
for capability in L:
conf.supybot.defaultCapabilities().remove(capability)
irc.replySuccess()
else:
irc.error('That command wasn\'t disabled.')
def addcapability(self, irc, msg, args):
"""<name|hostmask> <capability>

View File

@ -115,7 +115,11 @@ def loadPluginClass(irc, module, register=None):
conf.registerPlugin('Owner', True)
conf.supybot.plugins.Owner.register('public', registry.Boolean(True,
"""Determines whether this plugin is publically visible."""))
conf.registerGroup(conf.supybot, 'commands')
###
# supybot.commands.
###
conf.registerGroup(conf.supybot.commands, 'defaultPlugins')
conf.supybot.commands.defaultPlugins.help = utils.normalizeWhitespace("""
Determines what commands have default plugins set, and which plugins are set to
@ -555,6 +559,44 @@ class Owner(privmsgs.CapabilityCheckingPrivmsg):
except AttributeError: # There's a cleaner way to do this, but I'm lazy.
irc.error('I couldn\'t reconnect. You should restart me instead.')
def disable(self, irc, msg, args):
"""[<plugin>] <command>
Disables the command <command> for all non-owner users. If <plugin>
is given, only disables the <command> from <plugin>.
"""
(plugin, command) = privmsgs.getArgs(args, optional=1)
if not command:
(plugin, command) = (None, plugin)
conf.supybot.commands.disabled().add(command)
else:
conf.supybot.commands.disabled().add('%s.%s' % (plugin, command))
if command in ('enable', 'identify'):
irc.error('You can\'t disable %s.' % command)
else:
self._disabled.add(command, plugin)
irc.replySuccess()
def enable(self, irc, msg, args):
"""[<plugin>] <command>
Enables the command <command> for all non-owner users. If <plugin>
if given, only enables the <command> from <plugin>.
"""
(plugin, command) = privmsgs.getArgs(args, optional=1)
try:
if not command:
(plugin, command) = (None, plugin)
conf.supybot.commands.disabled().remove(command)
else:
name = '%s.%s' % (plugin, command)
conf.supybot.commands.disabled().remove(name)
self._disabled.remove(command, plugin)
irc.replySuccess()
except KeyError:
raise
irc.error('That command wasn\'t disabled.')
Class = Owner

View File

@ -716,6 +716,63 @@ class CommandThread(threading.Thread):
self.cb.threaded = self.originalThreaded
class CanonicalString(registry.NormalizedString):
def normalize(self, s):
return canonicalName(s)
class CanonicalNameSet(utils.NormalizingSet):
def normalize(self, s):
return canonicalName(s)
class Disabled(registry.SpaceSeparatedListOf):
Value = CanonicalString
List = CanonicalNameSet
conf.registerGlobalValue(conf.supybot.commands, 'disabled',
Disabled([], """Determines what commands are currently disabled. Such
commands will not appear in command lists, etc. They will appear not even
to exist."""))
class DisabledCommands(object):
class CanonicalNameDict(utils.InsensitivePreservingDict):
def key(self, s):
return canonicalName(s)
def __init__(self):
self.d = self.CanonicalNameDict()
for name in conf.supybot.commands.disabled():
if '.' in name:
(plugin, command) = name.split('.', 1)
if command in self.d:
if self.d[command] is not None:
self.d[command].add(plugin)
else:
self.d[command] = CanonicalNameSet([plugin])
else:
self.d[name] = None
def disabled(self, command, plugin=None):
if command in self.d:
if self.d[command] is None:
return True
elif plugin in self.d[command]:
return True
return False
def add(self, command, plugin=None):
if plugin is None:
self.d[command] = None
else:
if self.d[command] is not None:
self.d[command].add(plugin)
def remove(self, command, plugin=None):
if plugin is None:
del self.d[command]
else:
if self.d[command] is not None:
self.d[command].remove(plugin)
class Privmsg(irclib.IrcCallback):
"""Base class for all Privmsg handlers."""
__metaclass__ = log.MetaFirewall
@ -729,8 +786,9 @@ class Privmsg(irclib.IrcCallback):
errored = False
Proxy = IrcObjectProxy
commandArgs = ['self', 'irc', 'msg', 'args']
# This must be class-scope, so all subclasses use the same one.
# This must be class-scope, so all plugins use the same one.
_mores = ircutils.IrcDict()
_disabled = DisabledCommands()
def __init__(self):
self.__parent = super(Privmsg, self)
myName = self.name()
@ -795,6 +853,8 @@ class Privmsg(irclib.IrcCallback):
# Don't canonicalize this name: consider outFilter(self, irc, msg).
# methodName = canonicalName(methodName)
if self._disabled.disabled(methodName, plugin=self.name()):
return False
if hasattr(self, methodName):
method = getattr(self, methodName)
if inspect.ismethod(method):

View File

@ -500,27 +500,11 @@ class IrcDict(utils.InsensitivePreservingDict):
key = staticmethod(toLower)
class IrcSet(sets.Set):
class IrcSet(utils.NormalizingSet):
"""A sets.Set using IrcStrings instead of regular strings."""
def __init__(self, seq=()):
self.__parent = super(IrcSet, self)
self.__parent.__init__()
for elt in seq:
self.add(elt)
def add(self, s):
return self.__parent.add(IrcString(s))
def remove(self, s):
return self.__parent.remove(IrcString(s))
def discard(self, s):
return self.__parent.discard(IrcString(s))
def __contains__(self, s):
return self.__parent.__contains__(IrcString(s))
has_key = __contains__
def normalize(self, s):
return IrcString(s)
def __reduce__(self):
return (self.__class__, (list(self),))

View File

@ -42,6 +42,7 @@ import re
import md5
import new
import sha
import sets
import types
import socket
import string
@ -49,6 +50,7 @@ import sgmllib
import compiler
import textwrap
import UserDict
import itertools
import htmlentitydefs
from itertools import imap, ifilter
@ -640,6 +642,28 @@ class InsensitivePreservingDict(UserDict.DictMixin, object):
def __reduce__(self):
return (self.__class__, (dict(self.data.values()),))
class NormalizingSet(sets.Set):
def __init__(self, iterable=()):
iterable = itertools.imap(self.normalize, iterable)
super(NormalizingSet, self).__init__(iterable)
def normalize(self, x):
return x
def add(self, x):
return super(NormalizingSet, self).add(self.normalize(x))
def remove(self, x):
return super(NormalizingSet, self).remove(self.normalize(x))
def discard(self, x):
return super(NormalizingSet, self).discard(self.normalize(x))
def __contains__(self, x):
return super(NormalizingSet, self).__contains__(self.normalize(x))
has_key = __contains__
def mungeEmailForWeb(s):
s = s.replace('@', ' AT ')
s = s.replace('.', ' DOT ')

View File

@ -76,17 +76,6 @@ class AdminTestCase(PluginTestCase, PluginDocumentation):
def testRemoveCapability(self):
self.assertError('removecapability alsdfkjasd foo')
def testDisable(self):
self.assertError('disable enable')
self.assertError('disable identify')
def testEnable(self):
self.assertError('enable enable')
def testEnableIsCaseInsensitive(self):
self.assertNotError('disable Foo')
self.assertNotError('enable foo')
def testJoin(self):
m = self.getMsg('join #foo')
self.assertEqual(m.command, 'JOIN')

View File

@ -96,6 +96,17 @@ class OwnerTestCase(PluginTestCase, PluginDocumentation):
self.assertNotError('load ALIAS')
self.assertNotError('unload ALIAS')
def testDisable(self):
self.assertError('disable enable')
self.assertError('disable identify')
def testEnable(self):
self.assertError('enable enable')
def testEnableIsCaseInsensitive(self):
self.assertNotError('disable Foo')
self.assertNotError('enable foo')
class FunctionsTestCase(SupyTestCase):
def testLoadPluginModule(self):