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};
13use tuwunel_core::Result;
14use tuwunel_service::presence::Ping;
15
16use super::{reset_and_refresh_badge, set_private_marker};
17use crate::{ClientIp, Ruma};
18
19pub(crate) async fn set_read_marker_route(
27 State(services): State<crate::State>,
28 ClientIp(client): ClientIp,
29 body: Ruma<set_read_marker::v3::Request>,
30) -> Result<set_read_marker::v3::Response> {
31 let sender_user = body.sender_user();
32
33 if let Some(event) = &body.fully_read {
34 let fully_read_event = FullyReadEvent {
35 content: FullyReadEventContent { event_id: event.clone() },
36 };
37
38 services
39 .account_data
40 .update(
41 Some(&body.room_id),
42 sender_user,
43 RoomAccountDataEventType::FullyRead,
44 &serde_json::to_value(fully_read_event)?,
45 )
46 .await
47 .ok();
48 }
49
50 let private_advanced = match &body.private_read_receipt {
51 | None => false,
52 | Some(event) =>
53 set_private_marker(
54 &services,
55 &body.room_id,
56 sender_user,
57 event,
58 &ReceiptThread::Unthreaded,
59 )
60 .await?,
61 };
62
63 let public_advanced = match &body.read_receipt {
64 | None => false,
65 | Some(event) => {
66 let receipt_content = BTreeMap::from_iter([(
67 event.to_owned(),
68 BTreeMap::from_iter([(
69 ReceiptType::Read,
70 BTreeMap::from_iter([(sender_user.to_owned(), Receipt {
71 ts: Some(MilliSecondsSinceUnixEpoch::now()),
72 thread: ReceiptThread::Unthreaded,
73 })]),
74 )]),
75 )]);
76
77 let advanced = services
78 .read_receipt
79 .readreceipt_update(sender_user, &body.room_id, &ReceiptEvent {
80 content: ReceiptEventContent(receipt_content),
81 room_id: body.room_id.clone(),
82 })
83 .await;
84
85 let ping = Ping {
86 device_id: body.sender_device.as_deref(),
87 client_ip: Some(client),
88 appservice: body.appservice_info.as_ref(),
89 ..Default::default()
90 };
91
92 services
93 .presence
94 .maybe_ping_presence(sender_user, ping)
95 .await
96 .ok();
97
98 advanced
99 },
100 };
101
102 if private_advanced || public_advanced {
105 reset_and_refresh_badge(
106 &services,
107 sender_user,
108 &body.room_id,
109 &ReceiptThread::Unthreaded,
110 )
111 .await;
112 }
113
114 Ok(set_read_marker::v3::Response {})
115}