Updates to Voteserv

- Add Admin override clause (enabled by config plugins.voteserv.allowadminoverride)
- Add listallvotes to list entire voting dictionary
- Add --hosts and --number options to 'votes' to list hostnames and only numbers
This commit is contained in:
James Lu 2014-11-19 18:01:23 -08:00
parent 09d3a4b5f6
commit 1009856b1f
3 changed files with 65 additions and 22 deletions

View File

@ -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:

View File

@ -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 <n> 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):
"""<action>
Returns the amount of people that have voted for <action>."""
def votes(self, irc, msg, args, opts, action):
"""[--hosts] [--number] <action>
Returns the amount of people that have voted for <action>. If
--hosts is given, also show the hosts that have voted for <action>.
If --number is given, only returns the number of people who has
voted for <action> (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):
"""<number of votes> <action>
Sets the number of votes for <action> to a certain amount,
perfect for rigged elections!
This will also reset the list of hosts that have voted for
<action>, 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):
"""<takes no arguments>.
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

View File

@ -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: