#!/usr/bin/python # -*- coding:utf-8 -*- ### # Copyright (c) 2002, Stéphan Kochen # 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. ### """ A module for managing and voting on polls. """ __revision__ = "$Id$" import plugins import utils import ircdb import ircutils import privmsgs import callbacks import conf import debug import os.path import time import sqlite 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 Poll') class Poll(callbacks.Privmsg, plugins.ChannelDBHandler): def __init__(self): callbacks.Privmsg.__init__(self) plugins.ChannelDBHandler.__init__(self) def makeDb(self, filename): if os.path.exists(filename): db = sqlite.connect(filename) else: db = sqlite.connect(filename) cursor = db.cursor() cursor.execute("""CREATE TABLE polls ( id INTEGER PRIMARY KEY, question TEXT, started_by INTEGER, expires INTEGER)""") cursor.execute("""CREATE TABLE options ( poll_id INTEGER, option_id INTEGER, option TEXT, votes INTEGER, PRIMARY KEY (poll_id, option_id) ON CONFLICT IGNORE)""") cursor.execute("""CREATE TABLE votes ( user_id INTEGER, poll_id INTEGER, option_id INTERER)""") db.commit() return db def new(self, irc, msg, args): """[] [] Creates a new poll with the given question and optional lifespan. Without a lifespan the poll will never expire and accept voting until it is closed. """ channel = privmsgs.getChannel(msg, args) (lifespan, question) = privmsgs.getArgs(args, optional=1) try: lifespan = int(lifespan) except ValueError: if question: question = '%s %s' % (lifespan, question) else: question = lifespan lifespan = 0 if lifespan: lifespan += time.time() if not question: raise callbacks.ArgumentError try: userId = ircdb.users.getUserId(msg.prefix) except KeyError: irc.error(msg, conf.replyNotRegistered) return db = self.getDb(channel) cursor = db.cursor() cursor.execute("""INSERT INTO polls VALUES (NULL, %%s, %s, %s)""" % (userId, lifespan), question) db.commit() cursor.execute("""SELECT id FROM polls WHERE question=%s""", question) id = cursor.fetchone()[0] irc.reply(msg, '%s (poll #%s)' % (conf.replySuccess, id)) def open(self, irc, msg, args): """[] [] Reopens a closed poll with the given and optional lifespan. Without a lifespan the poll will never expire and accept voting until it is closed. """ channel = privmsgs.getChannel(msg, args) (lifespan, id) = privmsgs.getArgs(args, optional=1) if not id: id = lifespan lifespan = 0 else: try: lifespan = int(lifespan) except ValueError: irc.error(msg, 'The argument must be an integer.') return try: id = int(id) except ValueError: irc.error(msg, 'The argument must be an integer.') return if lifespan: lifespan += time.time() db = self.getDb(channel) cursor = db.cursor() cursor.execute("""UPDATE polls SET expires=%s WHERE id=%s""" % \ (lifespan, id)) db.commit() irc.reply(msg, conf.replySuccess) def close(self, irc, msg, args): """[] Closes the poll with the given ; further votes will not be allowed. """ channel = privmsgs.getChannel(msg, args) id = privmsgs.getArgs(args) try: id = int(id) except ValueError: irc.error(msg, 'The argument must be an integer.') return db = self.getDb(channel) cursor = db.cursor() cursor.execute("""UPDATE polls SET expires=%s WHERE id=%s""" % \ (int(time.time()), id)) db.commit() irc.reply(msg, conf.replySuccess) def add(self, irc, msg, args): """[]