This commit is contained in:
Didier Link
2018-06-22 00:00:15 +02:00
35 changed files with 532 additions and 488 deletions
+3 -3
View File
@@ -6,7 +6,7 @@ use rocket::{
use rocket_contrib::Template;
use serde_json;
use activity_pub::{ActivityStream, ActivityPub, actor::Actor};
use activity_pub::ActivityStream;
use db_conn::DbConn;
use models::{
blog_authors::*,
@@ -32,9 +32,9 @@ fn details(name: String, conn: DbConn, user: Option<User>) -> Template {
}
#[get("/~/<name>", format = "application/activity+json", rank = 1)]
fn activity_details(name: String, conn: DbConn) -> ActivityPub {
fn activity_details(name: String, conn: DbConn) -> ActivityStream<CustomGroup> {
let blog = Blog::find_local(&*conn, name).unwrap();
blog.as_activity_pub(&*conn)
ActivityStream::new(blog.into_activity(&*conn))
}
#[get("/blogs/new")]
+25 -38
View File
@@ -1,41 +1,22 @@
use rocket::{
request::Form,
response::{Redirect, Flash}
response::Redirect
};
use rocket_contrib::Template;
use serde_json;
use activity_pub::{broadcast, inbox::Notify};
use activity_pub::{broadcast, inbox::Inbox};
use db_conn::DbConn;
use models::{
blogs::Blog,
comments::*,
instance::Instance,
posts::Post,
users::User
};
use utils;
use safe_string::SafeString;
#[get("/~/<blog>/<slug>/comment")]
fn new(blog: String, slug: String, user: User, conn: DbConn) -> Template {
may_fail!(Blog::find_by_fqn(&*conn, blog), "Couldn't find this blog", |blog| {
may_fail!(Post::find_by_slug(&*conn, slug, blog.id), "Couldn't find this post", |post| {
Template::render("comments/new", json!({
"post": post,
"account": user
}))
})
})
}
#[get("/~/<blog>/<slug>/comment", rank=2)]
fn new_auth(blog: String, slug: String) -> Flash<Redirect>{
utils::requires_login("You need to be logged in order to post a comment", uri!(new: blog = blog, slug = slug))
}
#[derive(FromForm)]
struct CommentQuery {
responding_to: Option<i32>
pub struct CommentQuery {
pub responding_to: Option<i32>
}
#[derive(FromForm)]
@@ -43,23 +24,29 @@ struct NewCommentForm {
pub content: String
}
// See: https://github.com/SergioBenitez/Rocket/pull/454
#[post("/~/<blog_name>/<slug>/comment", data = "<data>")]
fn create(blog_name: String, slug: String, data: Form<NewCommentForm>, user: User, conn: DbConn) -> Redirect {
create_response(blog_name, slug, None, data, user, conn)
}
#[post("/~/<blog_name>/<slug>/comment?<query>", data = "<data>")]
fn create(blog_name: String, slug: String, query: CommentQuery, data: Form<NewCommentForm>, user: User, conn: DbConn) -> Redirect {
fn create_response(blog_name: String, slug: String, query: Option<CommentQuery>, data: Form<NewCommentForm>, user: User, conn: DbConn) -> Redirect {
let blog = Blog::find_by_fqn(&*conn, blog_name.clone()).unwrap();
let post = Post::find_by_slug(&*conn, slug.clone(), blog.id).unwrap();
let form = data.get();
let comment = Comment::insert(&*conn, NewComment {
content: SafeString::new(&form.content.clone()),
in_response_to_id: query.responding_to,
post_id: post.id,
author_id: user.id,
ap_url: None, // TODO: set it
sensitive: false,
spoiler_text: "".to_string()
});
comment.notify(&*conn);
broadcast(&*conn, &user, comment.create_activity(&*conn), user.get_followers(&*conn));
let (new_comment, id) = NewComment::build()
.content(form.content.clone())
.in_response_to_id(query.and_then(|q| q.responding_to))
.post(post)
.author(user.clone())
.create(&*conn);
Redirect::to(format!("/~/{}/{}/#comment-{}", blog_name, slug, comment.id))
let instance = Instance::get_local(&*conn).unwrap();
instance.received(&*conn, serde_json::to_value(new_comment.clone()).expect("JSON serialization error"))
.expect("We are not compatible with ourselve: local broadcast failed (new comment)");
broadcast(&user, new_comment, user.get_followers(&*conn));
Redirect::to(format!("/~/{}/{}/#comment-{}", blog_name, slug, id))
}
+7 -2
View File
@@ -35,8 +35,13 @@ fn index(conn: DbConn, user: Option<User>) -> Template {
fn shared_inbox(conn: DbConn, data: String) -> String {
let act: serde_json::Value = serde_json::from_str(&data[..]).unwrap();
let instance = Instance::get_local(&*conn).unwrap();
instance.received(&*conn, act);
String::from("")
match instance.received(&*conn, act) {
Ok(_) => String::new(),
Err(e) => {
println!("Shared inbox error: {}\n{}", e.cause(), e.backtrace());
format!("Error: {}", e.cause())
}
}
}
#[get("/nodeinfo")]
+2 -2
View File
@@ -25,11 +25,11 @@ fn create(blog: String, slug: String, user: User, conn: DbConn) -> Redirect {
like.update_ap_url(&*conn);
like.notify(&*conn);
broadcast(&*conn, &user, like.into_activity(&*conn), user.get_followers(&*conn));
broadcast(&user, like.into_activity(&*conn), user.get_followers(&*conn));
} else {
let like = likes::Like::find_by_user_on_post(&*conn, user.id, post.id).unwrap();
let delete_act = like.delete(&*conn);
broadcast(&*conn, &user, delete_act, user.get_followers(&*conn));
broadcast(&user, delete_act, user.get_followers(&*conn));
}
Redirect::to(uri!(super::posts::details: blog = blog, slug = slug))
+17 -9
View File
@@ -1,10 +1,11 @@
use activitypub::object::Article;
use heck::KebabCase;
use rocket::request::Form;
use rocket::response::{Redirect, Flash};
use rocket_contrib::Template;
use serde_json;
use activity_pub::{broadcast, context, activity_pub, ActivityPub, Id};
use activity_pub::{broadcast, ActivityStream};
use db_conn::DbConn;
use models::{
blogs::*,
@@ -14,14 +15,21 @@ use models::{
posts::*,
users::User
};
use routes::comments::CommentQuery;
use safe_string::SafeString;
use utils;
// See: https://github.com/SergioBenitez/Rocket/pull/454
#[get("/~/<blog>/<slug>", rank = 4)]
fn details(blog: String, slug: String, conn: DbConn, user: Option<User>) -> Template {
details_response(blog, slug, conn, user, None)
}
#[get("/~/<blog>/<slug>?<query>")]
fn details_response(blog: String, slug: String, conn: DbConn, user: Option<User>, query: Option<CommentQuery>) -> Template {
may_fail!(Blog::find_by_fqn(&*conn, blog), "Couldn't find this blog", |blog| {
may_fail!(Post::find_by_slug(&*conn, slug, blog.id), "Couldn't find this post", |post| {
let comments = Comment::find_by_post(&*conn, post.id);
let comments = Comment::list_by_post(&*conn, post.id);
Template::render("posts/details", json!({
"author": post.get_authors(&*conn)[0].to_json(&*conn),
@@ -33,20 +41,20 @@ fn details(blog: String, slug: String, conn: DbConn, user: Option<User>) -> Temp
"n_reshares": post.get_reshares(&*conn).len(),
"has_reshared": user.clone().map(|u| u.has_reshared(&*conn, &post)).unwrap_or(false),
"account": user,
"date": &post.creation_date.timestamp()
"date": &post.creation_date.timestamp(),
"previous": query.and_then(|q| q.responding_to.map(|r| Comment::get(&*conn, r).expect("Error retrieving previous comment").to_json(&*conn))),
"user_fqn": user.map(|u| u.get_fqn(&*conn)).unwrap_or(String::new())
}))
})
})
}
#[get("/~/<blog>/<slug>", rank = 3, format = "application/activity+json")]
fn activity_details(blog: String, slug: String, conn: DbConn) -> ActivityPub {
fn activity_details(blog: String, slug: String, conn: DbConn) -> ActivityStream<Article> {
let blog = Blog::find_by_fqn(&*conn, blog).unwrap();
let post = Post::find_by_slug(&*conn, slug, blog.id).unwrap();
let mut act = serde_json::to_value(post.into_activity(&*conn)).unwrap();
act["@context"] = context();
activity_pub(act)
ActivityStream::new(post.into_activity(&*conn))
}
#[get("/~/<blog>/new", rank = 2)]
@@ -106,11 +114,11 @@ fn create(blog_name: String, data: Form<NewPostForm>, user: User, conn: DbConn)
});
for m in mentions.into_iter() {
Mention::from_activity(&*conn, Mention::build_activity(&*conn, m), Id::new(post.compute_id(&*conn)));
Mention::from_activity(&*conn, Mention::build_activity(&*conn, m), post.id, true);
}
let act = post.create_activity(&*conn);
broadcast(&*conn, &user, act, user.get_followers(&*conn));
broadcast(&user, act, user.get_followers(&*conn));
Redirect::to(uri!(details: blog = blog_name, slug = slug))
}
+2 -2
View File
@@ -25,11 +25,11 @@ fn create(blog: String, slug: String, user: User, conn: DbConn) -> Redirect {
reshare.update_ap_url(&*conn);
reshare.notify(&*conn);
broadcast(&*conn, &user, reshare.into_activity(&*conn), user.get_followers(&*conn));
broadcast(&user, reshare.into_activity(&*conn), user.get_followers(&*conn));
} else {
let reshare = Reshare::find_by_user_on_post(&*conn, user.id, post.id).unwrap();
let delete_act = reshare.delete(&*conn);
broadcast(&*conn, &user, delete_act, user.get_followers(&*conn));
broadcast(&user, delete_act, user.get_followers(&*conn));
}
Redirect::to(uri!(super::posts::details: blog = blog, slug = slug))
+20 -19
View File
@@ -9,9 +9,8 @@ use rocket_contrib::Template;
use serde_json;
use activity_pub::{
activity_pub, ActivityPub, ActivityStream, context, broadcast, Id, IntoId,
inbox::{Inbox, Notify},
actor::Actor
ActivityStream, broadcast, Id, IntoId,
inbox::{Inbox, Notify}
};
use db_conn::DbConn;
use models::{
@@ -82,7 +81,7 @@ fn follow(name: String, conn: DbConn, user: User) -> Redirect {
act.follow_props.set_object_object(user.into_activity(&*conn)).unwrap();
act.object_props.set_id_string(format!("{}/follow/{}", user.ap_url, target.ap_url)).unwrap();
broadcast(&*conn, &user, act, vec![target]);
broadcast(&user, act, vec![target]);
Redirect::to(uri!(details: name = name))
}
@@ -110,9 +109,9 @@ fn followers(name: String, conn: DbConn, account: Option<User>) -> Template {
}
#[get("/@/<name>", format = "application/activity+json", rank = 1)]
fn activity_details(name: String, conn: DbConn) -> ActivityPub {
fn activity_details(name: String, conn: DbConn) -> ActivityStream<CustomPerson> {
let user = User::find_local(&*conn, name).unwrap();
user.as_activity_pub(&*conn)
ActivityStream::new(user.into_activity(&*conn))
}
#[get("/users/new")]
@@ -199,21 +198,23 @@ fn outbox(name: String, conn: DbConn) -> ActivityStream<OrderedCollection> {
fn inbox(name: String, conn: DbConn, data: String) -> String {
let user = User::find_local(&*conn, name).unwrap();
let act: serde_json::Value = serde_json::from_str(&data[..]).unwrap();
user.received(&*conn, act);
String::from("")
match user.received(&*conn, act) {
Ok(_) => String::new(),
Err(e) => {
println!("User inbox error: {}\n{}", e.cause(), e.backtrace());
format!("Error: {}", e.cause())
}
}
}
#[get("/@/<name>/followers", format = "application/activity+json")]
fn ap_followers(name: String, conn: DbConn) -> ActivityPub {
fn ap_followers(name: String, conn: DbConn) -> ActivityStream<OrderedCollection> {
let user = User::find_local(&*conn, name).unwrap();
let followers = user.get_followers(&*conn).into_iter().map(|f| f.compute_id(&*conn)).collect::<Vec<String>>();
let json = json!({
"@context": context(),
"id": user.compute_box(&*conn, "followers"),
"type": "OrderedCollection",
"totalItems": followers.len(),
"orderedItems": followers
});
activity_pub(json)
let followers = user.get_followers(&*conn).into_iter().map(|f| Id::new(f.ap_url)).collect::<Vec<Id>>();
let mut coll = OrderedCollection::default();
coll.object_props.set_id_string(format!("{}/followers", user.ap_url)).expect("Follower collection: id error");
coll.collection_props.set_total_items_u64(followers.len() as u64).expect("Follower collection: totalItems error");
coll.collection_props.set_items_link_vec(followers).expect("Follower collection: items error");
ActivityStream::new(coll)
}