feat: update dependencies to k-ap v0.1.7 and add profileHref utility for user links
This commit is contained in:
@@ -4,6 +4,37 @@ use k_ap::AS_PUBLIC;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
const STANDARD_NOTE_FIELDS: &[&str] = &[
|
||||
"type",
|
||||
"id",
|
||||
"attributedTo",
|
||||
"content",
|
||||
"published",
|
||||
"to",
|
||||
"cc",
|
||||
"inReplyTo",
|
||||
"sensitive",
|
||||
"summary",
|
||||
"tag",
|
||||
"url",
|
||||
"@context",
|
||||
"mediaType",
|
||||
];
|
||||
|
||||
pub fn extract_extensions(obj: &serde_json::Value) -> Option<serde_json::Value> {
|
||||
let extensions: serde_json::Map<String, serde_json::Value> = obj
|
||||
.as_object()?
|
||||
.iter()
|
||||
.filter(|(k, _)| !STANDARD_NOTE_FIELDS.contains(&k.as_str()))
|
||||
.map(|(k, v)| (k.clone(), v.clone()))
|
||||
.collect();
|
||||
if extensions.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(serde_json::Value::Object(extensions))
|
||||
}
|
||||
}
|
||||
|
||||
/// AP Note representing a Thought.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
@@ -42,6 +73,17 @@ pub struct ThoughtNoteInput {
|
||||
}
|
||||
|
||||
impl ThoughtNote {
|
||||
/// Returns `(note, extensions)` if `value` is a Note object, `None` otherwise.
|
||||
pub fn try_from_ap(value: serde_json::Value) -> Option<(Self, Option<serde_json::Value>)> {
|
||||
if value.get("type").and_then(|v| v.as_str()) != Some("Note") {
|
||||
return None;
|
||||
}
|
||||
let extensions = extract_extensions(&value);
|
||||
serde_json::from_value(value)
|
||||
.ok()
|
||||
.map(|note| (note, extensions))
|
||||
}
|
||||
|
||||
pub fn new_public(p: ThoughtNoteInput) -> Self {
|
||||
Self {
|
||||
kind: Default::default(),
|
||||
|
||||
@@ -1,5 +1,55 @@
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn extract_extensions_picks_up_non_standard_fields() {
|
||||
let obj = serde_json::json!({
|
||||
"type": "Note",
|
||||
"id": "https://example.com/notes/1",
|
||||
"content": "hello",
|
||||
"published": "2025-01-01T00:00:00Z",
|
||||
"movieTitle": "Dune",
|
||||
"rating": 5,
|
||||
"posterUrl": "https://example.com/poster.jpg"
|
||||
});
|
||||
let ext = extract_extensions(&obj).unwrap();
|
||||
assert_eq!(ext["movieTitle"], "Dune");
|
||||
assert_eq!(ext["rating"], 5);
|
||||
assert_eq!(ext["posterUrl"], "https://example.com/poster.jpg");
|
||||
assert!(ext.get("type").is_none());
|
||||
assert!(ext.get("content").is_none());
|
||||
assert!(ext.get("id").is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extract_extensions_returns_none_for_standard_only_note() {
|
||||
let obj = serde_json::json!({
|
||||
"type": "Note",
|
||||
"content": "hello",
|
||||
"published": "2025-01-01T00:00:00Z",
|
||||
"to": ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"tag": []
|
||||
});
|
||||
assert!(extract_extensions(&obj).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extract_extensions_returns_none_for_non_object() {
|
||||
let obj = serde_json::json!("not an object");
|
||||
assert!(extract_extensions(&obj).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_from_ap_returns_none_for_person() {
|
||||
let person = serde_json::json!({ "type": "Person", "id": "https://example.com/users/1" });
|
||||
assert!(ThoughtNote::try_from_ap(person).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_from_ap_returns_none_for_missing_type() {
|
||||
let obj = serde_json::json!({ "content": "hello" });
|
||||
assert!(ThoughtNote::try_from_ap(obj).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn note_serializes_with_public_audience() {
|
||||
let note = ThoughtNote::new_public(super::ThoughtNoteInput {
|
||||
|
||||
Reference in New Issue
Block a user