Added calc module

This commit is contained in:
dave 2014-10-11 20:47:31 -07:00
parent 3bf6183a96
commit 69efe84685
2 changed files with 273 additions and 0 deletions

12
data/config/Calc.yml Normal file
View File

@ -0,0 +1,12 @@
allowDelete: true
delaySubmit: 0
delayCalc: 0
delayCalcSpecific: 0
delayMatch: 0
cmd_calc:
- .calc
- calc
- .quote
cmd_match:
- .match
- match

261
pyircbot/modules/Calc.py Normal file
View File

@ -0,0 +1,261 @@
from modulebase import ModuleBase,ModuleHook
import datetime
import time
import math
class Calc(ModuleBase):
def __init__(self, bot, moduleName):
ModuleBase.__init__(self, bot, moduleName);
self.hooks=[ModuleHook("PRIVMSG", self.calc)]
self.timers={}
self.sqlite = self.bot.getBestModuleForService("sqlite")
if self.sqlite==None:
self.log.error("Calc: SQLIite service is required.")
return
self.sql = self.sqlite.opendb("calc.db")
if not self.sql.tableExists("calc_addedby"):
c = self.sql.getCursor()
c.execute("""
CREATE TABLE `calc_addedby` (
`id` INTEGER PRIMARY KEY,
`username` varchar(32),
`userhost` varchar(128)
) ;
""")
c.close()
if not self.sql.tableExists("calc_channels"):
c = self.sql.getCursor()
c.execute("""
CREATE TABLE `calc_channels` (
`id` INTEGER PRIMARY KEY,
`channel` varchar(32)
) ;
""")
if not self.sql.tableExists("calc_definitions"):
c = self.sql.getCursor()
c.execute("""
CREATE TABLE `calc_definitions` (
`id` INTEGER PRIMARY KEY,
`word` INTEGET,
`definition` varchar(512),
`addedby` INTEGER,
`date` timestamp,
`status` varchar(16)
) ;
""")
if not self.sql.tableExists("calc_words"):
c = self.sql.getCursor()
c.execute("""
CREATE TABLE `calc_words` (
`id` INTEGER PRIMARY KEY,
`channel` INTEGER,
`word` varchar(512),
`status` varchar(32),
unique(`channel`,`word`)
);
""")
c.close()
def timeSince(self, channel, timetype):
if not channel in self.timers:
self.createDefaultTimers(channel)
return time.time()-self.timers[channel][timetype]
def updateTimeSince(self, channel, timetype):
if not channel in self.timers:
self.createDefaultTimers(channel)
self.timers[channel][timetype] = time.time()
def createDefaultTimers(self, channel):
self.timers[channel]={"add":0, "calc":0, "calcspec":0, "match":0}
def remainingToStr(self, total, elasped):
remaining = total-elasped
minutes = int(math.floor(remaining/60))
seconds = int(remaining - (minutes*60))
return "Please wait %s minute(s) and %s second(s)." % (minutes, seconds)
def calc(self, args, prefix, trailing):
# Channel only
if not args[0][0]=="#":
return
sender = self.bot.decodePrefix(prefix)
foundCalc = False
commandFound = ""
for cmd in self.config["cmd_calc"]:
if trailing[0:len(cmd)] == cmd and ( len(trailing) == len(cmd) or (trailing[len(cmd):len(cmd)+1] in [" ", "="])):
commandFound=cmd
foundCalc=True
if foundCalc:
calcCmd = trailing[len(cmd)-1:].strip()
if "=" in calcCmd[1:]:
" Add a new calc "
calcWord, calcDefinition = calcCmd.split("=", 1)
calcWord = calcWord.strip()
calcDefinition = calcDefinition.strip()
if self.config["allowDelete"] and calcDefinition == "":
result = self.deleteCalc(args[0], calcWord)
if result:
self.bot.act_PRIVMSG(args[0], "Calc deleted, %s." % sender.nick)
else:
self.bot.act_PRIVMSG(args[0], "Sorry %s, I don't know what '%s' is." % (sender.nick, calcWord))
else:
if self.config["delaySubmit"]>0 and self.timeSince(args[0], "add") < self.config["delaySubmit"]:
self.bot.act_PRIVMSG(sender.nick, self.remainingToStr(self.config["delaySubmit"], self.timeSince(args[0], "add")))
else:
self.addNewCalc(args[0], calcWord, calcDefinition, prefix)
self.bot.act_PRIVMSG(args[0], "Thanks for the info, %s." % sender.nick)
self.updateTimeSince(args[0], "add")
elif len(calcCmd)>0:
" Lookup the word in calcCmd "
if self.config["delayCalcSpecific"]>0 and self.timeSince(args[0], "calcspec") < self.config["delayCalcSpecific"]:
self.bot.act_PRIVMSG(sender.nick, self.remainingToStr(self.config["delayCalcSpecific"], self.timeSince(args[0], "calcspec")))
else:
randCalc = self.getSpecificCalc(args[0], calcCmd)
if randCalc==None:
self.bot.act_PRIVMSG(args[0], "Sorry %s, I don't know what '%s' is." % (sender.nick, calcCmd))
else:
self.bot.act_PRIVMSG(args[0], "%s \x03= %s \x0314[added by: %s]" % (randCalc["word"], randCalc["definition"], randCalc["by"]))
self.updateTimeSince(args[0], "calcspec")
else:
if self.config["delayCalc"]>0 and self.timeSince(args[0], "calc") < self.config["delayCalc"]:
self.bot.act_PRIVMSG(sender.nick, self.remainingToStr(self.config["delayCalc"], self.timeSince(args[0], "calc")))
else:
randCalc = self.getRandomCalc(args[0])
if randCalc == None:
self.bot.act_PRIVMSG(args[0], "This channel has no calcs, %s :(" % (sender.nick,))
else:
self.bot.act_PRIVMSG(args[0], "%s \x03= %s \x0314[added by: %s]" % (randCalc["word"], randCalc["definition"], randCalc["by"]))
self.updateTimeSince(args[0], "calc")
return
cmd = self.bot.messageHasCommand(self.config["cmd_match"], trailing, True)
if cmd:
if self.config["delayMatch"]>0 and self.timeSince(args[0], "match") < self.config["delayMatch"]:
self.bot.act_PRIVMSG(sender.nick, self.remainingToStr(self.config["delayMatch"], self.timeSince(args[0], "match")))
else:
term = cmd.args_str
if term.strip()=='':
return
c = self.sql.getCursor()
channelId = self.getChannelId(args[0])
c.execute("SELECT * FROM `calc_words` WHERE `word` LIKE ? AND `channel`=? ORDER BY `word` ASC ;", ("%%"+term+"%%", channelId))
rows = c.fetchall()
if len(rows)==0:
self.bot.act_PRIVMSG(args[0], "%s: Sorry, no matches" % sender.nick)
else:
matches = []
for row in rows[0:10]:
if row == None:
break
matches.append(row["word"])
self.bot.act_PRIVMSG(args[0], "%s: %s match%s (%s\x03)" % (sender.nick, len(matches), "es" if len(matches)>1 else "", ", \x03".join(matches) ))
self.updateTimeSince(args[0], "match")
def addNewCalc(self, channel, word, definition, prefix):
sender = self.bot.decodePrefix(prefix)
" Find the channel ID"
channelId = self.getChannelId(channel)
" Check if we need to add a user"
c = self.sql.getCursor()
name = sender.nick
host = sender.hostname
c.execute("SELECT * FROM `calc_addedby` WHERE `username`=? AND `userhost`=? ;", (name, host))
rows = c.fetchall()
if len(rows)==0:
c.execute("INSERT INTO `calc_addedby` (`username`, `userhost`) VALUES (?, ?) ;", (name, host,))
c.execute("SELECT * FROM `calc_addedby` WHERE `username`=? AND `userhost`=? ;", (name, host))
rows = c.fetchall()
addedId = rows[0]["id"]
" Check if the word exists"
c.execute("SELECT * FROM `calc_words` WHERE `channel`=? AND `word`=? ;", (channelId, word))
rows = c.fetchall()
if len(rows)==0:
c.execute("INSERT INTO `calc_words` (`channel`, `word`, `status`) VALUES (?, ?, ?) ;", (channelId, word, 'approved'))
c.execute("SELECT * FROM `calc_words` WHERE `channel`=? AND `word`=? ;", (channelId, word))
rows = c.fetchall()
wordId = rows[0]["id"]
" Add definition "
c.execute("INSERT INTO `calc_definitions` (`word`, `definition`, `addedby`, `date`, `status`) VALUES (?, ?, ?, ?, ?) ;", (wordId, definition, addedId, datetime.datetime.now(), 'approved',))
c.close()
pass
def getSpecificCalc(self, channel, word):
c = self.sql.getCursor()
channelId = self.getChannelId(channel)
c.execute("SELECT `cw`.`word`, (SELECT `cdq`.`id` FROM `calc_definitions` `cdq` WHERE `cdq`.`word`=`cw`.`id` AND `cdq`.`status`='approved' ORDER BY `cdq`.`date` DESC LIMIT 1) as `definitionId` FROM `calc_words` `cw` WHERE `cw`.`channel`=? AND `cw`.`status`='approved' AND `cw`.`word`=? COLLATE NOCASE ORDER BY RANDOM() LIMIT 1 ;", (channelId, word.lower()))
word = c.fetchone()
if word == None:
return None
c.execute("SELECT `ca`.`username`, `cd`.`definition` FROM `calc_definitions` `cd` JOIN `calc_addedby` `ca` ON `ca`.`id` = `cd`.`addedby` WHERE `cd`.`id`=? LIMIT 1 ;", (word["definitionId"], ))
who = c.fetchone()
if who == None:
return None
c.close()
return {"word":word["word"], "definition":who["definition"], "by":who["username"]}
def getRandomCalc(self, channel):
c = self.sql.getCursor()
channelId = self.getChannelId(channel)
for i in range(0, 5):
c.execute("SELECT `cw`.`word`, (SELECT `cdq`.`id` FROM `calc_definitions` `cdq` WHERE `cdq`.`word`=`cw`.`id` AND `cdq`.`status`='approved' ORDER BY `cdq`.`date` DESC LIMIT 1) as `definitionId` FROM `calc_words` `cw` WHERE `cw`.`channel`=? AND `cw`.`status`='approved' ORDER BY RANDOM() LIMIT 1 ;", (channelId,))
word = c.fetchone()
if word == None:
return None
c.execute("SELECT `ca`.`username`, `cd`.`definition` FROM `calc_definitions` `cd` JOIN `calc_addedby` `ca` ON `ca`.`id` = `cd`.`addedby` WHERE `cd`.`id`=? LIMIT 1 ;", (word["definitionId"], ))
who = c.fetchone()
if who == None:
continue
c.close()
return {"word":word["word"], "definition":who["definition"], "by":who["username"]}
def deleteCalc(self, channel, word):
" Return true if deleted something, false if it doesnt exist"
c = self.sql.getCursor()
channelId = self.getChannelId(channel)
c.execute("SELECT * FROM `calc_words` WHERE `channel`=? and `word`=? ;", (channelId, word))
rows = c.fetchall()
if len(rows)==0:
c.close()
return False
wordId = rows[0]["id"]
#c.execute("DELETE FROM `calc_words` WHERE `id`=? ;", (wordId,))
#c.execute("DELETE FROM `calc_definitions` WHERE `word`=? ;", (wordId,))
c.execute("UPDATE `calc_definitions` SET `status`='deleted' WHERE `word`=? ;", (wordId,))
c.close()
return True
def getChannelId(self, channel):
c = self.sql.getCursor()
c.execute("SELECT * FROM `calc_channels` WHERE `channel` = ?", (channel,))
rows = c.fetchall()
if len(rows)==0:
c.execute("INSERT INTO `calc_channels` (`channel`) VALUES (?);", (channel,))
c.execute("SELECT * FROM `calc_channels` WHERE `channel` = ?", (channel,))
rows = c.fetchall()
chId = rows[0]["id"]
c.close()
return chId