diff --git a/src/service/admin/mod.rs b/src/service/admin/mod.rs index 358aa996..5659bc41 100644 --- a/src/service/admin/mod.rs +++ b/src/service/admin/mod.rs @@ -173,6 +173,10 @@ enum RoomCommand { #[command(subcommand)] /// Manage rooms' aliases Alias(RoomAliasCommand), + + #[command(subcommand)] + /// Manage the room directory + Directory(RoomDirectoryCommand), } #[cfg_attr(test, derive(Debug))] @@ -184,10 +188,10 @@ enum RoomAliasCommand { /// Set the alias even if a room is already using it force: bool, - // The room id to set the alias on + /// The room id to set the alias on room_id: Box, - // The alias localpart to use (`alias`, not `#alias:servername.tld`) + /// The alias localpart to use (`alias`, not `#alias:servername.tld`) room_alias_localpart: Box, }, @@ -210,6 +214,26 @@ enum RoomAliasCommand { }, } +#[cfg_attr(test, derive(Debug))] +#[derive(Subcommand)] +enum RoomDirectoryCommand { + /// Publish a room to the room directory + Publish { + /// The room id of the room to publish + room_id: Box, + }, + + /// Unpublish a room to the room directory + Unpublish { + /// The room id of the room to unpublish + room_id: Box, + }, + + /// List rooms that are published + // TODO: is this really necessary? + List, +} + #[cfg_attr(test, derive(Debug))] #[derive(Subcommand)] enum FederationCommand { @@ -735,21 +759,21 @@ impl Service { } AdminCommand::Room(command) => match command { RoomCommand::List => { - let room_ids = services().rooms.metadata.iter_ids(); + let mut rooms = services().rooms.metadata.iter_ids() + .filter_map(|r| r.ok()) + .map(|id| ( + id.clone(), + services().rooms.state_accessor.get_name(&id).ok().flatten().unwrap_or(id.to_string()), + services().rooms.state_cache.room_joined_count(&id).ok().flatten().unwrap_or(0), + )) + .collect::>(); + rooms.sort_by_key(|r| r.2); + rooms.reverse(); let output = format!( "Rooms:\n{}", - room_ids - .filter_map(|r| r.ok()) - .map(|id| id.to_string() - + "\tMembers: " - + &services() - .rooms - .state_cache - .room_joined_count(&id) - .ok() - .flatten() - .unwrap_or(0) - .to_string()) + rooms + .iter() + .map(|(id, name, members)| format!("{id}\tName: {name}\tMembers: {members}")) .collect::>() .join("\n") ); @@ -845,6 +869,37 @@ impl Service { } } } + RoomCommand::Directory(command) => match command { + RoomDirectoryCommand::Publish { room_id } => match services().rooms.directory.set_public(&room_id) { + Ok(()) => RoomMessageEventContent::text_plain("Room published"), + Err(err) => RoomMessageEventContent::text_plain(&format!("Unable to update room: {}", err)), + } + RoomDirectoryCommand::Unpublish { room_id } => match services().rooms.directory.set_not_public(&room_id) { + Ok(()) => RoomMessageEventContent::text_plain("Room unpublished"), + Err(err) => RoomMessageEventContent::text_plain(&format!("Unable to update room: {}", err)), + } + RoomDirectoryCommand::List => { + let mut rooms = services().rooms.directory.public_rooms() + .filter_map(|r| r.ok()) + .map(|id| ( + id.clone(), + services().rooms.state_accessor.get_name(&id).ok().flatten().unwrap_or(id.to_string()), + services().rooms.state_cache.room_joined_count(&id).ok().flatten().unwrap_or(0), + )) + .collect::>(); + rooms.sort_by_key(|r| r.2); + rooms.reverse(); + let output = format!( + "Rooms:\n{}", + rooms + .iter() + .map(|(id, name, members)| format!("{id}\tName: {name}\tMembers: {members}")) + .collect::>() + .join("\n") + ); + RoomMessageEventContent::text_plain(output) + } + } } AdminCommand::Federation(command) => match command { FederationCommand::DisableRoom { room_id } => {