diff --git a/Voteserv/config.py b/Voteserv/config.py index 4f1aefa..e36e2dc 100644 --- a/Voteserv/config.py +++ b/Voteserv/config.py @@ -48,9 +48,11 @@ def configure(advanced): Voteserv = conf.registerPlugin('Voteserv') -# This is where your configuration variables (if any) should go. For example: -# conf.registerGlobalValue(Voteserv, 'someConfigVariableName', -# registry.Boolean(False, _("""Help for someConfigVariableName."""))) - +conf.registerGlobalValue(Voteserv, 'allowAdminOverride', + registry.Boolean(False, _("""Determines whether bot admins will be + allowed to override duplicate vote checks."""))) +conf.registerGlobalValue(Voteserv, 'allowCheat', + registry.Boolean(False, _("""Determines whether the 'cheat' command + is enabled."""))) # vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: diff --git a/Voteserv/plugin.py b/Voteserv/plugin.py index d704292..538e17d 100644 --- a/Voteserv/plugin.py +++ b/Voteserv/plugin.py @@ -34,6 +34,7 @@ import supybot.utils as utils from supybot.commands import * import supybot.plugins as plugins import supybot.ircutils as ircutils +import supybot.ircdb as ircdb import supybot.callbacks as callbacks try: from supybot.i18n import PluginInternationalization @@ -47,6 +48,10 @@ class Voteserv(callbacks.Plugin): """Small plugin for storing and manipulating votes/polls.""" threaded = True + def _pluralize(self, n): + """Returns 's' if is not 1.""" + return 's' if n != 1 else '' + def __init__(self, irc): self.__parent = super(Voteserv, self) self.__parent.__init__(irc) @@ -99,10 +104,12 @@ class Voteserv(callbacks.Plugin): Votes for something. It doesn't actually perform any actions directly, but could be an interesting way to get user feedback.""" action = ircutils.stripFormatting(action.lower()).strip() + override = self.registryValue("allowAdminOverride") and \ + ircdb.checkCapability(msg.prefix, 'admin') if not action: # It must be just whitespace or formatting codes irc.error("You must specify a proper action!", Raise=True) try: - if self._lazyhostmask(msg.prefix) in self.votedb[action]: + if self._lazyhostmask(msg.prefix) in self.votedb[action] and not override: irc.error("You have already voted to %s." % action, Raise=True) except KeyError: self.votedb[action] = [0] @@ -113,9 +120,9 @@ class Voteserv(callbacks.Plugin): def voteexport(self, irc, msg, args): """takes no arguments. - + Exports votes stored in memory to file: data/votes.db - This is also done automatically when the plugin is unloaded or + This is also done automatically when the plugin is unloaded or reloaded.""" try: self.exportVoteDB() @@ -127,7 +134,7 @@ class Voteserv(callbacks.Plugin): def voteimport(self, irc, msg, args): """takes no arguments. - + Imports the vote database for the current network.""" try: self.loadVoteDB() @@ -139,38 +146,48 @@ class Voteserv(callbacks.Plugin): def voteclear(self, irc, msg, args): """takes no arguments. - + Clears all votes stored in memory. Use with caution!""" self.votedb = {} irc.replySuccess() voteclear = wrap(voteclear, ['admin']) - def votes(self, irc, msg, args, action): - """ - - Returns the amount of people that have voted for .""" + def votes(self, irc, msg, args, opts, action): + """[--hosts] [--number] + + Returns the amount of people that have voted for . If + --hosts is given, also show the hosts that have voted for . + If --number is given, only returns the number of people who has + voted for (useful for nested commands).""" action = ircutils.stripFormatting(action.lower()).strip() if not action: irc.error("You must specify a proper action!", Raise=True) try: - n = self.votedb[action][0] + n, hosts = self.votedb[action][0], self.votedb[action][1:] except KeyError: - n = 0 - if irc.nested: + n, hosts = 0, None + opts = dict(opts) + if 'number' in opts: irc.reply(n) else: - irc.reply('\x02%s\x02 %s voted to %s' % - (n, 'person has' if n == 1 else 'people have', - self._formatAction(action))) - votes = wrap(votes, ['text']) + s = '\x02%s\x02 %s voted to %s' % \ + (n, 'person has' if n == 1 else 'people have', \ + self._formatAction(action)) + if 'hosts' in opts and n: + s += " (%s)" % ", ".join(set(hosts)) + irc.reply(s) + votes = wrap(votes, [getopts({'hosts':'', 'number':''}), 'text']) def cheat(self, irc, msg, args, num, action): """ - + Sets the number of votes for to a certain amount, perfect for rigged elections! This will also reset the list of hosts that have voted for , allowing everyone to vote again.""" + if not self.registryValue("allowCheat"): + irc.error("This command is disabled; please set config plugins." + "voteserv.allowCheat accordingly.", Raise=True) action = ircutils.stripFormatting(action.lower()).strip() if not action: irc.error("You must specify a proper action!", Raise=True) @@ -178,6 +195,16 @@ class Voteserv(callbacks.Plugin): irc.replySuccess() cheat = wrap(cheat, ['admin', 'int', 'text']) + def listallvotes(self, irc, msg, args): + """. + + Returns the list of things that have been voted for, along + with the number of votes for each.""" + s = "; ".join(['"%s": \x02%s\x02 vote%s' % (k, v[0], self._pluralize(v[0])) + for k, v in self.votedb.items()]) + irc.reply(s) + listallvotes = wrap(listallvotes) + Class = Voteserv diff --git a/Voteserv/test.py b/Voteserv/test.py index a41d63a..517e06a 100644 --- a/Voteserv/test.py +++ b/Voteserv/test.py @@ -31,7 +31,8 @@ from supybot.test import * class VoteservTestCase(PluginTestCase): - plugins = ('Voteserv',) + plugins = ('Voteserv','Admin') + config = {'supybot.plugins.voteserv.allowCheat': True} def setUp(self): PluginTestCase.setUp(self) @@ -67,4 +68,17 @@ class VoteservTestCase(PluginTestCase): self.assertError('cheat 30 " "') self.assertNotError('cheat 30 " lose the game\x02 "') self.assertRegexp('votes lose the game ', ".*?30.*?voted to.*?") + + def testAdminOverride(self): + conf.supybot.plugins.voteserv.allowAdminOverride.setValue(True) + try: + u = ircdb.users.newUser() + u.name = 'abcde' + ircdb.users.setUser(u) + self.assertNotError('capability add abcde admin') + self.assertNotError('vote test something') + self.assertNotError('vote test something') + finally: + conf.supybot.plugins.voteserv.allowAdminOverride.setValue(False) + ircdb.users.delUser(u.id) # vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: