Parse source property properly

This commit is contained in:
Kitaiti Makoto 2022-05-03 10:04:22 +09:00
parent 384474930c
commit 19d30c12d1
3 changed files with 62 additions and 52 deletions

View file

@ -452,7 +452,7 @@ where
} }
} }
pub type LicensedArticle = Ext2<ApObject<Article>, Licensed, SourceProperty>; pub type LicensedArticle = Ext1<ApObject<Article>, Licensed>;
pub trait ToAsString { pub trait ToAsString {
fn to_as_string(&self) -> Option<String>; fn to_as_string(&self) -> Option<String>;
@ -489,7 +489,10 @@ impl ToAsUri for OneOrMany<AnyBase> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use activitystreams::activity::Create; use activitystreams::{
activity::{ActorAndObjectRef, Create},
object::kind::ArticleType,
};
use assert_json_diff::assert_json_eq; use assert_json_diff::assert_json_eq;
use serde_json::{from_str, json, to_value}; use serde_json::{from_str, json, to_value};
@ -569,20 +572,10 @@ mod tests {
Licensed { Licensed {
license: Some("CC-0".into()), license: Some("CC-0".into()),
}, },
SourceProperty {
source: Source {
content: "content".into(),
media_type: "text/plain".into(),
},
},
); );
let expected = json!({ let expected = json!({
"type": "Article", "type": "Article",
"license": "CC-0", "license": "CC-0",
"source": {
"content": "content",
"mediaType": "text/plain"
}
}); });
assert_json_eq!(to_value(licensed_article).unwrap(), expected); assert_json_eq!(to_value(licensed_article).unwrap(), expected);
} }
@ -630,7 +623,7 @@ mod tests {
#[test] #[test]
fn de_create_with_licensed_article() { fn de_create_with_licensed_article() {
let value: Create = from_str( let create: Create = from_str(
r#" r#"
{ {
"id": "https://plu.me/~/Blog/my-article", "id": "https://plu.me/~/Blog/my-article",
@ -656,26 +649,23 @@ mod tests {
"#, "#,
) )
.unwrap(); .unwrap();
let base = create.object_field_ref().as_single_base().unwrap();
let any_base = AnyBase::from_base(base.clone());
let value = any_base.extend::<LicensedArticle, ArticleType>().unwrap();
let expected = json!({ let expected = json!({
"type": "Article",
"id": "https://plu.me/~/Blog/my-article", "id": "https://plu.me/~/Blog/my-article",
"type": "Create", "attributedTo": ["https://plu.me/@/Admin", "https://plu.me/~/Blog"],
"actor": "https://plu.me/@/Admin", "content": "Hello.",
"to": "https://www.w3.org/ns/activitystreams#Public", "name": "My Article",
"object": { "summary": "Bye.",
"type": "Article", "source": {
"id": "https://plu.me/~/Blog/my-article",
"attributedTo": ["https://plu.me/@/Admin", "https://plu.me/~/Blog"],
"content": "Hello.", "content": "Hello.",
"name": "My Article", "mediaType": "text/markdown"
"summary": "Bye.", },
"source": { "published": "2014-12-12T12:12:12Z",
"content": "Hello.", "to": ["https://www.w3.org/ns/activitystreams#Public"],
"mediaType": "text/markdown" "license": "CC-0"
},
"published": "2014-12-12T12:12:12Z",
"to": ["https://www.w3.org/ns/activitystreams#Public"],
"license": "CC-0"
}
}); });
assert_eq!(to_value(value).unwrap(), expected); assert_eq!(to_value(value).unwrap(), expected);

View file

@ -8,7 +8,7 @@ use activitystreams::{
base::{AnyBase, Base}, base::{AnyBase, Base},
iri_string::types::IriString, iri_string::types::IriString,
link::{self, kind::MentionType}, link::{self, kind::MentionType},
object::{kind::ImageType, ApObject, Article, AsApObject, Image, Tombstone}, object::{kind::ImageType, ApObject, Article, AsApObject, Image, ObjectExt, Tombstone},
prelude::*, prelude::*,
time::OffsetDateTime, time::OffsetDateTime,
}; };
@ -19,8 +19,8 @@ use plume_common::{
activity_pub::{ activity_pub::{
inbox::{AsActor, AsObject, FromId}, inbox::{AsActor, AsObject, FromId},
sign::Signer, sign::Signer,
Hashtag, HashtagType, Id, IntoId, Licensed, LicensedArticle, Source, SourceProperty, Hashtag, HashtagType, Id, IntoId, Licensed, LicensedArticle, ToAsString, ToAsUri,
ToAsString, ToAsUri, PUBLIC_VISIBILITY, PUBLIC_VISIBILITY,
}, },
utils::{iri_percent_encode_seg, md_to_html}, utils::{iri_percent_encode_seg, md_to_html},
}; };
@ -367,12 +367,13 @@ impl Post {
authors.push(self.get_blog(conn)?.ap_url.parse::<IriString>()?); // add the blog URL here too authors.push(self.get_blog(conn)?.ap_url.parse::<IriString>()?); // add the blog URL here too
article.set_many_attributed_tos(authors); article.set_many_attributed_tos(authors);
article.set_content(self.content.get().clone()); article.set_content(self.content.get().clone());
let source = SourceProperty { let source = AnyBase::from_arbitrary_json(serde_json::json!({
source: Source { "source": {
content: self.source.clone(), "content": self.source,
media_type: String::from("text/markdown"), "mediaType": "text/markdown",
}, }
}; }))?;
article.set_source(source);
article.set_published( article.set_published(
OffsetDateTime::from_unix_timestamp_nanos(self.creation_date.timestamp_nanos().into()) OffsetDateTime::from_unix_timestamp_nanos(self.creation_date.timestamp_nanos().into())
.expect("OffsetDateTime"), .expect("OffsetDateTime"),
@ -412,7 +413,7 @@ impl Post {
let license = Licensed { let license = Licensed {
license: Some(self.license.clone()), license: Some(self.license.clone()),
}; };
Ok(LicensedArticle::new(article, license, source)) Ok(LicensedArticle::new(article, license))
} }
pub fn create_activity(&self, conn: &Connection) -> Result<Create> { pub fn create_activity(&self, conn: &Connection) -> Result<Create> {
@ -626,7 +627,6 @@ impl FromId<DbConn> for Post {
fn from_activity(conn: &DbConn, article: LicensedArticle) -> Result<Self> { fn from_activity(conn: &DbConn, article: LicensedArticle) -> Result<Self> {
let license = article.ext_one.license.unwrap_or_default(); let license = article.ext_one.license.unwrap_or_default();
let source = article.ext_two.source.content;
let article = article.inner; let article = article.inner;
let (blog, authors) = article let (blog, authors) = article
@ -674,6 +674,18 @@ impl FromId<DbConn> for Post {
.url() .url()
.and_then(|url| url.to_as_uri().or(id)) .and_then(|url| url.to_as_uri().or(id))
.ok_or(Error::MissingApProperty)?; .ok_or(Error::MissingApProperty)?;
let source = article
.source()
.and_then(|s| {
serde_json::to_value(s).ok().and_then(|obj| {
if !obj.is_object() {
return None;
}
obj.get("content")
.and_then(|content| content.as_str().map(|c| c.to_string()))
})
})
.unwrap_or_default();
let post = Post::from_db(conn, &ap_url) let post = Post::from_db(conn, &ap_url)
.and_then(|mut post| { .and_then(|mut post| {
let mut updated = false; let mut updated = false;
@ -711,7 +723,7 @@ impl FromId<DbConn> for Post {
updated = true; updated = true;
} }
if post.source != source { if post.source != source {
post.source = source.clone(); // FIXME: Don't clone post.source = source.clone();
updated = true; updated = true;
} }
if post.cover_id != cover { if post.cover_id != cover {
@ -874,7 +886,18 @@ impl FromId<DbConn> for PostUpdate {
.content() .content()
.and_then(|content| content.to_as_string()), .and_then(|content| content.to_as_string()),
cover: None, cover: None,
source: None, source: updated
.source()
.and_then(|s| {
serde_json::to_value(s).ok().and_then(|obj| {
if !obj.is_object() {
return None;
}
obj.get("content")
.and_then(|content| content.as_str().map(|c| c.to_string()))
})
})
.map(|s| s.to_string()),
license: None, license: None,
tags: updated tags: updated
.tag() .tag()
@ -891,7 +914,6 @@ impl FromId<DbConn> for PostUpdate {
}) })
.and_then(|m| m.map(|m| m.id)) .and_then(|m| m.map(|m| m.id))
}); });
post_update.source = Some(updated.ext_two.source.content);
post_update.license = updated.ext_one.license; post_update.license = updated.ext_one.license;
Ok(post_update) Ok(post_update)

View file

@ -72,18 +72,16 @@ fn fetch_and_cache_articles(user: &Arc<User>, conn: &DbConn) {
match create_acts { match create_acts {
Ok(create_acts) => { Ok(create_acts) => {
for create_act in create_acts { for create_act in create_acts {
match create_act match create_act.object_field_ref().as_single_base().map(|base| {
.object_field_ref() let any_base = AnyBase::from_base(base.clone()); // FIXME: Don't clone()
.as_single_base() any_base.extend::<LicensedArticle, ArticleType>()
.and_then(|base| { }) {
let any_base = AnyBase::from_base(base.clone()); // FIXME: Don't clone() Some(Ok(Some(article))) => {
any_base.extend::<LicensedArticle, ArticleType>().ok()
}) {
Some(Some(article)) => {
Post::from_activity(conn, article) Post::from_activity(conn, article)
.expect("Article from remote user couldn't be saved"); .expect("Article from remote user couldn't be saved");
info!("Fetched article from remote user"); info!("Fetched article from remote user");
} }
Some(Err(e)) => warn!("Error while fetching articles in background: {:?}", e),
_ => warn!("Error while fetching articles in background"), _ => warn!("Error while fetching articles in background"),
} }
} }