Dummy implementation to compile posts.rs
This commit is contained in:
parent
c36b544c20
commit
2ee19a866d
@ -3,20 +3,29 @@ use crate::{
|
||||
post_authors::*, safe_string::SafeString, schema::posts, tags::*, timeline::*, users::User,
|
||||
Connection, Error, PostEvent::*, Result, CONFIG, POST_CHAN,
|
||||
};
|
||||
use activitypub::{
|
||||
use activitystreams::{
|
||||
activity::{Create, Delete, Update},
|
||||
base::{AnyBase, AsBase, Base},
|
||||
iri, // CustomObject,
|
||||
link,
|
||||
object::{Article, Image, Tombstone},
|
||||
CustomObject,
|
||||
object::{kind::ImageType, ApObject, Article, Image, Object, Tombstone},
|
||||
prelude::*,
|
||||
primitives::OneOrMany,
|
||||
time::OffsetDateTime,
|
||||
};
|
||||
use chrono::{NaiveDateTime, TimeZone, Utc};
|
||||
use chrono::{NaiveDateTime, Utc};
|
||||
use diesel::{self, BelongingToDsl, ExpressionMethods, QueryDsl, RunQueryDsl};
|
||||
use once_cell::sync::Lazy;
|
||||
use plume_common::{
|
||||
activity_pub::{
|
||||
inbox::{AsActor, AsObject, FromId},
|
||||
sign::Signer,
|
||||
Hashtag, Id, IntoId, Licensed, Source, PUBLIC_VISIBILITY,
|
||||
// Hashtag, Id, IntoId, /Licensed, Source, PUBLIC_VISIBILITY,
|
||||
Hashtag,
|
||||
Id,
|
||||
IntoId,
|
||||
// Source,
|
||||
PUBLIC_VISIBILITY,
|
||||
},
|
||||
utils::{iri_percent_encode_seg, md_to_html},
|
||||
};
|
||||
@ -24,7 +33,43 @@ use riker::actors::{Publish, Tell};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
pub type LicensedArticle = CustomObject<Licensed, Article>;
|
||||
// pub type LicensedArticle = CustomObject<Licensed, Article>;
|
||||
|
||||
#[derive(
|
||||
Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, serde::Deserialize, serde::Serialize,
|
||||
)]
|
||||
enum LinkType {
|
||||
Link,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for LinkType {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, stringify!(Link))
|
||||
}
|
||||
}
|
||||
impl Default for LinkType {
|
||||
fn default() -> Self {
|
||||
LinkType::Link
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, serde::Deserialize, serde::Serialize,
|
||||
)]
|
||||
enum SourceType {
|
||||
Source,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for SourceType {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, stringify!(Source))
|
||||
}
|
||||
}
|
||||
impl Default for SourceType {
|
||||
fn default() -> Self {
|
||||
SourceType::Source
|
||||
}
|
||||
}
|
||||
|
||||
static BLOG_FQN_CACHE: Lazy<Mutex<HashMap<i32, String>>> = Lazy::new(|| Mutex::new(HashMap::new()));
|
||||
|
||||
@ -339,7 +384,8 @@ impl Post {
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn to_activity(&self, conn: &Connection) -> Result<LicensedArticle> {
|
||||
pub fn to_activity(&self, conn: &Connection) -> Result<ApObject<Article>> {
|
||||
// pub fn to_activity(&self, conn: &Connection) -> Result<LicensedArticle> {
|
||||
let cc = self.get_receivers_urls(conn)?;
|
||||
let to = vec![PUBLIC_VISIBILITY.to_string()];
|
||||
|
||||
@ -353,9 +399,9 @@ impl Post {
|
||||
.collect::<Vec<serde_json::Value>>();
|
||||
mentions_json.append(&mut tags_json);
|
||||
|
||||
let mut article = Article::default();
|
||||
article.object_props.set_name_string(self.title.clone())?;
|
||||
article.object_props.set_id_string(self.ap_url.clone())?;
|
||||
let mut article = ApObject::new(Article::new());
|
||||
article.set_name(self.title.clone());
|
||||
article.set_id(iri!(self.ap_url));
|
||||
|
||||
let mut authors = self
|
||||
.get_authors(conn)?
|
||||
@ -363,82 +409,110 @@ impl Post {
|
||||
.map(|x| Id::new(x.ap_url))
|
||||
.collect::<Vec<Id>>();
|
||||
authors.push(self.get_blog(conn)?.into_id()); // add the blog URL here too
|
||||
article
|
||||
.object_props
|
||||
.set_attributed_to_link_vec::<Id>(authors)?;
|
||||
article
|
||||
.object_props
|
||||
.set_content_string(self.content.get().clone())?;
|
||||
article.ap_object_props.set_source_object(Source {
|
||||
content: self.source.clone(),
|
||||
media_type: String::from("text/markdown"),
|
||||
})?;
|
||||
article
|
||||
.object_props
|
||||
.set_published_utctime(Utc.from_utc_datetime(&self.creation_date))?;
|
||||
article
|
||||
.object_props
|
||||
.set_summary_string(self.subtitle.clone())?;
|
||||
article.object_props.tag = Some(json!(mentions_json));
|
||||
// article.set_attributed_to(authors.into());
|
||||
article.set_content(self.content.get().clone());
|
||||
article.set_source(
|
||||
// FIXME
|
||||
// article.ap_object_props.set_source_object(Source {
|
||||
// content: self.source.clone(),
|
||||
// media_type: String::from("text/markdown"),
|
||||
// })?;
|
||||
AnyBase::from_base(
|
||||
*ApObject::new(Object::new())
|
||||
.set_content(self.source.clone())
|
||||
.set_media_type("text/markdown".parse().expect("Unreachable"))
|
||||
.base_ref(),
|
||||
),
|
||||
);
|
||||
article.set_published(
|
||||
OffsetDateTime::from_unix_timestamp_nanos(self.creation_date.timestamp_nanos().into())
|
||||
.expect("Unreachable"),
|
||||
);
|
||||
article.set_summary(self.subtitle.clone());
|
||||
article.set_tag(AnyBase::from_arbitrary_json(json!(mentions_json))?);
|
||||
|
||||
if let Some(media_id) = self.cover_id {
|
||||
let media = Media::get(conn, media_id)?;
|
||||
let mut cover = Image::default();
|
||||
cover.object_props.set_url_string(media.url()?)?;
|
||||
let mut cover = Image::new();
|
||||
cover.set_url(media.url()?);
|
||||
if media.sensitive {
|
||||
cover
|
||||
.object_props
|
||||
.set_summary_string(media.content_warning.unwrap_or_default())?;
|
||||
cover.set_summary(media.content_warning.unwrap_or_default());
|
||||
}
|
||||
cover.object_props.set_content_string(media.alt_text)?;
|
||||
cover
|
||||
.object_props
|
||||
.set_attributed_to_link_vec(vec![User::get(conn, media.owner_id)?.into_id()])?;
|
||||
article.object_props.set_icon_object(cover)?;
|
||||
cover.set_content(media.alt_text);
|
||||
cover.set_attributed_to(iri!(User::get(conn, media.owner_id)?.into_id()));
|
||||
let base = Base::retract(cover)?.into_generic()?;
|
||||
article.set_icon(AnyBase::from_base(base));
|
||||
}
|
||||
|
||||
article.object_props.set_url_string(self.ap_url.clone())?;
|
||||
article
|
||||
.object_props
|
||||
.set_to_link_vec::<Id>(to.into_iter().map(Id::new).collect())?;
|
||||
article
|
||||
.object_props
|
||||
.set_cc_link_vec::<Id>(cc.into_iter().map(Id::new).collect())?;
|
||||
let mut license = Licensed::default();
|
||||
license.set_license_string(self.license.clone())?;
|
||||
Ok(LicensedArticle::new(article, license))
|
||||
article.set_url(self.ap_url.clone());
|
||||
let tos = Vec::with_capacity(to.len());
|
||||
for addr in to.into_iter() {
|
||||
tos.push(iri!(addr));
|
||||
}
|
||||
article.set_many_tos(tos);
|
||||
let ccs = Vec::with_capacity(cc.len());
|
||||
for addr in cc.into_iter() {
|
||||
ccs.push(iri!(addr));
|
||||
}
|
||||
article.set_many_ccs(ccs);
|
||||
// let mut license = Licensed::default();
|
||||
// license.set_license_string(self.license.clone())?;
|
||||
// Ok(LicensedArticle::new(article, license))
|
||||
Ok(article)
|
||||
}
|
||||
|
||||
pub fn create_activity(&self, conn: &Connection) -> Result<Create> {
|
||||
let article = self.to_activity(conn)?;
|
||||
let mut act = Create::default();
|
||||
act.object_props
|
||||
.set_id_string(format!("{}/activity", self.ap_url))?;
|
||||
act.object_props
|
||||
.set_to_link_vec::<Id>(article.object.object_props.to_link_vec()?)?;
|
||||
act.object_props
|
||||
.set_cc_link_vec::<Id>(article.object.object_props.cc_link_vec()?)?;
|
||||
act.create_props
|
||||
.set_actor_link(Id::new(self.get_authors(conn)?[0].clone().ap_url))?;
|
||||
act.create_props.set_object_object(article)?;
|
||||
let base = Base::retract(article)?.into_generic()?;
|
||||
let mut act = Create::new::<_, OneOrMany<AnyBase>>(
|
||||
iri!(Id::new(self.get_authors(conn)?[0].clone().ap_url)),
|
||||
base.into(),
|
||||
);
|
||||
let id_string = format!("{}/activity", self.ap_url);
|
||||
act.set_id(iri!(id_string));
|
||||
act.set_many_tos(
|
||||
article
|
||||
.to()
|
||||
.expect("exists")
|
||||
.into_iter()
|
||||
.map(|addr| AnyBase::from_xsd_any_uri(*addr.id().expect("exists"))),
|
||||
);
|
||||
act.set_many_ccs(
|
||||
article
|
||||
.cc()
|
||||
.expect("exists")
|
||||
.into_iter()
|
||||
.map(|addr| AnyBase::from_xsd_any_uri(*addr.id().expect("exists"))),
|
||||
);
|
||||
Ok(act)
|
||||
}
|
||||
|
||||
pub fn update_activity(&self, conn: &Connection) -> Result<Update> {
|
||||
let article = self.to_activity(conn)?;
|
||||
let mut act = Update::default();
|
||||
act.object_props.set_id_string(format!(
|
||||
let base = Base::retract(article)?.into_generic()?;
|
||||
let mut act = Update::new::<_, OneOrMany<AnyBase>>(
|
||||
iri!(Id::new(self.get_authors(conn)?[0].clone().ap_url)),
|
||||
base.into(),
|
||||
);
|
||||
act.set_id(iri!(format!(
|
||||
"{}/update-{}",
|
||||
self.ap_url,
|
||||
Utc::now().timestamp()
|
||||
))?;
|
||||
act.object_props
|
||||
.set_to_link_vec::<Id>(article.object.object_props.to_link_vec()?)?;
|
||||
act.object_props
|
||||
.set_cc_link_vec::<Id>(article.object.object_props.cc_link_vec()?)?;
|
||||
act.update_props
|
||||
.set_actor_link(Id::new(self.get_authors(conn)?[0].clone().ap_url))?;
|
||||
act.update_props.set_object_object(article)?;
|
||||
)));
|
||||
act.set_many_tos(
|
||||
article
|
||||
.to()
|
||||
.expect("exists")
|
||||
.into_iter()
|
||||
.map(|addr| AnyBase::from_xsd_any_uri(*addr.id().expect("exists"))),
|
||||
);
|
||||
act.set_many_ccs(
|
||||
article
|
||||
.cc()
|
||||
.expect("exists")
|
||||
.into_iter()
|
||||
.map(|addr| AnyBase::from_xsd_any_uri(*addr.id().expect("exists"))),
|
||||
);
|
||||
Ok(act)
|
||||
}
|
||||
|
||||
@ -447,10 +521,8 @@ impl Post {
|
||||
.into_iter()
|
||||
.map(|m| {
|
||||
(
|
||||
m.link_props
|
||||
.href_string()
|
||||
.ok()
|
||||
.and_then(|ap_url| User::find_by_ap_url(conn, &ap_url).ok())
|
||||
m.href()
|
||||
.and_then(|ap_url| User::find_by_ap_url(conn, ap_url.as_str()).ok())
|
||||
.map(|u| u.id),
|
||||
m,
|
||||
)
|
||||
@ -566,18 +638,17 @@ impl Post {
|
||||
}
|
||||
|
||||
pub fn build_delete(&self, conn: &Connection) -> Result<Delete> {
|
||||
let mut act = Delete::default();
|
||||
act.delete_props
|
||||
.set_actor_link(self.get_authors(conn)?[0].clone().into_id())?;
|
||||
let mut tombstone = Tombstone::new();
|
||||
let ap_url = iri!(self.ap_url);
|
||||
tombstone.set_id(ap_url);
|
||||
let base = Base::retract(tombstone)?.into_generic()?;
|
||||
let mut act = Delete::new::<_, OneOrMany<AnyBase>>(
|
||||
iri!(self.get_authors(conn)?[0].clone().into_id()),
|
||||
base.into(),
|
||||
);
|
||||
|
||||
let mut tombstone = Tombstone::default();
|
||||
tombstone.object_props.set_id_string(self.ap_url.clone())?;
|
||||
act.delete_props.set_object_object(tombstone)?;
|
||||
|
||||
act.object_props
|
||||
.set_id_string(format!("{}#delete", self.ap_url))?;
|
||||
act.object_props
|
||||
.set_to_link_vec(vec![Id::new(PUBLIC_VISIBILITY)])?;
|
||||
act.set_id(format!("{}#delete", self.ap_url).parse()?);
|
||||
act.set_many_tos(vec![iri!(Id::new(PUBLIC_VISIBILITY))]);
|
||||
Ok(act)
|
||||
}
|
||||
|
||||
@ -614,54 +685,96 @@ impl Post {
|
||||
|
||||
impl FromId<DbConn> for Post {
|
||||
type Error = Error;
|
||||
type Object = LicensedArticle;
|
||||
// type Object = LicensedArticle;
|
||||
type Object = Article;
|
||||
|
||||
fn from_db(conn: &DbConn, id: &str) -> Result<Self> {
|
||||
Self::find_by_ap_url(conn, id)
|
||||
}
|
||||
|
||||
fn from_activity(conn: &DbConn, article: LicensedArticle) -> Result<Self> {
|
||||
// fn from_activity(conn: &DbConn, article: LicensedArticle) -> Result<Self> {
|
||||
fn from_activity(conn: &DbConn, article: Article) -> Result<Self> {
|
||||
let conn = conn;
|
||||
let license = article.custom_props.license_string().unwrap_or_default();
|
||||
let article = article.object;
|
||||
// let license = article.license().unwrap_or_default();
|
||||
|
||||
let (blog, authors) = article
|
||||
.object_props
|
||||
.attributed_to_link_vec::<Id>()?
|
||||
.into_iter()
|
||||
.fold((None, vec![]), |(blog, mut authors), link| {
|
||||
let url = link;
|
||||
match User::from_id(conn, &url, None, CONFIG.proxy()) {
|
||||
let (blog, authors) = article.attributed_to().into_iter().fold(
|
||||
(None, vec![]),
|
||||
|(blog, mut authors), link| {
|
||||
let href = link
|
||||
.as_one()
|
||||
.expect("exists and only")
|
||||
.extend::<link::Link<LinkType>, LinkType>()
|
||||
.expect("exists")
|
||||
.expect("object")
|
||||
.href()
|
||||
.expect("exists")
|
||||
.as_str();
|
||||
match User::from_id(conn, href, None, CONFIG.proxy()) {
|
||||
Ok(u) => {
|
||||
authors.push(u);
|
||||
(blog, authors)
|
||||
}
|
||||
Err(_) => (
|
||||
blog.or_else(|| Blog::from_id(conn, &url, None, CONFIG.proxy()).ok()),
|
||||
blog.or_else(|| Blog::from_id(conn, href, None, CONFIG.proxy()).ok()),
|
||||
authors,
|
||||
),
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
let cover = article
|
||||
.object_props
|
||||
.icon_object::<Image>()
|
||||
let cover = article.icon().and_then(|img| {
|
||||
Media::from_activity(
|
||||
conn,
|
||||
&img.as_one()
|
||||
.expect("possible")
|
||||
.extend::<Image, ImageType>()
|
||||
.expect("possilbe")
|
||||
.expect("exists"),
|
||||
)
|
||||
.ok()
|
||||
.and_then(|img| Media::from_activity(conn, &img).ok().map(|m| m.id));
|
||||
.map(|m| m.id)
|
||||
});
|
||||
|
||||
let title = article.object_props.name_string()?;
|
||||
let title = article
|
||||
.name()
|
||||
.expect("exists")
|
||||
.as_single_xsd_string()
|
||||
.expect("exists and only")
|
||||
.to_string();
|
||||
let ap_url = article
|
||||
.object_props
|
||||
.url_string()
|
||||
.or_else(|_| article.object_props.id_string())?;
|
||||
let post = Post::from_db(conn, &ap_url)
|
||||
.url()
|
||||
.map(|url| url.as_single_id().expect("exists"))
|
||||
.or_else(|| article.id())
|
||||
.expect("exists")
|
||||
.to_string();
|
||||
let post = Post::from_db(conn, ap_url.as_str())
|
||||
.and_then(|mut post| {
|
||||
let mut updated = false;
|
||||
|
||||
let slug = Self::slug(&title);
|
||||
let content = SafeString::new(&article.object_props.content_string()?);
|
||||
let subtitle = article.object_props.summary_string()?;
|
||||
let source = article.ap_object_props.source_object::<Source>()?.content;
|
||||
let content = SafeString::new(
|
||||
&article
|
||||
.content()
|
||||
.expect("exists and only")
|
||||
.as_one()
|
||||
.expect("only")
|
||||
.as_xsd_string()
|
||||
.expect("possible"),
|
||||
);
|
||||
let subtitle = article
|
||||
.summary()
|
||||
.expect("exists and only")
|
||||
.as_one()
|
||||
.expect("possible")
|
||||
.as_xsd_string()
|
||||
.expect("possible")
|
||||
.to_string();
|
||||
let source = ApObject::new(article)
|
||||
.source()
|
||||
.ok_or(Error::MissingApProperty)?
|
||||
.as_xsd_string()
|
||||
.expect("possible")
|
||||
.to_string();
|
||||
if post.slug != slug {
|
||||
post.slug = slug.to_string();
|
||||
updated = true;
|
||||
@ -674,10 +787,10 @@ impl FromId<DbConn> for Post {
|
||||
post.content = content;
|
||||
updated = true;
|
||||
}
|
||||
if post.license != license {
|
||||
post.license = license.clone();
|
||||
updated = true;
|
||||
}
|
||||
// if post.license != license {
|
||||
// post.license = license.clone();
|
||||
// updated = true;
|
||||
// }
|
||||
if post.subtitle != subtitle {
|
||||
post.subtitle = subtitle;
|
||||
updated = true;
|
||||
@ -698,20 +811,50 @@ impl FromId<DbConn> for Post {
|
||||
Ok(post)
|
||||
})
|
||||
.or_else(|_| {
|
||||
let published = article.published().ok_or(Error::MissingApProperty)?;
|
||||
let published_secs = published.unix_timestamp();
|
||||
let published_nanos =
|
||||
published.unix_timestamp_nanos() - (published_secs * 1000 * 1000) as i128;
|
||||
use std::convert::TryInto;
|
||||
let creation_date = NaiveDateTime::from_timestamp(
|
||||
published_secs,
|
||||
published_nanos.try_into().expect("Unreachable"),
|
||||
);
|
||||
Post::insert(
|
||||
conn,
|
||||
NewPost {
|
||||
blog_id: blog.ok_or(Error::NotFound)?.id,
|
||||
slug: Self::slug(&title).to_string(),
|
||||
title,
|
||||
content: SafeString::new(&article.object_props.content_string()?),
|
||||
content: SafeString::new(
|
||||
&article
|
||||
.content()
|
||||
.expect("exists and only")
|
||||
.as_one()
|
||||
.expect("only")
|
||||
.as_xsd_string()
|
||||
.expect("possible"),
|
||||
),
|
||||
published: true,
|
||||
license,
|
||||
// license,
|
||||
license: "".into(),
|
||||
// FIXME: This is wrong: with this logic, we may use the display URL as the AP ID. We need two different fields
|
||||
ap_url,
|
||||
creation_date: Some(article.object_props.published_utctime()?.naive_utc()),
|
||||
subtitle: article.object_props.summary_string()?,
|
||||
source: article.ap_object_props.source_object::<Source>()?.content,
|
||||
creation_date: Some(creation_date),
|
||||
subtitle: article
|
||||
.summary()
|
||||
.expect("exists and only")
|
||||
.as_one()
|
||||
.expect("possible")
|
||||
.as_xsd_string()
|
||||
.expect("possible")
|
||||
.to_string(),
|
||||
source: ApObject::new(article)
|
||||
.source()
|
||||
.ok_or(Error::MissingApProperty)?
|
||||
.as_xsd_string()
|
||||
.expect("possible")
|
||||
.to_string(),
|
||||
cover_id: cover,
|
||||
},
|
||||
)
|
||||
@ -735,24 +878,27 @@ impl FromId<DbConn> for Post {
|
||||
.2
|
||||
.into_iter()
|
||||
.collect::<HashSet<_>>();
|
||||
if let Some(serde_json::Value::Array(tags)) = article.object_props.tag {
|
||||
for tag in tags {
|
||||
serde_json::from_value::<link::Mention>(tag.clone())
|
||||
.map(|m| Mention::from_activity(conn, &m, post.id, true, true))
|
||||
.ok();
|
||||
if let Some(tags) = article.tag() {
|
||||
for tag in tags.iter() {
|
||||
Mention::from_activity(
|
||||
conn,
|
||||
&tag.extend::<link::Mention, link::kind::MentionType>()
|
||||
.expect("possible")
|
||||
.expect("exists"),
|
||||
post.id,
|
||||
true,
|
||||
true,
|
||||
)
|
||||
.ok();
|
||||
|
||||
serde_json::from_value::<Hashtag>(tag.clone())
|
||||
.map_err(Error::from)
|
||||
.and_then(|t| {
|
||||
let tag_name = t.name_string()?;
|
||||
Ok(Tag::from_activity(
|
||||
conn,
|
||||
&t,
|
||||
post.id,
|
||||
hashtags.remove(&tag_name),
|
||||
))
|
||||
})
|
||||
.ok();
|
||||
// TODO
|
||||
// let tag_name = tag.as_xsd_string().ok_or(Error::MissingApProperty)?;
|
||||
// Ok(Tag::from_activity(
|
||||
// conn,
|
||||
// &tag,
|
||||
// post.id,
|
||||
// hashtags.remove(&tag_name),
|
||||
// ));
|
||||
}
|
||||
}
|
||||
|
||||
@ -806,33 +952,54 @@ pub struct PostUpdate {
|
||||
|
||||
impl FromId<DbConn> for PostUpdate {
|
||||
type Error = Error;
|
||||
type Object = LicensedArticle;
|
||||
// type Object = LicensedArticle;
|
||||
type Object = Article;
|
||||
|
||||
fn from_db(_: &DbConn, _: &str) -> Result<Self> {
|
||||
// Always fail because we always want to deserialize the AP object
|
||||
Err(Error::NotFound)
|
||||
}
|
||||
|
||||
fn from_activity(conn: &DbConn, updated: LicensedArticle) -> Result<Self> {
|
||||
// fn from_activity(conn: &DbConn, updated: LicensedArticle) -> Result<Self> {
|
||||
fn from_activity(conn: &DbConn, updated: Article) -> Result<Self> {
|
||||
Ok(PostUpdate {
|
||||
ap_url: updated.object.object_props.id_string()?,
|
||||
title: updated.object.object_props.name_string().ok(),
|
||||
subtitle: updated.object.object_props.summary_string().ok(),
|
||||
content: updated.object.object_props.content_string().ok(),
|
||||
cover: updated
|
||||
.object
|
||||
.object_props
|
||||
.icon_object::<Image>()
|
||||
ap_url: updated.id().ok_or(Error::MissingApProperty)?.to_string(),
|
||||
title: updated
|
||||
.name()
|
||||
.map(|name| name.as_single_xsd_string().expect("exists").into()),
|
||||
subtitle: updated
|
||||
.summary()
|
||||
.map(|summary| summary.as_single_xsd_string().expect("exists").into()),
|
||||
content: updated
|
||||
.content()
|
||||
.map(|content| content.as_single_xsd_string().expect("exists").into()),
|
||||
cover: updated.icon().map_or(None, |img| {
|
||||
Media::from_activity(
|
||||
conn,
|
||||
&img.as_one()
|
||||
.expect("possible")
|
||||
.extend::<Image, ImageType>()
|
||||
.expect("possible")
|
||||
.expect("exists"),
|
||||
)
|
||||
.map(|m| m.id)
|
||||
.ok()
|
||||
.and_then(|img| Media::from_activity(conn, &img).ok().map(|m| m.id)),
|
||||
source: updated
|
||||
.object
|
||||
.ap_object_props
|
||||
.source_object::<Source>()
|
||||
.ok()
|
||||
.map(|x| x.content),
|
||||
license: updated.custom_props.license_string().ok(),
|
||||
tags: updated.object.object_props.tag,
|
||||
}),
|
||||
source: ApObject::new(updated).source().map(|x| {
|
||||
x.extend::<Object<SourceType>, SourceType>()
|
||||
.expect("possible")
|
||||
.expect("exists")
|
||||
.content()
|
||||
.expect("exists and only")
|
||||
.as_one()
|
||||
.expect("only")
|
||||
.xsd_string()
|
||||
.expect("possible")
|
||||
}),
|
||||
license: None, // updated.custom_props.license_string().ok(), // FIXME
|
||||
tags: updated.tag().and_then(|tags| {
|
||||
serde_json::to_value(tags.as_single_base().expect("possible")).ok()
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
@ -1021,10 +1188,12 @@ mod tests {
|
||||
article.object_props.set_id_string("Yo".into()).unwrap();
|
||||
let mut license = Licensed::default();
|
||||
license.set_license_string("WTFPL".into()).unwrap();
|
||||
let full_article = LicensedArticle::new(article, license);
|
||||
// let full_article = LicensedArticle::new(article, license);
|
||||
let full_article = Article::new(article, license);
|
||||
|
||||
let json = serde_json::to_value(full_article).unwrap();
|
||||
let article_from_json: LicensedArticle = serde_json::from_value(json).unwrap();
|
||||
// let article_from_json: LicensedArticle = serde_json::from_value(json).unwrap();
|
||||
let article_from_json: Article = serde_json::from_value(json).unwrap();
|
||||
assert_eq!(
|
||||
"Yo",
|
||||
&article_from_json.object.object_props.id_string().unwrap()
|
||||
@ -1051,7 +1220,8 @@ mod tests {
|
||||
"published": "2014-12-12T12:12:12Z",
|
||||
"to": [plume_common::activity_pub::PUBLIC_VISIBILITY]
|
||||
});
|
||||
let article: LicensedArticle = serde_json::from_value(json).unwrap();
|
||||
// let article: LicensedArticle = serde_json::from_value(json).unwrap();
|
||||
let article: Article = serde_json::from_value(json).unwrap();
|
||||
assert_eq!(
|
||||
"https://plu.me/~/Blog/my-article",
|
||||
&article.object.object_props.id_string().unwrap()
|
||||
|
Loading…
x
Reference in New Issue
Block a user