use clap::Subcommand; use ruma::{api::appservice::Registration, events::room::message::RoomMessageEventContent}; use crate::{service::admin::escape_html, services, Result}; #[cfg_attr(test, derive(Debug))] #[derive(Subcommand)] pub(crate) enum AppserviceCommand { /// - Register an appservice using its registration YAML /// /// This command needs a YAML generated by an appservice (such as a bridge), /// which must be provided in a Markdown code block below the command. /// /// Registering a new bridge using the ID of an existing bridge will replace /// the old one. Register, /// - Unregister an appservice using its ID /// /// You can find the ID using the `list-appservices` command. Unregister { /// The appservice to unregister appservice_identifier: String, }, /// - Show an appservice's config using its ID /// /// You can find the ID using the `list-appservices` command. Show { /// The appservice to show appservice_identifier: String, }, /// - List all the currently registered appservices List, } pub(crate) async fn process(command: AppserviceCommand, body: Vec<&str>) -> Result { match command { AppserviceCommand::Register => { if body.len() > 2 && body[0].trim().starts_with("```") && body.last().unwrap().trim() == "```" { let appservice_config = body[1..body.len() - 1].join("\n"); let parsed_config = serde_yaml::from_str::(&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.", )) } }, AppserviceCommand::Unregister { appservice_identifier, } => match services().appservice.unregister_appservice(&appservice_identifier).await { Ok(()) => Ok(RoomMessageEventContent::text_plain("Appservice unregistered.")), Err(e) => Ok(RoomMessageEventContent::text_plain(format!( "Failed to unregister appservice: {e}" ))), }, AppserviceCommand::Show { appservice_identifier, } => match services().appservice.get_registration(&appservice_identifier).await { Some(config) => { let config_str = serde_yaml::to_string(&config).expect("config should've been validated on register"); let output = format!("Config for {}:\n\n```yaml\n{}\n```", appservice_identifier, config_str,); let output_html = format!( "Config for {}:\n\n
{}
", escape_html(&appservice_identifier), escape_html(&config_str), ); Ok(RoomMessageEventContent::text_html(output, output_html)) }, None => Ok(RoomMessageEventContent::text_plain("Appservice does not exist.")), }, AppserviceCommand::List => { let appservices = services().appservice.iter_ids().await; let output = format!("Appservices ({}): {}", appservices.len(), appservices.join(", ")); Ok(RoomMessageEventContent::text_plain(output)) }, } }