Undo(Announce): now removes announce record from ActorRepository and
calls ApObjectHandler::on_announce_removed (default no-op, override
to decrement boost counts). Announce counts no longer drift.
Undo(Block): now logged at info level instead of silently ignored.
No automatic relationship restoration (spec doesn't require it).
AddActivity: now uses object["id"] as the stable ap_id (same as
CreateActivity), falling back to activity id only if object has no
id field. Fixes keying watchlist/collection items by the wrong id.
Featured collection: GET /users/{id}/featured now served by the router.
ApContentReader::get_featured_objects() has a default empty-list impl
— override to expose pinned posts without any breaking changes.
43 lines
1.5 KiB
Rust
43 lines
1.5 KiB
Rust
use activitypub_federation::{axum::json::FederationJson, config::Data};
|
|
use axum::extract::Path;
|
|
use serde_json::json;
|
|
|
|
use crate::data::FederationData;
|
|
use crate::error::Error;
|
|
use crate::urls::AP_CONTEXT;
|
|
|
|
/// Serves the `featured` (pinned posts) `OrderedCollection` for a local user.
|
|
///
|
|
/// Remote servers follow the `featured` link from the actor JSON and expect
|
|
/// an `OrderedCollection` whose `orderedItems` are the AP URLs of pinned objects.
|
|
/// The handler calls [`ApContentReader::get_featured_objects`] — override that
|
|
/// method to expose your pinned posts.
|
|
pub async fn featured_handler(
|
|
Path(user_id_str): Path<String>,
|
|
data: Data<FederationData>,
|
|
) -> Result<FederationJson<serde_json::Value>, Error> {
|
|
let user_id = uuid::Uuid::parse_str(&user_id_str)
|
|
.map_err(|_| Error::not_found(anyhow::anyhow!("user not found")))?;
|
|
|
|
data.user_repo
|
|
.find_by_id(user_id)
|
|
.await
|
|
.map_err(Error::from)?
|
|
.ok_or_else(|| Error::not_found(anyhow::anyhow!("user not found")))?;
|
|
|
|
let featured_url = format!("{}/users/{}/featured", data.base_url, user_id_str);
|
|
let items = data
|
|
.content_reader
|
|
.get_featured_objects(user_id)
|
|
.await
|
|
.map_err(|e| Error::from(anyhow::anyhow!("{}", e)))?;
|
|
|
|
Ok(FederationJson(json!({
|
|
"@context": AP_CONTEXT,
|
|
"type": "OrderedCollection",
|
|
"id": featured_url,
|
|
"totalItems": items.len(),
|
|
"orderedItems": items.iter().map(|u| u.as_str()).collect::<Vec<_>>(),
|
|
})))
|
|
}
|