Beispiel #1
0
def parsemsg(s, encoding="utf-8"):
    """Parse an IRC Message from s

    :param s bytes: bytes to parse
    :param encoding str: encoding to use (Default: utf-8)

    :returns tuple: parsed message in the form of (prefix, command, args)
    """

    s = s.decode(encoding, 'replace')

    prefix = u("")
    trailing = []

    if s and s[0] == u(":"):
        prefix, s = s[1:].split(u(" "), 1)

    prefix = parseprefix(prefix)

    if s.find(u(" :")) != -1:
        s, trailing = s.split(u(" :"), 1)
        args = s.split()
        args.append(trailing)
    else:
        args = s.split()

    args = iter(args)
    command = next(args, None)
    command = command and str(command)

    return prefix, command, list(args)
Beispiel #2
0
def parsemsg(s, encoding="utf-8"):
    """Parse an IRC Message from s

    :param s bytes: bytes to parse
    :param encoding str: encoding to use (Default: utf-8)

    :returns tuple: parsed message in the form of (prefix, command, args)
    """

    s = s.decode(encoding, 'replace')

    prefix = u("")
    trailing = []

    if s and s[0] == u(":"):
        prefix, s = s[1:].split(u(" "), 1)

    prefix = parseprefix(prefix)

    if s.find(u(" :")) != -1:
        s, trailing = s.split(u(" :"), 1)
        args = s.split()
        args.append(trailing)
    else:
        args = s.split()

    args = iter(args)
    command = next(args, None)
    command = command and str(command)

    return prefix, command, list(args)
Beispiel #3
0
def test_default_args(webapp, data, expected):
    args, kwargs = data
    url = u("{0:s}/test_default_args/{1:s}".format(webapp.server.http.base,
                                                   u("/").join(args)))
    data = urlencode(kwargs).encode("utf-8")
    f = urlopen(url, data)
    assert f.read() == expected
Beispiel #4
0
def RPL_LUSERCLIENT(nusers, nservices, nservers):
    return _M(
        u("251"),
        u("There are {0} users and {1} services on {2} servers").format(
            nusers, nservices, nservers
        )
    )
Beispiel #5
0
def MODE(target, modes, params=None, prefix=None):
    if params is None:
        return Message(u("MODE"), target, modes, prefix=prefix)
    return Message(u("MODE"),
                   target,
                   modes,
                   u(" ").join(params),
                   prefix=prefix)
Beispiel #6
0
def test_default_args(webapp, data, expected):
    args, kwargs = data
    url = u("{0:s}/test_default_args/{1:s}".format(
        webapp.server.http.base,
        u("/").join(args)
    ))
    data = urlencode(kwargs).encode("utf-8")
    f = urlopen(url, data)
    assert f.read() == expected
Beispiel #7
0
def joinprefix(nick, user, host):
    """Join the parts of a prefix

    :param nick str: nickname
    :param user str: username
    :param host str: hostname

    :returns str: a string in the form of <nick>!<user>@<host>
    """

    return u("{0}!{1}@{2}").format(nick or u(""), user or u(""), host or u(""))
Beispiel #8
0
def joinprefix(nick, user, host):
    """Join the parts of a prefix

    :param nick str: nickname
    :param user str: username
    :param host str: hostname

    :returns str: a string in the form of <nick>!<user>@<host>
    """

    return u("{0}!{1}@{2}").format(nick or u(""), user or u(""), host or u(""))
Beispiel #9
0
def test_parsemsg():
    s = b(":foo!bar@localhost NICK foobar")
    source, command, args = parsemsg(s)
    assert source == (u("foo"), u("bar"), u("localhost"))
    assert command == "NICK"
    assert args == [u("foobar")]

    s = b("")
    source, command, args = parsemsg(s)
    assert source == (None, None, None)
    assert command is None
    assert args == []
Beispiel #10
0
    def __init__(self, command, *args, **kwargs):
        self.command = command
        self.args = [x for x in args if x is not None]
        self.prefix = text_type(kwargs["prefix"]) if "prefix" in kwargs else None

        self.encoding = kwargs.get("encoding", "utf-8")
        self.add_nick = kwargs.get("add_nick", False)

        if any(u(' ') in arg for arg in self.args[:-1]):
            raise Error("Space can only appear in the very last arg")
        if any(u('\n') in arg for arg in self.args):
            raise Error("No newline allowed")
Beispiel #11
0
def test_parsemsg():
    s = b(":foo!bar@localhost NICK foobar")
    source, command, args = parsemsg(s)
    assert source == (u("foo"), u("bar"), u("localhost"))
    assert command == "NICK"
    assert args == [u("foobar")]

    s = b("")
    source, command, args = parsemsg(s)
    assert source == (None, None, None)
    assert command is None
    assert args == []
Beispiel #12
0
    def __init__(self, command, *args, **kwargs):
        self.command = command
        self.args = [x for x in args if x is not None]
        self.prefix = text_type(
            kwargs["prefix"]) if "prefix" in kwargs else None

        self.encoding = kwargs.get("encoding", "utf-8")
        self.add_nick = kwargs.get("add_nick", False)

        if any(u(' ') in arg for arg in self.args[:-1]):
            raise Error("Space can only appear in the very last arg")
        if any(u('\n') in arg for arg in self.args):
            raise Error("No newline allowed")
Beispiel #13
0
 def escape(data):
     ignore = set()
     start = []
     current_fg = ansi_default_fg
     current_bg = ansi_default_bg
     for i, char in enumerate(data):
         if i in ignore:
             continue
         if char == u('\x0f'):  # reset
             start = []
             yield ansi(0)
         elif char in start and char in revert_char:
             start.remove(char)
             yield ansi(revert_char[char])
         elif char in enable_char:
             start.append(char)
             yield ansi(enable_char[char])
         elif char == u('\x03'):
             i += 1
             m = COLOR_CODE.match(data[i:i + 5])
             colors = []
             if m:
                 fg, has_bg, bg = m.groups()
                 if fg:
                     ignore.update(range(i, i + len(fg)))
                     colors.append(color_map_fg.get(int(fg), current_fg))
                     current_fg = int(fg)
                 if has_bg:
                     ignore.update(range(i + len(fg), i + len(fg) + 1))
                 if bg:
                     ignore.update(
                         range(i + len(fg) + 1, i + len(fg) + 1 + len(bg)))
                     colors.append(color_map_bg.get(int(bg), current_bg))
                     current_bg = int(bg)
             if char in start:
                 start.remove(char)
             if colors:
                 start.append(char)
                 yield ansi(*colors)
             else:
                 yield ansi(ansi_default_fg, ansi_default_bg)
         #elif char == u('\x04'):
         #    if char[i + 1:i + 6].isdigit():
         #        ignore.update(range(i, i + 6))
         #    # TODO: parse hex representation
         #elif char == u('\x11'):  # monospace
         #    start.append(char)
         else:
             yield char
     if start and reset:
         yield ansi(0)
Beispiel #14
0
 def escape(data):
     ignore = set()
     start = []
     current_fg = ansi_default_fg
     current_bg = ansi_default_bg
     for i, char in enumerate(data):
         if i in ignore:
             continue
         if char == u('\x0f'):  # reset
             start = []
             yield ansi(0)
         elif char in start and char in revert_char:
             start.remove(char)
             yield ansi(revert_char[char])
         elif char in enable_char:
             start.append(char)
             yield ansi(enable_char[char])
         elif char == u('\x03'):
             i += 1
             m = COLOR_CODE.match(data[i:i + 5])
             colors = []
             if m:
                 fg, has_bg, bg = m.groups()
                 if fg:
                     ignore.update(range(i, i + len(fg)))
                     colors.append(color_map_fg.get(int(fg), current_fg))
                     current_fg = int(fg)
                 if has_bg:
                     ignore.update(range(i + len(fg), i + len(fg) + 1))
                 if bg:
                     ignore.update(range(i + len(fg) + 1, i + len(fg) + 1 + len(bg)))
                     colors.append(color_map_bg.get(int(bg), current_bg))
                     current_bg = int(bg)
             if char in start:
                 start.remove(char)
             if colors:
                 start.append(char)
                 yield ansi(*colors)
             else:
                 yield ansi(ansi_default_fg, ansi_default_bg)
         #elif char == u('\x04'):
         #    if char[i + 1:i + 6].isdigit():
         #        ignore.update(range(i, i + 6))
         #    # TODO: parse hex representation
         #elif char == u('\x11'):  # monospace
         #    start.append(char)
         else:
             yield char
     if start and reset:
         yield ansi(0)
