replace admin command branches returning RoomMessageEventContent

rename admin Command back to Context

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk 2025-04-06 23:41:58 +00:00 committed by Jade Ellis
commit 4f8fec7e5a
No known key found for this signature in database
GPG key ID: 8705A2A3EBF77BD2
32 changed files with 903 additions and 1306 deletions

View file

@ -1,11 +1,11 @@
use std::fmt::Write;
use clap::Subcommand;
use conduwuit::Result;
use conduwuit::{Err, Result};
use futures::StreamExt;
use ruma::{OwnedRoomAliasId, OwnedRoomId, events::room::message::RoomMessageEventContent};
use ruma::{OwnedRoomAliasId, OwnedRoomId};
use crate::{Command, escape_html};
use crate::Context;
#[derive(Debug, Subcommand)]
pub(crate) enum RoomAliasCommand {
@ -42,17 +42,7 @@ pub(crate) enum RoomAliasCommand {
},
}
pub(super) async fn process(command: RoomAliasCommand, context: &Command<'_>) -> Result {
let c = reprocess(command, context).await?;
context.write_str(c.body()).await?;
Ok(())
}
pub(super) async fn reprocess(
command: RoomAliasCommand,
context: &Command<'_>,
) -> Result<RoomMessageEventContent> {
pub(super) async fn process(command: RoomAliasCommand, context: &Context<'_>) -> Result {
let services = context.services;
let server_user = &services.globals.server_user;
@ -65,9 +55,7 @@ pub(super) async fn reprocess(
let room_alias = match OwnedRoomAliasId::parse(room_alias_str) {
| Ok(alias) => alias,
| Err(err) => {
return Ok(RoomMessageEventContent::text_plain(format!(
"Failed to parse alias: {err}"
)));
return Err!("Failed to parse alias: {err}");
},
};
match command {
@ -79,60 +67,50 @@ pub(super) async fn reprocess(
&room_id,
server_user,
) {
| Ok(()) => Ok(RoomMessageEventContent::text_plain(format!(
"Successfully overwrote alias (formerly {id})"
))),
| Err(err) => Ok(RoomMessageEventContent::text_plain(format!(
"Failed to remove alias: {err}"
))),
| Err(err) => Err!("Failed to remove alias: {err}"),
| Ok(()) =>
context
.write_str(&format!(
"Successfully overwrote alias (formerly {id})"
))
.await,
}
},
| (false, Ok(id)) => Ok(RoomMessageEventContent::text_plain(format!(
| (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,
) {
| Ok(()) => Ok(RoomMessageEventContent::text_plain(
"Successfully set alias",
)),
| Err(err) => Ok(RoomMessageEventContent::text_plain(format!(
"Failed to remove alias: {err}"
))),
| 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
{
| Ok(()) => Ok(RoomMessageEventContent::text_plain(format!(
"Removed alias from {id}"
))),
| Err(err) => Ok(RoomMessageEventContent::text_plain(format!(
"Failed to remove alias: {err}"
))),
| Err(err) => Err!("Failed to remove alias: {err}"),
| Ok(()) =>
context.write_str(&format!("Removed alias from {id}")).await,
},
| Err(_) =>
Ok(RoomMessageEventContent::text_plain("Alias isn't in use.")),
}
},
| RoomAliasCommand::Which { .. } => {
match services.rooms.alias.resolve_local_alias(&room_alias).await {
| Ok(id) => Ok(RoomMessageEventContent::text_plain(format!(
"Alias resolves to {id}"
))),
| Err(_) =>
Ok(RoomMessageEventContent::text_plain("Alias isn't in use.")),
| Err(_) => Err!("Alias isn't in use."),
| Ok(id) => context.write_str(&format!("Alias resolves to {id}")).await,
}
},
| RoomAliasCommand::List { .. } => unreachable!(),
@ -154,15 +132,8 @@ pub(super) async fn reprocess(
output
});
let html_list = aliases.iter().fold(String::new(), |mut output, alias| {
writeln!(output, "<li>{}</li>", escape_html(alias.as_ref()))
.expect("should be able to write to string buffer");
output
});
let plain = format!("Aliases for {room_id}:\n{plain_list}");
let html = format!("Aliases for {room_id}:\n<ul>{html_list}</ul>");
Ok(RoomMessageEventContent::text_html(plain, html))
context.write_str(&plain).await
} else {
let aliases = services
.rooms
@ -181,23 +152,8 @@ pub(super) async fn reprocess(
output
});
let html_list = aliases
.iter()
.fold(String::new(), |mut output, (alias, id)| {
writeln!(
output,
"<li><code>{}</code> -> #{}:{}</li>",
escape_html(alias.as_ref()),
escape_html(id),
server_name
)
.expect("should be able to write to string buffer");
output
});
let plain = format!("Aliases:\n{plain_list}");
let html = format!("Aliases:\n<ul>{html_list}</ul>");
Ok(RoomMessageEventContent::text_html(plain, html))
context.write_str(&plain).await
},
}
}

