2018-03-16 03:13:43 -04:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
"""
|
|
|
|
The trigger abstraction layer.
|
|
|
|
"""
|
|
|
|
import datetime
|
|
|
|
|
|
|
|
def split_user(user):
|
|
|
|
"""
|
|
|
|
Splits a user hostmask into <nick>!<ident>@<host>
|
|
|
|
"""
|
|
|
|
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, config):
|
|
|
|
"""
|
|
|
|
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, config)
|
|
|
|
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, config):
|
|
|
|
"""
|
|
|
|
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.
|
|
|
|
"""
|
|
|
|
prefix = config.core.prefix
|
|
|
|
group = []
|
|
|
|
group.append(message)
|
|
|
|
words = message.split()
|
|
|
|
group.append(words[0].replace(prefix, "", 1))
|
|
|
|
group.append(" ".join(words[1:]))
|
|
|
|
group += words[1:]
|
|
|
|
|
|
|
|
return group
|
|
|
|
|
|
|
|
|
|
|
|
class Trigger():
|
|
|
|
def __init__(self, user, channel, message, event, config):
|
|
|
|
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
|
2018-03-25 14:27:40 -04:00
|
|
|
that the message was received by Fulvia.
|
2018-03-16 03:13:43 -04:00
|
|
|
"""
|
|
|
|
|
|
|
|
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>
|
|
|
|
"""
|
|
|
|
|
|
|
|
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, config)
|
|
|
|
"""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.core.admins.split(",") + [config.core.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.core.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 <nick>@<host>.
|
|
|
|
"""
|
|
|
|
if self.ident:
|
|
|
|
return compare_against == self.hostmask
|
|
|
|
else:
|
|
|
|
return compare_against == "@".join(self.nick, self.host)
|
|
|
|
|
|
|
|
|
|
|
|
def set_group(self, line, config):
|
|
|
|
"""
|
|
|
|
Allows a you to easily change the current group to a new Group
|
|
|
|
instance.
|
|
|
|
"""
|
|
|
|
self.group = Group(line, config)
|