diff --git a/src/database/admin.rs b/src/database/admin.rs
index 7d2301d9..518d7587 100644
--- a/src/database/admin.rs
+++ b/src/database/admin.rs
@@ -1,10 +1,17 @@
-use std::{convert::TryInto, sync::Arc};
+use std::{convert::TryFrom, convert::TryInto, sync::Arc, time::Instant};
-use crate::{pdu::PduBuilder, Database};
-use rocket::futures::{channel::mpsc, stream::StreamExt};
+use crate::{
+ error::{Error, Result},
+ pdu::PduBuilder,
+ server_server, Database, PduEvent,
+};
+use rocket::{
+ futures::{channel::mpsc, stream::StreamExt},
+ http::RawStr,
+};
use ruma::{
events::{room::message::RoomMessageEventContent, EventType},
- UserId,
+ EventId, RoomId, RoomVersionId, UserId,
};
use serde_json::value::to_raw_value;
use tokio::sync::{MutexGuard, RwLock, RwLockReadGuard};
@@ -137,3 +144,227 @@ impl Admin {
self.sender.unbounded_send(command).unwrap();
}
}
+
+pub fn parse_admin_command(db: &Database, command_line: &str, body: Vec<&str>) -> AdminCommand {
+ let mut parts = command_line.split_whitespace().skip(1);
+
+ let command_name = match parts.next() {
+ Some(command) => command,
+ None => {
+ let message = "No command given. Use help
for a list of commands.";
+ return AdminCommand::SendMessage(RoomMessageEventContent::text_html(
+ html_to_markdown(message),
+ message,
+ ));
+ }
+ };
+
+ let args: Vec<_> = parts.collect();
+
+ match try_parse_admin_command(db, command_name, args, body) {
+ Ok(admin_command) => admin_command,
+ Err(error) => {
+ let message = format!(
+ "Encountered error while handling {}
command:\n\
+
{}", + command_name, error, + ); + + AdminCommand::SendMessage(RoomMessageEventContent::text_html( + html_to_markdown(&message), + message, + )) + } + } +} + +// Helper for `RoomMessageEventContent::text_html`, which needs the content as +// both markdown and HTML. +fn html_to_markdown(text: &str) -> String { + text.replace("
", "") + .replace("
", "\n") + .replace("", "```\n") + .replace("", "\n```") + .replace("
", "`")
+ .replace("
", "`")
+ .replace("The following commands are available:
+register_appservice
: Register a bridge using its registration YAMLunregister_appservice
: Unregister a bridge using its IDlist_appservices
: List all the currently registered bridgesget_auth_chain
: Get the `auth_chain` of a PDUparse_pdu
: Parse and print a PDU from a JSONget_pdu
: Retrieve and print a PDU by ID from the Conduit databasedatabase_memory_usage
: Print database memory usage statistics{}
\n{}\n
\n",
+ if outlier {
+ "PDU is outlier"
+ } else { "PDU was accepted"}, RawStr::new(&json_text).html_escape())
+ ),
+ )
+ }
+ None => AdminCommand::SendMessage(RoomMessageEventContent::text_plain(
+ "PDU not found.",
+ )),
+ }
+ } else {
+ AdminCommand::SendMessage(RoomMessageEventContent::text_plain(
+ "Event ID could not be parsed.",
+ ))
+ }
+ } else {
+ AdminCommand::SendMessage(RoomMessageEventContent::text_plain(
+ "Usage: get_pdu {}
, try help
for a list of commands.",
+ command,
+ );
+ AdminCommand::SendMessage(RoomMessageEventContent::text_html(
+ html_to_markdown(&message),
+ message,
+ ))
+ }
+ };
+
+ Ok(command)
+}
diff --git a/src/database/rooms.rs b/src/database/rooms.rs
index 0ba6c9ba..14df8f50 100644
--- a/src/database/rooms.rs
+++ b/src/database/rooms.rs
@@ -3,13 +3,13 @@ mod edus;
pub use edus::RoomEdus;
use crate::{
+ database::admin::parse_admin_command,
pdu::{EventHash, PduBuilder},
- server_server, utils, Database, Error, PduEvent, Result,
+ utils, Database, Error, PduEvent, Result,
};
use lru_cache::LruCache;
use regex::Regex;
use ring::digest;
-use rocket::http::RawStr;
use ruma::{
api::{client::error::ErrorKind, federation},
events::{
@@ -19,7 +19,6 @@ use ruma::{
room::{
create::RoomCreateEventContent,
member::{MembershipState, RoomMemberEventContent},
- message::RoomMessageEventContent,
power_levels::RoomPowerLevelsEventContent,
},
tag::TagEvent,
@@ -40,12 +39,11 @@ use std::{
iter,
mem::size_of,
sync::{Arc, Mutex, RwLock},
- time::Instant,
};
use tokio::sync::MutexGuard;
use tracing::{error, warn};
-use super::{abstraction::Tree, admin::AdminCommand, pusher};
+use super::{abstraction::Tree, pusher};
/// The unique identifier of each state group.
///
@@ -1496,216 +1494,8 @@ impl Rooms {
let command_line = lines.next().expect("each string has at least one line");
let body: Vec<_> = lines.collect();
- let mut parts = command_line.split_whitespace().skip(1);
- if let Some(command) = parts.next() {
- let args: Vec<_> = parts.collect();
-
- match command {
- "register_appservice" => {
- if body.len() > 2
- && body[0].trim() == "```"
- && body.last().unwrap().trim() == "```"
- {
- let appservice_config = body[1..body.len() - 1].join("\n");
- let parsed_config = serde_yaml::from_str::{}
\n{}\n
\n",
- if outlier {
- "PDU is outlier"
- } else { "PDU was accepted"}, RawStr::new(&json_text).html_escape())
- ),
- ));
- }
- None => {
- db.admin.send(AdminCommand::SendMessage(
- RoomMessageEventContent::text_plain(
- "PDU not found.",
- ),
- ));
- }
- }
- } else {
- db.admin.send(AdminCommand::SendMessage(
- RoomMessageEventContent::text_plain(
- "Event ID could not be parsed.",
- ),
- ));
- }
- } else {
- db.admin.send(AdminCommand::SendMessage(
- RoomMessageEventContent::text_plain(
- "Usage: get_pdu