summaryrefslogtreecommitdiff
path: root/miniirc_idc.py
blob: 45d775709319ed2219abd7136ad22189fe9f0e1d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#!/usr/bin/env python3
#
# This is very horrible and quickly written
# But it works
#

import datetime, miniirc, re
assert miniirc.ver >= (1,8,1)


_LEADING_COLON = '' if miniirc.ver[0] > 2 else ':'
_esc_re = re.compile(r'\\(.)|\t')


idc_to_irc = {
    #'MESSAGE': 'PRIVMSG',
    'RPL_LOGIN_GOOD': '001',
}


class IDC(miniirc.IRC):
    def idc_message_parser(self, msg):
        args = _esc_re.sub(lambda m: m.group(1) or '\udeff', msg).split('\udeff')

        command = args.pop(0).upper()
        tags = {}
        if command == 'PRIVMSG':
            dt = datetime.datetime.utcfromtimestamp(float(args[0]))
            tags['time'] = dt.isoformat() + 'Z'
            hostmask = (args[1], args[1], f'idc/{args[1]}')
            args = [self.current_nick, args[2]]
        else:
            hostmask = ('', '', '')

        if args and _LEADING_COLON:
            args[-1] = _LEADING_COLON + args[-1]
        return idc_to_irc.get(command, command), hostmask, tags, args

    # Send raw messages
    def idc_send(self, *args):
        line = '\t'.join(arg.replace('\\', '\\\\').replace('\t', '\\\t')
                         for arg in args)
        super().quote(line, force=True)

    if miniirc.ver < (2, 0, 0):
        @property
        def _sock(self):
            return self.sock

    def quote(self, *msg, force=None, tags=None) -> None:
        cmd, _, tags2, args = miniirc.ircv3_message_parser(' '.join(msg))
        if miniirc.ver[0] < 2 and args and args[-1].startswith(':'):
            args[-1] = args[-1][1:]
        self.send(cmd, *args, force=force, tags=tags or tags2)

    def _get_idc_account(self):
        if isinstance(self.ns_identity, tuple):
            return self.ns_identity
        else:
            return self.ns_identity.split(' ', 1)

    @property
    def current_nick(self):
        return self._get_idc_account()[0]

    def send(self, cmd, *args, force=None, tags=None) -> None:
        cmd = cmd.upper()
        if cmd in ('PRIVMSG', 'NOTICE'):
            target = args[0]
            # TODO: Make miniirc think that SASL worked PMs to NickServ don't
            # have to be blocked.
            if target == 'NickServ':
                return
            self.idc_send('CHANMSG' if target.startswith('#') else 'PRIVMSG',
                          *args)
        elif cmd in ('PING', 'QUIT'):
            self.idc_send(cmd, *args)
        elif cmd == 'USER':
            user, password = self._get_idc_account()
            self.idc_send('USER', user, password)

    # Override the message parser to change the default parser.
    def change_parser(self, parser=None):
        super().change_parser(parser or self.idc_message_parser)