apply new rustfmt.toml changes, fix some clippy lints
Signed-off-by: strawberry <strawberry@puppygock.gay>
This commit is contained in:
parent
0317cc8cc5
commit
77e0b76408
296 changed files with 7147 additions and 4300 deletions
|
@ -3,9 +3,10 @@ use conduwuit::Result;
|
|||
use ruma::events::room::message::RoomMessageEventContent;
|
||||
|
||||
use crate::{
|
||||
appservice, appservice::AppserviceCommand, check, check::CheckCommand, command::Command, debug,
|
||||
debug::DebugCommand, federation, federation::FederationCommand, media, media::MediaCommand, query,
|
||||
query::QueryCommand, room, room::RoomCommand, server, server::ServerCommand, user, user::UserCommand,
|
||||
appservice, appservice::AppserviceCommand, check, check::CheckCommand, command::Command,
|
||||
debug, debug::DebugCommand, federation, federation::FederationCommand, media,
|
||||
media::MediaCommand, query, query::QueryCommand, room, room::RoomCommand, server,
|
||||
server::ServerCommand, user, user::UserCommand,
|
||||
};
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
|
@ -49,18 +50,21 @@ pub(super) enum AdminCommand {
|
|||
}
|
||||
|
||||
#[tracing::instrument(skip_all, name = "command")]
|
||||
pub(super) async fn process(command: AdminCommand, context: &Command<'_>) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn process(
|
||||
command: AdminCommand,
|
||||
context: &Command<'_>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
use AdminCommand::*;
|
||||
|
||||
Ok(match command {
|
||||
Appservices(command) => appservice::process(command, context).await?,
|
||||
Media(command) => media::process(command, context).await?,
|
||||
Users(command) => user::process(command, context).await?,
|
||||
Rooms(command) => room::process(command, context).await?,
|
||||
Federation(command) => federation::process(command, context).await?,
|
||||
Server(command) => server::process(command, context).await?,
|
||||
Debug(command) => debug::process(command, context).await?,
|
||||
Query(command) => query::process(command, context).await?,
|
||||
Check(command) => check::process(command, context).await?,
|
||||
| Appservices(command) => appservice::process(command, context).await?,
|
||||
| Media(command) => media::process(command, context).await?,
|
||||
| Users(command) => user::process(command, context).await?,
|
||||
| Rooms(command) => room::process(command, context).await?,
|
||||
| Federation(command) => federation::process(command, context).await?,
|
||||
| Server(command) => server::process(command, context).await?,
|
||||
| Debug(command) => debug::process(command, context).await?,
|
||||
| Query(command) => query::process(command, context).await?,
|
||||
| Check(command) => check::process(command, context).await?,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -4,7 +4,9 @@ use crate::{admin_command, Result};
|
|||
|
||||
#[admin_command]
|
||||
pub(super) async fn register(&self) -> Result<RoomMessageEventContent> {
|
||||
if self.body.len() < 2 || !self.body[0].trim().starts_with("```") || self.body.last().unwrap_or(&"").trim() != "```"
|
||||
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.",
|
||||
|
@ -14,55 +16,63 @@ pub(super) async fn register(&self) -> Result<RoomMessageEventContent> {
|
|||
let appservice_config_body = self.body[1..self.body.len().checked_sub(1).unwrap()].join("\n");
|
||||
let parsed_config = serde_yaml::from_str::<Registration>(&appservice_config_body);
|
||||
match parsed_config {
|
||||
Ok(registration) => match self
|
||||
| Ok(registration) => match self
|
||||
.services
|
||||
.appservice
|
||||
.register_appservice(®istration, &appservice_config_body)
|
||||
.await
|
||||
{
|
||||
Ok(()) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
| Ok(()) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Appservice registered with ID: {}",
|
||||
registration.id
|
||||
))),
|
||||
Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
| Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Failed to register appservice: {e}"
|
||||
))),
|
||||
},
|
||||
Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
| Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Could not parse appservice config as YAML: {e}"
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn unregister(&self, appservice_identifier: String) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn unregister(
|
||||
&self,
|
||||
appservice_identifier: String,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
match self
|
||||
.services
|
||||
.appservice
|
||||
.unregister_appservice(&appservice_identifier)
|
||||
.await
|
||||
{
|
||||
Ok(()) => Ok(RoomMessageEventContent::text_plain("Appservice unregistered.")),
|
||||
Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
| Ok(()) => Ok(RoomMessageEventContent::text_plain("Appservice unregistered.")),
|
||||
| Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Failed to unregister appservice: {e}"
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn show_appservice_config(&self, appservice_identifier: String) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn show_appservice_config(
|
||||
&self,
|
||||
appservice_identifier: String,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
match self
|
||||
.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 {appservice_identifier}:\n\n```yaml\n{config_str}\n```",);
|
||||
| Some(config) => {
|
||||
let config_str = serde_yaml::to_string(&config)
|
||||
.expect("config should've been validated on register");
|
||||
let output =
|
||||
format!("Config for {appservice_identifier}:\n\n```yaml\n{config_str}\n```",);
|
||||
Ok(RoomMessageEventContent::notice_markdown(output))
|
||||
},
|
||||
None => Ok(RoomMessageEventContent::text_plain("Appservice does not exist.")),
|
||||
| None => Ok(RoomMessageEventContent::text_plain("Appservice does not exist.")),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,9 @@ pub(super) async fn check_all_users(&self) -> Result<RoomMessageEventContent> {
|
|||
let ok_count = users.iter().filter(|_user| true).count();
|
||||
|
||||
let message = format!(
|
||||
"Database query completed in {query_time:?}:\n\n```\nTotal entries: {total:?}\nFailure/Invalid user count: \
|
||||
{err_count:?}\nSuccess/Valid user count: {ok_count:?}\n```"
|
||||
"Database query completed in {query_time:?}:\n\n```\nTotal entries: \
|
||||
{total:?}\nFailure/Invalid user count: {err_count:?}\nSuccess/Valid user count: \
|
||||
{ok_count:?}\n```"
|
||||
);
|
||||
|
||||
Ok(RoomMessageEventContent::notice_markdown(message))
|
||||
|
|
|
@ -11,8 +11,11 @@ pub(super) enum CheckCommand {
|
|||
AllUsers,
|
||||
}
|
||||
|
||||
pub(super) async fn process(command: CheckCommand, context: &Command<'_>) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn process(
|
||||
command: CheckCommand,
|
||||
context: &Command<'_>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
Ok(match command {
|
||||
CheckCommand::AllUsers => context.check_all_users().await?,
|
||||
| CheckCommand::AllUsers => context.check_all_users().await?,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -6,7 +6,9 @@ use std::{
|
|||
time::{Instant, SystemTime},
|
||||
};
|
||||
|
||||
use conduwuit::{debug_error, err, info, trace, utils, utils::string::EMPTY, warn, Error, PduEvent, Result};
|
||||
use conduwuit::{
|
||||
debug_error, err, info, trace, utils, utils::string::EMPTY, warn, Error, PduEvent, Result,
|
||||
};
|
||||
use futures::{FutureExt, StreamExt};
|
||||
use ruma::{
|
||||
api::{client::error::ErrorKind, federation::event::get_room_state},
|
||||
|
@ -26,7 +28,10 @@ pub(super) async fn echo(&self, message: Vec<String>) -> Result<RoomMessageEvent
|
|||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn get_auth_chain(&self, event_id: Box<EventId>) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn get_auth_chain(
|
||||
&self,
|
||||
event_id: Box<EventId>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let Ok(event) = self.services.rooms.timeline.get_pdu_json(&event_id).await else {
|
||||
return Ok(RoomMessageEventContent::notice_plain("Event not found."));
|
||||
};
|
||||
|
@ -68,20 +73,26 @@ pub(super) async fn parse_pdu(&self) -> Result<RoomMessageEventContent> {
|
|||
|
||||
let string = self.body[1..self.body.len().saturating_sub(1)].join("\n");
|
||||
match serde_json::from_str(&string) {
|
||||
Ok(value) => match ruma::signatures::reference_hash(&value, &RoomVersionId::V6) {
|
||||
Ok(hash) => {
|
||||
| Ok(value) => match ruma::signatures::reference_hash(&value, &RoomVersionId::V6) {
|
||||
| Ok(hash) => {
|
||||
let event_id = EventId::parse(format!("${hash}"));
|
||||
|
||||
match serde_json::from_value::<PduEvent>(serde_json::to_value(value).expect("value is json")) {
|
||||
Ok(pdu) => Ok(RoomMessageEventContent::text_plain(format!("EventId: {event_id:?}\n{pdu:#?}"))),
|
||||
Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
match serde_json::from_value::<PduEvent>(
|
||||
serde_json::to_value(value).expect("value is json"),
|
||||
) {
|
||||
| Ok(pdu) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"EventId: {event_id:?}\n{pdu:#?}"
|
||||
))),
|
||||
| Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"EventId: {event_id:?}\nCould not parse event: {e}"
|
||||
))),
|
||||
}
|
||||
},
|
||||
Err(e) => Ok(RoomMessageEventContent::text_plain(format!("Could not parse PDU JSON: {e:?}"))),
|
||||
| Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Could not parse PDU JSON: {e:?}"
|
||||
))),
|
||||
},
|
||||
Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
| Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Invalid json in command body: {e}"
|
||||
))),
|
||||
}
|
||||
|
@ -103,8 +114,9 @@ pub(super) async fn get_pdu(&self, event_id: Box<EventId>) -> Result<RoomMessage
|
|||
}
|
||||
|
||||
match pdu_json {
|
||||
Ok(json) => {
|
||||
let json_text = serde_json::to_string_pretty(&json).expect("canonical json is valid json");
|
||||
| Ok(json) => {
|
||||
let json_text =
|
||||
serde_json::to_string_pretty(&json).expect("canonical json is valid json");
|
||||
Ok(RoomMessageEventContent::notice_markdown(format!(
|
||||
"{}\n```json\n{}\n```",
|
||||
if outlier {
|
||||
|
@ -115,13 +127,15 @@ pub(super) async fn get_pdu(&self, event_id: Box<EventId>) -> Result<RoomMessage
|
|||
json_text
|
||||
)))
|
||||
},
|
||||
Err(_) => Ok(RoomMessageEventContent::text_plain("PDU not found locally.")),
|
||||
| Err(_) => Ok(RoomMessageEventContent::text_plain("PDU not found locally.")),
|
||||
}
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn get_remote_pdu_list(
|
||||
&self, server: Box<ServerName>, force: bool,
|
||||
&self,
|
||||
server: Box<ServerName>,
|
||||
force: bool,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
if !self.services.globals.config.allow_federation {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
|
@ -131,8 +145,8 @@ pub(super) async fn get_remote_pdu_list(
|
|||
|
||||
if server == self.services.globals.server_name() {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"Not allowed to send federation requests to ourselves. Please use `get-pdu` for fetching local PDUs from \
|
||||
the database.",
|
||||
"Not allowed to send federation requests to ourselves. Please use `get-pdu` for \
|
||||
fetching local PDUs from the database.",
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -184,7 +198,9 @@ pub(super) async fn get_remote_pdu_list(
|
|||
|
||||
#[admin_command]
|
||||
pub(super) async fn get_remote_pdu(
|
||||
&self, event_id: Box<EventId>, server: Box<ServerName>,
|
||||
&self,
|
||||
event_id: Box<EventId>,
|
||||
server: Box<ServerName>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
if !self.services.globals.config.allow_federation {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
|
@ -194,30 +210,32 @@ pub(super) async fn get_remote_pdu(
|
|||
|
||||
if server == self.services.globals.server_name() {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"Not allowed to send federation requests to ourselves. Please use `get-pdu` for fetching local PDUs.",
|
||||
"Not allowed to send federation requests to ourselves. Please use `get-pdu` for \
|
||||
fetching local PDUs.",
|
||||
));
|
||||
}
|
||||
|
||||
match self
|
||||
.services
|
||||
.sending
|
||||
.send_federation_request(
|
||||
&server,
|
||||
ruma::api::federation::event::get_event::v1::Request {
|
||||
event_id: event_id.clone().into(),
|
||||
include_unredacted_content: None,
|
||||
},
|
||||
)
|
||||
.send_federation_request(&server, ruma::api::federation::event::get_event::v1::Request {
|
||||
event_id: event_id.clone().into(),
|
||||
include_unredacted_content: None,
|
||||
})
|
||||
.await
|
||||
{
|
||||
Ok(response) => {
|
||||
let json: CanonicalJsonObject = serde_json::from_str(response.pdu.get()).map_err(|e| {
|
||||
warn!(
|
||||
"Requested event ID {event_id} from server but failed to convert from RawValue to \
|
||||
CanonicalJsonObject (malformed event/response?): {e}"
|
||||
);
|
||||
Error::BadRequest(ErrorKind::Unknown, "Received response from server but failed to parse PDU")
|
||||
})?;
|
||||
| Ok(response) => {
|
||||
let json: CanonicalJsonObject =
|
||||
serde_json::from_str(response.pdu.get()).map_err(|e| {
|
||||
warn!(
|
||||
"Requested event ID {event_id} from server but failed to convert from \
|
||||
RawValue to CanonicalJsonObject (malformed event/response?): {e}"
|
||||
);
|
||||
Error::BadRequest(
|
||||
ErrorKind::Unknown,
|
||||
"Received response from server but failed to parse PDU",
|
||||
)
|
||||
})?;
|
||||
|
||||
trace!("Attempting to parse PDU: {:?}", &response.pdu);
|
||||
let _parsed_pdu = {
|
||||
|
@ -229,8 +247,8 @@ pub(super) async fn get_remote_pdu(
|
|||
.await;
|
||||
|
||||
let (event_id, value, room_id) = match parsed_result {
|
||||
Ok(t) => t,
|
||||
Err(e) => {
|
||||
| Ok(t) => t,
|
||||
| Err(e) => {
|
||||
warn!("Failed to parse PDU: {e}");
|
||||
info!("Full PDU: {:?}", &response.pdu);
|
||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||
|
@ -250,21 +268,27 @@ pub(super) async fn get_remote_pdu(
|
|||
.boxed()
|
||||
.await?;
|
||||
|
||||
let json_text = serde_json::to_string_pretty(&json).expect("canonical json is valid json");
|
||||
let json_text =
|
||||
serde_json::to_string_pretty(&json).expect("canonical json is valid json");
|
||||
|
||||
Ok(RoomMessageEventContent::notice_markdown(format!(
|
||||
"{}\n```json\n{}\n```",
|
||||
"Got PDU from specified server and handled as backfilled PDU successfully. Event body:", json_text
|
||||
"Got PDU from specified server and handled as backfilled PDU successfully. \
|
||||
Event body:",
|
||||
json_text
|
||||
)))
|
||||
},
|
||||
Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
| Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Remote server did not have PDU or failed sending request to remote server: {e}"
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn get_room_state(&self, room: OwnedRoomOrAliasId) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn get_room_state(
|
||||
&self,
|
||||
room: OwnedRoomOrAliasId,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let room_id = self.services.rooms.alias.resolve(&room).await?;
|
||||
let room_state: Vec<_> = self
|
||||
.services
|
||||
|
@ -285,7 +309,8 @@ pub(super) async fn get_room_state(&self, room: OwnedRoomOrAliasId) -> Result<Ro
|
|||
let json = serde_json::to_string_pretty(&room_state).map_err(|e| {
|
||||
warn!("Failed converting room state vector in our database to pretty JSON: {e}");
|
||||
Error::bad_database(
|
||||
"Failed to convert room state events to pretty JSON, possible invalid room state events in our database",
|
||||
"Failed to convert room state events to pretty JSON, possible invalid room state \
|
||||
events in our database",
|
||||
)
|
||||
})?;
|
||||
|
||||
|
@ -305,10 +330,13 @@ pub(super) async fn ping(&self, server: Box<ServerName>) -> Result<RoomMessageEv
|
|||
match self
|
||||
.services
|
||||
.sending
|
||||
.send_federation_request(&server, ruma::api::federation::discovery::get_server_version::v1::Request {})
|
||||
.send_federation_request(
|
||||
&server,
|
||||
ruma::api::federation::discovery::get_server_version::v1::Request {},
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(response) => {
|
||||
| Ok(response) => {
|
||||
let ping_time = timer.elapsed();
|
||||
|
||||
let json_text_res = serde_json::to_string_pretty(&response.server);
|
||||
|
@ -323,8 +351,11 @@ pub(super) async fn ping(&self, server: Box<ServerName>) -> Result<RoomMessageEv
|
|||
"Got non-JSON response which took {ping_time:?} time:\n{response:?}"
|
||||
)))
|
||||
},
|
||||
Err(e) => {
|
||||
warn!("Failed sending federation request to specified server from ping debug command: {e}");
|
||||
| Err(e) => {
|
||||
warn!(
|
||||
"Failed sending federation request to specified server from ping debug command: \
|
||||
{e}"
|
||||
);
|
||||
Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Failed sending federation request to specified server:\n\n{e}",
|
||||
)))
|
||||
|
@ -347,13 +378,17 @@ pub(super) async fn force_device_list_updates(&self) -> Result<RoomMessageEventC
|
|||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn change_log_level(&self, filter: Option<String>, reset: bool) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn change_log_level(
|
||||
&self,
|
||||
filter: Option<String>,
|
||||
reset: bool,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let handles = &["console"];
|
||||
|
||||
if reset {
|
||||
let old_filter_layer = match EnvFilter::try_new(&self.services.globals.config.log) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
| Ok(s) => s,
|
||||
| Err(e) => {
|
||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Log level from config appears to be invalid now: {e}"
|
||||
)));
|
||||
|
@ -367,13 +402,13 @@ pub(super) async fn change_log_level(&self, filter: Option<String>, reset: bool)
|
|||
.reload
|
||||
.reload(&old_filter_layer, Some(handles))
|
||||
{
|
||||
Ok(()) => {
|
||||
| Ok(()) => {
|
||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Successfully changed log level back to config value {}",
|
||||
self.services.globals.config.log
|
||||
)));
|
||||
},
|
||||
Err(e) => {
|
||||
| Err(e) => {
|
||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Failed to modify and reload the global tracing log level: {e}"
|
||||
)));
|
||||
|
@ -383,8 +418,8 @@ pub(super) async fn change_log_level(&self, filter: Option<String>, reset: bool)
|
|||
|
||||
if let Some(filter) = filter {
|
||||
let new_filter_layer = match EnvFilter::try_new(filter) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
| Ok(s) => s,
|
||||
| Err(e) => {
|
||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Invalid log level filter specified: {e}"
|
||||
)));
|
||||
|
@ -398,10 +433,10 @@ pub(super) async fn change_log_level(&self, filter: Option<String>, reset: bool)
|
|||
.reload
|
||||
.reload(&new_filter_layer, Some(handles))
|
||||
{
|
||||
Ok(()) => {
|
||||
| Ok(()) => {
|
||||
return Ok(RoomMessageEventContent::text_plain("Successfully changed log level"));
|
||||
},
|
||||
Err(e) => {
|
||||
| Err(e) => {
|
||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Failed to modify and reload the global tracing log level: {e}"
|
||||
)));
|
||||
|
@ -414,7 +449,9 @@ pub(super) async fn change_log_level(&self, filter: Option<String>, reset: bool)
|
|||
|
||||
#[admin_command]
|
||||
pub(super) async fn sign_json(&self) -> Result<RoomMessageEventContent> {
|
||||
if self.body.len() < 2 || !self.body[0].trim().starts_with("```") || self.body.last().unwrap_or(&"").trim() != "```"
|
||||
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.",
|
||||
|
@ -423,21 +460,24 @@ pub(super) async fn sign_json(&self) -> Result<RoomMessageEventContent> {
|
|||
|
||||
let string = self.body[1..self.body.len().checked_sub(1).unwrap()].join("\n");
|
||||
match serde_json::from_str(&string) {
|
||||
Ok(mut value) => {
|
||||
| Ok(mut value) => {
|
||||
self.services
|
||||
.server_keys
|
||||
.sign_json(&mut value)
|
||||
.expect("our request json is what ruma expects");
|
||||
let json_text = serde_json::to_string_pretty(&value).expect("canonical json is valid json");
|
||||
let json_text =
|
||||
serde_json::to_string_pretty(&value).expect("canonical json is valid json");
|
||||
Ok(RoomMessageEventContent::text_plain(json_text))
|
||||
},
|
||||
Err(e) => Ok(RoomMessageEventContent::text_plain(format!("Invalid json: {e}"))),
|
||||
| Err(e) => Ok(RoomMessageEventContent::text_plain(format!("Invalid json: {e}"))),
|
||||
}
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn verify_json(&self) -> Result<RoomMessageEventContent> {
|
||||
if self.body.len() < 2 || !self.body[0].trim().starts_with("```") || self.body.last().unwrap_or(&"").trim() != "```"
|
||||
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.",
|
||||
|
@ -446,13 +486,13 @@ pub(super) async fn verify_json(&self) -> Result<RoomMessageEventContent> {
|
|||
|
||||
let string = self.body[1..self.body.len().checked_sub(1).unwrap()].join("\n");
|
||||
match serde_json::from_str::<CanonicalJsonObject>(&string) {
|
||||
Ok(value) => match self.services.server_keys.verify_json(&value, None).await {
|
||||
Ok(()) => Ok(RoomMessageEventContent::text_plain("Signature correct")),
|
||||
Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
| Ok(value) => match self.services.server_keys.verify_json(&value, None).await {
|
||||
| Ok(()) => Ok(RoomMessageEventContent::text_plain("Signature correct")),
|
||||
| Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Signature verification failed: {e}"
|
||||
))),
|
||||
},
|
||||
Err(e) => Ok(RoomMessageEventContent::text_plain(format!("Invalid json: {e}"))),
|
||||
| Err(e) => Ok(RoomMessageEventContent::text_plain(format!("Invalid json: {e}"))),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -462,9 +502,10 @@ pub(super) async fn verify_pdu(&self, event_id: Box<EventId>) -> Result<RoomMess
|
|||
|
||||
event.remove("event_id");
|
||||
let msg = match self.services.server_keys.verify_event(&event, None).await {
|
||||
Ok(ruma::signatures::Verified::Signatures) => "signatures OK, but content hash failed (redaction).",
|
||||
Ok(ruma::signatures::Verified::All) => "signatures and hashes OK.",
|
||||
Err(e) => return Err(e),
|
||||
| Ok(ruma::signatures::Verified::Signatures) =>
|
||||
"signatures OK, but content hash failed (redaction).",
|
||||
| Ok(ruma::signatures::Verified::All) => "signatures and hashes OK.",
|
||||
| Err(e) => return Err(e),
|
||||
};
|
||||
|
||||
Ok(RoomMessageEventContent::notice_plain(msg))
|
||||
|
@ -472,7 +513,10 @@ pub(super) async fn verify_pdu(&self, event_id: Box<EventId>) -> Result<RoomMess
|
|||
|
||||
#[admin_command]
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub(super) async fn first_pdu_in_room(&self, room_id: Box<RoomId>) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn first_pdu_in_room(
|
||||
&self,
|
||||
room_id: Box<RoomId>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
if !self
|
||||
.services
|
||||
.rooms
|
||||
|
@ -498,7 +542,10 @@ pub(super) async fn first_pdu_in_room(&self, room_id: Box<RoomId>) -> Result<Roo
|
|||
|
||||
#[admin_command]
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub(super) async fn latest_pdu_in_room(&self, room_id: Box<RoomId>) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn latest_pdu_in_room(
|
||||
&self,
|
||||
room_id: Box<RoomId>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
if !self
|
||||
.services
|
||||
.rooms
|
||||
|
@ -525,7 +572,9 @@ pub(super) async fn latest_pdu_in_room(&self, room_id: Box<RoomId>) -> Result<Ro
|
|||
#[admin_command]
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub(super) async fn force_set_room_state_from_server(
|
||||
&self, room_id: Box<RoomId>, server_name: Box<ServerName>,
|
||||
&self,
|
||||
room_id: Box<RoomId>,
|
||||
server_name: Box<ServerName>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
if !self
|
||||
.services
|
||||
|
@ -554,13 +603,10 @@ pub(super) async fn force_set_room_state_from_server(
|
|||
let remote_state_response = self
|
||||
.services
|
||||
.sending
|
||||
.send_federation_request(
|
||||
&server_name,
|
||||
get_room_state::v1::Request {
|
||||
room_id: room_id.clone().into(),
|
||||
event_id: first_pdu.event_id.clone().into(),
|
||||
},
|
||||
)
|
||||
.send_federation_request(&server_name, get_room_state::v1::Request {
|
||||
room_id: room_id.clone().into(),
|
||||
event_id: first_pdu.event_id.clone().into(),
|
||||
})
|
||||
.await?;
|
||||
|
||||
for pdu in remote_state_response.pdus.clone() {
|
||||
|
@ -571,8 +617,8 @@ pub(super) async fn force_set_room_state_from_server(
|
|||
.parse_incoming_pdu(&pdu)
|
||||
.await
|
||||
{
|
||||
Ok(t) => t,
|
||||
Err(e) => {
|
||||
| Ok(t) => t,
|
||||
| Err(e) => {
|
||||
warn!("Could not parse PDU, ignoring: {e}");
|
||||
continue;
|
||||
},
|
||||
|
@ -654,8 +700,8 @@ pub(super) async fn force_set_room_state_from_server(
|
|||
.await?;
|
||||
|
||||
info!(
|
||||
"Updating joined counts for room just in case (e.g. we may have found a difference in the room's \
|
||||
m.room.member state"
|
||||
"Updating joined counts for room just in case (e.g. we may have found a difference in \
|
||||
the room's m.room.member state"
|
||||
);
|
||||
self.services
|
||||
.rooms
|
||||
|
@ -672,9 +718,13 @@ pub(super) async fn force_set_room_state_from_server(
|
|||
|
||||
#[admin_command]
|
||||
pub(super) async fn get_signing_keys(
|
||||
&self, server_name: Option<Box<ServerName>>, notary: Option<Box<ServerName>>, query: bool,
|
||||
&self,
|
||||
server_name: Option<Box<ServerName>>,
|
||||
notary: Option<Box<ServerName>>,
|
||||
query: bool,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let server_name = server_name.unwrap_or_else(|| self.services.server.config.server_name.clone().into());
|
||||
let server_name =
|
||||
server_name.unwrap_or_else(|| self.services.server.config.server_name.clone().into());
|
||||
|
||||
if let Some(notary) = notary {
|
||||
let signing_keys = self
|
||||
|
@ -706,8 +756,12 @@ pub(super) async fn get_signing_keys(
|
|||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn get_verify_keys(&self, server_name: Option<Box<ServerName>>) -> Result<RoomMessageEventContent> {
|
||||
let server_name = server_name.unwrap_or_else(|| self.services.server.config.server_name.clone().into());
|
||||
pub(super) async fn get_verify_keys(
|
||||
&self,
|
||||
server_name: Option<Box<ServerName>>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let server_name =
|
||||
server_name.unwrap_or_else(|| self.services.server.config.server_name.clone().into());
|
||||
|
||||
let keys = self
|
||||
.services
|
||||
|
@ -727,7 +781,9 @@ pub(super) async fn get_verify_keys(&self, server_name: Option<Box<ServerName>>)
|
|||
|
||||
#[admin_command]
|
||||
pub(super) async fn resolve_true_destination(
|
||||
&self, server_name: Box<ServerName>, no_cache: bool,
|
||||
&self,
|
||||
server_name: Box<ServerName>,
|
||||
no_cache: bool,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
if !self.services.globals.config.allow_federation {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
|
@ -737,7 +793,8 @@ pub(super) async fn resolve_true_destination(
|
|||
|
||||
if server_name == self.services.globals.config.server_name {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"Not allowed to send federation requests to ourselves. Please use `get-pdu` for fetching local PDUs.",
|
||||
"Not allowed to send federation requests to ourselves. Please use `get-pdu` for \
|
||||
fetching local PDUs.",
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -846,7 +903,9 @@ pub(super) async fn list_dependencies(&self, names: bool) -> Result<RoomMessageE
|
|||
|
||||
#[admin_command]
|
||||
pub(super) async fn database_stats(
|
||||
&self, property: Option<String>, map: Option<String>,
|
||||
&self,
|
||||
property: Option<String>,
|
||||
map: Option<String>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let property = property.unwrap_or_else(|| "rocksdb.stats".to_owned());
|
||||
let map_name = map.as_ref().map_or(EMPTY, String::as_str);
|
||||
|
|
|
@ -2,7 +2,9 @@ use std::fmt::Write;
|
|||
|
||||
use conduwuit::Result;
|
||||
use futures::StreamExt;
|
||||
use ruma::{events::room::message::RoomMessageEventContent, OwnedRoomId, RoomId, ServerName, UserId};
|
||||
use ruma::{
|
||||
events::room::message::RoomMessageEventContent, OwnedRoomId, RoomId, ServerName, UserId,
|
||||
};
|
||||
|
||||
use crate::{admin_command, get_room_info};
|
||||
|
||||
|
@ -38,7 +40,10 @@ pub(super) async fn incoming_federation(&self) -> Result<RoomMessageEventContent
|
|||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn fetch_support_well_known(&self, server_name: Box<ServerName>) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn fetch_support_well_known(
|
||||
&self,
|
||||
server_name: Box<ServerName>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let response = self
|
||||
.services
|
||||
.client
|
||||
|
@ -60,16 +65,20 @@ pub(super) async fn fetch_support_well_known(&self, server_name: Box<ServerName>
|
|||
}
|
||||
|
||||
let json: serde_json::Value = match serde_json::from_str(&text) {
|
||||
Ok(json) => json,
|
||||
Err(_) => {
|
||||
return Ok(RoomMessageEventContent::text_plain("Response text/body is not valid JSON."));
|
||||
| Ok(json) => json,
|
||||
| Err(_) => {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"Response text/body is not valid JSON.",
|
||||
));
|
||||
},
|
||||
};
|
||||
|
||||
let pretty_json: String = match serde_json::to_string_pretty(&json) {
|
||||
Ok(json) => json,
|
||||
Err(_) => {
|
||||
return Ok(RoomMessageEventContent::text_plain("Response text/body is not valid JSON."));
|
||||
| Ok(json) => json,
|
||||
| Err(_) => {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"Response text/body is not valid JSON.",
|
||||
));
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -79,10 +88,14 @@ pub(super) async fn fetch_support_well_known(&self, server_name: Box<ServerName>
|
|||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn remote_user_in_rooms(&self, user_id: Box<UserId>) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn remote_user_in_rooms(
|
||||
&self,
|
||||
user_id: Box<UserId>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
if user_id.server_name() == self.services.globals.config.server_name {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"User belongs to our server, please use `list-joined-rooms` user admin command instead.",
|
||||
"User belongs to our server, please use `list-joined-rooms` user admin command \
|
||||
instead.",
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,21 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use conduwuit::{debug, debug_info, debug_warn, error, info, trace, utils::time::parse_timepoint_ago, Result};
|
||||
use conduwuit::{
|
||||
debug, debug_info, debug_warn, error, info, trace, utils::time::parse_timepoint_ago, Result,
|
||||
};
|
||||
use conduwuit_service::media::Dim;
|
||||
use ruma::{
|
||||
events::room::message::RoomMessageEventContent, EventId, Mxc, MxcUri, OwnedMxcUri, OwnedServerName, ServerName,
|
||||
events::room::message::RoomMessageEventContent, EventId, Mxc, MxcUri, OwnedMxcUri,
|
||||
OwnedServerName, ServerName,
|
||||
};
|
||||
|
||||
use crate::{admin_command, utils::parse_local_user_id};
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn delete(
|
||||
&self, mxc: Option<Box<MxcUri>>, event_id: Option<Box<EventId>>,
|
||||
&self,
|
||||
mxc: Option<Box<MxcUri>>,
|
||||
event_id: Option<Box<EventId>>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
if event_id.is_some() && mxc.is_some() {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
|
@ -52,7 +57,10 @@ pub(super) async fn delete(
|
|||
let final_url = url.to_string().replace('"', "");
|
||||
mxc_urls.push(final_url);
|
||||
} else {
|
||||
info!("Found a URL in the event ID {event_id} but did not start with mxc://, ignoring");
|
||||
info!(
|
||||
"Found a URL in the event ID {event_id} but did not start with \
|
||||
mxc://, ignoring"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,17 +75,24 @@ pub(super) async fn delete(
|
|||
debug!("Found a thumbnail_url in info key: {thumbnail_url}");
|
||||
|
||||
if thumbnail_url.to_string().starts_with("\"mxc://") {
|
||||
debug!("Pushing thumbnail URL {thumbnail_url} to list of MXCs to delete");
|
||||
let final_thumbnail_url = thumbnail_url.to_string().replace('"', "");
|
||||
debug!(
|
||||
"Pushing thumbnail URL {thumbnail_url} to list of MXCs \
|
||||
to delete"
|
||||
);
|
||||
let final_thumbnail_url =
|
||||
thumbnail_url.to_string().replace('"', "");
|
||||
mxc_urls.push(final_thumbnail_url);
|
||||
} else {
|
||||
info!(
|
||||
"Found a thumbnail URL in the event ID {event_id} but did not start with \
|
||||
mxc://, ignoring"
|
||||
"Found a thumbnail URL in the event ID {event_id} but \
|
||||
did not start with mxc://, ignoring"
|
||||
);
|
||||
}
|
||||
} else {
|
||||
info!("No \"thumbnail_url\" key in \"info\" key, assuming no thumbnails.");
|
||||
info!(
|
||||
"No \"thumbnail_url\" key in \"info\" key, assuming no \
|
||||
thumbnails."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -98,8 +113,8 @@ pub(super) async fn delete(
|
|||
mxc_urls.push(final_url);
|
||||
} else {
|
||||
info!(
|
||||
"Found a URL in the event ID {event_id} but did not start with mxc://, \
|
||||
ignoring"
|
||||
"Found a URL in the event ID {event_id} but did not \
|
||||
start with mxc://, ignoring"
|
||||
);
|
||||
}
|
||||
} else {
|
||||
|
@ -109,13 +124,14 @@ pub(super) async fn delete(
|
|||
}
|
||||
} else {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"Event ID does not have a \"content\" key or failed parsing the event ID JSON.",
|
||||
"Event ID does not have a \"content\" key or failed parsing the event \
|
||||
ID JSON.",
|
||||
));
|
||||
}
|
||||
} else {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"Event ID does not have a \"content\" key, this is not a message or an event type that contains \
|
||||
media.",
|
||||
"Event ID does not have a \"content\" key, this is not a message or an \
|
||||
event type that contains media.",
|
||||
));
|
||||
}
|
||||
} else {
|
||||
|
@ -126,7 +142,9 @@ pub(super) async fn delete(
|
|||
|
||||
if mxc_urls.is_empty() {
|
||||
info!("Parsed event ID {event_id} but did not contain any MXC URLs.");
|
||||
return Ok(RoomMessageEventContent::text_plain("Parsed event ID but found no MXC URLs."));
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"Parsed event ID but found no MXC URLs.",
|
||||
));
|
||||
}
|
||||
|
||||
let mut mxc_deletion_count: usize = 0;
|
||||
|
@ -138,11 +156,11 @@ pub(super) async fn delete(
|
|||
.delete(&mxc_url.as_str().try_into()?)
|
||||
.await
|
||||
{
|
||||
Ok(()) => {
|
||||
| Ok(()) => {
|
||||
debug_info!("Successfully deleted {mxc_url} from filesystem and database");
|
||||
mxc_deletion_count = mxc_deletion_count.saturating_add(1);
|
||||
},
|
||||
Err(e) => {
|
||||
| Err(e) => {
|
||||
debug_warn!("Failed to delete {mxc_url}, ignoring error and skipping: {e}");
|
||||
continue;
|
||||
},
|
||||
|
@ -150,19 +168,22 @@ pub(super) async fn delete(
|
|||
}
|
||||
|
||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Deleted {mxc_deletion_count} total MXCs from our database and the filesystem from event ID {event_id}."
|
||||
"Deleted {mxc_deletion_count} total MXCs from our database and the filesystem from \
|
||||
event ID {event_id}."
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(RoomMessageEventContent::text_plain(
|
||||
"Please specify either an MXC using --mxc or an event ID using --event-id of the message containing an image. \
|
||||
See --help for details.",
|
||||
"Please specify either an MXC using --mxc or an event ID using --event-id of the \
|
||||
message containing an image. See --help for details.",
|
||||
))
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn delete_list(&self) -> Result<RoomMessageEventContent> {
|
||||
if self.body.len() < 2 || !self.body[0].trim().starts_with("```") || self.body.last().unwrap_or(&"").trim() != "```"
|
||||
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.",
|
||||
|
@ -192,11 +213,11 @@ pub(super) async fn delete_list(&self) -> Result<RoomMessageEventContent> {
|
|||
for mxc in &mxc_list {
|
||||
trace!(%failed_parsed_mxcs, %mxc_deletion_count, "Deleting MXC {mxc} in bulk");
|
||||
match self.services.media.delete(mxc).await {
|
||||
Ok(()) => {
|
||||
| Ok(()) => {
|
||||
debug_info!("Successfully deleted {mxc} from filesystem and database");
|
||||
mxc_deletion_count = mxc_deletion_count.saturating_add(1);
|
||||
},
|
||||
Err(e) => {
|
||||
| Err(e) => {
|
||||
debug_warn!("Failed to delete {mxc}, ignoring error and skipping: {e}");
|
||||
continue;
|
||||
},
|
||||
|
@ -204,14 +225,18 @@ pub(super) async fn delete_list(&self) -> Result<RoomMessageEventContent> {
|
|||
}
|
||||
|
||||
Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Finished bulk MXC deletion, deleted {mxc_deletion_count} total MXCs from our database and the filesystem. \
|
||||
{failed_parsed_mxcs} MXCs failed to be parsed from the database.",
|
||||
"Finished bulk MXC deletion, deleted {mxc_deletion_count} total MXCs from our database \
|
||||
and the filesystem. {failed_parsed_mxcs} MXCs failed to be parsed from the database.",
|
||||
)))
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn delete_past_remote_media(
|
||||
&self, duration: String, before: bool, after: bool, yes_i_want_to_delete_local_media: bool,
|
||||
&self,
|
||||
duration: String,
|
||||
before: bool,
|
||||
after: bool,
|
||||
yes_i_want_to_delete_local_media: bool,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
if before && after {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
|
@ -224,7 +249,12 @@ pub(super) async fn delete_past_remote_media(
|
|||
let deleted_count = self
|
||||
.services
|
||||
.media
|
||||
.delete_all_remote_media_at_after_time(duration, before, after, yes_i_want_to_delete_local_media)
|
||||
.delete_all_remote_media_at_after_time(
|
||||
duration,
|
||||
before,
|
||||
after,
|
||||
yes_i_want_to_delete_local_media,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(RoomMessageEventContent::text_plain(format!(
|
||||
|
@ -233,7 +263,10 @@ pub(super) async fn delete_past_remote_media(
|
|||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn delete_all_from_user(&self, username: String) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn delete_all_from_user(
|
||||
&self,
|
||||
username: String,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let user_id = parse_local_user_id(self.services, &username)?;
|
||||
|
||||
let deleted_count = self.services.media.delete_from_user(&user_id).await?;
|
||||
|
@ -245,7 +278,9 @@ pub(super) async fn delete_all_from_user(&self, username: String) -> Result<Room
|
|||
|
||||
#[admin_command]
|
||||
pub(super) async fn delete_all_from_server(
|
||||
&self, server_name: Box<ServerName>, yes_i_want_to_delete_local_media: bool,
|
||||
&self,
|
||||
server_name: Box<ServerName>,
|
||||
yes_i_want_to_delete_local_media: bool,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
if server_name == self.services.globals.server_name() && !yes_i_want_to_delete_local_media {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
|
@ -260,20 +295,26 @@ pub(super) async fn delete_all_from_server(
|
|||
.await
|
||||
.inspect_err(|e| error!("Failed to get MXC URIs from our database: {e}"))
|
||||
else {
|
||||
return Ok(RoomMessageEventContent::text_plain("Failed to get MXC URIs from our database"));
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"Failed to get MXC URIs from our database",
|
||||
));
|
||||
};
|
||||
|
||||
let mut deleted_count: usize = 0;
|
||||
|
||||
for mxc in all_mxcs {
|
||||
let Ok(mxc_server_name) = mxc.server_name().inspect_err(|e| {
|
||||
debug_warn!("Failed to parse MXC {mxc} server name from database, ignoring error and skipping: {e}");
|
||||
debug_warn!(
|
||||
"Failed to parse MXC {mxc} server name from database, ignoring error and \
|
||||
skipping: {e}"
|
||||
);
|
||||
}) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if mxc_server_name != server_name
|
||||
|| (self.services.globals.server_is_ours(mxc_server_name) && !yes_i_want_to_delete_local_media)
|
||||
|| (self.services.globals.server_is_ours(mxc_server_name)
|
||||
&& !yes_i_want_to_delete_local_media)
|
||||
{
|
||||
trace!("skipping MXC URI {mxc}");
|
||||
continue;
|
||||
|
@ -282,10 +323,10 @@ pub(super) async fn delete_all_from_server(
|
|||
let mxc: Mxc<'_> = mxc.as_str().try_into()?;
|
||||
|
||||
match self.services.media.delete(&mxc).await {
|
||||
Ok(()) => {
|
||||
| Ok(()) => {
|
||||
deleted_count = deleted_count.saturating_add(1);
|
||||
},
|
||||
Err(e) => {
|
||||
| Err(e) => {
|
||||
debug_warn!("Failed to delete {mxc}, ignoring error and skipping: {e}");
|
||||
continue;
|
||||
},
|
||||
|
@ -307,7 +348,10 @@ pub(super) async fn get_file_info(&self, mxc: OwnedMxcUri) -> Result<RoomMessage
|
|||
|
||||
#[admin_command]
|
||||
pub(super) async fn get_remote_file(
|
||||
&self, mxc: OwnedMxcUri, server: Option<OwnedServerName>, timeout: u32,
|
||||
&self,
|
||||
mxc: OwnedMxcUri,
|
||||
server: Option<OwnedServerName>,
|
||||
timeout: u32,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let mxc: Mxc<'_> = mxc.as_str().try_into()?;
|
||||
let timeout = Duration::from_millis(timeout.into());
|
||||
|
@ -327,7 +371,12 @@ pub(super) async fn get_remote_file(
|
|||
|
||||
#[admin_command]
|
||||
pub(super) async fn get_remote_thumbnail(
|
||||
&self, mxc: OwnedMxcUri, server: Option<OwnedServerName>, timeout: u32, width: u32, height: u32,
|
||||
&self,
|
||||
mxc: OwnedMxcUri,
|
||||
server: Option<OwnedServerName>,
|
||||
timeout: u32,
|
||||
width: u32,
|
||||
height: u32,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let mxc: Mxc<'_> = mxc.as_str().try_into()?;
|
||||
let timeout = Duration::from_millis(timeout.into());
|
||||
|
|
|
@ -53,8 +53,8 @@ async fn handle_command(services: Arc<Services>, command: CommandInput) -> Proce
|
|||
|
||||
async fn process_command(services: Arc<Services>, input: &CommandInput) -> ProcessorResult {
|
||||
let (command, args, body) = match parse(&services, input) {
|
||||
Err(error) => return Err(error),
|
||||
Ok(parsed) => parsed,
|
||||
| Err(error) => return Err(error),
|
||||
| Ok(parsed) => parsed,
|
||||
};
|
||||
|
||||
let context = Command {
|
||||
|
@ -68,7 +68,8 @@ async fn process_command(services: Arc<Services>, input: &CommandInput) -> Proce
|
|||
}
|
||||
|
||||
fn handle_panic(error: &Error, command: &CommandInput) -> ProcessorResult {
|
||||
let link = "Please submit a [bug report](https://github.com/girlbossceo/conduwuit/issues/new). 🥺";
|
||||
let link =
|
||||
"Please submit a [bug report](https://github.com/girlbossceo/conduwuit/issues/new). 🥺";
|
||||
let msg = format!("Panic occurred while processing command:\n```\n{error:#?}\n```\n{link}");
|
||||
let content = RoomMessageEventContent::notice_markdown(msg);
|
||||
error!("Panic while processing command: {error:?}");
|
||||
|
@ -76,7 +77,11 @@ fn handle_panic(error: &Error, command: &CommandInput) -> ProcessorResult {
|
|||
}
|
||||
|
||||
// Parse and process a message from the admin room
|
||||
async fn process(context: &Command<'_>, command: AdminCommand, args: &[String]) -> ProcessorResult {
|
||||
async fn process(
|
||||
context: &Command<'_>,
|
||||
command: AdminCommand,
|
||||
args: &[String],
|
||||
) -> ProcessorResult {
|
||||
let (capture, logs) = capture_create(context);
|
||||
|
||||
let capture_scope = capture.start();
|
||||
|
@ -100,11 +105,12 @@ async fn process(context: &Command<'_>, command: AdminCommand, args: &[String])
|
|||
drop(logs);
|
||||
|
||||
match result {
|
||||
Ok(content) => {
|
||||
write!(&mut output, "{0}", content.body()).expect("failed to format command result to output buffer");
|
||||
| Ok(content) => {
|
||||
write!(&mut output, "{0}", content.body())
|
||||
.expect("failed to format command result to output buffer");
|
||||
Ok(Some(reply(RoomMessageEventContent::notice_markdown(output), context.reply_id)))
|
||||
},
|
||||
Err(error) => {
|
||||
| Err(error) => {
|
||||
write!(&mut output, "Command failed with error:\n```\n{error:#?}\n```")
|
||||
.expect("failed to format command result to output");
|
||||
Err(reply(RoomMessageEventContent::notice_markdown(output), context.reply_id))
|
||||
|
@ -128,8 +134,9 @@ fn capture_create(context: &Command<'_>) -> (Arc<Capture>, Arc<Mutex<String>>) {
|
|||
.and_then(LevelFilter::into_level)
|
||||
.unwrap_or(Level::DEBUG);
|
||||
|
||||
let filter =
|
||||
move |data: capture::Data<'_>| data.level() <= log_level && data.our_modules() && data.scope.contains(&"admin");
|
||||
let filter = move |data: capture::Data<'_>| {
|
||||
data.level() <= log_level && data.our_modules() && data.scope.contains(&"admin")
|
||||
};
|
||||
|
||||
let logs = Arc::new(Mutex::new(
|
||||
collect_stream(|s| markdown_table_head(s)).expect("markdown table header"),
|
||||
|
@ -146,14 +153,15 @@ fn capture_create(context: &Command<'_>) -> (Arc<Capture>, Arc<Mutex<String>>) {
|
|||
|
||||
// Parse chat messages from the admin room into an AdminCommand object
|
||||
fn parse<'a>(
|
||||
services: &Arc<Services>, input: &'a CommandInput,
|
||||
services: &Arc<Services>,
|
||||
input: &'a CommandInput,
|
||||
) -> Result<(AdminCommand, Vec<String>, Vec<&'a str>), CommandOutput> {
|
||||
let lines = input.command.lines().filter(|line| !line.trim().is_empty());
|
||||
let command_line = lines.clone().next().expect("command missing first line");
|
||||
let body = lines.skip(1).collect();
|
||||
match parse_command(command_line) {
|
||||
Ok((command, args)) => Ok((command, args, body)),
|
||||
Err(error) => {
|
||||
| Ok((command, args)) => Ok((command, args, body)),
|
||||
| Err(error) => {
|
||||
let message = error
|
||||
.to_string()
|
||||
.replace("server.name", services.globals.server_name().as_str());
|
||||
|
@ -255,11 +263,12 @@ fn parse_line(command_line: &str) -> Vec<String> {
|
|||
argv
|
||||
}
|
||||
|
||||
fn reply(mut content: RoomMessageEventContent, reply_id: Option<&EventId>) -> RoomMessageEventContent {
|
||||
fn reply(
|
||||
mut content: RoomMessageEventContent,
|
||||
reply_id: Option<&EventId>,
|
||||
) -> RoomMessageEventContent {
|
||||
content.relates_to = reply_id.map(|event_id| Reply {
|
||||
in_reply_to: InReplyTo {
|
||||
event_id: event_id.to_owned(),
|
||||
},
|
||||
in_reply_to: InReplyTo { event_id: event_id.to_owned() },
|
||||
});
|
||||
|
||||
content
|
||||
|
|
|
@ -30,15 +30,14 @@ pub(crate) enum AccountDataCommand {
|
|||
}
|
||||
|
||||
/// All the getters and iterators from src/database/key_value/account_data.rs
|
||||
pub(super) async fn process(subcommand: AccountDataCommand, context: &Command<'_>) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn process(
|
||||
subcommand: AccountDataCommand,
|
||||
context: &Command<'_>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let services = context.services;
|
||||
|
||||
match subcommand {
|
||||
AccountDataCommand::ChangesSince {
|
||||
user_id,
|
||||
since,
|
||||
room_id,
|
||||
} => {
|
||||
| AccountDataCommand::ChangesSince { user_id, since, room_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results: Vec<_> = services
|
||||
.account_data
|
||||
|
@ -51,11 +50,7 @@ pub(super) async fn process(subcommand: AccountDataCommand, context: &Command<'_
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
|
||||
)))
|
||||
},
|
||||
AccountDataCommand::Get {
|
||||
user_id,
|
||||
kind,
|
||||
room_id,
|
||||
} => {
|
||||
| AccountDataCommand::Get { user_id, kind, room_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services
|
||||
.account_data
|
||||
|
|
|
@ -18,13 +18,14 @@ pub(crate) enum AppserviceCommand {
|
|||
}
|
||||
|
||||
/// All the getters and iterators from src/database/key_value/appservice.rs
|
||||
pub(super) async fn process(subcommand: AppserviceCommand, context: &Command<'_>) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn process(
|
||||
subcommand: AppserviceCommand,
|
||||
context: &Command<'_>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let services = context.services;
|
||||
|
||||
match subcommand {
|
||||
AppserviceCommand::GetRegistration {
|
||||
appservice_id,
|
||||
} => {
|
||||
| AppserviceCommand::GetRegistration { appservice_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services.appservice.get_registration(&appservice_id).await;
|
||||
|
||||
|
@ -34,7 +35,7 @@ pub(super) async fn process(subcommand: AppserviceCommand, context: &Command<'_>
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
|
||||
)))
|
||||
},
|
||||
AppserviceCommand::All => {
|
||||
| AppserviceCommand::All => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services.appservice.all().await;
|
||||
let query_time = timer.elapsed();
|
||||
|
|
|
@ -21,11 +21,14 @@ pub(crate) enum GlobalsCommand {
|
|||
}
|
||||
|
||||
/// All the getters and iterators from src/database/key_value/globals.rs
|
||||
pub(super) async fn process(subcommand: GlobalsCommand, context: &Command<'_>) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn process(
|
||||
subcommand: GlobalsCommand,
|
||||
context: &Command<'_>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let services = context.services;
|
||||
|
||||
match subcommand {
|
||||
GlobalsCommand::DatabaseVersion => {
|
||||
| GlobalsCommand::DatabaseVersion => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services.globals.db.database_version().await;
|
||||
let query_time = timer.elapsed();
|
||||
|
@ -34,7 +37,7 @@ pub(super) async fn process(subcommand: GlobalsCommand, context: &Command<'_>) -
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
|
||||
)))
|
||||
},
|
||||
GlobalsCommand::CurrentCount => {
|
||||
| GlobalsCommand::CurrentCount => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services.globals.db.current_count();
|
||||
let query_time = timer.elapsed();
|
||||
|
@ -43,7 +46,7 @@ pub(super) async fn process(subcommand: GlobalsCommand, context: &Command<'_>) -
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
|
||||
)))
|
||||
},
|
||||
GlobalsCommand::LastCheckForUpdatesId => {
|
||||
| GlobalsCommand::LastCheckForUpdatesId => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services.updates.last_check_for_updates_id().await;
|
||||
let query_time = timer.elapsed();
|
||||
|
@ -52,9 +55,7 @@ pub(super) async fn process(subcommand: GlobalsCommand, context: &Command<'_>) -
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
|
||||
)))
|
||||
},
|
||||
GlobalsCommand::SigningKeysFor {
|
||||
origin,
|
||||
} => {
|
||||
| GlobalsCommand::SigningKeysFor { origin } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services.server_keys.verify_keys_for(&origin).await;
|
||||
let query_time = timer.elapsed();
|
||||
|
|
|
@ -14,8 +14,9 @@ use conduwuit::Result;
|
|||
|
||||
use self::{
|
||||
account_data::AccountDataCommand, appservice::AppserviceCommand, globals::GlobalsCommand,
|
||||
presence::PresenceCommand, pusher::PusherCommand, resolver::ResolverCommand, room_alias::RoomAliasCommand,
|
||||
room_state_cache::RoomStateCacheCommand, sending::SendingCommand, users::UsersCommand,
|
||||
presence::PresenceCommand, pusher::PusherCommand, resolver::ResolverCommand,
|
||||
room_alias::RoomAliasCommand, room_state_cache::RoomStateCacheCommand,
|
||||
sending::SendingCommand, users::UsersCommand,
|
||||
};
|
||||
use crate::admin_command_dispatch;
|
||||
|
||||
|
|
|
@ -23,13 +23,14 @@ pub(crate) enum PresenceCommand {
|
|||
}
|
||||
|
||||
/// All the getters and iterators in key_value/presence.rs
|
||||
pub(super) async fn process(subcommand: PresenceCommand, context: &Command<'_>) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn process(
|
||||
subcommand: PresenceCommand,
|
||||
context: &Command<'_>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let services = context.services;
|
||||
|
||||
match subcommand {
|
||||
PresenceCommand::GetPresence {
|
||||
user_id,
|
||||
} => {
|
||||
| PresenceCommand::GetPresence { user_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services.presence.db.get_presence(&user_id).await;
|
||||
let query_time = timer.elapsed();
|
||||
|
@ -38,9 +39,7 @@ pub(super) async fn process(subcommand: PresenceCommand, context: &Command<'_>)
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
|
||||
)))
|
||||
},
|
||||
PresenceCommand::PresenceSince {
|
||||
since,
|
||||
} => {
|
||||
| PresenceCommand::PresenceSince { since } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results: Vec<(_, _, _)> = services
|
||||
.presence
|
||||
|
|
|
@ -13,13 +13,14 @@ pub(crate) enum PusherCommand {
|
|||
},
|
||||
}
|
||||
|
||||
pub(super) async fn process(subcommand: PusherCommand, context: &Command<'_>) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn process(
|
||||
subcommand: PusherCommand,
|
||||
context: &Command<'_>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let services = context.services;
|
||||
|
||||
match subcommand {
|
||||
PusherCommand::GetPushers {
|
||||
user_id,
|
||||
} => {
|
||||
| PusherCommand::GetPushers { user_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services.pusher.get_pushers(&user_id).await;
|
||||
let query_time = timer.elapsed();
|
||||
|
|
|
@ -22,20 +22,16 @@ pub(crate) enum ResolverCommand {
|
|||
}
|
||||
|
||||
#[admin_command]
|
||||
async fn destinations_cache(&self, server_name: Option<OwnedServerName>) -> Result<RoomMessageEventContent> {
|
||||
async fn destinations_cache(
|
||||
&self,
|
||||
server_name: Option<OwnedServerName>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
use service::resolver::cache::CachedDest;
|
||||
|
||||
let mut out = String::new();
|
||||
writeln!(out, "| Server Name | Destination | Hostname | Expires |")?;
|
||||
writeln!(out, "| ----------- | ----------- | -------- | ------- |")?;
|
||||
let row = |(
|
||||
name,
|
||||
&CachedDest {
|
||||
ref dest,
|
||||
ref host,
|
||||
expire,
|
||||
},
|
||||
)| {
|
||||
let row = |(name, &CachedDest { ref dest, ref host, expire })| {
|
||||
let expire = time::format(expire, "%+");
|
||||
writeln!(out, "| {name} | {dest} | {host} | {expire} |").expect("wrote line");
|
||||
};
|
||||
|
@ -64,14 +60,7 @@ async fn overrides_cache(&self, server_name: Option<String>) -> Result<RoomMessa
|
|||
let mut out = String::new();
|
||||
writeln!(out, "| Server Name | IP | Port | Expires |")?;
|
||||
writeln!(out, "| ----------- | --- | ----:| ------- |")?;
|
||||
let row = |(
|
||||
name,
|
||||
&CachedOverride {
|
||||
ref ips,
|
||||
port,
|
||||
expire,
|
||||
},
|
||||
)| {
|
||||
let row = |(name, &CachedOverride { ref ips, port, expire })| {
|
||||
let expire = time::format(expire, "%+");
|
||||
writeln!(out, "| {name} | {ips:?} | {port} | {expire} |").expect("wrote line");
|
||||
};
|
||||
|
|
|
@ -24,13 +24,14 @@ pub(crate) enum RoomAliasCommand {
|
|||
}
|
||||
|
||||
/// All the getters and iterators in src/database/key_value/rooms/alias.rs
|
||||
pub(super) async fn process(subcommand: RoomAliasCommand, context: &Command<'_>) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn process(
|
||||
subcommand: RoomAliasCommand,
|
||||
context: &Command<'_>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let services = context.services;
|
||||
|
||||
match subcommand {
|
||||
RoomAliasCommand::ResolveLocalAlias {
|
||||
alias,
|
||||
} => {
|
||||
| RoomAliasCommand::ResolveLocalAlias { alias } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services.rooms.alias.resolve_local_alias(&alias).await;
|
||||
let query_time = timer.elapsed();
|
||||
|
@ -39,9 +40,7 @@ pub(super) async fn process(subcommand: RoomAliasCommand, context: &Command<'_>)
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
|
||||
)))
|
||||
},
|
||||
RoomAliasCommand::LocalAliasesForRoom {
|
||||
room_id,
|
||||
} => {
|
||||
| RoomAliasCommand::LocalAliasesForRoom { room_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let aliases: Vec<_> = services
|
||||
.rooms
|
||||
|
@ -56,7 +55,7 @@ pub(super) async fn process(subcommand: RoomAliasCommand, context: &Command<'_>)
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{aliases:#?}\n```"
|
||||
)))
|
||||
},
|
||||
RoomAliasCommand::AllLocalAliases => {
|
||||
| RoomAliasCommand::AllLocalAliases => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let aliases = services
|
||||
.rooms
|
||||
|
|
|
@ -77,15 +77,13 @@ pub(crate) enum RoomStateCacheCommand {
|
|||
}
|
||||
|
||||
pub(super) async fn process(
|
||||
subcommand: RoomStateCacheCommand, context: &Command<'_>,
|
||||
subcommand: RoomStateCacheCommand,
|
||||
context: &Command<'_>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let services = context.services;
|
||||
|
||||
match subcommand {
|
||||
RoomStateCacheCommand::ServerInRoom {
|
||||
server,
|
||||
room_id,
|
||||
} => {
|
||||
| RoomStateCacheCommand::ServerInRoom { server, room_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let result = services
|
||||
.rooms
|
||||
|
@ -98,9 +96,7 @@ pub(super) async fn process(
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"
|
||||
)))
|
||||
},
|
||||
RoomStateCacheCommand::RoomServers {
|
||||
room_id,
|
||||
} => {
|
||||
| RoomStateCacheCommand::RoomServers { room_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results: Vec<_> = services
|
||||
.rooms
|
||||
|
@ -115,9 +111,7 @@ pub(super) async fn process(
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
|
||||
)))
|
||||
},
|
||||
RoomStateCacheCommand::ServerRooms {
|
||||
server,
|
||||
} => {
|
||||
| RoomStateCacheCommand::ServerRooms { server } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results: Vec<_> = services
|
||||
.rooms
|
||||
|
@ -132,9 +126,7 @@ pub(super) async fn process(
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
|
||||
)))
|
||||
},
|
||||
RoomStateCacheCommand::RoomMembers {
|
||||
room_id,
|
||||
} => {
|
||||
| RoomStateCacheCommand::RoomMembers { room_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results: Vec<_> = services
|
||||
.rooms
|
||||
|
@ -149,9 +141,7 @@ pub(super) async fn process(
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
|
||||
)))
|
||||
},
|
||||
RoomStateCacheCommand::LocalUsersInRoom {
|
||||
room_id,
|
||||
} => {
|
||||
| RoomStateCacheCommand::LocalUsersInRoom { room_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results: Vec<_> = services
|
||||
.rooms
|
||||
|
@ -166,9 +156,7 @@ pub(super) async fn process(
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
|
||||
)))
|
||||
},
|
||||
RoomStateCacheCommand::ActiveLocalUsersInRoom {
|
||||
room_id,
|
||||
} => {
|
||||
| RoomStateCacheCommand::ActiveLocalUsersInRoom { room_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results: Vec<_> = services
|
||||
.rooms
|
||||
|
@ -183,9 +171,7 @@ pub(super) async fn process(
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
|
||||
)))
|
||||
},
|
||||
RoomStateCacheCommand::RoomJoinedCount {
|
||||
room_id,
|
||||
} => {
|
||||
| RoomStateCacheCommand::RoomJoinedCount { room_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services.rooms.state_cache.room_joined_count(&room_id).await;
|
||||
let query_time = timer.elapsed();
|
||||
|
@ -194,9 +180,7 @@ pub(super) async fn process(
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
|
||||
)))
|
||||
},
|
||||
RoomStateCacheCommand::RoomInvitedCount {
|
||||
room_id,
|
||||
} => {
|
||||
| RoomStateCacheCommand::RoomInvitedCount { room_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services
|
||||
.rooms
|
||||
|
@ -209,9 +193,7 @@ pub(super) async fn process(
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
|
||||
)))
|
||||
},
|
||||
RoomStateCacheCommand::RoomUserOnceJoined {
|
||||
room_id,
|
||||
} => {
|
||||
| RoomStateCacheCommand::RoomUserOnceJoined { room_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results: Vec<_> = services
|
||||
.rooms
|
||||
|
@ -226,9 +208,7 @@ pub(super) async fn process(
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
|
||||
)))
|
||||
},
|
||||
RoomStateCacheCommand::RoomMembersInvited {
|
||||
room_id,
|
||||
} => {
|
||||
| RoomStateCacheCommand::RoomMembersInvited { room_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results: Vec<_> = services
|
||||
.rooms
|
||||
|
@ -243,10 +223,7 @@ pub(super) async fn process(
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
|
||||
)))
|
||||
},
|
||||
RoomStateCacheCommand::GetInviteCount {
|
||||
room_id,
|
||||
user_id,
|
||||
} => {
|
||||
| RoomStateCacheCommand::GetInviteCount { room_id, user_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services
|
||||
.rooms
|
||||
|
@ -259,10 +236,7 @@ pub(super) async fn process(
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
|
||||
)))
|
||||
},
|
||||
RoomStateCacheCommand::GetLeftCount {
|
||||
room_id,
|
||||
user_id,
|
||||
} => {
|
||||
| RoomStateCacheCommand::GetLeftCount { room_id, user_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services
|
||||
.rooms
|
||||
|
@ -275,9 +249,7 @@ pub(super) async fn process(
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
|
||||
)))
|
||||
},
|
||||
RoomStateCacheCommand::RoomsJoined {
|
||||
user_id,
|
||||
} => {
|
||||
| RoomStateCacheCommand::RoomsJoined { user_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results: Vec<_> = services
|
||||
.rooms
|
||||
|
@ -292,9 +264,7 @@ pub(super) async fn process(
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
|
||||
)))
|
||||
},
|
||||
RoomStateCacheCommand::RoomsInvited {
|
||||
user_id,
|
||||
} => {
|
||||
| RoomStateCacheCommand::RoomsInvited { user_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results: Vec<_> = services
|
||||
.rooms
|
||||
|
@ -308,9 +278,7 @@ pub(super) async fn process(
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
|
||||
)))
|
||||
},
|
||||
RoomStateCacheCommand::RoomsLeft {
|
||||
user_id,
|
||||
} => {
|
||||
| RoomStateCacheCommand::RoomsLeft { user_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results: Vec<_> = services
|
||||
.rooms
|
||||
|
@ -324,10 +292,7 @@ pub(super) async fn process(
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
|
||||
)))
|
||||
},
|
||||
RoomStateCacheCommand::InviteState {
|
||||
user_id,
|
||||
room_id,
|
||||
} => {
|
||||
| RoomStateCacheCommand::InviteState { user_id, room_id } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services
|
||||
.rooms
|
||||
|
|
|
@ -62,11 +62,14 @@ pub(crate) enum SendingCommand {
|
|||
}
|
||||
|
||||
/// All the getters and iterators in key_value/sending.rs
|
||||
pub(super) async fn process(subcommand: SendingCommand, context: &Command<'_>) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn process(
|
||||
subcommand: SendingCommand,
|
||||
context: &Command<'_>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let services = context.services;
|
||||
|
||||
match subcommand {
|
||||
SendingCommand::ActiveRequests => {
|
||||
| SendingCommand::ActiveRequests => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services.sending.db.active_requests();
|
||||
let active_requests = results.collect::<Vec<_>>().await;
|
||||
|
@ -76,25 +79,29 @@ pub(super) async fn process(subcommand: SendingCommand, context: &Command<'_>) -
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{active_requests:#?}\n```"
|
||||
)))
|
||||
},
|
||||
SendingCommand::QueuedRequests {
|
||||
| SendingCommand::QueuedRequests {
|
||||
appservice_id,
|
||||
server_name,
|
||||
user_id,
|
||||
push_key,
|
||||
} => {
|
||||
if appservice_id.is_none() && server_name.is_none() && user_id.is_none() && push_key.is_none() {
|
||||
if appservice_id.is_none()
|
||||
&& server_name.is_none()
|
||||
&& user_id.is_none()
|
||||
&& push_key.is_none()
|
||||
{
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"An appservice ID, server name, or a user ID with push key must be specified via arguments. See \
|
||||
--help for more details.",
|
||||
"An appservice ID, server name, or a user ID with push key must be \
|
||||
specified via arguments. See --help for more details.",
|
||||
));
|
||||
}
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = match (appservice_id, server_name, user_id, push_key) {
|
||||
(Some(appservice_id), None, None, None) => {
|
||||
| (Some(appservice_id), None, None, None) => {
|
||||
if appservice_id.is_empty() {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"An appservice ID, server name, or a user ID with push key must be specified via \
|
||||
arguments. See --help for more details.",
|
||||
"An appservice ID, server name, or a user ID with push key must be \
|
||||
specified via arguments. See --help for more details.",
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -103,15 +110,15 @@ pub(super) async fn process(subcommand: SendingCommand, context: &Command<'_>) -
|
|||
.db
|
||||
.queued_requests(&Destination::Appservice(appservice_id))
|
||||
},
|
||||
(None, Some(server_name), None, None) => services
|
||||
| (None, Some(server_name), None, None) => services
|
||||
.sending
|
||||
.db
|
||||
.queued_requests(&Destination::Normal(server_name.into())),
|
||||
(None, None, Some(user_id), Some(push_key)) => {
|
||||
| (None, None, Some(user_id), Some(push_key)) => {
|
||||
if push_key.is_empty() {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"An appservice ID, server name, or a user ID with push key must be specified via \
|
||||
arguments. See --help for more details.",
|
||||
"An appservice ID, server name, or a user ID with push key must be \
|
||||
specified via arguments. See --help for more details.",
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -120,16 +127,16 @@ pub(super) async fn process(subcommand: SendingCommand, context: &Command<'_>) -
|
|||
.db
|
||||
.queued_requests(&Destination::Push(user_id.into(), push_key))
|
||||
},
|
||||
(Some(_), Some(_), Some(_), Some(_)) => {
|
||||
| (Some(_), Some(_), Some(_), Some(_)) => {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"An appservice ID, server name, or a user ID with push key must be specified via arguments. \
|
||||
Not all of them See --help for more details.",
|
||||
"An appservice ID, server name, or a user ID with push key must be \
|
||||
specified via arguments. Not all of them See --help for more details.",
|
||||
));
|
||||
},
|
||||
_ => {
|
||||
| _ => {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"An appservice ID, server name, or a user ID with push key must be specified via arguments. \
|
||||
See --help for more details.",
|
||||
"An appservice ID, server name, or a user ID with push key must be \
|
||||
specified via arguments. See --help for more details.",
|
||||
));
|
||||
},
|
||||
};
|
||||
|
@ -141,26 +148,30 @@ pub(super) async fn process(subcommand: SendingCommand, context: &Command<'_>) -
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{queued_requests:#?}\n```"
|
||||
)))
|
||||
},
|
||||
SendingCommand::ActiveRequestsFor {
|
||||
| SendingCommand::ActiveRequestsFor {
|
||||
appservice_id,
|
||||
server_name,
|
||||
user_id,
|
||||
push_key,
|
||||
} => {
|
||||
if appservice_id.is_none() && server_name.is_none() && user_id.is_none() && push_key.is_none() {
|
||||
if appservice_id.is_none()
|
||||
&& server_name.is_none()
|
||||
&& user_id.is_none()
|
||||
&& push_key.is_none()
|
||||
{
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"An appservice ID, server name, or a user ID with push key must be specified via arguments. See \
|
||||
--help for more details.",
|
||||
"An appservice ID, server name, or a user ID with push key must be \
|
||||
specified via arguments. See --help for more details.",
|
||||
));
|
||||
}
|
||||
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = match (appservice_id, server_name, user_id, push_key) {
|
||||
(Some(appservice_id), None, None, None) => {
|
||||
| (Some(appservice_id), None, None, None) => {
|
||||
if appservice_id.is_empty() {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"An appservice ID, server name, or a user ID with push key must be specified via \
|
||||
arguments. See --help for more details.",
|
||||
"An appservice ID, server name, or a user ID with push key must be \
|
||||
specified via arguments. See --help for more details.",
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -169,15 +180,15 @@ pub(super) async fn process(subcommand: SendingCommand, context: &Command<'_>) -
|
|||
.db
|
||||
.active_requests_for(&Destination::Appservice(appservice_id))
|
||||
},
|
||||
(None, Some(server_name), None, None) => services
|
||||
| (None, Some(server_name), None, None) => services
|
||||
.sending
|
||||
.db
|
||||
.active_requests_for(&Destination::Normal(server_name.into())),
|
||||
(None, None, Some(user_id), Some(push_key)) => {
|
||||
| (None, None, Some(user_id), Some(push_key)) => {
|
||||
if push_key.is_empty() {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"An appservice ID, server name, or a user ID with push key must be specified via \
|
||||
arguments. See --help for more details.",
|
||||
"An appservice ID, server name, or a user ID with push key must be \
|
||||
specified via arguments. See --help for more details.",
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -186,16 +197,16 @@ pub(super) async fn process(subcommand: SendingCommand, context: &Command<'_>) -
|
|||
.db
|
||||
.active_requests_for(&Destination::Push(user_id.into(), push_key))
|
||||
},
|
||||
(Some(_), Some(_), Some(_), Some(_)) => {
|
||||
| (Some(_), Some(_), Some(_), Some(_)) => {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"An appservice ID, server name, or a user ID with push key must be specified via arguments. \
|
||||
Not all of them See --help for more details.",
|
||||
"An appservice ID, server name, or a user ID with push key must be \
|
||||
specified via arguments. Not all of them See --help for more details.",
|
||||
));
|
||||
},
|
||||
_ => {
|
||||
| _ => {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"An appservice ID, server name, or a user ID with push key must be specified via arguments. \
|
||||
See --help for more details.",
|
||||
"An appservice ID, server name, or a user ID with push key must be \
|
||||
specified via arguments. See --help for more details.",
|
||||
));
|
||||
},
|
||||
};
|
||||
|
@ -207,9 +218,7 @@ pub(super) async fn process(subcommand: SendingCommand, context: &Command<'_>) -
|
|||
"Query completed in {query_time:?}:\n\n```rs\n{active_requests:#?}\n```"
|
||||
)))
|
||||
},
|
||||
SendingCommand::GetLatestEduCount {
|
||||
server_name,
|
||||
} => {
|
||||
| SendingCommand::GetLatestEduCount { server_name } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services.sending.db.get_latest_educount(&server_name).await;
|
||||
let query_time = timer.elapsed();
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use clap::Subcommand;
|
||||
use conduwuit::Result;
|
||||
use futures::stream::StreamExt;
|
||||
use ruma::{events::room::message::RoomMessageEventContent, OwnedDeviceId, OwnedRoomId, OwnedUserId};
|
||||
use ruma::{
|
||||
events::room::message::RoomMessageEventContent, OwnedDeviceId, OwnedRoomId, OwnedUserId,
|
||||
};
|
||||
|
||||
use crate::{admin_command, admin_command_dispatch};
|
||||
|
||||
|
@ -91,7 +93,11 @@ pub(crate) enum UsersCommand {
|
|||
|
||||
#[admin_command]
|
||||
async fn get_backup_session(
|
||||
&self, user_id: OwnedUserId, version: String, room_id: OwnedRoomId, session_id: String,
|
||||
&self,
|
||||
user_id: OwnedUserId,
|
||||
version: String,
|
||||
room_id: OwnedRoomId,
|
||||
session_id: String,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let result = self
|
||||
|
@ -108,7 +114,10 @@ async fn get_backup_session(
|
|||
|
||||
#[admin_command]
|
||||
async fn get_room_backups(
|
||||
&self, user_id: OwnedUserId, version: String, room_id: OwnedRoomId,
|
||||
&self,
|
||||
user_id: OwnedUserId,
|
||||
version: String,
|
||||
room_id: OwnedRoomId,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let result = self
|
||||
|
@ -124,7 +133,11 @@ async fn get_room_backups(
|
|||
}
|
||||
|
||||
#[admin_command]
|
||||
async fn get_all_backups(&self, user_id: OwnedUserId, version: String) -> Result<RoomMessageEventContent> {
|
||||
async fn get_all_backups(
|
||||
&self,
|
||||
user_id: OwnedUserId,
|
||||
version: String,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let result = self.services.key_backups.get_all(&user_id, &version).await;
|
||||
let query_time = timer.elapsed();
|
||||
|
@ -135,7 +148,11 @@ async fn get_all_backups(&self, user_id: OwnedUserId, version: String) -> Result
|
|||
}
|
||||
|
||||
#[admin_command]
|
||||
async fn get_backup_algorithm(&self, user_id: OwnedUserId, version: String) -> Result<RoomMessageEventContent> {
|
||||
async fn get_backup_algorithm(
|
||||
&self,
|
||||
user_id: OwnedUserId,
|
||||
version: String,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let result = self
|
||||
.services
|
||||
|
@ -150,7 +167,10 @@ async fn get_backup_algorithm(&self, user_id: OwnedUserId, version: String) -> R
|
|||
}
|
||||
|
||||
#[admin_command]
|
||||
async fn get_latest_backup_version(&self, user_id: OwnedUserId) -> Result<RoomMessageEventContent> {
|
||||
async fn get_latest_backup_version(
|
||||
&self,
|
||||
user_id: OwnedUserId,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let result = self
|
||||
.services
|
||||
|
@ -244,7 +264,11 @@ async fn list_devices_metadata(&self, user_id: OwnedUserId) -> Result<RoomMessag
|
|||
}
|
||||
|
||||
#[admin_command]
|
||||
async fn get_device_metadata(&self, user_id: OwnedUserId, device_id: OwnedDeviceId) -> Result<RoomMessageEventContent> {
|
||||
async fn get_device_metadata(
|
||||
&self,
|
||||
user_id: OwnedUserId,
|
||||
device_id: OwnedDeviceId,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let device = self
|
||||
.services
|
||||
|
@ -270,7 +294,11 @@ async fn get_devices_version(&self, user_id: OwnedUserId) -> Result<RoomMessageE
|
|||
}
|
||||
|
||||
#[admin_command]
|
||||
async fn count_one_time_keys(&self, user_id: OwnedUserId, device_id: OwnedDeviceId) -> Result<RoomMessageEventContent> {
|
||||
async fn count_one_time_keys(
|
||||
&self,
|
||||
user_id: OwnedUserId,
|
||||
device_id: OwnedDeviceId,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let result = self
|
||||
.services
|
||||
|
@ -285,7 +313,11 @@ async fn count_one_time_keys(&self, user_id: OwnedUserId, device_id: OwnedDevice
|
|||
}
|
||||
|
||||
#[admin_command]
|
||||
async fn get_device_keys(&self, user_id: OwnedUserId, device_id: OwnedDeviceId) -> Result<RoomMessageEventContent> {
|
||||
async fn get_device_keys(
|
||||
&self,
|
||||
user_id: OwnedUserId,
|
||||
device_id: OwnedDeviceId,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let result = self
|
||||
.services
|
||||
|
@ -327,7 +359,9 @@ async fn get_master_key(&self, user_id: OwnedUserId) -> Result<RoomMessageEventC
|
|||
|
||||
#[admin_command]
|
||||
async fn get_to_device_events(
|
||||
&self, user_id: OwnedUserId, device_id: OwnedDeviceId,
|
||||
&self,
|
||||
user_id: OwnedUserId,
|
||||
device_id: OwnedDeviceId,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let result = self
|
||||
|
|
|
@ -3,7 +3,10 @@ use std::fmt::Write;
|
|||
use clap::Subcommand;
|
||||
use conduwuit::Result;
|
||||
use futures::StreamExt;
|
||||
use ruma::{events::room::message::RoomMessageEventContent, OwnedRoomAliasId, OwnedRoomId, RoomAliasId, RoomId};
|
||||
use ruma::{
|
||||
events::room::message::RoomMessageEventContent, OwnedRoomAliasId, OwnedRoomId, RoomAliasId,
|
||||
RoomId,
|
||||
};
|
||||
|
||||
use crate::{escape_html, Command};
|
||||
|
||||
|
@ -42,82 +45,92 @@ pub(crate) enum RoomAliasCommand {
|
|||
},
|
||||
}
|
||||
|
||||
pub(super) async fn process(command: RoomAliasCommand, context: &Command<'_>) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn process(
|
||||
command: RoomAliasCommand,
|
||||
context: &Command<'_>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
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());
|
||||
| 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 RoomAliasId::parse_box(room_alias_str) {
|
||||
Ok(alias) => alias,
|
||||
Err(err) => return Ok(RoomMessageEventContent::text_plain(format!("Failed to parse alias: {err}"))),
|
||||
| Ok(alias) => alias,
|
||||
| Err(err) =>
|
||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"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)
|
||||
{
|
||||
Ok(()) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Successfully overwrote alias (formerly {id})"
|
||||
| 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,
|
||||
) {
|
||||
| Ok(()) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Successfully overwrote alias (formerly {id})"
|
||||
))),
|
||||
| Err(err) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Failed to remove alias: {err}"
|
||||
))),
|
||||
}
|
||||
},
|
||||
| (false, Ok(id)) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Refusing to overwrite in use alias for {id}, use -f or --force to \
|
||||
overwrite"
|
||||
))),
|
||||
Err(err) => Ok(RoomMessageEventContent::text_plain(format!("Failed to remove alias: {err}"))),
|
||||
| (_, 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}"
|
||||
))),
|
||||
}
|
||||
},
|
||||
},
|
||||
(false, Ok(id)) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"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}"))),
|
||||
| RoomAliasCommand::Remove { .. } =>
|
||||
match services.rooms.alias.resolve_local_alias(&room_alias).await {
|
||||
| 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(_) =>
|
||||
Ok(RoomMessageEventContent::text_plain("Alias isn't in use.")),
|
||||
},
|
||||
},
|
||||
RoomAliasCommand::Remove {
|
||||
..
|
||||
} => match services.rooms.alias.resolve_local_alias(&room_alias).await {
|
||||
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}"))),
|
||||
| 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(_) => 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.")),
|
||||
},
|
||||
RoomAliasCommand::List {
|
||||
..
|
||||
} => unreachable!(),
|
||||
| RoomAliasCommand::List { .. } => unreachable!(),
|
||||
}
|
||||
},
|
||||
RoomAliasCommand::List {
|
||||
room_id,
|
||||
} => {
|
||||
| RoomAliasCommand::List { room_id } =>
|
||||
if let Some(room_id) = room_id {
|
||||
let aliases: Vec<OwnedRoomAliasId> = services
|
||||
.rooms
|
||||
|
@ -128,7 +141,8 @@ pub(super) async fn process(command: RoomAliasCommand, context: &Command<'_>) ->
|
|||
.await;
|
||||
|
||||
let plain_list = aliases.iter().fold(String::new(), |mut output, alias| {
|
||||
writeln!(output, "- {alias}").expect("should be able to write to string buffer");
|
||||
writeln!(output, "- {alias}")
|
||||
.expect("should be able to write to string buffer");
|
||||
output
|
||||
});
|
||||
|
||||
|
@ -176,7 +190,6 @@ pub(super) async fn process(command: RoomAliasCommand, context: &Command<'_>) ->
|
|||
let plain = format!("Aliases:\n{plain_list}");
|
||||
let html = format!("Aliases:\n<ul>{html_list}</ul>");
|
||||
Ok(RoomMessageEventContent::text_html(plain, html))
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,11 @@ use crate::{admin_command, get_room_info, PAGE_SIZE};
|
|||
|
||||
#[admin_command]
|
||||
pub(super) async fn list_rooms(
|
||||
&self, page: Option<usize>, exclude_disabled: bool, exclude_banned: bool, no_details: bool,
|
||||
&self,
|
||||
page: Option<usize>,
|
||||
exclude_disabled: bool,
|
||||
exclude_banned: bool,
|
||||
no_details: bool,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
// 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);
|
||||
|
@ -16,10 +20,12 @@ pub(super) async fn list_rooms(
|
|||
.metadata
|
||||
.iter_ids()
|
||||
.filter_map(|room_id| async move {
|
||||
(!exclude_disabled || !self.services.rooms.metadata.is_disabled(room_id).await).then_some(room_id)
|
||||
(!exclude_disabled || !self.services.rooms.metadata.is_disabled(room_id).await)
|
||||
.then_some(room_id)
|
||||
})
|
||||
.filter_map(|room_id| async move {
|
||||
(!exclude_banned || !self.services.rooms.metadata.is_banned(room_id).await).then_some(room_id)
|
||||
(!exclude_banned || !self.services.rooms.metadata.is_banned(room_id).await)
|
||||
.then_some(room_id)
|
||||
})
|
||||
.then(|room_id| get_room_info(self.services, room_id))
|
||||
.collect::<Vec<_>>()
|
||||
|
|
|
@ -25,24 +25,21 @@ pub(crate) enum RoomDirectoryCommand {
|
|||
},
|
||||
}
|
||||
|
||||
pub(super) async fn process(command: RoomDirectoryCommand, context: &Command<'_>) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn process(
|
||||
command: RoomDirectoryCommand,
|
||||
context: &Command<'_>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let services = context.services;
|
||||
match command {
|
||||
RoomDirectoryCommand::Publish {
|
||||
room_id,
|
||||
} => {
|
||||
| RoomDirectoryCommand::Publish { room_id } => {
|
||||
services.rooms.directory.set_public(&room_id);
|
||||
Ok(RoomMessageEventContent::notice_plain("Room published"))
|
||||
},
|
||||
RoomDirectoryCommand::Unpublish {
|
||||
room_id,
|
||||
} => {
|
||||
| RoomDirectoryCommand::Unpublish { room_id } => {
|
||||
services.rooms.directory.set_not_public(&room_id);
|
||||
Ok(RoomMessageEventContent::notice_plain("Room unpublished"))
|
||||
},
|
||||
RoomDirectoryCommand::List {
|
||||
page,
|
||||
} => {
|
||||
| RoomDirectoryCommand::List { page } => {
|
||||
// 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: Vec<_> = services
|
||||
|
@ -70,7 +67,9 @@ pub(super) async fn process(command: RoomDirectoryCommand, context: &Command<'_>
|
|||
"Rooms (page {page}):\n```\n{}\n```",
|
||||
rooms
|
||||
.iter()
|
||||
.map(|(id, members, name)| format!("{id} | Members: {members} | Name: {name}"))
|
||||
.map(|(id, members, name)| format!(
|
||||
"{id} | Members: {members} | Name: {name}"
|
||||
))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
);
|
||||
|
|
|
@ -27,7 +27,11 @@ pub(crate) enum RoomInfoCommand {
|
|||
}
|
||||
|
||||
#[admin_command]
|
||||
async fn list_joined_members(&self, room_id: Box<RoomId>, local_only: bool) -> Result<RoomMessageEventContent> {
|
||||
async fn list_joined_members(
|
||||
&self,
|
||||
room_id: Box<RoomId>,
|
||||
local_only: bool,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let room_name = self
|
||||
.services
|
||||
.rooms
|
||||
|
|
|
@ -9,7 +9,8 @@ use conduwuit::Result;
|
|||
use ruma::OwnedRoomId;
|
||||
|
||||
use self::{
|
||||
alias::RoomAliasCommand, directory::RoomDirectoryCommand, info::RoomInfoCommand, moderation::RoomModerationCommand,
|
||||
alias::RoomAliasCommand, directory::RoomDirectoryCommand, info::RoomInfoCommand,
|
||||
moderation::RoomModerationCommand,
|
||||
};
|
||||
use crate::admin_command_dispatch;
|
||||
|
||||
|
|
|
@ -6,7 +6,10 @@ use conduwuit::{
|
|||
warn, Result,
|
||||
};
|
||||
use futures::StreamExt;
|
||||
use ruma::{events::room::message::RoomMessageEventContent, OwnedRoomId, RoomAliasId, RoomId, RoomOrAliasId};
|
||||
use ruma::{
|
||||
events::room::message::RoomMessageEventContent, OwnedRoomId, RoomAliasId, RoomId,
|
||||
RoomOrAliasId,
|
||||
};
|
||||
|
||||
use crate::{admin_command, admin_command_dispatch, get_room_info};
|
||||
|
||||
|
@ -75,7 +78,10 @@ pub(crate) enum RoomModerationCommand {
|
|||
|
||||
#[admin_command]
|
||||
async fn ban_room(
|
||||
&self, force: bool, disable_federation: bool, room: Box<RoomOrAliasId>,
|
||||
&self,
|
||||
force: bool,
|
||||
disable_federation: bool,
|
||||
room: Box<RoomOrAliasId>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
debug!("Got room alias or ID: {}", room);
|
||||
|
||||
|
@ -89,13 +95,13 @@ async fn ban_room(
|
|||
|
||||
let room_id = if room.is_room_id() {
|
||||
let room_id = match RoomId::parse(&room) {
|
||||
Ok(room_id) => room_id,
|
||||
Err(e) => {
|
||||
| Ok(room_id) => room_id,
|
||||
| Err(e) =>
|
||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"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}"
|
||||
)))
|
||||
},
|
||||
"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}"
|
||||
))),
|
||||
};
|
||||
|
||||
debug!("Room specified is a room ID, banning room ID");
|
||||
|
@ -105,18 +111,18 @@ async fn ban_room(
|
|||
room_id
|
||||
} else if room.is_room_alias_id() {
|
||||
let room_alias = match RoomAliasId::parse(&room) {
|
||||
Ok(room_alias) => room_alias,
|
||||
Err(e) => {
|
||||
| Ok(room_alias) => room_alias,
|
||||
| Err(e) =>
|
||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"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}"
|
||||
)))
|
||||
},
|
||||
"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}"
|
||||
))),
|
||||
};
|
||||
|
||||
debug!(
|
||||
"Room specified is not a room ID, attempting to resolve room alias to a room ID locally, if not using \
|
||||
get_alias_helper to fetch room ID remotely"
|
||||
"Room specified is not a room ID, attempting to resolve room alias to a room ID \
|
||||
locally, if not using get_alias_helper to fetch room ID remotely"
|
||||
);
|
||||
|
||||
let room_id = if let Ok(room_id) = self
|
||||
|
@ -128,7 +134,10 @@ async fn ban_room(
|
|||
{
|
||||
room_id
|
||||
} else {
|
||||
debug!("We don't have this room alias to a room ID locally, attempting to fetch room ID over federation");
|
||||
debug!(
|
||||
"We don't have this room alias to a room ID locally, attempting to fetch room \
|
||||
ID over federation"
|
||||
);
|
||||
|
||||
match self
|
||||
.services
|
||||
|
@ -137,11 +146,15 @@ async fn ban_room(
|
|||
.resolve_alias(&room_alias, None)
|
||||
.await
|
||||
{
|
||||
Ok((room_id, servers)) => {
|
||||
debug!(?room_id, ?servers, "Got federation response fetching room ID for {room}");
|
||||
| Ok((room_id, servers)) => {
|
||||
debug!(
|
||||
?room_id,
|
||||
?servers,
|
||||
"Got federation response fetching room ID for {room}"
|
||||
);
|
||||
room_id
|
||||
},
|
||||
Err(e) => {
|
||||
| Err(e) => {
|
||||
return Ok(RoomMessageEventContent::notice_plain(format!(
|
||||
"Failed to resolve room alias {room} to a room ID: {e}"
|
||||
)));
|
||||
|
@ -154,8 +167,9 @@ async fn ban_room(
|
|||
room_id
|
||||
} else {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"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`)",
|
||||
"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`)",
|
||||
));
|
||||
};
|
||||
|
||||
|
@ -171,8 +185,8 @@ async fn ban_room(
|
|||
|
||||
while let Some(local_user) = users.next().await {
|
||||
debug!(
|
||||
"Attempting leave for user {local_user} in room {room_id} (forced, ignoring all errors, evicting \
|
||||
admins too)",
|
||||
"Attempting leave for user {local_user} in room {room_id} (forced, ignoring all \
|
||||
errors, evicting admins too)",
|
||||
);
|
||||
|
||||
if let Err(e) = leave_room(self.services, local_user, &room_id, None).await {
|
||||
|
@ -196,12 +210,14 @@ async fn ban_room(
|
|||
debug!("Attempting leave for user {} in room {}", &local_user, &room_id);
|
||||
if let Err(e) = leave_room(self.services, local_user, &room_id, None).await {
|
||||
error!(
|
||||
"Error attempting to make local user {} leave room {} during room banning: {}",
|
||||
"Error attempting to make local user {} leave room {} during room banning: \
|
||||
{}",
|
||||
&local_user, &room_id, e
|
||||
);
|
||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Error attempting to make local user {} leave room {} during room banning (room is still banned \
|
||||
but not removing any more users): {}\nIf you would like to ignore errors, use --force",
|
||||
"Error attempting to make local user {} leave room {} during room banning \
|
||||
(room is still banned but not removing any more users): {}\nIf you would \
|
||||
like to ignore errors, use --force",
|
||||
&local_user, &room_id, e
|
||||
)));
|
||||
}
|
||||
|
@ -232,19 +248,26 @@ async fn ban_room(
|
|||
if disable_federation {
|
||||
self.services.rooms.metadata.disable_room(&room_id, true);
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"Room banned, removed all our local users, and disabled incoming federation with room.",
|
||||
"Room banned, removed all our local users, and disabled incoming federation with \
|
||||
room.",
|
||||
));
|
||||
}
|
||||
|
||||
Ok(RoomMessageEventContent::text_plain(
|
||||
"Room banned and removed all our local users, use `!admin federation disable-room` to stop receiving new \
|
||||
inbound federation events as well if needed.",
|
||||
"Room banned and removed all our local users, use `!admin federation disable-room` to \
|
||||
stop receiving new inbound federation events as well if needed.",
|
||||
))
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
async fn ban_list_of_rooms(&self, force: bool, disable_federation: bool) -> Result<RoomMessageEventContent> {
|
||||
if self.body.len() < 2 || !self.body[0].trim().starts_with("```") || self.body.last().unwrap_or(&"").trim() != "```"
|
||||
async fn ban_list_of_rooms(
|
||||
&self,
|
||||
force: bool,
|
||||
disable_federation: bool,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
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.",
|
||||
|
@ -264,9 +287,10 @@ async fn ban_list_of_rooms(&self, force: bool, disable_federation: bool) -> Resu
|
|||
|
||||
for &room in &rooms_s {
|
||||
match <&RoomOrAliasId>::try_from(room) {
|
||||
Ok(room_alias_or_id) => {
|
||||
| Ok(room_alias_or_id) => {
|
||||
if let Ok(admin_room_id) = self.services.admin.get_admin_room().await {
|
||||
if room.to_owned().eq(&admin_room_id) || room.to_owned().eq(admin_room_alias) {
|
||||
if room.to_owned().eq(&admin_room_id) || room.to_owned().eq(admin_room_alias)
|
||||
{
|
||||
info!("User specified admin room in bulk ban list, ignoring");
|
||||
continue;
|
||||
}
|
||||
|
@ -274,19 +298,20 @@ async fn ban_list_of_rooms(&self, force: bool, disable_federation: bool) -> Resu
|
|||
|
||||
if room_alias_or_id.is_room_id() {
|
||||
let room_id = match RoomId::parse(room_alias_or_id) {
|
||||
Ok(room_id) => room_id,
|
||||
Err(e) => {
|
||||
| Ok(room_id) => room_id,
|
||||
| Err(e) => {
|
||||
if force {
|
||||
// ignore rooms we failed to parse if we're force banning
|
||||
warn!(
|
||||
"Error parsing room \"{room}\" during bulk room banning, ignoring error and \
|
||||
logging here: {e}"
|
||||
"Error parsing room \"{room}\" during bulk room banning, \
|
||||
ignoring error and logging here: {e}"
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"{room} is not a valid room ID or room alias, please fix the list and try again: {e}"
|
||||
"{room} is not a valid room ID or room alias, please fix the \
|
||||
list and try again: {e}"
|
||||
)));
|
||||
},
|
||||
};
|
||||
|
@ -296,7 +321,7 @@ async fn ban_list_of_rooms(&self, force: bool, disable_federation: bool) -> Resu
|
|||
|
||||
if room_alias_or_id.is_room_alias_id() {
|
||||
match RoomAliasId::parse(room_alias_or_id) {
|
||||
Ok(room_alias) => {
|
||||
| Ok(room_alias) => {
|
||||
let room_id = if let Ok(room_id) = self
|
||||
.services
|
||||
.rooms
|
||||
|
@ -307,8 +332,8 @@ async fn ban_list_of_rooms(&self, force: bool, disable_federation: bool) -> Resu
|
|||
room_id
|
||||
} else {
|
||||
debug!(
|
||||
"We don't have this room alias to a room ID locally, attempting to fetch room ID \
|
||||
over federation"
|
||||
"We don't have this room alias to a room ID locally, \
|
||||
attempting to fetch room ID over federation"
|
||||
);
|
||||
|
||||
match self
|
||||
|
@ -318,7 +343,7 @@ async fn ban_list_of_rooms(&self, force: bool, disable_federation: bool) -> Resu
|
|||
.resolve_alias(&room_alias, None)
|
||||
.await
|
||||
{
|
||||
Ok((room_id, servers)) => {
|
||||
| Ok((room_id, servers)) => {
|
||||
debug!(
|
||||
?room_id,
|
||||
?servers,
|
||||
|
@ -326,15 +351,19 @@ async fn ban_list_of_rooms(&self, force: bool, disable_federation: bool) -> Resu
|
|||
);
|
||||
room_id
|
||||
},
|
||||
Err(e) => {
|
||||
| Err(e) => {
|
||||
// don't fail if force blocking
|
||||
if force {
|
||||
warn!("Failed to resolve room alias {room} to a room ID: {e}");
|
||||
warn!(
|
||||
"Failed to resolve room alias {room} to a room \
|
||||
ID: {e}"
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Failed to resolve room alias {room} to a room ID: {e}"
|
||||
"Failed to resolve room alias {room} to a room ID: \
|
||||
{e}"
|
||||
)));
|
||||
},
|
||||
}
|
||||
|
@ -342,34 +371,37 @@ async fn ban_list_of_rooms(&self, force: bool, disable_federation: bool) -> Resu
|
|||
|
||||
room_ids.push(room_id);
|
||||
},
|
||||
Err(e) => {
|
||||
| Err(e) => {
|
||||
if force {
|
||||
// ignore rooms we failed to parse if we're force deleting
|
||||
error!(
|
||||
"Error parsing room \"{room}\" during bulk room banning, ignoring error and \
|
||||
logging here: {e}"
|
||||
"Error parsing room \"{room}\" during bulk room banning, \
|
||||
ignoring error and logging here: {e}"
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"{room} is not a valid room ID or room alias, please fix the list and try again: {e}"
|
||||
"{room} is not a valid room ID or room alias, please fix the \
|
||||
list and try again: {e}"
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
| Err(e) => {
|
||||
if force {
|
||||
// ignore rooms we failed to parse if we're force deleting
|
||||
error!(
|
||||
"Error parsing room \"{room}\" during bulk room banning, ignoring error and logging here: {e}"
|
||||
"Error parsing room \"{room}\" during bulk room banning, ignoring error \
|
||||
and logging here: {e}"
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"{room} is not a valid room ID or room alias, please fix the list and try again: {e}"
|
||||
"{room} is not a valid room ID or room alias, please fix the list and try \
|
||||
again: {e}"
|
||||
)));
|
||||
},
|
||||
}
|
||||
|
@ -393,8 +425,8 @@ async fn ban_list_of_rooms(&self, force: bool, disable_federation: bool) -> Resu
|
|||
|
||||
while let Some(local_user) = users.next().await {
|
||||
debug!(
|
||||
"Attempting leave for user {local_user} in room {room_id} (forced, ignoring all errors, evicting \
|
||||
admins too)",
|
||||
"Attempting leave for user {local_user} in room {room_id} (forced, ignoring \
|
||||
all errors, evicting admins too)",
|
||||
);
|
||||
|
||||
if let Err(e) = leave_room(self.services, local_user, &room_id, None).await {
|
||||
|
@ -418,14 +450,15 @@ async fn ban_list_of_rooms(&self, force: bool, disable_federation: bool) -> Resu
|
|||
debug!("Attempting leave for user {local_user} in room {room_id}");
|
||||
if let Err(e) = leave_room(self.services, local_user, &room_id, None).await {
|
||||
error!(
|
||||
"Error attempting to make local user {local_user} leave room {room_id} during bulk room \
|
||||
banning: {e}",
|
||||
"Error attempting to make local user {local_user} leave room {room_id} \
|
||||
during bulk room banning: {e}",
|
||||
);
|
||||
|
||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Error attempting to make local user {} leave room {} during room banning (room is still \
|
||||
banned but not removing any more users and not banning any more rooms): {}\nIf you would \
|
||||
like to ignore errors, use --force",
|
||||
"Error attempting to make local user {} leave room {} during room \
|
||||
banning (room is still banned but not removing any more users and not \
|
||||
banning any more rooms): {}\nIf you would like to ignore errors, use \
|
||||
--force",
|
||||
&local_user, &room_id, e
|
||||
)));
|
||||
}
|
||||
|
@ -458,8 +491,8 @@ async fn ban_list_of_rooms(&self, force: bool, disable_federation: bool) -> Resu
|
|||
|
||||
if disable_federation {
|
||||
Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Finished bulk room ban, banned {room_ban_count} total rooms, evicted all users, and disabled incoming \
|
||||
federation with the room."
|
||||
"Finished bulk room ban, banned {room_ban_count} total rooms, evicted all users, \
|
||||
and disabled incoming federation with the room."
|
||||
)))
|
||||
} else {
|
||||
Ok(RoomMessageEventContent::text_plain(format!(
|
||||
|
@ -469,16 +502,20 @@ async fn ban_list_of_rooms(&self, force: bool, disable_federation: bool) -> Resu
|
|||
}
|
||||
|
||||
#[admin_command]
|
||||
async fn unban_room(&self, enable_federation: bool, room: Box<RoomOrAliasId>) -> Result<RoomMessageEventContent> {
|
||||
async fn unban_room(
|
||||
&self,
|
||||
enable_federation: bool,
|
||||
room: Box<RoomOrAliasId>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let room_id = if room.is_room_id() {
|
||||
let room_id = match RoomId::parse(&room) {
|
||||
Ok(room_id) => room_id,
|
||||
Err(e) => {
|
||||
| Ok(room_id) => room_id,
|
||||
| Err(e) =>
|
||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"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}"
|
||||
)))
|
||||
},
|
||||
"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}"
|
||||
))),
|
||||
};
|
||||
|
||||
debug!("Room specified is a room ID, unbanning room ID");
|
||||
|
@ -488,18 +525,18 @@ async fn unban_room(&self, enable_federation: bool, room: Box<RoomOrAliasId>) ->
|
|||
room_id
|
||||
} else if room.is_room_alias_id() {
|
||||
let room_alias = match RoomAliasId::parse(&room) {
|
||||
Ok(room_alias) => room_alias,
|
||||
Err(e) => {
|
||||
| Ok(room_alias) => room_alias,
|
||||
| Err(e) =>
|
||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"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}"
|
||||
)))
|
||||
},
|
||||
"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}"
|
||||
))),
|
||||
};
|
||||
|
||||
debug!(
|
||||
"Room specified is not a room ID, attempting to resolve room alias to a room ID locally, if not using \
|
||||
get_alias_helper to fetch room ID remotely"
|
||||
"Room specified is not a room ID, attempting to resolve room alias to a room ID \
|
||||
locally, if not using get_alias_helper to fetch room ID remotely"
|
||||
);
|
||||
|
||||
let room_id = if let Ok(room_id) = self
|
||||
|
@ -511,7 +548,10 @@ async fn unban_room(&self, enable_federation: bool, room: Box<RoomOrAliasId>) ->
|
|||
{
|
||||
room_id
|
||||
} else {
|
||||
debug!("We don't have this room alias to a room ID locally, attempting to fetch room ID over federation");
|
||||
debug!(
|
||||
"We don't have this room alias to a room ID locally, attempting to fetch room \
|
||||
ID over federation"
|
||||
);
|
||||
|
||||
match self
|
||||
.services
|
||||
|
@ -520,11 +560,15 @@ async fn unban_room(&self, enable_federation: bool, room: Box<RoomOrAliasId>) ->
|
|||
.resolve_alias(&room_alias, None)
|
||||
.await
|
||||
{
|
||||
Ok((room_id, servers)) => {
|
||||
debug!(?room_id, ?servers, "Got federation response fetching room ID for room {room}");
|
||||
| Ok((room_id, servers)) => {
|
||||
debug!(
|
||||
?room_id,
|
||||
?servers,
|
||||
"Got federation response fetching room ID for room {room}"
|
||||
);
|
||||
room_id
|
||||
},
|
||||
Err(e) => {
|
||||
| Err(e) => {
|
||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Failed to resolve room alias {room} to a room ID: {e}"
|
||||
)));
|
||||
|
@ -537,8 +581,9 @@ async fn unban_room(&self, enable_federation: bool, room: Box<RoomOrAliasId>) ->
|
|||
room_id
|
||||
} else {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"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`)",
|
||||
"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`)",
|
||||
));
|
||||
};
|
||||
|
||||
|
@ -548,8 +593,8 @@ async fn unban_room(&self, enable_federation: bool, room: Box<RoomOrAliasId>) ->
|
|||
}
|
||||
|
||||
Ok(RoomMessageEventContent::text_plain(
|
||||
"Room unbanned, you may need to re-enable federation with the room using enable-room if this is a remote room \
|
||||
to make it fully functional.",
|
||||
"Room unbanned, you may need to re-enable federation with the room using enable-room if \
|
||||
this is a remote room to make it fully functional.",
|
||||
))
|
||||
}
|
||||
|
||||
|
|
|
@ -29,13 +29,12 @@ pub(super) async fn show_config(&self) -> Result<RoomMessageEventContent> {
|
|||
|
||||
#[admin_command]
|
||||
pub(super) async fn list_features(
|
||||
&self, available: bool, enabled: bool, comma: bool,
|
||||
&self,
|
||||
available: bool,
|
||||
enabled: bool,
|
||||
comma: bool,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let delim = if comma {
|
||||
","
|
||||
} else {
|
||||
" "
|
||||
};
|
||||
let delim = if comma { "," } else { " " };
|
||||
if enabled && !available {
|
||||
let features = info::rustc::features().join(delim);
|
||||
let out = format!("`\n{features}\n`");
|
||||
|
@ -53,16 +52,8 @@ pub(super) async fn list_features(
|
|||
let available = info::cargo::features();
|
||||
for feature in available {
|
||||
let active = enabled.contains(&feature.as_str());
|
||||
let emoji = if active {
|
||||
"✅"
|
||||
} else {
|
||||
"❌"
|
||||
};
|
||||
let remark = if active {
|
||||
"[enabled]"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
let emoji = if active { "✅" } else { "❌" };
|
||||
let remark = if active { "[enabled]" } else { "" };
|
||||
writeln!(features, "{emoji} {feature} {remark}")?;
|
||||
}
|
||||
|
||||
|
@ -73,7 +64,8 @@ pub(super) async fn list_features(
|
|||
pub(super) async fn memory_usage(&self) -> Result<RoomMessageEventContent> {
|
||||
let services_usage = self.services.memory_usage().await?;
|
||||
let database_usage = self.services.db.db.memory_usage()?;
|
||||
let allocator_usage = conduwuit::alloc::memory_usage().map_or(String::new(), |s| format!("\nAllocator:\n{s}"));
|
||||
let allocator_usage =
|
||||
conduwuit::alloc::memory_usage().map_or(String::new(), |s| format!("\nAllocator:\n{s}"));
|
||||
|
||||
Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Services:\n{services_usage}\nDatabase:\n{database_usage}{allocator_usage}",
|
||||
|
@ -106,8 +98,8 @@ pub(super) async fn backup_database(&self) -> Result<RoomMessageEventContent> {
|
|||
.server
|
||||
.runtime()
|
||||
.spawn_blocking(move || match globals.db.backup() {
|
||||
Ok(()) => String::new(),
|
||||
Err(e) => e.to_string(),
|
||||
| Ok(()) => String::new(),
|
||||
| Err(e) => e.to_string(),
|
||||
})
|
||||
.await?;
|
||||
|
||||
|
@ -147,8 +139,8 @@ pub(super) async fn restart(&self, force: bool) -> Result<RoomMessageEventConten
|
|||
|
||||
if !force && current_exe_deleted() {
|
||||
return Err!(
|
||||
"The server cannot be restarted because the executable changed. If this is expected use --force to \
|
||||
override."
|
||||
"The server cannot be restarted because the executable changed. If this is expected \
|
||||
use --force to override."
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -47,12 +47,18 @@ pub(super) async fn list_users(&self) -> Result<RoomMessageEventContent> {
|
|||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn create_user(&self, username: String, password: Option<String>) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn create_user(
|
||||
&self,
|
||||
username: String,
|
||||
password: Option<String>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
// Validate user id
|
||||
let user_id = parse_local_user_id(self.services, &username)?;
|
||||
|
||||
if self.services.users.exists(&user_id).await {
|
||||
return Ok(RoomMessageEventContent::text_plain(format!("Userid {user_id} already exists")));
|
||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Userid {user_id} already exists"
|
||||
)));
|
||||
}
|
||||
|
||||
if user_id.is_historical() {
|
||||
|
@ -120,7 +126,9 @@ pub(super) async fn create_user(&self, username: String, password: Option<String
|
|||
.server_in_room(self.services.globals.server_name(), &room_id)
|
||||
.await
|
||||
{
|
||||
warn!("Skipping room {room} to automatically join as we have never joined before.");
|
||||
warn!(
|
||||
"Skipping room {room} to automatically join as we have never joined before."
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -130,25 +138,31 @@ pub(super) async fn create_user(&self, username: String, password: Option<String
|
|||
&user_id,
|
||||
&room_id,
|
||||
Some("Automatically joining this room upon registration".to_owned()),
|
||||
&[self.services.globals.server_name().to_owned(), room_server_name.to_owned()],
|
||||
&[
|
||||
self.services.globals.server_name().to_owned(),
|
||||
room_server_name.to_owned(),
|
||||
],
|
||||
None,
|
||||
&None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(_response) => {
|
||||
| Ok(_response) => {
|
||||
info!("Automatically joined room {room} for user {user_id}");
|
||||
},
|
||||
Err(e) => {
|
||||
| Err(e) => {
|
||||
self.services
|
||||
.admin
|
||||
.send_message(RoomMessageEventContent::text_plain(format!(
|
||||
"Failed to automatically join room {room} for user {user_id}: {e}"
|
||||
"Failed to automatically join room {room} for user {user_id}: \
|
||||
{e}"
|
||||
)))
|
||||
.await
|
||||
.ok();
|
||||
// don't return this error so we don't fail registrations
|
||||
error!("Failed to automatically join room {room} for user {user_id}: {e}");
|
||||
error!(
|
||||
"Failed to automatically join room {room} for user {user_id}: {e}"
|
||||
);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -181,7 +195,11 @@ pub(super) async fn create_user(&self, username: String, password: Option<String
|
|||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn deactivate(&self, no_leave_rooms: bool, user_id: String) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn deactivate(
|
||||
&self,
|
||||
no_leave_rooms: bool,
|
||||
user_id: String,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
// Validate user id
|
||||
let user_id = parse_local_user_id(self.services, &user_id)?;
|
||||
|
||||
|
@ -229,7 +247,8 @@ pub(super) async fn reset_password(&self, username: String) -> Result<RoomMessag
|
|||
|
||||
if user_id == self.services.globals.server_user {
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"Not allowed to set the password for the server account. Please use the emergency password config option.",
|
||||
"Not allowed to set the password for the server account. Please use the emergency \
|
||||
password config option.",
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -240,18 +259,24 @@ pub(super) async fn reset_password(&self, username: String) -> Result<RoomMessag
|
|||
.users
|
||||
.set_password(&user_id, Some(new_password.as_str()))
|
||||
{
|
||||
Ok(()) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
| Ok(()) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Successfully reset the password for user {user_id}: `{new_password}`"
|
||||
))),
|
||||
Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
| Err(e) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Couldn't reset the password for user {user_id}: {e}"
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn deactivate_all(&self, no_leave_rooms: bool, force: bool) -> Result<RoomMessageEventContent> {
|
||||
if self.body.len() < 2 || !self.body[0].trim().starts_with("```") || self.body.last().unwrap_or(&"").trim() != "```"
|
||||
pub(super) async fn deactivate_all(
|
||||
&self,
|
||||
no_leave_rooms: bool,
|
||||
force: bool,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
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.",
|
||||
|
@ -269,7 +294,7 @@ pub(super) async fn deactivate_all(&self, no_leave_rooms: bool, force: bool) ->
|
|||
|
||||
for username in usernames {
|
||||
match parse_active_local_user_id(self.services, username).await {
|
||||
Ok(user_id) => {
|
||||
| Ok(user_id) => {
|
||||
if self.services.users.is_admin(&user_id).await && !force {
|
||||
self.services
|
||||
.admin
|
||||
|
@ -296,7 +321,7 @@ pub(super) async fn deactivate_all(&self, no_leave_rooms: bool, force: bool) ->
|
|||
|
||||
user_ids.push(user_id);
|
||||
},
|
||||
Err(e) => {
|
||||
| Err(e) => {
|
||||
self.services
|
||||
.admin
|
||||
.send_message(RoomMessageEventContent::text_plain(format!(
|
||||
|
@ -313,7 +338,7 @@ pub(super) async fn deactivate_all(&self, no_leave_rooms: bool, force: bool) ->
|
|||
|
||||
for user_id in user_ids {
|
||||
match self.services.users.deactivate_account(&user_id).await {
|
||||
Ok(()) => {
|
||||
| Ok(()) => {
|
||||
deactivation_count = deactivation_count.saturating_add(1);
|
||||
if !no_leave_rooms {
|
||||
info!("Forcing user {user_id} to leave all rooms apart of deactivate-all");
|
||||
|
@ -328,14 +353,17 @@ pub(super) async fn deactivate_all(&self, no_leave_rooms: bool, force: bool) ->
|
|||
|
||||
full_user_deactivate(self.services, &user_id, &all_joined_rooms).await?;
|
||||
update_displayname(self.services, &user_id, None, &all_joined_rooms).await;
|
||||
update_avatar_url(self.services, &user_id, None, None, &all_joined_rooms).await;
|
||||
update_avatar_url(self.services, &user_id, None, None, &all_joined_rooms)
|
||||
.await;
|
||||
leave_all_rooms(self.services, &user_id).await;
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
| Err(e) => {
|
||||
self.services
|
||||
.admin
|
||||
.send_message(RoomMessageEventContent::text_plain(format!("Failed deactivating user: {e}")))
|
||||
.send_message(RoomMessageEventContent::text_plain(format!(
|
||||
"Failed deactivating user: {e}"
|
||||
)))
|
||||
.await
|
||||
.ok();
|
||||
},
|
||||
|
@ -348,8 +376,8 @@ pub(super) async fn deactivate_all(&self, no_leave_rooms: bool, force: bool) ->
|
|||
)))
|
||||
} else {
|
||||
Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Deactivated {deactivation_count} accounts.\nSkipped admin accounts: {}. Use --force to deactivate admin \
|
||||
accounts",
|
||||
"Deactivated {deactivation_count} accounts.\nSkipped admin accounts: {}. Use \
|
||||
--force to deactivate admin accounts",
|
||||
admins.join(", ")
|
||||
)))
|
||||
}
|
||||
|
@ -391,9 +419,13 @@ pub(super) async fn list_joined_rooms(&self, user_id: String) -> Result<RoomMess
|
|||
|
||||
#[admin_command]
|
||||
pub(super) async fn force_join_list_of_local_users(
|
||||
&self, room_id: OwnedRoomOrAliasId, yes_i_want_to_do_this: bool,
|
||||
&self,
|
||||
room_id: OwnedRoomOrAliasId,
|
||||
yes_i_want_to_do_this: bool,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
if self.body.len() < 2 || !self.body[0].trim().starts_with("```") || self.body.last().unwrap_or(&"").trim() != "```"
|
||||
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.",
|
||||
|
@ -402,8 +434,8 @@ pub(super) async fn force_join_list_of_local_users(
|
|||
|
||||
if !yes_i_want_to_do_this {
|
||||
return Ok(RoomMessageEventContent::notice_markdown(
|
||||
"You must pass the --yes-i-want-to-do-this-flag to ensure you really want to force bulk join all \
|
||||
specified local users.",
|
||||
"You must pass the --yes-i-want-to-do-this-flag to ensure you really want to force \
|
||||
bulk join all specified local users.",
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -462,7 +494,7 @@ pub(super) async fn force_join_list_of_local_users(
|
|||
|
||||
for username in usernames {
|
||||
match parse_active_local_user_id(self.services, username).await {
|
||||
Ok(user_id) => {
|
||||
| Ok(user_id) => {
|
||||
// don't make the server service account join
|
||||
if user_id == self.services.globals.server_user {
|
||||
self.services
|
||||
|
@ -477,7 +509,7 @@ pub(super) async fn force_join_list_of_local_users(
|
|||
|
||||
user_ids.push(user_id);
|
||||
},
|
||||
Err(e) => {
|
||||
| Err(e) => {
|
||||
self.services
|
||||
.admin
|
||||
.send_message(RoomMessageEventContent::text_plain(format!(
|
||||
|
@ -505,10 +537,10 @@ pub(super) async fn force_join_list_of_local_users(
|
|||
)
|
||||
.await
|
||||
{
|
||||
Ok(_res) => {
|
||||
| Ok(_res) => {
|
||||
successful_joins = successful_joins.saturating_add(1);
|
||||
},
|
||||
Err(e) => {
|
||||
| Err(e) => {
|
||||
debug_warn!("Failed force joining {user_id} to {room_id} during bulk join: {e}");
|
||||
failed_joins = failed_joins.saturating_add(1);
|
||||
},
|
||||
|
@ -516,18 +548,21 @@ pub(super) async fn force_join_list_of_local_users(
|
|||
}
|
||||
|
||||
Ok(RoomMessageEventContent::notice_markdown(format!(
|
||||
"{successful_joins} local users have been joined to {room_id}. {failed_joins} joins failed.",
|
||||
"{successful_joins} local users have been joined to {room_id}. {failed_joins} joins \
|
||||
failed.",
|
||||
)))
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn force_join_all_local_users(
|
||||
&self, room_id: OwnedRoomOrAliasId, yes_i_want_to_do_this: bool,
|
||||
&self,
|
||||
room_id: OwnedRoomOrAliasId,
|
||||
yes_i_want_to_do_this: bool,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
if !yes_i_want_to_do_this {
|
||||
return Ok(RoomMessageEventContent::notice_markdown(
|
||||
"You must pass the --yes-i-want-to-do-this-flag to ensure you really want to force bulk join all local \
|
||||
users.",
|
||||
"You must pass the --yes-i-want-to-do-this-flag to ensure you really want to force \
|
||||
bulk join all local users.",
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -598,10 +633,10 @@ pub(super) async fn force_join_all_local_users(
|
|||
)
|
||||
.await
|
||||
{
|
||||
Ok(_res) => {
|
||||
| Ok(_res) => {
|
||||
successful_joins = successful_joins.saturating_add(1);
|
||||
},
|
||||
Err(e) => {
|
||||
| Err(e) => {
|
||||
debug_warn!("Failed force joining {user_id} to {room_id} during bulk join: {e}");
|
||||
failed_joins = failed_joins.saturating_add(1);
|
||||
},
|
||||
|
@ -609,13 +644,16 @@ pub(super) async fn force_join_all_local_users(
|
|||
}
|
||||
|
||||
Ok(RoomMessageEventContent::notice_markdown(format!(
|
||||
"{successful_joins} local users have been joined to {room_id}. {failed_joins} joins failed.",
|
||||
"{successful_joins} local users have been joined to {room_id}. {failed_joins} joins \
|
||||
failed.",
|
||||
)))
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn force_join_room(
|
||||
&self, user_id: String, room_id: OwnedRoomOrAliasId,
|
||||
&self,
|
||||
user_id: String,
|
||||
room_id: OwnedRoomOrAliasId,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let user_id = parse_local_user_id(self.services, &user_id)?;
|
||||
let (room_id, servers) = self
|
||||
|
@ -629,7 +667,8 @@ pub(super) async fn force_join_room(
|
|||
self.services.globals.user_is_local(&user_id),
|
||||
"Parsed user_id must be a local user"
|
||||
);
|
||||
join_room_by_id_helper(self.services, &user_id, &room_id, None, &servers, None, &None).await?;
|
||||
join_room_by_id_helper(self.services, &user_id, &room_id, None, &servers, None, &None)
|
||||
.await?;
|
||||
|
||||
Ok(RoomMessageEventContent::notice_markdown(format!(
|
||||
"{user_id} has been joined to {room_id}.",
|
||||
|
@ -638,7 +677,9 @@ pub(super) async fn force_join_room(
|
|||
|
||||
#[admin_command]
|
||||
pub(super) async fn force_leave_room(
|
||||
&self, user_id: String, room_id: OwnedRoomOrAliasId,
|
||||
&self,
|
||||
user_id: String,
|
||||
room_id: OwnedRoomOrAliasId,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let user_id = parse_local_user_id(self.services, &user_id)?;
|
||||
let room_id = self.services.rooms.alias.resolve(&room_id).await?;
|
||||
|
@ -656,7 +697,9 @@ pub(super) async fn force_leave_room(
|
|||
|
||||
#[admin_command]
|
||||
pub(super) async fn force_demote(
|
||||
&self, user_id: String, room_id: OwnedRoomOrAliasId,
|
||||
&self,
|
||||
user_id: String,
|
||||
room_id: OwnedRoomOrAliasId,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let user_id = parse_local_user_id(self.services, &user_id)?;
|
||||
let room_id = self.services.rooms.alias.resolve(&room_id).await?;
|
||||
|
@ -672,14 +715,19 @@ pub(super) async fn force_demote(
|
|||
.services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.room_state_get_content::<RoomPowerLevelsEventContent>(&room_id, &StateEventType::RoomPowerLevels, "")
|
||||
.room_state_get_content::<RoomPowerLevelsEventContent>(
|
||||
&room_id,
|
||||
&StateEventType::RoomPowerLevels,
|
||||
"",
|
||||
)
|
||||
.await
|
||||
.ok();
|
||||
|
||||
let user_can_demote_self = room_power_levels
|
||||
.as_ref()
|
||||
.is_some_and(|power_levels_content| {
|
||||
RoomPowerLevels::from(power_levels_content.clone()).user_can_change_user_power_level(&user_id, &user_id)
|
||||
RoomPowerLevels::from(power_levels_content.clone())
|
||||
.user_can_change_user_power_level(&user_id, &user_id)
|
||||
}) || self
|
||||
.services
|
||||
.rooms
|
||||
|
@ -710,7 +758,8 @@ pub(super) async fn force_demote(
|
|||
.await?;
|
||||
|
||||
Ok(RoomMessageEventContent::notice_markdown(format!(
|
||||
"User {user_id} demoted themselves to the room default power level in {room_id} - {event_id}"
|
||||
"User {user_id} demoted themselves to the room default power level in {room_id} - \
|
||||
{event_id}"
|
||||
)))
|
||||
}
|
||||
|
||||
|
@ -731,7 +780,10 @@ pub(super) async fn make_user_admin(&self, user_id: String) -> Result<RoomMessag
|
|||
|
||||
#[admin_command]
|
||||
pub(super) async fn put_room_tag(
|
||||
&self, user_id: String, room_id: Box<RoomId>, tag: String,
|
||||
&self,
|
||||
user_id: String,
|
||||
room_id: Box<RoomId>,
|
||||
tag: String,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let user_id = parse_active_local_user_id(self.services, &user_id).await?;
|
||||
|
||||
|
@ -741,9 +793,7 @@ pub(super) async fn put_room_tag(
|
|||
.get_room(&room_id, &user_id, RoomAccountDataEventType::Tag)
|
||||
.await
|
||||
.unwrap_or(TagEvent {
|
||||
content: TagEventContent {
|
||||
tags: BTreeMap::new(),
|
||||
},
|
||||
content: TagEventContent { tags: BTreeMap::new() },
|
||||
});
|
||||
|
||||
tags_event
|
||||
|
@ -768,7 +818,10 @@ pub(super) async fn put_room_tag(
|
|||
|
||||
#[admin_command]
|
||||
pub(super) async fn delete_room_tag(
|
||||
&self, user_id: String, room_id: Box<RoomId>, tag: String,
|
||||
&self,
|
||||
user_id: String,
|
||||
room_id: Box<RoomId>,
|
||||
tag: String,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let user_id = parse_active_local_user_id(self.services, &user_id).await?;
|
||||
|
||||
|
@ -778,9 +831,7 @@ pub(super) async fn delete_room_tag(
|
|||
.get_room(&room_id, &user_id, RoomAccountDataEventType::Tag)
|
||||
.await
|
||||
.unwrap_or(TagEvent {
|
||||
content: TagEventContent {
|
||||
tags: BTreeMap::new(),
|
||||
},
|
||||
content: TagEventContent { tags: BTreeMap::new() },
|
||||
});
|
||||
|
||||
tags_event.content.tags.remove(&tag.clone().into());
|
||||
|
@ -796,12 +847,17 @@ pub(super) async fn delete_room_tag(
|
|||
.await?;
|
||||
|
||||
Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Successfully updated room account data for {user_id} and room {room_id}, deleting room tag {tag}"
|
||||
"Successfully updated room account data for {user_id} and room {room_id}, deleting room \
|
||||
tag {tag}"
|
||||
)))
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn get_room_tags(&self, user_id: String, room_id: Box<RoomId>) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn get_room_tags(
|
||||
&self,
|
||||
user_id: String,
|
||||
room_id: Box<RoomId>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let user_id = parse_active_local_user_id(self.services, &user_id).await?;
|
||||
|
||||
let tags_event = self
|
||||
|
@ -810,9 +866,7 @@ pub(super) async fn get_room_tags(&self, user_id: String, room_id: Box<RoomId>)
|
|||
.get_room(&room_id, &user_id, RoomAccountDataEventType::Tag)
|
||||
.await
|
||||
.unwrap_or(TagEvent {
|
||||
content: TagEventContent {
|
||||
tags: BTreeMap::new(),
|
||||
},
|
||||
content: TagEventContent { tags: BTreeMap::new() },
|
||||
});
|
||||
|
||||
Ok(RoomMessageEventContent::notice_markdown(format!(
|
||||
|
@ -822,7 +876,10 @@ pub(super) async fn get_room_tags(&self, user_id: String, room_id: Box<RoomId>)
|
|||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn redact_event(&self, event_id: Box<EventId>) -> Result<RoomMessageEventContent> {
|
||||
pub(super) async fn redact_event(
|
||||
&self,
|
||||
event_id: Box<EventId>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
let Ok(event) = self
|
||||
.services
|
||||
.rooms
|
||||
|
@ -841,7 +898,9 @@ pub(super) async fn redact_event(&self, event_id: Box<EventId>) -> Result<RoomMe
|
|||
let sender_user = event.sender;
|
||||
|
||||
if !self.services.globals.user_is_local(&sender_user) {
|
||||
return Ok(RoomMessageEventContent::text_plain("This command only works on local users."));
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"This command only works on local users.",
|
||||
));
|
||||
}
|
||||
|
||||
let reason = format!(
|
||||
|
|
|
@ -8,7 +8,10 @@ pub(crate) fn escape_html(s: &str) -> String {
|
|||
.replace('>', ">")
|
||||
}
|
||||
|
||||
pub(crate) async fn get_room_info(services: &Services, room_id: &RoomId) -> (OwnedRoomId, u64, String) {
|
||||
pub(crate) async fn get_room_info(
|
||||
services: &Services,
|
||||
room_id: &RoomId,
|
||||
) -> (OwnedRoomId, u64, String) {
|
||||
(
|
||||
room_id.into(),
|
||||
services
|
||||
|
@ -44,7 +47,10 @@ pub(crate) fn parse_local_user_id(services: &Services, user_id: &str) -> Result<
|
|||
}
|
||||
|
||||
/// Parses user ID that is an active (not guest or deactivated) local user
|
||||
pub(crate) async fn parse_active_local_user_id(services: &Services, user_id: &str) -> Result<OwnedUserId> {
|
||||
pub(crate) async fn parse_active_local_user_id(
|
||||
services: &Services,
|
||||
user_id: &str,
|
||||
) -> Result<OwnedUserId> {
|
||||
let user_id = parse_local_user_id(services, user_id)?;
|
||||
|
||||
if !services.users.exists(&user_id).await {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue