]> git.gir.st - ircpipe.git/blob - contrib/highlight
highlight: keep C1 controls intact
[ircpipe.git] / contrib / highlight
1 #!/usr/bin/python3
2 import re, sys
3
4 def parse(line): #-> [nick, user, host], command, arguments
5 prefix, params = b"", []
6 command, arguments = None, []
7 nick, user, host = None, None, None
8
9 line = line.rstrip(b"\r\n")
10 # handle prefix:
11 if line.startswith(b":"):
12 prefix, line = line.split(b" ", 1)
13 # handle command and arguments:
14 while b" " in line and not line.startswith(b":"):
15 word, line = line.split(b" ", 1)
16 params += [word]
17 # handle final parameter:
18 params += [line.removeprefix(b":")]
19
20 command, *arguments = params # note: command may also be a numeric reply
21
22 if b"!" in prefix and b"@" in prefix:
23 nick, rest = prefix.removeprefix(b":").split(b"!", 1)
24 user, host = rest.split(b"@", 1)
25 elif prefix: # server
26 host = prefix.removeprefix(b":")
27
28 return [nick, user, host], command, arguments
29
30 DIM = b"\033[0;2m"
31 BOLD = b"\033[0;1m"
32 RESET = b"\033[0m"
33 REV = b"\033[0;7m"
34
35 def say(*args):
36 sys.stdout.buffer.write(b"".join(args)+b"\n")
37 sys.stdout.buffer.flush()
38
39 def sanitize(s):
40 # removes control characters so malicious actors can't mess up our terminal
41 # with escape sequences. this also removes formatting codes.
42 return re.sub(rb"[\001-\011\013\014\016-\037\177]", b"", s)
43
44 myself = None
45 for line in sys.stdin.buffer:
46 line = sanitize(line)
47
48 [nick, user, host], command, arguments = parse(line)
49
50 if command in (b"PRIVMSG", b"NOTICE") and len(arguments) == 2 and nick:
51 chan, msg = arguments
52 nick_start = len(b":")
53 nick_end = nick_start+len(nick)
54 cmd_start = nick_end+len(b"!")+len(user)+len(b"@")+len(host)+len(b" ")
55 cmd_end = cmd_start+len(command)
56 chan_start = cmd_end+len(b" ")
57 chan_end = chan_start+len(chan)
58 msg_start = chan_end+len(b" ")
59 msg_end = msg_start+len(msg)
60 if line[msg_start] == ord(':'):
61 msg_start +=1
62 msg_end +=1
63
64 hi_start, hi_end = msg_start, msg_start
65 if m := re.search(rb"\b%s\b" % re.escape(myself), msg):
66 hi_start = msg_start + m.start(0)
67 hi_end = msg_start + m.end(0)
68
69 say(
70 DIM, line[:nick_start],
71 BOLD, line[nick_start:nick_end],
72 DIM, line[nick_end:chan_start],
73 BOLD, line[chan_start:chan_end],
74 DIM, line[chan_end:msg_start],
75 RESET, line[msg_start:hi_start],
76 REV, line[hi_start:hi_end],
77 RESET, line[hi_end:msg_end],
78 REV, line[msg_end:].rstrip(b"\r\n"),
79 RESET)
80 elif command in (b"PING", b"PONG"):
81 pass # hide
82 else:
83 if command == b"001" and arguments:
84 myself = arguments[0] # store own username for later highlighting it
85
86 say(DIM, line.rstrip(b"\r\n"), RESET)
Imprint / Impressum