except AssertionError:
raise ImplementationFail( # pylint: disable=raise-missing-from
f'channel mode setting {modeset} on args: {args}')
- modes_attrs = self.prefixes, self.modes_listy, self.modes_valued, self.modes_toggled
- for attr in modes_attrs:
+ modes_complete = tuple(
+ attr for attr in (self.prefixes, self.modes_listy,
+ self.modes_valued, self.modes_toggled)
+ if attr.completed is not None)
+ for attr in modes_complete:
attr.completed = None
for do_add, char, arg in todos:
if char in modes['A'] + prefix_modes:
getattr(self.modes_toggled,
f'completable_{"add" if do_add else "remove"}'
)(char, False)
- for attr in modes_attrs:
+ for attr in modes_complete:
attr.complete()
'Reply PING with its expected reply.'
self.send('PONG', reply)
+ def ask_chanmodes(self, channel_name: str) -> None:
+ self.send('MODE', channel_name)
+
def handle_msg(self, msg: IrcMessage) -> None:
'Log msg.raw, then process incoming msg into appropriate client steps.'
ret: Optional[dict[str, Any]] = None
# joining/leaving
+ _MsgParseExpectation(
+ '324',
+ _MsgToken.SERVER,
+ ((_MsgToken.NICKNAME, 'setattr_db.users[me]:nick'),
+ (_MsgToken.CHANNEL, ':CHANNEL'),
+ (_MsgToken.ANY, ':modeset'),
+ (_MsgToken.LIST, ':args')),
+ bonus_tasks=('do_db.channels[CHANNEL].set_modes:modeset,args',
+ 'doafter_db.channels[CHANNEL].modes_valued.complete:',
+ 'doafter_db.channels[CHANNEL].modes_toggled.complete:')),
+
+ _MsgParseExpectation(
+ '329', # RPL_CREATIONTIME
+ _MsgToken.SERVER,
+ ((_MsgToken.NICKNAME, 'setattr_db.users[me]:nick'),
+ _MsgToken.CHANNEL,
+ _MsgToken.ANY)),
+
_MsgParseExpectation(
'332', # RPL_TOPIC
_MsgToken.SERVER,
'366', # RPL_ENDOFNAMES
_MsgToken.SERVER,
((_MsgToken.NICKNAME, 'setattr_db.users[me]:nick'),
- (_MsgToken.CHANNEL, ':CHAN'),
+ (_MsgToken.CHANNEL, 'do_ask_chanmodes:CHAN'),
_MsgToken.ANY), # comment
bonus_tasks=('doafter_db.channels[CHAN].prefixes.complete:',
'doafter_db.channels[CHAN].user_ids.complete:')),
insert ./lib/connect-to-usermode
insert ./lib/isupport-set
insert ./lib/join-channel
-# for: join-channel-0-cmd-to-list-residents, join-channel-1-end-of-names
+# for: join-channel-0-cmd-to-list-residents, join-channel-1-0-endofnames-to-prefixes, join-channel-1-1-userids-to-329, join-channel-1-endofnames-to-329
insert ./lib/no-handler
insert ./lib/part-no-msg-other
insert ./lib/privmsg-win
insert servermsglogged [% (MSG)=:foo.bar.baz%353%foo%=%#ch_win3%:+rab%zab]
insert user-set-to range=:1 [(USER_ID)=3 (USER_NICK)=rab]
insert user-set-to range=:1 [(USER_ID)=4 (USER_NICK)=zab]
-insert join-channel-1-end-of-names range=:-3 [(WIN_ID)=3]
+insert join-channel-1-0-endofnames-to-prefixes range=:-1 [(WIN_ID)=3]
log 1 $ channels:#ch_win3:prefixes:o set to: [1]
log 1 $ channels:#ch_win3:prefixes:v set to: [2], [3]
-insert join-channel-1-end-of-names range=-2: [% (WIN_ID)=3 (RESIDENT_IDS)=[1],%[2],%[3],%[4],%[me] (RESIDENT_NICKS)=@baz,%+oof,%+rab,%zab,%foo]
+insert join-channel-1-1-userids-to-329 [% (WIN_ID)=3 (RESIDENT_IDS)=[1],%[2],%[3],%[4],%[me] (RESIDENT_NICKS)=@baz,%+oof,%+rab,%zab,%foo]
# check (presence/absence of) membership prefixes mirrored in message display
insert privmsg-win [% (WIN_ID)=3 (TXT)=foo%foo%foo]
# check user parting loses them prefix even if kept identified by other window
insert join-channel-0-cmd-to-list-residents [% (WIN_ID)=4 (RESIDENT_NAMES)=foo%baz]
-insert join-channel-1-end-of-names [% (WIN_ID)=4 (RESIDENT_IDS)=[1],%[me] (RESIDENT_NICKS)=baz,%foo]
+insert join-channel-1-endofnames-to-329 [% (WIN_ID)=4 (RESIDENT_IDS)=[1],%[me] (RESIDENT_NICKS)=baz,%foo]
insert part-no-msg-other [% (USER_ID)=1 (NICK)=baz (REMAINING_IDS)=[2],%[3],%[4],%[me]]
log 1 $ channels:#ch_win3:prefixes:o set to: [4]
insert servermsglogged [% (MSG)=:baz!~bazbaz@baz.baz%JOIN%:#ch_win3]
# check server setting type-A modes
insert servermsg-mode [% (ARGS)=+l%:foo]
-log 1 $ channels:#ch_win3:modes_listy:l set to: [foo]
+# log 1 $ channels:#ch_win3:modes_listy:l set to: [foo]
insert servermsg-mode [% (ARGS)=+l%:bar]
-log 1 $ channels:#ch_win3:modes_listy:l set to: [bar], [foo]
+# log 1 $ channels:#ch_win3:modes_listy:l set to: [bar], [foo]
insert servermsg-mode [% (ARGS)=+l-l%:baz%foo]
-log 1 $ channels:#ch_win3:modes_listy:l set to: [bar], [baz]
+# log 1 $ channels:#ch_win3:modes_listy:l set to: [bar], [baz]
# check server setting type-B modes
insert servermsg-mode [% (ARGS)=+k%:password]
# check server setting type-C modes
insert servermsg-mode [% (ARGS)=+x%:foo]
log 1 $ channels:#ch_win3:modes_valued:x set to: [foo]
-insert servermsg-mode [% (ARGS)=+xy%:bar%zab]
+insert servermsg-mode [% (ARGS)=+xy%bar%zab]
log 1 $ channels:#ch_win3:modes_valued:x set to: [bar]
log 1 $ channels:#ch_win3:modes_valued:y set to: [zab]
insert servermsg-mode [(ARGS)=-x]
log 1 $ channels:#ch_win3:modes_toggled set to: [B]
insert servermsg-mode [(ARGS)=-B+cb]
log 1 $ channels:#ch_win3:modes_toggled set to: [b], [c]
+
+# check /join into channel with modes already set
+insert join-channel-0-cmd-to-list-residents [(WIN_ID)=5 (RESIDENT_NAMES)=foo]
+insert join-channel-1-endofnames-to-329 range=:-2 [% (WIN_ID)=5 (RESIDENT_IDS)=[me] (RESIDENT_NICKS)=foo %+=%+kxyaBc%foo%bar%baz]
+log 1 $ channels:#ch_win5:modes_valued:k set to: [foo]
+log 1 $ channels:#ch_win5:modes_valued:x set to: [bar]
+log 1 $ channels:#ch_win5:modes_valued:y set to: [baz]
+log 1 $ channels:#ch_win5:modes_toggled set to: [B], [a], [c]
+insert join-channel-1-endofnames-to-329 range=-2: [% (WIN_ID)=5]
insert ./lib/disconnect
# for: disconnect0, disconnect1
insert ./lib/join-channel
-# for: join-channel-0-cmd-to-list-residents, join-channel-0-0-cmd-to-ack, join-channel-0-1-list-residents, join-channel-1-end-of-names
+# for: join-channel-0-cmd-to-list-residents, join-channel-0-0-cmd-to-ack, join-channel-0-1-list-residents, join-channel-1-0-endofnames-to-prefixes, join-channel-1-1-userids-to-329, join-channel-1-endofnames-to-329
insert ./lib/join-empty
insert ./lib/part
# for: part, part-core, part-no-msg, part-no-msg-me, quit
# check /join to, and part from, channel with one other user
insert join-channel-0-cmd-to-list-residents [% (WIN_ID)=3 (RESIDENT_NAMES)=foo%bar]
insert user-set-to range=:1 [(USER_ID)=1 (USER_NICK)=bar]
-insert join-channel-1-end-of-names [% (WIN_ID)=3 (RESIDENT_IDS)=[1],%[me] (RESIDENT_NICKS)=bar,%foo]
+insert join-channel-1-endofnames-to-329 [% (WIN_ID)=3 (RESIDENT_IDS)=[1],%[me] (RESIDENT_NICKS)=bar,%foo]
insert part-no-msg-me [% (WIN_ID)=3 (USERIDS_CLEAR)=set%to:%[1]]
log 1 $ users:1 deleted
insert servermsglogged [% (MSG)=:foo.bar.baz%353%foo%=%#ch_win3%:rab%zab]
insert user-set-to range=:1 [(USER_ID)=4 (USER_NICK)=rab]
insert user-set-to range=:1 [(USER_ID)=5 (USER_NICK)=zab]
-insert join-channel-1-end-of-names [% (WIN_ID)=3 (RESIDENT_IDS)=[2],%[3],%[4],%[5],%[me] (RESIDENT_NICKS)=baz,%oof,%rab,%zab,%foo]
+insert join-channel-1-endofnames-to-329 [% (WIN_ID)=3 (RESIDENT_IDS)=[2],%[3],%[4],%[5],%[me] (RESIDENT_NICKS)=baz,%oof,%rab,%zab,%foo]
# check /join into channel with topic set
> /window 4
insert servermsglogged [% (MSG)=:foo.bar.baz%333%foo%#ch_win4%baz!~bazbaz@OLD.baz.baz%1234567890]
insert topic-set-to [% baz.baz=OLD.baz.baz (WIN_ID)=4 (TOPIC)=foo%bar%baz]
insert join-channel-0-1-list-residents [% (WIN_ID)=4 (RESIDENT_NAMES)=foo%baz]
-insert join-channel-1-end-of-names range=:-3 [(WIN_ID)=4]
-insert join-channel-1-end-of-names range=-2: [% (WIN_ID)=4 (RESIDENT_IDS)=[2],%[me] (RESIDENT_NICKS)=baz,%foo]
+insert join-channel-1-0-endofnames-to-prefixes range=:-1 [(WIN_ID)=4]
+insert join-channel-1-1-userids-to-329 [% (WIN_ID)=4 (RESIDENT_IDS)=[2],%[me] (RESIDENT_NICKS)=baz,%foo]
# check _observed_ topic change _does_ affect users database, and …
insert servermsglogged [% (MSG)=:baz!~bazbaz@baz.baz%TOPIC%#ch_win4%:foo%bar%baz]
insert ./lib/isupport-clear
insert ./lib/isupport-set
insert ./lib/join-channel
-# for: join-channel-0-cmd-to-list-residents, join-channel-1
+# for: join-channel-0-cmd-to-list-residents, join-channel-1-0-endofnames-to-prefixes, join-channel-1-1-userids-to-329
insert ./lib/join-empty
insert ./lib/no-handler
insert ./lib/servermsglogged
insert user-set-to range=:1 [(USER_ID)=1 (USER_NICK)=bar]
insert user-set-to range=:1 [(USER_ID)=2 (USER_NICK)=baz]
insert user-set-to range=:1 [(USER_ID)=3 (USER_NICK)==quux]
-insert join-channel-1-end-of-names range=:-3 [(WIN_ID)=7]
+insert join-channel-1-0-endofnames-to-prefixes range=:-1 [(WIN_ID)=7]
log 1 $ channels:#ch_win7:prefixes:o set to: [1]
log 1 $ channels:#ch_win7:prefixes:v set to: [2]
-insert join-channel-1-end-of-names range=-2: [% (WIN_ID)=7 (RESIDENT_IDS)=[1],%[2],%[3],%[me] (RESIDENT_NICKS)=@bar,%+baz,%=quux,%foo]
+insert join-channel-1-1-userids-to-329 [% (WIN_ID)=7 (RESIDENT_IDS)=[1],%[2],%[3],%[me] (RESIDENT_NICKS)=@bar,%+baz,%=quux,%foo]
insert isupport-set [(KEY)=PREFIX (VALUE)=(vE)+=]
insert join-channel-0-cmd-to-list-residents [% (WIN_ID)=8 (RESIDENT_NAMES)=foo%@bar%+baz%=quux]
insert user-set-to range=:1 [(USER_ID)=4 (USER_NICK)=@bar]
insert user-set-to range=:1 [(USER_ID)=5 (USER_NICK)=quux]
-insert join-channel-1-end-of-names range=:-3 [(WIN_ID)=8]
+insert join-channel-1-0-endofnames-to-prefixes range=:-1 [(WIN_ID)=8]
log 1 $ channels:#ch_win8:prefixes:v set to: [2]
log 1 $ channels:#ch_win8:prefixes:E set to: [5]
-insert join-channel-1-end-of-names range=-2: [% (WIN_ID)=8 (RESIDENT_IDS)=[2],%[4],%[5],%[me] (RESIDENT_NICKS)=+baz,%@bar,%=quux,%foo]
+insert join-channel-1-1-userids-to-329 [% (WIN_ID)=8 (RESIDENT_IDS)=[2],%[4],%[5],%[me] (RESIDENT_NICKS)=+baz,%@bar,%=quux,%foo]
# test effect of USERLEN
insert join-empty [(WIN_ID)=9]
insert join-channel-0-0-cmd-to-ack
insert join-channel-0-1-list-residents
-× join-channel-1-end-of-names
+× join-channel-1-0-endofnames-to-prefixes
insert servermsglogged [% (MSG)=:foo.bar.baz%366%foo%#ch_win(WIN_ID)%:End%of%/NAMES%list.]
+log 1 > MODE :#ch_win(WIN_ID)
log 1 $ channels:#ch_win(WIN_ID):prefixes cleared
+
+× join-channel-1-1-userids-to-329
log 1 $ channels:#ch_win(WIN_ID):user_ids set to: (RESIDENT_IDS)
log (WIN_ID) $ residents: (RESIDENT_NICKS)
+insert servermsglogged [% (MSG)=:foo.bar.baz%324%foo%#ch_win(WIN_ID)%+]
+insert servermsglogged [% (MSG)=:foo.bar.baz%329%foo%#ch_win(WIN_ID)%123456789]
+
+× join-channel-1-endofnames-to-329
+insert join-channel-1-0-endofnames-to-prefixes
+insert join-channel-1-1-userids-to-329
insert ./lib/join-channel
-# for join-channel-0-cmd-to-list-residents, join-channel-1-end-of-names
+# for join-channel-0-cmd-to-list-residents, join-channel-1-endofnames-to-329
× join-empty
insert join-channel-0-cmd-to-list-residents [(RESIDENT_NAMES)=foo]
-insert join-channel-1-end-of-names [(RESIDENT_IDS)=[me] (RESIDENT_NICKS)=foo]
+insert join-channel-1-endofnames-to-329 [(RESIDENT_IDS)=[me] (RESIDENT_NICKS)=foo (CHANMODES)=+]
# for: enter-help-win0
insert ./lib/isupport-clear
insert ./lib/join-channel
-# for: join-channel-0-cmd-to-list-residents, join-channel-1-end-of-names
+# for: join-channel-0-cmd-to-list-residents, join-channel-1-0-endofnames-to-prefixes, join-channel-1-1-userids-to-329, join-channel-1-endofnames-to-329
insert ./lib/part
# for: part-no-msg-me, quits
insert ./lib/pingpong
# join channel with other user
insert join-channel-0-cmd-to-list-residents [% (WIN_ID)=4 (RESIDENT_NAMES)=foo%@baz]
insert user-set-to range=:1 [(USER_ID)=1 (USER_NICK)=baz]
-insert join-channel-1-end-of-names range=:-3 [(WIN_ID)=4]
+insert join-channel-1-0-endofnames-to-prefixes range=:-1 [(WIN_ID)=4]
log 1 $ channels:#ch_win4:prefixes:o set to: [1]
-insert join-channel-1-end-of-names range=-2: [% (WIN_ID)=4 (RESIDENT_IDS)=[1],%[me] (RESIDENT_NICKS)=@baz,%foo]
+insert join-channel-1-1-userids-to-329 [% (WIN_ID)=4 (RESIDENT_IDS)=[1],%[me] (RESIDENT_NICKS)=@baz,%foo]
# process non-self channel JOIN
insert servermsglogged [% (MSG)=:bar!~barbar@bar.bar%JOIN%:#ch_win4]
# join second channel with partial residents identity to compare distribution of resident-specific messages
insert join-channel-0-cmd-to-list-residents [% (WIN_ID)=5 (RESIDENT_NAMES)=foo%bar]
-insert join-channel-1-end-of-names [% (WIN_ID)=5 (RESIDENT_IDS)=[2],%[me] (RESIDENT_NICKS)=bar,%foo]
+insert join-channel-1-endofnames-to-329 [% (WIN_ID)=5 (RESIDENT_IDS)=[2],%[me] (RESIDENT_NICKS)=bar,%foo]
# handle query window with known user
insert servermsglogged [% (MSG)=:bar!~barbar@bar.bar%PRIVMSG%foo%:hi%there]