initial (and working?) version of history tracking plugin
This commit is contained in:
parent
b3b8f832a2
commit
e43807fb27
1
history/__init__.py
Normal file
1
history/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
"""Track IRC channel history and report on it for users."""
|
142
history/ircplugin.py
Normal file
142
history/ircplugin.py
Normal file
@ -0,0 +1,142 @@
|
||||
"""Monitor and playback IRC stuff."""
|
||||
import logging
|
||||
|
||||
import irc.client
|
||||
|
||||
from ircbot.lib import Plugin, most_specific_message
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class History(Plugin):
|
||||
"""Watch the history of IRC channels and try to track what users may have missed."""
|
||||
|
||||
what_missed_regex = r'what did I miss\?$'
|
||||
|
||||
def start(self):
|
||||
"""Set up the handlers."""
|
||||
logger.debug("%s starting up", __name__)
|
||||
self.connection.add_global_handler('pubmsg', self.handle_chatter, 50)
|
||||
self.connection.add_global_handler('join', self.handle_join, 50)
|
||||
self.connection.add_global_handler('part', self.handle_part, 50)
|
||||
self.connection.add_global_handler('quit', self.handle_quit, 50)
|
||||
|
||||
self.connection.reactor.add_global_regex_handler(['pubmsg', 'privmsg'], self.what_missed_regex,
|
||||
self.handle_what_missed, 60)
|
||||
|
||||
self.channel_history = {}
|
||||
self.channel_participants = {}
|
||||
self.channel_leave_points = {}
|
||||
|
||||
super(History, self).start()
|
||||
|
||||
def stop(self):
|
||||
"""Tear down handlers."""
|
||||
logger.debug("%s shutting down", __name__)
|
||||
self.connection.remove_global_handler('pubmsg', self.handle_chatter)
|
||||
self.connection.remove_global_handler('join', self.handle_join)
|
||||
self.connection.remove_global_handler('part', self.handle_part)
|
||||
self.connection.remove_global_handler('quit', self.handle_quit)
|
||||
|
||||
self.connection.reactor.remove_global_regex_handler(['pubmsg', 'privmsg'], self.handle_what_missed)
|
||||
|
||||
super(History, self).stop()
|
||||
|
||||
def handle_chatter(self, connection, event):
|
||||
"""Track IRC chatter."""
|
||||
what = event.arguments[0]
|
||||
where = event.target
|
||||
who = irc.client.NickMask(event.source).nick
|
||||
|
||||
logger.debug("tracking message for %s: (%s,%s)", where, who, what)
|
||||
history = self.channel_history.setdefault(where, [])
|
||||
history.append((who, what))
|
||||
logger.debug("history for %s: %s", where, history)
|
||||
|
||||
# for when we maybe don't see a join, if they talked in the channel, add them to it
|
||||
self._add_channel_participant(where, who)
|
||||
|
||||
def handle_join(self, connection, event):
|
||||
"""Track who is entitled to see channel history."""
|
||||
where = event.target
|
||||
who = irc.client.NickMask(event.source).nick
|
||||
logger.debug("%s joined %s", who, where)
|
||||
|
||||
self._add_channel_participant(where, who)
|
||||
|
||||
def handle_part(self, connection, event):
|
||||
"""Note when people leave IRC channels."""
|
||||
where = event.target
|
||||
who = irc.client.NickMask(event.source).nick
|
||||
logger.debug("%s left %s", who, where)
|
||||
|
||||
# if they parted the channel, they must have been in it, so note their point in history
|
||||
self._add_channel_leave_point(where, who)
|
||||
self._remove_channel_participant(where, who)
|
||||
|
||||
def handle_quit(self, connection, event):
|
||||
"""Note when people leave IRC."""
|
||||
who = irc.client.NickMask(event.source).nick
|
||||
logger.debug("%s disconnected", who)
|
||||
|
||||
# find all channels the quitter was in, save their leave points
|
||||
for channel in self.channel_participants.keys():
|
||||
self._add_channel_leave_point(channel, who)
|
||||
self._remove_channel_participant(channel, who)
|
||||
|
||||
def handle_what_missed(self, connection, event, match):
|
||||
"""Tell the user what they missed."""
|
||||
who = irc.client.NickMask(event.source).nick
|
||||
if event.in_privmsg or event.addressed:
|
||||
logger.debug("<%s> %s is asking for an update", who, most_specific_message(event))
|
||||
if event.in_privmsg:
|
||||
total_history = []
|
||||
for channel in self.channel_leave_points.keys():
|
||||
logger.debug("checking history slice for %s", channel)
|
||||
total_history += self._missed_slice(channel, who)
|
||||
logger.debug("total history so far: %s", total_history)
|
||||
logger.debug("final missed history: %s", total_history)
|
||||
self._send_history(who, total_history)
|
||||
return 'NO MORE'
|
||||
else:
|
||||
where = event.target
|
||||
history = self._missed_slice(where, who)
|
||||
self._send_history(who, history)
|
||||
return 'NO MORE'
|
||||
|
||||
def _send_history(self, who, history):
|
||||
"""Reply to who with missed history."""
|
||||
for line in history:
|
||||
self.bot.privmsg(who, f"<{line[0]}> {line[1]}")
|
||||
|
||||
def _add_channel_leave_point(self, where, who):
|
||||
"""Note that the given who left the channel at the current history point."""
|
||||
leave_points = self.channel_leave_points.setdefault(where, {})
|
||||
leave_points[who] = len(self.channel_history.setdefault(where, [])) - 1
|
||||
logger.debug("leave points for %s: %s", where, leave_points)
|
||||
|
||||
def _add_channel_participant(self, where, who):
|
||||
"""Add a who to the list of people who are/were in a channel."""
|
||||
participants = self.channel_participants.setdefault(where, set())
|
||||
participants.add(who)
|
||||
logger.debug("participants for %s: %s", where, participants)
|
||||
|
||||
def _missed_slice(self, where, who):
|
||||
"""Get the lines in where since who last left."""
|
||||
leave_points = self.channel_leave_points.setdefault(where, {})
|
||||
if leave_points.get(who) is not None:
|
||||
leave_point = leave_points.get(who) + 1
|
||||
history = self.channel_history.setdefault(where, [])
|
||||
missed_history = history[leave_point:]
|
||||
logger.debug("in %s, %s missed: %s", where, who, missed_history)
|
||||
return missed_history
|
||||
return []
|
||||
|
||||
def _remove_channel_participant(self, where, who):
|
||||
"""Remove the specified who from the where channel's participants list."""
|
||||
participants = self.channel_participants.setdefault(where, set())
|
||||
participants.remove(who)
|
||||
logger.debug("participants for %s: %s", where, participants)
|
||||
|
||||
|
||||
plugin = History
|
Loading…
Reference in New Issue
Block a user