From 63eb1a7e9810208199781b2f3b05fe597861e652 Mon Sep 17 00:00:00 2001 From: Bat Date: Sat, 19 May 2018 10:51:10 +0100 Subject: [PATCH] Add a route to reshare posts --- src/main.rs | 2 ++ src/models/reshares.rs | 66 +++++++++++++++++++++++++++++++++++++----- src/models/users.rs | 11 +++++++ src/routes/mod.rs | 1 + src/routes/reshares.rs | 31 ++++++++++++++++++++ 5 files changed, 103 insertions(+), 8 deletions(-) create mode 100644 src/routes/reshares.rs diff --git a/src/main.rs b/src/main.rs index cbd27b47..9663b379 100644 --- a/src/main.rs +++ b/src/main.rs @@ -90,6 +90,8 @@ fn main() { routes::posts::new_auth, routes::posts::create, + routes::reshares::create, + routes::session::new, routes::session::create, routes::session::delete, diff --git a/src/models/reshares.rs b/src/models/reshares.rs index 0ad8f464..8d50ff5b 100644 --- a/src/models/reshares.rs +++ b/src/models/reshares.rs @@ -1,23 +1,26 @@ +use activitystreams_types::activity; use chrono::NaiveDateTime; use diesel::{self, PgConnection, QueryDsl, RunQueryDsl, ExpressionMethods}; +use activity_pub::{IntoId, actor::Actor, object::Object}; +use models::{posts::Post, users::User}; use schema::reshares; #[derive(Serialize, Deserialize, Queryable, Identifiable)] pub struct Reshare { - id: i32, - user_id: i32, - post_id: i32, - ap_url: String, - creation_date: NaiveDateTime + pub id: i32, + pub user_id: i32, + pub post_id: i32, + pub ap_url: String, + pub creation_date: NaiveDateTime } #[derive(Insertable)] #[table_name = "reshares"] pub struct NewReshare { - user_id: i32, - post_id: i32, - ap_url: String + pub user_id: i32, + pub post_id: i32, + pub ap_url: String } impl Reshare { @@ -35,4 +38,51 @@ impl Reshare { .expect("Could'nt load reshare") .into_iter().nth(0) } + + pub fn update_ap_url(&self, conn: &PgConnection) { + if self.ap_url.len() == 0 { + diesel::update(self) + .set(reshares::ap_url.eq(format!( + "{}/reshare/{}", + User::get(conn, self.user_id).unwrap().compute_id(conn), + Post::get(conn, self.post_id).unwrap().compute_id(conn) + ))) + .get_result::(conn).expect("Couldn't update AP URL"); + } + } + + pub fn find_by_ap_url(conn: &PgConnection, ap_url: String) -> Option { + reshares::table.filter(reshares::ap_url.eq(ap_url)) + .limit(1) + .load::(conn) + .expect("Error loading reshare by AP URL") + .into_iter().nth(0) + } + + pub fn find_by_user_on_post(conn: &PgConnection, user: &User, post: &Post) -> Option { + reshares::table.filter(reshares::post_id.eq(post.id)) + .filter(reshares::user_id.eq(user.id)) + .limit(1) + .load::(conn) + .expect("Error loading reshare for user and post") + .into_iter().nth(0) + } + + pub fn delete(&self, conn: &PgConnection) -> activity::Undo { + diesel::delete(self).execute(conn).unwrap(); + + let mut act = activity::Undo::default(); + act.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).unwrap(); + act.set_object_object(self.into_activity(conn)).unwrap(); + act + } + + pub fn into_activity(&self, conn: &PgConnection) -> activity::Announce { + let mut act = activity::Announce::default(); + act.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).unwrap(); + act.set_object_link(Post::get(conn, self.post_id).unwrap().into_id()).unwrap(); + act.object_props.set_id_string(self.ap_url.clone()).unwrap(); + + act + } } diff --git a/src/models/users.rs b/src/models/users.rs index 92b85715..3a38de9c 100644 --- a/src/models/users.rs +++ b/src/models/users.rs @@ -287,6 +287,17 @@ impl User { .len() > 0 } + pub fn has_reshared(&self, conn: &PgConnection, post: &Post) -> bool { + use schema::reshares; + use models::reshares::Reshare; + reshares::table + .filter(reshares::post_id.eq(post.id)) + .filter(reshares::user_id.eq(self.id)) + .load::(conn) + .expect("Couldn't load reshares") + .len() > 0 + } + pub fn get_keypair(&self) -> PKey { PKey::from_rsa(Rsa::private_key_from_pem(self.private_key.clone().unwrap().as_ref()).unwrap()).unwrap() } diff --git a/src/routes/mod.rs b/src/routes/mod.rs index 60946b8a..501c774c 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -7,6 +7,7 @@ pub mod instance; pub mod likes; pub mod notifications; pub mod posts; +pub mod reshares; pub mod session; pub mod user; pub mod well_known; diff --git a/src/routes/reshares.rs b/src/routes/reshares.rs new file mode 100644 index 00000000..7cf74d9d --- /dev/null +++ b/src/routes/reshares.rs @@ -0,0 +1,31 @@ +use rocket::response::Redirect; + +use activity_pub::broadcast; +use db_conn::DbConn; +use models::{ + posts::Post, + reshares::*, + users::User +}; + +#[get("/~///reshare")] +fn create(blog: String, slug: String, user: User, conn: DbConn) -> Redirect { + let post = Post::find_by_slug(&*conn, slug.clone()).unwrap(); + + if !user.has_reshared(&*conn, &post) { + let reshare = Reshare::insert(&*conn, NewReshare { + post_id: post.id, + user_id: user.id, + ap_url: "".to_string() + }); + reshare.update_ap_url(&*conn); + + broadcast(&*conn, &user, reshare.into_activity(&*conn), user.get_followers(&*conn)); + } else { + let reshare = Reshare::find_by_user_on_post(&*conn, &user, &post).unwrap(); + let delete_act = reshare.delete(&*conn); + broadcast(&*conn, &user, delete_act, user.get_followers(&*conn)); + } + + Redirect::to(format!("/~/{}/{}/", blog, slug).as_ref()) +}