tuwunel_api/client/read_marker/
read_markers.rs1use std::collections::BTreeMap;
2
3use axum::extract::State;
4use ruma::{
5 MilliSecondsSinceUnixEpoch,
6 api::client::read_marker::set_read_marker,
7 events::{
8 RoomAccountDataEventType,
9 fully_read::{FullyReadEvent, FullyReadEventContent},
10 receipt::{Receipt, ReceiptEvent, ReceiptEventContent, ReceiptThread, ReceiptType},
11 },
12 presence::PresenceState,
13};
14use tuwunel_core::{Err, PduCount, Result, err};
15
16use crate::{ClientIp, Ruma};
17
18pub(crate) async fn set_read_marker_route(
26 State(services): State<crate::State>,
27 ClientIp(client): ClientIp,
28 body: Ruma<set_read_marker::v3::Request>,
29) -> Result<set_read_marker::v3::Response> {
30 let sender_user = body.sender_user();
31
32 if body.private_read_receipt.is_some() || body.read_receipt.is_some() {
33 services
36 .pusher
37 .reset_notification_counts_for_thread(
38 sender_user,
39 &body.room_id,
40 &ReceiptThread::Unthreaded,
41 )
42 .await;
43 }
44
45 if let Some(event) = &body.fully_read {
46 let fully_read_event = FullyReadEvent {
47 content: FullyReadEventContent { event_id: event.clone() },
48 };
49
50 services
51 .account_data
52 .update(
53 Some(&body.room_id),
54 sender_user,
55 RoomAccountDataEventType::FullyRead,
56 &serde_json::to_value(fully_read_event)?,
57 )
58 .await
59 .ok();
60 }
61
62 if let Some(event) = &body.private_read_receipt {
63 let count = services
64 .timeline
65 .get_pdu_count(event)
66 .await
67 .map_err(|_| err!(Request(NotFound("Event not found."))))?;
68
69 let PduCount::Normal(count) = count else {
70 return Err!(Request(InvalidParam(
71 "Event is a backfilled PDU and cannot be marked as read."
72 )));
73 };
74
75 services
76 .read_receipt
77 .private_read_set(&body.room_id, sender_user, count, &ReceiptThread::Unthreaded)
78 .await;
79 }
80
81 if let Some(event) = &body.read_receipt {
82 let receipt_content = BTreeMap::from_iter([(
83 event.to_owned(),
84 BTreeMap::from_iter([(
85 ReceiptType::Read,
86 BTreeMap::from_iter([(sender_user.to_owned(), Receipt {
87 ts: Some(MilliSecondsSinceUnixEpoch::now()),
88 thread: ReceiptThread::Unthreaded,
89 })]),
90 )]),
91 )]);
92
93 services
94 .read_receipt
95 .readreceipt_update(sender_user, &body.room_id, &ReceiptEvent {
96 content: ReceiptEventContent(receipt_content),
97 room_id: body.room_id.clone(),
98 })
99 .await;
100
101 services
102 .presence
103 .maybe_ping_presence(
104 sender_user,
105 body.sender_device.as_deref(),
106 Some(client),
107 &PresenceState::Online,
108 )
109 .await
110 .ok();
111 }
112
113 Ok(set_read_marker::v3::Response {})
114}