diff --git a/src/service/admin/mod.rs b/src/service/admin/mod.rs index 5c5fc2b1..244df85f 100644 --- a/src/service/admin/mod.rs +++ b/src/service/admin/mod.rs @@ -30,7 +30,7 @@ use super::pdu::PduBuilder; use crate::{ service::admin::{ appservice::AppserviceCommand, debug::DebugCommand, federation::FederationCommand, media::MediaCommand, - query::QueryCommand, room::RoomCommand, server::ServerCommand, user::UserCommand, + query::query::QueryCommand, room::RoomCommand, server::ServerCommand, user::UserCommand, }, services, Error, Result, }; @@ -284,7 +284,7 @@ impl Service { AdminCommand::Federation(command) => federation::process(command, body).await?, AdminCommand::Server(command) => server::process(command, body).await?, AdminCommand::Debug(command) => debug::process(command, body).await?, - AdminCommand::Query(command) => query::process(command, body).await?, + AdminCommand::Query(command) => query::query::process(command, body).await?, }; Ok(reply_message_content) diff --git a/src/service/admin/query.rs b/src/service/admin/query.rs deleted file mode 100644 index b86387f6..00000000 --- a/src/service/admin/query.rs +++ /dev/null @@ -1,199 +0,0 @@ -use clap::Subcommand; -use ruma::{ - events::{room::message::RoomMessageEventContent, RoomAccountDataEventType}, - RoomId, UserId, -}; - -use crate::{services, Result}; - -#[cfg_attr(test, derive(Debug))] -#[derive(Subcommand)] -/// Query tables from database -pub(crate) enum QueryCommand { - /// - account_data.rs iterators and getters - #[command(subcommand)] - AccountData(AccountData), - - /// - appservice.rs iterators and getters - #[command(subcommand)] - Appservice(Appservice), - - /// - presence.rs iterators and getters - #[command(subcommand)] - Presence(Presence), -} - -#[cfg_attr(test, derive(Debug))] -#[derive(Subcommand)] -/// All the getters and iterators from src/database/key_value/account_data.rs -/// via services() -pub(crate) enum AccountData { - /// - Returns all changes to the account data that happened after `since`. - ChangesSince { - /// Full user ID - user_id: Box, - /// UNIX timestamp since (u64) - since: u64, - /// Optional room ID of the account data - room_id: Option>, - }, - - /// - Searches the account data for a specific kind. - Get { - /// Full user ID - user_id: Box, - /// Account data event type - kind: RoomAccountDataEventType, - /// Optional room ID of the account data - room_id: Option>, - }, -} - -#[cfg_attr(test, derive(Debug))] -#[derive(Subcommand)] -/// All the getters and iterators from src/database/key_value/appservice.rs via -/// services() -pub(crate) enum Appservice { - /// - Gets the appservice registration info/details from the ID as a string - GetRegistration { - /// Appservice registration ID - appservice_id: Box, - }, -} - -#[cfg_attr(test, derive(Debug))] -#[derive(Subcommand)] -/// All the getters and iterators from src/database/key_value/presence.rs via -/// services() -pub(crate) enum Presence { - /// - Returns the latest presence event for the given user. - GetPresence { - /// Full user ID - user_id: Box, - }, - - /// - Returns the most recent presence updates that happened after the event - /// with id `since`. - PresenceSince { - /// UNIX timestamp since (u64) - since: u64, - }, -} - -/// Processes admin command -#[allow(non_snake_case)] -pub(crate) async fn process(command: QueryCommand, _body: Vec<&str>) -> Result { - match command { - QueryCommand::AccountData(AccountData) => account_data(AccountData).await, - QueryCommand::Appservice(Appservice) => appservice(Appservice).await, - QueryCommand::Presence(Presence) => presence(Presence).await, - } -} - -/// All the getters and iterators in key_value/account_data.rs via services() -async fn account_data(subcommand: AccountData) -> Result { - match subcommand { - AccountData::ChangesSince { - user_id, - since, - room_id, - } => { - let timer = tokio::time::Instant::now(); - let results = services() - .account_data - .db - .changes_since(room_id.as_deref(), &user_id, since)?; - let query_time = timer.elapsed(); - - Ok(RoomMessageEventContent::text_html( - format!("Query completed in {query_time:?}:\n\n```\n{:?}```", results), - format!( - "

Query completed in {query_time:?}:

\n
{:?}\n
", - results - ), - )) - }, - AccountData::Get { - user_id, - kind, - room_id, - } => { - let timer = tokio::time::Instant::now(); - let results = services() - .account_data - .db - .get(room_id.as_deref(), &user_id, kind)?; - let query_time = timer.elapsed(); - - Ok(RoomMessageEventContent::text_html( - format!("Query completed in {query_time:?}:\n\n```\n{:?}```", results), - format!( - "

