rewrite tell, simplify db access in quote, seen, urlhistory. fix wolframalpha for the last time

This commit is contained in:
Ryan Hitchman 2010-02-01 00:29:50 -07:00
parent 72b8168b2e
commit 9eb5b236a6
7 changed files with 109 additions and 160 deletions

9
core/db.py Normal file
View File

@ -0,0 +1,9 @@
import os
import sqlite3
def get_db_connection(server, name='skybot.%s.db'):
"returns an sqlite3 connection to a persistent database"
filename = os.path.join(bot.persist_dir, name % server)
return sqlite3.connect(filename)
bot.get_db_connection = get_db_connection

View File

@ -1,37 +1,27 @@
import os
import sqlite3
import random import random
import re import re
import sqlite3
import time import time
from util import hook from util import hook
dbname = "skybot.db"
def db_connect(db): def add_quote(conn, chan, nick, add_nick, msg):
conn = sqlite3.connect(db)
conn.execute('''create table if not exists quotes
(server, chan, nick, add_nick, msg, time real, deleted default 0,
primary key (server, chan, nick, msg))''')
conn.commit()
return conn
def add_quote(conn, server, chan, nick, add_nick, msg):
now = time.time() now = time.time()
print repr((conn, server, add_nick, nick, msg, time)) print repr((conn, add_nick, nick, msg, time))
conn.execute('''insert or fail into quotes (server, chan, nick, add_nick, conn.execute('''insert or fail into quotes (chan, nick, add_nick,
msg, time) values(?,?,?,?,?,?)''', msg, time) values(?,?,?,?,?)''',
(server, chan, nick, add_nick, msg, now)) (chan, nick, add_nick, msg, now))
conn.commit() conn.commit()
def get_quotes_by_nick(conn, server, chan, nick): def get_quotes_by_nick(conn, chan, nick):
return conn.execute("select time, nick, msg from quotes where deleted!=1 " return conn.execute("select time, nick, msg from quotes where deleted!=1 "
"and server=? and chan=? and lower(nick)=lower(?) order by time", "and chan=? and lower(nick)=lower(?) order by time",
(server, chan, nick)).fetchall() (chan, nick)).fetchall()
def get_quotes_by_chan(conn, server, chan): def get_quotes_by_chan(conn, chan):
return conn.execute("select time, nick, msg from quotes where deleted!=1 " return conn.execute("select time, nick, msg from quotes where deleted!=1 "
"and server=? and chan=? order by time", (server, chan)).fetchall() "and chan=? order by time", (chan,)).fetchall()
def format_quote(q, num, n_quotes): def format_quote(q, num, n_quotes):
@ -39,15 +29,17 @@ def format_quote(q, num, n_quotes):
return "[%d/%d] %s <%s> %s" % (num, n_quotes, return "[%d/%d] %s <%s> %s" % (num, n_quotes,
time.strftime("%Y-%m-%d", time.gmtime(ctime)), nick, msg) time.strftime("%Y-%m-%d", time.gmtime(ctime)), nick, msg)
@hook.command('q') @hook.command('q')
@hook.command @hook.command
def quote(bot, input): def quote(bot, input):
".q/.quote <nick/#chan> [#n]/.quote add <nick> <msg> -- gets " \ ".q/.quote <nick/#chan> [#n]/.quote add <nick> <msg> -- gets " \
"random or [#n]th quote by <nick> or from <#chan>/adds quote" "random or [#n]th quote by <nick> or from <#chan>/adds quote"
dbpath = os.path.join(bot.persist_dir, dbname) conn = bot.get_db_connection(bot, input.server)
conn = db_connect(dbpath) conn.execute('''create table if not exists quotes
(chan, nick, add_nick, msg, time real, deleted default 0,
primary key (chan, nick, msg))''')
conn.commit()
try: try:
add = re.match(r"add\s+<?[^\w]?(\S+?)>?\s+(.*)", input.inp, re.I) add = re.match(r"add\s+<?[^\w]?(\S+?)>?\s+(.*)", input.inp, re.I)
@ -57,7 +49,7 @@ def quote(bot, input):
if add: if add:
nick, msg = add.groups() nick, msg = add.groups()
try: try:
add_quote(conn, input.server, chan, nick, input.nick, msg) add_quote(conn, chan, nick, input.nick, msg)
except sqlite3.IntegrityError: except sqlite3.IntegrityError:
return "message already stored, doing nothing." return "message already stored, doing nothing."
return "quote added." return "quote added."
@ -67,9 +59,9 @@ def quote(bot, input):
by_chan = False by_chan = False
if select.startswith('#'): if select.startswith('#'):
by_chan = True by_chan = True
quotes = get_quotes_by_chan(conn, input.server, select) quotes = get_quotes_by_chan(conn, select)
else: else:
quotes = get_quotes_by_nick(conn, input.server, chan, select) quotes = get_quotes_by_nick(conn, chan, select)
n_quotes = len(quotes) n_quotes = len(quotes)

