|
|
|
@ -15,22 +15,23 @@ use isahc::prelude::*;
|
|
|
|
|
use log::warn;
|
|
|
|
|
use serde::Deserialize;
|
|
|
|
|
use std::time::Duration;
|
|
|
|
|
use url::Url;
|
|
|
|
|
|
|
|
|
|
fn fetch_node_info(domain: &str) -> Result<NodeInfo, Error> {
|
|
|
|
|
let well_known_uri = format!(
|
|
|
|
|
let well_known_uri = Url::parse(&format!(
|
|
|
|
|
"{}://{}/.well-known/nodeinfo",
|
|
|
|
|
get_apub_protocol_string(),
|
|
|
|
|
domain
|
|
|
|
|
);
|
|
|
|
|
))?;
|
|
|
|
|
let well_known = fetch_remote_object::<NodeInfoWellKnown>(&well_known_uri)?;
|
|
|
|
|
Ok(fetch_remote_object::<NodeInfo>(&well_known.links.href)?)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn fetch_communities_from_instance(
|
|
|
|
|
community_list_url: &str,
|
|
|
|
|
community_list: &Url,
|
|
|
|
|
conn: &PgConnection,
|
|
|
|
|
) -> Result<Vec<Community>, Error> {
|
|
|
|
|
fetch_remote_object::<UnorderedCollection>(community_list_url)?
|
|
|
|
|
fetch_remote_object::<UnorderedCollection>(community_list)?
|
|
|
|
|
.collection_props
|
|
|
|
|
.get_many_items_base_boxes()
|
|
|
|
|
.unwrap()
|
|
|
|
@ -53,16 +54,16 @@ fn fetch_communities_from_instance(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: add an optional param last_updated and only fetch if its too old
|
|
|
|
|
pub fn fetch_remote_object<Response>(uri: &str) -> Result<Response, Error>
|
|
|
|
|
pub fn fetch_remote_object<Response>(url: &Url) -> Result<Response, Error>
|
|
|
|
|
where
|
|
|
|
|
Response: for<'de> Deserialize<'de>,
|
|
|
|
|
{
|
|
|
|
|
if Settings::get().federation.tls_enabled && !uri.starts_with("https://") {
|
|
|
|
|
return Err(format_err!("Activitypub uri is insecure: {}", uri));
|
|
|
|
|
if Settings::get().federation.tls_enabled && url.scheme() != "https" {
|
|
|
|
|
return Err(format_err!("Activitypub uri is insecure: {}", url));
|
|
|
|
|
}
|
|
|
|
|
// TODO: this function should return a future
|
|
|
|
|
let timeout = Duration::from_secs(60);
|
|
|
|
|
let text = Request::get(uri)
|
|
|
|
|
let text = Request::get(url.as_str())
|
|
|
|
|
.header("Accept", APUB_JSON_CONTENT_TYPE)
|
|
|
|
|
.connect_timeout(timeout)
|
|
|
|
|
.timeout(timeout)
|
|
|
|
@ -78,11 +79,14 @@ fn fetch_remote_community_posts(
|
|
|
|
|
community: &Community,
|
|
|
|
|
conn: &PgConnection,
|
|
|
|
|
) -> Result<Vec<Post>, Error> {
|
|
|
|
|
let endpoint = format!("http://{}/federation/c/{}", instance, community.name);
|
|
|
|
|
let endpoint = Url::parse(&format!(
|
|
|
|
|
"http://{}/federation/c/{}",
|
|
|
|
|
instance, community.name
|
|
|
|
|
))?;
|
|
|
|
|
let group = fetch_remote_object::<GroupExt>(&endpoint)?;
|
|
|
|
|
let outbox_uri = &group.extension.get_outbox().to_string();
|
|
|
|
|
let outbox_uri = Url::parse(&group.extension.get_outbox().to_string())?;
|
|
|
|
|
// TODO: outbox url etc should be stored in local db
|
|
|
|
|
let outbox = fetch_remote_object::<OrderedCollection>(outbox_uri)?;
|
|
|
|
|
let outbox = fetch_remote_object::<OrderedCollection>(&outbox_uri)?;
|
|
|
|
|
let items = outbox.collection_props.get_many_items_base_boxes();
|
|
|
|
|
|
|
|
|
|
Ok(
|
|
|
|
@ -106,7 +110,7 @@ fn fetch_remote_community_posts(
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn fetch_remote_user(apub_id: &str, conn: &PgConnection) -> Result<User_, Error> {
|
|
|
|
|
pub fn fetch_remote_user(apub_id: &Url, conn: &PgConnection) -> Result<User_, Error> {
|
|
|
|
|
let person = fetch_remote_object::<PersonExt>(apub_id)?;
|
|
|
|
|
let uf = UserForm::from_person(&person)?;
|
|
|
|
|
let existing = User_::read_from_apub_id(conn, &uf.actor_id);
|
|
|
|
@ -122,8 +126,8 @@ pub fn fetch_remote_user(apub_id: &str, conn: &PgConnection) -> Result<User_, Er
|
|
|
|
|
pub fn fetch_all(conn: &PgConnection) -> Result<(), Error> {
|
|
|
|
|
for instance in &get_following_instances() {
|
|
|
|
|
let node_info = fetch_node_info(instance)?;
|
|
|
|
|
if let Some(community_list_url) = node_info.metadata.community_list_url {
|
|
|
|
|
let communities = fetch_communities_from_instance(&community_list_url, conn)?;
|
|
|
|
|
if let Some(community_list) = node_info.metadata.community_list_url {
|
|
|
|
|
let communities = fetch_communities_from_instance(&community_list, conn)?;
|
|
|
|
|
for c in communities {
|
|
|
|
|
fetch_remote_community_posts(instance, &c, conn)?;
|
|
|
|
|
}
|
|
|
|
|