tuwunel_service/appservice/
append.rs1use ruma::{UserId, events::TimelineEventType};
2use tuwunel_core::{
3 Result, error, implement,
4 matrix::{
5 event::Event,
6 pdu::{Pdu, RawPduId},
7 },
8 utils::ReadyExt,
9};
10
11use super::RegistrationInfo;
12
13#[implement(super::Service)]
15#[tracing::instrument(name = "append", level = "debug", skip_all)]
16pub(crate) async fn append_pdu(&self, pdu_id: RawPduId, pdu: &Pdu) -> Result {
17 for appservice in self.read().await.values() {
18 self.append_pdu_to(appservice, pdu_id, pdu)
19 .await
20 .inspect_err(|e| {
21 error!(
22 event_id = %pdu.event_id(),
23 appservice = ?appservice.registration.id,
24 "Failed to send PDU to appservice: {e}"
25 );
26 })
27 .ok();
28 }
29
30 Ok(())
31}
32
33#[implement(super::Service)]
34#[tracing::instrument(
35 name = "append_to",
36 level = "debug",
37 skip_all,
38 fields(id = %appservice.registration.id),
39)]
40async fn append_pdu_to(
41 &self,
42 appservice: &RegistrationInfo,
43 pdu_id: RawPduId,
44 pdu: &Pdu,
45) -> Result {
46 if self.should_append_to(appservice, pdu).await {
47 self.services
48 .sending
49 .send_pdu_appservice(appservice.registration.id.clone(), pdu_id)?;
50 }
51
52 Ok(())
53}
54
55#[implement(super::Service)]
56async fn should_append_to(&self, appservice: &RegistrationInfo, pdu: &Pdu) -> bool {
57 if self
58 .services
59 .state_cache
60 .appservice_in_room(pdu.room_id(), appservice)
61 .await
62 {
63 return true;
64 }
65
66 if appservice.is_user_match(pdu.sender()) {
67 return true;
68 }
69
70 if *pdu.kind() == TimelineEventType::RoomMember
71 && pdu
72 .state_key
73 .as_ref()
74 .and_then(|state_key| UserId::parse(state_key.as_str()).ok())
75 .is_some_and(|user_id| appservice.is_user_match(&user_id))
76 {
77 return true;
78 }
79
80 if self
81 .services
82 .alias
83 .local_aliases_for_room(pdu.room_id())
84 .ready_any(|room_alias| appservice.aliases.is_match(room_alias.as_str()))
85 .await
86 {
87 return true;
88 }
89
90 if appservice.rooms.is_match(pdu.room_id().as_str()) {
91 return true;
92 }
93
94 false
95}