Mention all subscribers when creating subscribers-only post
This commit is contained in:
parent
5122fe2b78
commit
9f3b95c41d
5 changed files with 27 additions and 42 deletions
|
@ -20,7 +20,6 @@ use crate::errors::DatabaseError;
|
|||
use crate::frontend::get_tag_page_url;
|
||||
use crate::models::posts::queries::get_post_author;
|
||||
use crate::models::posts::types::{Post, Visibility};
|
||||
use crate::models::profiles::types::DbActorProfile;
|
||||
use crate::models::relationships::queries::{get_followers, get_subscribers};
|
||||
use crate::models::users::types::User;
|
||||
use crate::utils::files::get_file_url;
|
||||
|
@ -59,7 +58,6 @@ pub fn build_note(
|
|||
instance_host: &str,
|
||||
instance_url: &str,
|
||||
post: &Post,
|
||||
subscribers: Vec<DbActorProfile>,
|
||||
) -> Note {
|
||||
let object_id = local_object_id(instance_url, &post.id);
|
||||
let actor_id = local_actor_id(instance_url, &post.author.username);
|
||||
|
@ -95,13 +93,7 @@ pub fn build_note(
|
|||
};
|
||||
|
||||
let mut tags = vec![];
|
||||
let mut mentions = post.mentions.clone();
|
||||
if post.visibility == Visibility::Subscribers {
|
||||
// Mention all subscribers
|
||||
// (for recipients that don't support subscribers-only posts)
|
||||
mentions.extend(subscribers);
|
||||
};
|
||||
for profile in mentions {
|
||||
for profile in &post.mentions {
|
||||
let tag_name = format!("@{}", profile.actor_address(instance_host));
|
||||
let actor_id = profile.actor_id(instance_url);
|
||||
if !primary_audience.contains(&actor_id) {
|
||||
|
@ -154,9 +146,8 @@ pub fn build_create_note(
|
|||
instance_host: &str,
|
||||
instance_url: &str,
|
||||
post: &Post,
|
||||
subscribers: Vec<DbActorProfile>,
|
||||
) -> Activity {
|
||||
let object = build_note(instance_host, instance_url, post, subscribers);
|
||||
let object = build_note(instance_host, instance_url, post);
|
||||
let primary_audience = object.to.clone();
|
||||
let secondary_audience = object.cc.clone();
|
||||
let activity_id = format!("{}/create", object.id);
|
||||
|
@ -212,16 +203,10 @@ pub async fn prepare_create_note(
|
|||
post: &Post,
|
||||
) -> Result<OutgoingActivity<Activity>, DatabaseError> {
|
||||
assert_eq!(author.id, post.author.id);
|
||||
let subscribers = if post.visibility == Visibility::Subscribers {
|
||||
get_subscribers(db_client, &author.id).await?
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
let activity = build_create_note(
|
||||
&instance.host(),
|
||||
&instance.url(),
|
||||
post,
|
||||
subscribers,
|
||||
);
|
||||
let recipients = get_note_recipients(db_client, author, post).await?;
|
||||
Ok(OutgoingActivity {
|
||||
|
@ -235,6 +220,7 @@ pub async fn prepare_create_note(
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serde_json::json;
|
||||
use crate::models::profiles::types::DbActorProfile;
|
||||
use super::*;
|
||||
|
||||
const INSTANCE_HOST: &str = "example.com";
|
||||
|
@ -247,7 +233,7 @@ mod tests {
|
|||
..Default::default()
|
||||
};
|
||||
let post = Post { author, ..Default::default() };
|
||||
let note = build_note(INSTANCE_HOST, INSTANCE_URL, &post, vec![]);
|
||||
let note = build_note(INSTANCE_HOST, INSTANCE_URL, &post);
|
||||
|
||||
assert_eq!(
|
||||
note.id,
|
||||
|
@ -272,7 +258,7 @@ mod tests {
|
|||
visibility: Visibility::Followers,
|
||||
..Default::default()
|
||||
};
|
||||
let note = build_note(INSTANCE_HOST, INSTANCE_URL, &post, vec![]);
|
||||
let note = build_note(INSTANCE_HOST, INSTANCE_URL, &post);
|
||||
|
||||
assert_eq!(note.to, vec![
|
||||
local_actor_followers(INSTANCE_URL, &post.author.username),
|
||||
|
@ -282,10 +268,6 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_build_note_subscribers_only() {
|
||||
let post = Post {
|
||||
visibility: Visibility::Subscribers,
|
||||
..Default::default()
|
||||
};
|
||||
let subscriber_id = "https://test.com/users/3";
|
||||
let subscriber = DbActorProfile {
|
||||
username: "subscriber".to_string(),
|
||||
|
@ -296,7 +278,12 @@ mod tests {
|
|||
actor_id: Some(subscriber_id.to_string()),
|
||||
..Default::default()
|
||||
};
|
||||
let note = build_note(INSTANCE_HOST, INSTANCE_URL, &post, vec![subscriber]);
|
||||
let post = Post {
|
||||
visibility: Visibility::Subscribers,
|
||||
mentions: vec![subscriber],
|
||||
..Default::default()
|
||||
};
|
||||
let note = build_note(INSTANCE_HOST, INSTANCE_URL, &post);
|
||||
|
||||
assert_eq!(note.to, vec![
|
||||
local_actor_subscribers(INSTANCE_URL, &post.author.username),
|
||||
|
@ -322,7 +309,7 @@ mod tests {
|
|||
mentions: vec![mentioned],
|
||||
..Default::default()
|
||||
};
|
||||
let note = build_note(INSTANCE_HOST, INSTANCE_URL, &post, vec![]);
|
||||
let note = build_note(INSTANCE_HOST, INSTANCE_URL, &post);
|
||||
|
||||
assert_eq!(note.to, vec![mentioned_id]);
|
||||
assert_eq!(note.cc.is_empty(), true);
|
||||
|
@ -336,7 +323,7 @@ mod tests {
|
|||
in_reply_to: Some(Box::new(parent.clone())),
|
||||
..Default::default()
|
||||
};
|
||||
let note = build_note(INSTANCE_HOST, INSTANCE_URL, &post, vec![]);
|
||||
let note = build_note(INSTANCE_HOST, INSTANCE_URL, &post);
|
||||
|
||||
assert_eq!(
|
||||
note.in_reply_to.unwrap(),
|
||||
|
@ -374,7 +361,7 @@ mod tests {
|
|||
mentions: vec![parent_author],
|
||||
..Default::default()
|
||||
};
|
||||
let note = build_note(INSTANCE_HOST, INSTANCE_URL, &post, vec![]);
|
||||
let note = build_note(INSTANCE_HOST, INSTANCE_URL, &post);
|
||||
|
||||
assert_eq!(
|
||||
note.in_reply_to.unwrap(),
|
||||
|
@ -399,7 +386,6 @@ mod tests {
|
|||
INSTANCE_HOST,
|
||||
INSTANCE_URL,
|
||||
&post,
|
||||
vec![],
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
|
|
|
@ -7,9 +7,7 @@ use crate::activitypub::deliverer::OutgoingActivity;
|
|||
use crate::activitypub::vocabulary::{DELETE, NOTE, TOMBSTONE};
|
||||
use crate::config::Instance;
|
||||
use crate::errors::DatabaseError;
|
||||
use crate::models::posts::types::{Post, Visibility};
|
||||
use crate::models::profiles::types::DbActorProfile;
|
||||
use crate::models::relationships::queries::get_subscribers;
|
||||
use crate::models::posts::types::Post;
|
||||
use crate::models::users::types::User;
|
||||
use super::create_note::{
|
||||
build_note,
|
||||
|
@ -21,7 +19,6 @@ fn build_delete_note(
|
|||
instance_host: &str,
|
||||
instance_url: &str,
|
||||
post: &Post,
|
||||
subscribers: Vec<DbActorProfile>,
|
||||
) -> Activity {
|
||||
let object_id = post.get_object_id(instance_url);
|
||||
let object = Object {
|
||||
|
@ -36,7 +33,6 @@ fn build_delete_note(
|
|||
instance_host,
|
||||
instance_url,
|
||||
post,
|
||||
subscribers,
|
||||
);
|
||||
let activity = create_activity(
|
||||
instance_url,
|
||||
|
@ -57,16 +53,10 @@ pub async fn prepare_delete_note(
|
|||
post: &Post,
|
||||
) -> Result<OutgoingActivity<Activity>, DatabaseError> {
|
||||
assert_eq!(author.id, post.author.id);
|
||||
let subscribers = if post.visibility == Visibility::Subscribers {
|
||||
get_subscribers(db_client, &author.id).await?
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
let activity = build_delete_note(
|
||||
&instance.host(),
|
||||
&instance.url(),
|
||||
post,
|
||||
subscribers,
|
||||
);
|
||||
let recipients = get_note_recipients(db_client, author, post).await?;
|
||||
Ok(OutgoingActivity {
|
||||
|
@ -84,6 +74,7 @@ mod tests {
|
|||
constants::AP_PUBLIC,
|
||||
identifiers::local_actor_followers,
|
||||
};
|
||||
use crate::models::profiles::types::DbActorProfile;
|
||||
use super::*;
|
||||
|
||||
const INSTANCE_HOST: &str = "example.com";
|
||||
|
@ -100,7 +91,6 @@ mod tests {
|
|||
INSTANCE_HOST,
|
||||
INSTANCE_URL,
|
||||
&post,
|
||||
vec![],
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
|
|
|
@ -146,7 +146,6 @@ async fn outbox(
|
|||
&instance.host(),
|
||||
&instance.url(),
|
||||
post,
|
||||
vec![], // subscribers-only posts are not included
|
||||
);
|
||||
Some(activity)
|
||||
}).collect();
|
||||
|
@ -300,7 +299,6 @@ pub async fn object_view(
|
|||
&config.instance().host(),
|
||||
&config.instance().url(),
|
||||
&post,
|
||||
vec![], // subscribers-only posts are not accessible
|
||||
);
|
||||
let response = HttpResponse::Ok()
|
||||
.content_type(ACTIVITY_CONTENT_TYPE)
|
||||
|
|
|
@ -38,6 +38,7 @@ use crate::models::reactions::queries::{
|
|||
create_reaction,
|
||||
delete_reaction,
|
||||
};
|
||||
use crate::models::relationships::queries::get_subscribers;
|
||||
use crate::utils::currencies::Currency;
|
||||
use super::helpers::{
|
||||
build_status,
|
||||
|
@ -71,6 +72,15 @@ async fn create_status(
|
|||
);
|
||||
post_data.mentions.extend(mention_map.values()
|
||||
.map(|profile| profile.id));
|
||||
if post_data.visibility == Visibility::Subscribers {
|
||||
// Mention all subscribers.
|
||||
// This makes post accessible only to active subscribers
|
||||
// and is required for sending activities to subscribers
|
||||
// on other instances.
|
||||
let subscribers = get_subscribers(db_client, ¤t_user.id).await?
|
||||
.into_iter().map(|profile| profile.id);
|
||||
post_data.mentions.extend(subscribers);
|
||||
};
|
||||
post_data.mentions.sort();
|
||||
post_data.mentions.dedup();
|
||||
// Hashtags
|
||||
|
|
|
@ -263,6 +263,7 @@ fn build_visibility_filter() -> String {
|
|||
AND target_id = post.author_id
|
||||
AND relationship_type = {relationship_follow}
|
||||
)
|
||||
-- TODO: remove and rely on mentions instead
|
||||
OR post.visibility = {visibility_subscribers} AND EXISTS (
|
||||
SELECT 1 FROM relationship
|
||||
WHERE
|
||||
|
|
Loading…
Reference in a new issue