1use std::collections::BTreeMap;
2
3use futures::FutureExt;
4use ruma::{
5 RoomId, RoomVersionId,
6 events::room::{
7 canonical_alias::RoomCanonicalAliasEventContent,
8 create::RoomCreateEventContent,
9 guest_access::{GuestAccess, RoomGuestAccessEventContent},
10 history_visibility::{HistoryVisibility, RoomHistoryVisibilityEventContent},
11 join_rules::{JoinRule, RoomJoinRulesEventContent},
12 member::{MembershipState, RoomMemberEventContent},
13 name::RoomNameEventContent,
14 power_levels::RoomPowerLevelsEventContent,
15 preview_url::RoomPreviewUrlsEventContent,
16 topic::{RoomTopicEventContent, TopicContentBlock},
17 },
18};
19use tuwunel_core::{Result, pdu::PduBuilder};
20
21use crate::Services;
22
23pub async fn create_server_user(services: &Services) -> Result {
28 let server_user = services.globals.server_user.as_ref();
29
30 services
32 .users
33 .create(server_user, None, None)
34 .await?;
35
36 Ok(())
37}
38
39pub async fn create_admin_room(services: &Services) -> Result {
44 let room_id = RoomId::new_v1(services.globals.server_name());
45 let room_version = RoomVersionId::V11;
46
47 let _short_id = services
48 .short
49 .get_or_create_shortroomid(&room_id)
50 .await;
51
52 let state_lock = services.state.mutex.lock(&room_id).await;
53
54 let server_user = services.globals.server_user.as_ref();
56 if !services.users.exists(server_user).await {
57 create_server_user(services).await?;
58 }
59
60 let create_content = {
61 use RoomVersionId::*;
62 match room_version {
63 | V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 | V9 | V10 =>
64 RoomCreateEventContent::new_v1(server_user.into()),
65 | _ => RoomCreateEventContent::new_v11(),
66 }
67 };
68
69 services
71 .timeline
72 .build_and_append_pdu(
73 PduBuilder::state(String::new(), &RoomCreateEventContent {
74 federate: services.config.federate_admin_room,
75 predecessor: None,
76 room_version: room_version.clone(),
77 ..create_content
78 }),
79 server_user,
80 &room_id,
81 &state_lock,
82 )
83 .boxed()
84 .await?;
85
86 services
88 .timeline
89 .build_and_append_pdu(
90 PduBuilder::state(
91 String::from(server_user),
92 &RoomMemberEventContent::new(MembershipState::Join),
93 ),
94 server_user,
95 &room_id,
96 &state_lock,
97 )
98 .boxed()
99 .await?;
100
101 let users = BTreeMap::from_iter([(server_user.into(), 69420.into())]);
103
104 services
105 .timeline
106 .build_and_append_pdu(
107 PduBuilder::state(String::new(), &RoomPowerLevelsEventContent {
108 users,
109 ..Default::default()
110 }),
111 server_user,
112 &room_id,
113 &state_lock,
114 )
115 .boxed()
116 .await?;
117
118 services
120 .timeline
121 .build_and_append_pdu(
122 PduBuilder::state(String::new(), &RoomJoinRulesEventContent::new(JoinRule::Invite)),
123 server_user,
124 &room_id,
125 &state_lock,
126 )
127 .boxed()
128 .await?;
129
130 services
132 .timeline
133 .build_and_append_pdu(
134 PduBuilder::state(
135 String::new(),
136 &RoomHistoryVisibilityEventContent::new(HistoryVisibility::Shared),
137 ),
138 server_user,
139 &room_id,
140 &state_lock,
141 )
142 .boxed()
143 .await?;
144
145 services
147 .timeline
148 .build_and_append_pdu(
149 PduBuilder::state(
150 String::new(),
151 &RoomGuestAccessEventContent::new(GuestAccess::Forbidden),
152 ),
153 server_user,
154 &room_id,
155 &state_lock,
156 )
157 .boxed()
158 .await?;
159
160 let room_name = format!("{} Admin Room", services.config.server_name);
162 services
163 .timeline
164 .build_and_append_pdu(
165 PduBuilder::state(String::new(), &RoomNameEventContent::new(room_name)),
166 server_user,
167 &room_id,
168 &state_lock,
169 )
170 .boxed()
171 .await?;
172
173 services
174 .timeline
175 .build_and_append_pdu(
176 PduBuilder::state(String::new(), &RoomTopicEventContent {
177 topic_block: TopicContentBlock::default(),
178 topic: format!("Manage {} | Run commands prefixed with `!admin` | Run `!admin -h` for help | Documentation: https://matrix-construct.github.io/tuwunel", services.config.server_name),
179 }),
180 server_user,
181 &room_id,
182 &state_lock,
183 )
184 .boxed()
185 .await?;
186
187 let alias = &services.admin.admin_alias;
189
190 services
191 .timeline
192 .build_and_append_pdu(
193 PduBuilder::state(String::new(), &RoomCanonicalAliasEventContent {
194 alias: Some(alias.clone()),
195 alt_aliases: Vec::new(),
196 }),
197 server_user,
198 &room_id,
199 &state_lock,
200 )
201 .boxed()
202 .await?;
203
204 services.alias.set_alias(alias, &room_id)?;
205
206 services
208 .timeline
209 .build_and_append_pdu(
210 PduBuilder::state(String::new(), &RoomPreviewUrlsEventContent { disabled: true }),
211 server_user,
212 &room_id,
213 &state_lock,
214 )
215 .boxed()
216 .await?;
217
218 Ok(())
219}