Beispiel #15
0
    def __unicode__(self):
        args = self.args[:]
        if any(u(' ') in arg for arg in args[:-1]):
            raise Error("Space can only appear in the very last arg")
        if any(u('\n') in arg for arg in args):
            raise Error("No newline allowed")

        if args and u(" ") in args[-1] and not args[-1].startswith(u(":")):
            args[-1] = u(":{0:s}").format(args[-1])

        return u("{prefix:s}{command:s} {args:s}\r\n").format(
            prefix=(u(":{0:s} ").format(self.prefix)
                    if self.prefix is not None else u("")),
            command=text_type(self.command),
            args=u(" ").join(args))
Beispiel #16
0
def strip(s, color=False):
    """strip(s, color=False) -> str

    Strips the : from the start of a string
    and optionally also strips all colors if
    color is True.

    :param s str: string to process
    :param color bool: whether to strip colors

    :returns str: returns processes string
    """

    if len(s) > 0:
        if s[0] == u(":"):
            s = s[1:]
    if color:
        s = s.replace(u("\x01"), u(""))
        s = s.replace(u("\x02"), u(""))
    return s
Beispiel #17
0
def strip(s, color=False):
    """strip(s, color=False) -> str

    Strips the : from the start of a string
    and optionally also strips all colors if
    color is True.

    :param s str: string to process
    :param color bool: whether to strip colors

    :returns str: returns processes string
    """

    if len(s) > 0:
        if s[0] == u(":"):
            s = s[1:]
    if color:
        s = s.replace(u("\x01"), u(""))
        s = s.replace(u("\x02"), u(""))
    return s
Beispiel #18
0
    def __init__(self, command, *args, **kwargs):
        for arg in args[:-1]:
            if u(" ") in arg:
                raise Error("Space can only appear in the very last arg")

        self.command = command
        self.args = list(filter(lambda x: x is not None, list(args)))
        self.prefix = text_type(kwargs["prefix"]) if "prefix" in kwargs else None

        self.encoding = kwargs.get("encoding", "utf-8")
        self.add_nick = kwargs.get("add_nick", False)
Beispiel #19
0
    def __init__(self, command, *args, **kwargs):
        for arg in args[:-1]:
            if u(" ") in arg:
                raise Error("Space can only appear in the very last arg")

        self.command = command
        self.args = list(filter(lambda x: x is not None, list(args)))
        self.prefix = text_type(kwargs["prefix"]) if "prefix" in kwargs else None

        self.encoding = kwargs.get("encoding", "utf-8")
        self.add_nick = kwargs.get("add_nick", False)
Beispiel #20
0
    def __unicode__(self):
        args = self.args[:]
        for arg in args[:-1]:
            if arg is not None and u(" ") in arg:
                raise Error("Space can only appear in the very last arg")

        if len(args) > 0 and u(" ") in args[-1] and args[-1][0] != u(":"):
            args[-1] = u(":{0:s}").format(args[-1])

        return u("{prefix:s}{command:s} {args:s}\r\n").format(
            prefix=(u(":{0:s} ").format(self.prefix)
                    if self.prefix is not None else u("")),
            command=text_type(self.command),
            args=u(" ").join(args))
Beispiel #21
0
    def __unicode__(self):
        self._check_args()
        args = self.args[:]

        if args and u(" ") in args[-1] and not args[-1].startswith(u(":")):
            args[-1] = u(":{0:s}").format(args[-1])

        return u("{prefix:s}{command:s} {args:s}\r\n").format(
            prefix=(u(":{0:s} ").format(self.prefix)
                    if self.prefix is not None else u("")),
            command=text_type(self.command),
            args=u(" ").join(args))
