Skip to main content

tuwunel_service/appservice/
append.rs

1use 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/// Called by timeline::append() after accepting new PDU.
14#[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}