dr.botzo/karma/ircplugin.py

162 lines
7.2 KiB
Python
Raw Normal View History

"""Karma hooks for the IRC bot."""
import logging
import re
import irc.client
2015-06-20 16:34:18 -05:00
from django.conf import settings
from ircbot.lib import Plugin
from karma.models import KarmaKey, KarmaLogEntry
log = logging.getLogger('karma.ircplugin')
class Karma(Plugin):
"""Track karma and report on it."""
def start(self):
"""Set up the handlers."""
self.connection.add_global_handler('pubmsg', self.handle_chatter, -20)
self.connection.add_global_handler('privmsg', self.handle_chatter, -20)
self.connection.reactor.add_global_regex_handler(['pubmsg', 'privmsg'],
r'^!karma\s+rank\s+(.*)$',
self.handle_rank, -20)
self.connection.reactor.add_global_regex_handler(['pubmsg', 'privmsg'],
(r'^!karma\s+report\s+(highest|lowest|positive|negative'
r'|top|opinionated)'),
self.handle_report, -20)
self.connection.reactor.add_global_regex_handler(['pubmsg', 'privmsg'],
r'^!karma\s+stats\s+([\S]+)',
self.handle_stats, -20)
super(Karma, self).start()
def stop(self):
"""Tear down handlers."""
self.connection.remove_global_handler('pubmsg', self.handle_chatter)
self.connection.remove_global_handler('privmsg', self.handle_chatter)
self.connection.reactor.remove_global_regex_handler(['pubmsg', 'privmsg'], self.handle_rank)
self.connection.reactor.remove_global_regex_handler(['pubmsg', 'privmsg'], self.handle_report)
self.connection.reactor.remove_global_regex_handler(['pubmsg', 'privmsg'], self.handle_stats)
super(Karma, self).stop()
@staticmethod
def handle_chatter(connection, event):
"""Watch karma from IRC chatter."""
what = event.arguments[0].lower()
karma_pattern = r'(?:\((.+?)\)|(\S+))(\+\+|--|\+-|-\+)(\s+|$)'
2015-06-20 16:34:18 -05:00
where = event.target
if where in settings.KARMA_IGNORE_CHATTER_TARGETS:
2015-06-20 16:34:18 -05:00
log.debug("ignoring chatter in {0:s}".format(where))
return
# check the line for karma
2016-01-16 17:58:11 -06:00
log.debug("searching '%s' for karma", what)
matches = re.findall(karma_pattern, what, re.IGNORECASE)
for match in matches:
key = match[0] if match[0] else match[1]
value = match[2]
karma_key, c = KarmaKey.objects.get_or_create(key=key)
if value == '++':
KarmaLogEntry.objects.create(key=karma_key, delta=1, nickmask=event.source)
elif value == '--':
KarmaLogEntry.objects.create(key=karma_key, delta=-1, nickmask=event.source)
elif value == '+-':
KarmaLogEntry.objects.create(key=karma_key, delta=1, nickmask=event.source)
KarmaLogEntry.objects.create(key=karma_key, delta=-1, nickmask=event.source)
elif value == '-+':
KarmaLogEntry.objects.create(key=karma_key, delta=-1, nickmask=event.source)
KarmaLogEntry.objects.create(key=karma_key, delta=1, nickmask=event.source)
def handle_rank(self, connection, event, match):
"""Report on the rank of a karma item."""
where = event.target
if where in settings.KARMA_IGNORE_COMMAND_TARGETS:
log.debug("ignoring command in {0:s}".format(where))
return
key = match.group(1).lower().rstrip()
try:
karma_key = KarmaKey.objects.get(key=key)
return self.bot.reply(event, "{0:s} has {1:d} points of karma (rank {2:d})".format(karma_key.key,
karma_key.score(),
karma_key.rank()))
except KarmaKey.DoesNotExist:
return self.bot.reply(event, "i have not seen any karma for {0:s}".format(match.group(1)))
def handle_report(self, connection, event, match):
"""Provide some karma reports."""
where = event.target
if where in settings.KARMA_IGNORE_COMMAND_TARGETS:
log.debug("ignoring command in {0:s}".format(where))
return
report = match.group(1).lower()
if report == 'highest':
sorted_keys = KarmaKey.objects.ranked_scored_order()
msg = "top 5 recipients: {0:s}".format(", ".join([str(x) for x in sorted_keys[:5]]))
return self.bot.reply(event, msg)
elif report == 'lowest':
sorted_keys = KarmaKey.objects.ranked_scored_reverse_order()
msg = "bottom 5 recipients: {0:s}".format(", ".join([str(x) for x in sorted_keys[:5]]))
return self.bot.reply(event, msg)
elif report == 'positive':
karmaers = KarmaLogEntry.objects.optimists()
karmaer_list = ", ".join(["{0:s} ({1:d})".format(irc.client.NickMask(x['nickmask']).nick,
x['karma_outlook']) for x in karmaers])
msg = "top 5 optimists: {0:s}".format(karmaer_list)
return self.bot.reply(event, msg)
elif report == 'negative':
karmaers = KarmaLogEntry.objects.pessimists()
karmaer_list = ", ".join(["{0:s} ({1:d})".format(irc.client.NickMask(x['nickmask']).nick,
x['karma_outlook']) for x in karmaers])
msg = "top 5 pessimists: {0:s}".format(karmaer_list)
return self.bot.reply(event, msg)
elif report == 'top' or report == 'opinionated':
karmaers = KarmaLogEntry.objects.most_opinionated()
karmaer_list = ", ".join(["{0:s} ({1:d})".format(irc.client.NickMask(x['nickmask']).nick,
x['karma_count']) for x in karmaers])
msg = "top 5 opinionated users: {0:s}".format(karmaer_list)
return self.bot.reply(event, msg)
def handle_stats(self, connection, event, match):
"""Provide stats on a karma user."""
where = event.target
if where in settings.KARMA_IGNORE_COMMAND_TARGETS:
log.debug("ignoring command in {0:s}".format(where))
return
karmaer = match.group(1)
log_entries = KarmaLogEntry.objects.filter(nickmask=karmaer)
if len(log_entries) == 0:
# fallback, try to match the nick part of nickmask
log_entries = KarmaLogEntry.objects.filter(nickmask__startswith='{0:s}!'.format(karmaer))
if len(log_entries) == 0:
return self.bot.reply(event, "karma user {0:s} not found".format(karmaer))
total_karma = log_entries.count()
positive_karma = log_entries.filter(delta__gt=0).count()
negative_karma = log_entries.filter(delta__lt=0).count()
msg = ("{0:s} has given {1:d} postive karma and {2:d} negative karma, for a total of {3:d} karma"
"".format(karmaer, positive_karma, negative_karma, total_karma))
return self.bot.reply(event, msg)
plugin = Karma