Beispiel #22
0
    def __unicode__(self):
        args = self.args[:]
        if any(u(' ') in arg for arg in args[:-1]):
            raise Error("Space can only appear in the very last arg")
        if any(u('\n') in arg for arg in args):
            raise Error("No newline allowed")

        if args and u(" ") in args[-1] and not args[-1].startswith(u(":")):
            args[-1] = u(":{0:s}").format(args[-1])

        return u("{prefix:s}{command:s} {args:s}\r\n").format(
            prefix=(
                u(":{0:s} ").format(self.prefix)
                if self.prefix is not None
                else u("")
            ),
            command=text_type(self.command),
            args=u(" ").join(args)
        )
Beispiel #23
0
    def __unicode__(self):
        args = self.args[:]
        for arg in args[:-1]:
            if arg is not None and u(" ") in arg:
                raise Error("Space can only appear in the very last arg")

        if len(args) > 0 and u(" ") in args[-1] and args[-1][0] != u(":"):
            args[-1] = u(":{0:s}").format(args[-1])

        return u("{prefix:s}{command:s} {args:s}\r\n").format(
            prefix=(
                u(":{0:s} ").format(self.prefix)
                if self.prefix is not None
                else u("")
            ),
            command=text_type(self.command),
            args=u(" ").join(args)
        )
Beispiel #24
0
def RPL_ISUPPORT(features):
    return _M(u("005"), *(features + (u("are supported by this server"), )))
Beispiel #25
0
def RPL_CREATED(date):
    return _M(u("003"), u("This server was created {0}").format(date))
Beispiel #26
0
def irc_color_to_ansi(data, reset=True):
    """Maps IRC color codes to ANSI terminal escape sequences"""
    def ansi(*seq):
        return u("\33[{}m").format(
            u(";").join(u("{:02}").format(x) for x in seq if x))

    ansi_default_fg = 39
    ansi_default_bg = 49
    color_map_fg = {
        0: 37,
        1: 30,
        2: 34,
        3: 32,
        4: 31,
        5: 36,
        6: 35,
        7: 33,
        8: 93,
        9: 92,
        10: 36,
        11: 96,
        12: 94,
        13: 95,
        14: 90,
        15: 37,
        16: 52,
        17: 94,
        18: 100,
        19: 58,
        20: 22,
        21: 29,
        22: 23,
        23: 24,
        24: 17,
        25: 54,
        26: 53,
        27: 89,
        28: 88,
        29: 130,
        30: 142,
        31: 64,
        32: 28,
        33: 35,
        34: 30,
        35: 25,
        36: 18,
        37: 91,
        38: 90,
        39: 125,
        40: 124,
        41: 166,
        42: 184,
        43: 106,
        44: 34,
        45: 49,
        46: 37,
        47: 33,
        48: 19,
        49: 129,
        50: 127,
        51: 161,
        52: 196,
        53: 208,
        54: 226,
        55: 154,
        56: 46,
        57: 86,
        58: 51,
        59: 75,
        60: 21,
        61: 171,
        62: 201,
        63: 198,
        64: 203,
        65: 215,
        66: 227,
        67: 191,
        68: 83,
        69: 122,
        70: 87,
        71: 111,
        72: 63,
        73: 177,
        74: 207,
        75: 205,
        76: 217,
        77: 223,
        78: 229,
        79: 193,
        80: 157,
        81: 158,
        82: 159,
        83: 153,
        84: 147,
        85: 183,
        86: 219,
        87: 212,
        88: 16,
        89: 233,
        90: 235,
        91: 237,
        92: 239,
        93: 241,
        94: 244,
        95: 247,
        96: 250,
        97: 254,
        98: 231,
        99: ansi_default_fg
    }
    color_map_bg = {
        0: 47,
        1: 40,
        2: 44,
        3: 42,
        4: 41,
        5: 46,
        6: 45,
        7: 43,
        8: 103,
        10: 46,
        14: 97,
        15: 47,
        99: ansi_default_bg
    }

    enable_char = {
        u('\x16'): 1,
        u('\x1d'): 3,
        u('\x1e'): 9,
        u('\x1f'): 4,
        u('\x16'): 7
    }
    revert_char = {
        u('\x02'): 22,
        u('\x1d'): 23,
        u('\x1f'): 24,
        u('\x16'): 27,
        u('\x1e'): 29
    }

    def escape(data):
        ignore = set()
        start = []
        current_fg = ansi_default_fg
        current_bg = ansi_default_bg
        for i, char in enumerate(data):
            if i in ignore:
                continue
            if char == u('\x0f'):  # reset
                start = []
                yield ansi(0)
            elif char in start and char in revert_char:
                start.remove(char)
                yield ansi(revert_char[char])
            elif char in enable_char:
                start.append(char)
                yield ansi(enable_char[char])
            elif char == u('\x03'):
                i += 1
                m = COLOR_CODE.match(data[i:i + 5])
                colors = []
                if m:
                    fg, has_bg, bg = m.groups()
                    if fg:
                        ignore.update(range(i, i + len(fg)))
                        colors.append(color_map_fg.get(int(fg), current_fg))
                        current_fg = int(fg)
                    if has_bg:
                        ignore.update(range(i + len(fg), i + len(fg) + 1))
                    if bg:
                        ignore.update(
                            range(i + len(fg) + 1, i + len(fg) + 1 + len(bg)))
                        colors.append(color_map_bg.get(int(bg), current_bg))
                        current_bg = int(bg)
                if char in start:
                    start.remove(char)
                if colors:
                    start.append(char)
                    yield ansi(*colors)
                else:
                    yield ansi(ansi_default_fg, ansi_default_bg)
            #elif char == u('\x04'):
            #    if char[i + 1:i + 6].isdigit():
            #        ignore.update(range(i, i + 6))
            #    # TODO: parse hex representation
            #elif char == u('\x11'):  # monospace
            #    start.append(char)
            else:
                yield char
        if start and reset:
            yield ansi(0)

    return u("").join(escape(data))
