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