allow ban-list-of-rooms to take room aliases

Signed-off-by: strawberry <strawberry@puppygock.gay>
This commit is contained in:
strawberry 2024-04-15 20:32:52 -04:00 committed by June
parent 59be0b3ddc
commit 404bdd1db5

View file

@ -1,7 +1,9 @@
use std::fmt::Write as _; use std::fmt::Write as _;
use clap::Subcommand; use clap::Subcommand;
use ruma::{events::room::message::RoomMessageEventContent, OwnedUserId, RoomAliasId, RoomId, RoomOrAliasId}; use ruma::{
events::room::message::RoomMessageEventContent, OwnedRoomId, OwnedUserId, RoomAliasId, RoomId, RoomOrAliasId,
};
use tracing::{debug, error, info}; use tracing::{debug, error, info};
use crate::{ use crate::{
@ -37,8 +39,8 @@ pub(crate) enum RoomModerationCommand {
room: Box<RoomOrAliasId>, room: Box<RoomOrAliasId>,
}, },
/// - Bans a list of rooms from a newline delimited codeblock similar to /// - Bans a list of rooms (room IDs and room aliases) from a newline
/// `user deactivate-all` /// delimited codeblock similar to `user deactivate-all`
BanListOfRooms { BanListOfRooms {
#[arg(short, long)] #[arg(short, long)]
/// Evicts admins out of the room and ignores any potential errors when /// Evicts admins out of the room and ignores any potential errors when
@ -236,41 +238,121 @@ pub(crate) async fn process(command: RoomModerationCommand, body: Vec<&str>) ->
if body.len() > 2 && body[0].trim().starts_with("```") && body.last().unwrap().trim() == "```" { if body.len() > 2 && body[0].trim().starts_with("```") && body.last().unwrap().trim() == "```" {
let rooms_s = body.clone().drain(1..body.len() - 1).collect::<Vec<_>>(); let rooms_s = body.clone().drain(1..body.len() - 1).collect::<Vec<_>>();
let mut room_ban_count = 0; let admin_room_alias: Box<RoomAliasId> = format!("#admins:{}", services().globals.server_name())
let mut room_ids: Vec<&RoomId> = Vec::new(); .try_into()
.expect("#admins:server_name is a valid alias name");
for &room_id in &rooms_s { let mut room_ban_count = 0;
match <&RoomId>::try_from(room_id) { let mut room_ids: Vec<OwnedRoomId> = Vec::new();
Ok(owned_room_id) => {
// silently ignore deleting admin room for &room in &rooms_s {
match <&RoomOrAliasId>::try_from(room) {
Ok(room_alias_or_id) => {
if let Some(admin_room_id) = Service::get_admin_room()? { if let Some(admin_room_id) = Service::get_admin_room()? {
if owned_room_id.eq(&admin_room_id) { if room.to_owned().eq(&admin_room_id) || room.to_owned().eq(&admin_room_alias) {
info!("User specified admin room in bulk ban list, ignoring"); info!("User specified admin room in bulk ban list, ignoring");
continue; continue;
} }
} }
room_ids.push(owned_room_id); if room_alias_or_id.is_room_id() {
let room_id = match RoomId::parse(room_alias_or_id) {
Ok(room_id) => room_id,
Err(e) => {
if force {
// ignore rooms we failed to parse if we're force banning
error!(
"Error parsing room \"{room}\" during bulk room banning, ignoring \
error and logging here: {e}"
);
continue;
}
return Ok(RoomMessageEventContent::text_plain(format!(
"{room} is not a valid room ID or room alias, please fix the list and try \
again: {e}"
)));
},
};
room_ids.push(room_id);
}
if room_alias_or_id.is_room_alias_id() {
match RoomAliasId::parse(room_alias_or_id) {
Ok(room_alias) => {
let room_id = if let Some(room_id) =
services().rooms.alias.resolve_local_alias(&room_alias)?
{
room_id
} else {
debug!(
"We don't have this room alias to a room ID locally, attempting to \
fetch room ID over federation"
);
match get_alias_helper(room_alias).await {
Ok(response) => {
debug!(
"Got federation response fetching room ID for room {room}: \
{:?}",
response
);
response.room_id
},
Err(e) => {
if force {
format!(
"Failed to resolve room alias {room} to a room ID: {e}"
);
}
return Ok(RoomMessageEventContent::text_plain(format!(
"Failed to resolve room alias {room} to a room ID: {e}"
)));
},
}
};
room_ids.push(room_id);
},
Err(e) => {
if force {
// ignore rooms we failed to parse if we're force deleting
error!(
"Error parsing room \"{room}\" during bulk room banning, ignoring \
error and logging here: {e}"
);
continue;
}
return Ok(RoomMessageEventContent::text_plain(format!(
"{room} is not a valid room ID or room alias, please fix the list and try \
again: {e}"
)));
},
}
}
}, },
Err(e) => { Err(e) => {
if force { if force {
// ignore rooms we failed to parse if we're force deleting // ignore rooms we failed to parse if we're force deleting
error!( error!(
"Error parsing room ID {room_id} during bulk room banning, ignoring error and \ "Error parsing room \"{room}\" during bulk room banning, ignoring error and \
logging here: {e}" logging here: {e}"
); );
continue; continue;
} }
return Ok(RoomMessageEventContent::text_plain(format!( return Ok(RoomMessageEventContent::text_plain(format!(
"{room_id} is not a valid room ID, please fix the list and try again: {e}" "{room} is not a valid room ID or room alias, please fix the list and try again: {e}"
))); )));
}, },
} }
} }
for room_id in room_ids { for room_id in room_ids {
if services().rooms.metadata.ban_room(room_id, true).is_ok() { if services().rooms.metadata.ban_room(&room_id, true).is_ok() {
debug!("Banned {room_id} successfully"); debug!("Banned {room_id} successfully");
room_ban_count += 1; room_ban_count += 1;
} }
@ -280,7 +362,7 @@ pub(crate) async fn process(command: RoomModerationCommand, body: Vec<&str>) ->
for local_user in services() for local_user in services()
.rooms .rooms
.state_cache .state_cache
.room_members(room_id) .room_members(&room_id)
.filter_map(|user| { .filter_map(|user| {
user.ok().filter(|local_user| { user.ok().filter(|local_user| {
local_user.server_name() == services().globals.server_name() local_user.server_name() == services().globals.server_name()
@ -306,13 +388,13 @@ pub(crate) async fn process(command: RoomModerationCommand, body: Vec<&str>) ->
admins too)", admins too)",
&local_user, room_id &local_user, room_id
); );
_ = leave_room(&local_user, room_id, None).await; _ = leave_room(&local_user, &room_id, None).await;
} }
} else { } else {
for local_user in services() for local_user in services()
.rooms .rooms
.state_cache .state_cache
.room_members(room_id) .room_members(&room_id)
.filter_map(|user| { .filter_map(|user| {
user.ok().filter(|local_user| { user.ok().filter(|local_user| {
local_user.server_name() == services().globals.server_name() local_user.server_name() == services().globals.server_name()
@ -329,7 +411,7 @@ pub(crate) async fn process(command: RoomModerationCommand, body: Vec<&str>) ->
.collect::<Vec<OwnedUserId>>() .collect::<Vec<OwnedUserId>>()
{ {
debug!("Attempting leave for user {} in room {}", &local_user, &room_id); debug!("Attempting leave for user {} in room {}", &local_user, &room_id);
if let Err(e) = leave_room(&local_user, room_id, None).await { if let Err(e) = leave_room(&local_user, &room_id, None).await {
error!( error!(
"Error attempting to make local user {} leave room {} during bulk room banning: {}", "Error attempting to make local user {} leave room {} during bulk room banning: {}",
&local_user, &room_id, e &local_user, &room_id, e
@ -345,7 +427,7 @@ pub(crate) async fn process(command: RoomModerationCommand, body: Vec<&str>) ->
} }
if disable_federation { if disable_federation {
services().rooms.metadata.disable_room(room_id, true)?; services().rooms.metadata.disable_room(&room_id, true)?;
} }
} }