Beispiel #27
0
def strip(s, color=False):
    """strip(s, color=False) -> str

    Strips the : from the start of a string
    and optionally also strips all colors if
    color is True.

    :param s str: string to process
    :param color bool: whether to strip colors

    :returns str: returns processes string
    """

    if len(s) > 0:
        if s[0] == u(":"):
            s = s[1:]
    if color:
        s = s.replace(u("\x01"), u(""))
        s = s.replace(u("\x02"), u(""))  # bold
        s = s.replace(u("\x1d"), u(""))  # italics
        s = s.replace(u("\x1f"), u(""))  # underline
        s = s.replace(u("\x1e"), u(""))  # strikethrough
        s = s.replace(u("\x11"), u(""))  # monospace
        s = s.replace(u("\x16"), u(""))  # reverse color
        s = COLOR.sub(u(""), s)  # color codes
        s = s.replace(u("\x03"), u(""))  # color
        s = s.replace(u("\x0f"), u(""))  # reset
    return s
Beispiel #28
0
def RPL_LUSERCHANNELS(nchannels):
    return _M(u("254"), u("{0}").format(nchannels), u("channels formed"))
Beispiel #29
0
def RPL_AWAY(nick, message):
    return _M(u("301"), nick, u(":{0}").format(message))
Beispiel #30
0
def RPL_LUSEROP(noperators):
    return _M(u("252"), u("{0}").format(noperators), u("operator(s) online"))
Beispiel #31
0
def RPL_LUSERME(nclients, nservers):
    return _M(
        u("255"),
        u("I have {0} clients and {1} servers".format(nclients, nservers)))
Beispiel #32
0
def ERR_USERSDONTMATCH():
    return _M(u("502"), u("Cannot change mode for other users"))
Beispiel #33
0
def PART(channel, nick, reason=None, prefix=None):
    return Message(u("PART"), channel, nick, reason, prefix=prefix)
Beispiel #34
0
def ERR_NOOPERHOST():
    return _M(u("491"), u("No O-lines for your host"))
Beispiel #35
0
def ERR_NOPRIVILEGES():
    return _M(u("481"), u("Permission Denied- You're not an IRC operator"))
Beispiel #36
0
def RPL_LUSERUNKOWN(nunknown):
    return _M(u("253"), u("{0}").format(nunknown), u("unknown connection(s)"))
