Skip to content

Commit

Permalink
Merge remote-tracking branch 'maltee1/power_level'
Browse files Browse the repository at this point in the history
  • Loading branch information
tulir committed Jun 4, 2022
2 parents 38ff3e0 + 053db40 commit 99642da
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 28 deletions.
2 changes: 2 additions & 0 deletions mausignald/signald.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ async def update_group(
add_members: list[Address] | None = None,
remove_members: list[Address] | None = None,
update_access_control: GroupAccessControl | None = None,
update_role: GroupMember | None = None,
) -> Group | GroupV2 | None:
update_params = {
key: value
Expand All @@ -370,6 +371,7 @@ async def update_group(
"updateAccessControl": (
update_access_control.serialize() if update_access_control else None
),
"updateRole": (update_role.serialize() if update_role else None),
}.items()
if value is not None
}
Expand Down
9 changes: 8 additions & 1 deletion mautrix_signal/matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,12 @@ async def handle_ephemeral_event(
await super().handle_ephemeral_event(evt)

async def handle_state_event(self, evt: StateEvent) -> None:
if evt.type not in (EventType.ROOM_NAME, EventType.ROOM_TOPIC, EventType.ROOM_AVATAR):
if evt.type not in (
EventType.ROOM_NAME,
EventType.ROOM_TOPIC,
EventType.ROOM_AVATAR,
EventType.ROOM_POWER_LEVELS,
):
return

user = await u.User.get_by_mxid(evt.sender)
Expand All @@ -204,6 +209,8 @@ async def handle_state_event(self, evt: StateEvent) -> None:
await portal.handle_matrix_avatar(user, evt.content.url)
elif evt.type == EventType.ROOM_TOPIC:
await portal.handle_matrix_topic(user, evt.content.topic)
elif evt.type == EventType.ROOM_POWER_LEVELS:
await portal.handle_matrix_power_level(user, evt.content, evt.unsigned.prev_content)

async def allow_message(self, user: u.User) -> bool:
return user.relay_whitelisted
Expand Down
138 changes: 111 additions & 27 deletions mautrix_signal/portal.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
Group,
GroupAccessControl,
GroupID,
GroupMember,
GroupMemberRole,
GroupV2,
GroupV2ID,
Expand Down Expand Up @@ -774,6 +775,20 @@ async def handle_matrix_invite(self, invited_by: u.User, user: u.User | p.Puppet
)
except RPCError as e:
raise RejectMatrixInvite(str(e)) from e
power_levels = await self.main_intent.get_power_levels(self.mxid)
invitee_pl = power_levels.get_user_level(user.mxid)
if invitee_pl >= 50:
group_member = GroupMember(uuid=user.uuid, role=GroupMemberRole.ADMINISTRATOR)
try:
update_meta = await self.signal.update_group(
invited_by.username, self.chat_id, update_role=group_member
)
self.revision = update_meta.revision
except Exception as e:
self.log.exception(f"Failed to update Signal member role: {e}")
await self._update_power_levels(
await self.signal.get_group(invited_by.username, self.chat_id)
)

async def handle_matrix_name(self, user: u.User, name: str) -> None:
if self.name == name or self.is_direct or not name:
Expand Down Expand Up @@ -839,6 +854,101 @@ async def handle_matrix_avatar(self, user: u.User, url: ContentURI) -> None:
except FileNotFoundError:
pass

async def handle_matrix_power_level(
self,
sender: u.User,
levels: PowerLevelStateEventContent,
prev_content: PowerLevelStateEventContent | None = None,
) -> None:
old_users = prev_content.users if prev_content else None
new_users = levels.users
changes = {}
sender, is_relay = await self.get_relay_sender(sender, "power level change")
if not sender:
return

if not old_users:
changes = new_users
else:
for user, level in new_users.items():
if (
user
and user != self.main_intent.mxid
and (user not in old_users or level != old_users[user])
):
changes[user] = level
for user, level in old_users.items():
if user and user != self.main_intent.mxid and user not in new_users:
changes[user] = levels.users_default
if changes:
for user, level in changes.items():
address = p.Puppet.get_id_from_mxid(user)
if not address:
mx_user = await u.User.get_by_mxid(user, create=False)
if not mx_user or not mx_user.is_logged_in:
continue
address = mx_user.address
if not address or not address.uuid:
continue
signal_role = (
GroupMemberRole.DEFAULT if level < 50 else GroupMemberRole.ADMINISTRATOR
)
group_member = GroupMember(uuid=address.uuid, role=signal_role)
try:
update_meta = await self.signal.update_group(
sender.username, self.chat_id, update_role=group_member
)
self.revision = update_meta.revision
except Exception as e:
self.log.exception(f"Failed to update Signal member role: {e}")
await self._update_power_levels(
await self.signal.get_group(sender.username, self.chat_id)
)
return
if not prev_content or levels.invite != prev_content.invite:
try:
update_meta = await self.signal.update_group(
username=sender.username,
group_id=self.chat_id,
update_access_control=GroupAccessControl(
members=(
AccessControlMode.MEMBER
if levels.invite == 0
else AccessControlMode.ADMINISTRATOR
),
attributes=None,
link=None,
),
)
self.revision = update_meta.revision
except Exception as e:
self.log.exception(f"Failed to update Signal member add permission: {e}")
await self._update_power_levels(
await self.signal.get_group(sender.username, self.chat_id)
)
return
if not prev_content or levels.state_default != prev_content.state_default:
try:
update_meta = await self.signal.update_group(
username=sender.username,
group_id=self.chat_id,
update_access_control=GroupAccessControl(
attributes=(
AccessControlMode.MEMBER
if levels.state_default == 0
else AccessControlMode.ADMINISTRATOR
),
members=None,
link=None,
),
)
self.revision = update_meta.revision
except Exception as e:
self.log.exception(f"Failed to update Signal metadata change permission: {e}")
await self._update_power_levels(
await self.signal.get_group(sender.username, self.chat_id)
)

# endregion
# region Signal event handling

Expand Down Expand Up @@ -1335,33 +1445,7 @@ async def create_signal_group(
pass
if self.topic:
await self.signal.update_group(source.username, self.chat_id, description=self.topic)
await self.signal.update_group(
username=source.username,
group_id=self.chat_id,
update_access_control=GroupAccessControl(
members=(
AccessControlMode.MEMBER
if levels.invite == 0
else AccessControlMode.ADMINISTRATOR
),
attributes=None,
link=None,
),
)
update_meta = await self.signal.update_group(
username=source.username,
group_id=self.chat_id,
update_access_control=GroupAccessControl(
attributes=(
AccessControlMode.MEMBER
if levels.state_default == 0
else AccessControlMode.ADMINISTRATOR
),
members=None,
link=None,
),
)
self.revision = update_meta.revision
await self.handle_matrix_power_level(source, levels)
await self.update()
await self.update_bridge_info()

Expand Down

0 comments on commit 99642da

Please sign in to comment.