chore: update apb usage
it should become a bit faster which makes no sense but before refs were made from strings created on demand and then cloned again so this should at least make sense
This commit is contained in:
parent
0dedb4d243
commit
5f998e9773
37 changed files with 218 additions and 218 deletions
|
@ -25,7 +25,7 @@ pub async fn fetch(ctx: upub::Context, uri: String, save: bool, actor: Option<St
|
|||
let mut node = apb::Node::link(uri.to_string());
|
||||
if let apb::Node::Link(ref uri) = node {
|
||||
if let Ok(href) = uri.href() {
|
||||
node = upub::Context::request(reqwest::Method::GET, href, None, &from, &pkey, ctx.domain())
|
||||
node = upub::Context::request(reqwest::Method::GET, &href, None, &from, &pkey, ctx.domain())
|
||||
.await?
|
||||
.json::<serde_json::Value>()
|
||||
.await?
|
||||
|
|
|
@ -63,7 +63,7 @@ pub async fn nuke(ctx: upub::Context, for_real: bool, delete_posts: bool) -> Res
|
|||
|
||||
let aid = ctx.aid(&upub::Context::new_id());
|
||||
let undo_activity = apb::new()
|
||||
.set_id(Some(&aid))
|
||||
.set_id(Some(aid.clone()))
|
||||
.set_activity_type(Some(apb::ActivityType::Undo))
|
||||
.set_actor(apb::Node::link(activity.actor.clone()))
|
||||
.set_object(apb::Node::object(undone))
|
||||
|
@ -73,7 +73,7 @@ pub async fn nuke(ctx: upub::Context, for_real: bool, delete_posts: bool) -> Res
|
|||
|
||||
let job = upub::model::job::ActiveModel {
|
||||
internal: NotSet,
|
||||
activity: Set(aid.clone()),
|
||||
activity: Set(aid),
|
||||
job_type: Set(upub::model::job::JobType::Outbound),
|
||||
actor: Set(activity.actor),
|
||||
target: Set(None),
|
||||
|
@ -101,7 +101,7 @@ pub async fn nuke(ctx: upub::Context, for_real: bool, delete_posts: bool) -> Res
|
|||
let aid = ctx.aid(&upub::Context::new_id());
|
||||
let actor = object.attributed_to.unwrap_or_else(|| ctx.domain().to_string());
|
||||
let undo_activity = apb::new()
|
||||
.set_id(Some(&aid))
|
||||
.set_id(Some(aid.clone()))
|
||||
.set_activity_type(Some(apb::ActivityType::Delete))
|
||||
.set_actor(apb::Node::link(actor.clone()))
|
||||
.set_object(apb::Node::link(object.id.clone()))
|
||||
|
@ -114,7 +114,7 @@ pub async fn nuke(ctx: upub::Context, for_real: bool, delete_posts: bool) -> Res
|
|||
|
||||
let job = upub::model::job::ActiveModel {
|
||||
internal: NotSet,
|
||||
activity: Set(aid.clone()),
|
||||
activity: Set(aid),
|
||||
job_type: Set(upub::model::job::JobType::Outbound),
|
||||
actor: Set(actor),
|
||||
target: Set(None),
|
||||
|
|
|
@ -67,7 +67,7 @@ pub async fn relay(ctx: upub::Context, action: RelayCommand) -> Result<(), Reque
|
|||
RelayCommand::Follow { actor } => {
|
||||
let aid = ctx.aid(&upub::Context::new_id());
|
||||
let payload = apb::new()
|
||||
.set_id(Some(&aid))
|
||||
.set_id(Some(aid.clone()))
|
||||
.set_activity_type(Some(apb::ActivityType::Follow))
|
||||
.set_actor(apb::Node::link(ctx.base().to_string()))
|
||||
.set_object(apb::Node::link(actor.clone()))
|
||||
|
@ -76,7 +76,7 @@ pub async fn relay(ctx: upub::Context, action: RelayCommand) -> Result<(), Reque
|
|||
.set_published(Some(chrono::Utc::now()));
|
||||
let job = upub::model::job::ActiveModel {
|
||||
internal: NotSet,
|
||||
activity: Set(aid.clone()),
|
||||
activity: Set(aid),
|
||||
job_type: Set(upub::model::job::JobType::Outbound),
|
||||
actor: Set(ctx.base().to_string()),
|
||||
target: Set(None),
|
||||
|
@ -103,7 +103,7 @@ pub async fn relay(ctx: upub::Context, action: RelayCommand) -> Result<(), Reque
|
|||
.ok_or_else(|| DbErr::RecordNotFound(format!("activity#{}", relation.activity)))?;
|
||||
let aid = ctx.aid(&upub::Context::new_id());
|
||||
let payload = apb::new()
|
||||
.set_id(Some(&aid))
|
||||
.set_id(Some(aid.clone()))
|
||||
.set_activity_type(Some(apb::ActivityType::Accept(apb::AcceptType::Accept)))
|
||||
.set_actor(apb::Node::link(ctx.base().to_string()))
|
||||
.set_object(apb::Node::link(activity.id))
|
||||
|
@ -112,7 +112,7 @@ pub async fn relay(ctx: upub::Context, action: RelayCommand) -> Result<(), Reque
|
|||
.set_published(Some(chrono::Utc::now()));
|
||||
let job = upub::model::job::ActiveModel {
|
||||
internal: NotSet,
|
||||
activity: Set(aid.clone()),
|
||||
activity: Set(aid),
|
||||
job_type: Set(upub::model::job::JobType::Outbound),
|
||||
actor: Set(ctx.base().to_string()),
|
||||
target: Set(None),
|
||||
|
@ -140,7 +140,7 @@ pub async fn relay(ctx: upub::Context, action: RelayCommand) -> Result<(), Reque
|
|||
.ok_or_else(|| DbErr::RecordNotFound(format!("activity#{}", accept_activity_id)))?;
|
||||
let aid = ctx.aid(&upub::Context::new_id());
|
||||
let payload = apb::new()
|
||||
.set_id(Some(&aid))
|
||||
.set_id(Some(aid.clone()))
|
||||
.set_activity_type(Some(apb::ActivityType::Undo))
|
||||
.set_actor(apb::Node::link(ctx.base().to_string()))
|
||||
.set_object(apb::Node::object(activity.ap()))
|
||||
|
@ -149,7 +149,7 @@ pub async fn relay(ctx: upub::Context, action: RelayCommand) -> Result<(), Reque
|
|||
.set_published(Some(chrono::Utc::now()));
|
||||
let job = upub::model::job::ActiveModel {
|
||||
internal: NotSet,
|
||||
activity: Set(aid.clone()),
|
||||
activity: Set(aid),
|
||||
job_type: Set(upub::model::job::JobType::Outbound),
|
||||
actor: Set(ctx.base().to_string()),
|
||||
target: Set(None),
|
||||
|
@ -176,7 +176,7 @@ pub async fn relay(ctx: upub::Context, action: RelayCommand) -> Result<(), Reque
|
|||
.ok_or_else(|| DbErr::RecordNotFound(format!("activity#{}", relation.activity)))?;
|
||||
let aid = ctx.aid(&upub::Context::new_id());
|
||||
let payload = apb::new()
|
||||
.set_id(Some(&aid))
|
||||
.set_id(Some(aid.clone()))
|
||||
.set_activity_type(Some(apb::ActivityType::Undo))
|
||||
.set_actor(apb::Node::link(ctx.base().to_string()))
|
||||
.set_object(apb::Node::object(activity.ap()))
|
||||
|
@ -185,7 +185,7 @@ pub async fn relay(ctx: upub::Context, action: RelayCommand) -> Result<(), Reque
|
|||
.set_published(Some(chrono::Utc::now()));
|
||||
let job = upub::model::job::ActiveModel {
|
||||
internal: NotSet,
|
||||
activity: Set(aid.clone()),
|
||||
activity: Set(aid),
|
||||
job_type: Set(upub::model::job::JobType::Outbound),
|
||||
actor: Set(ctx.base().to_string()),
|
||||
target: Set(None),
|
||||
|
|
|
@ -90,7 +90,7 @@ impl Entity {
|
|||
impl Model {
|
||||
pub fn ap(self) -> serde_json::Value {
|
||||
apb::new()
|
||||
.set_id(Some(&self.id))
|
||||
.set_id(Some(self.id))
|
||||
.set_activity_type(Some(self.activity_type))
|
||||
.set_actor(apb::Node::link(self.actor))
|
||||
.set_object(apb::Node::maybe_link(self.object))
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use sea_orm::{entity::prelude::*, QuerySelect, SelectColumns};
|
||||
|
||||
use apb::{field::OptionalString, ActorMut, ActorType, BaseMut, DocumentMut, EndpointsMut, ObjectMut, PublicKeyMut};
|
||||
use apb::{ActorMut, ActorType, BaseMut, DocumentMut, EndpointsMut, ObjectMut, PublicKeyMut};
|
||||
|
||||
use crate::ext::{JsonVec, TypeName};
|
||||
|
||||
|
@ -25,8 +25,8 @@ impl TypeName for Field {
|
|||
impl<T: apb::Object> From<T> for Field {
|
||||
fn from(value: T) -> Self {
|
||||
Field {
|
||||
name: value.name().str().unwrap_or_default(),
|
||||
value: mdhtml::safe_html(value.value().unwrap_or_default()),
|
||||
name: value.name().unwrap_or_default().to_string(),
|
||||
value: mdhtml::safe_html(&value.value().unwrap_or_default()),
|
||||
field_type: "PropertyValue".to_string(), // TODO can we try parsing this instead??
|
||||
verified_at: None, // TODO where does verified_at come from? extend apb maybe
|
||||
}
|
||||
|
@ -203,10 +203,10 @@ impl Entity {
|
|||
impl Model {
|
||||
pub fn ap(self) -> serde_json::Value {
|
||||
apb::new()
|
||||
.set_id(Some(&self.id))
|
||||
.set_id(Some(self.id.clone()))
|
||||
.set_actor_type(Some(self.actor_type))
|
||||
.set_name(self.name.as_deref())
|
||||
.set_summary(self.summary.as_deref())
|
||||
.set_name(self.name)
|
||||
.set_summary(self.summary)
|
||||
.set_icon(apb::Node::maybe_object(self.icon.map(|i|
|
||||
apb::new()
|
||||
.set_document_type(Some(apb::DocumentType::Image))
|
||||
|
@ -225,7 +225,7 @@ impl Model {
|
|||
))
|
||||
.set_published(Some(self.published))
|
||||
.set_updated(if self.updated != self.published { Some(self.updated) } else { None })
|
||||
.set_preferred_username(Some(&self.preferred_username))
|
||||
.set_preferred_username(Some(self.preferred_username))
|
||||
.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))
|
||||
|
@ -235,13 +235,13 @@ impl Model {
|
|||
.set_followers(apb::Node::maybe_link(self.followers))
|
||||
.set_public_key(apb::Node::object(
|
||||
apb::new()
|
||||
.set_id(Some(&format!("{}#main-key", self.id)))
|
||||
.set_owner(Some(&self.id))
|
||||
.set_public_key_pem(&self.public_key)
|
||||
.set_id(Some(format!("{}#main-key", self.id)))
|
||||
.set_owner(Some(self.id))
|
||||
.set_public_key_pem(self.public_key)
|
||||
))
|
||||
.set_endpoints(apb::Node::object(
|
||||
apb::new()
|
||||
.set_shared_inbox(self.shared_inbox.as_deref())
|
||||
.set_shared_inbox(self.shared_inbox)
|
||||
))
|
||||
.set_also_known_as(apb::Node::links(self.also_known_as.0))
|
||||
.set_moved_to(apb::Node::maybe_link(self.moved_to))
|
||||
|
|
|
@ -39,7 +39,7 @@ impl Model {
|
|||
apb::new()
|
||||
.set_url(apb::Node::link(self.url))
|
||||
.set_document_type(Some(self.document_type))
|
||||
.set_media_type(Some(&self.media_type))
|
||||
.set_name(self.name.as_deref())
|
||||
.set_media_type(Some(self.media_type))
|
||||
.set_name(self.name)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -163,12 +163,12 @@ impl Entity {
|
|||
impl Model {
|
||||
pub fn ap(self) -> serde_json::Value {
|
||||
apb::new()
|
||||
.set_id(Some(&self.id))
|
||||
.set_id(Some(self.id))
|
||||
.set_object_type(Some(self.object_type))
|
||||
.set_attributed_to(apb::Node::maybe_link(self.attributed_to))
|
||||
.set_name(self.name.as_deref())
|
||||
.set_summary(self.summary.as_deref())
|
||||
.set_content(self.content.as_deref())
|
||||
.set_name(self.name)
|
||||
.set_summary(self.summary)
|
||||
.set_content(self.content)
|
||||
.set_image(apb::Node::maybe_object(self.image.map(|x|
|
||||
apb::new()
|
||||
.set_document_type(Some(apb::DocumentType::Image))
|
||||
|
|
|
@ -12,8 +12,8 @@ impl RichMention {
|
|||
use apb::LinkMut;
|
||||
apb::new()
|
||||
.set_link_type(Some(apb::LinkType::Mention))
|
||||
.set_href(Some(&self.id))
|
||||
.set_name(Some(&self.fqn))
|
||||
.set_href(Some(self.id))
|
||||
.set_name(Some(self.fqn))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ impl RichHashtag {
|
|||
pub fn ap(self) -> serde_json::Value {
|
||||
use apb::LinkMut;
|
||||
apb::new()
|
||||
.set_name(Some(&format!("#{}", self.hash.name)))
|
||||
.set_name(Some(format!("#{}", self.hash.name)))
|
||||
.set_link_type(Some(apb::LinkType::Hashtag))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
use std::collections::BTreeMap;
|
||||
|
||||
use apb::{Activity, Actor, ActorMut, Base, Collection, CollectionPage, Object};
|
||||
use apb::{Shortcuts, Activity, Actor, ActorMut, Base, Collection, CollectionPage, Object};
|
||||
use reqwest::{header::{ACCEPT, CONTENT_TYPE, USER_AGENT}, Method, Response};
|
||||
use sea_orm::{ActiveValue::Set, ColumnTrait, ConnectionTrait, DbErr, EntityTrait, IntoActiveModel, NotSet, QueryFilter, ActiveModelTrait};
|
||||
|
||||
use crate::{ext::Shortcuts, traits::normalize::AP};
|
||||
|
||||
use super::{Addresser, Cloaker, Normalizer};
|
||||
use httpsign::HttpSignature;
|
||||
|
||||
use crate::AP;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Pull<T> {
|
||||
Actor(T),
|
||||
|
@ -184,7 +184,7 @@ impl Fetcher for crate::Context {
|
|||
if depth >= self.cfg().security.max_id_redirects {
|
||||
return Err(RequestError::TooManyRedirects);
|
||||
}
|
||||
return self.pull(doc_id).await;
|
||||
return self.pull(&doc_id).await;
|
||||
}
|
||||
|
||||
match document.object_type()? {
|
||||
|
@ -299,7 +299,7 @@ impl Fetcher for crate::Context {
|
|||
// TODO try fetching these numbers from audience/generator fields to avoid making 2 more GETs every time
|
||||
if let Ok(followers_url) = document.followers().id() {
|
||||
let req = Self::request(
|
||||
Method::GET, followers_url, None,
|
||||
Method::GET, &followers_url, None,
|
||||
self.base(), self.pkey(), self.domain(),
|
||||
).await;
|
||||
if let Ok(res) = req {
|
||||
|
@ -313,7 +313,7 @@ impl Fetcher for crate::Context {
|
|||
|
||||
if let Ok(following_url) = document.following().id() {
|
||||
let req = Self::request(
|
||||
Method::GET, following_url, None,
|
||||
Method::GET, &following_url, None,
|
||||
self.base(), self.pkey(), self.domain(),
|
||||
).await;
|
||||
if let Ok(res) = req {
|
||||
|
@ -362,7 +362,7 @@ impl Fetcher for crate::Context {
|
|||
let document = self.pull(id).await?.actor()?;
|
||||
|
||||
if document.id()? != id {
|
||||
if let Some(x) = crate::model::actor::Entity::find_by_ap_id(document.id()?).one(tx).await? {
|
||||
if let Some(x) = crate::model::actor::Entity::find_by_ap_id(&document.id()?).one(tx).await? {
|
||||
return Ok(x); // already in db but we had to follow the "pretty" url, mehh
|
||||
}
|
||||
}
|
||||
|
@ -381,16 +381,16 @@ impl Fetcher for crate::Context {
|
|||
}
|
||||
|
||||
async fn resolve_activity(&self, activity: serde_json::Value, tx: &impl ConnectionTrait) -> Result<crate::model::activity::Model, RequestError> {
|
||||
let _domain = self.fetch_domain(&crate::Context::server(activity.id()?), tx).await?;
|
||||
let _domain = self.fetch_domain(&crate::Context::server(&activity.id()?), tx).await?;
|
||||
|
||||
if let Ok(activity_actor) = activity.actor().id() {
|
||||
if let Err(e) = self.fetch_user(activity_actor, tx).await {
|
||||
if let Err(e) = self.fetch_user(&activity_actor, tx).await {
|
||||
tracing::warn!("could not get actor of fetched activity: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(activity_object) = activity.object().id() {
|
||||
if let Err(e) = self.fetch_object(activity_object, tx).await {
|
||||
if let Err(e) = self.fetch_object(&activity_object, tx).await {
|
||||
tracing::warn!("could not get object of fetched activity: {e}");
|
||||
}
|
||||
}
|
||||
|
@ -441,13 +441,13 @@ impl Fetcher for crate::Context {
|
|||
}
|
||||
|
||||
for obj in page.items().flat() {
|
||||
if let Err(e) = self.fetch_object(obj.id()?, tx).await {
|
||||
if let Err(e) = self.fetch_object(&obj.id()?, tx).await {
|
||||
tracing::warn!("error fetching reply: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
for obj in page.ordered_items().flat() {
|
||||
if let Err(e) = self.fetch_object(obj.id()?, tx).await {
|
||||
if let Err(e) = self.fetch_object(&obj.id()?, tx).await {
|
||||
tracing::warn!("error fetching reply: {e}");
|
||||
}
|
||||
}
|
||||
|
@ -477,7 +477,7 @@ async fn fetch_object_r(ctx: &crate::Context, id: &str, depth: u32, tx: &impl Co
|
|||
let object = ctx.pull(id).await?.object()?;
|
||||
|
||||
if object.id()? != id {
|
||||
if let Some(x) = crate::model::object::Entity::find_by_ap_id(object.id()?).one(tx).await? {
|
||||
if let Some(x) = crate::model::object::Entity::find_by_ap_id(&object.id()?).one(tx).await? {
|
||||
return Ok(x); // already in db but we had to follow the "pretty" url, mehh
|
||||
}
|
||||
}
|
||||
|
@ -490,21 +490,21 @@ async fn resolve_object_r(ctx: &crate::Context, object: serde_json::Value, depth
|
|||
|
||||
if let Ok(oid) = object.id() {
|
||||
if oid != id {
|
||||
if let Some(x) = crate::model::object::Entity::find_by_ap_id(oid).one(tx).await? {
|
||||
if let Some(x) = crate::model::object::Entity::find_by_ap_id(&oid).one(tx).await? {
|
||||
return Ok(x); // already in db, but with id different that given url
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(attributed_to) = object.attributed_to().id() {
|
||||
if let Err(e) = ctx.fetch_user(attributed_to, tx).await {
|
||||
if let Err(e) = ctx.fetch_user(&attributed_to, tx).await {
|
||||
tracing::warn!("could not get actor of fetched object: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(reply) = object.in_reply_to().id() {
|
||||
if depth <= ctx.cfg().security.thread_crawl_depth {
|
||||
fetch_object_r(ctx, reply, depth + 1, tx).await?;
|
||||
fetch_object_r(ctx, &reply, depth + 1, tx).await?;
|
||||
} else {
|
||||
tracing::warn!("thread deeper than {}, giving up fetching more replies", ctx.cfg().security.thread_crawl_depth);
|
||||
}
|
||||
|
@ -527,7 +527,7 @@ impl Dereferenceable<serde_json::Value> for apb::Node<serde_json::Value> {
|
|||
apb::Node::Link(uri) => {
|
||||
let href = uri.href()?;
|
||||
tracing::info!("dereferencing {href}");
|
||||
let res = crate::Context::request(Method::GET, href, None, ctx.base(), ctx.pkey(), ctx.domain())
|
||||
let res = crate::Context::request(Method::GET, &href, None, ctx.base(), ctx.pkey(), ctx.domain())
|
||||
.await?
|
||||
.json::<serde_json::Value>()
|
||||
.await?;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use apb::{field::OptionalString, Document, Endpoints, Node, Object, PublicKey};
|
||||
use apb::{Document, Endpoints, Node, Object, PublicKey, Shortcuts};
|
||||
use sea_orm::{sea_query::Expr, ActiveModelTrait, ActiveValue::{Unchanged, NotSet, Set}, ColumnTrait, ConnectionTrait, DbErr, EntityTrait, IntoActiveModel, QueryFilter};
|
||||
use crate::ext::Shortcuts;
|
||||
|
||||
use super::{Cloaker, Fetcher};
|
||||
|
||||
|
@ -40,7 +39,7 @@ impl Normalizer for crate::Context {
|
|||
// > 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 Ok(reply) = object.in_reply_to().id() {
|
||||
if let Some(o) = crate::model::object::Entity::find_by_ap_id(reply).one(tx).await? {
|
||||
if let Some(o) = crate::model::object::Entity::find_by_ap_id(&reply).one(tx).await? {
|
||||
object_model.context = o.context;
|
||||
} else {
|
||||
object_model.context = None; // TODO to be filled by some other task
|
||||
|
@ -104,7 +103,7 @@ impl Normalizer for crate::Context {
|
|||
Node::Link(l) => {
|
||||
let url = l.href().unwrap_or_default();
|
||||
if url == obj_image { continue };
|
||||
let mut media_type = l.media_type().unwrap_or("link").to_string();
|
||||
let mut media_type = l.media_type().unwrap_or("link".to_string());
|
||||
let mut document_type = apb::DocumentType::Page;
|
||||
if self.cfg().compat.fix_attachment_images_media_type
|
||||
&& [".jpg", ".jpeg", ".png", ".webp", ".bmp"] // TODO more image types???
|
||||
|
@ -117,10 +116,10 @@ impl Normalizer for crate::Context {
|
|||
}
|
||||
crate::model::attachment::ActiveModel {
|
||||
internal: sea_orm::ActiveValue::NotSet,
|
||||
url: Set(self.cloaked(url)),
|
||||
url: Set(self.cloaked(&url)),
|
||||
object: Set(object_model.internal),
|
||||
document_type: Set(document_type),
|
||||
name: Set(l.name().str()),
|
||||
name: Set(l.name().ok()),
|
||||
media_type: Set(media_type),
|
||||
}
|
||||
},
|
||||
|
@ -142,7 +141,7 @@ impl Normalizer for crate::Context {
|
|||
// we should try to resolve remote users mentioned, otherwise most mentions will
|
||||
// be lost. also we shouldn't fail inserting the whole post if the mention fails
|
||||
// resolving.
|
||||
if let Ok(user) = self.fetch_user(href, tx).await {
|
||||
if let Ok(user) = self.fetch_user(&href, tx).await {
|
||||
let model = crate::model::mention::ActiveModel {
|
||||
internal: NotSet,
|
||||
object: Set(object_model.internal),
|
||||
|
@ -156,7 +155,7 @@ impl Normalizer for crate::Context {
|
|||
},
|
||||
Ok(apb::LinkType::Hashtag) => {
|
||||
let hashtag = l.name()
|
||||
.unwrap_or_else(|_| l.href().unwrap_or_default().split('/').last().unwrap_or_default()) // TODO maybe just fail?
|
||||
.unwrap_or_else(|_| l.href().unwrap_or_default().split('/').last().unwrap_or_default().to_string()) // TODO maybe just fail?
|
||||
.replace('#', "");
|
||||
// TODO lemmy added a "fix" to make its communities kind of work with mastodon:
|
||||
// basically they include the community name as hashtag. ughhhh, since we handle
|
||||
|
@ -238,8 +237,8 @@ impl AP {
|
|||
id: activity.id()?.to_string(),
|
||||
activity_type: activity.activity_type()?,
|
||||
actor: activity.actor().id()?.to_string(),
|
||||
object: activity.object().id().str(),
|
||||
target: activity.target().id().str(),
|
||||
object: activity.object().id().ok(),
|
||||
target: activity.target().id().ok(),
|
||||
published: activity.published().unwrap_or(chrono::Utc::now()),
|
||||
to: activity.to().all_ids().into(),
|
||||
bto: activity.bto().all_ids().into(),
|
||||
|
@ -268,11 +267,11 @@ impl AP {
|
|||
}
|
||||
Ok(crate::model::attachment::Model {
|
||||
internal: 0,
|
||||
url: document.url().id().str().unwrap_or_default(),
|
||||
url: document.url().id().unwrap_or_default(),
|
||||
object: parent,
|
||||
document_type: document.as_document().map_or(apb::DocumentType::Document, |x| x.document_type().unwrap_or(apb::DocumentType::Page)),
|
||||
name: document.name().str(),
|
||||
media_type: document.media_type().unwrap_or("link").to_string(),
|
||||
name: document.name().ok(),
|
||||
media_type: document.media_type().unwrap_or("link".to_string()),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -307,21 +306,21 @@ impl AP {
|
|||
internal: 0,
|
||||
id: object.id()?.to_string(),
|
||||
object_type: object.object_type()?,
|
||||
attributed_to: object.attributed_to().id().str(),
|
||||
name: object.name().str(),
|
||||
summary: object.summary().str(),
|
||||
content: object.content().str(),
|
||||
attributed_to: object.attributed_to().id().ok(),
|
||||
name: object.name().ok(),
|
||||
summary: object.summary().ok(),
|
||||
content: object.content().ok(),
|
||||
image: object.image_url().ok(),
|
||||
context: object.context().id().str(),
|
||||
in_reply_to: object.in_reply_to().id().str(),
|
||||
quote: object.quote_url().id().str(),
|
||||
context: object.context().id().ok(),
|
||||
in_reply_to: object.in_reply_to().id().ok(),
|
||||
quote: object.quote_url().id().ok(),
|
||||
published: object.published().unwrap_or_else(|_| chrono::Utc::now()),
|
||||
updated: object.updated().unwrap_or_else(|_| chrono::Utc::now()),
|
||||
url: object.url().id().str(),
|
||||
url: object.url().id().ok(),
|
||||
replies: object.replies_count().unwrap_or_default(),
|
||||
likes: object.likes_count().unwrap_or_default(),
|
||||
announces: object.shares_count().unwrap_or_default(),
|
||||
audience: object.audience().id().str(),
|
||||
audience: object.audience().id().ok(),
|
||||
to: object.to().all_ids().into(),
|
||||
bto: object.bto().all_ids().into(),
|
||||
cc: object.cc().all_ids().into(),
|
||||
|
@ -362,19 +361,19 @@ impl AP {
|
|||
internal: 0,
|
||||
domain,
|
||||
id: ap_id,
|
||||
preferred_username: actor.preferred_username().unwrap_or(&fallback_preferred_username).to_string(),
|
||||
preferred_username: actor.preferred_username().unwrap_or(fallback_preferred_username).to_string(),
|
||||
actor_type: actor.actor_type()?,
|
||||
name: actor.name().str(),
|
||||
summary: actor.summary().str(),
|
||||
name: actor.name().ok(),
|
||||
summary: actor.summary().ok(),
|
||||
icon: actor.icon_url().ok(),
|
||||
image: actor.image_url().ok(),
|
||||
inbox: actor.inbox().id().str(),
|
||||
outbox: actor.outbox().id().str(),
|
||||
inbox: actor.inbox().id().ok(),
|
||||
outbox: actor.outbox().id().ok(),
|
||||
shared_inbox: actor.endpoints().inner().and_then(|x| x.shared_inbox()).map(|x| x.to_string()).ok(),
|
||||
followers: actor.followers().id().str(),
|
||||
following: actor.following().id().str(),
|
||||
also_known_as: actor.also_known_as().flat().into_iter().filter_map(|x| x.id().str()).collect::<Vec<String>>().into(),
|
||||
moved_to: actor.moved_to().id().str(),
|
||||
followers: actor.followers().id().ok(),
|
||||
following: actor.following().id().ok(),
|
||||
also_known_as: actor.also_known_as().flat().into_iter().filter_map(|x| x.id().ok()).collect::<Vec<String>>().into(),
|
||||
moved_to: actor.moved_to().id().ok(),
|
||||
published: actor.published().unwrap_or(chrono::Utc::now()),
|
||||
updated: chrono::Utc::now(),
|
||||
following_count: actor.following_count().unwrap_or(0) as i32,
|
||||
|
|
|
@ -60,14 +60,14 @@ pub async fn create(ctx: &crate::Context, activity: impl apb::Activity, tx: &Dat
|
|||
tracing::error!("refusing to process activity without embedded object");
|
||||
return Err(ProcessorError::Unprocessable(activity.id()?.to_string()));
|
||||
};
|
||||
if model::object::Entity::ap_to_internal(object_node.id()?, tx).await?.is_some() {
|
||||
if model::object::Entity::ap_to_internal(&object_node.id()?, tx).await?.is_some() {
|
||||
return Err(ProcessorError::AlreadyProcessed);
|
||||
}
|
||||
if object_node.attributed_to().id()? != activity.actor().id()? {
|
||||
return Err(ProcessorError::Unauthorized);
|
||||
}
|
||||
if let Ok(reply) = object_node.in_reply_to().id() {
|
||||
if let Err(e) = ctx.fetch_object(reply, tx).await {
|
||||
if let Err(e) = ctx.fetch_object(&reply, tx).await {
|
||||
tracing::warn!("failed fetching replies for received object: {e}");
|
||||
}
|
||||
}
|
||||
|
@ -96,8 +96,8 @@ pub async fn create(ctx: &crate::Context, activity: impl apb::Activity, tx: &Dat
|
|||
}
|
||||
|
||||
pub async fn like(ctx: &crate::Context, activity: impl apb::Activity, tx: &DatabaseTransaction) -> Result<(), ProcessorError> {
|
||||
let actor = ctx.fetch_user(activity.actor().id()?, tx).await?;
|
||||
let obj = ctx.fetch_object(activity.object().id()?, tx).await?;
|
||||
let actor = ctx.fetch_user(&activity.actor().id()?, tx).await?;
|
||||
let obj = ctx.fetch_object(&activity.object().id()?, tx).await?;
|
||||
let likes_local_object = obj.attributed_to.as_ref().map(|x| ctx.is_local(x)).unwrap_or_default();
|
||||
if crate::model::like::Entity::find_by_uid_oid(actor.internal, obj.internal)
|
||||
.any(tx)
|
||||
|
@ -146,8 +146,8 @@ pub async fn like(ctx: &crate::Context, activity: impl apb::Activity, tx: &Datab
|
|||
|
||||
// TODO basically same as like, can we make one function, maybe with const generic???
|
||||
pub async fn dislike(ctx: &crate::Context, activity: impl apb::Activity, tx: &DatabaseTransaction) -> Result<(), ProcessorError> {
|
||||
let actor = ctx.fetch_user(activity.actor().id()?, tx).await?;
|
||||
let obj = ctx.fetch_object(activity.object().id()?, tx).await?;
|
||||
let actor = ctx.fetch_user(&activity.actor().id()?, tx).await?;
|
||||
let obj = ctx.fetch_object(&activity.object().id()?, tx).await?;
|
||||
if crate::model::dislike::Entity::find_by_uid_oid(actor.internal, obj.internal)
|
||||
.any(tx)
|
||||
.await?
|
||||
|
@ -186,11 +186,11 @@ pub async fn dislike(ctx: &crate::Context, activity: impl apb::Activity, tx: &Da
|
|||
}
|
||||
|
||||
pub async fn follow(ctx: &crate::Context, activity: impl apb::Activity, tx: &DatabaseTransaction) -> Result<(), ProcessorError> {
|
||||
let source_actor = crate::model::actor::Entity::find_by_ap_id(activity.actor().id()?)
|
||||
let source_actor = crate::model::actor::Entity::find_by_ap_id(&activity.actor().id()?)
|
||||
.one(tx)
|
||||
.await?
|
||||
.ok_or(ProcessorError::Incomplete)?;
|
||||
let target_actor = ctx.fetch_user(activity.object().id()?, tx).await?;
|
||||
let target_actor = ctx.fetch_user(&activity.object().id()?, tx).await?;
|
||||
let activity_model = ctx.insert_activity(activity, tx).await?;
|
||||
ctx.address(Some(&activity_model), None, tx).await?;
|
||||
|
||||
|
@ -246,7 +246,7 @@ pub async fn follow(ctx: &crate::Context, activity: impl apb::Activity, tx: &Dat
|
|||
|
||||
pub async fn accept(ctx: &crate::Context, activity: impl apb::Activity, tx: &DatabaseTransaction) -> Result<(), ProcessorError> {
|
||||
// TODO what about TentativeAccept
|
||||
let follow_activity = crate::model::activity::Entity::find_by_ap_id(activity.object().id()?)
|
||||
let follow_activity = crate::model::activity::Entity::find_by_ap_id(&activity.object().id()?)
|
||||
.one(tx)
|
||||
.await?
|
||||
.ok_or(ProcessorError::Incomplete)?;
|
||||
|
@ -305,7 +305,7 @@ pub async fn accept(ctx: &crate::Context, activity: impl apb::Activity, tx: &Dat
|
|||
|
||||
pub async fn reject(ctx: &crate::Context, activity: impl apb::Activity, tx: &DatabaseTransaction) -> Result<(), ProcessorError> {
|
||||
// TODO what about TentativeReject?
|
||||
let follow_activity = crate::model::activity::Entity::find_by_ap_id(activity.object().id()?)
|
||||
let follow_activity = crate::model::activity::Entity::find_by_ap_id(&activity.object().id()?)
|
||||
.one(tx)
|
||||
.await?
|
||||
.ok_or(ProcessorError::Incomplete)?;
|
||||
|
@ -429,7 +429,7 @@ pub async fn undo(ctx: &crate::Context, activity: impl apb::Activity, tx: &Datab
|
|||
match undone_activity.as_activity()?.activity_type()? {
|
||||
apb::ActivityType::Like => {
|
||||
let internal_oid = crate::model::object::Entity::ap_to_internal(
|
||||
undone_activity.as_activity()?.object().id()?,
|
||||
&undone_activity.as_activity()?.object().id()?,
|
||||
tx
|
||||
)
|
||||
.await?
|
||||
|
@ -450,7 +450,7 @@ pub async fn undo(ctx: &crate::Context, activity: impl apb::Activity, tx: &Datab
|
|||
},
|
||||
apb::ActivityType::Follow => {
|
||||
let internal_uid_following = crate::model::actor::Entity::ap_to_internal(
|
||||
undone_activity.as_activity()?.object().id()?,
|
||||
&undone_activity.as_activity()?.object().id()?,
|
||||
tx,
|
||||
)
|
||||
.await?
|
||||
|
@ -494,7 +494,7 @@ pub async fn undo(ctx: &crate::Context, activity: impl apb::Activity, tx: &Datab
|
|||
ctx.address(Some(&activity_model), None, tx).await?;
|
||||
}
|
||||
|
||||
if let Some(internal) = crate::model::activity::Entity::ap_to_internal(undone_activity.id()?, tx).await? {
|
||||
if let Some(internal) = crate::model::activity::Entity::ap_to_internal(&undone_activity.id()?, tx).await? {
|
||||
crate::model::notification::Entity::delete_many()
|
||||
.filter(crate::model::notification::Column::Activity.eq(internal))
|
||||
.exec(tx)
|
||||
|
@ -532,7 +532,7 @@ pub async fn announce(ctx: &crate::Context, activity: impl apb::Activity, tx: &D
|
|||
}
|
||||
};
|
||||
|
||||
let actor = ctx.fetch_user(activity.actor().id()?, tx).await?;
|
||||
let actor = ctx.fetch_user(&activity.actor().id()?, tx).await?;
|
||||
|
||||
// we only care about announces produced by "Person" actors, because there's intention
|
||||
// anything shared by groups, services or applications is automated: fetch it and be done
|
||||
|
|
|
@ -47,7 +47,7 @@ pub async fn get<const OUTGOING: bool>(
|
|||
};
|
||||
|
||||
|
||||
crate::builders::collection(&upub::url!(ctx, "/actors/{id}/{follow___}"), Some(count as u64))
|
||||
crate::builders::collection(upub::url!(ctx, "/actors/{id}/{follow___}"), Some(count as u64))
|
||||
}
|
||||
|
||||
pub async fn page<const OUTGOING: bool>(
|
||||
|
|
|
@ -14,7 +14,7 @@ pub async fn get(
|
|||
Identity::Anonymous => Err(crate::ApiError::forbidden()),
|
||||
Identity::Remote { .. } => Err(crate::ApiError::forbidden()),
|
||||
Identity::Local { id: user, .. } => if ctx.uid(&id) == user {
|
||||
crate::builders::collection(&upub::url!(ctx, "/actors/{id}/inbox"), None)
|
||||
crate::builders::collection(upub::url!(ctx, "/actors/{id}/inbox"), None)
|
||||
} else {
|
||||
Err(crate::ApiError::forbidden())
|
||||
},
|
||||
|
|
|
@ -65,8 +65,8 @@ pub async fn view(
|
|||
.set_manually_approves_followers(Some(!cfg.accept_follow_requests))
|
||||
.set_endpoints(Node::object(
|
||||
apb::new()
|
||||
.set_shared_inbox(Some(&upub::url!(ctx, "/inbox")))
|
||||
.set_proxy_url(Some(&upub::url!(ctx, "/fetch")))
|
||||
.set_shared_inbox(Some(upub::url!(ctx, "/inbox")))
|
||||
.set_proxy_url(Some(upub::url!(ctx, "/fetch")))
|
||||
));
|
||||
|
||||
if auth.is(&uid) {
|
||||
|
|
|
@ -22,7 +22,7 @@ pub async fn get(
|
|||
.count(ctx.db())
|
||||
.await?;
|
||||
|
||||
crate::builders::collection(&upub::url!(ctx, "/actors/{id}/notifications"), Some(count))
|
||||
crate::builders::collection(upub::url!(ctx, "/actors/{id}/notifications"), Some(count))
|
||||
}
|
||||
|
||||
pub async fn page(
|
||||
|
|
|
@ -9,7 +9,7 @@ pub async fn get(
|
|||
State(ctx): State<Context>,
|
||||
Path(id): Path<String>,
|
||||
) -> crate::ApiResult<JsonLD<serde_json::Value>> {
|
||||
crate::builders::collection(&upub::url!(ctx, "/actors/{id}/outbox"), None)
|
||||
crate::builders::collection(upub::url!(ctx, "/actors/{id}/outbox"), None)
|
||||
}
|
||||
|
||||
pub async fn page(
|
||||
|
|
|
@ -22,21 +22,21 @@ pub async fn view(
|
|||
}
|
||||
Ok(JsonLD(
|
||||
apb::new()
|
||||
.set_id(Some(&upub::url!(ctx, "")))
|
||||
.set_id(Some(upub::url!(ctx, "")))
|
||||
.set_actor_type(Some(apb::ActorType::Application))
|
||||
.set_name(Some(&ctx.cfg().instance.name))
|
||||
.set_summary(Some(&ctx.cfg().instance.description))
|
||||
.set_name(Some(ctx.cfg().instance.name.clone()))
|
||||
.set_summary(Some(ctx.cfg().instance.description.clone()))
|
||||
.set_inbox(apb::Node::link(upub::url!(ctx, "/inbox")))
|
||||
.set_outbox(apb::Node::link(upub::url!(ctx, "/outbox")))
|
||||
.set_published(Some(ctx.actor().published))
|
||||
.set_endpoints(apb::Node::Empty)
|
||||
.set_preferred_username(Some(ctx.domain()))
|
||||
.set_preferred_username(Some(ctx.domain().to_string()))
|
||||
.set_url(apb::Node::link(upub::url!(ctx, "/")))
|
||||
.set_public_key(apb::Node::object(
|
||||
apb::new()
|
||||
.set_id(Some(&upub::url!(ctx, "#main-key")))
|
||||
.set_owner(Some(&upub::url!(ctx, "")))
|
||||
.set_public_key_pem(&ctx.actor().public_key)
|
||||
.set_id(Some(upub::url!(ctx, "#main-key")))
|
||||
.set_owner(Some(upub::url!(ctx, "")))
|
||||
.set_public_key_pem(ctx.actor().public_key.clone())
|
||||
))
|
||||
.ld_context()
|
||||
).into_response())
|
||||
|
|
|
@ -11,7 +11,7 @@ use super::Pagination;
|
|||
pub async fn get(
|
||||
State(ctx): State<Context>,
|
||||
) -> crate::ApiResult<JsonLD<serde_json::Value>> {
|
||||
crate::builders::collection(&upub::url!(ctx, "/inbox"), None)
|
||||
crate::builders::collection(upub::url!(ctx, "/inbox"), None)
|
||||
}
|
||||
|
||||
pub async fn page(
|
||||
|
|
|
@ -17,7 +17,7 @@ pub async fn get(
|
|||
.count(ctx.db())
|
||||
.await?;
|
||||
|
||||
crate::builders::collection(&upub::url!(ctx, "/objects/{id}/context"), Some(count))
|
||||
crate::builders::collection(upub::url!(ctx, "/objects/{id}/context"), Some(count))
|
||||
}
|
||||
|
||||
pub async fn page(
|
||||
|
|
|
@ -55,7 +55,7 @@ pub async fn view(
|
|||
|
||||
replies = apb::Node::object(
|
||||
apb::new()
|
||||
.set_id(Some(&upub::url!(ctx, "/objects/{id}/replies")))
|
||||
.set_id(Some(upub::url!(ctx, "/objects/{id}/replies")))
|
||||
.set_first(apb::Node::link(upub::url!(ctx, "/objects/{id}/replies/page")))
|
||||
.set_collection_type(Some(apb::CollectionType::Collection))
|
||||
.set_total_items(item.object.as_ref().map(|x| x.replies as u64))
|
||||
|
|
|
@ -32,7 +32,7 @@ pub async fn get(
|
|||
|
||||
Ok(JsonLD(
|
||||
apb::new()
|
||||
.set_id(Some(&upub::url!(ctx, "/objects/{id}/replies")))
|
||||
.set_id(Some(upub::url!(ctx, "/objects/{id}/replies")))
|
||||
.set_collection_type(Some(apb::CollectionType::Collection))
|
||||
.set_first(apb::Node::link(upub::url!(ctx, "/objects/{id}/replies/page")))
|
||||
.set_total_items(Some(replies_ids.len() as u64))
|
||||
|
|
|
@ -5,7 +5,7 @@ use upub::Context;
|
|||
use crate::{activitypub::{CreationResult, Pagination}, AuthIdentity, builders::JsonLD};
|
||||
|
||||
pub async fn get(State(ctx): State<Context>) -> crate::ApiResult<JsonLD<serde_json::Value>> {
|
||||
crate::builders::collection(&upub::url!(ctx, "/outbox"), None)
|
||||
crate::builders::collection(upub::url!(ctx, "/outbox"), None)
|
||||
}
|
||||
|
||||
pub async fn page(
|
||||
|
|
|
@ -10,7 +10,7 @@ pub async fn get(
|
|||
Path(id): Path<String>,
|
||||
) -> crate::ApiResult<JsonLD<serde_json::Value>> {
|
||||
crate::builders::collection(
|
||||
&upub::url!(ctx, "/tags/{id}"),
|
||||
upub::url!(ctx, "/tags/{id}"),
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ pub fn collection_page(id: &str, offset: u64, limit: u64, items: Vec<serde_json:
|
|||
};
|
||||
Ok(JsonLD(
|
||||
apb::new()
|
||||
.set_id(Some(&format!("{id}?offset={offset}")))
|
||||
.set_id(Some(format!("{id}?offset={offset}")))
|
||||
.set_collection_type(Some(apb::CollectionType::OrderedCollectionPage))
|
||||
.set_part_of(apb::Node::link(id.replace("/page", "")))
|
||||
.set_ordered_items(apb::Node::array(items))
|
||||
|
@ -73,13 +73,13 @@ pub fn collection_page(id: &str, offset: u64, limit: u64, items: Vec<serde_json:
|
|||
}
|
||||
|
||||
|
||||
pub fn collection(id: &str, total_items: Option<u64>) -> crate::ApiResult<JsonLD<serde_json::Value>> {
|
||||
pub fn collection(id: String, total_items: Option<u64>) -> crate::ApiResult<JsonLD<serde_json::Value>> {
|
||||
Ok(JsonLD(
|
||||
apb::new()
|
||||
.set_id(Some(id))
|
||||
.set_collection_type(Some(apb::CollectionType::OrderedCollection))
|
||||
.set_first(apb::Node::link(format!("{id}/page")))
|
||||
.set_total_items(total_items)
|
||||
.set_id(Some(id))
|
||||
.ld_context()
|
||||
))
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use apb::{field::OptionalString, target::Addressed, Activity, ActivityMut, Base, BaseMut, Object, ObjectMut};
|
||||
use apb::{target::Addressed, Activity, ActivityMut, Base, BaseMut, Object, ObjectMut, Shortcuts};
|
||||
use sea_orm::{prelude::Expr, ColumnTrait, DbErr, EntityTrait, QueryFilter, QueryOrder, QuerySelect, SelectColumns, TransactionTrait};
|
||||
use upub::{model::{self, actor::Field}, traits::{process::ProcessorError, Addresser, Processor}, Context};
|
||||
|
||||
|
@ -17,7 +17,7 @@ pub async fn process(ctx: Context, job: &model::job::Model) -> crate::JobResult<
|
|||
let actor = upub::model::actor::Entity::ap_to_internal(&job.actor, &tx)
|
||||
.await?
|
||||
.ok_or_else(|| DbErr::RecordNotFound(job.actor.clone()))?;
|
||||
let activity = upub::model::activity::Entity::ap_to_internal(activity.object().id()?, &tx)
|
||||
let activity = upub::model::activity::Entity::ap_to_internal(&activity.object().id()?, &tx)
|
||||
.await?
|
||||
.ok_or_else(|| DbErr::RecordNotFound(activity.object().id().unwrap_or_default().to_string()))?;
|
||||
upub::model::notification::Entity::update_many()
|
||||
|
@ -41,14 +41,14 @@ pub async fn process(ctx: Context, job: &model::job::Model) -> crate::JobResult<
|
|||
}
|
||||
|
||||
activity = activity
|
||||
.set_id(Some(&job.activity))
|
||||
.set_id(Some(job.activity.clone()))
|
||||
.set_actor(apb::Node::link(job.actor.clone()))
|
||||
.set_published(Some(now));
|
||||
|
||||
if matches!(t, apb::ObjectType::Activity(apb::ActivityType::Undo)) {
|
||||
let mut undone = activity.object().into_inner()?;
|
||||
if undone.id().is_err() {
|
||||
let undone_target = undone.object().id().str().ok_or(crate::JobError::MissingPayload)?;
|
||||
let undone_target = undone.object().id()?;
|
||||
let undone_type = undone.activity_type().map_err(|_| crate::JobError::MissingPayload)?;
|
||||
let undone_model = model::activity::Entity::find()
|
||||
.filter(model::activity::Column::Object.eq(&undone_target))
|
||||
|
@ -59,7 +59,7 @@ pub async fn process(ctx: Context, job: &model::job::Model) -> crate::JobResult<
|
|||
.await?
|
||||
.ok_or_else(|| sea_orm::DbErr::RecordNotFound(format!("actor={},type={},object={}",job.actor, undone_type, undone_target)))?;
|
||||
undone = undone
|
||||
.set_id(Some(&undone_model.id))
|
||||
.set_id(Some(undone_model.id))
|
||||
.set_actor(apb::Node::link(job.actor.clone()));
|
||||
}
|
||||
activity = activity.set_object(apb::Node::object(undone));
|
||||
|
@ -67,7 +67,7 @@ pub async fn process(ctx: Context, job: &model::job::Model) -> crate::JobResult<
|
|||
|
||||
macro_rules! update {
|
||||
($prev:ident, $field:ident, $getter:expr) => {
|
||||
if let Some($field) = $getter {
|
||||
if let Ok($field) = $getter {
|
||||
$prev.$field = Some($field.to_string());
|
||||
}
|
||||
};
|
||||
|
@ -77,7 +77,7 @@ pub async fn process(ctx: Context, job: &model::job::Model) -> crate::JobResult<
|
|||
let mut updated = activity.object().into_inner()?;
|
||||
match updated.object_type()? {
|
||||
apb::ObjectType::Actor(_) => {
|
||||
let mut prev = model::actor::Entity::find_by_ap_id(updated.id()?)
|
||||
let mut prev = model::actor::Entity::find_by_ap_id(&updated.id()?)
|
||||
.one(&tx)
|
||||
.await?
|
||||
.ok_or_else(|| crate::JobError::MissingPayload)?;
|
||||
|
@ -86,10 +86,10 @@ pub async fn process(ctx: Context, job: &model::job::Model) -> crate::JobResult<
|
|||
return Err(crate::JobError::Forbidden);
|
||||
}
|
||||
|
||||
update!(prev, name, updated.name().ok());
|
||||
update!(prev, summary, updated.summary().ok());
|
||||
update!(prev, icon, updated.icon().get().and_then(|x| x.url().id().str()));
|
||||
update!(prev, image, updated.image().get().and_then(|x| x.url().id().str()));
|
||||
update!(prev, name, updated.name());
|
||||
update!(prev, summary, updated.summary());
|
||||
update!(prev, icon, updated.icon_url());
|
||||
update!(prev, image, updated.image_url());
|
||||
|
||||
if !updated.attachment().is_empty() {
|
||||
prev.fields = updated.attachment()
|
||||
|
@ -104,7 +104,7 @@ pub async fn process(ctx: Context, job: &model::job::Model) -> crate::JobResult<
|
|||
updated = prev.ap();
|
||||
},
|
||||
apb::ObjectType::Note => {
|
||||
let mut prev = model::object::Entity::find_by_ap_id(updated.id()?)
|
||||
let mut prev = model::object::Entity::find_by_ap_id(&updated.id()?)
|
||||
.one(&tx)
|
||||
.await?
|
||||
.ok_or_else(|| crate::JobError::MissingPayload)?;
|
||||
|
@ -113,10 +113,10 @@ pub async fn process(ctx: Context, job: &model::job::Model) -> crate::JobResult<
|
|||
return Err(crate::JobError::Forbidden);
|
||||
}
|
||||
|
||||
update!(prev, name, updated.name().ok());
|
||||
update!(prev, summary, updated.summary().ok());
|
||||
update!(prev, content, updated.content().ok());
|
||||
update!(prev, image, updated.image().get().and_then(|x| x.url().id().str()));
|
||||
update!(prev, name, updated.name());
|
||||
update!(prev, summary, updated.summary());
|
||||
update!(prev, content, updated.content());
|
||||
update!(prev, image, updated.image_url());
|
||||
|
||||
if let Ok(sensitive) = updated.sensitive() {
|
||||
prev.sensitive = sensitive;
|
||||
|
@ -158,8 +158,8 @@ pub async fn process(ctx: Context, job: &model::job::Model) -> crate::JobResult<
|
|||
activity = activity
|
||||
.set_object(apb::Node::object(
|
||||
object
|
||||
.set_id(Some(&oid))
|
||||
.set_content(content.as_deref())
|
||||
.set_id(Some(oid))
|
||||
.set_content(content)
|
||||
.set_attributed_to(apb::Node::link(job.actor.clone()))
|
||||
.set_published(Some(now))
|
||||
.set_updated(Some(now))
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
use leptos::*;
|
||||
use crate::prelude::*;
|
||||
|
||||
use apb::{field::OptionalString, target::Addressed, Activity, ActivityMut, Base, Object};
|
||||
use apb::{target::Addressed, Activity, ActivityMut, Base, Object};
|
||||
|
||||
|
||||
#[component]
|
||||
pub fn ActivityLine(activity: crate::Object, children: Children) -> impl IntoView {
|
||||
let object_id = activity.object().id().str().unwrap_or_default();
|
||||
let object_id = activity.object().id().unwrap_or_default();
|
||||
let activity_url = activity.id().map(|x| view! {
|
||||
<sup><small><a class="clean ml-s" href={x.to_string()} target="_blank">"↗"</a></small></sup>
|
||||
});
|
||||
let actor_id = activity.actor().id().str().unwrap_or_default();
|
||||
let actor_id = activity.actor().id().unwrap_or_default();
|
||||
let actor = cache::OBJECTS.get_or(&actor_id, serde_json::Value::String(actor_id.clone()).into());
|
||||
let kind = activity.activity_type().unwrap_or(apb::ActivityType::Activity);
|
||||
let href = match kind {
|
||||
|
@ -60,7 +60,7 @@ pub fn Item(
|
|||
Some(view! { <Object object=item.clone() />{sep.clone()} }.into_view()),
|
||||
// everything else
|
||||
apb::ObjectType::Activity(t) => {
|
||||
let object_id = item.object().id().str().unwrap_or_default();
|
||||
let object_id = item.object().id().unwrap_or_default();
|
||||
let object = match t {
|
||||
apb::ActivityType::Create | apb::ActivityType::Announce =>
|
||||
cache::OBJECTS.get(&object_id).map(|obj| {
|
||||
|
|
|
@ -2,7 +2,7 @@ use leptos::*;
|
|||
use leptos_router::*;
|
||||
use crate::{getters::Getter, prelude::*, FALLBACK_IMAGE_URL};
|
||||
|
||||
use apb::{field::OptionalString, ActivityMut, Actor, Base, Object, ObjectMut};
|
||||
use apb::{ActivityMut, Actor, Base, Object, ObjectMut, Shortcuts};
|
||||
|
||||
#[component]
|
||||
pub fn ActorHeader() -> impl IntoView {
|
||||
|
@ -16,7 +16,7 @@ pub fn ActorHeader() -> impl IntoView {
|
|||
Some(x) => Some(x.clone()),
|
||||
None => {
|
||||
let user = cache::OBJECTS.resolve(&id, U::Actor, auth).await?;
|
||||
if let Some(url) = user.url().id().str() {
|
||||
if let Ok(url) = user.url().id() {
|
||||
cache::WEBFINGER.store(&url, user.id().unwrap_or_default().to_string());
|
||||
}
|
||||
Some(user)
|
||||
|
@ -29,10 +29,10 @@ pub fn ActorHeader() -> impl IntoView {
|
|||
None => view! { <Loader /> }.into_view(),
|
||||
Some(None) => view! { <code class="center cw color">"could not resolve user"</code> }.into_view(),
|
||||
Some(Some(actor)) => {
|
||||
let avatar_url = actor.icon().get().map(|x| x.url().id().str().unwrap_or(FALLBACK_IMAGE_URL.into())).unwrap_or(FALLBACK_IMAGE_URL.into());
|
||||
let background_url = actor.image().get().map(|x| x.url().id().str().unwrap_or(FALLBACK_IMAGE_URL.into())).unwrap_or(FALLBACK_IMAGE_URL.into());
|
||||
let avatar_url = actor.icon_url().unwrap_or(FALLBACK_IMAGE_URL.into());
|
||||
let background_url = actor.image_url().unwrap_or(FALLBACK_IMAGE_URL.into());
|
||||
let username = actor.preferred_username().unwrap_or_default().to_string();
|
||||
let name = actor.name().str().unwrap_or(username.clone());
|
||||
let name = actor.name().unwrap_or(username.clone());
|
||||
let created = actor.published().ok();
|
||||
let following_me = actor.following_me().unwrap_or(false);
|
||||
let followed_by_me = actor.followed_by_me().unwrap_or(false);
|
||||
|
@ -44,11 +44,11 @@ pub fn ActorHeader() -> impl IntoView {
|
|||
let fields = actor.attachment()
|
||||
.flat()
|
||||
.into_iter()
|
||||
.filter_map(|x| x.extract())
|
||||
.filter_map(|x| x.into_inner().ok())
|
||||
.map(|x| view! {
|
||||
<tr>
|
||||
<td class="w-25"><b class="color">{x.name().str().unwrap_or_default()}</b></td>
|
||||
<td class="w-75" inner_html={mdhtml::safe_html(x.value().unwrap_or_default())}></td>
|
||||
<td class="w-25"><b class="color">{x.name().unwrap_or_default()}</b></td>
|
||||
<td class="w-75" inner_html={mdhtml::safe_html(&x.value().unwrap_or_default())}></td>
|
||||
</tr>
|
||||
})
|
||||
.collect_view();
|
||||
|
@ -110,7 +110,7 @@ pub fn ActorHeader() -> impl IntoView {
|
|||
}}
|
||||
</div>
|
||||
</div>
|
||||
<p class="mb-2 mt-0 center bio" inner_html={mdhtml::safe_html(actor.summary().unwrap_or_default())}></p>
|
||||
<p class="mb-2 mt-0 center bio" inner_html={mdhtml::safe_html(&actor.summary().unwrap_or_default())}></p>
|
||||
<p class="center">
|
||||
<table class="fields center w-100 pa-s" style="margin: auto; table-layout: fixed;">{fields}</table>
|
||||
</p>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use apb::{field::OptionalString, ActivityMut, Base, BaseMut, Object, ObjectMut};
|
||||
use apb::{ActivityMut, Base, BaseMut, Object, ObjectMut};
|
||||
|
||||
use leptos::*;
|
||||
use crate::prelude::*;
|
||||
|
@ -12,7 +12,7 @@ pub struct ReplyControls {
|
|||
impl ReplyControls {
|
||||
pub fn reply(&self, oid: &str) {
|
||||
if let Some(obj) = cache::OBJECTS.get(oid) {
|
||||
self.context.set(obj.context().id().str());
|
||||
self.context.set(obj.context().id().ok());
|
||||
self.reply_to.set(obj.id().ok().map(|x| x.to_string()));
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ impl ReplyControls {
|
|||
}
|
||||
|
||||
fn post_author(post_id: &str) -> Option<crate::Object> {
|
||||
let usr = cache::OBJECTS.get(post_id)?.attributed_to().id().str()?;
|
||||
let usr = cache::OBJECTS.get(post_id)?.attributed_to().id().ok()?;
|
||||
cache::OBJECTS.get(&usr)
|
||||
}
|
||||
|
||||
|
@ -135,9 +135,9 @@ pub fn PostBox(advanced: WriteSignal<bool>) -> impl IntoView {
|
|||
.into_iter()
|
||||
.map(|x| {
|
||||
use apb::LinkMut;
|
||||
LinkMut::set_name(apb::new(), Some(&format!("@{}@{}", x.name, x.domain))) // TODO ewww but name clashes
|
||||
LinkMut::set_name(apb::new(), Some(format!("@{}@{}", x.name, x.domain))) // TODO ewww but name clashes
|
||||
.set_link_type(Some(apb::LinkType::Mention))
|
||||
.set_href(Some(&x.href))
|
||||
.set_href(Some(x.href))
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -146,10 +146,10 @@ pub fn PostBox(advanced: WriteSignal<bool>) -> impl IntoView {
|
|||
if let Ok(uid) = au.id() {
|
||||
to_vec.push(uid.to_string());
|
||||
if let Ok(name) = au.name() {
|
||||
let domain = Uri::domain(uid);
|
||||
let domain = Uri::domain(&uid);
|
||||
mention_tags.push({
|
||||
use apb::LinkMut;
|
||||
LinkMut::set_name(apb::new(), Some(&format!("@{}@{}", name, domain))) // TODO ewww but name clashes
|
||||
LinkMut::set_name(apb::new(), Some(format!("@{}@{}", name, domain))) // TODO ewww but name clashes
|
||||
.set_link_type(Some(apb::LinkType::Mention))
|
||||
.set_href(Some(uid))
|
||||
});
|
||||
|
@ -162,8 +162,8 @@ pub fn PostBox(advanced: WriteSignal<bool>) -> impl IntoView {
|
|||
}
|
||||
let payload = apb::new()
|
||||
.set_object_type(Some(apb::ObjectType::Note))
|
||||
.set_summary(summary.as_deref())
|
||||
.set_content(Some(&content))
|
||||
.set_summary(summary)
|
||||
.set_content(Some(content))
|
||||
.set_context(apb::Node::maybe_link(reply.context.get()))
|
||||
.set_in_reply_to(apb::Node::maybe_link(reply.reply_to.get()))
|
||||
.set_to(apb::Node::links(to_vec))
|
||||
|
@ -299,11 +299,11 @@ pub fn AdvancedPostBox(advanced: WriteSignal<bool>) -> impl IntoView {
|
|||
if embedded.get() {
|
||||
apb::Node::object(
|
||||
serde_json::Value::Object(serde_json::Map::default())
|
||||
.set_id(object_id.as_deref())
|
||||
.set_id(object_id)
|
||||
.set_object_type(Some(apb::ObjectType::Note))
|
||||
.set_name(name.as_deref())
|
||||
.set_summary(summary.as_deref())
|
||||
.set_content(content.as_deref())
|
||||
.set_name(name)
|
||||
.set_summary(summary)
|
||||
.set_content(content)
|
||||
.set_in_reply_to(apb::Node::maybe_link(reply))
|
||||
.set_context(apb::Node::maybe_link(context))
|
||||
.set_to(apb::Node::links(to))
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use leptos::*;
|
||||
use crate::{prelude::*, FALLBACK_IMAGE_URL};
|
||||
|
||||
use apb::{field::OptionalString, Activity, ActivityMut, Actor, Base, Object, ObjectMut};
|
||||
use apb::{Activity, ActivityMut, Actor, Base, Object, ObjectMut, Shortcuts};
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref REGEX: regex::Regex = regex::Regex::new(r":\w+:").expect("failed compiling custom emoji regex");
|
||||
|
@ -12,7 +12,7 @@ pub fn ActorStrip(object: crate::Object) -> impl IntoView {
|
|||
let actor_id = object.id().unwrap_or_default().to_string();
|
||||
let username = object.preferred_username().unwrap_or_default().to_string();
|
||||
let domain = object.id().unwrap_or_default().replace("https://", "").split('/').next().unwrap_or_default().to_string();
|
||||
let avatar = object.icon().get().map(|x| x.url().id().str().unwrap_or(FALLBACK_IMAGE_URL.into())).unwrap_or(FALLBACK_IMAGE_URL.into());
|
||||
let avatar = object.icon_url().unwrap_or(FALLBACK_IMAGE_URL.into());
|
||||
view! {
|
||||
<a href={Uri::web(U::Actor, &actor_id)} class="clean hover">
|
||||
<img src={avatar} class="avatar inline mr-s" onerror={format!("this.onerror=null; this.src='{FALLBACK_IMAGE_URL}';")} /><b>{username}</b><small>@{domain}</small>
|
||||
|
@ -29,7 +29,7 @@ pub fn ActorBanner(object: crate::Object) -> impl IntoView {
|
|||
serde_json::Value::Object(_) => {
|
||||
let uid = object.id().unwrap_or_default().to_string();
|
||||
let uri = Uri::web(U::Actor, &uid);
|
||||
let avatar_url = object.icon().get().map(|x| x.url().id().str().unwrap_or(FALLBACK_IMAGE_URL.into())).unwrap_or(FALLBACK_IMAGE_URL.into());
|
||||
let avatar_url = object.icon_url().unwrap_or(FALLBACK_IMAGE_URL.into());
|
||||
let username = object.preferred_username().unwrap_or_default().to_string();
|
||||
let domain = object.id().unwrap_or_default().replace("https://", "").split('/').next().unwrap_or_default().to_string();
|
||||
let display_name = object.name().unwrap_or_default().to_string();
|
||||
|
@ -70,7 +70,7 @@ pub fn FollowRequestButtons(activity_id: String, actor_id: String) -> impl IntoV
|
|||
// TODO lmao what is going on with this double move / triple clone ???????????
|
||||
let _activity_id = activity_id.clone();
|
||||
let _actor_id = actor_id.clone();
|
||||
let from_actor = cache::OBJECTS.get(&activity_id).map(|x| x.actor().id().str().unwrap_or_default()).unwrap_or_default();
|
||||
let from_actor = cache::OBJECTS.get(&activity_id).and_then(|x| x.actor().id().ok()).unwrap_or_default();
|
||||
let _from_actor = from_actor.clone();
|
||||
if actor_id == auth.user_id() {
|
||||
Some(view! {
|
||||
|
|
|
@ -66,7 +66,7 @@ impl FiltersConfig {
|
|||
let mut reply_filter = true;
|
||||
|
||||
if let Ok(obj_id) = item.object().id() {
|
||||
if let Some(obj) = crate::cache::OBJECTS.get(obj_id) {
|
||||
if let Some(obj) = crate::cache::OBJECTS.get(&obj_id) {
|
||||
if obj.in_reply_to().id().is_ok() {
|
||||
reply_filter = self.replies;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use leptos::*;
|
|||
use crate::{prelude::*, URL_SENSITIVE};
|
||||
|
||||
use base64::prelude::*;
|
||||
use apb::{field::OptionalString, Document, Object};
|
||||
use apb::{Document, Object};
|
||||
|
||||
fn uncloak(txt: Option<&str>) -> Option<String> {
|
||||
let decoded = BASE64_URL_SAFE.decode(txt?).ok()?;
|
||||
|
@ -17,11 +17,10 @@ pub fn Attachment(
|
|||
) -> impl IntoView {
|
||||
let config = use_context::<Signal<crate::Config>>().expect("missing config context");
|
||||
let (expand, set_expand) = create_signal(false);
|
||||
let href = object.url().id().str().unwrap_or_default();
|
||||
let href = object.url().id().ok().unwrap_or_default();
|
||||
let uncloaked = uncloak(href.split('/').last()).unwrap_or_default();
|
||||
let media_type = object.media_type()
|
||||
.unwrap_or("link") // TODO make it an Option rather than defaulting to link everywhere
|
||||
.to_string();
|
||||
.unwrap_or("link".to_string()); // TODO make it an Option rather than defaulting to link everywhere
|
||||
let mut kind = media_type
|
||||
.split('/')
|
||||
.next()
|
||||
|
|
|
@ -3,29 +3,26 @@ use std::sync::Arc;
|
|||
use leptos::*;
|
||||
use crate::{prelude::*, URL_SENSITIVE};
|
||||
|
||||
use apb::{field::OptionalString, target::Addressed, ActivityMut, Base, Collection, CollectionMut, Object, ObjectMut};
|
||||
use apb::{target::Addressed, ActivityMut, Base, Collection, CollectionMut, Object, ObjectMut};
|
||||
|
||||
#[component]
|
||||
pub fn Object(object: crate::Object) -> impl IntoView {
|
||||
let oid = object.id().unwrap_or_default().to_string();
|
||||
let author_id = object.attributed_to().id().str().unwrap_or_default();
|
||||
let author_id = object.attributed_to().id().ok().unwrap_or_default();
|
||||
let author = cache::OBJECTS.get_or(&author_id, serde_json::Value::String(author_id.clone()).into());
|
||||
let sensitive = object.sensitive().unwrap_or_default();
|
||||
let addressed = object.addressed();
|
||||
let public = addressed.iter().any(|x| x.as_str() == apb::target::PUBLIC);
|
||||
let external_url = object.url().id().str().unwrap_or_else(|| oid.clone());
|
||||
let external_url = object.url().id().ok().unwrap_or_else(|| oid.clone());
|
||||
let attachments = object.attachment()
|
||||
.flat()
|
||||
.into_iter()
|
||||
.filter_map(|x| x.extract()) // TODO maybe show links?
|
||||
.filter_map(|x| x.into_inner().ok()) // TODO maybe show links?
|
||||
.map(|x| view! { <Attachment object=x sensitive=sensitive /> })
|
||||
.collect_view();
|
||||
let comments = object.replies().get()
|
||||
.map_or(0, |x| x.total_items().unwrap_or(0));
|
||||
let shares = object.shares().get()
|
||||
.map_or(0, |x| x.total_items().unwrap_or(0));
|
||||
let likes = object.likes().get()
|
||||
.map_or(0, |x| x.total_items().unwrap_or(0));
|
||||
let comments = object.replies().inner().and_then(|x| x.total_items()).unwrap_or_default();
|
||||
let shares = object.shares().inner().and_then(|x| x.total_items()).unwrap_or_default();
|
||||
let likes = object.likes().inner().and_then(|x| x.total_items()).unwrap_or_default();
|
||||
let already_liked = object.liked_by_me().unwrap_or(false);
|
||||
|
||||
let attachments_padding = if object.attachment().is_empty() {
|
||||
|
@ -34,9 +31,9 @@ pub fn Object(object: crate::Object) -> impl IntoView {
|
|||
Some(view! { <div class="pb-1"></div> })
|
||||
};
|
||||
|
||||
let content = mdhtml::safe_html(object.content().unwrap_or_default());
|
||||
let content = mdhtml::safe_html(&object.content().unwrap_or_default());
|
||||
|
||||
let audience_badge = object.audience().id().str()
|
||||
let audience_badge = object.audience().id().ok()
|
||||
.map(|x| {
|
||||
// TODO this isn't guaranteed to work every time...
|
||||
let name = x.split('/').last().unwrap_or_default().to_string();
|
||||
|
@ -56,7 +53,7 @@ pub fn Object(object: crate::Object) -> impl IntoView {
|
|||
.id()
|
||||
.ok()
|
||||
.map(|x| {
|
||||
let href = Uri::web(U::Object, x);
|
||||
let href = Uri::web(U::Object, &x);
|
||||
view! {
|
||||
<a class="clean dim" href={href}>
|
||||
<span class="border-button ml-s" >
|
||||
|
@ -103,7 +100,7 @@ pub fn Object(object: crate::Object) -> impl IntoView {
|
|||
uid.replace("https://", "").replace("http://", "").split('/').next().unwrap_or_default().to_string(),
|
||||
)
|
||||
};
|
||||
let href = Uri::web(U::Actor, uid);
|
||||
let href = Uri::web(U::Actor, &uid);
|
||||
Some(view! {
|
||||
<a class="clean dim" href={href}>
|
||||
<span class="border-button ml-s" title={format!("@{username}@{domain}")} >
|
||||
|
@ -119,7 +116,7 @@ pub fn Object(object: crate::Object) -> impl IntoView {
|
|||
}
|
||||
}).collect_view();
|
||||
|
||||
let post_image = object.image().get().and_then(|x| x.url().id().str()).map(|x| {
|
||||
let post_image = object.image().inner().and_then(|x| x.url().id()).ok().map(|x| {
|
||||
let (expand, set_expand) = create_signal(false);
|
||||
view! {
|
||||
<img
|
||||
|
@ -180,11 +177,11 @@ pub fn Object(object: crate::Object) -> impl IntoView {
|
|||
<tr>
|
||||
<td><ActorBanner object=author /></td>
|
||||
<td class="rev" >
|
||||
{object.in_reply_to().id().str().map(|reply| view! {
|
||||
{object.in_reply_to().id().ok().map(|reply| view! {
|
||||
<small><i><a class="clean" href={Uri::web(U::Object, &reply)} title={reply}>reply</a></i></small>
|
||||
})}
|
||||
<PrivacyMarker addressed=addressed />
|
||||
<a class="clean hover ml-s" href={Uri::web(U::Object, object.id().unwrap_or_default())}>
|
||||
<a class="clean hover ml-s" href={Uri::web(U::Object, &object.id().unwrap_or_default())}>
|
||||
<DateTime t=object.published().ok() />
|
||||
</a>
|
||||
<sup><small><a class="clean ml-s" href={external_url} target="_blank">"↗"</a></small></sup>
|
||||
|
@ -262,7 +259,7 @@ pub fn LikeButton(
|
|||
set_count.set(count.get() + 1);
|
||||
if let Some(cached) = cache::OBJECTS.get(&target) {
|
||||
let mut new = (*cached).clone().set_liked_by_me(Some(true));
|
||||
if let Some(likes) = new.likes().get() {
|
||||
if let Ok(likes) = new.likes().inner() {
|
||||
if let Ok(count) = likes.total_items() {
|
||||
new = new.set_likes(apb::Node::object(likes.clone().set_total_items(Some(count + 1))));
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ pub fn ObjectView() -> impl IntoView {
|
|||
move |oid| async move {
|
||||
let obj = cache::OBJECTS.resolve(&oid, U::Object, auth).await?;
|
||||
if let Ok(author) = obj.attributed_to().id() {
|
||||
cache::OBJECTS.resolve(author, U::Actor, auth).await;
|
||||
cache::OBJECTS.resolve(&author, U::Actor, auth).await;
|
||||
}
|
||||
Some(obj)
|
||||
|
||||
|
@ -36,8 +36,8 @@ pub fn ObjectView() -> impl IntoView {
|
|||
Some(Some(o)) => {
|
||||
let object = o.clone();
|
||||
let oid = o.id().unwrap_or_default();
|
||||
let base = Uri::web(U::Object, oid);
|
||||
let api = Uri::api(U::Object, oid, false);
|
||||
let base = Uri::web(U::Object, &oid);
|
||||
let api = Uri::api(U::Object, &oid, false);
|
||||
view!{
|
||||
<Object object=object />
|
||||
<hr class="color ma-2" />
|
||||
|
|
|
@ -21,10 +21,15 @@ pub fn ConfigPage(setter: WriteSignal<crate::Config>) -> impl IntoView {
|
|||
let banner_url_ref: NodeRef<html::Input> = create_node_ref();
|
||||
|
||||
let myself = cache::OBJECTS.get(&auth.userid.get_untracked().unwrap_or_default());
|
||||
let curr_display_name = myself.as_ref().and_then(|x| Some(x.name().ok()?.to_string())).unwrap_or_default();
|
||||
let curr_summary = myself.as_ref().and_then(|x| Some(x.summary().ok()?.to_string())).unwrap_or_default();
|
||||
let curr_icon = myself.as_ref().and_then(|x| Some(x.icon().get()?.url().id().ok()?.to_string())).unwrap_or_default();
|
||||
let curr_banner = myself.as_ref().and_then(|x| Some(x.image().get()?.url().id().ok()?.to_string())).unwrap_or_default();
|
||||
let (curr_display_name, curr_summary, curr_icon, curr_banner) = match myself.as_ref() {
|
||||
None => (String::default(), String::default(), String::default(), String::default()),
|
||||
Some(myself) => (
|
||||
myself.name().unwrap_or_default().to_string(),
|
||||
myself.summary().unwrap_or_default().to_string(),
|
||||
myself.icon().inner().and_then(|x| Ok(x.url().id()?.to_string())).unwrap_or_default(),
|
||||
myself.image().inner().and_then(|x| Ok(x.url().id()?.to_string())).unwrap_or_default(),
|
||||
),
|
||||
};
|
||||
|
||||
macro_rules! get_cfg {
|
||||
(filter $field:ident) => {
|
||||
|
@ -175,8 +180,8 @@ pub fn ConfigPage(setter: WriteSignal<crate::Config>) -> impl IntoView {
|
|||
.set_to(apb::Node::links(vec![apb::target::PUBLIC.to_string(), format!("{id}/followers")]))
|
||||
.set_object(apb::Node::object(
|
||||
(*me).clone()
|
||||
.set_name(display_name.as_deref())
|
||||
.set_summary(summary.as_deref())
|
||||
.set_name(display_name)
|
||||
.set_summary(summary)
|
||||
.set_icon(apb::Node::maybe_object(avatar))
|
||||
.set_image(apb::Node::maybe_object(banner))
|
||||
.set_published(Some(chrono::Utc::now()))
|
||||
|
|
|
@ -41,7 +41,7 @@ pub fn SearchPage() -> impl IntoView {
|
|||
.ordered_items()
|
||||
.flat()
|
||||
.into_iter()
|
||||
.filter_map(|x| x.extract())
|
||||
.filter_map(|x| x.into_inner().ok())
|
||||
.collect(),
|
||||
auth
|
||||
).await
|
||||
|
|
|
@ -3,7 +3,7 @@ pub mod thread;
|
|||
|
||||
use std::{collections::BTreeSet, pin::Pin, sync::Arc};
|
||||
|
||||
use apb::{field::OptionalString, Activity, ActivityMut, Actor, Base, Object};
|
||||
use apb::{Activity, ActivityMut, Actor, Base, Object};
|
||||
use leptos::*;
|
||||
use crate::prelude::*;
|
||||
|
||||
|
@ -89,7 +89,7 @@ impl Timeline {
|
|||
.ordered_items()
|
||||
.flat()
|
||||
.into_iter()
|
||||
.filter_map(|x| x.extract())
|
||||
.filter_map(|x| x.into_inner().ok())
|
||||
.collect();
|
||||
|
||||
let mut feed = self.feed.get_untracked();
|
||||
|
@ -121,18 +121,18 @@ pub async fn process_activities(activities: Vec<serde_json::Value>, auth: Auth)
|
|||
for activity in activities {
|
||||
let activity_type = activity.activity_type().unwrap_or(apb::ActivityType::Activity);
|
||||
// save embedded object if present
|
||||
if let Some(object) = activity.object().get() {
|
||||
if let Ok(object) = activity.object().inner() {
|
||||
// also fetch actor attributed to
|
||||
if let Some(attributed_to) = object.attributed_to().id().str() {
|
||||
if let Ok(attributed_to) = object.attributed_to().id() {
|
||||
actors_seen.insert(attributed_to);
|
||||
}
|
||||
if let Ok(object_uri) = object.id() {
|
||||
cache::OBJECTS.store(object_uri, Arc::new(object.clone()));
|
||||
cache::OBJECTS.store(&object_uri, Arc::new(object.clone()));
|
||||
} else {
|
||||
tracing::warn!("embedded object without id: {object:?}");
|
||||
}
|
||||
} else { // try fetching it
|
||||
if let Some(object_id) = activity.object().id().str() {
|
||||
if let Ok(object_id) = activity.object().id() {
|
||||
if !gonna_fetch.contains(&object_id) {
|
||||
let fetch_kind = match activity_type {
|
||||
apb::ActivityType::Follow => U::Actor,
|
||||
|
@ -145,25 +145,25 @@ pub async fn process_activities(activities: Vec<serde_json::Value>, auth: Auth)
|
|||
}
|
||||
|
||||
// save activity, removing embedded object
|
||||
let object_id = activity.object().id().str();
|
||||
if let Some(activity_id) = activity.id().str() {
|
||||
let object_id = activity.object().id().ok();
|
||||
if let Ok(activity_id) = activity.id() {
|
||||
out.push(activity_id.to_string());
|
||||
cache::OBJECTS.store(
|
||||
&activity_id,
|
||||
Arc::new(activity.clone().set_object(apb::Node::maybe_link(object_id)))
|
||||
);
|
||||
} else if let Some(object_id) = activity.object().id().str() {
|
||||
} else if let Ok(object_id) = activity.object().id() {
|
||||
out.push(object_id);
|
||||
}
|
||||
|
||||
if let Some(uid) = activity.attributed_to().id().str() {
|
||||
if let Ok(uid) = activity.attributed_to().id() {
|
||||
if cache::OBJECTS.get(&uid).is_none() && !gonna_fetch.contains(&uid) {
|
||||
gonna_fetch.insert(uid.clone());
|
||||
sub_tasks.push(Box::pin(fetch_and_update(U::Actor, uid, auth)));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(uid) = activity.actor().id().str() {
|
||||
if let Ok(uid) = activity.actor().id() {
|
||||
if cache::OBJECTS.get(&uid).is_none() && !gonna_fetch.contains(&uid) {
|
||||
gonna_fetch.insert(uid.clone());
|
||||
sub_tasks.push(Box::pin(fetch_and_update(U::Actor, uid, auth)));
|
||||
|
@ -185,7 +185,7 @@ async fn fetch_and_update(kind: U, id: String, auth: Auth) {
|
|||
Err(e) => console_warn(&format!("could not fetch '{id}': {e}")),
|
||||
Ok(data) => {
|
||||
if data.actor_type().is_ok() {
|
||||
if let Some(url) = data.url().id().str() {
|
||||
if let Ok(url) = data.url().id() {
|
||||
cache::WEBFINGER.store(&id, url);
|
||||
}
|
||||
}
|
||||
|
@ -198,8 +198,8 @@ async fn fetch_and_update_with_user(kind: U, id: String, auth: Auth) {
|
|||
fetch_and_update(kind, id.clone(), auth).await;
|
||||
if let Some(obj) = cache::OBJECTS.get(&id) {
|
||||
if let Some(actor_id) = match kind {
|
||||
U::Object => obj.attributed_to().id().str(),
|
||||
U::Activity => obj.actor().id().str(),
|
||||
U::Object => obj.attributed_to().id().ok(),
|
||||
U::Activity => obj.actor().id().ok(),
|
||||
U::Actor => None,
|
||||
U::Hashtag => None,
|
||||
} {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use apb::{field::OptionalString, Activity, Base, Object};
|
||||
use apb::{Activity, Base, Object};
|
||||
use leptos::*;
|
||||
use crate::prelude::*;
|
||||
use super::Timeline;
|
||||
|
@ -40,15 +40,15 @@ fn FeedRecursive(tl: Timeline, root: String) -> impl IntoView {
|
|||
let (oid, reply) = match document.object_type().ok()? {
|
||||
// if it's a create, get and check created object: does it reply to root?
|
||||
apb::ObjectType::Activity(apb::ActivityType::Create) => {
|
||||
let object = cache::OBJECTS.get(document.object().id().ok()?)?;
|
||||
(object.id().str()?, object.in_reply_to().id().str()?)
|
||||
let object = cache::OBJECTS.get(&document.object().id().ok()?)?;
|
||||
(object.id().ok()?, object.in_reply_to().id().ok()?)
|
||||
},
|
||||
|
||||
// if it's a raw note, directly check if it replies to root
|
||||
apb::ObjectType::Note => (document.id().str()?, document.in_reply_to().id().str()?),
|
||||
apb::ObjectType::Note => (document.id().ok()?, document.in_reply_to().id().ok()?),
|
||||
|
||||
// if it's anything else, check if it relates to root, maybe like or announce?
|
||||
_ => (document.id().str()?, document.object().id().str()?),
|
||||
_ => (document.id().ok()?, document.object().id().ok()?),
|
||||
};
|
||||
if reply == root {
|
||||
Some((oid, document))
|
||||
|
|
Loading…
Reference in a new issue