nxy/nxy/plugins/futures.py
2017-05-16 18:37:27 +02:00

109 lines
4.1 KiB
Python

# -*- coding: utf-8 -*-
from datetime import datetime, timedelta
import asyncio
from docopt import Dict as DocOptDict
from irc3.plugins.command import command
from irc3.utils import IrcString
from irc3 import IrcBot, event
import irc3
from . import DatabasePlugin
from ..utils import fmt, time_delta
@irc3.plugin
class Futures(DatabasePlugin):
requires = [
'irc3.plugins.command',
'nxy.plugins.database',
]
def __init__(self, bot: IrcBot):
super().__init__(bot)
self.tell_queue = {}
# Restore timers from database
self.cur.execute('select * from timers')
for res in self.cur.fetchall():
delta = res['until'] - datetime.utcnow()
args = (IrcString(res['mask']), res['channel'], delta,
res['message'], res['delay'], res['id'])
asyncio.ensure_future(self._timer(*args))
# Restore tells from database
self.cur.execute('select * from tells')
for res in self.cur.fetchall():
user = res['user']
if user not in self.tell_queue:
self.tell_queue[user] = []
self.tell_queue[user].append(res)
@command
def timer(self, mask: IrcString, channel: IrcString, args: DocOptDict):
"""Sets a timer, delay can be: s, m, h, w, mon, y(
%%timer <delay> <message>...
"""
delay = args['<delay>']
delta = time_delta(delay)
if delta:
date = datetime.utcnow() + delta
message = ' '.join(args['<message>'])
self.cur.execute('''insert into timers (mask, channel, message,
delay, until) values (?, ?, ?, ?, ?)''', [mask.nick, channel,
message, delay, date])
self.con.commit()
asyncio.ensure_future(self._timer(mask, channel, delta, message,
delay, self.cur.lastrowid))
self.bot.notice(mask.nick, 'Timer in {delay} set: {message}'
.format(delay=delay, message=message))
else:
self.bot.privmsg(channel, 'Invalid timer delay')
# noinspection PyUnusedLocal
@command
def tell(self, mask: IrcString, channel: IrcString, args: DocOptDict):
"""Saves a message for nick to forward on activity
%%tell <nick> <message>...
"""
nick = args['<nick>']
message = ' '.join(args['<message>'])
if nick not in self.tell_queue:
self.tell_queue[nick] = []
self.cur.execute('insert into tells (mask, user, message) values '
'(?, ?, ?)', [mask, nick, message])
self.con.commit()
self.tell_queue[nick].append({
'id': self.cur.lastrowid,
'mask': mask,
'user': nick,
'message': message,
})
async def _timer(self, mask: IrcString, channel: IrcString,
delta: timedelta, message: str, delay: str, row_id: int):
"""Async function, sleeps for `delay` seconds and sends notification"""
seconds = delta.total_seconds()
if seconds > 0:
await asyncio.sleep(seconds)
text = fmt('{bold}[Timer]{reset} {nick}: {message} ({delay})',
message=message, delay=delay, nick=mask.nick)
self.bot.privmsg(channel, text)
self.cur.execute('delete from timers where id = ?', [row_id])
self.con.commit()
@event(r'(?i)^:(?P<mask>.*) PRIVMSG .* :.*')
def tell_check(self, mask: str):
nick = IrcString(mask).nick
if nick in self.tell_queue:
ids = []
for tell in self.tell_queue[nick]:
ids.append(tell['id'])
self.bot.privmsg(nick, '[Tell] Message from {nick}: {message}'
.format(nick=IrcString(tell['mask']).nick,
message=tell['message']))
del self.tell_queue[nick]
self.cur.execute('delete from tells where id in ({})'
.format(', '.join('?' * len(ids))), ids)
self.con.commit()