Update bot.py

fix: resolve room aliases in setpower and filter unjoined space rooms

This commit addresses two issues that caused API errors during room iteration and power level syncing:

1. Filter unjoined rooms in `get_space_roomlist`:
Previously, the bot assumed it was a member of all child rooms returned by the parent space state. If the bot was missing from certain child rooms, it threw errors during subsequent operations. The room list is now intersected with `await self.client.get_joined_rooms()` to safely ignore rooms the bot hasn't actually joined yet. Logging has been added to indicate when rooms are skipped.

2. Fix alias resolution (Sigil Bug) in `room_setpower`:
The `room_setpower <target_room>` command failed when users provided a standard room alias (starting with `#`) instead of an internal room ID (`!`), as the Matrix API expects the internal ID for state event operations. Added logic to detect aliases and explicitly resolve them to their respective `room_id` via `self.client.resolve_room_alias()` before attempting to update power levels. Appropriate error handling was also added to notify the user if the alias cannot be resolved.
This commit is contained in:
2026-04-09 09:01:06 +02:00
committed by GitHub
parent 1ec4523fc1
commit 5a1ed5aa1a
+57 -21
View File
@@ -430,7 +430,18 @@ class CommunityBot(Plugin):
rooms.append(evt.state_key) rooms.append(evt.state_key)
except Exception as e: except Exception as e:
self.log.error(f"Error getting space roomlist: {e}") self.log.error(f"Error getting space roomlist: {e}")
return rooms
try:
joined_rooms = await self.client.get_joined_rooms()
filtered_rooms = [r for r in rooms if r in joined_rooms]
if len(rooms) != len(filtered_rooms):
self.log.info(f"Ignoriere {len(rooms) - len(filtered_rooms)} Räume aus dem Space, da der Bot dort kein Mitglied ist.")
return filtered_rooms
except Exception as e:
self.log.error(f"Fehler beim Abgleich der joined_rooms: {e}")
return rooms
async def generate_report(self) -> None: async def generate_report(self) -> None:
now = int(time.time() * 1000) now = int(time.time() * 1000)
@@ -2531,12 +2542,27 @@ class CommunityBot(Plugin):
await evt.mark_read() await evt.mark_read()
if target_room: if target_room:
roomlist = [target_room] if target_room.startswith("#"):
try:
resolved_alias = await self.client.resolve_room_alias(target_room)
roomlist = [resolved_alias.room_id]
except Exception as e:
await evt.respond(f"Fehler: Konnte Alias {target_room} nicht in eine ID auflösen: {e}")
return
elif target_room.startswith("!"):
roomlist = [target_room]
else:
await evt.respond("Fehler: Der Raum muss mit ! (ID) oder # (Alias) beginnen.")
return
target_msg = target_room target_msg = target_room
else: else:
roomlist = await self.get_space_roomlist() roomlist = await self.get_space_roomlist()
target_msg = "space rooms" target_msg = "space rooms"
if not roomlist:
await evt.respond("Fehler: Keine gültigen Räume zum Aktualisieren gefunden. Ist der Bot in den Zielräumen Mitglied?")
return
msg = await evt.respond( msg = await evt.respond(
f"Syncing power levels from parent room to {target_msg}..." f"Syncing power levels from parent room to {target_msg}..."
) )
@@ -2579,10 +2605,14 @@ class CommunityBot(Plugin):
f"Parent room is modern (v{parent_version}), bot is not creator, power level set to 1000" f"Parent room is modern (v{parent_version}), bot is not creator, power level set to 1000"
) )
else: else:
# In legacy parent rooms, ensure bot has highest power level # In legacy parent rooms, keep the bot at its actual current PL (cannot self-promote)
user_power_levels[self.client.mxid] = 1000 bot_pl = parent_power_levels.users.get(
self.client.mxid,
getattr(parent_power_levels, "users_default", 0),
)
user_power_levels[self.client.mxid] = bot_pl
self.log.info( self.log.info(
f"Parent room is legacy (v{parent_version}), bot power level set to 1000" f"Parent room is legacy (v{parent_version}), bot power level retained at {bot_pl}"
) )
for room in roomlist: for room in roomlist:
@@ -2695,20 +2725,15 @@ class CommunityBot(Plugin):
else: else:
mapped_power_levels[user] = level mapped_power_levels[user] = level
# Handle bot power level based on whether it's a creator in the parent # In a legacy target room, keep the bot at its actual current PL (cannot self-promote)
if self.client.mxid in parent_creators: bot_pl = room_power_levels.users.get(
# Bot is a creator in parent, but this is a legacy room self.client.mxid,
# Set bot to highest power level since creators don't have unlimited power in legacy rooms getattr(room_power_levels, "users_default", 0),
mapped_power_levels[self.client.mxid] = 1000 )
self.log.info( mapped_power_levels[self.client.mxid] = bot_pl
f"Bot is creator in parent but target is legacy room - setting power level to 1000" self.log.info(
) f"Target room is legacy, bot power level retained at {bot_pl} in {roomname or room}"
else: )
# Bot is not a creator in parent, set to highest power level
mapped_power_levels[self.client.mxid] = 1000
self.log.info(
f"Bot is not creator in parent, setting power level to 1000 in legacy target room"
)
room_power_levels.users = mapped_power_levels room_power_levels.users = mapped_power_levels
@@ -2717,7 +2742,18 @@ class CommunityBot(Plugin):
self.log.info( self.log.info(
f"Both rooms are legacy - direct power level transfer" f"Both rooms are legacy - direct power level transfer"
) )
room_power_levels.users = user_power_levels # Capture the bot's current PL in this child room before overwriting.
# This is always the value we use — the bot cannot self-promote above
# its current PL, and we must not demote it if it's higher than the parent.
child_bot_pl = room_power_levels.users.get(
self.client.mxid,
getattr(room_power_levels, "users_default", 0),
)
room_power_levels.users = user_power_levels.copy()
room_power_levels.users[self.client.mxid] = child_bot_pl
self.log.info(
f"Both rooms legacy: bot PL retained at {child_bot_pl} in {roomname or room}"
)
# Send the updated power levels to this room # Send the updated power levels to this room
await self.client.send_state_event( await self.client.send_state_event(
@@ -2751,7 +2787,7 @@ class CommunityBot(Plugin):
else: else:
results += f"<b>Mapping Strategy:</b> Parent room is legacy (v{parent_version}), using traditional power level system.<br />" results += f"<b>Mapping Strategy:</b> Parent room is legacy (v{parent_version}), using traditional power level system.<br />"
results += ( results += (
"• Bot power level set to 1000 for administrative control<br />" "• Bot power level retained at its current level in legacy rooms<br />"
) )
results += "• Direct power level transfer to legacy child rooms<br />" results += "• Direct power level transfer to legacy child rooms<br />"
results += "• Modern child rooms preserve their creator power levels<br /><br />" results += "• Modern child rooms preserve their creator power levels<br /><br />"