adminroom: simplify codeblock checks
Signed-off-by: strawberry <strawberry@puppygock.gay>
This commit is contained in:
parent
14a3471fcb
commit
0e7c3cb338
4 changed files with 306 additions and 299 deletions
|
@ -3,26 +3,26 @@ use ruma::{api::appservice::Registration, events::room::message::RoomMessageEven
|
||||||
use crate::{escape_html, services, Result};
|
use crate::{escape_html, services, Result};
|
||||||
|
|
||||||
pub(crate) async fn register(body: Vec<&str>) -> Result<RoomMessageEventContent> {
|
pub(crate) async fn register(body: Vec<&str>) -> Result<RoomMessageEventContent> {
|
||||||
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_or(&"").trim() != "```" {
|
||||||
let appservice_config = body[1..body.len().checked_sub(1).unwrap()].join("\n");
|
return Ok(RoomMessageEventContent::text_plain(
|
||||||
let parsed_config = serde_yaml::from_str::<Registration>(&appservice_config);
|
|
||||||
match parsed_config {
|
|
||||||
Ok(yaml) => match services().appservice.register_appservice(yaml).await {
|
|
||||||
Ok(id) => Ok(RoomMessageEventContent::text_plain(format!(
|
|
||||||
"Appservice registered with ID: {id}."
|
|
||||||
))),
|
|
||||||
Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
|
||||||
"Failed to register appservice: {e}"
|
|
||||||
))),
|
|
||||||
},
|
|
||||||
Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
|
||||||
"Could not parse appservice config: {e}"
|
|
||||||
))),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Ok(RoomMessageEventContent::text_plain(
|
|
||||||
"Expected code block in command body. Add --help for details.",
|
"Expected code block in command body. Add --help for details.",
|
||||||
))
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let appservice_config = body[1..body.len().checked_sub(1).unwrap()].join("\n");
|
||||||
|
let parsed_config = serde_yaml::from_str::<Registration>(&appservice_config);
|
||||||
|
match parsed_config {
|
||||||
|
Ok(yaml) => match services().appservice.register_appservice(yaml).await {
|
||||||
|
Ok(id) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||||
|
"Appservice registered with ID: {id}."
|
||||||
|
))),
|
||||||
|
Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||||
|
"Failed to register appservice: {e}"
|
||||||
|
))),
|
||||||
|
},
|
||||||
|
Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||||
|
"Could not parse appservice config: {e}"
|
||||||
|
))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,28 +43,30 @@ pub(crate) async fn get_auth_chain(_body: Vec<&str>, event_id: Box<EventId>) ->
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn parse_pdu(body: Vec<&str>) -> Result<RoomMessageEventContent> {
|
pub(crate) async fn parse_pdu(body: Vec<&str>) -> Result<RoomMessageEventContent> {
|
||||||
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_or(&"").trim() != "```" {
|
||||||
let string = body[1..body.len() - 1].join("\n");
|
return Ok(RoomMessageEventContent::text_plain(
|
||||||
match serde_json::from_str(&string) {
|
"Expected code block in command body. Add --help for details.",
|
||||||
Ok(value) => match ruma::signatures::reference_hash(&value, &RoomVersionId::V6) {
|
));
|
||||||
Ok(hash) => {
|
}
|
||||||
let event_id = EventId::parse(format!("${hash}"));
|
|
||||||
|
|
||||||
match serde_json::from_value::<PduEvent>(serde_json::to_value(value).expect("value is json")) {
|
let string = body[1..body.len() - 1].join("\n");
|
||||||
Ok(pdu) => Ok(RoomMessageEventContent::text_plain(format!("EventId: {event_id:?}\n{pdu:#?}"))),
|
match serde_json::from_str(&string) {
|
||||||
Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
Ok(value) => match ruma::signatures::reference_hash(&value, &RoomVersionId::V6) {
|
||||||
"EventId: {event_id:?}\nCould not parse event: {e}"
|
Ok(hash) => {
|
||||||
))),
|
let event_id = EventId::parse(format!("${hash}"));
|
||||||
}
|
|
||||||
},
|
match serde_json::from_value::<PduEvent>(serde_json::to_value(value).expect("value is json")) {
|
||||||
Err(e) => Ok(RoomMessageEventContent::text_plain(format!("Could not parse PDU JSON: {e:?}"))),
|
Ok(pdu) => Ok(RoomMessageEventContent::text_plain(format!("EventId: {event_id:?}\n{pdu:#?}"))),
|
||||||
|
Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||||
|
"EventId: {event_id:?}\nCould not parse event: {e}"
|
||||||
|
))),
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
Err(e) => Ok(RoomMessageEventContent::text_plain(format!("Could not parse PDU JSON: {e:?}"))),
|
||||||
"Invalid json in command body: {e}"
|
},
|
||||||
))),
|
Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||||
}
|
"Invalid json in command body: {e}"
|
||||||
} else {
|
))),
|
||||||
Ok(RoomMessageEventContent::text_plain("Expected code block in command body."))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,33 +119,40 @@ pub(crate) async fn get_remote_pdu_list(
|
||||||
|
|
||||||
if server == services().globals.server_name() {
|
if server == services().globals.server_name() {
|
||||||
return Ok(RoomMessageEventContent::text_plain(
|
return Ok(RoomMessageEventContent::text_plain(
|
||||||
"Not allowed to send federation requests to ourselves. Please use `get-pdu` for fetching local PDUs.",
|
"Not allowed to send federation requests to ourselves. Please use `get-pdu` for fetching local PDUs from \
|
||||||
|
the database.",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
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_or(&"").trim() != "```" {
|
||||||
let list = body
|
return Ok(RoomMessageEventContent::text_plain(
|
||||||
.clone()
|
"Expected code block in command body. Add --help for details.",
|
||||||
.drain(1..body.len().checked_sub(1).unwrap())
|
));
|
||||||
.filter_map(|pdu| EventId::parse(pdu).ok())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
for pdu in list {
|
|
||||||
if force {
|
|
||||||
if let Err(e) = get_remote_pdu(Vec::new(), Box::from(pdu), server.clone()).await {
|
|
||||||
warn!(%e, "Failed to get remote PDU, ignoring error");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
get_remote_pdu(Vec::new(), Box::from(pdu), server.clone()).await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(RoomMessageEventContent::text_plain("Fetched list of remote PDUs."));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(RoomMessageEventContent::text_plain(
|
let list = body
|
||||||
"Expected code block in command body. Add --help for details.",
|
.clone()
|
||||||
))
|
.drain(1..body.len().checked_sub(1).unwrap())
|
||||||
|
.filter_map(|pdu| EventId::parse(pdu).ok())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
for pdu in list {
|
||||||
|
if force {
|
||||||
|
if let Err(e) = get_remote_pdu(Vec::new(), Box::from(pdu), server.clone()).await {
|
||||||
|
services()
|
||||||
|
.admin
|
||||||
|
.send_message(RoomMessageEventContent::text_plain(format!(
|
||||||
|
"Failed to get remote PDU, ignoring error: {e}"
|
||||||
|
)))
|
||||||
|
.await;
|
||||||
|
warn!(%e, "Failed to get remote PDU, ignoring error");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
get_remote_pdu(Vec::new(), Box::from(pdu), server.clone()).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(RoomMessageEventContent::text_plain("Fetched list of remote PDUs."))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn get_remote_pdu(
|
pub(crate) async fn get_remote_pdu(
|
||||||
|
@ -384,55 +393,55 @@ pub(crate) async fn change_log_level(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn sign_json(body: Vec<&str>) -> Result<RoomMessageEventContent> {
|
pub(crate) async fn sign_json(body: Vec<&str>) -> Result<RoomMessageEventContent> {
|
||||||
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_or(&"").trim() != "```" {
|
||||||
let string = body[1..body.len().checked_sub(1).unwrap()].join("\n");
|
return Ok(RoomMessageEventContent::text_plain(
|
||||||
match serde_json::from_str(&string) {
|
|
||||||
Ok(mut value) => {
|
|
||||||
ruma::signatures::sign_json(
|
|
||||||
services().globals.server_name().as_str(),
|
|
||||||
services().globals.keypair(),
|
|
||||||
&mut value,
|
|
||||||
)
|
|
||||||
.expect("our request json is what ruma expects");
|
|
||||||
let json_text = serde_json::to_string_pretty(&value).expect("canonical json is valid json");
|
|
||||||
Ok(RoomMessageEventContent::text_plain(json_text))
|
|
||||||
},
|
|
||||||
Err(e) => Ok(RoomMessageEventContent::text_plain(format!("Invalid json: {e}"))),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Ok(RoomMessageEventContent::text_plain(
|
|
||||||
"Expected code block in command body. Add --help for details.",
|
"Expected code block in command body. Add --help for details.",
|
||||||
))
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let string = body[1..body.len().checked_sub(1).unwrap()].join("\n");
|
||||||
|
match serde_json::from_str(&string) {
|
||||||
|
Ok(mut value) => {
|
||||||
|
ruma::signatures::sign_json(
|
||||||
|
services().globals.server_name().as_str(),
|
||||||
|
services().globals.keypair(),
|
||||||
|
&mut value,
|
||||||
|
)
|
||||||
|
.expect("our request json is what ruma expects");
|
||||||
|
let json_text = serde_json::to_string_pretty(&value).expect("canonical json is valid json");
|
||||||
|
Ok(RoomMessageEventContent::text_plain(json_text))
|
||||||
|
},
|
||||||
|
Err(e) => Ok(RoomMessageEventContent::text_plain(format!("Invalid json: {e}"))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn verify_json(body: Vec<&str>) -> Result<RoomMessageEventContent> {
|
pub(crate) async fn verify_json(body: Vec<&str>) -> Result<RoomMessageEventContent> {
|
||||||
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_or(&"").trim() != "```" {
|
||||||
let string = body[1..body.len().checked_sub(1).unwrap()].join("\n");
|
return Ok(RoomMessageEventContent::text_plain(
|
||||||
match serde_json::from_str(&string) {
|
|
||||||
Ok(value) => {
|
|
||||||
let pub_key_map = RwLock::new(BTreeMap::new());
|
|
||||||
|
|
||||||
services()
|
|
||||||
.rooms
|
|
||||||
.event_handler
|
|
||||||
.fetch_required_signing_keys([&value], &pub_key_map)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let pub_key_map = pub_key_map.read().await;
|
|
||||||
match ruma::signatures::verify_json(&pub_key_map, &value) {
|
|
||||||
Ok(()) => Ok(RoomMessageEventContent::text_plain("Signature correct")),
|
|
||||||
Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
|
||||||
"Signature verification failed: {e}"
|
|
||||||
))),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(e) => Ok(RoomMessageEventContent::text_plain(format!("Invalid json: {e}"))),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Ok(RoomMessageEventContent::text_plain(
|
|
||||||
"Expected code block in command body. Add --help for details.",
|
"Expected code block in command body. Add --help for details.",
|
||||||
))
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let string = body[1..body.len().checked_sub(1).unwrap()].join("\n");
|
||||||
|
match serde_json::from_str(&string) {
|
||||||
|
Ok(value) => {
|
||||||
|
let pub_key_map = RwLock::new(BTreeMap::new());
|
||||||
|
|
||||||
|
services()
|
||||||
|
.rooms
|
||||||
|
.event_handler
|
||||||
|
.fetch_required_signing_keys([&value], &pub_key_map)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let pub_key_map = pub_key_map.read().await;
|
||||||
|
match ruma::signatures::verify_json(&pub_key_map, &value) {
|
||||||
|
Ok(()) => Ok(RoomMessageEventContent::text_plain("Signature correct")),
|
||||||
|
Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||||
|
"Signature verification failed: {e}"
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => Ok(RoomMessageEventContent::text_plain(format!("Invalid json: {e}"))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -138,30 +138,30 @@ pub(crate) async fn delete(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn delete_list(body: Vec<&str>) -> Result<RoomMessageEventContent> {
|
pub(crate) async fn delete_list(body: Vec<&str>) -> Result<RoomMessageEventContent> {
|
||||||
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_or(&"").trim() != "```" {
|
||||||
let mxc_list = body
|
return Ok(RoomMessageEventContent::text_plain(
|
||||||
.clone()
|
"Expected code block in command body. Add --help for details.",
|
||||||
.drain(1..body.len().checked_sub(1).unwrap())
|
));
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let mut mxc_deletion_count: usize = 0;
|
|
||||||
|
|
||||||
for mxc in mxc_list {
|
|
||||||
debug!("Deleting MXC {mxc} in bulk");
|
|
||||||
services().media.delete(mxc.to_owned()).await?;
|
|
||||||
mxc_deletion_count = mxc_deletion_count
|
|
||||||
.checked_add(1)
|
|
||||||
.expect("mxc_deletion_count should not get this high");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
|
||||||
"Finished bulk MXC deletion, deleted {mxc_deletion_count} total MXCs from our database and the filesystem.",
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(RoomMessageEventContent::text_plain(
|
let mxc_list = body
|
||||||
"Expected code block in command body. Add --help for details.",
|
.clone()
|
||||||
))
|
.drain(1..body.len().checked_sub(1).unwrap())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let mut mxc_deletion_count: usize = 0;
|
||||||
|
|
||||||
|
for mxc in mxc_list {
|
||||||
|
debug!("Deleting MXC {mxc} in bulk");
|
||||||
|
services().media.delete(mxc.to_owned()).await?;
|
||||||
|
mxc_deletion_count = mxc_deletion_count
|
||||||
|
.checked_add(1)
|
||||||
|
.expect("mxc_deletion_count should not get this high");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(RoomMessageEventContent::text_plain(format!(
|
||||||
|
"Finished bulk MXC deletion, deleted {mxc_deletion_count} total MXCs from our database and the filesystem.",
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn delete_past_remote_media(
|
pub(crate) async fn delete_past_remote_media(
|
||||||
|
|
|
@ -187,135 +187,137 @@ async fn ban_room(
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn ban_list_of_rooms(body: Vec<&str>, force: bool, disable_federation: bool) -> Result<RoomMessageEventContent> {
|
async fn ban_list_of_rooms(body: Vec<&str>, force: bool, disable_federation: bool) -> Result<RoomMessageEventContent> {
|
||||||
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_or(&"").trim() != "```" {
|
||||||
let rooms_s = body.clone().drain(1..body.len() - 1).collect::<Vec<_>>();
|
return Ok(RoomMessageEventContent::text_plain(
|
||||||
|
"Expected code block in command body. Add --help for details.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
let admin_room_alias: Box<RoomAliasId> = format!("#admins:{}", services().globals.server_name())
|
let rooms_s = body.clone().drain(1..body.len() - 1).collect::<Vec<_>>();
|
||||||
.try_into()
|
|
||||||
.expect("#admins:server_name is a valid alias name");
|
|
||||||
|
|
||||||
let mut room_ban_count: usize = 0;
|
let admin_room_alias: Box<RoomAliasId> = format!("#admins:{}", services().globals.server_name())
|
||||||
let mut room_ids: Vec<OwnedRoomId> = Vec::new();
|
.try_into()
|
||||||
|
.expect("#admins:server_name is a valid alias name");
|
||||||
|
|
||||||
for &room in &rooms_s {
|
let mut room_ban_count: usize = 0;
|
||||||
match <&RoomOrAliasId>::try_from(room) {
|
let mut room_ids: Vec<OwnedRoomId> = Vec::new();
|
||||||
Ok(room_alias_or_id) => {
|
|
||||||
if let Some(admin_room_id) = Service::get_admin_room().await? {
|
|
||||||
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");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if room_alias_or_id.is_room_id() {
|
for &room in &rooms_s {
|
||||||
let room_id = match RoomId::parse(room_alias_or_id) {
|
match <&RoomOrAliasId>::try_from(room) {
|
||||||
Ok(room_id) => room_id,
|
Ok(room_alias_or_id) => {
|
||||||
Err(e) => {
|
if let Some(admin_room_id) = Service::get_admin_room().await? {
|
||||||
if force {
|
if room.to_owned().eq(&admin_room_id) || room.to_owned().eq(&admin_room_alias) {
|
||||||
// ignore rooms we failed to parse if we're force banning
|
info!("User specified admin room in bulk ban list, ignoring");
|
||||||
warn!(
|
|
||||||
"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, None).await {
|
|
||||||
Ok(response) => {
|
|
||||||
debug!(
|
|
||||||
"Got federation response fetching room ID for room {room}: {:?}",
|
|
||||||
response
|
|
||||||
);
|
|
||||||
response.room_id
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
// don't fail if force blocking
|
|
||||||
if force {
|
|
||||||
warn!("Failed to resolve room alias {room} to a room ID: {e}");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
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) => {
|
|
||||||
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
if room_alias_or_id.is_room_id() {
|
||||||
"{room} is not a valid room ID or room alias, please fix the list and try again: {e}"
|
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
|
||||||
|
warn!(
|
||||||
|
"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, None).await {
|
||||||
|
Ok(response) => {
|
||||||
|
debug!(
|
||||||
|
"Got federation response fetching room ID for room {room}: {:?}",
|
||||||
|
response
|
||||||
|
);
|
||||||
|
response.room_id
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
// don't fail if force blocking
|
||||||
|
if force {
|
||||||
|
warn!("Failed to resolve room alias {room} to a room ID: {e}");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) => {
|
||||||
|
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}"
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for room_id in room_ids {
|
||||||
|
if services().rooms.metadata.ban_room(&room_id, true).is_ok() {
|
||||||
|
debug!("Banned {room_id} successfully");
|
||||||
|
room_ban_count = room_ban_count.saturating_add(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for room_id in room_ids {
|
debug!("Making all users leave the room {}", &room_id);
|
||||||
if services().rooms.metadata.ban_room(&room_id, true).is_ok() {
|
if force {
|
||||||
debug!("Banned {room_id} successfully");
|
for local_user in services()
|
||||||
room_ban_count = room_ban_count.saturating_add(1);
|
.rooms
|
||||||
}
|
.state_cache
|
||||||
|
.room_members(&room_id)
|
||||||
debug!("Making all users leave the room {}", &room_id);
|
.filter_map(|user| {
|
||||||
if force {
|
user.ok().filter(|local_user| {
|
||||||
for local_user in services()
|
local_user.server_name() == services().globals.server_name()
|
||||||
.rooms
|
|
||||||
.state_cache
|
|
||||||
.room_members(&room_id)
|
|
||||||
.filter_map(|user| {
|
|
||||||
user.ok().filter(|local_user| {
|
|
||||||
local_user.server_name() == services().globals.server_name()
|
|
||||||
// additional wrapped check here is to avoid adding remote users
|
// additional wrapped check here is to avoid adding remote users
|
||||||
// who are in the admin room to the list of local users (would fail auth check)
|
// who are in the admin room to the list of local users (would fail auth check)
|
||||||
&& (local_user.server_name()
|
&& (local_user.server_name()
|
||||||
|
@ -324,31 +326,31 @@ async fn ban_list_of_rooms(body: Vec<&str>, force: bool, disable_federation: boo
|
||||||
.users
|
.users
|
||||||
.is_admin(local_user)
|
.is_admin(local_user)
|
||||||
.unwrap_or(true)) // since this is a
|
.unwrap_or(true)) // since this is a
|
||||||
// force operation,
|
// force operation,
|
||||||
// assume user is
|
// assume user is
|
||||||
// an admin if
|
// an admin if
|
||||||
// somehow this
|
// somehow this
|
||||||
// fails
|
// fails
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.collect::<Vec<OwnedUserId>>()
|
})
|
||||||
{
|
.collect::<Vec<OwnedUserId>>()
|
||||||
debug!(
|
{
|
||||||
"Attempting leave for user {} in room {} (forced, ignoring all errors, evicting admins too)",
|
debug!(
|
||||||
&local_user, room_id
|
"Attempting leave for user {} in room {} (forced, ignoring all errors, evicting admins too)",
|
||||||
);
|
&local_user, room_id
|
||||||
if let Err(e) = leave_room(&local_user, &room_id, None).await {
|
);
|
||||||
warn!(%e, "Failed to leave room");
|
if let Err(e) = leave_room(&local_user, &room_id, None).await {
|
||||||
}
|
warn!(%e, "Failed to leave room");
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
for local_user in services()
|
} else {
|
||||||
.rooms
|
for local_user in services()
|
||||||
.state_cache
|
.rooms
|
||||||
.room_members(&room_id)
|
.state_cache
|
||||||
.filter_map(|user| {
|
.room_members(&room_id)
|
||||||
user.ok().filter(|local_user| {
|
.filter_map(|user| {
|
||||||
local_user.server_name() == services().globals.server_name()
|
user.ok().filter(|local_user| {
|
||||||
|
local_user.server_name() == services().globals.server_name()
|
||||||
// additional wrapped check here is to avoid adding remote users
|
// additional wrapped check here is to avoid adding remote users
|
||||||
// who are in the admin room to the list of local users (would fail auth check)
|
// who are in the admin room to the list of local users (would fail auth check)
|
||||||
&& (local_user.server_name()
|
&& (local_user.server_name()
|
||||||
|
@ -357,45 +359,41 @@ async fn ban_list_of_rooms(body: Vec<&str>, force: bool, disable_federation: boo
|
||||||
.users
|
.users
|
||||||
.is_admin(local_user)
|
.is_admin(local_user)
|
||||||
.unwrap_or(false))
|
.unwrap_or(false))
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.collect::<Vec<OwnedUserId>>()
|
})
|
||||||
{
|
.collect::<Vec<OwnedUserId>>()
|
||||||
debug!("Attempting leave for user {} in room {}", &local_user, &room_id);
|
{
|
||||||
if let Err(e) = leave_room(&local_user, &room_id, None).await {
|
debug!("Attempting leave for user {} in room {}", &local_user, &room_id);
|
||||||
error!(
|
if let Err(e) = leave_room(&local_user, &room_id, None).await {
|
||||||
"Error attempting to make local user {} leave room {} during bulk room banning: {}",
|
error!(
|
||||||
&local_user, &room_id, e
|
"Error attempting to make local user {} leave room {} during bulk room banning: {}",
|
||||||
);
|
&local_user, &room_id, e
|
||||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
);
|
||||||
"Error attempting to make local user {} leave room {} during room banning (room is still \
|
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||||
banned but not removing any more users and not banning any more rooms): {}\nIf you would \
|
"Error attempting to make local user {} leave room {} during room banning (room is still \
|
||||||
like to ignore errors, use --force",
|
banned but not removing any more users and not banning any more rooms): {}\nIf you would \
|
||||||
&local_user, &room_id, e
|
like to ignore errors, use --force",
|
||||||
)));
|
&local_user, &room_id, e
|
||||||
}
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if disable_federation {
|
|
||||||
services().rooms.metadata.disable_room(&room_id, true)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if disable_federation {
|
if disable_federation {
|
||||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
services().rooms.metadata.disable_room(&room_id, true)?;
|
||||||
"Finished bulk room ban, banned {room_ban_count} total rooms, evicted all users, and disabled \
|
|
||||||
incoming federation with the room."
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
|
||||||
"Finished bulk room ban, banned {room_ban_count} total rooms and evicted all users."
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(RoomMessageEventContent::text_plain(
|
if disable_federation {
|
||||||
"Expected code block in command body. Add --help for details.",
|
Ok(RoomMessageEventContent::text_plain(format!(
|
||||||
))
|
"Finished bulk room ban, banned {room_ban_count} total rooms, evicted all users, and disabled incoming \
|
||||||
|
federation with the room."
|
||||||
|
)))
|
||||||
|
} else {
|
||||||
|
Ok(RoomMessageEventContent::text_plain(format!(
|
||||||
|
"Finished bulk room ban, banned {room_ban_count} total rooms and evicted all users."
|
||||||
|
)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn unban_room(
|
async fn unban_room(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue