# Path: cardinal/decorators.py
# def command(triggers):
#     if isinstance(triggers, str):
#         triggers = [triggers]
# 
#     if not isinstance(triggers, list):
#         raise TypeError("Command must be a trigger string or list of triggers")
# 
#     def wrap(f):
#         f.commands = triggers
#         return f
# 
#     return wrap
# 
# def help(lines):
#     # For backwards compatibility
#     if isinstance(lines, str):
#         lines = [lines]
# 
#     if not isinstance(lines, list):
#         raise TypeError("Help must be a help string or list of help strings")
# 
#     def wrap(f):
#         # Create help list or prepend to it
#         if not hasattr(f, 'help'):
#             f.help = lines
#         else:
#             f.help = lines + f.help
# 
#         return f
# 
#     return wrap
# 
# def event(triggers):
#     if isinstance(triggers, str):
#         triggers = [triggers]
# 
#     if not isinstance(triggers, list):
#         raise TypeError("Event must be a trigger string or list of triggers")
# 
#     def wrap(f):
#         f.events = triggers
#         return f
# 
#     return wrap
# 
# Path: cardinal/util.py
# def is_action(message):
#     """Checks if a message is a /me message."""
#     return message.startswith("\x01ACTION")
# 
# def parse_action(nick, message):
#     """Parses a /me message like an IRC client might.
# 
#     e.g. "/me dances." -> "* Cardinal dances."
#     """
#     if not is_action(message):
#         raise ValueError("This message is not an ACTION message")
# 
#     message = message[len("\x01ACTION "):]
#     if message and message[-1] == "\x01":
#         message = message[:-1]
# 
#     return "* {}{}".format(
#         nick,
#         " " + message if message else "",
#     )
# 
# def strip_formatting(line):
#     """Removes mIRC control code formatting"""
#     return re.sub(r"(?:\x03\d\d?,\d\d?|\x03\d\d?|[\x01-\x1f])", "", line)


from datetime import datetime, timezone
from cardinal.decorators import command, help, event
from cardinal.util import (
    is_action,
    parse_action,
    strip_formatting,
)
        days, seconds = divmod(seconds, 60 * 60 * 24)
        hours, seconds = divmod(seconds, 60 * 60)
        minutes, seconds = divmod(seconds, 60)
        retval = "%d days " % days if days else ""
        retval += "%02d:%02d:%02d" % (hours, minutes, seconds)
        return retval

    def format_seen(self, nick):
        with self.db() as db:
            if nick.lower() not in db['users']:
                return "Sorry, I haven't seen {}.".format(nick)

            entry = db['users'][nick.lower()]

        dt_timestamp = datetime.fromtimestamp(
            entry['timestamp'],
            tz=timezone.utc,
        )
        t_seen = dt_timestamp.strftime("%Y-%m-%d %H:%M:%S")
        t_ago = self._pretty_seconds((datetime
                                     .now(tz=timezone.utc)
                                     .replace(microsecond=0)
                                     - dt_timestamp).total_seconds())

        message = "I last saw {} {} ago ({}). ".format(nick, t_ago, t_seen)

        action, params = entry['action'], entry['params']
        if action == PRIVMSG:
            last_msg = params[1]
            if is_action(last_msg):

# Path: cardinal/decorators.py
# def command(triggers):
#     if isinstance(triggers, str):
#         triggers = [triggers]
# 
#     if not isinstance(triggers, list):
#         raise TypeError("Command must be a trigger string or list of triggers")
# 
#     def wrap(f):
#         f.commands = triggers
#         return f
# 
#     return wrap
# 
# def help(lines):
#     # For backwards compatibility
#     if isinstance(lines, str):
#         lines = [lines]
# 
#     if not isinstance(lines, list):
#         raise TypeError("Help must be a help string or list of help strings")
# 
#     def wrap(f):
#         # Create help list or prepend to it
#         if not hasattr(f, 'help'):
#             f.help = lines
#         else:
#             f.help = lines + f.help
# 
#         return f
# 
#     return wrap
# 
# def event(triggers):
#     if isinstance(triggers, str):
#         triggers = [triggers]
# 
#     if not isinstance(triggers, list):
#         raise TypeError("Event must be a trigger string or list of triggers")
# 
#     def wrap(f):
#         f.events = triggers
#         return f
# 
#     return wrap
# 
# Path: cardinal/util.py
# def is_action(message):
#     """Checks if a message is a /me message."""
#     return message.startswith("\x01ACTION")
# 
# def parse_action(nick, message):
#     """Parses a /me message like an IRC client might.
# 
#     e.g. "/me dances." -> "* Cardinal dances."
#     """
#     if not is_action(message):
#         raise ValueError("This message is not an ACTION message")
# 
#     message = message[len("\x01ACTION "):]
#     if message and message[-1] == "\x01":
#         message = message[:-1]
# 
#     return "* {}{}".format(
#         nick,
#         " " + message if message else "",
#     )
# 
# def strip_formatting(line):
#     """Removes mIRC control code formatting"""
#     return re.sub(r"(?:\x03\d\d?,\d\d?|\x03\d\d?|[\x01-\x1f])", "", line)


# Path: plugins/seen/plugin.py
from datetime import datetime, timezone
from cardinal.decorators import command, help, event
from cardinal.util import (
    is_action,
    parse_action,
    strip_formatting,
)

        days, seconds = divmod(seconds, 60 * 60 * 24)
        hours, seconds = divmod(seconds, 60 * 60)
        minutes, seconds = divmod(seconds, 60)
        retval = "%d days " % days if days else ""
        retval += "%02d:%02d:%02d" % (hours, minutes, seconds)
        return retval

    def format_seen(self, nick):
        with self.db() as db:
            if nick.lower() not in db['users']:
                return "Sorry, I haven't seen {}.".format(nick)

            entry = db['users'][nick.lower()]

        dt_timestamp = datetime.fromtimestamp(
            entry['timestamp'],
            tz=timezone.utc,
        )
        t_seen = dt_timestamp.strftime("%Y-%m-%d %H:%M:%S")
        t_ago = self._pretty_seconds((datetime
                                     .now(tz=timezone.utc)
                                     .replace(microsecond=0)
                                     - dt_timestamp).total_seconds())

        message = "I last saw {} {} ago ({}). ".format(nick, t_ago, t_seen)

        action, params = entry['action'], entry['params']
        if action == PRIVMSG:
            last_msg = params[1]
            if is_action(last_msg):

                last_msg = parse_action(nick, last_msg)