From cefa4a4ddca9566c11351f10b8be2747853bbf4e Mon Sep 17 00:00:00 2001 From: sugyan Date: Wed, 5 Jun 2024 22:26:44 +0900 Subject: [PATCH] Add moderation::tests::quoteposts --- bsky-sdk/src/moderation/decision.rs | 6 +- bsky-sdk/src/moderation/subjects/post.rs | 75 +++- bsky-sdk/src/moderation/tests.rs | 95 ++-- bsky-sdk/src/moderation/tests/behaviors.rs | 416 +++++++++--------- .../src/moderation/tests/custom_labels.rs | 86 ++-- bsky-sdk/src/moderation/tests/quoteposts.rs | 282 ++++++++++++ 6 files changed, 643 insertions(+), 317 deletions(-) create mode 100644 bsky-sdk/src/moderation/tests/quoteposts.rs diff --git a/bsky-sdk/src/moderation/decision.rs b/bsky-sdk/src/moderation/decision.rs index 41918379..fd84cc47 100644 --- a/bsky-sdk/src/moderation/decision.rs +++ b/bsky-sdk/src/moderation/decision.rs @@ -204,9 +204,9 @@ impl ModerationDecision { } pub(crate) fn merge(decisions: &[Self]) -> Self { assert!(!decisions.is_empty()); - assert!(decisions - .windows(2) - .all(|w| w[0].did == w[1].did && w[0].is_me == w[1].is_me)); + // assert!(decisions + // .windows(2) + // .all(|w| w[0].did == w[1].did && w[0].is_me == w[1].is_me)); Self { did: decisions[0].did.clone(), is_me: decisions[0].is_me, diff --git a/bsky-sdk/src/moderation/subjects/post.rs b/bsky-sdk/src/moderation/subjects/post.rs index a0b01b07..e03dcd09 100644 --- a/bsky-sdk/src/moderation/subjects/post.rs +++ b/bsky-sdk/src/moderation/subjects/post.rs @@ -2,6 +2,8 @@ use super::super::decision::ModerationDecision; use super::super::types::{LabelTarget, SubjectPost}; use super::super::Moderator; use atrium_api::app::bsky::actor::defs::MutedWord; +use atrium_api::app::bsky::embed::record::{ViewBlocked, ViewRecord, ViewRecordRefs}; +use atrium_api::app::bsky::feed::defs::PostViewEmbedRefs; use atrium_api::app::bsky::richtext::facet::MainFeaturesItem; use atrium_api::records::{KnownRecord, Record}; use atrium_api::types::Union; @@ -29,10 +31,35 @@ impl Moderator { acc.add_muted_word(); } - let embed_acc = Option::::None; - if let Some(Union::Refs(embed)) = &subject.embed { - todo!() - } + let embed_acc = match &subject.embed { + Some(Union::Refs(PostViewEmbedRefs::AppBskyEmbedRecordView(view))) => { + match &view.record { + Union::Refs(ViewRecordRefs::ViewRecord(record)) => { + // quoted post + Some(self.decide_quoted_post(record)) + } + Union::Refs(ViewRecordRefs::ViewBlocked(blocked)) => { + // blocked quote post + Some(self.decide_bloked_quoted_post(blocked)) + } + _ => None, + } + } + Some(Union::Refs(PostViewEmbedRefs::AppBskyEmbedRecordWithMediaView(view))) => { + match &view.record.record { + Union::Refs(ViewRecordRefs::ViewRecord(record)) => { + // quoted post with media + Some(self.decide_quoted_post(record)) + } + Union::Refs(ViewRecordRefs::ViewBlocked(blocked)) => { + // blocked quote post with media + Some(self.decide_bloked_quoted_post(blocked)) + } + _ => None, + } + } + _ => None, + }; let mut decisions = vec![acc]; if let Some(mut embed_acc) = embed_acc { @@ -43,6 +70,46 @@ impl Moderator { decisions.extend([self.decide_account(&author), self.decide_profile(&author)]); ModerationDecision::merge(&decisions) } + fn decide_quoted_post(&self, subject: &ViewRecord) -> ModerationDecision { + let mut acc = ModerationDecision::new(); + acc.set_did(subject.author.did.clone()); + acc.set_is_me(self.user_did.as_ref() == Some(&subject.author.did)); + if let Some(labels) = &subject.labels { + for label in labels { + acc.add_label(LabelTarget::Content, label, self); + } + } + ModerationDecision::merge(&[ + acc, + self.decide_account(&subject.author.clone().into()), + self.decide_profile(&subject.author.clone().into()), + ]) + } + fn decide_bloked_quoted_post(&self, subject: &ViewBlocked) -> ModerationDecision { + let mut acc = ModerationDecision::new(); + acc.set_did(subject.author.did.clone()); + acc.set_is_me(self.user_did.as_ref() == Some(&subject.author.did)); + if let Some(viewer) = &subject.author.viewer { + if viewer.muted.unwrap_or_default() { + if let Some(list_view) = &viewer.muted_by_list { + acc.add_muted_by_list(list_view); + } else { + acc.add_muted(); + } + } + if viewer.blocking.is_some() { + if let Some(list_view) = &viewer.blocking_by_list { + acc.add_blocking_by_list(list_view); + } else { + acc.add_blocking(); + } + } + if viewer.blocked_by.unwrap_or_default() { + acc.add_blocked_by(); + } + } + acc + } } fn check_muted_words(subject: &SubjectPost, muted_words: &[MutedWord]) -> bool { diff --git a/bsky-sdk/src/moderation/tests.rs b/bsky-sdk/src/moderation/tests.rs index 75ab025b..6b970446 100644 --- a/bsky-sdk/src/moderation/tests.rs +++ b/bsky-sdk/src/moderation/tests.rs @@ -1,6 +1,7 @@ mod behaviors; mod custom_labels; mod mutewords; +mod quoteposts; use crate::moderation::decision::{DecisionContext, ModerationDecision}; use crate::moderation::types::*; @@ -16,7 +17,7 @@ use std::collections::HashMap; const FAKE_CID: &str = "bafyreiclp443lavogvhj3d2ob2cxbfuscni2k5jk7bebjzg7khl3esabwq"; #[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum ModerationTestResultFlag { +enum ResultFlag { Filter, Blur, Alert, @@ -25,19 +26,19 @@ enum ModerationTestResultFlag { } #[derive(Debug, Default)] -struct TestExpectedBehaviors { - profile_list: Vec, - profile_view: Vec, - avatar: Vec, - banner: Vec, - display_name: Vec, - content_list: Vec, - content_view: Vec, - content_media: Vec, +struct ExpectedBehaviors { + profile_list: Vec, + profile_view: Vec, + avatar: Vec, + banner: Vec, + display_name: Vec, + content_list: Vec, + content_view: Vec, + content_media: Vec, } -impl TestExpectedBehaviors { - fn expected_for(&self, context: DecisionContext) -> &Vec { +impl ExpectedBehaviors { + fn expected_for(&self, context: DecisionContext) -> &Vec { match context { DecisionContext::ProfileList => &self.profile_list, DecisionContext::ProfileView => &self.profile_view, @@ -110,11 +111,7 @@ fn label(src: &str, uri: &str, val: &str) -> Label { } } -fn assert_ui( - decision: &ModerationDecision, - expected: &[ModerationTestResultFlag], - context: DecisionContext, -) { +fn assert_ui(decision: &ModerationDecision, expected: &[ResultFlag], context: DecisionContext) { let ui = decision.ui(context); if expected.is_empty() { assert!( @@ -137,31 +134,31 @@ fn assert_ui( } else { assert_eq!( ui.inform(), - expected.contains(&ModerationTestResultFlag::Inform), + expected.contains(&ResultFlag::Inform), "inform should be {} for context {context:?}", !ui.inform() ); assert_eq!( ui.alert(), - expected.contains(&ModerationTestResultFlag::Alert), + expected.contains(&ResultFlag::Alert), "alert should be {} for context {context:?}", !ui.alert() ); assert_eq!( ui.blur(), - expected.contains(&ModerationTestResultFlag::Blur), + expected.contains(&ResultFlag::Blur), "blur should be {} for context {context:?}", !ui.blur() ); assert_eq!( ui.filter(), - expected.contains(&ModerationTestResultFlag::Filter), + expected.contains(&ResultFlag::Filter), "filter should be {} for context {context:?}", !ui.filter() ); assert_eq!( ui.no_override, - expected.contains(&ModerationTestResultFlag::NoOverride), + expected.contains(&ResultFlag::NoOverride), "no_override should be {} for context {context:?}", !ui.no_override ); @@ -191,11 +188,7 @@ fn self_label_global() { HashMap::new(), ); let result = moderator.moderate_profile(&profile); - assert_ui( - &result, - &[ModerationTestResultFlag::Blur], - DecisionContext::Avatar, - ) + assert_ui(&result, &[ResultFlag::Blur], DecisionContext::Avatar) } // porn (ignore) { @@ -350,8 +343,8 @@ fn prioritize_custom_labels() { )); for context in DecisionContext::ALL { let expected = match context { - DecisionContext::ContentList => vec![ModerationTestResultFlag::Inform], - DecisionContext::ContentView => vec![ModerationTestResultFlag::Inform], + DecisionContext::ContentList => vec![ResultFlag::Inform], + DecisionContext::ContentView => vec![ResultFlag::Inform], _ => vec![], }; assert_ui(&result, &expected, context); @@ -399,15 +392,10 @@ fn does_not_override_imperative_labels() { )); for context in DecisionContext::ALL { let expected = match context { - DecisionContext::ContentList => vec![ - ModerationTestResultFlag::Filter, - ModerationTestResultFlag::Blur, - ModerationTestResultFlag::NoOverride, - ], - DecisionContext::ContentView => vec![ - ModerationTestResultFlag::Blur, - ModerationTestResultFlag::NoOverride, - ], + DecisionContext::ContentList => { + vec![ResultFlag::Filter, ResultFlag::Blur, ResultFlag::NoOverride] + } + DecisionContext::ContentView => vec![ResultFlag::Blur, ResultFlag::NoOverride], _ => vec![], }; assert_ui(&result, &expected, context); @@ -551,11 +539,8 @@ fn custom_labels_with_default_settings() { )); for context in DecisionContext::ALL { let expected = match context { - DecisionContext::ContentList => vec![ - ModerationTestResultFlag::Filter, - ModerationTestResultFlag::Blur, - ], - DecisionContext::ContentView => vec![ModerationTestResultFlag::Inform], + DecisionContext::ContentList => vec![ResultFlag::Filter, ResultFlag::Blur], + DecisionContext::ContentView => vec![ResultFlag::Inform], _ => vec![], }; assert_ui(&result, &expected, context); @@ -573,8 +558,8 @@ fn custom_labels_with_default_settings() { )); for context in DecisionContext::ALL { let expected = match context { - DecisionContext::ContentList => vec![ModerationTestResultFlag::Blur], - DecisionContext::ContentView => vec![ModerationTestResultFlag::Inform], + DecisionContext::ContentList => vec![ResultFlag::Blur], + DecisionContext::ContentView => vec![ResultFlag::Inform], _ => vec![], }; assert_ui(&result, &expected, context); @@ -637,15 +622,10 @@ fn custom_labels_require_adult_content_enabled() { )); for context in DecisionContext::ALL { let expected = match context { - DecisionContext::ContentList => vec![ - ModerationTestResultFlag::Filter, - ModerationTestResultFlag::Blur, - ModerationTestResultFlag::NoOverride, - ], - DecisionContext::ContentView => vec![ - ModerationTestResultFlag::Blur, - ModerationTestResultFlag::NoOverride, - ], + DecisionContext::ContentList => { + vec![ResultFlag::Filter, ResultFlag::Blur, ResultFlag::NoOverride] + } + DecisionContext::ContentView => vec![ResultFlag::Blur, ResultFlag::NoOverride], _ => vec![], }; assert_ui(&result, &expected, context); @@ -679,11 +659,8 @@ fn adult_content_disabled_forces_hide() { )); for context in DecisionContext::ALL { let expected = match context { - DecisionContext::ContentList => vec![ModerationTestResultFlag::Filter], - DecisionContext::ContentMedia => vec![ - ModerationTestResultFlag::Blur, - ModerationTestResultFlag::NoOverride, - ], + DecisionContext::ContentList => vec![ResultFlag::Filter], + DecisionContext::ContentMedia => vec![ResultFlag::Blur, ResultFlag::NoOverride], _ => vec![], }; assert_ui(&result, &expected, context); diff --git a/bsky-sdk/src/moderation/tests/behaviors.rs b/bsky-sdk/src/moderation/tests/behaviors.rs index 8bc78dc2..ee8b8d26 100644 --- a/bsky-sdk/src/moderation/tests/behaviors.rs +++ b/bsky-sdk/src/moderation/tests/behaviors.rs @@ -1,5 +1,5 @@ use super::{assert_ui, label, post_view, profile_view_basic}; -use super::{ModerationTestResultFlag, TestExpectedBehaviors, FAKE_CID}; +use super::{ExpectedBehaviors, ResultFlag, FAKE_CID}; use crate::moderation::decision::DecisionContext; use crate::moderation::types::*; use crate::moderation::Moderator; @@ -146,22 +146,22 @@ impl AsRef for TestUser { } #[derive(Debug, Default)] -struct TestScenarioLabels { +struct TestLabels { post: Vec, profile: Vec, account: Vec, } #[derive(Debug)] -struct BehaviorsTestScenario { +struct Scenario { cfg: TestConfig, subject: TestSubject, author: TestUser, - labels: TestScenarioLabels, - behaviors: TestExpectedBehaviors, + labels: TestLabels, + behaviors: ExpectedBehaviors, } -impl BehaviorsTestScenario { +impl Scenario { fn run(&self) { let moderator = self.moderator(); let result = match self.subject { @@ -264,19 +264,19 @@ impl BehaviorsTestScenario { #[test] fn moderation_behaviors() { - use ModerationTestResultFlag::*; + use ResultFlag::*; let scenarios = [ ( "Imperative label ('!hide') on account", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Profile, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { account: vec![String::from("!hide")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { profile_list: vec![Filter, Blur, NoOverride], profile_view: vec![Blur, NoOverride], avatar: vec![Blur, NoOverride], @@ -290,15 +290,15 @@ fn moderation_behaviors() { ), ( "Imperative label ('!hide') on profile", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Profile, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { profile: vec![String::from("!hide")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { avatar: vec![Blur, NoOverride], banner: vec![Blur, NoOverride], display_name: vec![Blur, NoOverride], @@ -308,15 +308,15 @@ fn moderation_behaviors() { ), ( "Imperative label ('!hide') on post", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { post: vec![String::from("!hide")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { content_list: vec![Filter, Blur, NoOverride], content_view: vec![Blur, NoOverride], ..Default::default() @@ -325,15 +325,15 @@ fn moderation_behaviors() { ), ( "Imperative label ('!hide') on author profile", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { profile: vec![String::from("!hide")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { avatar: vec![Blur, NoOverride], banner: vec![Blur, NoOverride], display_name: vec![Blur, NoOverride], @@ -343,15 +343,15 @@ fn moderation_behaviors() { ), ( "Imperative label ('!hide') on author account", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { account: vec![String::from("!hide")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { avatar: vec![Blur, NoOverride], banner: vec![Blur, NoOverride], display_name: vec![Blur, NoOverride], @@ -363,15 +363,15 @@ fn moderation_behaviors() { ), ( "Imperative label ('!warn') on account", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Profile, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { account: vec![String::from("!warn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { profile_list: vec![Blur], profile_view: vec![Blur], avatar: vec![Blur], @@ -384,15 +384,15 @@ fn moderation_behaviors() { ), ( "Imperative label ('!warn') on profile", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Profile, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { profile: vec![String::from("!warn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { avatar: vec![Blur], banner: vec![Blur], display_name: vec![Blur], @@ -402,15 +402,15 @@ fn moderation_behaviors() { ), ( "Imperative label ('!warn') on post", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { post: vec![String::from("!warn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { content_list: vec![Blur], content_view: vec![Blur], ..Default::default() @@ -419,15 +419,15 @@ fn moderation_behaviors() { ), ( "Imperative label ('!warn') on author profile", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { profile: vec![String::from("!warn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { avatar: vec![Blur], banner: vec![Blur], display_name: vec![Blur], @@ -437,15 +437,15 @@ fn moderation_behaviors() { ), ( "Imperative label ('!warn') on author account", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { account: vec![String::from("!warn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { avatar: vec![Blur], banner: vec![Blur], content_list: vec![Blur], @@ -456,15 +456,15 @@ fn moderation_behaviors() { ), ( "Imperative label ('!no-unauthenticated') on account when logged out", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::LoggedOut, subject: TestSubject::Profile, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { account: vec![String::from("!no-unauthenticated")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { profile_list: vec![Filter, Blur, NoOverride], profile_view: vec![Blur, NoOverride], avatar: vec![Blur, NoOverride], @@ -478,15 +478,15 @@ fn moderation_behaviors() { ), ( "Imperative label ('!no-unauthenticated') on profile when logged out", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::LoggedOut, subject: TestSubject::Profile, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { profile: vec![String::from("!no-unauthenticated")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { profile_list: vec![Filter, Blur, NoOverride], profile_view: vec![Blur, NoOverride], avatar: vec![Blur, NoOverride], @@ -500,15 +500,15 @@ fn moderation_behaviors() { ), ( "Imperative label ('!no-unauthenticated') on post when logged out", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::LoggedOut, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { post: vec![String::from("!no-unauthenticated")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { content_list: vec![Filter, Blur, NoOverride], content_view: vec![Blur, NoOverride], ..Default::default() @@ -517,15 +517,15 @@ fn moderation_behaviors() { ), ( "Imperative label ('!no-unauthenticated') on author profile when logged out", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::LoggedOut, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { profile: vec![String::from("!no-unauthenticated")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { avatar: vec![Blur, NoOverride], banner: vec![Blur, NoOverride], display_name: vec![Blur, NoOverride], @@ -537,15 +537,15 @@ fn moderation_behaviors() { ), ( "Imperative label ('!no-unauthenticated') on author account when logged out", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::LoggedOut, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { account: vec![String::from("!no-unauthenticated")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { avatar: vec![Blur, NoOverride], banner: vec![Blur, NoOverride], display_name: vec![Blur, NoOverride], @@ -557,80 +557,80 @@ fn moderation_behaviors() { ), ( "Imperative label ('!no-unauthenticated') on account when logged in", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Profile, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { account: vec![String::from("!no-unauthenticated")], ..Default::default() }, - behaviors: TestExpectedBehaviors::default(), + behaviors: ExpectedBehaviors::default(), }, ), ( "Imperative label ('!no-unauthenticated') on profile when logged in", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Profile, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { profile: vec![String::from("!no-unauthenticated")], ..Default::default() }, - behaviors: TestExpectedBehaviors::default(), + behaviors: ExpectedBehaviors::default(), }, ), ( "Imperative label ('!no-unauthenticated') on post when logged in", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { post: vec![String::from("!no-unauthenticated")], ..Default::default() }, - behaviors: TestExpectedBehaviors::default(), + behaviors: ExpectedBehaviors::default(), }, ), ( "Imperative label ('!no-unauthenticated') on author profile when logged in", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { profile: vec![String::from("!no-unauthenticated")], ..Default::default() }, - behaviors: TestExpectedBehaviors::default(), + behaviors: ExpectedBehaviors::default(), }, ), ( "Imperative label ('!no-unauthenticated') on author account when logged in", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { account: vec![String::from("!no-unauthenticated")], ..Default::default() }, - behaviors: TestExpectedBehaviors::default(), + behaviors: ExpectedBehaviors::default(), }, ), ( "Blur-media label ('porn') on account (hide)", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::PornHide, subject: TestSubject::Profile, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { account: vec![String::from("porn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { profile_list: vec![Filter], avatar: vec![Blur], banner: vec![Blur], @@ -641,15 +641,15 @@ fn moderation_behaviors() { ), ( "Blur-media label ('porn') on profile (hide)", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::PornHide, subject: TestSubject::Profile, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { profile: vec![String::from("porn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { avatar: vec![Blur], banner: vec![Blur], ..Default::default() @@ -658,15 +658,15 @@ fn moderation_behaviors() { ), ( "Blur-media label ('porn') on post (hide)", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::PornHide, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { post: vec![String::from("porn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { content_list: vec![Filter], content_media: vec![Blur], ..Default::default() @@ -675,15 +675,15 @@ fn moderation_behaviors() { ), ( "Blur-media label ('porn') on author profile (hide)", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::PornHide, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { profile: vec![String::from("porn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { avatar: vec![Blur], banner: vec![Blur], ..Default::default() @@ -692,15 +692,15 @@ fn moderation_behaviors() { ), ( "Blur-media label ('porn') on author account (hide)", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::PornHide, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { account: vec![String::from("porn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { profile_list: vec![Filter], avatar: vec![Blur], banner: vec![Blur], @@ -711,15 +711,15 @@ fn moderation_behaviors() { ), ( "Blur-media label ('porn') on account (warn)", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::PornWarn, subject: TestSubject::Profile, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { account: vec![String::from("porn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { avatar: vec![Blur], banner: vec![Blur], ..Default::default() @@ -728,15 +728,15 @@ fn moderation_behaviors() { ), ( "Blur-media label ('porn') on profile (warn)", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::PornWarn, subject: TestSubject::Profile, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { profile: vec![String::from("porn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { avatar: vec![Blur], banner: vec![Blur], ..Default::default() @@ -745,15 +745,15 @@ fn moderation_behaviors() { ), ( "Blur-media label ('porn') on post (warn)", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::PornWarn, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { post: vec![String::from("porn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { content_media: vec![Blur], ..Default::default() }, @@ -761,15 +761,15 @@ fn moderation_behaviors() { ), ( "Blur-media label ('porn') on author profile (warn)", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::PornWarn, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { profile: vec![String::from("porn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { avatar: vec![Blur], banner: vec![Blur], ..Default::default() @@ -778,15 +778,15 @@ fn moderation_behaviors() { ), ( "Blur-media label ('porn') on author account (warn)", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::PornWarn, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { account: vec![String::from("porn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { avatar: vec![Blur], banner: vec![Blur], ..Default::default() @@ -795,80 +795,80 @@ fn moderation_behaviors() { ), ( "Blur-media label ('porn') on account (ignore)", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::PornIgnore, subject: TestSubject::Profile, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { account: vec![String::from("porn")], ..Default::default() }, - behaviors: TestExpectedBehaviors::default(), + behaviors: ExpectedBehaviors::default(), }, ), ( "Blur-media label ('porn') on profile (ignore)", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::PornIgnore, subject: TestSubject::Profile, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { profile: vec![String::from("porn")], ..Default::default() }, - behaviors: TestExpectedBehaviors::default(), + behaviors: ExpectedBehaviors::default(), }, ), ( "Blur-media label ('porn') on post (ignore)", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::PornIgnore, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { post: vec![String::from("porn")], ..Default::default() }, - behaviors: TestExpectedBehaviors::default(), + behaviors: ExpectedBehaviors::default(), }, ), ( "Blur-media label ('porn') on author profile (ignore)", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::PornIgnore, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { profile: vec![String::from("porn")], ..Default::default() }, - behaviors: TestExpectedBehaviors::default(), + behaviors: ExpectedBehaviors::default(), }, ), ( "Blur-media label ('porn') on author account (ignore)", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::PornIgnore, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { account: vec![String::from("porn")], ..Default::default() }, - behaviors: TestExpectedBehaviors::default(), + behaviors: ExpectedBehaviors::default(), }, ), ( "Adult-only label on account when adult content is disabled", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::AdultDisabled, subject: TestSubject::Profile, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { account: vec![String::from("porn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { profile_list: vec![Filter], avatar: vec![Blur, NoOverride], banner: vec![Blur, NoOverride], @@ -879,15 +879,15 @@ fn moderation_behaviors() { ), ( "Adult-only label on profile when adult content is disabled", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::AdultDisabled, subject: TestSubject::Profile, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { profile: vec![String::from("porn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { avatar: vec![Blur, NoOverride], banner: vec![Blur, NoOverride], ..Default::default() @@ -896,15 +896,15 @@ fn moderation_behaviors() { ), ( "Adult-only label on post when adult content is disabled", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::AdultDisabled, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { post: vec![String::from("porn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { content_list: vec![Filter], content_media: vec![Blur, NoOverride], ..Default::default() @@ -913,15 +913,15 @@ fn moderation_behaviors() { ), ( "Adult-only label on author profile when adult content is disabled", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::AdultDisabled, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { profile: vec![String::from("porn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { avatar: vec![Blur, NoOverride], banner: vec![Blur, NoOverride], ..Default::default() @@ -930,15 +930,15 @@ fn moderation_behaviors() { ), ( "Adult-only label on author account when adult content is disabled", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::AdultDisabled, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { account: vec![String::from("porn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { avatar: vec![Blur, NoOverride], banner: vec![Blur, NoOverride], content_list: vec![Filter], @@ -948,15 +948,15 @@ fn moderation_behaviors() { ), ( "Self-profile: !hide on account", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Profile, author: TestUser::UserSelf, - labels: TestScenarioLabels { + labels: TestLabels { account: vec![String::from("!hide")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { profile_list: vec![Blur], profile_view: vec![Blur], avatar: vec![Blur], @@ -970,15 +970,15 @@ fn moderation_behaviors() { ), ( "Self-profile: !hide on profile", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Profile, author: TestUser::UserSelf, - labels: TestScenarioLabels { + labels: TestLabels { profile: vec![String::from("!hide")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { avatar: vec![Blur], banner: vec![Blur], display_name: vec![Blur], @@ -988,15 +988,15 @@ fn moderation_behaviors() { ), ( "Self-post: Imperative label ('!hide') on post", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Post, author: TestUser::UserSelf, - labels: TestScenarioLabels { + labels: TestLabels { post: vec![String::from("!hide")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { content_list: vec![Blur], content_view: vec![Blur], ..Default::default() @@ -1005,15 +1005,15 @@ fn moderation_behaviors() { ), ( "Self-post: Imperative label ('!hide') on author profile", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Post, author: TestUser::UserSelf, - labels: TestScenarioLabels { + labels: TestLabels { profile: vec![String::from("!hide")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { avatar: vec![Blur], banner: vec![Blur], display_name: vec![Blur], @@ -1023,15 +1023,15 @@ fn moderation_behaviors() { ), ( "Self-post: Imperative label ('!hide') on author account", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Post, author: TestUser::UserSelf, - labels: TestScenarioLabels { + labels: TestLabels { account: vec![String::from("!hide")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { avatar: vec![Blur], banner: vec![Blur], display_name: vec![Blur], @@ -1043,15 +1043,15 @@ fn moderation_behaviors() { ), ( "Self-post: Imperative label ('!warn') on post", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Post, author: TestUser::UserSelf, - labels: TestScenarioLabels { + labels: TestLabels { post: vec![String::from("!warn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { content_list: vec![Blur], content_view: vec![Blur], ..Default::default() @@ -1060,15 +1060,15 @@ fn moderation_behaviors() { ), ( "Self-post: Imperative label ('!warn') on author profile", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Post, author: TestUser::UserSelf, - labels: TestScenarioLabels { + labels: TestLabels { profile: vec![String::from("!warn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { avatar: vec![Blur], banner: vec![Blur], display_name: vec![Blur], @@ -1078,15 +1078,15 @@ fn moderation_behaviors() { ), ( "Self-post: Imperative label ('!warn') on author account", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Post, author: TestUser::UserSelf, - labels: TestScenarioLabels { + labels: TestLabels { account: vec![String::from("!warn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { avatar: vec![Blur], banner: vec![Blur], content_list: vec![Blur], @@ -1097,12 +1097,12 @@ fn moderation_behaviors() { ), ( "Mute/block: Blocking user", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Profile, author: TestUser::Bob, - labels: TestScenarioLabels::default(), - behaviors: TestExpectedBehaviors { + labels: TestLabels::default(), + behaviors: ExpectedBehaviors { profile_list: vec![Filter, Blur, NoOverride], profile_view: vec![Alert], avatar: vec![Blur, NoOverride], @@ -1115,12 +1115,12 @@ fn moderation_behaviors() { ), ( "Post with blocked author", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Post, author: TestUser::Bob, - labels: TestScenarioLabels::default(), - behaviors: TestExpectedBehaviors { + labels: TestLabels::default(), + behaviors: ExpectedBehaviors { avatar: vec![Blur, NoOverride], banner: vec![Blur, NoOverride], content_list: vec![Filter, Blur, NoOverride], @@ -1131,12 +1131,12 @@ fn moderation_behaviors() { ), ( "Post with author blocking user", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Post, author: TestUser::Carla, - labels: TestScenarioLabels::default(), - behaviors: TestExpectedBehaviors { + labels: TestLabels::default(), + behaviors: ExpectedBehaviors { avatar: vec![Blur, NoOverride], banner: vec![Blur, NoOverride], content_list: vec![Filter, Blur, NoOverride], @@ -1147,12 +1147,12 @@ fn moderation_behaviors() { ), ( "Mute/block: Blocking-by-list user", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Profile, author: TestUser::Georgia, - labels: TestScenarioLabels::default(), - behaviors: TestExpectedBehaviors { + labels: TestLabels::default(), + behaviors: ExpectedBehaviors { profile_list: vec![Filter, Blur, NoOverride], profile_view: vec![Alert], avatar: vec![Blur, NoOverride], @@ -1165,12 +1165,12 @@ fn moderation_behaviors() { ), ( "Mute/block: Blocked by user", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Profile, author: TestUser::Carla, - labels: TestScenarioLabels::default(), - behaviors: TestExpectedBehaviors { + labels: TestLabels::default(), + behaviors: ExpectedBehaviors { profile_list: vec![Filter, Blur, NoOverride], profile_view: vec![Alert], avatar: vec![Blur, NoOverride], @@ -1183,12 +1183,12 @@ fn moderation_behaviors() { ), ( "Mute/block: Muted user", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Profile, author: TestUser::Dan, - labels: TestScenarioLabels::default(), - behaviors: TestExpectedBehaviors { + labels: TestLabels::default(), + behaviors: ExpectedBehaviors { profile_list: vec![Filter, Inform], profile_view: vec![Alert], content_list: vec![Filter, Blur], @@ -1199,12 +1199,12 @@ fn moderation_behaviors() { ), ( "Mute/block: Muted-by-list user", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Profile, author: TestUser::Elise, - labels: TestScenarioLabels::default(), - behaviors: TestExpectedBehaviors { + labels: TestLabels::default(), + behaviors: ExpectedBehaviors { profile_list: vec![Filter, Inform], profile_view: vec![Alert], content_list: vec![Filter, Blur], @@ -1215,12 +1215,12 @@ fn moderation_behaviors() { ), ( "Merging: blocking & blocked-by user", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Profile, author: TestUser::Fern, - labels: TestScenarioLabels::default(), - behaviors: TestExpectedBehaviors { + labels: TestLabels::default(), + behaviors: ExpectedBehaviors { profile_list: vec![Filter, Blur, NoOverride], profile_view: vec![Alert], avatar: vec![Blur, NoOverride], @@ -1233,12 +1233,12 @@ fn moderation_behaviors() { ), ( "Post with muted author", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Post, author: TestUser::Dan, - labels: TestScenarioLabels::default(), - behaviors: TestExpectedBehaviors { + labels: TestLabels::default(), + behaviors: ExpectedBehaviors { content_list: vec![Filter, Blur], content_view: vec![Inform], ..Default::default() @@ -1247,12 +1247,12 @@ fn moderation_behaviors() { ), ( "Post with muted-by-list author", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Post, author: TestUser::Elise, - labels: TestScenarioLabels::default(), - behaviors: TestExpectedBehaviors { + labels: TestLabels::default(), + behaviors: ExpectedBehaviors { content_list: vec![Filter, Blur], content_view: vec![Inform], ..Default::default() @@ -1261,15 +1261,15 @@ fn moderation_behaviors() { ), ( "Merging: '!hide' label on account of blocked user", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Profile, author: TestUser::Bob, - labels: TestScenarioLabels { + labels: TestLabels { account: vec![String::from("!hide")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { profile_list: vec![Filter, Blur, NoOverride], profile_view: vec![Blur, Alert, NoOverride], avatar: vec![Blur, NoOverride], @@ -1283,15 +1283,15 @@ fn moderation_behaviors() { ), ( "Merging: '!hide' and 'porn' labels on account (hide)", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::PornHide, subject: TestSubject::Profile, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { account: vec![String::from("!hide"), String::from("porn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { profile_list: vec![Filter, Blur, NoOverride], profile_view: vec![Blur, NoOverride], avatar: vec![Blur, NoOverride], @@ -1305,15 +1305,15 @@ fn moderation_behaviors() { ), ( "Merging: '!warn' and 'porn' labels on account (hide)", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::PornHide, subject: TestSubject::Profile, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { account: vec![String::from("!warn"), String::from("porn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { profile_list: vec![Filter, Blur], profile_view: vec![Blur], avatar: vec![Blur], @@ -1326,16 +1326,16 @@ fn moderation_behaviors() { ), ( "Merging: !hide on account, !warn on profile", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Profile, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { account: vec![String::from("!hide")], profile: vec![String::from("!warn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { profile_list: vec![Filter, Blur, NoOverride], profile_view: vec![Blur, NoOverride], avatar: vec![Blur, NoOverride], @@ -1349,16 +1349,16 @@ fn moderation_behaviors() { ), ( "Merging: !warn on account, !hide on profile", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Profile, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { account: vec![String::from("!warn")], profile: vec![String::from("!hide")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { profile_list: vec![Blur], profile_view: vec![Blur], avatar: vec![Blur, NoOverride], @@ -1372,12 +1372,12 @@ fn moderation_behaviors() { ), ( "Merging: post with blocking & blocked-by author", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Post, author: TestUser::Fern, - labels: TestScenarioLabels::default(), - behaviors: TestExpectedBehaviors { + labels: TestLabels::default(), + behaviors: ExpectedBehaviors { avatar: vec![Blur, NoOverride], banner: vec![Blur, NoOverride], content_list: vec![Filter, Blur, NoOverride], @@ -1388,15 +1388,15 @@ fn moderation_behaviors() { ), ( "Merging: '!hide' label on post by blocked user", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::None, subject: TestSubject::Post, author: TestUser::Bob, - labels: TestScenarioLabels { + labels: TestLabels { post: vec![String::from("!hide")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { avatar: vec![Blur, NoOverride], banner: vec![Blur, NoOverride], content_list: vec![Filter, Blur, NoOverride], @@ -1407,15 +1407,15 @@ fn moderation_behaviors() { ), ( "Merging: '!hide' and 'porn' labels on post (hide)", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::PornHide, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { post: vec![String::from("!warn"), String::from("porn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { content_list: vec![Filter, Blur], content_view: vec![Blur], content_media: vec![Blur], @@ -1425,15 +1425,15 @@ fn moderation_behaviors() { ), ( "Merging: '!warn' and 'porn' labels on post (hide)", - BehaviorsTestScenario { + Scenario { cfg: TestConfig::PornHide, subject: TestSubject::Post, author: TestUser::Alice, - labels: TestScenarioLabels { + labels: TestLabels { post: vec![String::from("!warn"), String::from("porn")], ..Default::default() }, - behaviors: TestExpectedBehaviors { + behaviors: ExpectedBehaviors { content_list: vec![Filter, Blur], content_view: vec![Blur], content_media: vec![Blur], diff --git a/bsky-sdk/src/moderation/tests/custom_labels.rs b/bsky-sdk/src/moderation/tests/custom_labels.rs index b42bef3c..eea49a32 100644 --- a/bsky-sdk/src/moderation/tests/custom_labels.rs +++ b/bsky-sdk/src/moderation/tests/custom_labels.rs @@ -1,5 +1,5 @@ use super::{assert_ui, label, post_view, profile_view_basic}; -use super::{ModerationTestResultFlag, TestExpectedBehaviors}; +use super::{ExpectedBehaviors, ResultFlag}; use crate::moderation::decision::DecisionContext; use crate::moderation::error::Result; use crate::moderation::types::*; @@ -9,15 +9,15 @@ use atrium_api::com::atproto::label::defs::LabelValueDefinition; use std::collections::HashMap; #[derive(Debug)] -struct CustomLabelTestScenario { +struct Scenario { blurs: LabelValueDefinitionBlurs, severity: LabelValueDefinitionSeverity, - account: TestExpectedBehaviors, - profile: TestExpectedBehaviors, - post: TestExpectedBehaviors, + account: ExpectedBehaviors, + profile: ExpectedBehaviors, + post: ExpectedBehaviors, } -impl CustomLabelTestScenario { +impl Scenario { fn run(&self) { let moderator = self.moderator().expect("failed to create moderator"); // account @@ -106,70 +106,70 @@ impl CustomLabelTestScenario { #[test] fn moderation_custom_labels() { - use ModerationTestResultFlag::*; + use ResultFlag::*; let scenarios = [ - CustomLabelTestScenario { + Scenario { blurs: LabelValueDefinitionBlurs::Content, severity: LabelValueDefinitionSeverity::Alert, - account: TestExpectedBehaviors { + account: ExpectedBehaviors { profile_list: vec![Filter, Alert], profile_view: vec![Alert], content_list: vec![Filter, Blur], content_view: vec![Alert], ..Default::default() }, - profile: TestExpectedBehaviors { + profile: ExpectedBehaviors { profile_list: vec![Alert], profile_view: vec![Alert], ..Default::default() }, - post: TestExpectedBehaviors { + post: ExpectedBehaviors { content_list: vec![Filter, Blur], content_view: vec![Alert], ..Default::default() }, }, - CustomLabelTestScenario { + Scenario { blurs: LabelValueDefinitionBlurs::Content, severity: LabelValueDefinitionSeverity::Inform, - account: TestExpectedBehaviors { + account: ExpectedBehaviors { profile_list: vec![Filter, Inform], profile_view: vec![Inform], content_list: vec![Filter, Blur], content_view: vec![Inform], ..Default::default() }, - profile: TestExpectedBehaviors { + profile: ExpectedBehaviors { profile_list: vec![Inform], profile_view: vec![Inform], ..Default::default() }, - post: TestExpectedBehaviors { + post: ExpectedBehaviors { content_list: vec![Filter, Blur], content_view: vec![Inform], ..Default::default() }, }, - CustomLabelTestScenario { + Scenario { blurs: LabelValueDefinitionBlurs::Content, severity: LabelValueDefinitionSeverity::None, - account: TestExpectedBehaviors { + account: ExpectedBehaviors { profile_list: vec![Filter], content_list: vec![Filter, Blur], ..Default::default() }, - profile: TestExpectedBehaviors { + profile: ExpectedBehaviors { ..Default::default() }, - post: TestExpectedBehaviors { + post: ExpectedBehaviors { content_list: vec![Filter, Blur], ..Default::default() }, }, - CustomLabelTestScenario { + Scenario { blurs: LabelValueDefinitionBlurs::Media, severity: LabelValueDefinitionSeverity::Alert, - account: TestExpectedBehaviors { + account: ExpectedBehaviors { profile_list: vec![Filter, Alert], profile_view: vec![Alert], avatar: vec![Blur], @@ -177,23 +177,23 @@ fn moderation_custom_labels() { content_list: vec![Filter], ..Default::default() }, - profile: TestExpectedBehaviors { + profile: ExpectedBehaviors { profile_list: vec![Alert], profile_view: vec![Alert], avatar: vec![Blur], banner: vec![Blur], ..Default::default() }, - post: TestExpectedBehaviors { + post: ExpectedBehaviors { content_list: vec![Filter], content_media: vec![Blur], ..Default::default() }, }, - CustomLabelTestScenario { + Scenario { blurs: LabelValueDefinitionBlurs::Media, severity: LabelValueDefinitionSeverity::Inform, - account: TestExpectedBehaviors { + account: ExpectedBehaviors { profile_list: vec![Filter, Inform], profile_view: vec![Inform], avatar: vec![Blur], @@ -201,94 +201,94 @@ fn moderation_custom_labels() { content_list: vec![Filter], ..Default::default() }, - profile: TestExpectedBehaviors { + profile: ExpectedBehaviors { profile_list: vec![Inform], profile_view: vec![Inform], avatar: vec![Blur], banner: vec![Blur], ..Default::default() }, - post: TestExpectedBehaviors { + post: ExpectedBehaviors { content_list: vec![Filter], content_media: vec![Blur], ..Default::default() }, }, - CustomLabelTestScenario { + Scenario { blurs: LabelValueDefinitionBlurs::Media, severity: LabelValueDefinitionSeverity::None, - account: TestExpectedBehaviors { + account: ExpectedBehaviors { profile_list: vec![Filter], avatar: vec![Blur], banner: vec![Blur], content_list: vec![Filter], ..Default::default() }, - profile: TestExpectedBehaviors { + profile: ExpectedBehaviors { avatar: vec![Blur], banner: vec![Blur], ..Default::default() }, - post: TestExpectedBehaviors { + post: ExpectedBehaviors { content_list: vec![Filter], content_media: vec![Blur], ..Default::default() }, }, - CustomLabelTestScenario { + Scenario { blurs: LabelValueDefinitionBlurs::None, severity: LabelValueDefinitionSeverity::Alert, - account: TestExpectedBehaviors { + account: ExpectedBehaviors { profile_list: vec![Filter, Alert], profile_view: vec![Alert], content_list: vec![Filter, Alert], content_view: vec![Alert], ..Default::default() }, - profile: TestExpectedBehaviors { + profile: ExpectedBehaviors { profile_list: vec![Alert], profile_view: vec![Alert], ..Default::default() }, - post: TestExpectedBehaviors { + post: ExpectedBehaviors { content_list: vec![Filter, Alert], content_view: vec![Alert], ..Default::default() }, }, - CustomLabelTestScenario { + Scenario { blurs: LabelValueDefinitionBlurs::None, severity: LabelValueDefinitionSeverity::Inform, - account: TestExpectedBehaviors { + account: ExpectedBehaviors { profile_list: vec![Filter, Inform], profile_view: vec![Inform], content_list: vec![Filter, Inform], content_view: vec![Inform], ..Default::default() }, - profile: TestExpectedBehaviors { + profile: ExpectedBehaviors { profile_list: vec![Inform], profile_view: vec![Inform], ..Default::default() }, - post: TestExpectedBehaviors { + post: ExpectedBehaviors { content_list: vec![Filter, Inform], content_view: vec![Inform], ..Default::default() }, }, - CustomLabelTestScenario { + Scenario { blurs: LabelValueDefinitionBlurs::None, severity: LabelValueDefinitionSeverity::None, - account: TestExpectedBehaviors { + account: ExpectedBehaviors { profile_list: vec![Filter], content_list: vec![Filter], ..Default::default() }, - profile: TestExpectedBehaviors { + profile: ExpectedBehaviors { ..Default::default() }, - post: TestExpectedBehaviors { + post: ExpectedBehaviors { content_list: vec![Filter], ..Default::default() }, diff --git a/bsky-sdk/src/moderation/tests/quoteposts.rs b/bsky-sdk/src/moderation/tests/quoteposts.rs new file mode 100644 index 00000000..0e5f49c5 --- /dev/null +++ b/bsky-sdk/src/moderation/tests/quoteposts.rs @@ -0,0 +1,282 @@ +use super::{assert_ui, label, post_view, profile_view_basic}; +use super::{ExpectedBehaviors, ResultFlag, FAKE_CID}; +use crate::moderation::decision::DecisionContext; +use crate::moderation::error::Result; +use crate::moderation::types::*; +use crate::moderation::util::interpret_label_value_definition; +use crate::moderation::Moderator; +use atrium_api::app::bsky::actor::defs::ProfileViewBasic; +use atrium_api::app::bsky::embed::record::{View, ViewRecord, ViewRecordRefs}; +use atrium_api::app::bsky::feed::defs::{PostView, PostViewEmbedRefs}; +use atrium_api::com::atproto::label::defs::{Label, LabelValueDefinition}; +use atrium_api::records::{KnownRecord, Record}; +use atrium_api::types::string::Datetime; +use atrium_api::types::Union; +use std::collections::HashMap; + +fn embed_record_view( + author: &ProfileViewBasic, + record: &atrium_api::app::bsky::feed::post::Record, + labels: Option>, +) -> Union { + Union::Refs(PostViewEmbedRefs::AppBskyEmbedRecordView(Box::new(View { + record: Union::Refs(ViewRecordRefs::ViewRecord(Box::new(ViewRecord { + author: author.clone(), + cid: FAKE_CID.parse().expect("invalid cid"), + embeds: None, + indexed_at: Datetime::now(), + labels, + like_count: None, + reply_count: None, + repost_count: None, + uri: format!("at://{}/app.bsky.feed.post/fake", author.did.as_ref()), + value: Record::Known(KnownRecord::AppBskyFeedPost(Box::new(record.clone()))), + }))), + }))) +} + +fn quoted_post(profile_labels: Option>, post_labels: Option>) -> PostView { + let mut quoted = post_view( + &profile_view_basic("bob.test", Some("Bob"), None), + "Hello", + None, + ); + quoted.embed = Some(embed_record_view( + &profile_view_basic("carla.test", Some("Carla"), profile_labels), + &atrium_api::app::bsky::feed::post::Record { + created_at: Datetime::now(), + embed: None, + entities: None, + facets: None, + labels: None, + langs: Some(vec!["en".parse().expect("invalid lang")]), + reply: None, + tags: None, + text: String::from("Quoted post text"), + }, + post_labels, + )); + quoted +} + +struct Scenario { + blurs: LabelValueDefinitionBlurs, + severity: LabelValueDefinitionSeverity, + account: ExpectedBehaviors, + profile: ExpectedBehaviors, + post: ExpectedBehaviors, +} + +impl Scenario { + fn run(&self) { + let moderator = self.moderator().expect("failed to create moderator"); + // account + { + let result = moderator.moderate_post("ed_post( + Some(vec![label( + "did:web:labeler.test", + "did:web:carla.test", + "custom", + )]), + None, + )); + for context in DecisionContext::ALL { + assert_ui(&result, self.account.expected_for(context), context); + } + } + // profile + { + let result = moderator.moderate_post("ed_post( + Some(vec![label( + "did:web:labeler.test", + "at://did:web:carla.test/app.bsky.actor.profile/self", + "custom", + )]), + None, + )); + for context in DecisionContext::ALL { + assert_ui(&result, self.profile.expected_for(context), context); + } + } + // post + { + let result = moderator.moderate_post("ed_post( + None, + Some(vec![label( + "did:web:labeler.test", + "at://did:web:carla.test/app.bsky.feed.post/fake", + "custom", + )]), + )); + for context in DecisionContext::ALL { + assert_ui(&result, self.post.expected_for(context), context); + } + } + } + fn moderator(&self) -> Result { + Ok(Moderator::new( + Some("did:web:alice.test".parse().expect("invalid did")), + ModerationPrefs { + adult_content_enabled: true, + labels: HashMap::new(), + labelers: vec![ModerationPrefsLabeler { + did: "did:web:labeler.test".parse().expect("invalid did"), + labels: HashMap::from_iter([(String::from("custom"), LabelPreference::Hide)]), + is_default_labeler: false, + }], + muted_words: Vec::new(), + hidden_posts: Vec::new(), + }, + HashMap::from_iter([( + "did:web:labeler.test".parse().expect("invalid did"), + vec![interpret_label_value_definition( + &LabelValueDefinition { + adult_only: None, + blurs: self.blurs.as_ref().to_string(), + default_setting: Some(LabelPreference::Warn.as_ref().to_string()), + identifier: String::from("custom"), + locales: Vec::new(), + severity: self.severity.as_ref().to_string(), + }, + Some("did:web:labeler.test".parse().expect("invalid did")), + )?], + )]), + )) + } +} + +#[test] +fn moderation_quoteposts() { + use ResultFlag::*; + let scenarios = [ + Scenario { + blurs: LabelValueDefinitionBlurs::Content, + severity: LabelValueDefinitionSeverity::Alert, + account: ExpectedBehaviors { + profile_list: vec![Filter], + content_list: vec![Filter], + ..Default::default() + }, + profile: ExpectedBehaviors::default(), + post: ExpectedBehaviors { + content_list: vec![Filter], + ..Default::default() + }, + }, + Scenario { + blurs: LabelValueDefinitionBlurs::Content, + severity: LabelValueDefinitionSeverity::Inform, + account: ExpectedBehaviors { + profile_list: vec![Filter], + content_list: vec![Filter], + ..Default::default() + }, + profile: ExpectedBehaviors::default(), + post: ExpectedBehaviors { + content_list: vec![Filter], + ..Default::default() + }, + }, + Scenario { + blurs: LabelValueDefinitionBlurs::Content, + severity: LabelValueDefinitionSeverity::None, + account: ExpectedBehaviors { + profile_list: vec![Filter], + content_list: vec![Filter], + ..Default::default() + }, + profile: ExpectedBehaviors::default(), + post: ExpectedBehaviors { + content_list: vec![Filter], + ..Default::default() + }, + }, + Scenario { + blurs: LabelValueDefinitionBlurs::Media, + severity: LabelValueDefinitionSeverity::Alert, + account: ExpectedBehaviors { + profile_list: vec![Filter], + content_list: vec![Filter], + ..Default::default() + }, + profile: ExpectedBehaviors::default(), + post: ExpectedBehaviors { + content_list: vec![Filter], + ..Default::default() + }, + }, + Scenario { + blurs: LabelValueDefinitionBlurs::Media, + severity: LabelValueDefinitionSeverity::Inform, + account: ExpectedBehaviors { + profile_list: vec![Filter], + content_list: vec![Filter], + ..Default::default() + }, + profile: ExpectedBehaviors::default(), + post: ExpectedBehaviors { + content_list: vec![Filter], + ..Default::default() + }, + }, + Scenario { + blurs: LabelValueDefinitionBlurs::Media, + severity: LabelValueDefinitionSeverity::None, + account: ExpectedBehaviors { + profile_list: vec![Filter], + content_list: vec![Filter], + ..Default::default() + }, + profile: ExpectedBehaviors::default(), + post: ExpectedBehaviors { + content_list: vec![Filter], + ..Default::default() + }, + }, + Scenario { + blurs: LabelValueDefinitionBlurs::None, + severity: LabelValueDefinitionSeverity::Alert, + account: ExpectedBehaviors { + profile_list: vec![Filter], + content_list: vec![Filter], + ..Default::default() + }, + profile: ExpectedBehaviors::default(), + post: ExpectedBehaviors { + content_list: vec![Filter], + ..Default::default() + }, + }, + Scenario { + blurs: LabelValueDefinitionBlurs::None, + severity: LabelValueDefinitionSeverity::Inform, + account: ExpectedBehaviors { + profile_list: vec![Filter], + content_list: vec![Filter], + ..Default::default() + }, + profile: ExpectedBehaviors::default(), + post: ExpectedBehaviors { + content_list: vec![Filter], + ..Default::default() + }, + }, + Scenario { + blurs: LabelValueDefinitionBlurs::None, + severity: LabelValueDefinitionSeverity::None, + account: ExpectedBehaviors { + profile_list: vec![Filter], + content_list: vec![Filter], + ..Default::default() + }, + profile: ExpectedBehaviors::default(), + post: ExpectedBehaviors { + content_list: vec![Filter], + ..Default::default() + }, + }, + ]; + for scenario in scenarios { + scenario.run(); + } +}