|
19 | 19 | """ |
20 | 20 |
|
21 | 21 | import logging |
22 | | -from typing import TYPE_CHECKING, Awaitable, Optional, Tuple |
| 22 | +from typing import TYPE_CHECKING, Optional, Tuple |
23 | 23 |
|
24 | | -from synapse.api.constants import EventTypes, RelationTypes |
25 | | -from synapse.api.errors import ShadowBanError, SynapseError |
| 24 | +from synapse.api.constants import RelationTypes |
| 25 | +from synapse.api.errors import SynapseError |
26 | 26 | from synapse.http.server import HttpServer |
27 | | -from synapse.http.servlet import ( |
28 | | - RestServlet, |
29 | | - parse_integer, |
30 | | - parse_json_object_from_request, |
31 | | - parse_string, |
32 | | -) |
| 27 | +from synapse.http.servlet import RestServlet, parse_integer, parse_string |
33 | 28 | from synapse.http.site import SynapseRequest |
34 | | -from synapse.rest.client.transactions import HttpTransactionCache |
| 29 | +from synapse.rest.client._base import client_patterns |
35 | 30 | from synapse.storage.relations import ( |
36 | 31 | AggregationPaginationToken, |
37 | 32 | PaginationChunk, |
38 | 33 | RelationPaginationToken, |
39 | 34 | ) |
40 | 35 | from synapse.types import JsonDict |
41 | | -from synapse.util.stringutils import random_string |
42 | | - |
43 | | -from ._base import client_patterns |
44 | 36 |
|
45 | 37 | if TYPE_CHECKING: |
46 | 38 | from synapse.server import HomeServer |
47 | 39 |
|
48 | 40 | logger = logging.getLogger(__name__) |
49 | 41 |
|
50 | 42 |
|
51 | | -class RelationSendServlet(RestServlet): |
52 | | - """Helper API for sending events that have relation data. |
53 | | -
|
54 | | - Example API shape to send a 👍 reaction to a room: |
55 | | -
|
56 | | - POST /rooms/!foo/send_relation/$bar/m.annotation/m.reaction?key=%F0%9F%91%8D |
57 | | - {} |
58 | | -
|
59 | | - { |
60 | | - "event_id": "$foobar" |
61 | | - } |
62 | | - """ |
63 | | - |
64 | | - PATTERN = ( |
65 | | - "/rooms/(?P<room_id>[^/]*)/send_relation" |
66 | | - "/(?P<parent_id>[^/]*)/(?P<relation_type>[^/]*)/(?P<event_type>[^/]*)" |
67 | | - ) |
68 | | - |
69 | | - def __init__(self, hs: "HomeServer"): |
70 | | - super().__init__() |
71 | | - self.auth = hs.get_auth() |
72 | | - self.event_creation_handler = hs.get_event_creation_handler() |
73 | | - self.txns = HttpTransactionCache(hs) |
74 | | - |
75 | | - def register(self, http_server: HttpServer) -> None: |
76 | | - http_server.register_paths( |
77 | | - "POST", |
78 | | - client_patterns(self.PATTERN + "$", releases=()), |
79 | | - self.on_PUT_or_POST, |
80 | | - self.__class__.__name__, |
81 | | - ) |
82 | | - http_server.register_paths( |
83 | | - "PUT", |
84 | | - client_patterns(self.PATTERN + "/(?P<txn_id>[^/]*)$", releases=()), |
85 | | - self.on_PUT, |
86 | | - self.__class__.__name__, |
87 | | - ) |
88 | | - |
89 | | - def on_PUT( |
90 | | - self, |
91 | | - request: SynapseRequest, |
92 | | - room_id: str, |
93 | | - parent_id: str, |
94 | | - relation_type: str, |
95 | | - event_type: str, |
96 | | - txn_id: Optional[str] = None, |
97 | | - ) -> Awaitable[Tuple[int, JsonDict]]: |
98 | | - return self.txns.fetch_or_execute_request( |
99 | | - request, |
100 | | - self.on_PUT_or_POST, |
101 | | - request, |
102 | | - room_id, |
103 | | - parent_id, |
104 | | - relation_type, |
105 | | - event_type, |
106 | | - txn_id, |
107 | | - ) |
108 | | - |
109 | | - async def on_PUT_or_POST( |
110 | | - self, |
111 | | - request: SynapseRequest, |
112 | | - room_id: str, |
113 | | - parent_id: str, |
114 | | - relation_type: str, |
115 | | - event_type: str, |
116 | | - txn_id: Optional[str] = None, |
117 | | - ) -> Tuple[int, JsonDict]: |
118 | | - requester = await self.auth.get_user_by_req(request, allow_guest=True) |
119 | | - |
120 | | - if event_type == EventTypes.Member: |
121 | | - # Add relations to a membership is meaningless, so we just deny it |
122 | | - # at the CS API rather than trying to handle it correctly. |
123 | | - raise SynapseError(400, "Cannot send member events with relations") |
124 | | - |
125 | | - content = parse_json_object_from_request(request) |
126 | | - |
127 | | - aggregation_key = parse_string(request, "key", encoding="utf-8") |
128 | | - |
129 | | - content["m.relates_to"] = { |
130 | | - "event_id": parent_id, |
131 | | - "rel_type": relation_type, |
132 | | - } |
133 | | - if aggregation_key is not None: |
134 | | - content["m.relates_to"]["key"] = aggregation_key |
135 | | - |
136 | | - event_dict = { |
137 | | - "type": event_type, |
138 | | - "content": content, |
139 | | - "room_id": room_id, |
140 | | - "sender": requester.user.to_string(), |
141 | | - } |
142 | | - |
143 | | - try: |
144 | | - ( |
145 | | - event, |
146 | | - _, |
147 | | - ) = await self.event_creation_handler.create_and_send_nonmember_event( |
148 | | - requester, event_dict=event_dict, txn_id=txn_id |
149 | | - ) |
150 | | - event_id = event.event_id |
151 | | - except ShadowBanError: |
152 | | - event_id = "$" + random_string(43) |
153 | | - |
154 | | - return 200, {"event_id": event_id} |
155 | | - |
156 | | - |
157 | 43 | class RelationPaginationServlet(RestServlet): |
158 | 44 | """API to paginate relations on an event by topological ordering, optionally |
159 | 45 | filtered by relation type and event type. |
@@ -431,7 +317,6 @@ async def on_GET( |
431 | 317 |
|
432 | 318 |
|
433 | 319 | def register_servlets(hs: "HomeServer", http_server: HttpServer) -> None: |
434 | | - RelationSendServlet(hs).register(http_server) |
435 | 320 | RelationPaginationServlet(hs).register(http_server) |
436 | 321 | RelationAggregationPaginationServlet(hs).register(http_server) |
437 | 322 | RelationAggregationGroupPaginationServlet(hs).register(http_server) |
0 commit comments