feat: add ApVisibility (Public/FollowersOnly/Private) to broadcast_create_note and broadcast_update_note
This commit is contained in:
@@ -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"]
|
||||
|
||||
@@ -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![]),
|
||||
}
|
||||
}
|
||||
|
||||
16
src/user.rs
16
src/user.rs
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user