]> Untitled Git - lemmy.git/blob - server/src/apub/activities.rs
Merge branch 'dev' into federation
[lemmy.git] / server / src / apub / activities.rs
1 use crate::apub::{get_apub_protocol_string, get_following_instances};
2 use crate::db::community::Community;
3 use crate::db::post::Post;
4 use crate::db::user::User_;
5 use crate::db::Crud;
6 use activitystreams::activity::{Accept, Create, Follow, Update};
7 use activitystreams::object::properties::ObjectProperties;
8 use activitystreams::BaseBox;
9 use activitystreams::{context, public};
10 use diesel::PgConnection;
11 use failure::Error;
12 use failure::_core::fmt::Debug;
13 use isahc::prelude::*;
14 use serde::Serialize;
15
16 fn populate_object_props(
17   props: &mut ObjectProperties,
18   addressed_to: &str,
19   object_id: &str,
20 ) -> Result<(), Error> {
21   props
22     .set_context_xsd_any_uri(context())?
23     // TODO: the activity needs a seperate id from the object
24     .set_id(object_id)?
25     // TODO: should to/cc go on the Create, or on the Post? or on both?
26     // TODO: handle privacy on the receiving side (at least ignore anything thats not public)
27     .set_to_xsd_any_uri(public())?
28     .set_cc_xsd_any_uri(addressed_to)?;
29   Ok(())
30 }
31
32 fn send_activity<A>(activity: &A, to: Vec<String>) -> Result<(), Error>
33 where
34   A: Serialize + Debug,
35 {
36   let json = serde_json::to_string(&activity)?;
37   println!("sending data {}", json);
38   for t in to {
39     println!("to: {}", t);
40     let res = Request::post(t)
41       .header("Content-Type", "application/json")
42       .body(json.to_owned())?
43       .send()?;
44     dbg!(res);
45   }
46   Ok(())
47 }
48
49 fn get_followers(_community: &Community) -> Vec<String> {
50   // TODO: this is wrong, needs to go to the (non-local) followers of the community
51   get_following_instances()
52     .iter()
53     .map(|i| {
54       format!(
55         "{}://{}/federation/inbox",
56         get_apub_protocol_string(),
57         i.domain
58       )
59     })
60     .collect()
61 }
62
63 pub fn post_create(post: &Post, creator: &User_, conn: &PgConnection) -> Result<(), Error> {
64   let page = post.as_page(conn)?;
65   let community = Community::read(conn, post.community_id)?;
66   let mut create = Create::new();
67   populate_object_props(
68     &mut create.object_props,
69     &community.get_followers_url(),
70     &post.ap_id,
71   )?;
72   create
73     .create_props
74     .set_actor_xsd_any_uri(creator.actor_id.to_owned())?
75     .set_object_base_box(page)?;
76   send_activity(&create, get_followers(&community))?;
77   Ok(())
78 }
79
80 pub fn post_update(post: &Post, creator: &User_, conn: &PgConnection) -> Result<(), Error> {
81   let page = post.as_page(conn)?;
82   let community = Community::read(conn, post.community_id)?;
83   let mut update = Update::new();
84   populate_object_props(
85     &mut update.object_props,
86     &community.get_followers_url(),
87     &post.ap_id,
88   )?;
89   update
90     .update_props
91     .set_actor_xsd_any_uri(creator.actor_id.to_owned())?
92     .set_object_base_box(page)?;
93   send_activity(&update, get_followers(&community))?;
94   Ok(())
95 }
96
97 pub fn follow_community(
98   community: &Community,
99   user: &User_,
100   _conn: &PgConnection,
101 ) -> Result<(), Error> {
102   let mut follow = Follow::new();
103   follow
104     .object_props
105     .set_context_xsd_any_uri(context())?
106     // TODO: needs proper id
107     .set_id(user.actor_id.clone())?;
108   follow
109     .follow_props
110     .set_actor_xsd_any_uri(user.actor_id.clone())?
111     .set_object_xsd_any_uri(community.actor_id.clone())?;
112   let to = format!("{}/inbox", community.actor_id);
113   send_activity(&follow, vec![to])?;
114   Ok(())
115 }
116
117 pub fn accept_follow(follow: &Follow) -> Result<(), Error> {
118   let mut accept = Accept::new();
119   accept
120     .object_props
121     .set_context_xsd_any_uri(context())?
122     // TODO: needs proper id
123     .set_id(
124       follow
125         .follow_props
126         .get_actor_xsd_any_uri()
127         .unwrap()
128         .to_string(),
129     )?;
130   accept
131     .accept_props
132     .set_object_base_box(BaseBox::from_concrete(follow.clone())?)?;
133   let to = format!(
134     "{}/inbox",
135     follow
136       .follow_props
137       .get_actor_xsd_any_uri()
138       .unwrap()
139       .to_string()
140   );
141   send_activity(&accept, vec![to])?;
142   Ok(())
143 }