64 lines
2.1 KiB
Rust
64 lines
2.1 KiB
Rust
use errify::{errify, errify_with};
|
|
use eyre::{bail, Context, ContextCompat};
|
|
use matrix_sdk::{
|
|
ruma::{
|
|
events::room::power_levels::{self, RoomPowerLevelsEventContent},
|
|
OwnedRoomId,
|
|
},
|
|
Client, Room,
|
|
};
|
|
use tracing::debug;
|
|
|
|
use crate::initial_sync;
|
|
|
|
pub async fn run(client: &Client, rooms: &[OwnedRoomId], power_level: u32) -> eyre::Result<()> {
|
|
initial_sync(client).await?;
|
|
for room_id in rooms {
|
|
let Some(room) = client.get_room(room_id) else {
|
|
bail!("could not find room {room_id} in client")
|
|
};
|
|
make_room_read_only(&room, power_level).await?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Perform a Read-Modify-Write to the `m.room.power_levels` event to
|
|
/// effectively make the room read-only.
|
|
///
|
|
/// The following modifications are performed:
|
|
///
|
|
/// - The `event_default` power level is increased to at least `new_min_power_level`.
|
|
/// - The power level for each specified event type in `events` is increased to at least `new_min_power_level`.
|
|
#[errify("failed to make room {room:?} read-only")]
|
|
async fn make_room_read_only(room: &Room, new_min_power_level: u32) -> eyre::Result<()> {
|
|
let power_level_state = room
|
|
.get_state_event_static::<RoomPowerLevelsEventContent>()
|
|
.await
|
|
.context("fetching power level event")?
|
|
.context("there are no power levels in this room")?;
|
|
|
|
debug!("In room {}:", room.room_id());
|
|
|
|
let mut power_levels = power_level_state
|
|
.deserialize()
|
|
.context("could not deserialise power levels")?
|
|
.power_levels();
|
|
|
|
debug!("Original PLs: {power_levels:?}");
|
|
|
|
// Modify the power levels
|
|
power_levels.events_default = power_levels.events_default.max(new_min_power_level.into());
|
|
for event_power_level in power_levels.events.values_mut() {
|
|
*event_power_level = (*event_power_level).max(new_min_power_level.into());
|
|
}
|
|
|
|
debug!("New PLs: {power_levels:?}");
|
|
|
|
// Send the new event
|
|
room.send_state_event(RoomPowerLevelsEventContent::from(power_levels))
|
|
.await
|
|
.context("failed to send power levels")?;
|
|
Ok(())
|
|
}
|