nxy/bot/plugins/quotes.py

132 lines
3.7 KiB
Python
Raw Normal View History

2017-05-15 22:26:10 +00:00
# -*- coding: utf-8 -*-
2017-07-07 00:11:20 +00:00
import re
2017-05-15 22:26:10 +00:00
2017-07-07 00:11:20 +00:00
import irc3
2017-05-16 10:06:29 +00:00
from docopt import Dict as DocOptDict
from irc3.plugins.command import command
from irc3.utils import IrcString
from psycopg2 import Error
2017-05-16 10:06:29 +00:00
2017-05-15 22:26:10 +00:00
from . import DatabasePlugin
2017-07-07 00:11:20 +00:00
from ..utils import parse_int
2017-05-15 22:26:10 +00:00
@irc3.plugin
class Quotes(DatabasePlugin):
requires = ['irc3.plugins.command',
2017-07-07 00:11:20 +00:00
'bot.plugins.storage']
def add_quote(self, mask, nick, quote, channel):
# Parse nick from "<@foobar>" like strings
2017-07-07 00:11:20 +00:00
nick = re.match(r'<?[~&@%+]?([a-zA-Z0-9_\-^`|\\\[\]{}]+)>?', nick).group(1)
if not nick:
self.bot.notice(mask.nick, '[Quotes] Error parsing nick')
else:
# Insert quote into database
self.cur.execute('''
2017-08-16 12:39:44 +00:00
INSERT INTO
quotes (nick, item, channel, created_by)
2017-08-16 12:39:44 +00:00
VALUES
2017-06-30 17:33:26 +00:00
(%s, %s, %s, %s)
''', [nick, quote, channel, mask.nick])
def delete_quote(self, nick, quote):
2017-07-07 00:11:20 +00:00
index, order = parse_int(quote, select=False)
if index:
# Delete from database
self.cur.execute('''
with ranked_quotes as (
select
id,
rank() over (partition by nick order by id {order})
from
quotes
where
nick = %s
)
delete from
quotes
where
id = (
select
id
from
ranked_quotes
where
rank = %s
)
'''.format(order=order), [nick, index])
2017-05-15 22:26:10 +00:00
@command(options_first=True)
def q(self, mask: IrcString, target: IrcString, args: DocOptDict):
2017-06-30 18:14:02 +00:00
"""Get, add or delete quotes for an user.
2017-05-16 12:27:34 +00:00
2017-05-15 22:26:10 +00:00
%%q <cmd> <nick> <quote>...
2017-05-16 06:54:47 +00:00
%%q <nick> [<index>]
2017-05-15 22:26:10 +00:00
"""
cmd = args.get('<cmd>')
nick = args['<nick>']
2017-07-04 14:41:54 +00:00
quote = ' '.join(args.get('<quote>'))
if cmd and quote:
try:
# Anybody can add
2017-05-16 06:54:47 +00:00
if cmd == 'add':
self.add_quote(mask, nick, quote, target)
# But only admins can delete
elif cmd == 'del' and self.guard.has_permission(mask, 'admin'):
self.delete_quote(nick, quote)
2017-05-16 06:54:47 +00:00
self.con.commit()
2017-07-04 13:22:20 +00:00
except Error as ex:
# Rollback transaction on error
2017-08-16 12:39:44 +00:00
print(ex)
self.con.rollback()
2017-05-15 22:26:10 +00:00
else:
2017-05-16 06:54:47 +00:00
index = args.get('<index>')
values = [nick]
2017-05-16 06:54:47 +00:00
if index:
index = parse_int(index)
if not index:
return
2017-07-07 00:11:20 +00:00
index, order = index
order = 'rank {order}'.format(order=order)
offset = 'offset %s'
values.append(index)
2017-05-15 22:26:10 +00:00
else:
2017-05-16 06:54:47 +00:00
order = 'random()'
offset = ''
# Fetch quote from database
self.cur.execute("""
with ranked_quotes as (
select
nick,
item,
rank() over (partition by nick order by id),
count(*) over (partition by nick) as total
from
quotes
)
select
*
from
ranked_quotes
where
lower(nick) like lower(%s)
order by
{order}
limit
1
{offset}
""".format(order=order, offset=offset), values)
2017-05-16 06:54:47 +00:00
result = self.cur.fetchone()
2017-05-16 06:54:47 +00:00
if result:
return '[{rank}/{total}] <{nick}> {item}'.format(**result)