From 7857da8a0b6322618b12e4b41c6945bcd7dee9ef Mon Sep 17 00:00:00 2001
From: Torsten Flammiger <git@netfg.net>
Date: Mon, 20 Dec 2021 15:46:36 +0100
Subject: [PATCH 1/4] Add ability to remove an appservice

---
 APPSERVICES.md             | 8 ++++++++
 src/database/admin.rs      | 4 ++++
 src/database/appservice.rs | 9 +++++++++
 src/database/rooms.rs      | 9 +++++++++
 4 files changed, 30 insertions(+)

diff --git a/APPSERVICES.md b/APPSERVICES.md
index 26c34cc4..894bc6f4 100644
--- a/APPSERVICES.md
+++ b/APPSERVICES.md
@@ -42,6 +42,14 @@ could help.
 
 ## Appservice-specific instructions
 
+### Remove an appservice
+
+To remove an appservice go to your admin room and execute
+
+```@conduit:your.server.name: unregister_appservice <name>```
+
+where `<name>` one of the output of `list_appservices`.
+
 ### Tested appservices
 
 These appservices have been tested and work with Conduit without any extra steps:
diff --git a/src/database/admin.rs b/src/database/admin.rs
index 1e5c47c9..0702bcdd 100644
--- a/src/database/admin.rs
+++ b/src/database/admin.rs
@@ -12,6 +12,7 @@ use tracing::warn;
 
 pub enum AdminCommand {
     RegisterAppservice(serde_yaml::Value),
+    UnregisterAppservice(String),
     ListAppservices,
     SendMessage(RoomMessageEventContent),
 }
