home · contact · privacy
Reformat message expectations code for better readability.
authorChristian Heller <c.heller@plomlompom.de>
Wed, 3 Sep 2025 15:00:36 +0000 (17:00 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Wed, 3 Sep 2025 15:00:36 +0000 (17:00 +0200)
ircplom/msg_parse_expectations.py

index 25dbfac74180a9f0ee78db50ba39797f22e4a0e4..35c3606ab2c2b19d1c8c40bd3e29b8fa0691b1cc 100644 (file)
@@ -18,341 +18,432 @@ _MsgTokGuide = str | MsgTok | tuple[str | MsgTok, str]
 
 
 class _MsgParseExpectation(NamedTuple):
-    source: _MsgTokGuide
     verb: str
+    source: _MsgTokGuide
     params: tuple[_MsgTokGuide, ...] = tuple()
     idx_into_list: int = -1
     bonus_tasks: tuple[str, ...] = tuple()
 
 
-MSG_EXPECTATIONS: list[_MsgParseExpectation] = []
-
-# these we ignore except for confirming/collecting the nickname
-MSG_EXPECTATIONS += [
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '001',  # RPL_WELCOME
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          MsgTok.ANY)),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '002',  # RPL_YOURHOST
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          MsgTok.ANY)),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '003',  # RPL_CREATED
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          MsgTok.ANY)),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '004',  # RPL_MYINFO
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          MsgTok.ANY,
-                          MsgTok.ANY,
-                          MsgTok.ANY,
-                          MsgTok.ANY,
-                          MsgTok.ANY)),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '250',  # RPL_STATSDLINE / RPL_STATSCONN
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          MsgTok.ANY)),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '251',  # RPL_LUSERCLIENT
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          MsgTok.ANY)),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '252',  # RPL_LUSEROP
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          MsgTok.ANY,
-                          MsgTok.ANY)),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '253',  # RPL_LUSERUNKNOWN
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          MsgTok.ANY,
-                          MsgTok.ANY)),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '254',  # RPL_LUSERCHANNELS
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          MsgTok.ANY,
-                          MsgTok.ANY)),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '255',  # RPL_LUSERME
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          MsgTok.ANY)),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '265',  # RPL_LOCALUSERS
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          MsgTok.ANY)),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '265',  # RPL_LOCALUSERS
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          MsgTok.ANY,
-                          MsgTok.ANY,
-                          MsgTok.ANY)),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '266',  # RPL_GLOBALUSERS
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          MsgTok.ANY)),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '266',  # RPL_GLOBALUSERS
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          MsgTok.ANY,
-                          MsgTok.ANY,
-                          MsgTok.ANY)),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '375',  # RPL_MOTDSTART already implied by 1st 372
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          MsgTok.ANY)),
-]
+MSG_EXPECTATIONS: list[_MsgParseExpectation] = [
 
-# various login stuff
-MSG_EXPECTATIONS += [
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '005',  # RPL_ISUPPORT
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          (MsgTok.ANY, ':isupport'),
-                          MsgTok.ANY),  # comment
-                         idx_into_list=1),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '372',  # RPL_MOTD
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          (MsgTok.ANY, ':line'))),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '376',  # RPL_ENDOFMOTD
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          MsgTok.ANY),  # comment
-                         bonus_tasks=('do_db.motd:complete',)),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '396',  # RPL_VISIBLEHOST
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          (MsgTok.SERVER, 'setattr_db.users.me:host'),
-                          MsgTok.ANY)),  # comment
-]
+    # these we ignore except for confirming/collecting the nickname
 
-# SASL
-MSG_EXPECTATIONS += [
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '900',  # RPL_LOGGEDIN
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          (MsgTok.NICK_USER_HOST, 'setattr_db.users.me:nickuserhost'),
-                          (MsgTok.ANY, 'setattr_db:sasl_account'),
-                          MsgTok.ANY)),  # comment
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '903',  # RPL_SASLSUCCESS
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          (MsgTok.ANY, 'setattr_db:sasl_auth_state')),
-                         bonus_tasks=('do_caps:end_negotiation',)),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '904',  # ERR_SASLFAIL
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          (MsgTok.ANY, 'setattr_db:sasl_auth_state')),
-                         bonus_tasks=('do_caps:end_negotiation',)),
-    _MsgParseExpectation(MsgTok.NONE,
-                         'AUTHENTICATE',
-                         ('+',)),
-]
+    _MsgParseExpectation(
+        '001',  # RPL_WELCOME
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         MsgTok.ANY)),
 
