forked from alemi/upub
fix: use new apb fields
This commit is contained in:
parent
a499c93e99
commit
bcd8f27933
5 changed files with 69 additions and 141 deletions
|
@ -34,7 +34,7 @@ sea-orm = { version = "0.12", features = ["macros", "sqlx-sqlite", "runtime-toki
|
|||
reqwest = { version = "0.12", features = ["json"] }
|
||||
axum = "0.7"
|
||||
tower-http = { version = "0.5", features = ["cors", "trace"] }
|
||||
apb = { path = "apb", features = ["unstructured", "orm"] }
|
||||
apb = { path = "apb", features = ["unstructured", "orm", "activitypub-fe", "activitypub-counters"] }
|
||||
# nodeinfo = "0.0.2" # the version on crates.io doesn't re-export necessary types to build the struct!!!
|
||||
nodeinfo = { git = "https://codeberg.org/thefederationinfo/nodeinfo-rs", rev = "e865094804" }
|
||||
# migrations
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use apb::{ActivityMut, CollectionMut, ObjectMut};
|
||||
use apb::{ActivityMut, ObjectMut};
|
||||
use sea_orm::{entity::prelude::*, sea_query::IntoCondition, Condition, FromQueryResult, Iterable, Order, QueryOrder, QuerySelect, SelectColumns};
|
||||
|
||||
use crate::routes::activitypub::jsonld::LD;
|
||||
|
@ -98,36 +98,18 @@ impl Event {
|
|||
match self {
|
||||
Event::Activity(x) => x.ap(),
|
||||
Event::DeepActivity { activity, object, liked } =>
|
||||
activity.ap().set_object(apb::Node::object({
|
||||
let likes = object.likes;
|
||||
let mut obj = object.ap()
|
||||
.set_attachment(attachment);
|
||||
if let Some(liked) = liked {
|
||||
obj = obj.set_audience(apb::Node::object( // TODO setting this again ewww...
|
||||
serde_json::Value::new_object()
|
||||
.set_collection_type(Some(apb::CollectionType::OrderedCollection))
|
||||
.set_total_items(Some(likes as u64))
|
||||
.set_ordered_items(apb::Node::links(vec![liked]))
|
||||
));
|
||||
}
|
||||
obj
|
||||
})),
|
||||
activity.ap().set_object(apb::Node::object(
|
||||
object.ap()
|
||||
.set_attachment(attachment)
|
||||
.set_liked_by_me(if liked.is_some() { Some(true) } else { None })
|
||||
)),
|
||||
Event::StrayObject { object, liked } => serde_json::Value::new_object()
|
||||
.set_activity_type(Some(apb::ActivityType::Activity))
|
||||
.set_object(apb::Node::object({
|
||||
let likes = object.likes;
|
||||
let mut obj = object.ap()
|
||||
.set_attachment(attachment);
|
||||
if let Some(liked) = liked {
|
||||
obj = obj.set_audience(apb::Node::object( // TODO setting this again ewww...
|
||||
serde_json::Value::new_object()
|
||||
.set_collection_type(Some(apb::CollectionType::OrderedCollection))
|
||||
.set_total_items(Some(likes as u64))
|
||||
.set_ordered_items(apb::Node::links(vec![liked]))
|
||||
));
|
||||
}
|
||||
obj
|
||||
})),
|
||||
.set_object(apb::Node::object(
|
||||
object.ap()
|
||||
.set_attachment(attachment)
|
||||
.set_liked_by_me(if liked.is_some() { Some(true) } else { None })
|
||||
)),
|
||||
Event::Tombstone => serde_json::Value::new_object()
|
||||
.set_activity_type(Some(apb::ActivityType::Activity))
|
||||
.set_object(apb::Node::object(
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use apb::{BaseMut, Object, Collection, CollectionMut, ObjectMut};
|
||||
use apb::{BaseMut, Collection, CollectionMut, ObjectMut};
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
use crate::routes::activitypub::jsonld::LD;
|
||||
|
@ -41,21 +41,12 @@ impl Model {
|
|||
context: object.context().id(),
|
||||
in_reply_to: object.in_reply_to().id(),
|
||||
published: object.published().ok_or(super::FieldError("published"))?,
|
||||
comments: object.replies()
|
||||
.get()
|
||||
comments: object.replies().get()
|
||||
.map_or(0, |x| x.total_items().unwrap_or(0)) as i64,
|
||||
likes: object.likes().get()
|
||||
.map_or(0, |x| x.total_items().unwrap_or(0)) as i64,
|
||||
shares: object.shares().get()
|
||||
.map_or(0, |x| x.total_items().unwrap_or(0)) as i64,
|
||||
likes: object.audience()
|
||||
.get()
|
||||
.map_or(0, |x|
|
||||
x.as_collection()
|
||||
.map_or(0, |x| x.total_items().unwrap_or(0))
|
||||
) as i64,
|
||||
shares: object.generator()
|
||||
.get()
|
||||
.map_or(0, |x|
|
||||
x.as_collection()
|
||||
.map_or(0, |x| x.total_items().unwrap_or(0))
|
||||
) as i64,
|
||||
to: object.to().into(),
|
||||
bto: object.bto().into(),
|
||||
cc: object.cc().into(),
|
||||
|
@ -81,12 +72,12 @@ impl Model {
|
|||
.set_cc(apb::Node::links(self.cc.0.clone()))
|
||||
.set_bcc(apb::Node::Empty)
|
||||
.set_sensitive(Some(self.sensitive))
|
||||
.set_generator(apb::Node::object(
|
||||
.set_shares(apb::Node::object(
|
||||
serde_json::Value::new_object()
|
||||
.set_collection_type(Some(apb::CollectionType::OrderedCollection))
|
||||
.set_total_items(Some(self.shares as u64))
|
||||
))
|
||||
.set_audience(apb::Node::object(
|
||||
.set_likes(apb::Node::object(
|
||||
serde_json::Value::new_object()
|
||||
.set_collection_type(Some(apb::CollectionType::OrderedCollection))
|
||||
.set_total_items(Some(self.likes as u64))
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use sea_orm::entity::prelude::*;
|
||||
|
||||
use apb::{Actor, ActorMut, ActorType, BaseMut, Collection, CollectionMut, DocumentMut, Object, ObjectMut, PublicKey, PublicKeyMut};
|
||||
use apb::{Actor, ActorMut, ActorType, BaseMut, DocumentMut, Object, ObjectMut, PublicKey, PublicKeyMut};
|
||||
|
||||
use crate::routes::activitypub::jsonld::LD;
|
||||
|
||||
|
@ -59,9 +59,9 @@ impl Model {
|
|||
following: object.following().id(),
|
||||
created: object.published().unwrap_or(chrono::Utc::now()),
|
||||
updated: chrono::Utc::now(),
|
||||
following_count: object.generator().get().map_or(0, |f| f.as_collection().map_or(0, |f| f.total_items().unwrap_or(0))) as i64,
|
||||
followers_count: object.audience().get().map_or(0, |f| f.as_collection().map_or(0, |f| f.total_items().unwrap_or(0))) as i64,
|
||||
statuses_count: object.replies().get().map_or(0, |o| o.total_items().unwrap_or(0)) as i64,
|
||||
following_count: object.following_count().unwrap_or(0) as i64,
|
||||
followers_count: object.followers_count().unwrap_or(0) as i64,
|
||||
statuses_count: object.statuses_count().unwrap_or(0) as i64,
|
||||
public_key: object.public_key().get().ok_or(super::FieldError("publicKey"))?.public_key_pem().to_string(),
|
||||
private_key: None, // there's no way to transport privkey over AP json, must come from DB
|
||||
})
|
||||
|
@ -85,24 +85,9 @@ impl Model {
|
|||
)))
|
||||
.set_published(Some(self.created))
|
||||
.set_preferred_username(Some(&self.preferred_username))
|
||||
.set_replies(apb::Node::object(
|
||||
serde_json::Value::new_object()
|
||||
.set_id(self.outbox.as_deref())
|
||||
.set_collection_type(Some(apb::CollectionType::OrderedCollection))
|
||||
.set_total_items(Some(self.statuses_count as u64))
|
||||
))
|
||||
.set_audience(apb::Node::object(
|
||||
serde_json::Value::new_object()
|
||||
.set_id(self.followers.as_deref())
|
||||
.set_collection_type(Some(apb::CollectionType::OrderedCollection))
|
||||
.set_total_items(Some(self.followers_count as u64))
|
||||
))
|
||||
.set_generator(apb::Node::object(
|
||||
serde_json::Value::new_object()
|
||||
.set_id(self.following.as_deref())
|
||||
.set_collection_type(Some(apb::CollectionType::OrderedCollection))
|
||||
.set_total_items(Some(self.following_count as u64))
|
||||
))
|
||||
.set_statuses_count(Some(self.statuses_count as u64))
|
||||
.set_followers_count(Some(self.followers_count as u64))
|
||||
.set_following_count(Some(self.following_count as u64))
|
||||
.set_inbox(apb::Node::maybe_link(self.inbox))
|
||||
.set_outbox(apb::Node::maybe_link(self.outbox))
|
||||
.set_following(apb::Node::maybe_link(self.following))
|
||||
|
|
|
@ -7,7 +7,7 @@ pub mod following;
|
|||
use axum::extract::{Path, Query, State};
|
||||
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter, QuerySelect, SelectColumns};
|
||||
|
||||
use apb::{ActorMut, CollectionMut, Node, Object, ObjectMut};
|
||||
use apb::{ActorMut, Node, ObjectMut};
|
||||
use crate::{errors::UpubError, model::{self, user}, server::{auth::AuthIdentity, fetcher::Fetcher, Context}, url};
|
||||
|
||||
use super::{jsonld::LD, JsonLD, TryFetch};
|
||||
|
@ -27,6 +27,37 @@ pub async fn view(
|
|||
if auth.is_local() && query.fetch && !ctx.is_local(&uid) {
|
||||
ctx.fetch_user(&uid).await?;
|
||||
}
|
||||
|
||||
let (followed_by_me, following_me) = match auth.my_id() {
|
||||
None => (None, None),
|
||||
Some(my_id) => {
|
||||
// TODO these two queries are fast because of indexes but still are 2 subqueries for each
|
||||
// user GET, not even parallelized... should really add these as joins on the main query, so
|
||||
// that it's one roundtrip only
|
||||
let followed_by_me = model::relation::Entity::find()
|
||||
.filter(model::relation::Column::Follower.eq(my_id))
|
||||
.filter(model::relation::Column::Following.eq(&uid))
|
||||
.select_only()
|
||||
.select_column(model::relation::Column::Follower)
|
||||
.into_tuple::<String>()
|
||||
.one(ctx.db())
|
||||
.await?
|
||||
.map(|_| true);
|
||||
|
||||
let following_me = model::relation::Entity::find()
|
||||
.filter(model::relation::Column::Following.eq(my_id))
|
||||
.filter(model::relation::Column::Follower.eq(&uid))
|
||||
.select_only()
|
||||
.select_column(model::relation::Column::Follower)
|
||||
.into_tuple::<String>()
|
||||
.one(ctx.db())
|
||||
.await?
|
||||
.map(|_| true);
|
||||
|
||||
(followed_by_me, following_me)
|
||||
},
|
||||
};
|
||||
|
||||
match user::Entity::find_by_id(&uid)
|
||||
.find_also_related(model::config::Entity)
|
||||
.one(ctx.db()).await?
|
||||
|
@ -37,39 +68,9 @@ pub async fn view(
|
|||
.set_inbox(Node::link(url!(ctx, "/users/{id}/inbox")))
|
||||
.set_outbox(Node::link(url!(ctx, "/users/{id}/outbox")))
|
||||
.set_following(Node::link(url!(ctx, "/users/{id}/following")))
|
||||
.set_followers(Node::link(url!(ctx, "/users/{id}/followers")));
|
||||
|
||||
// TODO maybe this thing could be made as a single join, to avoid triple db roundtrip for
|
||||
// each fetch made by local users? it's indexed and fast but still...
|
||||
if let Some(my_id) = auth.my_id() {
|
||||
if !auth.is(&uid) {
|
||||
let followed_by_me = model::relation::Entity::find()
|
||||
.filter(model::relation::Column::Follower.eq(my_id))
|
||||
.filter(model::relation::Column::Following.eq(&uid))
|
||||
.select_only()
|
||||
.select_column(model::relation::Column::Follower)
|
||||
.into_tuple::<String>()
|
||||
.all(ctx.db())
|
||||
.await?;
|
||||
|
||||
user
|
||||
.audience()
|
||||
.update(|x| x.set_ordered_items(apb::Node::links(followed_by_me)));
|
||||
|
||||
let following_me = model::relation::Entity::find()
|
||||
.filter(model::relation::Column::Following.eq(my_id))
|
||||
.filter(model::relation::Column::Follower.eq(&uid))
|
||||
.select_only()
|
||||
.select_column(model::relation::Column::Following)
|
||||
.into_tuple::<String>()
|
||||
.all(ctx.db())
|
||||
.await?;
|
||||
|
||||
user
|
||||
.generator()
|
||||
.update(|x| x.set_ordered_items(apb::Node::links(following_me)));
|
||||
}
|
||||
}
|
||||
.set_followers(Node::link(url!(ctx, "/users/{id}/followers")))
|
||||
.set_following_me(following_me)
|
||||
.set_followed_by_me(followed_by_me);
|
||||
|
||||
if !auth.is(&uid) && !cfg.show_followers_count {
|
||||
user = user.set_audience(apb::Node::Empty);
|
||||
|
@ -81,44 +82,13 @@ pub async fn view(
|
|||
|
||||
Ok(JsonLD(user.ld_context()))
|
||||
},
|
||||
// remote user TODDO doesn't work?
|
||||
Some((user_model, None)) => {
|
||||
let user = user_model.ap();
|
||||
|
||||
// TODO maybe this thing could be made as a single join, to avoid triple db roundtrip for
|
||||
// each fetch made by local users? it's indexed and fast but still...
|
||||
if let Some(my_id) = auth.my_id() {
|
||||
if !auth.is(&uid) {
|
||||
let followed_by_me = model::relation::Entity::find()
|
||||
.filter(model::relation::Column::Follower.eq(my_id))
|
||||
.filter(model::relation::Column::Following.eq(&uid))
|
||||
.select_only()
|
||||
.select_column(model::relation::Column::Follower)
|
||||
.into_tuple::<String>()
|
||||
.all(ctx.db())
|
||||
.await?;
|
||||
|
||||
user
|
||||
.audience()
|
||||
.update(|x| x.set_ordered_items(apb::Node::links(followed_by_me)));
|
||||
|
||||
let following_me = model::relation::Entity::find()
|
||||
.filter(model::relation::Column::Following.eq(my_id))
|
||||
.filter(model::relation::Column::Follower.eq(&uid))
|
||||
.select_only()
|
||||
.select_column(model::relation::Column::Following)
|
||||
.into_tuple::<String>()
|
||||
.all(ctx.db())
|
||||
.await?;
|
||||
|
||||
user
|
||||
.generator()
|
||||
.update(|x| x.set_ordered_items(apb::Node::links(following_me)));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(JsonLD(user.ld_context()))
|
||||
},
|
||||
// remote user
|
||||
Some((user_model, None)) => Ok(JsonLD(
|
||||
user_model.ap()
|
||||
.set_following_me(following_me)
|
||||
.set_followed_by_me(followed_by_me)
|
||||
.ld_context()
|
||||
)),
|
||||
None => Err(UpubError::not_found()),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue