klafirc/klafirc/bot.py
2018-08-28 21:55:39 +02:00

111 lines
3.4 KiB
Python

import re
import random
import importlib
import datetime
class Bot:
def __init__(self, nickname):
"""Initialize a bot object
Args:
nickname: nickname of the bot on irc
"""
self.nickname = nickname
self.channel = None
self.port = None
self.server = None
self.reactions = {}
self.pings = []
self.on_join = None
self.tg_user_match = re.compile('^<\x03..\x02\x02(?P<username>.+)\x03>')
self.ping_match = re.compile('^(<.+> )?\@?{name}'.format(name=nickname))
self.min_time = 0
self.last_time = datetime.datetime(1,1,1)
def add_reaction(self, match, reaction):
"""Add a reaction to the bot.
Args:
match: The string which, if matched will trigger the answer.
reaction: The string which will be sent.
"""
context = {
'server': self.server,
'channel': self.channel,
'name': self.nickname,
}
self.reactions[re.compile(match.format(**context))] = reaction
def add_python_reaction(self, match, reaction):
""" Add a Python callback to the reactions.
Args:
match: The string which, if matched will trigger the answer.
reaction: The path to the callback
"""
self.add_reaction(match, self.fetch_callback(reaction))
def add_ping(self, reaction):
"""Add a reaction to a ping"""
self.pings.append(reaction)
def add_python_ping(self, reaction):
"""Fetch a Python callable and add it to the pings"""
self.add_ping(self.fetch_callback(reaction))
def fetch_callback(self, path):
"""Fetch a Python callable"""
s = path.split('.')
module, callback = '.'.join(s[:-1]), s[-1]
module = importlib.import_module(module)
return getattr(module, callback)
def get_reaction(self, user, channel, message):
"""Get a reaction to a message.
Args:
user: The user who sent the message.
channel: The channel on which the bot speak.
message: The message to which the bot has to react.
Returns:
Every matched reactions.
"""
if (datetime.datetime.now() - self.last_time).total_seconds() < self.min_time:
return []
username = user.split('!')[0]
tg_user_match = self.tg_user_match.match(message)
if 'bot' in username.lower() and tg_user_match:
username = '@' + tg_user_match.groupdict()['username']
context = {
'server': self.server,
'channel': channel,
'name': self.nickname,
'user': username,
'message': message
}
result = []
for m in self.reactions.keys():
if m.search(message):
r = self.reactions[m]
if callable(r):
r = r(self, username, channel, message)
else:
r = r.format(**context)
result.append(r)
if not result and self.ping_match.search(message):
r = random.choice(self.pings)
if callable(r):
r = r(self, username, channel, message)
else:
r = r.format(**context)
result.append(' : '.join([username, r]))
if len(result) > 0:
self.last_time = datetime.datetime.now()
return result