Skip to content

Commit b055e48

Browse files
committed
Clean up branching logic in chan_track mode hook
1 parent 2c7f813 commit b055e48

1 file changed

Lines changed: 61 additions & 35 deletions

File tree

plugins/chan_track.py

Lines changed: 61 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
"""
77
import gc
88
import json
9-
import weakref
10-
from collections import Mapping, Iterable
9+
from collections import Mapping, Iterable, namedtuple
1110
from contextlib import suppress
1211
from numbers import Number
1312
from operator import attrgetter
@@ -269,6 +268,15 @@ def get_chan_data(bot):
269268
update_conn_data(conn)
270269

271270

271+
def sort_member_status(member):
272+
"""
273+
:type member: Channel.Member
274+
"""
275+
status = list(set(member.status))
276+
status.sort(key=attrgetter("level"), reverse=True)
277+
member.status = status
278+
279+
272280
def clean_user_data(user):
273281
"""
274282
:type user: User
@@ -543,6 +551,35 @@ def on_join(nick, user, host, conn, irc_paramlist):
543551
user_data.join_channel(chan_data)
544552

545553

554+
ModeChange = namedtuple('ModeChange', 'mode adding param is_status')
555+
556+
557+
def _parse_mode_string(modes, params, status_modes, mode_types):
558+
new_modes = []
559+
adding = True
560+
for c in modes:
561+
if c == '+':
562+
adding = True
563+
elif c == '-':
564+
adding = False
565+
else:
566+
is_status = c in status_modes
567+
mode_type = mode_types.get(c)
568+
if mode_type:
569+
mode_type = mode_type.type
570+
else:
571+
mode_type = 'B' if is_status else None
572+
573+
if mode_type in "AB" or (mode_type == 'C' and adding):
574+
param = params.pop(0)
575+
else:
576+
param = None
577+
578+
new_modes.append(ModeChange(c, adding, param, is_status))
579+
580+
return new_modes
581+
582+
546583
@hook.irc_raw('MODE')
547584
def on_mode(chan, irc_paramlist, conn):
548585
"""
@@ -565,42 +602,31 @@ def on_mode(chan, irc_paramlist, conn):
565602
chan_data = get_chans(conn).getchan(chan)
566603

567604
modes = irc_paramlist[1]
568-
mode_params = irc_paramlist[2:]
569-
new_modes = {}
570-
adding = True
571-
for c in modes:
572-
if c == '+':
573-
adding = True
574-
elif c == '-':
575-
adding = False
605+
mode_params = list(irc_paramlist[2:]).copy()
606+
new_modes = _parse_mode_string(modes, mode_params, status_modes, mode_types)
607+
new_statuses = [change for change in new_modes if change.is_status]
608+
to_sort = {}
609+
for change in new_statuses:
610+
status_char = change.mode
611+
nick = change.param
612+
user = get_users(conn).getuser(nick)
613+
memb = chan_data.get_member(user, create=True)
614+
status = statuses[status_char]
615+
memb_status = memb.status
616+
if change.adding:
617+
memb_status.append(status)
618+
to_sort[user.nick] = memb
576619
else:
577-
new_modes[c] = adding
578-
is_status = c in status_modes
579-
mode_type = mode_types.get(c)
580-
if mode_type:
581-
mode_type = mode_type.type
620+
if status in memb_status:
621+
memb_status.remove(status)
582622
else:
583-
mode_type = 'B' if is_status else None
623+
logger.debug(
624+
"[%s|chantrack] Attempt to remove status %s from user %s in channel %s",
625+
conn.name, status, user['nick'], chan
626+
)
584627

585-
if mode_type in "AB" or (mode_type == 'C' and adding):
586-
param = mode_params.pop(0)
587-
588-
if is_status:
589-
user = get_users(conn).getuser(param)
590-
memb = chan_data.get_member(user, create=True)
591-
status = statuses[c]
592-
memb_status = memb.status
593-
if adding:
594-
memb_status.append(status)
595-
memb_status.sort(key=attrgetter("level"), reverse=True)
596-
else:
597-
if status in memb_status:
598-
memb_status.remove(status)
599-
else:
600-
logger.debug(
601-
"[%s|chantrack] Attempt to remove status %s from user %s in channel %s",
602-
conn.name, status, user['nick'], chan
603-
)
628+
for member in to_sort.values():
629+
sort_member_status(member)
604630

605631

606632
@hook.irc_raw('PART')

0 commit comments

Comments
 (0)