Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit c3d121a

Browse files
committed
Implement changes to MSC2285
Signed-off-by: Šimon Brandner <[email protected]>
1 parent bc2a3db commit c3d121a

File tree

6 files changed

+100
-119
lines changed

6 files changed

+100
-119
lines changed

Diff for: synapse/api/constants.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,5 @@ class GuestAccess:
255255

256256
class ReceiptTypes:
257257
READ: Final = "m.read"
258-
259-
260-
class ReadReceiptEventFields:
261-
MSC2285_HIDDEN: Final = "org.matrix.msc2285.hidden"
258+
READ_PRIVATE: Final = "org.matrix.msc2285.read.private"
259+
FULLY_READ: Final = "m.fully_read"

Diff for: synapse/handlers/receipts.py

+22-29
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import logging
1515
from typing import TYPE_CHECKING, Iterable, List, Optional, Tuple
1616

17-
from synapse.api.constants import ReadReceiptEventFields, ReceiptTypes
17+
from synapse.api.constants import ReceiptTypes
1818
from synapse.appservice import ApplicationService
1919
from synapse.streams import EventSource
2020
from synapse.types import JsonDict, ReadReceipt, UserID, get_domain_from_id
@@ -138,7 +138,7 @@ async def _handle_new_receipts(self, receipts: List[ReadReceipt]) -> bool:
138138
return True
139139