-# capability negotation
-MSG_EXPECTATIONS += [
-    _MsgParseExpectation(MsgTok.SERVER,
-                         'CAP',
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          ('NEW', ':subverb'),
-                          (MsgTok.LIST, ':items'))),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         'CAP',
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          ('DEL', ':subverb'),
-                          (MsgTok.LIST, ':items'))),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         'CAP',
-                         ('*',
-                          ('ACK', ':subverb'),
-                          (MsgTok.LIST, ':items'))),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         'CAP',
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          ('ACK', ':subverb'),
-                          (MsgTok.LIST, ':items'))),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         'CAP',
-                         ('*',
-                          ('NAK', ':subverb'),
-                          (MsgTok.LIST, ':items'))),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         'CAP',
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          ('NAK', ':subverb'),
-                          (MsgTok.LIST, ':items'))),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         'CAP',
-                         ('*',
-                          ('LS', ':subverb'),
-                          (MsgTok.LIST, ':items'))),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         'CAP',
-                         ('*',
-                          ('LS', ':subverb'),
-                          ('*', ':tbc'),
-                          (MsgTok.LIST, ':items'))),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         'CAP',
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          ('LS', ':subverb'),
-                          (MsgTok.LIST, ':items'))),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         'CAP',
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          ('LS', ':subverb'),
-                          ('*', ':tbc'),
-                          (MsgTok.LIST, ':items'))),
-
-    _MsgParseExpectation(MsgTok.SERVER,
-                         'CAP',
-                         ('*',
-                          ('LIST', ':subverb'),
-                          (MsgTok.LIST, ':items'))),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         'CAP',
-                         ('*',
-                          ('LIST', ':subverb'),
-                          ('*', ':tbc'),
-                          (MsgTok.LIST, ':items'))),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         'CAP',
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          ('LIST', ':subverb'),
-                          (MsgTok.LIST, ':items'))),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         'CAP',
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          ('LIST', ':subverb'),
-                          ('*', ':tbc'),
-                          (MsgTok.LIST, ':items'))),
-]
+    _MsgParseExpectation(
+        '002',  # RPL_YOURHOST
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         MsgTok.ANY)),
 
-# nickname management
-MSG_EXPECTATIONS += [
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '432',  # ERR_ERRONEOUSNICKNAME
-                         ('*',
-                          MsgTok.NICKNAME,  # no need to re-use the bad one
-                          MsgTok.ANY)),  # comment
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '432',  # ERR_ERRONEOUSNICKNAME
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          MsgTok.NICKNAME,  # no need to re-use the bad one
-                          MsgTok.ANY)),  # comment
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '433',  # ERR_NICKNAMEINUSE
-                         ('*',
-                          (MsgTok.NICKNAME, ':used'),
-                          MsgTok.ANY)),  # comment
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '433',  # ERR_NICKNAMEINUSE
-                         (MsgTok.NICKNAME,  # we rather go for incrementation
-                          (MsgTok.NICKNAME, ':used'),
-                          MsgTok.ANY)),  # comment
-    _MsgParseExpectation((MsgTok.NICK_USER_HOST, ':named'),
-                         'NICK',
-                         ((MsgTok.NICKNAME, ':nick'),)),
-]
+    _MsgParseExpectation(
+        '003',  # RPL_CREATED
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         MsgTok.ANY)),
 
