@ -165,43 +165,69 @@ class ReceiptEventSource(EventSource[int, JsonDict]):
self . config = hs . config
self . config = hs . config
@staticmethod
@staticmethod
def filter_out_private ( events : List [ JsonDict ] , user_id : str ) - > List [ JsonDict ] :
def filter_out_private_receipts (
rooms : List [ JsonDict ] , user_id : str
) - > List [ JsonDict ] :
"""
"""
This method takes in what is returned by
Filters a list of serialized receipts ( as returned by / sync and / initialSync )
get_linearized_receipts_for_rooms ( ) and goes through read receipts
and removes private read receipts of other users .
filtering out m . read . private receipts if they were not sent by the
current user .
"""
visible_events = [ ]
# filter out private receipts the user shouldn't see
This operates on the return value of get_linearized_receipts_for_rooms ( ) ,
for event in events :
which is wrapped in a cache . Care must be taken to ensure that the input
content = event . get ( " content " , { } )
values are not modified .
new_event = event . copy ( )
new_event [ " content " ] = { }
for event_id , event_content in content . items ( ) :
Args :
receipt_event = { }
rooms : A list of mappings , each mapping has a ` content ` field , which
for receipt_type , receipt_content in event_content . items ( ) :
is a map of event ID - > receipt type - > user ID - > receipt information .
if receipt_type == ReceiptTypes . READ_PRIVATE :
user_rr = receipt_content . get ( user_id , None )
if user_rr :
receipt_event [ ReceiptTypes . READ_PRIVATE ] = {
user_id : user_rr . copy ( )
}
else :
receipt_event [ receipt_type ] = receipt_content . copy ( )
# Only include the receipt event if it is non-empty.
if receipt_event :
new_event [ " content " ] [ event_id ] = receipt_event
# Append new_event to visible_events unless empty
Returns :
if len ( new_event [ " content " ] . keys ( ) ) > 0 :
The same as rooms , but filtered .
visible_events . append ( new_event )
"""
return visible_events
result = [ ]
# Iterate through each room's receipt content.
for room in rooms :
# The receipt content with other user's private read receipts removed.
content = { }
# Iterate over each event ID / receipts for that event.
for event_id , orig_event_content in room . get ( " content " , { } ) . items ( ) :
event_content = orig_event_content
# If there are private read receipts, additional logic is necessary.
if ReceiptTypes . READ_PRIVATE in event_content :
# Make a copy without private read receipts to avoid leaking
# other user's private read receipts..
event_content = {
receipt_type : receipt_value
for receipt_type , receipt_value in event_content . items ( )
if receipt_type != ReceiptTypes . READ_PRIVATE
}
# Copy the current user's private read receipt from the
# original content, if it exists.
user_private_read_receipt = orig_event_content [
ReceiptTypes . READ_PRIVATE
] . get ( user_id , None )
if user_private_read_receipt :
event_content [ ReceiptTypes . READ_PRIVATE ] = {
user_id : user_private_read_receipt
}
# Include the event if there is at least one non-private read
# receipt or the current user has a private read receipt.
if event_content :
content [ event_id ] = event_content
# Include the event if there is at least one non-private read receipt
# or the current user has a private read receipt.
if content :
# Build a new event to avoid mutating the cache.
new_room = { k : v for k , v in room . items ( ) if k != " content " }
new_room [ " content " ] = content
result . append ( new_room )
return result
async def get_new_events (
async def get_new_events (
self ,
self ,
@ -223,7 +249,9 @@ class ReceiptEventSource(EventSource[int, JsonDict]):
)
)
if self . config . experimental . msc2285_enabled :
if self . config . experimental . msc2285_enabled :
events = ReceiptEventSource . filter_out_private ( events , user . to_string ( ) )
events = ReceiptEventSource . filter_out_private_receipts (
events , user . to_string ( )
)
return events , to_key
return events , to_key