feat: store AP note extensions in JSONB and render movies-diary posts as rich cards

This commit is contained in:
2026-05-24 04:29:04 +02:00
parent f4932af2ba
commit 5097c91261
17 changed files with 227 additions and 9 deletions

View File

@@ -0,0 +1 @@
ALTER TABLE thoughts ADD COLUMN note_extensions JSONB;

View File

@@ -65,6 +65,7 @@ impl ActivityPubRepository for PgActivityPubRepository {
local: true,
created_at: r.created_at,
updated_at: r.updated_at,
note_extensions: None,
},
author_username: Username::from_trusted(r.username),
})
@@ -130,6 +131,7 @@ impl ActivityPubRepository for PgActivityPubRepository {
local: true,
created_at: r.created_at,
updated_at: r.updated_at,
note_extensions: None,
},
author_username: Username::from_trusted(r.username),
})
@@ -220,6 +222,7 @@ impl ActivityPubRepository for PgActivityPubRepository {
content_warning,
visibility,
in_reply_to,
note_extensions,
} = input;
let capped: String = content.chars().take(MAX_REMOTE_CONTENT_CHARS).collect();
let (in_reply_to_id, in_reply_to_url) = match in_reply_to {
@@ -236,8 +239,8 @@ impl ActivityPubRepository for PgActivityPubRepository {
None => (None, None),
};
sqlx::query(
"INSERT INTO thoughts(id,user_id,content,ap_id,visibility,sensitive,local,content_warning,created_at,in_reply_to_id,in_reply_to_url)
VALUES($1,$2,$3,$4,$8,$5,false,$6,$7,$9,$10) ON CONFLICT(ap_id) DO NOTHING",
"INSERT INTO thoughts(id,user_id,content,ap_id,visibility,sensitive,local,content_warning,created_at,in_reply_to_id,in_reply_to_url,note_extensions)
VALUES($1,$2,$3,$4,$8,$5,false,$6,$7,$9,$10,$11) ON CONFLICT(ap_id) DO NOTHING",
)
.bind(uuid::Uuid::new_v4())
.bind(author_id.as_uuid())
@@ -249,6 +252,7 @@ impl ActivityPubRepository for PgActivityPubRepository {
.bind(visibility)
.bind(in_reply_to_id)
.bind(&in_reply_to_url)
.bind(note_extensions)
.execute(&self.pool)
.await
.into_domain()?;

View File

@@ -25,6 +25,7 @@ async fn accept_and_retract_note(pool: sqlx::PgPool) {
content_warning: None,
visibility: "public",
in_reply_to: None,
note_extensions: None,
})
.await
.unwrap();
@@ -55,6 +56,7 @@ async fn accept_note_returns_thought_id(pool: sqlx::PgPool) {
content_warning: None,
visibility: "public",
in_reply_to: None,
note_extensions: None,
})
.await
.unwrap();

View File

@@ -35,6 +35,7 @@ struct FeedRow {
t_local: bool,
thought_created_at: DateTime<Utc>,
updated_at: Option<DateTime<Utc>>,
note_extensions: Option<serde_json::Value>,
author_id: uuid::Uuid,
username: String,
email: String,
@@ -82,6 +83,7 @@ fn feed_select(viewer: Option<uuid::Uuid>) -> String {
t.in_reply_to_id,
t.visibility, t.content_warning, t.sensitive, t.local AS t_local,
t.created_at AS thought_created_at, t.updated_at,
t.note_extensions,
u.id AS author_id,
CASE WHEN NOT u.local AND ra.handle IS NOT NULL AND ra.handle != ''
THEN '@' || ra.handle ||
@@ -118,6 +120,7 @@ fn row_to_entry(r: FeedRow, viewer: Option<uuid::Uuid>) -> Result<FeedEntry, Dom
local: r.t_local,
created_at: r.thought_created_at,
updated_at: r.updated_at,
note_extensions: r.note_extensions,
};
let author = User {
id: UserId::from_uuid(r.author_id),

View File

@@ -34,6 +34,7 @@ pub(crate) struct ThoughtRow {
pub local: bool,
pub created_at: DateTime<Utc>,
pub updated_at: Option<DateTime<Utc>>,
pub note_extensions: Option<serde_json::Value>,
}
impl TryFrom<ThoughtRow> for Thought {
@@ -50,12 +51,13 @@ impl TryFrom<ThoughtRow> for Thought {
local: r.local,
created_at: r.created_at,
updated_at: r.updated_at,
note_extensions: r.note_extensions,
})
}
}
const THOUGHT_SELECT: &str =
"SELECT id,user_id,content,in_reply_to_id,visibility,content_warning,sensitive,local,created_at,updated_at FROM thoughts";
"SELECT id,user_id,content,in_reply_to_id,visibility,content_warning,sensitive,local,created_at,updated_at,note_extensions FROM thoughts";
#[async_trait]
impl ThoughtRepository for PgThoughtRepository {
@@ -117,11 +119,11 @@ impl ThoughtRepository for PgThoughtRepository {
sqlx::query_as::<_, ThoughtRow>(
"WITH RECURSIVE thread AS (
SELECT id,user_id,content,in_reply_to_id,
visibility,content_warning,sensitive,local,created_at,updated_at
visibility,content_warning,sensitive,local,created_at,updated_at,note_extensions
FROM thoughts WHERE id = $1
UNION ALL
SELECT t.id,t.user_id,t.content,t.in_reply_to_id,
t.visibility,t.content_warning,t.sensitive,t.local,t.created_at,t.updated_at
t.visibility,t.content_warning,t.sensitive,t.local,t.created_at,t.updated_at,t.note_extensions
FROM thoughts t JOIN thread ON t.in_reply_to_id = thread.id
)
SELECT * FROM thread ORDER BY created_at ASC",