Query completed in {query_time:?}:

\n
{:?}\n
", - results - ), - )) - }, - } -} - -/// All the getters and iterators in key_value/appservice.rs via services() -async fn appservice(subcommand: Appservice) -> Result { - match subcommand { - Appservice::GetRegistration { - appservice_id, - } => { - let timer = tokio::time::Instant::now(); - let results = services() - .appservice - .db - .get_registration(appservice_id.as_ref())?; - let query_time = timer.elapsed(); - - Ok(RoomMessageEventContent::text_html( - format!("Query completed in {query_time:?}:\n\n```\n{:?}```", results), - format!( - "

Query completed in {query_time:?}:

\n
{:?}\n
", - results - ), - )) - }, - } -} - -/// All the getters and iterators in key_value/appservice.rs via services() -async fn presence(subcommand: Presence) -> Result { - match subcommand { - Presence::GetPresence { - user_id, - } => { - let timer = tokio::time::Instant::now(); - let results = services().presence.db.get_presence(&user_id)?; - let query_time = timer.elapsed(); - - Ok(RoomMessageEventContent::text_html( - format!("Query completed in {query_time:?}:\n\n```\n{:?}```", results), - format!( - "

Query completed in {query_time:?}:

\n
{:?}\n
", - results - ), - )) - }, - Presence::PresenceSince { - since, - } => { - let timer = tokio::time::Instant::now(); - let results = services().presence.db.presence_since(since); - let query_time = timer.elapsed(); - - let presence_since: Vec<(_, _, _)> = results.collect(); - - Ok(RoomMessageEventContent::text_html( - format!("Query completed in {query_time:?}:\n\n```\n{:?}```", presence_since), - format!( - "

Query completed in {query_time:?}:

\n
{:?}\n
", - presence_since - ), - )) - }, - } -} diff --git a/src/service/admin/query/account_data.rs b/src/service/admin/query/account_data.rs new file mode 100644 index 00000000..34bba0f6 --- /dev/null +++ b/src/service/admin/query/account_data.rs @@ -0,0 +1,79 @@ +use clap::Subcommand; +use ruma::{ + events::{room::message::RoomMessageEventContent, RoomAccountDataEventType}, + RoomId, UserId, +}; + +use crate::{services, Result}; + +#[cfg_attr(test, derive(Debug))] +#[derive(Subcommand)] +/// All the getters and iterators from src/database/key_value/account_data.rs +/// via services() +pub(crate) enum AccountData { + /// - Returns all changes to the account data that happened after `since`. + ChangesSince { + /// Full user ID + user_id: Box, + /// UNIX timestamp since (u64) + since: u64, + /// Optional room ID of the account data + room_id: Option>, + }, + + /// - Searches the account data for a specific kind. + Get { + /// Full user ID + user_id: Box, + /// Account data event type + kind: RoomAccountDataEventType, + /// Optional room ID of the account data + room_id: Option>, + }, +} + +/// All the getters and iterators in key_value/account_data.rs via services() +pub(crate) async fn account_data(subcommand: AccountData) -> Result { + match subcommand { + AccountData::ChangesSince { + user_id, + since, + room_id, + } => { + let timer = tokio::time::Instant::now(); + let results = services() + .account_data + .db + .changes_since(room_id.as_deref(), &user_id, since)?; + let query_time = timer.elapsed(); + + Ok(RoomMessageEventContent::text_html( + format!("Query completed in {query_time:?}:\n\n```\n{:?}```", results), + format!( + "

Query completed in {query_time:?}:

\n
{:?}\n
", + results + ), + )) + }, + AccountData::Get { + user_id, + kind, + room_id, + } => { + let timer = tokio::time::Instant::now(); + let results = services() + .account_data + .db + .get(room_id.as_deref(), &user_id, kind)?; + let query_time = timer.elapsed(); + + Ok(RoomMessageEventContent::text_html( + format!("Query completed in {query_time:?}:\n\n```\n{:?}```", results), + format!( + "

Query completed in {query_time:?}:

\n
{:?}\n
", + results + ), + )) + }, + } +} diff --git a/src/service/admin/query/appservice.rs b/src/service/admin/query/appservice.rs new file mode 100644 index 00000000..2ab3c1a1 --- /dev/null +++ b/src/service/admin/query/appservice.rs @@ -0,0 +1,40 @@ +use clap::Subcommand; +use ruma::events::room::message::RoomMessageEventContent; + +use crate::{services, Result}; + +#[cfg_attr(test, derive(Debug))] +#[derive(Subcommand)] +/// All the getters and iterators from src/database/key_value/appservice.rs via +/// services() +pub(crate) enum Appservice { + /// - Gets the appservice registration info/details from the ID as a string + GetRegistration { + /// Appservice registration ID + appservice_id: Box, + }, +} + +/// All the getters and iterators in key_value/appservice.rs via services() +pub(crate) async fn appservice(subcommand: Appservice) -> Result { + match subcommand { + Appservice::GetRegistration { + appservice_id, + } => { + let timer = tokio::time::Instant::now(); + let results = services() + .appservice + .db + .get_registration(appservice_id.as_ref())?; + let query_time = timer.elapsed(); + + Ok(RoomMessageEventContent::text_html( + format!("Query completed in {query_time:?}:\n\n```\n{:?}```", results), + format!( + "

