Send read reciept and typing indicator EDUs to appservices with receive_ephemeral

This commit is contained in:
Jade Ellis 2024-12-18 03:04:39 +00:00 committed by strawberry
parent 5b6ff3869c
commit 3675c941f8
8 changed files with 135 additions and 46 deletions

View file

@ -2,9 +2,10 @@ mod data;
use std::{collections::BTreeMap, sync::Arc};
use conduwuit::{debug, err, warn, PduCount, PduId, RawPduId, Result};
use conduwuit::{debug, err, result::LogErr, warn, PduCount, PduId, RawPduId, Result};
use futures::{try_join, Stream, TryFutureExt};
use ruma::{
api::appservice::event::push_events::v1::EphemeralData,
events::{
receipt::{ReceiptEvent, ReceiptEventContent, Receipts},
AnySyncEphemeralRoomEvent, SyncEphemeralRoomEvent,
@ -48,14 +49,25 @@ impl Service {
&self,
user_id: &UserId,
room_id: &RoomId,
event: &ReceiptEvent,
event: ReceiptEvent,
) {
self.db.readreceipt_update(user_id, room_id, event).await;
self.db.readreceipt_update(user_id, room_id, &event).await;
self.services
.sending
.flush_room(room_id)
.await
.expect("room flush failed");
// update appservices
let edu = EphemeralData::Receipt(event);
let _ = self
.services
.sending
.send_edu_appservice_room(
room_id,
serde_json::to_vec(&edu).expect("Serialized EphemeralData::Receipt"),
)
.await
.log_err();
}
/// Gets the latest private read receipt from the user in the room

View file

@ -7,8 +7,11 @@ use conduwuit::{
};
use futures::StreamExt;
use ruma::{
api::federation::transactions::edu::{Edu, TypingContent},
events::SyncEphemeralRoomEvent,
api::{
appservice::event::push_events::v1::EphemeralData,
federation::transactions::edu::{Edu, TypingContent},
},
events::{typing::TypingEventContent, EphemeralRoomEvent, SyncEphemeralRoomEvent},
OwnedRoomId, OwnedUserId, RoomId, UserId,
};
use tokio::sync::{broadcast, RwLock};
@ -76,6 +79,9 @@ impl Service {
trace!("receiver found what it was looking for and is no longer interested");
}
// update appservices
self.appservice_send(room_id).await?;
// update federation
if self.services.globals.user_is_local(user_id) {
self.federation_send(room_id, user_id, true).await?;
@ -103,7 +109,8 @@ impl Service {
if self.typing_update_sender.send(room_id.to_owned()).is_err() {
trace!("receiver found what it was looking for and is no longer interested");
}
// update appservices
self.appservice_send(room_id).await?;
// update federation
if self.services.globals.user_is_local(user_id) {
self.federation_send(room_id, user_id, false).await?;
@ -157,6 +164,9 @@ impl Service {
trace!("receiver found what it was looking for and is no longer interested");
}
// update appservices
self.appservice_send(room_id).await?;
// update federation
for user in &removable {
if self.services.globals.user_is_local(user) {
@ -180,17 +190,30 @@ impl Service {
.unwrap_or(0))
}
/// Returns a new typing EDU.
pub async fn typings_content(&self, room_id: &RoomId) -> Result<TypingEventContent> {
let room_typing_indicators = self.typing.read().await.get(room_id).cloned();
let Some(typing_indicators) = room_typing_indicators else {
return Ok(TypingEventContent { user_ids: Vec::new() });
};
let user_ids: Vec<_> = typing_indicators.into_keys().collect();
Ok(TypingEventContent { user_ids })
}
/// Returns a new typing EDU.
pub async fn typings_all(
&self,
room_id: &RoomId,
sender_user: &UserId,
) -> Result<SyncEphemeralRoomEvent<ruma::events::typing::TypingEventContent>> {
) -> Result<SyncEphemeralRoomEvent<TypingEventContent>> {
let room_typing_indicators = self.typing.read().await.get(room_id).cloned();
let Some(typing_indicators) = room_typing_indicators else {
return Ok(SyncEphemeralRoomEvent {
content: ruma::events::typing::TypingEventContent { user_ids: Vec::new() },
content: TypingEventContent { user_ids: Vec::new() },
});
};
@ -208,9 +231,7 @@ impl Service {
.collect()
.await;
Ok(SyncEphemeralRoomEvent {
content: ruma::events::typing::TypingEventContent { user_ids },
})
Ok(SyncEphemeralRoomEvent { content: TypingEventContent { user_ids } })
}
async fn federation_send(
@ -237,4 +258,21 @@ impl Service {
Ok(())
}
async fn appservice_send(&self, room_id: &RoomId) -> Result<()> {
let edu = EphemeralData::Typing(EphemeralRoomEvent {
content: self.typings_content(room_id).await?,
room_id: room_id.into(),
});
self.services
.sending
.send_edu_appservice_room(
room_id,
serde_json::to_vec(&edu).expect("Serialized EphemeralData::Typing"),
)
.await?;
Ok(())
}
}