-# joining/leaving
-MSG_EXPECTATIONS += [
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '332',  # RPL_TOPIC
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          (MsgTok.CHANNEL, ':CHAN'),
-                          (MsgTok.ANY, 'setattr_db.channels.CHAN.topic:what'))),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '333',  # RPL_TOPICWHOTIME
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          (MsgTok.CHANNEL, ':CHAN'),
-                          (MsgTok.NICK_USER_HOST, 'setattr_db.channels.CHAN.topic:who'),
-                          (MsgTok.ANY, ':timestamp'))),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '353',  # RPL_NAMREPLY
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          '@',
-                          (MsgTok.CHANNEL, ':channel'),
-                          (MsgTok.LIST, ':names'))),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '353',  # RPL_NAMREPLY
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          '=',
-                          (MsgTok.CHANNEL, ':channel'),
-                          (MsgTok.LIST, ':names'))),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '366',  # RPL_ENDOFNAMES
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          (MsgTok.CHANNEL, ':CHAN'),
-                          MsgTok.ANY),  # comment
-                         bonus_tasks=('do_db.channels.CHAN.user_ids:complete',)),
-    _MsgParseExpectation((MsgTok.NICK_USER_HOST, ':joiner'),
-                         'JOIN',
-                         ((MsgTok.CHANNEL, ':channel'),)),
-    _MsgParseExpectation((MsgTok.NICK_USER_HOST, ':parter'),
-                         'PART',
-                         ((MsgTok.CHANNEL, ':channel'),)),
-    _MsgParseExpectation((MsgTok.NICK_USER_HOST, ':parter'),
-                         'PART',
-                         ((MsgTok.CHANNEL, ':channel'),
-                          (MsgTok.ANY, ':message'))),
-    _MsgParseExpectation((MsgTok.NICK_USER_HOST, 'setattr_db.channels.CHAN.topic:who'),
-                         'TOPIC',
-                         ((MsgTok.CHANNEL, ':CHAN'),
-                          (MsgTok.ANY, 'setattr_db.channels.CHAN.topic:what'))),
-]
+    _MsgParseExpectation(
+        '004',  # RPL_MYINFO
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         MsgTok.ANY,
+         MsgTok.ANY,
+         MsgTok.ANY,
+         MsgTok.ANY,
+         MsgTok.ANY)),
 
