From 70053021a5c4c9d258817aa70aa257dc7432efa5 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 30 Dec 2024 02:50:04 +0100 Subject: [PATCH] `astreams`: Implement entity processing and Entity.preview --- acrate_astreams/src/activitystreams/jsonld.rs | 31 ++++++++++++++++--- acrate_astreams/src/activitystreams/mod.rs | 14 +++++++-- acrate_astreams/tests/test_activitystreams.rs | 25 ++++++++++++++- 3 files changed, 63 insertions(+), 7 deletions(-) diff --git a/acrate_astreams/src/activitystreams/jsonld.rs b/acrate_astreams/src/activitystreams/jsonld.rs index a930496..39b0a45 100644 --- a/acrate_astreams/src/activitystreams/jsonld.rs +++ b/acrate_astreams/src/activitystreams/jsonld.rs @@ -6,11 +6,11 @@ use json_ld::Direction; use json_ld::object::Any; use json_ld::syntax::LangTagBuf; use mediatype::MediaType; -use crate::activitystreams::StreamsLink; +use crate::activitystreams::{StreamsEntity, StreamsLink}; pub type LangTriple = (String, Option, Option); -pub trait StreamsJsonLD { +pub trait StreamsJsonLD { fn jsonld_any_value_string(&self, id: &Iri) -> Option>; fn jsonld_iter_value_string(&self, id: &Iri) -> impl Iterator>; fn jsonld_iter_value_langstring(&self, id: &Iri) -> impl Iterator>; @@ -19,9 +19,10 @@ pub trait StreamsJsonLD { fn jsonld_any_value_langtag(&self, id: &Iri) -> Option>; fn jsonld_any_value_u32(&self, id: &Iri) -> Option>; fn jsonld_any_value_u64(&self, id: &Iri) -> Option>; + fn jsonld_iter_node_entity(&self, id: &Iri) -> impl Iterator>; } -impl StreamsJsonLD for &json_ld::Node { +impl StreamsJsonLD for json_ld::Node { fn jsonld_any_value_string(&self, id: &Iri) -> Option> { let property = match self.properties.get_any(&id) { None => return None, @@ -222,9 +223,31 @@ impl StreamsJsonLD for &json_ld::Node { Some(Ok(r#u64)) } + + fn jsonld_iter_node_entity(&self, id: &Iri) -> impl Iterator> { + let properties = self.properties.get(&id); + + let nodes = properties.map(|v| v + .as_node() + .ok_or(anyhow!("Couldn't process property as JSON-LD node")) + .map(|v| v + .clone() + ) + ); + + nodes + } } -impl StreamsLink for &json_ld::Node { +impl StreamsEntity for json_ld::Node { + fn activitystreams_previews(&self) -> impl Iterator> { + self.jsonld_iter_node_entity( + iri!("https://www.w3.org/ns/activitystreams#preview") + ) + } +} + +impl StreamsLink for json_ld::Node { fn activitystreams_href(&self) -> Option> { self.jsonld_any_node_string( iri!("https://www.w3.org/ns/activitystreams#href") diff --git a/acrate_astreams/src/activitystreams/mod.rs b/acrate_astreams/src/activitystreams/mod.rs index dff8614..b5b657f 100644 --- a/acrate_astreams/src/activitystreams/mod.rs +++ b/acrate_astreams/src/activitystreams/mod.rs @@ -18,13 +18,23 @@ use mediatype::MediaType; pub mod jsonld; +/// Something that is either a [`StreamsObject`] or a [`StreamsLink`]. +pub trait StreamsEntity { + fn activitystreams_previews(&self) -> impl Iterator>; +} + /// Something that can be considered a `https://www.w3.org/ns/activitystreams#Object`. -pub trait StreamsObject { +pub trait StreamsObject where + Self: StreamsEntity, +{ } /// Something that can be considered a `https://www.w3.org/ns/activitystreams#Link`. -pub trait StreamsLink { +pub trait StreamsLink where + Self: StreamsEntity, + Preview: StreamsEntity, +{ fn activitystreams_href(&self) -> Option>; // FIXME: This accepts any kind of string, and does not filter to HTML link relations diff --git a/acrate_astreams/tests/test_activitystreams.rs b/acrate_astreams/tests/test_activitystreams.rs index 83bae47..cc6aaf2 100644 --- a/acrate_astreams/tests/test_activitystreams.rs +++ b/acrate_astreams/tests/test_activitystreams.rs @@ -1,6 +1,5 @@ use json_ld::syntax::LangTagBuf; use acrate_astreams::activitystreams::jsonld::LangTriple; -use acrate_astreams::activitystreams::StreamsLink; macro_rules! test_example { ($modname:ident, $filename:literal) => { @@ -383,3 +382,27 @@ async fn test_link_width() { assert_eq!(width, 100u64) } + +#[tokio::test] +async fn test_link_preview() { + let doc = e102::expand().await; + + let node = doc.main_node() + .expect("Main node was not found"); + + let previews: Vec = { + use acrate_astreams::activitystreams::StreamsEntity; + + node.activitystreams_previews() + .map(|v| v + .expect("Property `preview` failed to process") + ) + .collect() + }; + + let mut previews = previews.into_iter(); + + let _preview = previews.next().expect("Expected `preview` [0] to be present"); + + // TODO: More tests when StreamsObject is implemented +}