示例#1
0
    async def get_state_event(
        self,
        room_id: RoomID,
        event_type: EventType,
        state_key: str = "",
    ) -> StateEventContent:
        """
        Looks up the contents of a state event in a room. If the user is joined to the room then the
        state is taken from the current state of the room. If the user has left the room then the
        state is taken from the state of the room when they left.

        See also: `API reference <https://spec.matrix.org/v1.1/client-server-api/#get_matrixclientv3roomsroomidstateeventtypestatekey>`__

        Args:
            room_id: The ID of the room to look up the state in.
            event_type: The type of state to look up.
            state_key: The key of the state to look up. Defaults to empty string.

        Returns:
            The state event.
        """
        content = await self.api.request(
            Method.GET,
            Path.v3.rooms[room_id].state[event_type][state_key],
            metrics_method="getStateEvent",
        )
        content["__mautrix_event_type"] = event_type
        try:
            return StateEvent.deserialize_content(content)
        except SerializerError as e:
            raise MatrixResponseError("Invalid state event in response") from e
示例#2
0
    async def get_members(
        self,
        room_id: RoomID,
        at: SyncToken | None = None,
        membership: Membership | None = None,
        not_membership: Membership | None = None,
    ) -> list[StateEvent]:
        """
        Get the list of members for a room.

        See also: `API reference <https://spec.matrix.org/v1.1/client-server-api/#get_matrixclientv3roomsroomidmembers>`__

        Args:
            room_id: The ID of the room to get the member events for.
            at: The point in time (pagination token) to return members for in the room. This token
                can be obtained from a ``prev_batch`` token returned for each room by the sync API.
                Defaults to the current state of the room, as determined by the server.
            membership: The kind of membership to filter for. Defaults to no filtering if
                unspecified. When specified alongside ``not_membership``, the two parameters create
                an 'or' condition: either the ``membership`` is the same as membership or is not the
                same as ``not_membership``.
            not_membership: The kind of membership to exclude from the results. Defaults to no
                filtering if unspecified.

        Returns:
            A list of most recent member events for each user.
        """
        query = {}
        if at:
            query["at"] = at
        if membership:
            query["membership"] = membership.value
        if not_membership:
            query["not_membership"] = not_membership.value
        content = await self.api.request(
            Method.GET,
            Path.v3.rooms[room_id].members,
            query_params=query,
            metrics_method="getMembers",
        )
        try:
            return [
                StateEvent.deserialize(event) for event in content["chunk"]
            ]
        except KeyError:
            raise MatrixResponseError("`chunk` not in response.")
        except SerializerError as e:
            raise MatrixResponseError(
                "Invalid state events in response") from e
示例#3
0
 async def handle_room_membership(self, evt: StateEvent) -> None:
     if self._ignore_user(evt.state_key):
         return
     try:
         room = self.client.rooms[evt.room_id]
     except KeyError:
         room = self.client.rooms[evt.room_id] = NioRoom(evt.room_id,
                                                         self.bot_mxid,
                                                         encrypted=True)
         await self.client.joined_members(evt.room_id)
     nio_evt = NioMemberEvent.from_dict(evt.serialize())
     try:
         if room.handle_membership(nio_evt):
             self.client._invalidate_session_for_member_event(evt.room_id)
     except Exception:
         self.log.exception("matrix-nio failed to handle membership event")
示例#4
0
 async def get_state_event(
         self,
         room_id: RoomID,
         event_type: EventType,
         state_key: Optional[str] = None) -> StateEventContent:
     event = await super().get_state_event(room_id, event_type, state_key)
     if self.state_store:
         fake_event = StateEvent(type=event_type,
                                 room_id=room_id,
                                 event_id=EventID(""),
                                 sender=UserID(""),
                                 state_key=state_key,
                                 timestamp=0,
                                 content=event)
         await self.state_store.update_state(fake_event)
     return event
示例#5
0
 async def send_state_event(self,
                            room_id: RoomID,
                            event_type: EventType,
                            content: Union[StateEventContent, Dict],
                            state_key: Optional[str] = "",
                            **kwargs) -> EventID:
     event_id = await super().send_state_event(room_id, event_type, content,
                                               state_key, **kwargs)
     if self.state_store:
         fake_event = StateEvent(type=event_type,
                                 room_id=room_id,
                                 event_id=event_id,
                                 sender=self.mxid,
                                 state_key=state_key,
                                 timestamp=0,
                                 content=content)
         await self.state_store.update_state(fake_event)
     return event_id
示例#6
0
    async def get_state(self, room_id: RoomID) -> List[StateEvent]:
        """
        Get the state events for the current state of a room. See also: `/state API reference`_

        Args:
            room_id: The ID of the room to look up the state for.

        Returns:
            A list of state events with the most recent of each event_type/state_key pair.

        .. _/state API reference:
            https://matrix.org/docs/spec/client_server/r0.5.0#get-matrix-client-r0-rooms-roomid-state
        """
        content = await self.api.request(Method.GET, Path.rooms[room_id].state)
        try:
            return [StateEvent.deserialize(event) for event in content]
        except SerializerError as e:
            raise MatrixResponseError(
                "Invalid state events in response") from e
