mrsbfh

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

commit 042c76a783c49129bfb1f8c4c6edffed812dafa0
parent 346af5b8c1563ec3bff09d41b119ed431b2436cc
Author: MTRNord <mtrnord1@gmail.com>
Date:   Thu,  7 Jan 2021 18:39:55 +0100

feat: Add autojoin proc macro and implement in the example bot

Diffstat:
Mexample-bot/src/matrix/sync.rs | 13++++++++++++-
Mmrsbfh-macros/src/lib.rs | 84++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mmrsbfh/src/utils.rs | 2++
3 files changed, 97 insertions(+), 2 deletions(-)

diff --git a/example-bot/src/matrix/sync.rs b/example-bot/src/matrix/sync.rs @@ -2,8 +2,9 @@ use crate::commands::match_command; use crate::config::Config; use mrsbfh::matrix_sdk::{ events::{ + room::member::MemberEventContent, room::message::{MessageEventContent, TextMessageEventContent}, - SyncMessageEvent, + StrippedStateEvent, SyncMessageEvent, }, Client, EventEmitter, SyncRoom, }; @@ -26,6 +27,7 @@ impl Bot { } } +#[mrsbfh::utils::autojoin] #[async_trait] impl EventEmitter for Bot { async fn on_room_message(&self, room: SyncRoom, event: &SyncMessageEvent<MessageEventContent>) { @@ -83,4 +85,13 @@ impl EventEmitter for Bot { } } } + + async fn on_stripped_state_member( + &self, + room: SyncRoom, + room_member: &StrippedStateEvent<MemberEventContent>, + _: Option<MemberEventContent>, + ) { + println!("test") + } } diff --git a/mrsbfh-macros/src/lib.rs b/mrsbfh-macros/src/lib.rs @@ -1,5 +1,4 @@ pub(crate) mod utils; - use crate::utils::get_arg; use convert_case::{Case, Casing}; use proc_macro::TokenStream; @@ -192,3 +191,86 @@ pub fn config_derive(input: TokenStream) -> TokenStream { TokenStream::from(expanded) } + +/// Used to generate code to autojoin when we get a invite for the bot +/// +/// Requirements: +/// +/// * Tokio +/// * Naming of arguments needs to be EXACTLY like in the example +/// * the async_trait macro needs to be BELOW the autojoin macro +/// +/// ```compile_fail +/// #[mrsbfh::utils::autojoin] +/// #[async_trait] +/// impl EventEmitter for Bot { +/// +/// async fn on_stripped_state_member( +/// &self, +/// room: SyncRoom, +/// room_member: &StrippedStateEvent<MemberEventContent>, +/// _: Option<MemberEventContent>, +/// ) { +/// // Your own logic. (Executed BEFORE the autojoin) +/// } +/// } +/// ``` +/// +#[proc_macro_attribute] +pub fn autojoin(_: TokenStream, input: TokenStream) -> TokenStream { + let mut input = parse_macro_input!(input as syn::ItemImpl); + let items = &mut input.items; + + for item in items { + if let syn::ImplItem::Method(method) = item { + if method.sig.ident.to_string() == "on_stripped_state_member" { + let original = method.block.clone(); + let new_block = syn::parse_quote! { + { + #original + + // Autojoin logic + if room_member.state_key != self.client.user_id().await.unwrap() { + warn!("Got invite that isn't for us"); + return; + } + if let SyncRoom::Invited(room) = room { + let room_id = { + let room = room.read().await; + room.room_id.clone() + }; + let client = self.client.clone(); + + tokio::spawn(async move { + info!("Autojoining room {}", room_id); + let mut delay = 2; + + while let Err(err) = client.join_room_by_id(&room_id).await { + // retry autojoin due to synapse sending invites, before the + // invited user can join for more information see + // https://github.com/matrix-org/synapse/issues/4345 + error!( + "Failed to join room {} ({:?}), retrying in {}s", + room_id, err, delay + ); + + tokio::time::delay_for(tokio::time::Duration::from_secs(delay)).await; + delay *= 2; + + if delay > 3600 { + error!("Can't join room {} ({:?})", room_id, err); + break; + } + } + info!("Successfully joined room {}", room_id); + }); + } + } + }; + method.block = new_block; + } + } + } + + TokenStream::from(quote! {#input}) +} diff --git a/mrsbfh/src/utils.rs b/mrsbfh/src/utils.rs @@ -3,6 +3,8 @@ use std::error::Error; use std::path::PathBuf; use tracing::*; +pub use mrsbfh_macros::autojoin; + #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Session { /// The homeserver used for this session.