-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Support optionally not sending read receipts to other users/servers #5990
Changes from all commits
aab3f5d
53cf721
27eac52
30f0824
1705265
c4f3e97
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Support a way for clients to not send read receipts to other users/servers. | ||
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -262,6 +262,8 @@ def _on_new_receipts(self, rows): | |||||
# we only want to send on receipts for our own users | ||||||
if not self._is_mine_id(receipt.user_id): | ||||||
continue | ||||||
if receipt.data.get("hidden", False): | ||||||
return # do not send over federation | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we don't want to skip all receipts in the list, aiui:
Suggested change
|
||||||
receipt_info = ReadReceipt( | ||||||
receipt.room_id, | ||||||
receipt.receipt_type, | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -395,7 +395,12 @@ def get_receipts(): | |
) | ||
if not receipts: | ||
receipts = [] | ||
return receipts | ||
|
||
return [ | ||
r | ||
for r in receipts | ||
if not r.data.get("hidden", False) or r.user_id == user_id | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not entirely convinced that this works because I didn't test initialSync. I am hoping to pawn all this imperfect python over to someone else eventually. |
||
] | ||
|
||
presence, receipts, (messages, token) = yield make_deferred_yieldable( | ||
defer.gatherResults( | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -334,6 +334,7 @@ def ephemeral_by_room(self, sync_result_builder, now_token, since_token=None): | |
""" | ||
|
||
sync_config = sync_result_builder.sync_config | ||
user_id = sync_result_builder.sync_config.user.to_string() | ||
|
||
with Measure(self.clock, "ephemeral_by_room"): | ||
typing_key = since_token.typing_key if since_token else "0" | ||
|
@@ -376,7 +377,33 @@ def ephemeral_by_room(self, sync_result_builder, now_token, since_token=None): | |
room_id = event["room_id"] | ||
# exclude room id, as above | ||
event_copy = {k: v for (k, v) in iteritems(event) if k != "room_id"} | ||
ephemeral_by_room.setdefault(room_id, []).append(event_copy) | ||
|
||
# filter out receipts the user shouldn't see | ||
content = event_copy.get("content", {}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've not really managed to grok what this lump of code is doing. If it's just filtering events, shouldn't that be handled in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ideally yes, however there's a comment in a similar area around typing notifications that says the results from that are cached. Didn't want to risk all read receipts being dropped due to a caching issue. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the comment says you shouldn't modify returned event objects, which is true... I don't think there's any reason you can't modify This code feels super-complicated at the moment. |
||
event_ids = content.keys() | ||
reconstructed = event_copy.copy() | ||
reconstructed["content"] = {} # clear old content | ||
for event_id in event_ids: | ||
m_read = content[event_id].get("m.read", None) | ||
if m_read is None: | ||
# clone it now - it's not something we can process | ||
reconstructed["content"][event_id] = content[event_id] | ||
continue | ||
user_ids = m_read.keys() | ||
for rr_user_id in user_ids: | ||
data = m_read[rr_user_id] | ||
hidden = data.get("hidden", False) | ||
if rr_user_id == user_id or not hidden: | ||
# append the key to the reconstructed receipt | ||
new_content = reconstructed["content"] | ||
if new_content.get(event_id, None) is None: | ||
new_content[event_id] = {"m.read": {}} | ||
ev_content = new_content[event_id]["m.read"] | ||
if ev_content.get(rr_user_id, None) is None: | ||
ev_content[rr_user_id] = {} | ||
ev_content[rr_user_id] = data | ||
if len(reconstructed["content"].keys()) > 0: | ||
ephemeral_by_room.setdefault(room_id, []).append(reconstructed) | ||
|
||
return now_token, ephemeral_by_room | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,6 +49,7 @@ def on_POST(self, request, room_id): | |
"m.read", | ||
user_id=requester.user.to_string(), | ||
event_id=read_event_id, | ||
hidden=body.get("m.hidden", False), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should check this is a bool before accepting it |
||
) | ||
|
||
read_marker_event_id = body.get("m.fully_read", None) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,7 +18,7 @@ | |
from twisted.internet import defer | ||
|
||
from synapse.api.errors import SynapseError | ||
from synapse.http.servlet import RestServlet | ||
from synapse.http.servlet import RestServlet, parse_json_object_from_request | ||
|
||
from ._base import client_patterns | ||
|
||
|
@@ -46,10 +46,16 @@ def on_POST(self, request, room_id, receipt_type, event_id): | |
if receipt_type != "m.read": | ||
raise SynapseError(400, "Receipt type must be 'm.read'") | ||
|
||
body = parse_json_object_from_request(request) | ||
|
||
yield self.presence_handler.bump_presence_active_time(requester.user) | ||
|
||
yield self.receipts_handler.received_client_receipt( | ||
room_id, receipt_type, user_id=requester.user.to_string(), event_id=event_id | ||
room_id, | ||
receipt_type, | ||
user_id=requester.user.to_string(), | ||
event_id=event_id, | ||
hidden=body.get("m.hidden", False), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. again, needs a type check |
||
) | ||
|
||
return 200, {} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
link to MSC?