140140
async def received_client_receipt(
141-
self, room_id: str, receipt_type: str, user_id: str, event_id: str, hidden: bool
141+
self, room_id: str, receipt_type: str, user_id: str, event_id: str
142142
) -> None:
143143
"""Called when a client tells us a local user has read up to the given
144144
event_id in the room.
@@ -148,15 +148,16 @@ async def received_client_receipt(
148148
receipt_type=receipt_type,
149149
user_id=user_id,
150150
event_ids=[event_id],
151-
data={"ts": int(self.clock.time_msec()), "hidden": hidden},
151+
data={"ts": int(self.clock.time_msec())},
152152
)
153153

154154
is_new = await self._handle_new_receipts([receipt])
155155
if not is_new:
156156
return
157157

158158
if self.federation_sender and not (
159-
self.hs.config.experimental.msc2285_enabled and hidden
159+
self.hs.config.experimental.msc2285_enabled
160+
and receipt_type == ReceiptTypes.READ_PRIVATE
160161
):
161162
await self.federation_sender.send_read_receipt(receipt)
162163

@@ -178,35 +179,27 @@ def filter_out_hidden(events: List[JsonDict], user_id: str) -> List[JsonDict]:
178179

179180
for event_id in content.keys():
180181
event_content = content.get(event_id, {})
181-
m_read = event_content.get(ReceiptTypes.READ, {})
182182

183-
# If m_read is missing copy over the original event_content as there is nothing to process here
184-
if not m_read:
185-
new_event["content"][event_id] = event_content.copy()
183+
m_read = event_content.get(ReceiptTypes.READ, None)
184+
if m_read:
185+
new_event["content"][event_id] = {ReceiptTypes.READ: m_read}
186186
continue
187187

188-
new_users = {}
189-
for rr_user_id, user_rr in m_read.items():
190-
try:
191-
hidden = user_rr.get("hidden")
192-
except AttributeError:
193-
# Due to https://github.com/matrix-org/synapse/issues/10376
194-
# there are cases where user_rr is a string, in those cases
195-
# we just ignore the read receipt
196-
continue
188+
m_read_private = event_content.get(ReceiptTypes.READ_PRIVATE, None)
189+
if m_read_private:
190+
new_users = {}
191+
for rr_user_id, user_rr in m_read_private.items():
192+
if rr_user_id == user_id:
193+
new_users[rr_user_id] = user_rr.copy()
194+
195+
# Set new users unless empty
196+
if len(new_users.keys()) > 0:
197+
new_event["content"][event_id] = {
198+
ReceiptTypes.READ_PRIVATE: new_users
199+
}
200+
continue
197201

198-
if hidden is not True or rr_user_id == user_id:
199-
new_users[rr_user_id] = user_rr.copy()
200-
# If hidden has a value replace hidden with the correct prefixed key
201-
if hidden is not None:
202-
new_users[rr_user_id].pop("hidden")
203-
new_users[rr_user_id][
204-
ReadReceiptEventFields.MSC2285_HIDDEN
205-
] = hidden
206-
207-
# Set new users unless empty
208-
if len(new_users.keys()) > 0:
209-
new_event["content"][event_id] = {ReceiptTypes.READ: new_users}
202+
new_event["content"][event_id] = event_content
210203

211204
# Append new_event to visible_events unless empty
212205
if len(new_event["content"].keys()) > 0:

Diff for: synapse/rest/client/read_marker.py

+12-14
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@
1515
import logging
1616
from typing import TYPE_CHECKING, Tuple
1717

18-
from synapse.api.constants import ReadReceiptEventFields, ReceiptTypes
19-
from synapse.api.errors import Codes, SynapseError
18+
from synapse.api.constants import ReceiptTypes
2019
from synapse.http.server import HttpServer
2120
from synapse.http.servlet import RestServlet, parse_json_object_from_request
2221
from synapse.http.site import SynapseRequest
@@ -48,27 +47,26 @@ async def on_POST(
4847
await self.presence_handler.bump_presence_active_time(requester.user)
4948

5049
body = parse_json_object_from_request(request)
51-
read_event_id = body.get(ReceiptTypes.READ, None)
52-
hidden = body.get(ReadReceiptEventFields.MSC2285_HIDDEN, False)
53-
54-
if not isinstance(hidden, bool):
55-
raise SynapseError(
56-
400,
57-
"Param %s must be a boolean, if given"
58-
% ReadReceiptEventFields.MSC2285_HIDDEN,
59-
Codes.BAD_JSON,
60-
)
6150

51+
read_event_id = body.get(ReceiptTypes.READ, None)
6252
if read_event_id:
6353
await self.receipts_handler.received_client_receipt(
6454
room_id,
6555
ReceiptTypes.READ,
6656
user_id=requester.user.to_string(),
6757
event_id=read_event_id,
68-
hidden=hidden,
6958
)
7059

71-
read_marker_event_id = body.get("m.fully_read", None)
60+
read_private_event_id = body.get(ReceiptTypes.READ_PRIVATE, None)
61+
if read_private_event_id:
62+
await self.receipts_handler.received_client_receipt(
63+
room_id,
64+
ReceiptTypes.READ_PRIVATE,
65+
user_id=requester.user.to_string(),
66+
event_id=read_private_event_id,
67+
)
68+
69+
read_marker_event_id = body.get(ReceiptTypes.FULLY_READ, None)
7270
if read_marker_event_id:
7371
await self.read_marker_handler.received_client_read_marker(
7472
room_id,

Diff for: synapse/rest/client/receipts.py

+23-28
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,10 @@
1616
import re
1717
from typing import TYPE_CHECKING, Tuple
1818

19-
from synapse.api.constants import ReadReceiptEventFields, ReceiptTypes
20-
from synapse.api.errors import Codes, SynapseError
21-
from synapse.http import get_request_user_agent
19+
from synapse.api.constants import ReceiptTypes
20+
from synapse.api.errors import SynapseError
2221
from synapse.http.server import HttpServer
23-
from synapse.http.servlet import RestServlet, parse_json_object_from_request
22+
from synapse.http.servlet import RestServlet
2423
from synapse.http.site import SynapseRequest
2524
from synapse.types import JsonDict
2625

@@ -46,42 +45,38 @@ def __init__(self, hs: "HomeServer"):
4645
self.hs = hs
4746
self.auth = hs.get_auth()
4847
self.receipts_handler = hs.get_receipts_handler()
48+
self.read_marker_handler = hs.get_read_marker_handler()
4949
self.presence_handler = hs.get_presence_handler()
5050

5151
async def on_POST(
5252
self, request: SynapseRequest, room_id: str, receipt_type: str, event_id: str
5353
) -> Tuple[int, JsonDict]:
5454
requester = await self.auth.get_user_by_req(request)
5555

56-
if receipt_type != ReceiptTypes.READ:
57-
raise SynapseError(400, "Receipt type must be 'm.read'")
58-
59-
# Do not allow older SchildiChat and Element Android clients (prior to Element/1.[012].x) to send an empty body.
60-
user_agent = get_request_user_agent(request)
61-
allow_empty_body = False
62-
if "Android" in user_agent:
63-
if pattern.match(user_agent) or "Riot" in user_agent:
64-
allow_empty_body = True
65-
body = parse_json_object_from_request(request, allow_empty_body)
66-
hidden = body.get(ReadReceiptEventFields.MSC2285_HIDDEN, False)
67-
68-
if not isinstance(hidden, bool):
56+
if receipt_type in [
57+
ReceiptTypes.READ,
58+
ReceiptTypes.READ_PRIVATE,
59+
ReceiptTypes.FULLY_READ,
60+
]:
6961
raise SynapseError(
70-
400,
71-
"Param %s must be a boolean, if given"
72-
% ReadReceiptEventFields.MSC2285_HIDDEN,
73-
Codes.BAD_JSON,
62+
400, "Receipt type must be 'm.read', 'm.read.private' or 'm.fully_read'"
7463
)
7564

7665
await self.presence_handler.bump_presence_active_time(requester.user)
7766

78-
await self.receipts_handler.received_client_receipt(
79-
room_id,
80-
receipt_type,
81-
user_id=requester.user.to_string(),
82-
event_id=event_id,
83-
hidden=hidden,
84-
)
67+
if receipt_type == ReceiptTypes.FULLY_READ:
68+
await self.read_marker_handler.received_client_read_marker(
69+
room_id,
70+
user_id=requester.user.to_string(),
71+
event_id=event_id,
72+
)
73+
else:
74+
await self.receipts_handler.received_client_receipt(
75+
room_id,
76+
receipt_type,
77+
user_id=requester.user.to_string(),
78+
event_id=event_id,
79+
)
8580

8681
return 200, {}
8782

0 commit comments

Comments
 (0)