#!/usr/bin/python3 import re, sys def parse(line): #-> [nick, user, host], command, arguments prefix, params = b"", [] command, arguments = None, [] nick, user, host = None, None, None line = line.rstrip(b"\r\n") # handle prefix: if line.startswith(b":"): prefix, line = line.split(b" ", 1) # handle command and arguments: while b" " in line and not line.startswith(b":"): word, line = line.split(b" ", 1) params += [word] # handle final parameter: params += [line.removeprefix(b":")] command, *arguments = params # note: command may also be a numeric reply if b"!" in prefix and b"@" in prefix: nick, rest = prefix.removeprefix(b":").split(b"!", 1) user, host = rest.split(b"@", 1) elif prefix: # server host = prefix.removeprefix(b":") return [nick, user, host], command, arguments DIM = b"\033[0;2m" BOLD = b"\033[0;1m" RESET = b"\033[0m" REV = b"\033[0;7m" def say(*args): sys.stdout.buffer.write(b"".join(args)+b"\n") sys.stdout.buffer.flush() def sanitize(s): # removes control characters so malicious actors can't mess up our terminal # with escape sequences. this also removes formatting codes. return re.sub(rb"[\001-\011\013\014\016-\037\177]", b"", s) myself = None for line in sys.stdin.buffer: line = sanitize(line) [nick, user, host], command, arguments = parse(line) if command in (b"PRIVMSG", b"NOTICE") and len(arguments) == 2 and nick: chan, msg = arguments nick_start = len(b":") nick_end = nick_start+len(nick) cmd_start = nick_end+len(b"!")+len(user)+len(b"@")+len(host)+len(b" ") cmd_end = cmd_start+len(command) chan_start = cmd_end+len(b" ") chan_end = chan_start+len(chan) msg_start = chan_end+len(b" ") msg_end = msg_start+len(msg) if line[msg_start] == ord(':'): msg_start +=1 msg_end +=1 hi_start, hi_end = msg_start, msg_start if m := re.search(rb"\b%s\b" % re.escape(myself), msg): hi_start = msg_start + m.start(0) hi_end = msg_start + m.end(0) say( DIM, line[:nick_start], BOLD, line[nick_start:nick_end], DIM, line[nick_end:chan_start], BOLD, line[chan_start:chan_end], DIM, line[chan_end:msg_start], RESET, line[msg_start:hi_start], REV, line[hi_start:hi_end], RESET, line[hi_end:msg_end], REV, line[msg_end:].rstrip(b"\r\n"), RESET) elif command in (b"PING", b"PONG"): pass # hide else: if command == b"001" and arguments: myself = arguments[0] # store own username for later highlighting it say(DIM, line.rstrip(b"\r\n"), RESET)