from csbot.plugin import Plugin
from csbot.util import nick
from csbot.events import Event
from datetime import datetime
import pymongo
[docs]class Last(Plugin):
"""Utility plugin to record the last message (and time said) of a
user. Records both messages and actions individually, and allows
querying on either.
"""
db = Plugin.use('mongodb', collection='last')
[docs] def last(self, nick, channel=None, msgtype=None):
"""Get the last thing said (including actions) by a given
nick, optionally filtering by channel.
"""
search = {'nick': nick}
if channel is not None:
search['channel'] = channel
if msgtype is not None:
search['type'] = msgtype
# Additional sorting by _id to make sort order stable for messages that arrive in the same millisecond
# (which sometimes happens during tests).
return self.db.find_one(search, sort=[('when', pymongo.DESCENDING), ('_id', pymongo.DESCENDING)])
[docs] def last_message(self, nick, channel=None):
"""Get the last message sent by a nick, optionally filtering
by channel.
"""
return self.last(nick, channel=channel, msgtype='message')
[docs] def last_action(self, nick, channel=None):
"""Get the last action sent by a nick, optionally filtering
by channel.
"""
return self.last(nick, channel=channel, msgtype='action')
[docs] def last_command(self, nick, channel=None):
"""Get the last command sent by a nick, optionally filtering
by channel.
"""
return self.last(nick, channel=channel, msgtype='command')
[docs] @Plugin.hook('core.message.privmsg')
def record_message(self, event):
"""Record the receipt of a new message.
"""
# Check if this is an action
if event['message'].startswith('\x01ACTION'):
return
# Check if this is a command
if event['message'].startswith(self.bot.config.command_prefix):
return
self.record(event,
nick(event['user']),
event['channel'],
'message',
event['message'])
[docs] @Plugin.hook('core.message.privmsg')
def record_command(self, event):
"""Record the receipt of a new command.
"""
if not event['message'].startswith(self.bot.config.command_prefix):
return
self.record(event,
nick(event['user']),
event['channel'],
'command',
event['message'])
[docs] @Plugin.hook('core.message.action')
def record_action(self, event):
"""Record the receipt of a new action.
"""
self.record(event,
nick(event['user']),
event['channel'],
'action',
event['message'])
[docs] def record(self, event, nick, channel, msgtype, msg):
"""Record a new message, of a given type.
"""
self._schedule_update(event,
{'nick': nick,
'channel': channel,
'type': msgtype},
{'nick': nick,
'channel': channel,
'type': msgtype,
'when': datetime.now(),
'message': msg})
def _schedule_update(self, e, query, update):
self.bot.post_event(Event.extend(e, 'last.update',
{'query': query, 'update': update}))
@Plugin.hook('last.update')
def _apply_update(self, e):
self.db.replace_one(e['query'], e['update'], upsert=True)
[docs] @Plugin.command('seen', help=('seen nick [type]: show the last thing'
' said by a nick in this channel, optionally'
' filtering by type: message, action,'
' or command.'))
def show_seen(self, event):
splitted = event['data'].split()
thenick = splitted[0]
msgtype = splitted[1] if len(splitted) > 1 else None
if msgtype not in ['message', 'command', 'action', None]:
event.reply('Bad filter: {}. Accepted are "message", "command", and "action".'.format(msgtype))
return
message = self.last(thenick, channel=event['channel'], msgtype=msgtype)
if message is None:
event.reply('Nothing recorded for {}'.format(thenick))
elif message['type'] in ['message', 'command']:
event.reply('[{}] <{}> {}'.format(message['when'].strftime("%Y-%m-%d %H:%M:%S"),
thenick,
message['message']))
else:
event.reply('[{}] * {} {}'.format(message['when'].strftime("%Y-%m-%d %H:%M:%S"),
thenick,
message['message']))