View File

@ -1,36 +1,21 @@
" seen.py: written by sklnd in about two beers July 2009" " seen.py: written by sklnd in about two beers July 2009"
import os
import time import time
from datetime import datetime
import sqlite3
from util import hook, timesince from util import hook, timesince
dbname = "skybot.db"
def adapt_datetime(ts):
return time.mktime(ts.timetuple())
sqlite3.register_adapter(datetime, adapt_datetime)
@hook.tee @hook.tee
def seeninput(bot, input): def seeninput(bot, input):
if input.command != 'PRIVMSG': if input.command != 'PRIVMSG':
return return
dbpath = os.path.join(bot.persist_dir, dbname) conn = db_connect(bot, input.server)
conn = dbconnect(dbpath)
cursor = conn.cursor() cursor = conn.cursor()
cursor.execute("INSERT OR REPLACE INTO seen(name, date, quote, chan)" cursor.execute("INSERT OR REPLACE INTO seen(name, date, quote, chan)"
"values(?,?,?,?)", (input.nick.lower(), datetime.now(), "values(?,?,?,?)", (input.nick.lower(), time.time(),
input.msg, input.chan)) input.msg, input.chan))
conn.commit() conn.commit()
conn.close()
@hook.command @hook.command
@ -45,8 +30,7 @@ def seen(bot, input):
if query.lower() == input.nick.lower(): if query.lower() == input.nick.lower():
return "Have you looked in a mirror lately?" return "Have you looked in a mirror lately?"
dbpath = os.path.join(bot.persist_dir, dbname) conn = db_connect(bot, input.server)
conn = dbconnect(dbpath)
cursor = conn.cursor() cursor = conn.cursor()
command = "SELECT date, quote FROM seen WHERE name LIKE ? AND chan = ?" \ command = "SELECT date, quote FROM seen WHERE name LIKE ? AND chan = ?" \
@ -54,19 +38,17 @@ def seen(bot, input):
cursor.execute(command, (query, input.chan)) cursor.execute(command, (query, input.chan))
results = cursor.fetchone() results = cursor.fetchone()
conn.close() if results:
reltime = timesince.timesince(results[0])
if(results != None):
reltime = timesince.timesince(datetime.fromtimestamp(results[0]))
return '%s was last seen %s ago saying: %s' % \ return '%s was last seen %s ago saying: %s' % \
(query, reltime, results[1]) (query, reltime, results[1])
else: else:
return "I've never seen %s" % query return "I've never seen %s" % query
def dbconnect(db): def db_connect(bot, server):
"check to see that our db has the the seen table and return a connection." "check to see that our db has the the seen table and return a connection."
conn = sqlite3.connect(db) conn = bot.get_db_connection(server)
conn.execute("CREATE TABLE IF NOT EXISTS " conn.execute("CREATE TABLE IF NOT EXISTS "
"seen(name varchar(30) not null, date datetime not null, " "seen(name varchar(30) not null, date datetime not null, "

View File

@ -1,131 +1,100 @@
" tell.py: written by sklnd in July 2009" " tell.py: written by sklnd in July 2009"
" 2010.01.25 - modified by Scaevolus"
import os
import time
from datetime import datetime
import sqlite3 import sqlite3
import time
from util import hook, timesince from util import hook, timesince
def get_tells(conn, user_to, chan):
dbname = "skybot.db" return conn.execute("select user_from, message, time from tell where"
" user_to=lower(?) and chan=? order by time",
(user_to.lower(), chan)).fetchall()
def adapt_datetime(ts): @hook.command(hook=r'(.*)', prefix=False)
return time.mktime(ts.timetuple())
sqlite3.register_adapter(datetime, adapt_datetime)
@hook.command(hook=r'^(?!\.showtells)(.*)', prefix=False, ignorebots=True)
def tellinput(bot, input): def tellinput(bot, input):
dbpath = os.path.join(bot.persist_dir, dbname) if 'showtells' in input.inp.lower():
conn = dbconnect(dbpath) return
cursor = conn.cursor() conn = db_connect(bot, input.server)
command = "select count(name) from tell where name LIKE ? and chan = ?"
results = cursor.execute(command, (input.nick, input.chan)).fetchone()
tells = get_tells(conn, input.nick, input.chan)
if results[0] > 0: if tells:
command = "select id, user_from, quote, date from tell " \ user_from, message, time = tells[0]
"where name LIKE ? and chan = ? limit 1" reltime = timesince.timesince(time)
tell = cursor.execute(command, (input.nick, input.chan)).fetchall()[0]
more = results[0] - 1
reltime = timesince.timesince(datetime.fromtimestamp(tell[3]))
reply = "%(teller)s said %(reltime)s ago: %(quote)s" % \ reply = "%s said %s ago: %s" % (user_from, reltime, message)
{"teller": tell[1], "quote": tell[2], "reltime": reltime} if len(tells) > 1:
if more: reply += " (+%d more, .showtells to view)" % (len(tells) - 1)
reply += " (+%(more)d more, to view use .showtells)" % {"more": more}
input.reply(reply)
command = "delete from tell where id = ?"
cursor.execute(command, (tell[0], ))
conn.execute("delete from tell where user_to=lower(?) and message=?",
(input.nick, message))
conn.commit() conn.commit()
conn.close() return reply
@hook.command @hook.command
def showtells(bot, input): def showtells(bot, input):
".showtells -- view all pending tell messages (sent in PM)." ".showtells -- view all pending tell messages (sent in PM)."
dbpath = os.path.join(bot.persist_dir, dbname) conn = db_connect(bot, input.server)
conn = dbconnect(dbpath)
cursor = conn.cursor() tells = get_tells(conn, input.nick, input.chan)
command = "SELECT id, user_from, quote, date FROM tell " \
"WHERE name LIKE ? and chan = ?"
tells = cursor.execute(command, (input.nick, input.chan)).fetchall()
if(len(tells) > 0): if not tells:
for tell in tells:
reltime = timesince.timesince(datetime.fromtimestamp(tell[3]))
input.pm('%(teller)s said %(time)s ago: %(quote)s' % \
{'teller': tell[1], 'quote': tell[2], 'time': reltime})
command = "delete from tell where id = ?"
cursor.execute(command, (tell[0], ))
conn.commit()
else:
input.pm("You have no pending tells.") input.pm("You have no pending tells.")
return
conn.close() for tell in tells:
user_from, message, time = tell
reltime = timesince.timesince(time)
input.pm("%s said %s ago: %s" % (user_from, reltime, message))
conn.execute("delete from tell where user_to=lower(?) and chan=?",
(input.nick, input.chan))
conn.commit()
@hook.command @hook.command
def tell(bot, input): def tell(bot, input):
".tell <nick> <message> -- relay <message> to <nick> when <nick> is around" ".tell <nick> <message> -- relay <message> to <nick> when <nick> is around"
if len(input.msg) < 6: query = input.inp.split(' ', 1)
if len(query) != 2 or not input.inp:
return tell.__doc__ return tell.__doc__
query = input.inp.partition(" ") user_to = query[0].lower()
message = query[1].strip()
user_from = input.nick
if query[0] == input.nick: if user_to == user_from.lower():
return "No." return "No."
conn = db_connect(bot, input.server)
if query[2] != "": if conn.execute("select count() from tell where user_to=?",
dbpath = os.path.join(bot.persist_dir, dbname) (user_to,)).fetchone()[0] >= 5:
conn = dbconnect(dbpath) return "That person has too many things queued."
command = "select count(*) from tell_probation where name=? and chan=?"
if conn.execute(command, (input.nick, input.chan)).fetchone()[0] > 0:
return "No."
command = "select count(*) from tell where name=? and user_from=?"
if conn.execute(command, (query[0], input.nick)).fetchone()[0] >= 3:
return "You've told that person too many things."
cursor = conn.cursor()
command = "insert into tell(name, user_from, quote, chan, date) " \
"values(?,?,?,?,?)"
cursor.execute(command, (query[0], input.nick, query[2], input.chan,
datetime.now()))
try:
conn.execute("insert into tell(user_to, user_from, message, chan,"
"time) values(?,?,?,?,?)", (user_to, user_from, message,
input.chan, time.time()))
conn.commit() conn.commit()
conn.close() except sqlite3.IntegrityError:
return "Message has already been queued."
return "I'll pass that along." return "I'll pass that along."
else:
return tell.__doc__
def db_connect(bot, server):
def dbconnect(db):
"check to see that our db has the tell table and return a connection." "check to see that our db has the tell table and return a connection."
conn = sqlite3.connect(db) conn = bot.get_db_connection(server)
conn.execute("CREATE TABLE IF NOT EXISTS tell(id integer primary key "
"autoincrement, name text not null, user_from text not null,"
"quote text not null, chan text not null, "
"date datetime not null);")
conn.execute("CREATE TABLE IF NOT EXISTS "
"tell_probation(name text, chan text,"
"primary key(name, chan));")
conn.execute("create table if not exists tell"
"(user_to, user_from, message, chan, time,"
"primary key(user_to, message))")
conn.commit() conn.commit()
return conn return conn

View File

@ -1,39 +1,34 @@
import os
import time import time
import sqlite3
import pickle
import re import re
from util import hook, urlnorm from util import hook, urlnorm
url_re = re.compile(r'([a-zA-Z]+://|www\.)[^ ]*') url_re = re.compile(r'([a-zA-Z]+://|www\.)[^ ]*')
dbname = "skybot.db"
expiration_period = 60 * 60 * 24 # 1 day expiration_period = 60 * 60 * 24 # 1 day
expiration_period_text = "24 hours" expiration_period_text = "24 hours"
ignored_urls = [urlnorm.normalize("http://google.com")] ignored_urls = [urlnorm.normalize("http://google.com")]
def dbconnect(db): def db_connect(bot, server):
"check to see that our db has the the seen table and return a connection." "check to see that our db has the the seen table and return a connection."
conn = sqlite3.connect(db) conn = bot.get_db_connection(server)
conn.execute("create table if not exists urlhistory" conn.execute("create table if not exists urlhistory"
"(server, chan, url, nick, time)") "(chan, url, nick, time)")
conn.commit() conn.commit()
return conn return conn
def insert_history(conn, server, chan, url, nick): def insert_history(conn, chan, url, nick):
now = time.time() now = time.time()
conn.execute("insert into urlhistory(server, chan, url, nick, time) " conn.execute("insert into urlhistory(chan, url, nick, time) "
"values(?,?,?,?,?)", (server, chan, url, nick, time.time())) "values(?,?,?,?)", (chan, url, nick, time.time()))
conn.commit() conn.commit()
def get_history(conn, server, chan, url): def get_history(conn, chan, url):
conn.execute("delete from urlhistory where time < ?", conn.execute("delete from urlhistory where time < ?",
(time.time() - expiration_period,)) (time.time() - expiration_period,))
nicks = conn.execute("select nick from urlhistory where server=? " nicks = conn.execute("select nick from urlhistory where "
"and chan=? and url=?", (server, chan, url)).fetchall() "chan=? and url=?", (chan, url)).fetchall()
return [x[0] for x in nicks] return [x[0] for x in nicks]
def get_nicklist(nicks): def get_nicklist(nicks):
@ -48,18 +43,17 @@ def ordinal(count):
@hook.command(hook=r'(.*)', prefix=False) @hook.command(hook=r'(.*)', prefix=False)
def urlinput(bot, input): def urlinput(bot, input):
dbpath = os.path.join(bot.persist_dir, dbname)
m = url_re.search(input.msg.encode('utf8')) m = url_re.search(input.msg.encode('utf8'))
if not m: if not m:
return return
# URL detected # URL detected
conn = dbconnect(dbpath) conn = db_connect(bot, input.server)
try: try:
url = urlnorm.normalize(m.group(0)) url = urlnorm.normalize(m.group(0))
if url not in ignored_urls: if url not in ignored_urls:
dupes = get_history(conn, input.server, input.chan, url) dupes = get_history(conn, input.chan, url)
insert_history(conn, input.server, input.chan, url, input.nick) insert_history(conn, input.chan, url, input.nick)
if dupes and input.nick not in dupes: if dupes and input.nick not in dupes:
input.reply("That link has been posted " + ordinal(len(dupes)) input.reply("That link has been posted " + ordinal(len(dupes))
+ " in the past " + expiration_period_text + " by " + + " in the past " + expiration_period_text + " by " +

View File

@ -50,6 +50,9 @@ def timesince(d, now=None):
(60 * 60, ('hour', 'hours')), (60 * 60, ('hour', 'hours')),
(60, ('minute', 'minutes')) (60, ('minute', 'minutes'))
) )
if isinstance(d, int) or isinstance(d, float):
d = datetime.datetime.fromtimestamp(d)
# Convert datetime.date to datetime.datetime for comparison. # Convert datetime.date to datetime.datetime for comparison.
if not isinstance(d, datetime.datetime): if not isinstance(d, datetime.datetime):
d = datetime.datetime(d.year, d.month, d.day) d = datetime.datetime(d.year, d.month, d.day)

View File

@ -12,7 +12,7 @@ def wolframalpha(inp):
"results for <query>" "results for <query>"
if not inp: if not inp:
return wolframalpha.__help__ return wolframalpha.__doc__
url = "http://www.wolframalpha.com/input/?i=%s&asynchronous=false" url = "http://www.wolframalpha.com/input/?i=%s&asynchronous=false"