async def invite_user(self, room_id: RoomID, user_id: UserID, check_cache: bool = False) -> None: """ Invite a user to participate in a particular room. They do not start participating in the room until they actually join the room. Only users currently in the room can invite other users to join that room. If the user was invited to the room, the homeserver will add a ``m.room.member`` event to the room. See also: `API reference <https://matrix.org/docs/spec/client_server/r0.4.0.html#post-matrix-client-r0-rooms-roomid-invite>`__ Args: room_id: The ID of the room to which to invite the user. user_id: The fully qualified user ID of the invitee. check_cache: Whether or not the function should be a no-op if the state store says the user is already invited. """ try: ok_states = (Membership.INVITE, Membership.JOIN) do_invite = (not check_cache or (await self.state_store.get_membership( room_id, user_id) not in ok_states)) if do_invite: await super().invite_user(room_id, user_id) await self.state_store.invited(room_id, user_id) except MatrixRequestError as e: if e.errcode != "M_FORBIDDEN": raise IntentError(f"Failed to invite {user_id} to {room_id}", e) if "is already in the room" in e.message: await self.state_store.joined(room_id, user_id)
async def ensure_joined(self, room_id: RoomID, ignore_cache: bool = False, bot: Optional['IntentAPI'] = _bridgebot) -> bool: if not room_id: raise ValueError("Room ID not given") if not ignore_cache and await self.state_store.is_joined( room_id, self.mxid): return False if bot is _bridgebot: bot = self.bot if bot is self: bot = None await self.ensure_registered() try: await self.join_room(room_id, max_retries=0) await self.state_store.joined(room_id, self.mxid) except MForbidden as e: if not bot: raise IntentError( f"Failed to join room {room_id} as {self.mxid}") from e try: await bot.invite_user(room_id, self.mxid) await self.join_room(room_id, max_retries=0) await self.state_store.joined(room_id, self.mxid) except MatrixRequestError as e2: raise IntentError( f"Failed to join room {room_id} as {self.mxid}") from e2 except MBadState as e: if not bot: raise IntentError( f"Failed to join room {room_id} as {self.mxid}") from e try: await bot.unban_user(room_id, self.mxid) await bot.invite_user(room_id, self.mxid) await self.join_room(room_id, max_retries=0) await self.state_store.joined(room_id, self.mxid) except MatrixRequestError as e2: raise IntentError( f"Failed to join room {room_id} as {self.mxid}") from e2 except MatrixRequestError as e: raise IntentError( f"Failed to join room {room_id} as {self.mxid}") from e return True
async def ensure_registered(self) -> None: if await self.state_store.is_registered(self.mxid): return try: await self._register() except MatrixRequestError as e: if e.errcode != "M_USER_IN_USE": raise IntentError(f"Failed to register {self.mxid}", e) # self.log.exception(f"Failed to register {self.mxid}!") # return await self.state_store.registered(self.mxid)
async def _ensure_has_power_level_for(self, room_id: RoomID, event_type: EventType) -> None: if not room_id: raise ValueError("Room ID not given") elif not event_type: raise ValueError("Event type not given") if not await self.state_store.has_power_levels_cached(room_id): await self.get_power_levels(room_id, ignore_cache=True) if not await self.state_store.has_power_level(room_id, self.mxid, event_type): # TODO implement something better raise IntentError(f"Power level of {self.mxid} is not enough " f"for {event_type} in {room_id}")
async def _ensure_has_power_level_for(self, room_id: RoomID, event_type: EventType, state_key: str = "") -> None: if not room_id: raise ValueError("Room ID not given") elif not event_type: raise ValueError("Event type not given") if event_type == EventType.ROOM_MEMBER: # TODO: if state_key doesn't equal self.mxid, check invite/kick/ban permissions return if not await self.state_store.has_power_levels_cached(room_id): # TODO add option to not try to fetch power levels from server await self.get_power_levels(room_id, ignore_cache=True) if not await self.state_store.has_power_level(room_id, self.mxid, event_type): # TODO implement something better raise IntentError(f"Power level of {self.mxid} is not enough " f"for {event_type} in {room_id}")