#!/usr/bin/env python3 """ The trigger abstraction layer. """ import datetime import config def split_user(user): """ Splits a user hostmask into !@ """ nick, _, host = user.partition("!") ident, _, host = host.partition("@") if not host: host = ident ident = "" return nick, ident, host class Group(list): """ Custom list class that permits calling it like a function so as to emulate a re.group instance. """ def __init__(self, message): """ Initializes the group class. If 'message' is a string, we split it into groups according to the usual trigger.group structure. Otherwise we assume it's already been split appropriately. """ if type(message) == str: message = self.split_group(message) list.__init__(self, message) def __call__(self, n=0): """ Allows you to call the instance like a function. Or a re.group instance ;^). If calling would result in an index error, None is returned instead. """ try: item = list.__getitem__(self, n) except IndexError: item = None return item def split_group(self, message): """ Splits the message by spaces. group(0) is always the entire message. group(1) is always the first word of the message minus the prefix, if present. This is usually just the command. group(2) is always the entire message after the first word. group(3+) is always every individual word after the first word. """ group = [] group.append(message) words = message.split() group.append(words[0].replace(config.prefix, "", 1)) group.append(" ".join(words[1:])) group += words[1:] return group class Trigger(): def __init__(self, user, channel, message, event): self.channel = channel """ The channel from which the message was sent. In a private message, this is the nick that sent the message. """ self.time = datetime.datetime.now() """ A datetime object at which the message was received by the IRC server. If the server does not support server-time, then `time` will be the time that the message was received by Fulvia. """ self.raw = "" """ The entire message, as sent from the server. This includes the CTCP \\x01 bytes and command, if they were included. """ self.is_privmsg = not channel.startswith("#") """True if the trigger is from a user, False if it's from a channel.""" self.hostmask = user """ Entire hostmask of the person who sent the message. eg. !@ """ nick, ident, host = split_user(user) self.nick = nick """Nick of person who sent the message.""" self.ident = ident self.user = ident """Local username (AKA ident) of the person who sent the message.""" self.host = host """The hostname of the person who sent the message""" self.event = event """ The IRC event (e.g. ``PRIVMSG`` or ``MODE``) which triggered the message. """ self.group = Group(message) """The ``group`` function of the ``match`` attribute. See Python :mod:`re` documentation for details.""" self.args = () """ A tuple containing each of the arguments to an event. These are the strings passed between the event name and the colon. For example, setting ``mode -m`` on the channel ``#example``, args would be ``('#example', '-m')`` """ admins = config.admins + [config.owner] self.admin = any([self.compare_hostmask(admin) for admin in admins]) """ True if the nick which triggered the command is one of the bot's admins. """ self.owner = self.compare_hostmask(config.owner) """True if the nick which triggered the command is the bot's owner.""" def compare_hostmask(self, compare_against): """ Compares the current hostmask against the given one. If ident is not None, it uses that, otherwise it only uses @. """ if self.ident: return compare_against == self.hostmask else: return compare_against == "@".join(self.nick, self.host) def set_group(self, line): """ Allows a you to easily change the current group to a new Group instance. """ self.group = Group(line)