Compare commits

..

No commits in common. "af994da294d84e5e3a913e277ec2972d7c3ed2f5" and "34c01dd858f9ae052d70bfef73308ed44913711e" have entirely different histories.

7 changed files with 35 additions and 49 deletions

View file

@ -40,7 +40,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", "activitypub-fe", "activitypub-counters", "litepub", "ostatus", "toot"] }
apb = { path = "apb", features = ["unstructured", "orm", "activitypub-fe", "activitypub-counters", "litepub"] }
# 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

View file

@ -67,9 +67,6 @@ pub struct SecurityConfig {
#[serde(default)]
pub allow_public_debugger: bool,
#[serde_inline_default(true)]
pub show_reply_ids: bool,
}

View file

@ -69,7 +69,6 @@ impl Model {
.set_summary(self.summary.as_deref())
.set_content(self.content.as_deref())
.set_context(apb::Node::maybe_link(self.context.clone()))
.set_conversation(apb::Node::maybe_link(self.context.clone())) // duplicate context for mastodon
.set_in_reply_to(apb::Node::maybe_link(self.in_reply_to.clone()))
.set_published(Some(self.published))
.set_updated(self.updated)

View file

@ -33,8 +33,6 @@ impl LD for serde_json::Value {
Some(_) => {
ctx.insert("fe".to_string(), serde_json::Value::String("https://ns.alemi.dev/as/fe/#".into()));
ctx.insert("likedByMe".to_string(), serde_json::Value::String("fe:likedByMe".into()));
ctx.insert("ostatus".to_string(), serde_json::Value::String("http://ostatus.org#".into()));
ctx.insert("conversation".to_string(), serde_json::Value::String("ostatus:conversation".into()));
},
None => {},
}

View file

@ -2,7 +2,7 @@ pub mod replies;
use apb::{CollectionMut, ObjectMut};
use axum::extract::{Path, Query, State};
use sea_orm::{ColumnTrait, EntityTrait, ModelTrait, QueryFilter, QuerySelect, SelectColumns};
use sea_orm::{ColumnTrait, ModelTrait, QueryFilter};
use crate::{errors::UpubError, model::{self, addressing::Event}, server::{auth::AuthIdentity, fetcher::Fetcher, Context}};
@ -31,11 +31,11 @@ pub async fn view(
.await?
.ok_or_else(UpubError::not_found)?;
let object = match item {
let (object, liked) = match item {
Event::Tombstone => return Err(UpubError::not_found()),
Event::Activity(_) => return Err(UpubError::not_found()),
Event::StrayObject { liked: _, object } => object,
Event::DeepActivity { activity: _, liked: _, object } => object,
Event::StrayObject { object, liked } => (object, liked),
Event::DeepActivity { activity: _, liked, object } => (object, liked),
};
let attachments = object.find_related(model::attachment::Entity)
@ -45,32 +45,24 @@ pub async fn view(
.map(|x| x.ap())
.collect::<Vec<serde_json::Value>>();
let mut replies = apb::Node::Empty;
// let replies =
// serde_json::Value::new_object()
// .set_id(Some(&crate::url!(ctx, "/objects/{id}/replies")))
// .set_collection_type(Some(apb::CollectionType::OrderedCollection))
// .set_first(apb::Node::link(crate::url!(ctx, "/objects/{id}/replies/page")))
// .set_total_items(Some(object.comments as u64));
if ctx.cfg().security.show_reply_ids {
let replies_ids = model::addressing::Entity::find_addressed(None)
.filter(model::object::Column::InReplyTo.eq(oid))
.filter(auth.filter_condition())
.select_only()
.select_column(model::object::Column::Id)
.into_tuple::<String>()
.all(ctx.db())
.await?;
let likes_count = object.likes as u64;
let mut obj = object.ap().set_attachment(apb::Node::array(attachments));
replies = apb::Node::object(
if let Some(liked) = liked {
obj = obj.set_audience(apb::Node::object( // TODO setting this again ewww...
serde_json::Value::new_object()
// .set_id(Some(&crate::url!(ctx, "/objects/{id}/replies")))
// .set_first(apb::Node::link(crate::url!(ctx, "/objects/{id}/replies/page")))
.set_collection_type(Some(apb::CollectionType::Collection))
.set_total_items(Some(object.comments as u64))
.set_items(apb::Node::links(replies_ids))
);
.set_collection_type(Some(apb::CollectionType::OrderedCollection))
.set_total_items(Some(likes_count))
.set_ordered_items(apb::Node::links(vec![liked]))
));
}
Ok(JsonLD(
object.ap()
.set_attachment(apb::Node::array(attachments))
.set_replies(replies)
.ld_context()
))
Ok(JsonLD(obj.ld_context()))
}

View file

@ -307,6 +307,11 @@ async fn fetch_object_inner(ctx: &Context, id: &str, depth: usize) -> crate::Res
if let Some(reply) = object.in_reply_to().id() {
if depth <= 16 {
fetch_object_inner(ctx, &reply, depth + 1).await?;
model::object::Entity::update_many()
.filter(model::object::Column::Id.eq(reply))
.col_expr(model::object::Column::Comments, Expr::col(model::object::Column::Comments).add(1))
.exec(ctx.db())
.await?;
} else {
tracing::warn!("thread deeper than 16, giving up fetching more replies");
}

View file

@ -31,20 +31,15 @@ impl Normalizer for super::Context {
object_model.content = Some(mdhtml::safe_html(&content));
}
// fix context for remote posts
// > note that this will effectively recursively try to fetch the parent object, in order to find
// > the context (which is id of topmost object). there's a recursion limit of 16 hidden inside
// > btw! also if any link is broken or we get rate limited, the whole insertion fails which is
// > kind of dumb. there should be a job system so this can be done in waves. or maybe there's
// > some whole other way to do this?? im thinking but misskey aaaa!! TODO
if let Some(ref reply) = object_model.in_reply_to {
if let Some(o) = model::object::Entity::find_by_id(reply).one(self.db()).await? {
object_model.context = o.context;
} else {
object_model.context = None; // TODO to be filled by some other task
}
} else {
object_model.context = Some(object_model.id.clone());
// fix context also for remote posts
// TODO this is not really appropriate because we're mirroring incorrectly remote objects, but
// it makes it SOO MUCH EASIER for us to fetch threads and stuff, so we're filling it for them
match (&object_model.in_reply_to, &object_model.context) {
(Some(reply_id), None) => // get context from replied object
object_model.context = self.fetch_object(reply_id).await?.context,
(None, None) => // generate a new context
object_model.context = Some(object_model.id.clone()),
(_, Some(_)) => {}, // leave it as set by user
}
model::object::Entity::insert(object_model.clone().into_active_model()).exec(self.db()).await?;