@@ -96,6 +97,9 @@ impl Admin {
                             AdminCommand::RegisterAppservice(yaml) => {
                                 guard.appservice.register_appservice(yaml).unwrap(); // TODO handle error
                             }
+                            AdminCommand::UnregisterAppservice(service_name) => {
+                                guard.appservice.unregister_appservice(&service_name).unwrap(); // TODO: see above
+                            }
                             AdminCommand::ListAppservices => {
                                 if let Ok(appservices) = guard.appservice.iter_ids().map(|ids| ids.collect::<Vec<_>>()) {
                                     let count = appservices.len();
diff --git a/src/database/appservice.rs b/src/database/appservice.rs
index 7cc91372..caa48ad0 100644
--- a/src/database/appservice.rs
+++ b/src/database/appservice.rs
@@ -27,6 +27,15 @@ impl Appservice {
         Ok(())
     }
 
+    /**
+     * Remove an appservice registration
+     * service_name is the name you send to register the service
+     */
+    pub fn unregister_appservice(&self, service_name: &str) -> Result<()> {
+        self.id_appserviceregistrations.remove(service_name.as_bytes())?;
+        Ok(())
+    }
+
     pub fn get_registration(&self, id: &str) -> Result<Option<serde_yaml::Value>> {
         self.cached_registrations
             .read()
diff --git a/src/database/rooms.rs b/src/database/rooms.rs
index fb9ecbf0..612bd51d 100644
--- a/src/database/rooms.rs
+++ b/src/database/rooms.rs
@@ -1528,6 +1528,15 @@ impl Rooms {
                                         ));
                                     }
                                 }
+                                "unregister_appservice" => {
+                                    if args.len() == 1 {
+                                        db.admin.send(AdminCommand::UnregisterAppservice(args[0].to_owned()));
+                                    } else {
+                                        db.admin.send(AdminCommand::SendMessage(
+                                            RoomMessageEventContent::text_plain("Missing appservice identifier"),
+                                        ));
+                                    }
+                                }
                                 "list_appservices" => {
                                     db.admin.send(AdminCommand::ListAppservices);
                                 }

From b6c9582cf4e9255e0610a63849bb3c5113be16e2 Mon Sep 17 00:00:00 2001
From: Torsten Flammiger <git@netfg.net>
Date: Wed, 22 Dec 2021 13:09:56 +0100
Subject: [PATCH 2/4] Fix doc style comment according to Rust; VSCode added
 line breaks

---
 src/database/appservice.rs | 12 +++++++-----
 src/database/rooms.rs      |  8 ++++++--
 2 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/src/database/appservice.rs b/src/database/appservice.rs
index caa48ad0..910964a4 100644
--- a/src/database/appservice.rs
+++ b/src/database/appservice.rs
@@ -27,12 +27,14 @@ impl Appservice {
         Ok(())
     }
 
-    /**
-     * Remove an appservice registration
-     * service_name is the name you send to register the service
-     */
+    /// Remove an appservice registration
+    /// 
+    /// # Arguments
+    /// 
+    /// * `service_name` - the name you send to register the service previously
     pub fn unregister_appservice(&self, service_name: &str) -> Result<()> {
-        self.id_appserviceregistrations.remove(service_name.as_bytes())?;
+        self.id_appserviceregistrations
+            .remove(service_name.as_bytes())?;
         Ok(())
     }
 
diff --git a/src/database/rooms.rs b/src/database/rooms.rs
index 612bd51d..775e2f8d 100644
--- a/src/database/rooms.rs
+++ b/src/database/rooms.rs
@@ -1530,10 +1530,14 @@ impl Rooms {
                                 }
                                 "unregister_appservice" => {
                                     if args.len() == 1 {
-                                        db.admin.send(AdminCommand::UnregisterAppservice(args[0].to_owned()));
+                                        db.admin.send(AdminCommand::UnregisterAppservice(
+                                            args[0].to_owned(),
+                                        ));
                                     } else {
                                         db.admin.send(AdminCommand::SendMessage(
-                                            RoomMessageEventContent::text_plain("Missing appservice identifier"),
+                                            RoomMessageEventContent::text_plain(
+                                                "Missing appservice identifier",
+                                            ),
                                         ));
                                     }
                                 }

From 7f2445be6ca7798ec25458e5447b23e7aeea1f7f Mon Sep 17 00:00:00 2001
From: Torsten Flammiger <git@netfg.net>
Date: Wed, 22 Dec 2021 16:48:27 +0100
Subject: [PATCH 3/4] On unregister_appservice(service_name), remove the
 appservice service_name from cache too

---
 src/database/appservice.rs | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/database/appservice.rs b/src/database/appservice.rs
index 910964a4..847d7479 100644
--- a/src/database/appservice.rs
+++ b/src/database/appservice.rs
@@ -35,6 +35,10 @@ impl Appservice {
     pub fn unregister_appservice(&self, service_name: &str) -> Result<()> {
         self.id_appserviceregistrations
             .remove(service_name.as_bytes())?;
+        self.cached_registrations.
+            write().
+            unwrap().
+            remove(service_name);
         Ok(())
     }
 

From eecd664c43c652f7fe4afc06154b346fc6a45b58 Mon Sep 17 00:00:00 2001
From: Torsten Flammiger <git@netfg.net>
Date: Thu, 13 Jan 2022 12:26:23 +0100
Subject: [PATCH 4/4] Reformat code

---
 src/database/appservice.rs | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/database/appservice.rs b/src/database/appservice.rs
index 847d7479..88de1f33 100644
--- a/src/database/appservice.rs
+++ b/src/database/appservice.rs
@@ -28,17 +28,17 @@ impl Appservice {
     }
 
     /// Remove an appservice registration
-    /// 
+    ///
     /// # Arguments
-    /// 
+    ///
     /// * `service_name` - the name you send to register the service previously
     pub fn unregister_appservice(&self, service_name: &str) -> Result<()> {
         self.id_appserviceregistrations
             .remove(service_name.as_bytes())?;
-        self.cached_registrations.
-            write().
-            unwrap().
-            remove(service_name);
+        self.cached_registrations
+            .write()
+            .unwrap()
+            .remove(service_name);
         Ok(())
     }