mirror of
https://git.joinplu.me/Plume/Plume.git
synced 2024-12-23 18:40:34 +00:00
Followers listing
And clean up models functions a bit
This commit is contained in:
parent
601fe7cf4f
commit
c6b2560eb0
12 changed files with 84 additions and 20 deletions
|
@ -30,7 +30,7 @@ pub trait Inbox: Actor + Sized {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
"Note" => {
|
"Note" => {
|
||||||
let previous_comment = Comment::get_by_ap_url(conn, act["object"]["inReplyTo"].as_str().unwrap().to_string());
|
let previous_comment = Comment::find_by_ap_url(conn, act["object"]["inReplyTo"].as_str().unwrap().to_string());
|
||||||
Comment::insert(conn, NewComment {
|
Comment::insert(conn, NewComment {
|
||||||
content: act["object"]["content"].as_str().unwrap().to_string(),
|
content: act["object"]["content"].as_str().unwrap().to_string(),
|
||||||
spoiler_text: act["object"]["summary"].as_str().unwrap_or("").to_string(),
|
spoiler_text: act["object"]["summary"].as_str().unwrap_or("").to_string(),
|
||||||
|
@ -38,7 +38,7 @@ pub trait Inbox: Actor + Sized {
|
||||||
in_response_to_id: previous_comment.clone().map(|c| c.id),
|
in_response_to_id: previous_comment.clone().map(|c| c.id),
|
||||||
post_id: previous_comment
|
post_id: previous_comment
|
||||||
.map(|c| c.post_id)
|
.map(|c| c.post_id)
|
||||||
.unwrap_or_else(|| Post::get_by_ap_url(conn, act["object"]["inReplyTo"].as_str().unwrap().to_string()).unwrap().id),
|
.unwrap_or_else(|| Post::find_by_ap_url(conn, act["object"]["inReplyTo"].as_str().unwrap().to_string()).unwrap().id),
|
||||||
author_id: User::from_url(conn, act["actor"].as_str().unwrap().to_string()).unwrap().id,
|
author_id: User::from_url(conn, act["actor"].as_str().unwrap().to_string()).unwrap().id,
|
||||||
sensitive: act["object"]["sensitive"].as_bool().unwrap_or(false)
|
sensitive: act["object"]["sensitive"].as_bool().unwrap_or(false)
|
||||||
});
|
});
|
||||||
|
@ -61,7 +61,7 @@ pub trait Inbox: Actor + Sized {
|
||||||
}
|
}
|
||||||
"Like" => {
|
"Like" => {
|
||||||
let liker = User::from_url(conn, act["actor"].as_str().unwrap().to_string());
|
let liker = User::from_url(conn, act["actor"].as_str().unwrap().to_string());
|
||||||
let post = Post::get_by_ap_url(conn, act["object"].as_str().unwrap().to_string());
|
let post = Post::find_by_ap_url(conn, act["object"].as_str().unwrap().to_string());
|
||||||
Like::insert(conn, NewLike {
|
Like::insert(conn, NewLike {
|
||||||
post_id: post.unwrap().id,
|
post_id: post.unwrap().id,
|
||||||
user_id: liker.unwrap().id,
|
user_id: liker.unwrap().id,
|
||||||
|
|
|
@ -69,13 +69,14 @@ fn main() {
|
||||||
|
|
||||||
routes::user::me,
|
routes::user::me,
|
||||||
routes::user::details,
|
routes::user::details,
|
||||||
|
routes::user::followers,
|
||||||
routes::user::edit,
|
routes::user::edit,
|
||||||
routes::user::update,
|
routes::user::update,
|
||||||
routes::user::follow,
|
routes::user::follow,
|
||||||
routes::user::activity_details,
|
routes::user::activity_details,
|
||||||
routes::user::outbox,
|
routes::user::outbox,
|
||||||
routes::user::inbox,
|
routes::user::inbox,
|
||||||
routes::user::followers,
|
routes::user::ap_followers,
|
||||||
routes::user::new,
|
routes::user::new,
|
||||||
routes::user::create,
|
routes::user::create,
|
||||||
|
|
||||||
|
|
|
@ -50,13 +50,13 @@ impl Comment {
|
||||||
.into_iter().nth(0)
|
.into_iter().nth(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn for_post(conn: &PgConnection, post_id: i32) -> Vec<Comment> {
|
pub fn find_by_post(conn: &PgConnection, post_id: i32) -> Vec<Comment> {
|
||||||
comments::table.filter(comments::post_id.eq(post_id))
|
comments::table.filter(comments::post_id.eq(post_id))
|
||||||
.load::<Comment>(conn)
|
.load::<Comment>(conn)
|
||||||
.expect("Error loading comment by post id")
|
.expect("Error loading comment by post id")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_by_ap_url(conn: &PgConnection, ap_url: String) -> Option<Comment> {
|
pub fn find_by_ap_url(conn: &PgConnection, ap_url: String) -> Option<Comment> {
|
||||||
comments::table.filter(comments::ap_url.eq(ap_url))
|
comments::table.filter(comments::ap_url.eq(ap_url))
|
||||||
.limit(1)
|
.limit(1)
|
||||||
.load::<Comment>(conn)
|
.load::<Comment>(conn)
|
||||||
|
|
|
@ -61,7 +61,7 @@ impl Instance {
|
||||||
.into_iter().nth(0)
|
.into_iter().nth(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_by_domain(conn: &PgConnection, domain: String) -> Option<Instance> {
|
pub fn find_by_domain(conn: &PgConnection, domain: String) -> Option<Instance> {
|
||||||
instances::table.filter(instances::public_domain.eq(domain))
|
instances::table.filter(instances::public_domain.eq(domain))
|
||||||
.limit(1)
|
.limit(1)
|
||||||
.load::<Instance>(conn)
|
.load::<Instance>(conn)
|
||||||
|
@ -69,7 +69,9 @@ impl Instance {
|
||||||
.into_iter().nth(0)
|
.into_iter().nth(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn block(&self) {}
|
pub fn block(&self) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn has_admin(&self, conn: &PgConnection) -> bool {
|
pub fn has_admin(&self, conn: &PgConnection) -> bool {
|
||||||
users::table.filter(users::instance_id.eq(self.id))
|
users::table.filter(users::instance_id.eq(self.id))
|
||||||
|
|
|
@ -57,7 +57,7 @@ impl Like {
|
||||||
.into_iter().nth(0)
|
.into_iter().nth(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn for_user_on_post(conn: &PgConnection, user: &User, post: &Post) -> Option<Like> {
|
pub fn find_by_user_on_post(conn: &PgConnection, user: &User, post: &Post) -> Option<Like> {
|
||||||
likes::table.filter(likes::post_id.eq(post.id))
|
likes::table.filter(likes::post_id.eq(post.id))
|
||||||
.filter(likes::user_id.eq(user.id))
|
.filter(likes::user_id.eq(user.id))
|
||||||
.limit(1)
|
.limit(1)
|
||||||
|
|
|
@ -62,7 +62,7 @@ impl Post {
|
||||||
.into_iter().nth(0)
|
.into_iter().nth(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_by_ap_url(conn: &PgConnection, ap_url: String) -> Option<Post> {
|
pub fn find_by_ap_url(conn: &PgConnection, ap_url: String) -> Option<Post> {
|
||||||
posts::table.filter(posts::ap_url.eq(ap_url))
|
posts::table.filter(posts::ap_url.eq(ap_url))
|
||||||
.limit(1)
|
.limit(1)
|
||||||
.load::<Post>(conn)
|
.load::<Post>(conn)
|
||||||
|
|
|
@ -67,7 +67,12 @@ pub struct NewUser {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl User {
|
impl User {
|
||||||
pub fn grant_admin_rights() {}
|
pub fn grant_admin_rights(&self, conn: &PgConnection) {
|
||||||
|
diesel::update(self)
|
||||||
|
.set(users::is_admin.eq(true))
|
||||||
|
.load::<User>(conn)
|
||||||
|
.expect("Couldn't grant admin rights");
|
||||||
|
}
|
||||||
|
|
||||||
pub fn insert(conn: &PgConnection, new: NewUser) -> User {
|
pub fn insert(conn: &PgConnection, new: NewUser) -> User {
|
||||||
diesel::insert_into(users::table)
|
diesel::insert_into(users::table)
|
||||||
|
@ -118,7 +123,7 @@ impl User {
|
||||||
|
|
||||||
pub fn find_by_fqn(conn: &PgConnection, fqn: String) -> Option<User> {
|
pub fn find_by_fqn(conn: &PgConnection, fqn: String) -> Option<User> {
|
||||||
if fqn.contains("@") { // remote user
|
if fqn.contains("@") { // remote user
|
||||||
match Instance::get_by_domain(conn, String::from(fqn.split("@").last().unwrap())) {
|
match Instance::find_by_domain(conn, String::from(fqn.split("@").last().unwrap())) {
|
||||||
Some(instance) => {
|
Some(instance) => {
|
||||||
match User::find_by_name(conn, String::from(fqn.split("@").nth(0).unwrap()), instance.id) {
|
match User::find_by_name(conn, String::from(fqn.split("@").nth(0).unwrap()), instance.id) {
|
||||||
Some(u) => Some(u),
|
Some(u) => Some(u),
|
||||||
|
@ -157,7 +162,7 @@ impl User {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_activity(conn: &PgConnection, acct: serde_json::Value, inst: String) -> User {
|
fn from_activity(conn: &PgConnection, acct: serde_json::Value, inst: String) -> User {
|
||||||
let instance = match Instance::get_by_domain(conn, inst.clone()) {
|
let instance = match Instance::find_by_domain(conn, inst.clone()) {
|
||||||
Some(instance) => instance,
|
Some(instance) => instance,
|
||||||
None => {
|
None => {
|
||||||
Instance::insert(conn, inst.clone(), inst.clone(), false)
|
Instance::insert(conn, inst.clone(), inst.clone(), false)
|
||||||
|
@ -219,6 +224,10 @@ impl User {
|
||||||
posts.into_iter().map(|p| Arc::new(Create::new(self, &p, conn)) as Arc<Activity>).collect::<Vec<Arc<Activity>>>()
|
posts.into_iter().map(|p| Arc::new(Create::new(self, &p, conn)) as Arc<Activity>).collect::<Vec<Arc<Activity>>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_fqn(&self, conn: &PgConnection) -> String {
|
||||||
|
format!("{}@{}", self.username, self.get_instance(conn).public_domain)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_followers(&self, conn: &PgConnection) -> Vec<User> {
|
pub fn get_followers(&self, conn: &PgConnection) -> Vec<User> {
|
||||||
use schema::follows;
|
use schema::follows;
|
||||||
let follows = Follow::belonging_to(self).select(follows::follower_id);
|
let follows = Follow::belonging_to(self).select(follows::follower_id);
|
||||||
|
|
|
@ -21,7 +21,7 @@ fn create(blog: String, slug: String, user: User, conn: DbConn) -> Redirect {
|
||||||
let act = Like::new(&user, &post, &*conn);
|
let act = Like::new(&user, &post, &*conn);
|
||||||
broadcast(&*conn, &user, act, user.get_followers(&*conn));
|
broadcast(&*conn, &user, act, user.get_followers(&*conn));
|
||||||
} else {
|
} else {
|
||||||
let like = likes::Like::for_user_on_post(&*conn, &user, &post).unwrap();
|
let like = likes::Like::find_by_user_on_post(&*conn, &user, &post).unwrap();
|
||||||
like.delete(&*conn);
|
like.delete(&*conn);
|
||||||
broadcast(&*conn, &user, Undo::new(&user, &like, &*conn), user.get_followers(&*conn));
|
broadcast(&*conn, &user, Undo::new(&user, &like, &*conn), user.get_followers(&*conn));
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ use utils;
|
||||||
fn details(blog: String, slug: String, conn: DbConn, user: Option<User>) -> Template {
|
fn details(blog: String, slug: String, conn: DbConn, user: Option<User>) -> Template {
|
||||||
let blog = Blog::find_by_actor_id(&*conn, blog).unwrap();
|
let blog = Blog::find_by_actor_id(&*conn, blog).unwrap();
|
||||||
let post = Post::find_by_slug(&*conn, slug).unwrap();
|
let post = Post::find_by_slug(&*conn, slug).unwrap();
|
||||||
let comments = Comment::for_post(&*conn, post.id);
|
let comments = Comment::find_by_post(&*conn, post.id);
|
||||||
Template::render("posts/details", json!({
|
Template::render("posts/details", json!({
|
||||||
"post": post,
|
"post": post,
|
||||||
"blog": blog,
|
"blog": blog,
|
||||||
|
|
|
@ -23,6 +23,7 @@ fn details(name: String, conn: DbConn, account: Option<User>) -> Template {
|
||||||
let user = User::find_by_fqn(&*conn, name).unwrap();
|
let user = User::find_by_fqn(&*conn, name).unwrap();
|
||||||
let recents = Post::get_recents_for_author(&*conn, &user, 5);
|
let recents = Post::get_recents_for_author(&*conn, &user, 5);
|
||||||
let user_id = user.id.clone();
|
let user_id = user.id.clone();
|
||||||
|
let n_followers = user.get_followers(&*conn).len();
|
||||||
|
|
||||||
Template::render("users/details", json!({
|
Template::render("users/details", json!({
|
||||||
"user": serde_json::to_value(user).unwrap(),
|
"user": serde_json::to_value(user).unwrap(),
|
||||||
|
@ -35,7 +36,8 @@ fn details(name: String, conn: DbConn, account: Option<User>) -> Template {
|
||||||
"date": p.creation_date.timestamp()
|
"date": p.creation_date.timestamp()
|
||||||
})
|
})
|
||||||
}).collect::<Vec<serde_json::Value>>(),
|
}).collect::<Vec<serde_json::Value>>(),
|
||||||
"is_self": account.map(|a| a.id == user_id).unwrap_or(false)
|
"is_self": account.map(|a| a.id == user_id).unwrap_or(false),
|
||||||
|
"n_followers": n_followers
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +52,24 @@ fn follow(name: String, conn: DbConn, user: User) -> Redirect {
|
||||||
Redirect::to(format!("/@/{}", name).as_ref())
|
Redirect::to(format!("/@/{}", name).as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("/@/<name>/followers", rank = 2)]
|
||||||
|
fn followers(name: String, conn: DbConn, account: Option<User>) -> Template {
|
||||||
|
let user = User::find_by_fqn(&*conn, name.clone()).unwrap();
|
||||||
|
let user_id = user.id.clone();
|
||||||
|
|
||||||
|
Template::render("users/followers", json!({
|
||||||
|
"user": serde_json::to_value(user.clone()).unwrap(),
|
||||||
|
"followers": user.get_followers(&*conn).into_iter().map(|f| {
|
||||||
|
let fqn = f.get_fqn(&*conn);
|
||||||
|
let mut json = serde_json::to_value(f).unwrap();
|
||||||
|
json["fqn"] = serde_json::Value::String(fqn);
|
||||||
|
json
|
||||||
|
}).collect::<Vec<serde_json::Value>>(),
|
||||||
|
"account": account,
|
||||||
|
"is_self": account.map(|a| a.id == user_id).unwrap_or(false)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
#[get("/@/<name>", format = "application/activity+json", rank = 1)]
|
#[get("/@/<name>", format = "application/activity+json", rank = 1)]
|
||||||
fn activity_details(name: String, conn: DbConn) -> ActivityPub {
|
fn activity_details(name: String, conn: DbConn) -> ActivityPub {
|
||||||
let user = User::find_local(&*conn, name).unwrap();
|
let user = User::find_local(&*conn, name).unwrap();
|
||||||
|
@ -133,8 +153,8 @@ fn inbox(name: String, conn: DbConn, data: String) -> String {
|
||||||
String::from("")
|
String::from("")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/@/<name>/followers")]
|
#[get("/@/<name>/followers", format = "application/activity+json")]
|
||||||
fn followers(name: String, conn: DbConn) -> ActivityPub {
|
fn ap_followers(name: String, conn: DbConn) -> ActivityPub {
|
||||||
let user = User::find_local(&*conn, name).unwrap();
|
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 followers = user.get_followers(&*conn).into_iter().map(|f| f.compute_id(&*conn)).collect::<Vec<String>>();
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,10 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<a href="followers">{{ n_followers }} follower{{ n_followers | pluralize }}</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{{ user.summary | safe }}
|
{{ user.summary | safe }}
|
||||||
</div>
|
</div>
|
||||||
|
|
28
templates/users/followers.tera
Normal file
28
templates/users/followers.tera
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
{% extends "base" %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
{{ user.display_name }}'s Followers
|
||||||
|
{% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div>
|
||||||
|
<h1>
|
||||||
|
{{ user.display_name }}
|
||||||
|
{% if user.is_admin %}
|
||||||
|
<span class="badge">Admin</span>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if is_self %}
|
||||||
|
<span class="badge">It is you</span>
|
||||||
|
{% endif %}
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Followers</h2>
|
||||||
|
{% for follower in followers %}
|
||||||
|
<div>
|
||||||
|
<h3><a href="{{ follower.ap_url }}">{{ follower.display_name }}</a> — @{{ follower.fqn }}</h3>
|
||||||
|
<p>{{ follower.summary }}</p>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endblock content %}
|
Loading…
Reference in a new issue