112 lines
3.5 KiB
Python
112 lines
3.5 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():
|
|
search = m.search(message)
|
|
if search:
|
|
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
|