Query completed in {query_time:?}:

\n
{:?}\n
", + results + ), + )) + }, + } +} diff --git a/src/service/admin/query/mod.rs b/src/service/admin/query/mod.rs new file mode 100644 index 00000000..04c98a8d --- /dev/null +++ b/src/service/admin/query/mod.rs @@ -0,0 +1,6 @@ +#[allow(clippy::module_inception)] +pub(crate) mod query; + +pub(crate) mod account_data; +pub(crate) mod appservice; +pub(crate) mod presence; diff --git a/src/service/admin/query/presence.rs b/src/service/admin/query/presence.rs new file mode 100644 index 00000000..7df4858a --- /dev/null +++ b/src/service/admin/query/presence.rs @@ -0,0 +1,61 @@ +use clap::Subcommand; +use ruma::{events::room::message::RoomMessageEventContent, UserId}; + +use crate::{services, Result}; + +#[cfg_attr(test, derive(Debug))] +#[derive(Subcommand)] +/// All the getters and iterators from src/database/key_value/presence.rs via +/// services() +pub(crate) enum Presence { + /// - Returns the latest presence event for the given user. + GetPresence { + /// Full user ID + user_id: Box, + }, + + /// - Returns the most recent presence updates that happened after the event + /// with id `since`. + PresenceSince { + /// UNIX timestamp since (u64) + since: u64, + }, +} + +/// All the getters and iterators in key_value/presence.rs via services() +pub(crate) async fn presence(subcommand: Presence) -> Result { + match subcommand { + Presence::GetPresence { + user_id, + } => { + let timer = tokio::time::Instant::now(); + let results = services().presence.db.get_presence(&user_id)?; + let query_time = timer.elapsed(); + + Ok(RoomMessageEventContent::text_html( + format!("Query completed in {query_time:?}:\n\n```\n{:?}```", results), + format!( + "

Query completed in {query_time:?}:

\n
{:?}\n
", + results + ), + )) + }, + Presence::PresenceSince { + since, + } => { + let timer = tokio::time::Instant::now(); + let results = services().presence.db.presence_since(since); + let query_time = timer.elapsed(); + + let presence_since: Vec<(_, _, _)> = results.collect(); + + Ok(RoomMessageEventContent::text_html( + format!("Query completed in {query_time:?}:\n\n```\n{:?}```", presence_since), + format!( + "

Query completed in {query_time:?}:

\n
{:?}\n
", + presence_since + ), + )) + }, + } +} diff --git a/src/service/admin/query/query.rs b/src/service/admin/query/query.rs new file mode 100644 index 00000000..6d56eca2 --- /dev/null +++ b/src/service/admin/query/query.rs @@ -0,0 +1,36 @@ +use clap::Subcommand; +use ruma::events::room::message::RoomMessageEventContent; + +use super::{ + account_data::{account_data, AccountData}, + appservice::{appservice, Appservice}, + presence::{presence, Presence}, +}; +use crate::Result; + +#[cfg_attr(test, derive(Debug))] +#[derive(Subcommand)] +/// Query tables from database +pub(crate) enum QueryCommand { + /// - account_data.rs iterators and getters + #[command(subcommand)] + AccountData(AccountData), + + /// - appservice.rs iterators and getters + #[command(subcommand)] + Appservice(Appservice), + + /// - presence.rs iterators and getters + #[command(subcommand)] + Presence(Presence), +} + +/// Processes admin query commands +#[allow(non_snake_case)] +pub(crate) async fn process(command: QueryCommand, _body: Vec<&str>) -> Result { + match command { + QueryCommand::AccountData(AccountData) => account_data(AccountData).await, + QueryCommand::Appservice(Appservice) => appservice(Appservice).await, + QueryCommand::Presence(Presence) => presence(Presence).await, + } +} diff --git a/src/service/admin/query/rooms/alias.rs b/src/service/admin/query/rooms/alias.rs new file mode 100644 index 00000000..e69de29b diff --git a/src/service/admin/query/rooms/mod.rs b/src/service/admin/query/rooms/mod.rs new file mode 100644 index 00000000..10d83ca6 --- /dev/null +++ b/src/service/admin/query/rooms/mod.rs @@ -0,0 +1 @@ +pub(crate) use alias;