diff --git a/synapse/handlers/message.py b/synapse/handlers/message.py
index 4a4b535bae..0951b9c71f 100644
--- a/synapse/handlers/message.py
+++ b/synapse/handlers/message.py
@@ -44,7 +44,7 @@ from synapse.api.errors import (
from synapse.api.room_versions import KNOWN_ROOM_VERSIONS, RoomVersions
from synapse.api.urls import ConsentURIBuilder
from synapse.event_auth import validate_event_for_room_version
-from synapse.events import EventBase
+from synapse.events import EventBase, relation_from_event
from synapse.events.builder import EventBuilder
from synapse.events.snapshot import EventContext
from synapse.events.validator import EventValidator
@@ -1060,20 +1060,11 @@ class EventCreationHandler:
SynapseError if the event is invalid.
"""
- relation = event.content.get("m.relates_to")
+ relation = relation_from_event(event)
if not relation:
return
- relation_type = relation.get("rel_type")
- if not relation_type:
- return
-
- # Ensure the parent is real.
- relates_to = relation.get("event_id")
- if not relates_to:
- return
-
- parent_event = await self.store.get_event(relates_to, allow_none=True)
+ parent_event = await self.store.get_event(relation.parent_id, allow_none=True)
if parent_event:
# And in the same room.
if parent_event.room_id != event.room_id:
@@ -1082,28 +1073,31 @@ class EventCreationHandler:
else:
# There must be some reason that the client knows the event exists,
# see if there are existing relations. If so, assume everything is fine.
- if not await self.store.event_is_target_of_relation(relates_to):
+ if not await self.store.event_is_target_of_relation(relation.parent_id):
# Otherwise, the client can't know about the parent event!
raise SynapseError(400, "Can't send relation to unknown event")
# If this event is an annotation then we check that that the sender
# can't annotate the same way twice (e.g. stops users from liking an
# event multiple times).
- if relation_type == RelationTypes.ANNOTATION:
- aggregation_key = relation["key"]
+ if relation.rel_type == RelationTypes.ANNOTATION:
+ aggregation_key = relation.aggregation_key
+
+ if aggregation_key is None:
+ raise SynapseError(400, "Missing aggregation key")
if len(aggregation_key) > 500:
raise SynapseError(400, "Aggregation key is too long")
already_exists = await self.store.has_user_annotated_event(
- relates_to, event.type, aggregation_key, event.sender
+ relation.parent_id, event.type, aggregation_key, event.sender
)
if already_exists:
raise SynapseError(400, "Can't send same reaction twice")
# Don't attempt to start a thread if the parent event is a relation.
- elif relation_type == RelationTypes.THREAD:
- if await self.store.event_includes_relation(relates_to):
+ elif relation.rel_type == RelationTypes.THREAD:
+ if await self.store.event_includes_relation(relation.parent_id):
raise SynapseError(
400, "Cannot start threads from an event with a relation"
)
diff --git a/synapse/handlers/relations.py b/synapse/handlers/relations.py
index c2754ec918..ab7e54857d 100644
--- a/synapse/handlers/relations.py
+++ b/synapse/handlers/relations.py
@@ -11,7 +11,6 @@
# 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 collections.abc
import logging
from typing import (
TYPE_CHECKING,
@@ -28,7 +27,7 @@ import attr
from synapse.api.constants import RelationTypes
from synapse.api.errors import SynapseError
-from synapse.events import EventBase
+from synapse.events import EventBase, relation_from_event
from synapse.storage.databases.main.relations import _RelatedEvent
from synapse.types import JsonDict, Requester, StreamToken, UserID
from synapse.visibility import filter_events_for_client
@@ -373,20 +372,21 @@ class RelationsHandler:
if event.is_state():
continue
- relates_to = event.content.get("m.relates_to")
- relation_type = None
- if isinstance(relates_to, collections.abc.Mapping):
- relation_type = relates_to.get("rel_type")
+ relates_to = relation_from_event(event)
+ if relates_to:
# An event which is a replacement (ie edit) or annotation (ie,
# reaction) may not have any other event related to it.
- if relation_type in (RelationTypes.ANNOTATION, RelationTypes.REPLACE):
+ if relates_to.rel_type in (
+ RelationTypes.ANNOTATION,
+ RelationTypes.REPLACE,
+ ):
continue
+ # Track the event's relation information for later.
+ relations_by_id[event.event_id] = relates_to.rel_type
+
# The event should get bundled aggregations.
events_by_id[event.event_id] = event
- # Track the event's relation information for later.
- if isinstance(relation_type, str):
- relations_by_id[event.event_id] = relation_type
# event ID -> bundled aggregation in non-serialized form.
results: Dict[str, BundledAggregations] = {}
|