feat: add ApVisibility (Public/FollowersOnly/Private) to broadcast_create_note and broadcast_update_note

This commit is contained in:
2026-05-29 01:15:26 +02:00
parent 4ef1315671
commit e11b0a6609
3 changed files with 51 additions and 5 deletions

View File

@@ -25,7 +25,7 @@ pub use repository::{
BlockedDomain, FederationRepository, Follower, FollowerStatus, FollowingStatus, RemoteActor,
};
pub use service::ActivityPubService;
pub use user::{ApActorType, ApProfileField, ApUser, ApUserRepository, LookedUpActor};
pub use user::{ApActorType, ApProfileField, ApUser, ApUserRepository, ApVisibility, LookedUpActor};
#[cfg(test)]
#[path = "tests/integration.rs"]

View File

@@ -8,6 +8,7 @@ use crate::{
},
actors::get_local_actor,
urls::activity_url,
user::ApVisibility,
};
use super::ActivityPubService;
@@ -168,7 +169,11 @@ impl ActivityPubService {
&self,
local_user_id: uuid::Uuid,
note: serde_json::Value,
visibility: ApVisibility,
) -> anyhow::Result<()> {
if visibility == ApVisibility::Private {
return Ok(());
}
let data = self.federation_config.to_request_data();
let Some((local_actor, inboxes)) = self.accepted_follower_inboxes(&data, local_user_id).await? else { return Ok(()); };
let note_id_str = note["id"].as_str().unwrap_or("");
@@ -177,13 +182,14 @@ impl ActivityPubService {
self.base_url,
uuid::Uuid::new_v5(&uuid::Uuid::NAMESPACE_URL, note_id_str.as_bytes())
)).map_err(|e| anyhow::anyhow!("{e}"))?;
let (to, cc) = visibility_addressing(visibility, &local_actor.followers_url);
let create = CreateActivity {
id: create_id,
kind: Default::default(),
actor: ObjectId::from(local_actor.ap_id.clone()),
object: note,
to: vec![crate::urls::AS_PUBLIC.to_string()],
cc: vec![local_actor.followers_url.to_string()],
to,
cc,
bto: vec![],
bcc: vec![],
};
@@ -195,16 +201,21 @@ impl ActivityPubService {
&self,
local_user_id: uuid::Uuid,
note: serde_json::Value,
visibility: ApVisibility,
) -> anyhow::Result<()> {
if visibility == ApVisibility::Private {
return Ok(());
}
let data = self.federation_config.to_request_data();
let Some((local_actor, inboxes)) = self.accepted_follower_inboxes(&data, local_user_id).await? else { return Ok(()); };
let (to, cc) = visibility_addressing(visibility, &local_actor.followers_url);
let update = crate::activities::UpdateActivity {
id: activity_url(&self.base_url).map_err(|e| anyhow::anyhow!("{e}"))?,
kind: Default::default(),
actor: ObjectId::from(local_actor.ap_id.clone()),
object: note,
to: vec![crate::urls::AS_PUBLIC.to_string()],
cc: vec![local_actor.followers_url.to_string()],
to,
cc,
};
let (json, sends, inboxes) = self.prepare_broadcast(&data, &local_actor, inboxes, update).await?;
self.dispatch_deliveries(&data, &local_actor, inboxes, sends, json).await
@@ -257,3 +268,22 @@ impl ActivityPubService {
Ok(())
}
}
/// Returns `(to, cc)` addressing for the given visibility.
/// `Private` is handled before calling this (early return in broadcast methods).
pub(super) fn visibility_addressing(
visibility: ApVisibility,
followers_url: &Url,
) -> (Vec<String>, Vec<String>) {
match visibility {
ApVisibility::Public => (
vec![crate::urls::AS_PUBLIC.to_string()],
vec![followers_url.to_string()],
),
ApVisibility::FollowersOnly => (
vec![followers_url.to_string()],
vec![],
),
ApVisibility::Private => (vec![], vec![]),
}
}

View File

@@ -8,6 +8,22 @@ pub struct ApProfileField {
pub value: String,
}
/// Visibility of a federated post.
///
/// Controls the `to`/`cc` addressing fields of outbound Create/Update activities
/// and whether the library fans the activity out to followers at all.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum ApVisibility {
/// `to: [AS_PUBLIC], cc: [followers]` — fully public, indexable by search engines.
#[default]
Public,
/// `to: [followers], cc: []` — only followers receive it, not indexed publicly.
FollowersOnly,
/// No federation delivery. The library returns immediately without sending anything.
/// Use when the post should exist only on the local instance.
Private,
}
/// Actor type for AP serialization. Defaults to `Person`.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ApActorType {