Beispiel #37
0
 def __unicode__(self):
     return u(self.__str__())
Beispiel #38
0
def PONG(server, text):
    return Message(u("PONG"), server, u(":{0}").format(text))
Beispiel #39
0
def PONG(server, text):
    return Message(u("PONG"), server, u(":{0}").format(text))
Beispiel #40
0
def TOPIC(channel, topic, prefix=None):
    return Message(u("TOPIC"), channel, topic, prefix=prefix)
Beispiel #41
0
def RPL_LUSERUNKOWN(nunknown):
    return _M(u("253"), u("{0}").format(nunknown), u("unknown connection(s)"))
Beispiel #42
0
def RPL_WELCOME(network):
    return _M(u("001"), u("Welcome to the {0} IRC Network").format(network))
Beispiel #43
0
def RPL_LUSERME(nclients, nservers):
    return _M(u("255"), u("I have {0} clients and {1} servers".format(nclients, nservers)))
Beispiel #44
0
def RPL_YOURHOST(host, version):
    return _M(u("002"), u("Your host is {0} running {1}").format(host, version))
Beispiel #45
0
 def __unicode__(self):
     return u(self.__str__())
Beispiel #46
0
def RPL_CREATED(date):
    return _M(u("003"), u("This server was created {0}").format(date))
Beispiel #47
0
 def ansi(*seq):
     return u("\33[{}m").format(
         u(";").join(u("{:02}").format(x) for x in seq if x))
Beispiel #48
0
def RPL_MYINFO(server, version, umodes, chmodes):
    return _M(u("004"), server, version, umodes, chmodes)
Beispiel #49
0
def RPL_UMODEIS(modes):
    return _M(u("221"), modes)
Beispiel #50
0
def RPL_YOURHOST(host, version):
    return _M(u("002"),
              u("Your host is {0} running {1}").format(host, version))
Beispiel #51
0
def RPL_MYINFO(server, version, umodes, chmodes):
    return _M(u("004"), server, version, umodes, chmodes)
Beispiel #52
0
def TOPIC(channel, topic, prefix=None):
    return Message(u("TOPIC"), channel, topic, prefix=prefix)
Beispiel #53
0
def RPL_ISUPPORT(features):
    return _M(u("005"), *(features + (u("are supported by this server"),)))
Beispiel #54
0
def RPL_LUSERCHANNELS(nchannels):
    return _M(u("254"), u("{0}").format(nchannels), u("channels formed"))
Beispiel #55
0
def RPL_WELCOME(network):
    return _M(u("001"), u("Welcome to the {0} IRC Network").format(network))
Beispiel #56
0
def RPL_UMODEIS(modes):
    return _M(u("221"), modes)
Beispiel #57
0
    (INVITE("test", "#test"), b"INVITE test #test\r\n"),
    (NAMES(), b"NAMES\r\n"),
    (NAMES("#test"), b"NAMES #test\r\n"),
    (AWAY("I am away."), b"AWAY :I am away.\r\n"),
    (WHOIS("somenick"), b"WHOIS :somenick\r\n"),
])
def test_commands(event, data):
    message = event.args[0]
    return bytes(message) == data


@pytest.mark.parametrize("data,event", [
    (b":localhost NOTICE * :*** Looking up your hostname...\r\n",
     Event.create(
         "notice",
         (u("localhost"), None, None),
         u("*"),
         u("*** Looking up your hostname..."),
     )),
])
def test_responses(app, data, event):
    app.reset()
    app.fire(read(data))
    while len(app):
        app.flush()

    e = app.events[-1]

    assert event.name == e.name
    assert event.args == e.args
    assert event.kwargs == e.kwargs
Beispiel #58
0
def RPL_LUSERCLIENT(nusers, nservices, nservers):
    return _M(
        u("251"),
        u("There are {0} users and {1} services on {2} servers").format(
            nusers, nservices, nservers))
Beispiel #59
0
def PING(server):
    return Message(u("PING"), u(":{0}").format(server))
Beispiel #60
0
def RPL_LUSEROP(noperators):
    return _M(u("252"), u("{0}").format(noperators), u("operator(s) online"))