continuwuity/src/admin/room/alias.rs
Jade Ellis a0610fd11f
Some checks failed
Release Docker Image / define-variables (push) Failing after 1s
Release Docker Image / build-image (linux/amd64, linux-amd64) (push) Has been skipped
Release Docker Image / build-image (linux/arm64, linux-arm64) (push) Has been skipped
Release Docker Image / merge (push) Has been skipped
Rust Checks / Format (push) Failing after 1s
Rust Checks / Clippy (push) Failing after 9s
Rust Checks / Cargo Test (push) Failing after 10s
feat: Generate admin command documentation
The first part of getting admin command docs on the website.

Next is is including it in the same way we do the example config or
readme.

There's also the beginnings of manpage generation here, although it's
kinda sus and I'm not sure how it's supposed to work. I'll leave that to
anyone who wants to package it.

We introduce the beginings of the xtask pattern here - we do a lot of
file generation, I thought it would be best to avoid doing that on every
compilation. It also helps avoid lots of runtime deps.

We'll need to document generating this stuff & probably add pre-commit
hooks for it, though.
2025-05-24 01:00:58 +01:00

159 lines
4.4 KiB
Rust

use std::fmt::Write;
use clap::Subcommand;
use conduwuit::{Err, Result};
use futures::StreamExt;
use ruma::{OwnedRoomAliasId, OwnedRoomId};
use crate::Context;
#[derive(Debug, Subcommand)]
pub enum RoomAliasCommand {
/// - Make an alias point to a room.
Set {
#[arg(short, long)]
/// Set the alias even if a room is already using it
force: bool,
/// The room id to set the alias on
room_id: OwnedRoomId,
/// The alias localpart to use (`alias`, not `#alias:servername.tld`)
room_alias_localpart: String,
},
/// - Remove a local alias
Remove {
/// The alias localpart to remove (`alias`, not `#alias:servername.tld`)
room_alias_localpart: String,
},
/// - Show which room is using an alias
Which {
/// The alias localpart to look up (`alias`, not
/// `#alias:servername.tld`)
room_alias_localpart: String,
},
/// - List aliases currently being used
List {
/// If set, only list the aliases for this room
room_id: Option<OwnedRoomId>,
},
}
pub(super) async fn process(command: RoomAliasCommand, context: &Context<'_>) -> Result {
let services = context.services;
let server_user = &services.globals.server_user;
match command {
| RoomAliasCommand::Set { ref room_alias_localpart, .. }
| RoomAliasCommand::Remove { ref room_alias_localpart }
| RoomAliasCommand::Which { ref room_alias_localpart } => {
let room_alias_str =
format!("#{}:{}", room_alias_localpart, services.globals.server_name());
let room_alias = match OwnedRoomAliasId::parse(room_alias_str) {
| Ok(alias) => alias,
| Err(err) => {
return Err!("Failed to parse alias: {err}");
},
};
match command {
| RoomAliasCommand::Set { force, room_id, .. } => {
match (force, services.rooms.alias.resolve_local_alias(&room_alias).await) {
| (true, Ok(id)) => {
match services.rooms.alias.set_alias(
&room_alias,
&room_id,
server_user,
) {
| Err(err) => Err!("Failed to remove alias: {err}"),
| Ok(()) =>
context
.write_str(&format!(
"Successfully overwrote alias (formerly {id})"
))
.await,
}
},
| (false, Ok(id)) => Err!(
"Refusing to overwrite in use alias for {id}, use -f or --force to \
overwrite"
),
| (_, Err(_)) => {
match services.rooms.alias.set_alias(
&room_alias,
&room_id,
server_user,
) {
| Err(err) => Err!("Failed to remove alias: {err}"),
| Ok(()) => context.write_str("Successfully set alias").await,
}
},
}
},
| RoomAliasCommand::Remove { .. } => {
match services.rooms.alias.resolve_local_alias(&room_alias).await {
| Err(_) => Err!("Alias isn't in use."),
| Ok(id) => match services
.rooms
.alias
.remove_alias(&room_alias, server_user)
.await
{
| Err(err) => Err!("Failed to remove alias: {err}"),
| Ok(()) =>
context.write_str(&format!("Removed alias from {id}")).await,
},
}
},
| RoomAliasCommand::Which { .. } => {
match services.rooms.alias.resolve_local_alias(&room_alias).await {
| Err(_) => Err!("Alias isn't in use."),
| Ok(id) => context.write_str(&format!("Alias resolves to {id}")).await,
}
},
| RoomAliasCommand::List { .. } => unreachable!(),
}
},
| RoomAliasCommand::List { room_id } =>
if let Some(room_id) = room_id {
let aliases: Vec<OwnedRoomAliasId> = services
.rooms
.alias
.local_aliases_for_room(&room_id)
.map(Into::into)
.collect()
.await;
let plain_list = aliases.iter().fold(String::new(), |mut output, alias| {
writeln!(output, "- {alias}")
.expect("should be able to write to string buffer");
output
});
let plain = format!("Aliases for {room_id}:\n{plain_list}");
context.write_str(&plain).await
} else {
let aliases = services
.rooms
.alias
.all_local_aliases()
.map(|(room_id, localpart)| (room_id.into(), localpart.into()))
.collect::<Vec<(OwnedRoomId, String)>>()
.await;
let server_name = services.globals.server_name();
let plain_list = aliases
.iter()
.fold(String::new(), |mut output, (alias, id)| {
writeln!(output, "- `{alias}` -> #{id}:{server_name}")
.expect("should be able to write to string buffer");
output
});
let plain = format!("Aliases:\n{plain_list}");
context.write_str(&plain).await
},
}
}