-# messaging
-MSG_EXPECTATIONS += [
-    _MsgParseExpectation(MsgTok.SERVER,
-                         '401',  # ERR_NOSUCKNICK
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          (MsgTok.NICKNAME, ':target'),
-                          MsgTok.ANY)),  # comment
-    _MsgParseExpectation(MsgTok.SERVER,
-                         'NOTICE',
-                         ('*',
-                          (MsgTok.ANY, ':message'))),
-    _MsgParseExpectation(MsgTok.SERVER,
-                         'NOTICE',
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          (MsgTok.ANY, ':message'))),
-    _MsgParseExpectation((MsgTok.NICK_USER_HOST, 'set_user:sender'),
-                         'NOTICE',
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          (MsgTok.ANY, ':message'))),
-    _MsgParseExpectation((MsgTok.NICK_USER_HOST, 'set_user:sender'),
-                         'NOTICE',
-                         ((MsgTok.CHANNEL, ':channel'),
-                          (MsgTok.ANY, ':message'))),
-    _MsgParseExpectation((MsgTok.NICK_USER_HOST, 'set_user:sender'),
-                         'PRIVMSG',
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          (MsgTok.ANY, ':message'))),
-    _MsgParseExpectation((MsgTok.NICK_USER_HOST, 'set_user:sender'),
-                         'PRIVMSG',
-                         ((MsgTok.CHANNEL, ':channel'),
-                          (MsgTok.ANY, ':message'))),
-]
+    _MsgParseExpectation(
+        '250',  # RPL_STATSDLINE / RPL_STATSCONN
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         MsgTok.ANY)),
+
+    _MsgParseExpectation(
+        '251',  # RPL_LUSERCLIENT
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         MsgTok.ANY)),
+
+    _MsgParseExpectation(
+        '252',  # RPL_LUSEROP
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         MsgTok.ANY,
+         MsgTok.ANY)),
+
+    _MsgParseExpectation(
+        '253',  # RPL_LUSERUNKNOWN
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         MsgTok.ANY,
+         MsgTok.ANY)),
+
+    _MsgParseExpectation(
+        '254',  # RPL_LUSERCHANNELS
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         MsgTok.ANY,
+         MsgTok.ANY)),
+
+    _MsgParseExpectation(
+        '255',  # RPL_LUSERME
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         MsgTok.ANY)),
+
+    _MsgParseExpectation(
+        '265',  # RPL_LOCALUSERS
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         MsgTok.ANY)),
+    _MsgParseExpectation(
+        '265',  # RPL_LOCALUSERS
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         MsgTok.ANY,
+         MsgTok.ANY,
+         MsgTok.ANY)),
+
+    _MsgParseExpectation(
+        '266',  # RPL_GLOBALUSERS
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         MsgTok.ANY)),
+    _MsgParseExpectation(
+        '266',  # RPL_GLOBALUSERS
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         MsgTok.ANY,
+         MsgTok.ANY,
+         MsgTok.ANY)),
+
+    _MsgParseExpectation(
+        '375',  # RPL_MOTDSTART already implied by 1st 372
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         MsgTok.ANY)),
+
+    # various login stuff
+
+    _MsgParseExpectation(
+        '005',  # RPL_ISUPPORT
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         (MsgTok.ANY, ':isupport'),
+         MsgTok.ANY),  # comment
+        idx_into_list=1),
+
+    _MsgParseExpectation(
+        '372',  # RPL_MOTD
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         (MsgTok.ANY, ':line'))),
+
+    _MsgParseExpectation(
+        '376',  # RPL_ENDOFMOTD
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         MsgTok.ANY),  # comment
+        bonus_tasks=('do_db.motd:complete',)),
+
+    _MsgParseExpectation(
+        '396',  # RPL_VISIBLEHOST
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         (MsgTok.SERVER, 'setattr_db.users.me:host'),
+         MsgTok.ANY)),  # comment
+
+    # SASL
+
+    _MsgParseExpectation(
+        '900',  # RPL_LOGGEDIN
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         (MsgTok.NICK_USER_HOST, 'setattr_db.users.me:nickuserhost'),
+         (MsgTok.ANY, 'setattr_db:sasl_account'),
+         MsgTok.ANY)),  # comment
+
+    _MsgParseExpectation(
+        '903',  # RPL_SASLSUCCESS
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         (MsgTok.ANY, 'setattr_db:sasl_auth_state')),
+        bonus_tasks=('do_caps:end_negotiation',)),
+
+    _MsgParseExpectation(
+        '904',  # ERR_SASLFAIL
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         (MsgTok.ANY, 'setattr_db:sasl_auth_state')),
+        bonus_tasks=('do_caps:end_negotiation',)),
+
+    _MsgParseExpectation(
+        'AUTHENTICATE',
+        MsgTok.NONE,
+        ('+',)),
+
+    # capability negotation
+
+    _MsgParseExpectation(
+        'CAP',
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         ('NEW', ':subverb'),
+         (MsgTok.LIST, ':items'))),
+
+    _MsgParseExpectation(
+        'CAP',
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         ('DEL', ':subverb'),
+         (MsgTok.LIST, ':items'))),
+
+    _MsgParseExpectation(
+        'CAP',
+        MsgTok.SERVER,
+        ('*',
+         ('ACK', ':subverb'),
+         (MsgTok.LIST, ':items'))),
+    _MsgParseExpectation(
+        'CAP',
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         ('ACK', ':subverb'),
+         (MsgTok.LIST, ':items'))),
+
+    _MsgParseExpectation(
+        'CAP',
+        MsgTok.SERVER,
+        ('*',
+         ('NAK', ':subverb'),
+         (MsgTok.LIST, ':items'))),
+    _MsgParseExpectation(
+        'CAP',
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         ('NAK', ':subverb'),
+         (MsgTok.LIST, ':items'))),
+
+    _MsgParseExpectation(
+        'CAP',
+        MsgTok.SERVER,
+        ('*',
+         ('LS', ':subverb'),
+         (MsgTok.LIST, ':items'))),
+    _MsgParseExpectation(
+        'CAP',
+        MsgTok.SERVER,
+        ('*',
+         ('LS', ':subverb'),
+         ('*', ':tbc'),
+         (MsgTok.LIST, ':items'))),
+    _MsgParseExpectation(
+        'CAP',
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         ('LS', ':subverb'),
+         (MsgTok.LIST, ':items'))),
+    _MsgParseExpectation(
+        'CAP',
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         ('LS', ':subverb'),
+         ('*', ':tbc'),
+         (MsgTok.LIST, ':items'))),
+
+    _MsgParseExpectation(
+        'CAP',
+        MsgTok.SERVER,
+        ('*',
+         ('LIST', ':subverb'),
+         (MsgTok.LIST, ':items'))),
+    _MsgParseExpectation(
+        'CAP',
+        MsgTok.SERVER,
+        ('*',
+         ('LIST', ':subverb'),
+         ('*', ':tbc'),
+         (MsgTok.LIST, ':items'))),
+    _MsgParseExpectation(
+        'CAP',
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         ('LIST', ':subverb'),
+         (MsgTok.LIST, ':items'))),
+    _MsgParseExpectation(
+        'CAP',
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         ('LIST', ':subverb'),
+         ('*', ':tbc'),
+         (MsgTok.LIST, ':items'))),
+
+    # nickname management
+
+    _MsgParseExpectation(
+        '432',  # ERR_ERRONEOUSNICKNAME
+        MsgTok.SERVER,
+        ('*',
+         MsgTok.NICKNAME,  # no need to re-use the bad one
+         MsgTok.ANY)),  # comment
+    _MsgParseExpectation(
+        '432',  # ERR_ERRONEOUSNICKNAME
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         MsgTok.NICKNAME,  # no need to re-use the bad one
+         MsgTok.ANY)),  # comment
+
+    _MsgParseExpectation(
+        '433',  # ERR_NICKNAMEINUSE
+        MsgTok.SERVER,
+        ('*',
+         (MsgTok.NICKNAME, ':used'),
+         MsgTok.ANY)),  # comment
+    _MsgParseExpectation(
+        '433',  # ERR_NICKNAMEINUSE
+        MsgTok.SERVER,
+        (MsgTok.NICKNAME,  # we rather go for incrementation
+         (MsgTok.NICKNAME, ':used'),
+         MsgTok.ANY)),  # comment
+
+    _MsgParseExpectation(
+        'NICK',
+        (MsgTok.NICK_USER_HOST, ':named'),
+        ((MsgTok.NICKNAME, ':nick'),)),
+
+    # joining/leaving
+
+    _MsgParseExpectation(
+        '332',  # RPL_TOPIC
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         (MsgTok.CHANNEL, ':CHAN'),
+         (MsgTok.ANY, 'setattr_db.channels.CHAN.topic:what'))),
+
+    _MsgParseExpectation(
+        '333',  # RPL_TOPICWHOTIME
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         (MsgTok.CHANNEL, ':CHAN'),
+         (MsgTok.NICK_USER_HOST, 'setattr_db.channels.CHAN.topic:who'),
+         (MsgTok.ANY, ':timestamp'))),
+
+    _MsgParseExpectation(
+        '353',  # RPL_NAMREPLY
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         '@',
+         (MsgTok.CHANNEL, ':channel'),
+         (MsgTok.LIST, ':names'))),
+    _MsgParseExpectation(
+        '353',  # RPL_NAMREPLY
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         '=',
+         (MsgTok.CHANNEL, ':channel'),
+         (MsgTok.LIST, ':names'))),
+
+    _MsgParseExpectation(
+        '366',  # RPL_ENDOFNAMES
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         (MsgTok.CHANNEL, ':CHAN'),
+         MsgTok.ANY),  # comment
+        bonus_tasks=('do_db.channels.CHAN.user_ids:complete',)),
+
+    _MsgParseExpectation(
+        'JOIN',
+        (MsgTok.NICK_USER_HOST, ':joiner'),
+        ((MsgTok.CHANNEL, ':channel'),)),
+
+    _MsgParseExpectation(
+        'PART',
+        (MsgTok.NICK_USER_HOST, ':parter'),
+        ((MsgTok.CHANNEL, ':channel'),)),
+    _MsgParseExpectation(
+        'PART',
+        (MsgTok.NICK_USER_HOST, ':parter'),
+        ((MsgTok.CHANNEL, ':channel'),
+         (MsgTok.ANY, ':message'))),
+
+    _MsgParseExpectation(
+        'TOPIC',
+        (MsgTok.NICK_USER_HOST, 'setattr_db.channels.CHAN.topic:who'),
+        ((MsgTok.CHANNEL, ':CHAN'),
+         (MsgTok.ANY, 'setattr_db.channels.CHAN.topic:what'))),
+
+    # messaging
+
+    _MsgParseExpectation(
+        '401',  # ERR_NOSUCKNICK
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         (MsgTok.NICKNAME, ':target'),
+         MsgTok.ANY)),  # comment
+
+    _MsgParseExpectation(
+        'NOTICE',
+        MsgTok.SERVER,
+        ('*',
+         (MsgTok.ANY, ':message'))),
+    _MsgParseExpectation(
+        'NOTICE',
+        MsgTok.SERVER,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         (MsgTok.ANY, ':message'))),
+    _MsgParseExpectation(
+        'NOTICE',
+        (MsgTok.NICK_USER_HOST, 'set_user:sender'),
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         (MsgTok.ANY, ':message'))),
+    _MsgParseExpectation(
+        'NOTICE',
+        (MsgTok.NICK_USER_HOST, 'set_user:sender'),
+        ((MsgTok.CHANNEL, ':channel'),
+         (MsgTok.ANY, ':message'))),
+
+    _MsgParseExpectation(
+        'PRIVMSG',
+        (MsgTok.NICK_USER_HOST, 'set_user:sender'),
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         (MsgTok.ANY, ':message'))),
+    _MsgParseExpectation(
+        'PRIVMSG',
+        (MsgTok.NICK_USER_HOST, 'set_user:sender'),
+        ((MsgTok.CHANNEL, ':channel'),
+         (MsgTok.ANY, ':message'))),
+
+    # misc.
+
+    _MsgParseExpectation(
+        'ERROR',
+        MsgTok.NONE,
+        ((MsgTok.ANY, 'setattr_db:connection_state'),),
+        bonus_tasks=('do_:close',)),
+
+    _MsgParseExpectation(
+        'MODE',
+        (MsgTok.NICK_USER_HOST, 'setattr_db.users.me:nickuserhost'),
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         (MsgTok.ANY, 'setattr_db:user_modes'))),
+    _MsgParseExpectation(
+        'MODE',
+        MsgTok.NICKNAME,
+        ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
+         (MsgTok.ANY, 'setattr_db:user_modes'))),
+
+    _MsgParseExpectation(
+        'PING',
+        MsgTok.NONE,
+        ((MsgTok.ANY, ':reply'),)),
 
-# misc.
-MSG_EXPECTATIONS += [
-    _MsgParseExpectation(MsgTok.NONE,
-                         'ERROR',
-                         ((MsgTok.ANY, 'setattr_db:connection_state'),),
-                         bonus_tasks=('do_:close',)),
-    _MsgParseExpectation((MsgTok.NICK_USER_HOST, 'setattr_db.users.me:nickuserhost'),
-                         'MODE',
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          (MsgTok.ANY, 'setattr_db:user_modes'))),
-    _MsgParseExpectation(MsgTok.NICKNAME,
-                         'MODE',
-                         ((MsgTok.NICKNAME, 'setattr_db.users.me:nick'),
-                          (MsgTok.ANY, 'setattr_db:user_modes'))),
-    _MsgParseExpectation(MsgTok.NONE,
-                         'PING',
-                         ((MsgTok.ANY, ':reply'),)),
-    _MsgParseExpectation((MsgTok.NICK_USER_HOST, ':quitter'),
-                         'QUIT',
-                         ((MsgTok.ANY, ':message'),)),
+    _MsgParseExpectation(
+        'QUIT',
+        (MsgTok.NICK_USER_HOST, ':quitter'),
+        ((MsgTok.ANY, ':message'),)),
 ]