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:
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.