diff --git a/maubot.yaml b/maubot.yaml index b114188..a41b9dd 100644 --- a/maubot.yaml +++ b/maubot.yaml @@ -1,6 +1,6 @@ maubot: 0.1.0 id: nl.roomsoverview -version: 2.3.1 +version: 2.4.0 license: MIT modules: - roomsoverview diff --git a/roomsoverview.mbp b/roomsoverview.mbp index 35e6db8..1b34b3d 100644 Binary files a/roomsoverview.mbp and b/roomsoverview.mbp differ diff --git a/roomsoverview.py b/roomsoverview.py index 7f1d0bb..677cf8c 100644 --- a/roomsoverview.py +++ b/roomsoverview.py @@ -435,23 +435,16 @@ class RoomsOverviewPlugin(Plugin): ) return [dict(r) for r in rows] - async def _send_list(self, evt: MessageEvent) -> None: - rooms = await self._list_rooms() - if not rooms: - await evt.reply( - "De room-index is nog leeg. Moderators kunnen rooms toevoegen met " - "`!rooms add `." - ) - return + def _sort_rooms(self, rooms: List[Dict[str, Any]]) -> List[Dict[str, Any]]: + return sorted( + rooms, + key=lambda r: ( + r.get("display_name") or r.get("canonical_alias") or r["room_id"] + ).lower(), + ) - def sort_key(r: Dict[str, Any]) -> str: - return ( - r.get("display_name") - or r.get("canonical_alias") - or r["room_id"] - ).lower() - - rooms.sort(key=sort_key) + def _build_cards(self, rooms: List[Dict[str, Any]]) -> List[Tuple[str, str]]: + """Bouw per room een blockquote-kaart (html, plain).""" # Elke room wordt een blockquote-kaart: icoontje + naam/leden als kop, # omschrijving eronder, onderaan de join-link. De formatted_body bouwen @@ -510,13 +503,21 @@ class RoomsOverviewPlugin(Plugin): f"{e(address)}

" ) cards.append(("".join(body_parts), plain)) + return cards + async def _send_cards( + self, + evt: MessageEvent, + cards: List[Tuple[str, str]], + subject: str, + count_label: str, + ) -> None: chunk_size = max(1, int(self.config.get("rooms_per_message", 50) or 50)) chunks = [cards[i : i + chunk_size] for i in range(0, len(cards), chunk_size)] total = len(cards) for idx, chunk in enumerate(chunks, start=1): - header = f"Rooms overzicht ({total} rooms getoond, deel {idx}/{len(chunks)}):" + header = f"{subject} ({total} {count_label}, deel {idx}/{len(chunks)}):" html_body = ( f'

{html.escape(header)}

' + "".join(html_part for html_part, _ in chunk) @@ -530,6 +531,47 @@ class RoomsOverviewPlugin(Plugin): ) await evt.respond(content) + async def _send_list(self, evt: MessageEvent) -> None: + rooms = self._sort_rooms(await self._list_rooms()) + if not rooms: + await evt.reply( + "De room-index is nog leeg. Moderators kunnen rooms toevoegen met " + "`!rooms add `." + ) + return + await self._send_cards( + evt, self._build_cards(rooms), "Rooms overzicht", "rooms getoond" + ) + + async def _search_rooms(self, terms: str) -> List[Dict[str, Any]]: + """Zoek rooms: alle termen moeten matchen (case-insensitive, substring) + in naam, alias of omschrijving.""" + needles = [t for t in (part.lower() for part in terms.split()) if t] + if not needles: + return [] + found = [] + for r in await self._list_rooms(): + hay = " ".join( + str(r.get(field) or "").lower() + for field in ("display_name", "canonical_alias", "topic") + ) + if all(n in hay for n in needles): + found.append(r) + return self._sort_rooms(found) + + async def _send_search(self, evt: MessageEvent, query: str) -> None: + found = await self._search_rooms(query) + query_label = " ".join(query.split()) + if not found: + await evt.reply(f"Geen rooms gevonden voor `{query_label}`.") + return + await self._send_cards( + evt, + self._build_cards(found), + f"Zoekresultaten voor '{query_label}'", + "gevonden", + ) + async def _send_help(self, evt: MessageEvent) -> None: """Uitgebreide Nederlandstalige handleiding voor !rooms.""" help_text = ( @@ -539,7 +581,10 @@ class RoomsOverviewPlugin(Plugin): "naast de naam.\n\n" "**Basis:**\n" "* `!rooms` — toon de volledige lijst (bij veel rooms verdeeld " - "over meerdere berichten)\n\n" + "over meerdere berichten)\n" + "* `!rooms over ` — zoek rooms op naam, alias en/of " + "omschrijving (bijv. `!rooms over linux`); alle termen moeten " + "matchen\n\n" "**Subcommando's (moderator of hoger vereist):**\n" "* `!rooms add ` — voeg een room toe aan de index\n" "* `!rooms edit =` — wijzig een " @@ -561,7 +606,7 @@ class RoomsOverviewPlugin(Plugin): @command.new( name="rooms", - help="Toon de room-index als kaarten; subcommands: add, edit, remove, refresh, help", + help="Toon de room-index als kaarten; subcommands: over (zoeken), add, edit, remove, refresh, help", require_subcommand=False, ) async def handle_rooms(self, evt: MessageEvent) -> None: @@ -572,6 +617,20 @@ class RoomsOverviewPlugin(Plugin): async def rooms_help(self, evt: MessageEvent) -> None: await self._send_help(evt) + @handle_rooms.subcommand( + name="over", + help="Zoek rooms op naam, alias of omschrijving: !rooms over ", + ) + @command.argument("terms", pass_raw=True, required=True) + async def search_over(self, evt: MessageEvent, terms: str) -> None: + if not terms.strip(): + await evt.reply( + "Gebruik: `!rooms over ` (bijv. `!rooms over linux`).\n" + "Zoekt op naam, alias en omschrijving; alle termen moeten matchen." + ) + return + await self._send_search(evt, terms) + @handle_rooms.subcommand( name="add", help="Voeg een room toe aan de index: !rooms add (moderator+)",