mirror of
https://mau.dev/maunium/synapse.git
synced 2024-10-01 01:36:05 -04:00
118 lines
4.4 KiB
Python
118 lines
4.4 KiB
Python
|
# Copyright 2021 The Matrix.org Foundation C.I.C.
|
||
|
#
|
||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
# you may not use this file except in compliance with the License.
|
||
|
# You may obtain a copy of the License at
|
||
|
#
|
||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||
|
#
|
||
|
# Unless required by applicable law or agreed to in writing, software
|
||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
# See the License for the specific language governing permissions and
|
||
|
# limitations under the License.
|
||
|
import logging
|
||
|
from typing import TYPE_CHECKING, Optional
|
||
|
|
||
|
from synapse.api.errors import SynapseError
|
||
|
from synapse.types import JsonDict, Requester, StreamToken
|
||
|
|
||
|
if TYPE_CHECKING:
|
||
|
from synapse.server import HomeServer
|
||
|
|
||
|
|
||
|
logger = logging.getLogger(__name__)
|
||
|
|
||
|
|
||
|
class RelationsHandler:
|
||
|
def __init__(self, hs: "HomeServer"):
|
||
|
self._main_store = hs.get_datastores().main
|
||
|
self._auth = hs.get_auth()
|
||
|
self._clock = hs.get_clock()
|
||
|
self._event_handler = hs.get_event_handler()
|
||
|
self._event_serializer = hs.get_event_client_serializer()
|
||
|
|
||
|
async def get_relations(
|
||
|
self,
|
||
|
requester: Requester,
|
||
|
event_id: str,
|
||
|
room_id: str,
|
||
|
relation_type: Optional[str] = None,
|
||
|
event_type: Optional[str] = None,
|
||
|
aggregation_key: Optional[str] = None,
|
||
|
limit: int = 5,
|
||
|
direction: str = "b",
|
||
|
from_token: Optional[StreamToken] = None,
|
||
|
to_token: Optional[StreamToken] = None,
|
||
|
) -> JsonDict:
|
||
|
"""Get related events of a event, ordered by topological ordering.
|
||
|
|
||
|
TODO Accept a PaginationConfig instead of individual pagination parameters.
|
||
|
|
||
|
Args:
|
||
|
requester: The user requesting the relations.
|
||
|
event_id: Fetch events that relate to this event ID.
|
||
|
room_id: The room the event belongs to.
|
||
|
relation_type: Only fetch events with this relation type, if given.
|
||
|
event_type: Only fetch events with this event type, if given.
|
||
|
aggregation_key: Only fetch events with this aggregation key, if given.
|
||
|
limit: Only fetch the most recent `limit` events.
|
||
|
direction: Whether to fetch the most recent first (`"b"`) or the
|
||
|
oldest first (`"f"`).
|
||
|
from_token: Fetch rows from the given token, or from the start if None.
|
||
|
to_token: Fetch rows up to the given token, or up to the end if None.
|
||
|
|
||
|
Returns:
|
||
|
The pagination chunk.
|
||
|
"""
|
||
|
|
||
|
user_id = requester.user.to_string()
|
||
|
|
||
|
await self._auth.check_user_in_room_or_world_readable(
|
||
|
room_id, user_id, allow_departed_users=True
|
||
|
)
|
||
|
|
||
|
# This gets the original event and checks that a) the event exists and
|
||
|
# b) the user is allowed to view it.
|
||
|
event = await self._event_handler.get_event(requester.user, room_id, event_id)
|
||
|
if event is None:
|
||
|
raise SynapseError(404, "Unknown parent event.")
|
||
|
|
||
|
pagination_chunk = await self._main_store.get_relations_for_event(
|
||
|
event_id=event_id,
|
||
|
event=event,
|
||
|
room_id=room_id,
|
||
|
relation_type=relation_type,
|
||
|
event_type=event_type,
|
||
|
aggregation_key=aggregation_key,
|
||
|
limit=limit,
|
||
|
direction=direction,
|
||
|
from_token=from_token,
|
||
|
to_token=to_token,
|
||
|
)
|
||
|
|
||
|
events = await self._main_store.get_events_as_list(
|
||
|
[c["event_id"] for c in pagination_chunk.chunk]
|
||
|
)
|
||
|
|
||
|
now = self._clock.time_msec()
|
||
|
# Do not bundle aggregations when retrieving the original event because
|
||
|
# we want the content before relations are applied to it.
|
||
|
original_event = self._event_serializer.serialize_event(
|
||
|
event, now, bundle_aggregations=None
|
||
|
)
|
||
|
# The relations returned for the requested event do include their
|
||
|
# bundled aggregations.
|
||
|
aggregations = await self._main_store.get_bundled_aggregations(
|
||
|
events, requester.user.to_string()
|
||
|
)
|
||
|
serialized_events = self._event_serializer.serialize_events(
|
||
|
events, now, bundle_aggregations=aggregations
|
||
|
)
|
||
|
|
||
|
return_value = await pagination_chunk.to_dict(self._main_store)
|
||
|
return_value["chunk"] = serialized_events
|
||
|
return_value["original_event"] = original_event
|
||
|
|
||
|
return return_value
|