2024-05-23 01:27:04 -04:00
|
|
|
use std::fmt::Write;
|
2024-03-22 03:37:55 -07:00
|
|
|
|
2024-07-27 00:11:41 +00:00
|
|
|
use clap::Subcommand;
|
2024-08-08 17:18:30 +00:00
|
|
|
use futures::StreamExt;
|
2025-04-06 23:41:58 +00:00
|
|
|
use ruma::{OwnedRoomAliasId, OwnedRoomId};
|
2025-04-22 01:41:02 +00:00
|
|
|
use tuwunel_core::{Err, Result};
|
2024-03-22 03:37:55 -07:00
|
|
|
|
2025-04-06 23:41:58 +00:00
|
|
|
use crate::Context;
|
2024-03-22 03:37:55 -07:00
|
|
|
|
2024-07-27 00:11:41 +00:00
|
|
|
#[derive(Debug, Subcommand)]
|
|
|
|
|
pub(crate) 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
|
2025-04-08 04:39:01 +00:00
|
|
|
room_id: OwnedRoomId,
|
2024-07-27 00:11:41 +00:00
|
|
|
|
|
|
|
|
/// 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
|
2025-04-08 04:39:01 +00:00
|
|
|
room_id: Option<OwnedRoomId>,
|
2024-07-27 00:11:41 +00:00
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-06 23:41:58 +00:00
|
|
|
pub(super) async fn process(command: RoomAliasCommand, context: &Context<'_>) -> Result {
|
2024-07-27 00:11:41 +00:00
|
|
|
let services = context.services;
|
|
|
|
|
let server_user = &services.globals.server_user;
|
2024-06-12 01:42:39 -04:00
|
|
|
|
2024-03-22 03:37:55 -07:00
|
|
|
match command {
|
2024-12-15 00:05:47 -05:00
|
|
|
| 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());
|
2024-12-28 23:31:24 +00:00
|
|
|
let room_alias = match OwnedRoomAliasId::parse(room_alias_str) {
|
2024-12-15 00:05:47 -05:00
|
|
|
| Ok(alias) => alias,
|
2025-03-02 23:15:05 -05:00
|
|
|
| Err(err) => {
|
2025-04-06 23:41:58 +00:00
|
|
|
return Err!("Failed to parse alias: {err}");
|
2025-03-02 23:15:05 -05:00
|
|
|
},
|
2024-03-22 03:37:55 -07:00
|
|
|
};
|
|
|
|
|
match command {
|
2025-01-31 02:36:14 +01:00
|
|
|
| RoomAliasCommand::Set { force, room_id, .. } => {
|
2025-04-22 04:42:26 +00:00
|
|
|
match (
|
|
|
|
|
force,
|
|
|
|
|
services
|
|
|
|
|
.alias
|
|
|
|
|
.resolve_local_alias(&room_alias)
|
|
|
|
|
.await,
|
|
|
|
|
) {
|
2024-12-15 00:05:47 -05:00
|
|
|
| (true, Ok(id)) => {
|
2025-08-22 20:15:54 +05:00
|
|
|
match services
|
|
|
|
|
.alias
|
|
|
|
|
.set_alias(&room_alias, &room_id, server_user)
|
|
|
|
|
{
|
2025-04-06 23:41:58 +00:00
|
|
|
| Err(err) => Err!("Failed to remove alias: {err}"),
|
|
|
|
|
| Ok(()) =>
|
|
|
|
|
context
|
|
|
|
|
.write_str(&format!(
|
|
|
|
|
"Successfully overwrote alias (formerly {id})"
|
|
|
|
|
))
|
|
|
|
|
.await,
|
2024-12-15 00:05:47 -05:00
|
|
|
}
|
|
|
|
|
},
|
2025-04-06 23:41:58 +00:00
|
|
|
| (false, Ok(id)) => Err!(
|
2024-12-15 00:05:47 -05:00
|
|
|
"Refusing to overwrite in use alias for {id}, use -f or --force to \
|
|
|
|
|
overwrite"
|
2025-04-06 23:41:58 +00:00
|
|
|
),
|
2024-12-15 00:05:47 -05:00
|
|
|
| (_, Err(_)) => {
|
2025-08-22 20:15:54 +05:00
|
|
|
match services
|
|
|
|
|
.alias
|
|
|
|
|
.set_alias(&room_alias, &room_id, server_user)
|
|
|
|
|
{
|
2025-04-06 23:41:58 +00:00
|
|
|
| Err(err) => Err!("Failed to remove alias: {err}"),
|
|
|
|
|
| Ok(()) => context.write_str("Successfully set alias").await,
|
2024-12-15 00:05:47 -05:00
|
|
|
}
|
|
|
|
|
},
|
2025-01-31 02:36:14 +01:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
| RoomAliasCommand::Remove { .. } => {
|
2025-04-22 04:42:26 +00:00
|
|
|
match services
|
|
|
|
|
.alias
|
|
|
|
|
.resolve_local_alias(&room_alias)
|
|
|
|
|
.await
|
|
|
|
|
{
|
2025-04-06 23:41:58 +00:00
|
|
|
| Err(_) => Err!("Alias isn't in use."),
|
2024-12-15 00:05:47 -05:00
|
|
|
| Ok(id) => match services
|
|
|
|
|
.alias
|
|
|
|
|
.remove_alias(&room_alias, server_user)
|
|
|
|
|
.await
|
|
|
|
|
{
|
2025-04-06 23:41:58 +00:00
|
|
|
| Err(err) => Err!("Failed to remove alias: {err}"),
|
|
|
|
|
| Ok(()) =>
|
2025-04-22 04:42:26 +00:00
|
|
|
context
|
|
|
|
|
.write_str(&format!("Removed alias from {id}"))
|
|
|
|
|
.await,
|
2024-12-15 00:05:47 -05:00
|
|
|
},
|
2025-01-31 02:36:14 +01:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
| RoomAliasCommand::Which { .. } => {
|
2025-04-22 04:42:26 +00:00
|
|
|
match services
|
|
|
|
|
.alias
|
|
|
|
|
.resolve_local_alias(&room_alias)
|
|
|
|
|
.await
|
|
|
|
|
{
|
2025-04-06 23:41:58 +00:00
|
|
|
| Err(_) => Err!("Alias isn't in use."),
|
2025-04-22 04:42:26 +00:00
|
|
|
| Ok(id) =>
|
|
|
|
|
context
|
|
|
|
|
.write_str(&format!("Alias resolves to {id}"))
|
|
|
|
|
.await,
|
2025-01-31 02:36:14 +01:00
|
|
|
}
|
|
|
|
|
},
|
2024-12-15 00:05:47 -05:00
|
|
|
| RoomAliasCommand::List { .. } => unreachable!(),
|
2024-03-22 03:37:55 -07:00
|
|
|
}
|
|
|
|
|
},
|
2024-12-15 00:05:47 -05:00
|
|
|
| RoomAliasCommand::List { room_id } =>
|
2024-03-22 03:37:55 -07:00
|
|
|
if let Some(room_id) = room_id {
|
2024-10-01 02:47:39 +00:00
|
|
|
let aliases: Vec<OwnedRoomAliasId> = services
|
2024-03-25 17:05:11 -04:00
|
|
|
.alias
|
|
|
|
|
.local_aliases_for_room(&room_id)
|
2024-08-08 17:18:30 +00:00
|
|
|
.map(Into::into)
|
2024-10-01 02:47:39 +00:00
|
|
|
.collect()
|
2024-08-08 17:18:30 +00:00
|
|
|
.await;
|
|
|
|
|
|
2025-04-22 04:42:26 +00:00
|
|
|
let plain_list = aliases
|
|
|
|
|
.iter()
|
|
|
|
|
.fold(String::new(), |mut output, alias| {
|
|
|
|
|
writeln!(output, "- {alias}")
|
|
|
|
|
.expect("should be able to write to string buffer");
|
|
|
|
|
output
|
|
|
|
|
});
|
2024-08-08 17:18:30 +00:00
|
|
|
|
|
|
|
|
let plain = format!("Aliases for {room_id}:\n{plain_list}");
|
2025-04-06 23:41:58 +00:00
|
|
|
context.write_str(&plain).await
|
2024-03-22 03:37:55 -07:00
|
|
|
} else {
|
2024-07-27 00:11:41 +00:00
|
|
|
let aliases = services
|
2024-03-25 17:05:11 -04:00
|
|
|
.alias
|
|
|
|
|
.all_local_aliases()
|
2024-08-08 17:18:30 +00:00
|
|
|
.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}");
|
2025-04-06 23:41:58 +00:00
|
|
|
context.write_str(&plain).await
|
2024-12-15 00:05:47 -05:00
|
|
|
},
|
2024-03-22 03:37:55 -07:00
|
|
|
}
|
|
|
|
|
}
|