示例#7
0
    async def get_state(self, room_id: RoomID) -> list[StateEvent]:
        """
        Get the state events for the current state of a room.

        See also: `API reference <https://spec.matrix.org/v1.1/client-server-api/#get_matrixclientv3roomsroomidstate>`__

        Args:
            room_id: The ID of the room to look up the state for.

        Returns:
            A list of state events with the most recent of each event_type/state_key pair.
        """
        content = await self.api.request(Method.GET,
                                         Path.v3.rooms[room_id].state,
                                         metrics_method="getState")
        try:
            return [StateEvent.deserialize(event) for event in content]
        except SerializerError as e:
            raise MatrixResponseError(
                "Invalid state events in response") from e
示例#8
0
 async def send_state_event(
     self,
     room_id: RoomID,
     event_type: EventType,
     content: StateEventContent | dict[str, JSON],
     state_key: str = "",
     **kwargs,
 ) -> EventID:
     event_id = await super().send_state_event(room_id, event_type, content,
                                               state_key, **kwargs)
     if self.state_store:
         fake_event = StateEvent(
             type=event_type,
             room_id=room_id,
             event_id=event_id,
             sender=self.mxid,
             state_key=state_key,
             timestamp=0,
             content=content,
         )
         await self.state_store.update_state(fake_event)
     return event_id
示例#9
0
    def handle_sync(self, data: JSON) -> List[asyncio.Task]:
        """
        Handle a /sync object.

        Args:
            data: The data from a /sync request.
        """
        tasks = []

        otk_count = data.get("device_one_time_keys_count", {})
        tasks += self.dispatch_internal_event(
            InternalEventType.DEVICE_OTK_COUNT,
            custom_type=DeviceOTKCount(curve25519=otk_count.get("curve25519", 0),
                                       signed_curve25519=otk_count.get("signed_curve25519", 0)))

        device_lists = data.get("device_lists", {})
        tasks += self.dispatch_internal_event(InternalEventType.DEVICE_LISTS,
                                              custom_type=DeviceLists(
                                                  changed=device_lists.get("changed", []),
                                                  left=device_lists.get("left", [])))

        for raw_event in data.get("account_data", {}).get("events", []):
            tasks += self.dispatch_event(AccountDataEvent.deserialize(raw_event),
                                         source=SyncStream.ACCOUNT_DATA)
        for raw_event in data.get("ephemeral", {}).get("events", []):
            tasks += self.dispatch_event(EphemeralEvent.deserialize(raw_event),
                                         source=SyncStream.EPHEMERAL)
        for raw_event in data.get("to_device", {}).get("events", []):
            tasks += self.dispatch_event(ToDeviceEvent.deserialize(raw_event),
                                         source=SyncStream.TO_DEVICE)

        rooms = data.get("rooms", {})
        for room_id, room_data in rooms.get("join", {}).items():
            for raw_event in room_data.get("state", {}).get("events", []):
                raw_event["room_id"] = room_id
                tasks += self.dispatch_event(StateEvent.deserialize(raw_event),
                                             source=SyncStream.JOINED_ROOM | SyncStream.STATE)

            for raw_event in room_data.get("timeline", {}).get("events", []):
                raw_event["room_id"] = room_id
                tasks += self.dispatch_event(Event.deserialize(raw_event),
                                             source=SyncStream.JOINED_ROOM | SyncStream.TIMELINE)
        for room_id, room_data in rooms.get("invite", {}).items():
            events: List[Dict[str, Any]] = room_data.get("invite_state", {}).get("events", [])
            for raw_event in events:
                raw_event["room_id"] = room_id
            raw_invite = next(raw_event for raw_event in events
                              if raw_event.get("type", "") == "m.room.member"
                              and raw_event.get("state_key", "") == self.mxid)
            # These aren't required by the spec, so make sure they're set
            raw_invite.setdefault("event_id", None)
            raw_invite.setdefault("origin_server_ts", int(time() * 1000))
            raw_invite.setdefault("unsigned", {})

            invite = StateEvent.deserialize(raw_invite)
            invite.unsigned.invite_room_state = [StrippedStateEvent.deserialize(raw_event)
                                                 for raw_event in events
                                                 if raw_event != raw_invite]
            tasks += self.dispatch_event(invite, source=SyncStream.INVITED_ROOM | SyncStream.STATE)
        for room_id, room_data in rooms.get("leave", {}).items():
            for raw_event in room_data.get("timeline", {}).get("events", []):
                if "state_key" in raw_event:
                    raw_event["room_id"] = room_id
                    tasks += self.dispatch_event(StateEvent.deserialize(raw_event),
                                                 source=SyncStream.LEFT_ROOM | SyncStream.TIMELINE)
        return tasks