View file

@ -1,6 +1,6 @@
use conduwuit::Result;
use conduwuit::{Err, Result};
use futures::StreamExt;
use ruma::{OwnedRoomId, events::room::message::RoomMessageEventContent};
use ruma::OwnedRoomId;
use crate::{PAGE_SIZE, admin_command, get_room_info};
@ -11,7 +11,7 @@ pub(super) async fn list_rooms(
exclude_disabled: bool,
exclude_banned: bool,
no_details: bool,
) -> Result<RoomMessageEventContent> {
) -> Result {
// TODO: i know there's a way to do this with clap, but i can't seem to find it
let page = page.unwrap_or(1);
let mut rooms = self
@ -41,29 +41,28 @@ pub(super) async fn list_rooms(
.collect::<Vec<_>>();
if rooms.is_empty() {
return Ok(RoomMessageEventContent::text_plain("No more rooms."));
return Err!("No more rooms.");
}
let output_plain = format!(
"Rooms ({}):\n```\n{}\n```",
rooms.len(),
rooms
.iter()
.map(|(id, members, name)| if no_details {
let body = rooms
.iter()
.map(|(id, members, name)| {
if no_details {
format!("{id}")
} else {
format!("{id}\tMembers: {members}\tName: {name}")
})
.collect::<Vec<_>>()
.join("\n")
);
}
})
.collect::<Vec<_>>()
.join("\n");
Ok(RoomMessageEventContent::notice_markdown(output_plain))
self.write_str(&format!("Rooms ({}):\n```\n{body}\n```", rooms.len(),))
.await
}
#[admin_command]
pub(super) async fn exists(&self, room_id: OwnedRoomId) -> Result<RoomMessageEventContent> {
pub(super) async fn exists(&self, room_id: OwnedRoomId) -> Result {
let result = self.services.rooms.metadata.exists(&room_id).await;
Ok(RoomMessageEventContent::notice_markdown(format!("{result}")))
self.write_str(&format!("{result}")).await
}

View file

@ -1,9 +1,9 @@
use clap::Subcommand;
use conduwuit::Result;
use conduwuit::{Err, Result};
use futures::StreamExt;
use ruma::{OwnedRoomId, events::room::message::RoomMessageEventContent};
use ruma::OwnedRoomId;
use crate::{Command, PAGE_SIZE, get_room_info};
use crate::{Context, PAGE_SIZE, get_room_info};
#[derive(Debug, Subcommand)]
pub(crate) enum RoomDirectoryCommand {
@ -25,25 +25,16 @@ pub(crate) enum RoomDirectoryCommand {
},
}
pub(super) async fn process(command: RoomDirectoryCommand, context: &Command<'_>) -> Result {
let c = reprocess(command, context).await?;
context.write_str(c.body()).await?;
Ok(())
}
pub(super) async fn reprocess(
command: RoomDirectoryCommand,
context: &Command<'_>,
) -> Result<RoomMessageEventContent> {
pub(super) async fn process(command: RoomDirectoryCommand, context: &Context<'_>) -> Result {
let services = context.services;
match command {
| RoomDirectoryCommand::Publish { room_id } => {
services.rooms.directory.set_public(&room_id);
Ok(RoomMessageEventContent::notice_plain("Room published"))
context.write_str("Room published").await
},
| RoomDirectoryCommand::Unpublish { room_id } => {
services.rooms.directory.set_not_public(&room_id);
Ok(RoomMessageEventContent::notice_plain("Room unpublished"))
context.write_str("Room unpublished").await
},
| RoomDirectoryCommand::List { page } => {
// TODO: i know there's a way to do this with clap, but i can't seem to find it
@ -66,20 +57,18 @@ pub(super) async fn reprocess(
.collect();
if rooms.is_empty() {
return Ok(RoomMessageEventContent::text_plain("No more rooms."));
return Err!("No more rooms.");
}
let output = format!(
"Rooms (page {page}):\n```\n{}\n```",
rooms
.iter()
.map(|(id, members, name)| format!(
"{id} | Members: {members} | Name: {name}"
))
.collect::<Vec<_>>()
.join("\n")
);
Ok(RoomMessageEventContent::text_markdown(output))
let body = rooms
.iter()
.map(|(id, members, name)| format!("{id} | Members: {members} | Name: {name}"))
.collect::<Vec<_>>()
.join("\n");
context
.write_str(&format!("Rooms (page {page}):\n```\n{body}\n```",))
.await
},
}
}

View file

@ -1,7 +1,7 @@
use clap::Subcommand;
use conduwuit::{Result, utils::ReadyExt};
use conduwuit::{Err, Result, utils::ReadyExt};
use futures::StreamExt;
use ruma::{OwnedRoomId, events::room::message::RoomMessageEventContent};
use ruma::OwnedRoomId;
use crate::{admin_command, admin_command_dispatch};
@ -27,11 +27,7 @@ pub(crate) enum RoomInfoCommand {
}
#[admin_command]
async fn list_joined_members(
&self,
room_id: OwnedRoomId,
local_only: bool,
) -> Result<RoomMessageEventContent> {
async fn list_joined_members(&self, room_id: OwnedRoomId, local_only: bool) -> Result {
let room_name = self
.services
.rooms
@ -64,22 +60,19 @@ async fn list_joined_members(
.collect()
.await;
let output_plain = format!(
"{} Members in Room \"{}\":\n```\n{}\n```",
member_info.len(),
room_name,
member_info
.into_iter()
.map(|(displayname, mxid)| format!("{mxid} | {displayname}"))
.collect::<Vec<_>>()
.join("\n")
);
let num = member_info.len();
let body = member_info
.into_iter()
.map(|(displayname, mxid)| format!("{mxid} | {displayname}"))
.collect::<Vec<_>>()
.join("\n");
Ok(RoomMessageEventContent::notice_markdown(output_plain))
self.write_str(&format!("{num} Members in Room \"{room_name}\":\n```\n{body}\n```",))
.await
}
#[admin_command]
async fn view_room_topic(&self, room_id: OwnedRoomId) -> Result<RoomMessageEventContent> {
async fn view_room_topic(&self, room_id: OwnedRoomId) -> Result {
let Ok(room_topic) = self
.services
.rooms
@ -87,10 +80,9 @@ async fn view_room_topic(&self, room_id: OwnedRoomId) -> Result<RoomMessageEvent
.get_room_topic(&room_id)
.await
else {
return Ok(RoomMessageEventContent::text_plain("Room does not have a room topic set."));
return Err!("Room does not have a room topic set.");
};
Ok(RoomMessageEventContent::notice_markdown(format!(
"Room topic:\n```\n{room_topic}\n```"
)))
self.write_str(&format!("Room topic:\n```\n{room_topic}\n```"))
.await
}

View file

@ -1,15 +1,12 @@
use api::client::leave_room;
use clap::Subcommand;
use conduwuit::{
Result, debug,
Err, Result, debug,
utils::{IterStream, ReadyExt},
warn,
};
use futures::StreamExt;
use ruma::{
OwnedRoomId, OwnedRoomOrAliasId, RoomAliasId, RoomId, RoomOrAliasId,
events::room::message::RoomMessageEventContent,
};
use ruma::{OwnedRoomId, OwnedRoomOrAliasId, RoomAliasId, RoomId, RoomOrAliasId};
use crate::{admin_command, admin_command_dispatch, get_room_info};
@ -49,14 +46,14 @@ pub(crate) enum RoomModerationCommand {
}
#[admin_command]
async fn ban_room(&self, room: OwnedRoomOrAliasId) -> Result<RoomMessageEventContent> {
async fn ban_room(&self, room: OwnedRoomOrAliasId) -> Result {
debug!("Got room alias or ID: {}", room);
let admin_room_alias = &self.services.globals.admin_alias;
if let Ok(admin_room_id) = self.services.admin.get_admin_room().await {
if room.to_string().eq(&admin_room_id) || room.to_string().eq(admin_room_alias) {
return Ok(RoomMessageEventContent::text_plain("Not allowed to ban the admin room."));
return Err!("Not allowed to ban the admin room.");
}
}
@ -64,11 +61,11 @@ async fn ban_room(&self, room: OwnedRoomOrAliasId) -> Result<RoomMessageEventCon
let room_id = match RoomId::parse(&room) {
| Ok(room_id) => room_id,
| Err(e) => {
return Ok(RoomMessageEventContent::text_plain(format!(
return Err!(
"Failed to parse room ID {room}. Please note that this requires a full room \
ID (`!awIh6gGInaS5wLQJwa:example.com`) or a room alias \
(`#roomalias:example.com`): {e}"
)));
);
},
};
@ -80,11 +77,11 @@ async fn ban_room(&self, room: OwnedRoomOrAliasId) -> Result<RoomMessageEventCon
let room_alias = match RoomAliasId::parse(&room) {
| Ok(room_alias) => room_alias,
| Err(e) => {
return Ok(RoomMessageEventContent::text_plain(format!(
return Err!(
"Failed to parse room ID {room}. Please note that this requires a full room \
ID (`!awIh6gGInaS5wLQJwa:example.com`) or a room alias \
(`#roomalias:example.com`): {e}"
)));
);
},
};
@ -123,9 +120,9 @@ async fn ban_room(&self, room: OwnedRoomOrAliasId) -> Result<RoomMessageEventCon
room_id
},
| Err(e) => {
return Ok(RoomMessageEventContent::notice_plain(format!(
return Err!(
"Failed to resolve room alias {room_alias} to a room ID: {e}"
)));
);
},
}
},
@ -135,11 +132,11 @@ async fn ban_room(&self, room: OwnedRoomOrAliasId) -> Result<RoomMessageEventCon
room_id
} else {
return Ok(RoomMessageEventContent::text_plain(
return Err!(
"Room specified is not a room ID or room alias. Please note that this requires a \
full room ID (`!awIh6gGInaS5wLQJwa:example.com`) or a room alias \
(`#roomalias:example.com`)",
));
);
};
debug!("Making all users leave the room {room_id} and forgetting it");
@ -185,20 +182,19 @@ async fn ban_room(&self, room: OwnedRoomOrAliasId) -> Result<RoomMessageEventCon
self.services.rooms.metadata.disable_room(&room_id, true);
Ok(RoomMessageEventContent::text_plain(
self.write_str(
"Room banned, removed all our local users, and disabled incoming federation with room.",
))
)
.await
}
#[admin_command]
async fn ban_list_of_rooms(&self) -> Result<RoomMessageEventContent> {
async fn ban_list_of_rooms(&self) -> Result {
if self.body.len() < 2
|| !self.body[0].trim().starts_with("```")
|| self.body.last().unwrap_or(&"").trim() != "```"
{
return Ok(RoomMessageEventContent::text_plain(
"Expected code block in command body. Add --help for details.",
));
return Err!("Expected code block in command body. Add --help for details.",);
}
let rooms_s = self
@ -356,23 +352,24 @@ async fn ban_list_of_rooms(&self) -> Result<RoomMessageEventContent> {
self.services.rooms.metadata.disable_room(&room_id, true);
}
Ok(RoomMessageEventContent::text_plain(format!(
self.write_str(&format!(
"Finished bulk room ban, banned {room_ban_count} total rooms, evicted all users, and \
disabled incoming federation with the room."
)))
))
.await
}
#[admin_command]
async fn unban_room(&self, room: OwnedRoomOrAliasId) -> Result<RoomMessageEventContent> {
async fn unban_room(&self, room: OwnedRoomOrAliasId) -> Result {
let room_id = if room.is_room_id() {
let room_id = match RoomId::parse(&room) {
| Ok(room_id) => room_id,
| Err(e) => {
return Ok(RoomMessageEventContent::text_plain(format!(
return Err!(
"Failed to parse room ID {room}. Please note that this requires a full room \
ID (`!awIh6gGInaS5wLQJwa:example.com`) or a room alias \
(`#roomalias:example.com`): {e}"
)));
);
},
};
@ -384,11 +381,11 @@ async fn unban_room(&self, room: OwnedRoomOrAliasId) -> Result<RoomMessageEventC
let room_alias = match RoomAliasId::parse(&room) {
| Ok(room_alias) => room_alias,
| Err(e) => {
return Ok(RoomMessageEventContent::text_plain(format!(
return Err!(
"Failed to parse room ID {room}. Please note that this requires a full room \
ID (`!awIh6gGInaS5wLQJwa:example.com`) or a room alias \
(`#roomalias:example.com`): {e}"
)));
);
},
};
@ -427,9 +424,7 @@ async fn unban_room(&self, room: OwnedRoomOrAliasId) -> Result<RoomMessageEventC
room_id
},
| Err(e) => {
return Ok(RoomMessageEventContent::text_plain(format!(
"Failed to resolve room alias {room} to a room ID: {e}"
)));
return Err!("Failed to resolve room alias {room} to a room ID: {e}");
},
}
},
@ -439,19 +434,20 @@ async fn unban_room(&self, room: OwnedRoomOrAliasId) -> Result<RoomMessageEventC
room_id
} else {
return Ok(RoomMessageEventContent::text_plain(
return Err!(
"Room specified is not a room ID or room alias. Please note that this requires a \
full room ID (`!awIh6gGInaS5wLQJwa:example.com`) or a room alias \
(`#roomalias:example.com`)",
));
);
};
self.services.rooms.metadata.disable_room(&room_id, false);
Ok(RoomMessageEventContent::text_plain("Room unbanned and federation re-enabled."))
self.write_str("Room unbanned and federation re-enabled.")
.await
}
#[admin_command]
async fn list_banned_rooms(&self, no_details: bool) -> Result<RoomMessageEventContent> {
async fn list_banned_rooms(&self, no_details: bool) -> Result {
let room_ids: Vec<OwnedRoomId> = self
.services
.rooms
@ -462,7 +458,7 @@ async fn list_banned_rooms(&self, no_details: bool) -> Result<RoomMessageEventCo
.await;
if room_ids.is_empty() {
return Ok(RoomMessageEventContent::text_plain("No rooms are banned."));
return Err!("No rooms are banned.");
}
let mut rooms = room_ids
@ -475,19 +471,20 @@ async fn list_banned_rooms(&self, no_details: bool) -> Result<RoomMessageEventCo
rooms.sort_by_key(|r| r.1);
rooms.reverse();
let output_plain = format!(
"Rooms Banned ({}):\n```\n{}\n```",
rooms.len(),
rooms
.iter()
.map(|(id, members, name)| if no_details {
let num = rooms.len();
let body = rooms
.iter()
.map(|(id, members, name)| {
if no_details {
format!("{id}")
} else {
format!("{id}\tMembers: {members}\tName: {name}")
})
.collect::<Vec<_>>()
.join("\n")
);
}
})
.collect::<Vec<_>>()
.join("\n");
Ok(RoomMessageEventContent::notice_markdown(output_plain))
self.write_str(&format!("Rooms Banned ({num}):\n```\n{body}\n```",))
.await
}