mrsbfh

Matrix-Rust-SDK-Bot-Framework-Helper
git clone git://archive.git.mtrnord.blog/MTRNord/mrsbfh.git
Log | Files | Refs | README

commit 79417cefc3ad6844277860c8931655b237fba83c
parent d7ca0ac94f9ac467f54f4e3d7967fbd5e6955f21
Author: MTRNord <mtrnord1@gmail.com>
Date:   Thu,  7 Jan 2021 21:11:56 +0100

chore: Add docs everywhere

Diffstat:
MREADME.md | 8+++++++-
Mmrsbfh/src/commands.rs | 121+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmrsbfh/src/config.rs | 32++++++++++++++++++++++++++++++++
Mmrsbfh/src/lib.rs | 24++++++++++++++++++++++++
Mmrsbfh/src/utils.rs | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 285 insertions(+), 1 deletion(-)

diff --git a/README.md b/README.md @@ -1,5 +1,11 @@ # MRSBFH - Matrix-Rust-SDK-Bot-Framework-Helper +[<img alt="github" src="https://img.shields.io/badge/github-MTRNord/mrsbfh-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/MTRNord/mrsbfh) +[<img alt="crates.io" src="https://img.shields.io/crates/v/mrsbfh.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/mrsbfh) +[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-mrsbfh-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" height="20">](https://docs.rs/mrsbfh) +<!--[<img alt="build status" src="https://img.shields.io/github/workflow/status/MTRNord/mrsbfh/CI/master?style=for-the-badge" height="20">](https://github.com/MTRNord/mrsbfh/actions?query=branch%3Amaster)--> + + A toolkit for writing commandbots more efficient in rust for matrix. ## How to use @@ -12,6 +18,6 @@ mrsbfh = {git = "https://github.com/MTRNord/mrsbfh"} After that there are the possible helpers available that are further described in the docs. -As there was no release yet, you can open them using `cargo doc -p mrsbfh --open` in any crate depending on it or after cloning the repository. +As there was no release yet, you can open them using `cargo +nigtly doc -p mrsbfh --open` in any crate depending on it or after cloning the repository. For a minimal example of the bot checkout the crate under the `example-bot` folder which is a minimal version of what is needed. diff --git a/mrsbfh/src/commands.rs b/mrsbfh/src/commands.rs @@ -1 +1,122 @@ +//! # Commands +//! +//! ## `#[command]` macro +//! +//! Commands are defined in their own submodules using a function which name defines the command name. +//! +//! These functions require a specific syntax which is described below. +//! +//! Also that function requires you to have a config struct which implements the [Config](crate::config::Config) +//! trait. +//! +//! <br> +//! +//! To use the commands macros you want a module where these commands are stored in. This is because +//! each is REQUIRED to be in a submodule with the SAME name as the commands name. +//! +//! In each of these submodules you can define a command like this: +//! +//! ```compile_fail +//! use matrix_sdk::events::{room::message::MessageEventContent, AnyMessageEventContent}; +//! use mrsbfh::commands::command; +//! use mrsbfh::config::Config; +//! use std::error::Error; +//! +//! #[command(help = "`!hello_world` - Prints \"hello world\".")] +//! pub async fn hello_world<C: Config>( +//! tx: mrsbfh::Sender, +//! _config: C, +//! _sender: String, +//! mut _args: Vec<&str>, +//! ) -> Result<(), Box<dyn Error>> { +//! let content = +//! AnyMessageEventContent::RoomMessage(MessageEventContent::notice_plain("Hello World!")); +//! +//! tx.send(content).await?; +//! Ok(()) +//! } +//! ``` +//! +//! <br> +//! +//! ## `#[command_generate]` macro +//! +//! You can now either build your own match statement and help or to make this more convenient you +//! can use the `command_generate` macro to do this for you. +//! +//! To use it you are required to have the following code structure inside the file that is the +//! direct parent module of the commands. +//! +//! ```compile_fail +//! use mrsbfh::commands::command_generate; +//! +//! pub mod hello_world; +//! +//! #[command_generate( +//! bot_name = "Example", +//! description = "This bot prints hello!" +//! )] +//! enum Commands { +//! HelloWorld +//! } +//! ``` +//! +//! This does generate a `match_command` function which takes the following arguments: +//! +//! `(command: &str, config: C, tx: mrsbfh::Sender, sender: String, args: Vec<&str>)` +//! +//! and it returns: `Result<(), Box<dyn Error>>`. +//! +//! This can either be called by you or you can continue reading and instead use another macro to +//! do this for you. +//! +//! <br> +//! +//! ## `#[commands]` macro +//! +//! This macro is used to generate the logic in the [EventEmitter](matrix_sdk::EventEmitter) to +//! handle commands after your code. +//! +//! The usage is: +//! +//! ```compile_fail +//! use crate::commands::match_command; +//! use crate::config::Config; +//! use matrix_sdk::async_trait; +//! use matrix_sdk::{ +//! events::{ +//! room::message::MessageEventContent, +//! SyncMessageEvent, +//! }, +//! Client, EventEmitter, SyncRoom, +//! }; +//! use tracing::*; +//! +//! #[derive(Debug, Clone)] +//! pub struct Bot { +//! client: Client, +//! config: Config<'static>, +//! } +//! +//! #[mrsbfh::commands::commands] +//! #[async_trait] +//! impl EventEmitter for Bot { +//! async fn on_room_message(&self, room: SyncRoom, event: &SyncMessageEvent<MessageEventContent>) { +//! println!("message example") +//! } +//! } +//! ``` +//! +//! <br> +//! +//! **This does have some requirements:** +//! * Your `match_command` function MUST be imported +//! * The struct MUST have a field `config` which implements the [Config](crate::config::Config) +//! trait +//! * The struct MUST have a field `client` which is the [MatrixSDK Client](matrix_sdk::Client) +//! * The `#[async_trait]` macro MUST be below the `#[commands]` macro +//! * The `on_room_message` method MUST exist and the arguments MUST be named the way they are named +//! in the example. +//! + pub use mrsbfh_macros::{command, command_generate, commands}; diff --git a/mrsbfh/src/config.rs b/mrsbfh/src/config.rs @@ -1,3 +1,35 @@ +//! # Config +//! +//! The Config Trait is used to be able to pass your Config to the commands as well as use them for +//! the path of the session. +//! +//! <br> +//! +//! The simplest way is to use the Derive macro [`#[derive(ConfigDerive)]`](crate::config::ConfigDerive) +//! +//! It requires however that You also derive [Clone](std::clone::Clone), [Serialize](serde::Serialize) +//! and [Deserialize](serde::Deserialize). +//! +//! Also this only works for yaml config files. For any other format you will to implement the trait +//! yourself. However the crate still needs to implement [Clone](std::clone::Clone). +//! +//! ## Example +//! +//! ```compile_fail +//! use serde::{Deserialize, Serialize}; +//! use std::borrow::Cow; +//! +//! #[derive(Debug, PartialEq, Serialize, Deserialize, Clone, ConfigDerive)] +//! pub struct Config<'a> { +//! pub homeserver_url: Cow<'a, str>, +//! pub mxid: Cow<'a, str>, +//! pub password: Cow<'a, str>, +//! pub store_path: Cow<'a, str>, +//! pub session_path: Cow<'a, str>, +//! } +//! ``` +//! + use serde::de::DeserializeOwned; use serde::Serialize; use std::error::Error; diff --git a/mrsbfh/src/lib.rs b/mrsbfh/src/lib.rs @@ -1,3 +1,27 @@ +//! [![github]](https://github.com/MTRNord/mrsbfh)&ensp;[![crates-io]](https://crates.io/crates/mrsbfh)&ensp;[![docs-rs]](crate) +//! +//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github +//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust +//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K +//! +//! <br> +//! +//! # MRSBFH - Matrix-Rust-SDK-Bot-Framework-Helper +//! +//! `mrsbfh` is a collection of utilities to make performing certain tasks in command bots +//! with matrix easier. +//! +//! ## Features +//! +//! * Macro for simple autojoin functionality +//! * Macros for pretty defining of commands +//! * Utils for a simple Config +//! * Utils for restoring ad saving matrix sessions +//! +//! ## Examples +//! +//! For examples please have a look at the [example-bot](https://github.com/MTRNord/mrsbfh/tree/main/example-bot) or take a look in the individual modules. + pub mod commands; pub mod config; pub mod utils; diff --git a/mrsbfh/src/utils.rs b/mrsbfh/src/utils.rs @@ -1,3 +1,104 @@ +//! # Utils +//! +//! ## Session +//! +//! The easiest way to use the [Session](crate::utils::Session) struct is to use it like this: +//! +//! ```compile_fail +//! use matrix_sdk::Session as SDKSession; +//! +//! if let Some(session) = Session::load(config.session_path.parse().unwrap()) { +//! info!("Starting relogin"); +//! +//! let session = SDKSession { +//! access_token: session.access_token, +//! device_id: session.device_id.into(), +//! user_id: matrix_sdk::identifiers::UserId::try_from(session.user_id.as_str()).unwrap(), +//! }; +//! +//! if let Err(e) = client.restore_login(session).await { +//! error!("{}", e); +//! }; +//! info!("Finished relogin"); +//! } else { +//! info!("Starting login"); +//! let login_response = client +//! .login( +//! &config.mxid, +//! &config.password, +//! None, +//! Some(&"timetracking-bot".to_string()), +//! ) +//! .await; +//! match login_response { +//! Ok(login_response) => { +//! info!("Session: {:#?}", login_response); +//! let session = Session { +//! homeserver: client.homeserver().to_string(), +//! user_id: login_response.user_id.to_string(), +//! access_token: login_response.access_token, +//! device_id: login_response.device_id.into(), +//! }; +//! session.save(config.session_path.parse().unwrap())?; +//! } +//! Err(e) => error!("Error while login: {}", e), +//! } +//! info!("Finished login"); +//! } +//! ``` +//! +//! <br> +//! +//! This first checks if there is a session already existing and uses it to relogin using the known +//! session data. +//! +//! If not it creates and saves the [Session](crate::utils::Session) struct. Allowing for a relogin on the next start. +//! +//! ## Autojoin +//! +//! The [`#[autojoin]`](crate::utils::autojoin) macro is used to generate the logic in the +//! [EventEmitter](matrix_sdk::EventEmitter) to handle invites for the bot. It is executed after your code. +//! +//! The usage is: +//! +//! ```compile_fail +//! use matrix_sdk::async_trait; +//! use matrix_sdk::{ +//! events::{ +//! room::message::MessageEventContent, StrippedStateEvent, +//! }, +//! EventEmitter, SyncRoom, Client +//! }; +//! use tracing::*; +//! +//! #[derive(Debug, Clone)] +//! pub struct Bot { +//! client: Client, +//! } +//! +//! #[mrsbfh::utils::autojoin] +//! #[async_trait] +//! impl EventEmitter for Bot { +//! async fn on_stripped_state_member( +//! &self, +//! room: SyncRoom, +//! room_member: &StrippedStateEvent<MemberEventContent>, +//! _: Option<MemberEventContent>, +//! ) { +//! println!("autojoin example") +//! } +//! } +//! ``` +//! +//! <br> +//! +//! **This does have some requirements:** +//! * The struct MUST have a field `client` which is the [MatrixSDK Client](matrix_sdk::Client) +//! * The `#[async_trait]` macro MUST be below the `#[autojoin]` macro +//! * The `on_stripped_state_member` method MUST exist and the arguments MUST be named the way they are named +//! in the example. +//! + use serde::{Deserialize, Serialize}; use std::error::Error; use std::path::PathBuf;