From c6888472dcc0b54d778af2fde015e5d126eae7bf Mon Sep 17 00:00:00 2001
From: Dessalines <dessalines@users.noreply.github.com>
Date: Thu, 24 Sep 2020 09:46:57 -0400
Subject: [PATCH] Add linked instances. (#1149)

* Adding linked instances. Fixes #1147

* Removing current instance, checking for federation enabled.

* Cleaning up.

* Switching to iterator.
---
 lemmy_db/src/community.rs |  5 +++++
 src/api/mod.rs            | 32 +++++++++++++++++++++++++++++++-
 src/api/site.rs           |  6 +++---
 tests/integration_test.rs |  1 +
 4 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/lemmy_db/src/community.rs b/lemmy_db/src/community.rs
index 25cb272a..24cf7e32 100644
--- a/lemmy_db/src/community.rs
+++ b/lemmy_db/src/community.rs
@@ -154,6 +154,11 @@ impl Community {
     Ok(mods_and_admins)
   }
 
+  pub fn distinct_federated_communities(conn: &PgConnection) -> Result<Vec<String>, Error> {
+    use crate::schema::community::dsl::*;
+    community.select(actor_id).distinct().load::<String>(conn)
+  }
+
   pub fn is_mod_or_admin(conn: &PgConnection, user_id: i32, community_id: i32) -> bool {
     Self::community_mods_and_admins(conn, community_id)
       .unwrap_or_default()
diff --git a/src/api/mod.rs b/src/api/mod.rs
index d63f38eb..785bd601 100644
--- a/src/api/mod.rs
+++ b/src/api/mod.rs
@@ -8,7 +8,8 @@ use lemmy_db::{
   Crud,
 };
 use lemmy_structs::blocking;
-use lemmy_utils::{APIError, ConnectionId, LemmyError};
+use lemmy_utils::{settings::Settings, APIError, ConnectionId, LemmyError};
+use url::Url;
 
 pub mod claims;
 pub mod comment;
@@ -96,3 +97,32 @@ pub(in crate::api) async fn check_community_ban(
     Ok(())
   }
 }
+
+pub(in crate::api) async fn linked_instances(pool: &DbPool) -> Result<Vec<String>, LemmyError> {
+  let mut instances: Vec<String> = Vec::new();
+
+  if Settings::get().federation.enabled {
+    let distinct_communities = blocking(pool, move |conn| {
+      Community::distinct_federated_communities(conn)
+    })
+    .await??;
+
+    instances = distinct_communities
+      .iter()
+      .map(|actor_id| Ok(Url::parse(actor_id)?.host_str().unwrap_or("").to_string()))
+      .collect::<Result<Vec<String>, LemmyError>>()?;
+
+    instances.append(&mut Settings::get().get_allowed_instances());
+    instances.retain(|a| {
+      !Settings::get().get_blocked_instances().contains(a)
+        && !a.eq("")
+        && !a.eq(&Settings::get().hostname)
+    });
+
+    // Sort and remove dupes
+    instances.sort_unstable();
+    instances.dedup();
+  }
+
+  Ok(instances)
+}
diff --git a/src/api/site.rs b/src/api/site.rs
index 3ff1e49d..e9a0d659 100644
--- a/src/api/site.rs
+++ b/src/api/site.rs
@@ -1,5 +1,5 @@
 use crate::{
-  api::{get_user_from_jwt, get_user_from_jwt_opt, is_admin, Perform},
+  api::{get_user_from_jwt, get_user_from_jwt_opt, is_admin, linked_instances, Perform},
   apub::fetcher::search_by_apub_id,
   version,
   LemmyContext,
@@ -314,7 +314,7 @@ impl Perform for GetSite {
       online,
       version: version::VERSION.to_string(),
       my_user,
-      federated_instances: Settings::get().get_allowed_instances(),
+      federated_instances: linked_instances(context.pool()).await?,
     })
   }
 }
@@ -543,7 +543,7 @@ impl Perform for TransferSite {
       online: 0,
       version: version::VERSION.to_string(),
       my_user: Some(user),
-      federated_instances: Settings::get().get_allowed_instances(),
+      federated_instances: linked_instances(context.pool()).await?,
     })
   }
 }
diff --git a/tests/integration_test.rs b/tests/integration_test.rs
index 4f280f62..4edaefac 100644
--- a/tests/integration_test.rs
+++ b/tests/integration_test.rs
@@ -86,6 +86,7 @@ fn create_user(conn: &PgConnection, name: &str) -> User_ {
     admin: false,
     banned: false,
     updated: None,
+    published: None,
     show_nsfw: false,
     theme: "darkly".into(),
     default_sort_type: SortType::Hot as i16,
-- 
2.44.1