diff --git a/mgb.ini b/mgb.ini
index aee6c9b1f9dedde388565a547a916e4d9c488a1d..47a6bec69c0761bf9167c04adfb3bf5ea4f4699a 100644
--- a/mgb.ini
+++ b/mgb.ini
@@ -1,12 +1,13 @@
 [user]
-id           = "@some_id:matrix.org"
-password     = no-password
-display_name = MGB-Hitagi
+id=@some_id\:matrix.org
+password=no-password
+display_name=MGB-Hitagi
 
 [handler]
-state_member = true
+state_member=false
+reaction=true
 
 [basic]
-name   = basic package
-acl    = any
-admins = @martin2018:iiens.net
+name=basic package
+acl=any
+admins=@some_id\:matrix.org
diff --git a/src/config.rs b/src/config.rs
index a2696c5325114245670a293fd5a65e458ccc253a..e2adb2558327137e77ba5683a41550dcb65bee84 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -12,6 +12,7 @@ pub struct Config {
     pub user_password: String, // The true user name
 
     pub handle_state_member: bool, // Install handler for state memver changes
+    pub handle_reaction: bool,     // Install handler for emoji reactions
 
     ini_handler: Ini,
 }
@@ -49,6 +50,9 @@ pub fn from_file(file_name: &String) -> Result<Config, String> {
             let handle_state_member_str = conf
                 .get_from_or(Some("handler"), "state_member", "true")
                 .to_string();
+            let handle_reaction_str = conf
+                .get_from_or(Some("handler"), "reaction", "true")
+                .to_string();
             return match Url::parse(hs_url_str) {
                 Err(e) => Err(e.to_string()),
                 Ok(hs_url) => Ok(Config {
@@ -64,6 +68,8 @@ pub fn from_file(file_name: &String) -> Result<Config, String> {
                     homeserver_url: hs_url,
                     handle_state_member: <bool as FromStr>::from_str(&handle_state_member_str)
                         .unwrap_or(false),
+                    handle_reaction: <bool as FromStr>::from_str(&handle_reaction_str)
+                        .unwrap_or(false),
                     ini_handler: conf,
                 }),
             };
@@ -78,7 +84,8 @@ pub fn write_default(file_name: &String) -> Result<(), String> {
         .set("password", "no-password")
         .set("display_name", "MGB-Hitagi");
     conf.with_section(Some("handler"))
-        .set("state_member", "true");
+        .set("state_member", "false")
+        .set("reaction", "true");
     conf.with_section(Some("basic"))
         .set("name", "basic package")
         .set("acl", "any")
diff --git a/src/matrix.rs b/src/matrix.rs
index 08896e4a34f7a35efdf052bc2cd6c80565202979..48b7abca801cd4b077797707b8068fc00ec55202 100644
--- a/src/matrix.rs
+++ b/src/matrix.rs
@@ -81,9 +81,83 @@ async fn startup_and_log_rooms(client: &Client) {
     join_all(list_to_wait_for).await;
 }
 
+async fn on_msg_room_event(
+    ev: SyncMessageEvent<MessageEventContent>,
+    room: Room,
+    __info: Option<EncryptionInfo>,
+) {
+    let sender_id = ev.sender.clone();
+    return_if!(sender_id.as_str() == room.own_user_id().as_str(), ());
+
+    if let (Room::Joined(joined), MessageType::Text(TextMessageEventContent { ref body, .. })) =
+        (room, ev.content.msgtype.clone())
+    {
+        if body.starts_with("%") {
+            if let Some(stripped) = body.strip_prefix("%") {
+                let args = stripped.split(' ').collect::<Vec<&str>>();
+                let mut res: String = format!("Command not found");
+                if let Some(pkg) = GLOBAL_PKG
+                    .lock()
+                    .unwrap()
+                    .iter()
+                    .find(|x| x.has_command(&args))
+                {
+                    res = pkg.handle(&joined, &sender_id, args);
+                }
+
+                let event = ev.into_full_event(joined.room_id().clone());
+                let msg = AnyMessageEventContent::RoomMessage(
+                    MessageEventContent::text_reply_html(res.clone(), res, &event),
+                );
+                joined.send(msg, None).await.unwrap();
+            }
+        }
+    };
+}
+
+async fn on_msg_room_reaction(
+    ev: SyncMessageEvent<ReactionEventContent>,
+    room: Room,
+    _: Option<EncryptionInfo>,
+) {
+    let sender_id = ev.sender.clone();
+    return_if!(sender_id.as_str() == room.own_user_id().as_str(), ());
+    if let (
+        Room::Joined(joined),
+        ReactionEventContent {
+            relates_to: Relation {
+                emoji, event_id, ..
+            },
+            ..
+        },
+    ) = (room, ev.content)
+    {
+        let msg_content = format!(
+            "Not handled reactions in room {} with event {event_id}, emoji was {emoji}",
+            joined.room_id()
+        );
+        let msg = AnyMessageEventContent::RoomMessage(MessageEventContent::text_html(
+            msg_content.clone(),
+            msg_content,
+        ));
+        joined.send(msg, None).await.unwrap();
+    };
+}
+
 static GLOBAL_PKG: SyncLazy<Arc<Mutex<Vec<CmdPackage>>>> =
     SyncLazy::new(|| Arc::new(Mutex::new(Vec::<CmdPackage>::new())));
 
+macro_rules! register_handler_if_enabled {
+    ($client: expr, $config: expr, $handler: expr, $handler_name: expr) => {{
+        if ($config) {
+            info!("Handle {} events", $handler_name);
+            ($client).register_event_handler($handler).await;
+        } else {
+            warn!("Ignore {} events", $handler_name);
+        }
+    }};
+}
+
 pub async fn connect_and_handle(config: Config) -> Result<()> {
     // TODO: Refactor
     let pkg_commands_vec = vec![
@@ -98,65 +172,6 @@ pub async fn connect_and_handle(config: Config) -> Result<()> {
     };
     GLOBAL_PKG.lock().unwrap().push(pkg);
 
-    let on_msg_room_reaction = |ev: SyncMessageEvent<ReactionEventContent>,
-                                room: Room,
-                                _: Option<EncryptionInfo>| async move {
-        let sender_id = ev.sender.clone();
-        return_if!(sender_id.as_str() == room.own_user_id().as_str(), ());
-        if let (
-            Room::Joined(joined),
-            ReactionEventContent {
-                relates_to: Relation {
-                    emoji, event_id, ..
-                },
-                ..
-            },
-        ) = (room, ev.content)
-        {
-            let msg_content = format!(
-                "Not handled reactions in room {} with event {event_id}, emoji was {emoji}",
-                joined.room_id()
-            );
-            let msg = AnyMessageEventContent::RoomMessage(MessageEventContent::text_html(
-                msg_content.clone(),
-                msg_content,
-            ));
-            joined.send(msg, None).await.unwrap();
-        };
-    };
-
-    let on_msg_room_event = |ev: SyncMessageEvent<MessageEventContent>,
-                             room: Room,
-                             __info: Option<EncryptionInfo>| async {
-        let sender_id = ev.sender.clone();
-        return_if!(sender_id.as_str() == room.own_user_id().as_str(), ());
-
-        if let (Room::Joined(joined), MessageType::Text(TextMessageEventContent { ref body, .. })) =
-            (room, ev.content.msgtype.clone())
-        {
-            if body.starts_with("%") {
-                if let Some(stripped) = body.strip_prefix("%") {
-                    let args = stripped.split(' ').collect::<Vec<&str>>();
-                    let mut res: String = format!("Command not found");
-                    if let Some(pkg) = GLOBAL_PKG
-                        .lock()
-                        .unwrap()
-                        .iter()
-                        .find(|x| x.has_command(&args))
-                    {
-                        res = pkg.handle(&joined, &sender_id, args);
-                    }
-
-                    let event = ev.into_full_event(joined.room_id().clone());
-                    let msg = AnyMessageEventContent::RoomMessage(
-                        MessageEventContent::text_reply_html(res.clone(), res, &event),
-                    );
-                    joined.send(msg, None).await.unwrap();
-                }
-            }
-        };
-    };
-
     let alice = UserId::try_from(config.user_name)?;
     let client = Client::new(config.homeserver_url)?;
 
@@ -171,14 +186,13 @@ pub async fn connect_and_handle(config: Config) -> Result<()> {
     info!("Logged as: {}", alice);
 
     client.sync_once(SyncSettings::default()).await?;
-
     startup_and_log_rooms(&client).await;
-    if config.handle_state_member {
-        info!("Handle state member events");
-        client.register_event_handler(on_state_member).await;
-    } else {
-        warn!("Ignore state member events");
-    }
+    register_handler_if_enabled!(
+        client,
+        config.handle_state_member,
+        on_state_member,
+        "state member"
+    );
 
     client.register_event_handler(on_msg_room_event).await;
     client.register_event_handler(on_msg_room_reaction).await;