diff options
Diffstat (limited to 'quarg/quassel/formatter.py')
-rw-r--r-- | quarg/quassel/formatter.py | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/quarg/quassel/formatter.py b/quarg/quassel/formatter.py new file mode 100644 index 0000000..1297288 --- /dev/null +++ b/quarg/quassel/formatter.py @@ -0,0 +1,139 @@ +import datetime + +# from functools import partial +from typing import NamedTuple +from quarg.quassel.types import MessageType + +class User(NamedTuple): + nick: str + host: str + prefix: str + + @classmethod + def from_sender(cls, sender, prefixes=''): + nick, *host = sender.split('!', 1) + prefix = prefixes[0] if prefixes else '' + return cls(nick, host[0] if host else '', prefix) + + def __repr__(self): + return f'{self.prefix}{self.nick}' + +class Message(NamedTuple): + type: MessageType + time: datetime.datetime + buffer: str + user: User + message: str + + @classmethod + def from_backlog(cls, backlog): + return cls(MessageType(backlog.type), backlog.time, backlog.buffer.buffername, + User.from_sender(backlog.sender.sender, backlog.senderprefixes), backlog.message) + +def format_from(backlog_row): + message = Message.from_backlog(backlog_row) + formatter = FORMATTERS[message.type] + timestamp = message.time.isoformat(sep=' ', timespec='seconds') + + return f'{timestamp}\t{message.buffer}\t{formatter(message)}' + +def format_privmsg(msg): + return f'<{msg.user}> {msg.message}' + +def format_notice(msg): + return f'[{msg.user}] {msg.message}' + +def format_action(msg): + return f'-*- {msg.user} {msg.message}' + +def format_nick(msg): + return f'<-> {msg.user} is now known as {msg.message}' + +def format_mode(msg): + return f'*** Mode {msg.message} by {msg.user}' + +def format_join(msg): + return f'--> {msg.user} ({msg.user.host}) has joined {msg.buffer}' + +def format_part(msg): + if msg.message: + return f'<-- {msg.user} has left {msg.buffer} ({msg.message})' + + return f'<-- {msg.user} has left {msg.buffer}' + +def format_quit(msg): + if msg.message: + return f'<-- {msg.user} has quit ({msg.message})' + + return f'<-- {msg.user} has quit' + +def format_kick(msg): + target, *kickmsg = msg.message.split(' ', 1) + + if kickmsg: + return f'<-* {msg.user} has kicked {target} from {msg.buffer} ({kickmsg[0]})' + + return f'<-* {msg.user} has kicked {target} from {msg.buffer}' + +def format_kill(msg): + # pylint: disable=line-too-long + + # As of 2021-04-24 not even Quassel implements printing this message [1]. + # They do have a symbol [2] for it, however, so use that along with the message + # [1] https://github.com/quassel/quassel/blob/285215315e6f2420724532323a4b1bccae156cb1/src/uisupport/uistyle.cpp#L950 + # [2] https://github.com/quassel/quassel/blob/285215315e6f2420724532323a4b1bccae156cb1/src/uisupport/uistyle.cpp#L1079-L1080 + return f'<-x {msg.message}' + +def format_generic(msg): + return f'* {msg.message}' + +def parse_netsplit(splitmsg): + # splitmsg contains user!host separated by #:# ... + elements = splitmsg.split('#:#') + + # ... however, the last element contains the split servers instead + servers = elements.pop().split(' ', 1) + + # TODO: This takes ages if the netsplit was large + users = [User.from_sender(e) for e in elements] + + return users, servers + +def format_netsplit_join(msg): + users, (srv_left, srv_right) = parse_netsplit(msg.message) + have_joined = ', '.join(user.nick for user in users) + return f'=> Netsplit between {srv_left} and {srv_right} ended. Users joined: {have_joined}' + +def format_netsplit_quit(msg): + users, (srv_left, srv_right) = parse_netsplit(msg.message) + have_quit = ', '.join(user.nick for user in users) + return f'<= Netsplit between {srv_left} and {srv_right}. Users quit: {have_quit}' + +# TODO inline the format strings here and have a wrapper function that gives msg? +# TODO also <string>.format(**msg) + +def format_from_string(string, msg): + return string.format(**msg._asdict()) + +# MessageType.PART: partial(format_from_string, '<-- {user} has left {buffer}'), + +FORMATTERS = { + MessageType.PRIVMSG: format_privmsg, + MessageType.NOTICE: format_notice, + MessageType.ACTION: format_action, + MessageType.NICK: format_nick, + MessageType.MODE: format_mode, + MessageType.JOIN: format_join, + MessageType.PART: format_part, + MessageType.QUIT: format_quit, + MessageType.KICK: format_kick, + MessageType.KILL: format_kill, + MessageType.SERVER: format_generic, + MessageType.INFO: format_generic, + MessageType.ERROR: format_generic, + MessageType.DAYCHANGE: format_generic, + MessageType.TOPIC: format_generic, + MessageType.NETSPLIT_JOIN: format_netsplit_join, + MessageType.NETSPLIT_QUIT: format_netsplit_quit, + MessageType.INVITE: format_generic, +} |