diff --git a/visibilitylib/BUILD b/visibilitylib/BUILD deleted file mode 100644 index 76ea1a659..000000000 --- a/visibilitylib/BUILD +++ /dev/null @@ -1,29 +0,0 @@ -target( - dependencies = [ - "visibility/lib/src/main/scala/com/twitter/visibility", - ], -) - -target( - name = "conversations", - dependencies = [ - "visibility/lib/src/main/scala/com/twitter/visibility/interfaces/common/tweets", - "visibility/lib/src/main/scala/com/twitter/visibility/interfaces/conversations", - ], -) - -target( - name = "tweets", - dependencies = [ - "visibility/lib/src/main/scala/com/twitter/visibility/generators", - "visibility/lib/src/main/scala/com/twitter/visibility/interfaces/common/tweets", - "visibility/lib/src/main/scala/com/twitter/visibility/interfaces/tweets", - ], -) - -target( - name = "users", - dependencies = [ - "visibility/lib/src/main/scala/com/twitter/visibility/interfaces/users", - ], -) diff --git a/visibilitylib/README.md b/visibilitylib/README.md deleted file mode 100644 index 28c7af03f..000000000 --- a/visibilitylib/README.md +++ /dev/null @@ -1,51 +0,0 @@ -Overview -======== - -Visibility Filtering is a centralized rule engine that instructs clients how to alter the display of certain Twitter content on read time. The Visibility Filtering library is responsible for filtering Twitter content to support legal compliance, improve product quality, increase user trust, protect revenue through the use of hard-filtering, visible product treatments, and coarse-grained downranking. - -Notice -====== - -Visibility Filtering library is currently being reviewed and rebuilt, and part of the code has been removed and is not ready to be shared yet. The remaining part of the code needs further review and will be shared once it’s ready. Also code comments have been sanitized. - -SafetyLevel -=========== - -Represents the product context in which the Viewer is requesting to view the Content (e.g. Timeline, Profile). - -Features -======== - -Include safety labels and other metadata of a Tweet, flags set on a User (including the Viewer), relationships between Users (e.g. block, follow), User settings, relationships between Users and Content (e.g. reported for spam). - -Action -====== - -The way the Visibility Framework instructs the client to respond to the Viewer’s request for Content, and can include hard filtering (e.g. Drop), soft filtering (e.g. Labels and Interstitials), ranking clues, etc. - -Condition -========= - -Returns a boolean when given map of Features. Conditions can be combined to determine if a Rule should return an Action or the default (Allow). - -Policy -====== - -Rules are expressed as a sequence in priority order to create a Visibility Policy. The library has one policy -per SafetyLevel. - -RuleEngine -=========== - -Evaluates the Action for a Request. - -SafetyLabel -=========== - -A primary labeling mechanism for Safety. A labeled entity associates with tweet, user, Direct Message, media, space etc. Safety labels power different ways of remediations (e.g. applying a SafetyLabel that results in tweet interstitial or notice). - -SafetyLabelType -=============== - -Describes a particular policy violation for a given noun instance, and usually leads to reduced visibility of the -labeled entity in product surfaces. There are many deprecated, and experimental safety label types. Labels with these safety label types have no effect on VF. Additionally, some safety label types are not used, and not designed for VF. diff --git a/visibilitylib/src/main/resources/config/BUILD b/visibilitylib/src/main/resources/config/BUILD deleted file mode 100644 index b45c857ae..000000000 --- a/visibilitylib/src/main/resources/config/BUILD +++ /dev/null @@ -1,6 +0,0 @@ -resources( - sources = [ - "com/twitter/visibility/*.csv", - "com/twitter/visibility/*.yml", - ], -) diff --git a/visibilitylib/src/main/resources/config/com/twitter/visibility/decider.yml b/visibilitylib/src/main/resources/config/com/twitter/visibility/decider.yml deleted file mode 100644 index 54b5edcba..000000000 --- a/visibilitylib/src/main/resources/config/com/twitter/visibility/decider.yml +++ /dev/null @@ -1,909 +0,0 @@ - -visibility_library_enable_all_subscribed_lists_safety_level: - default_availability: 10000 - -visibility_library_enable_ads_business_settings_safety_level: - default_availability: 10000 - -visibility_library_enable_ads_campaign_safety_level: - default_availability: 10000 - -visibility_library_enable_ads_manager_safety_level: - default_availability: 10000 - -visibility_library_enable_appeals_safety_level: - default_availability: 10000 - -visibility_library_enable_article_tweet_timeline_safety_level: - default_availability: 10000 - -visibility_library_enable_birdwatch_note_author_safety_level: - default_availability: 10000 - -visibility_library_enable_birdwatch_note_tweets_timeline_safety_level: - default_availability: 10000 - -visibility_library_enable_birdwatch_needs_your_help_notifications_safety_level: - default_availability: 10000 - -visibility_library_enable_block_mute_users_timeline_safety_level: - default_availability: 10000 - -visibility_library_enable_brand_safety_safety_level: - default_availability: 10000 - -visibility_library_enable_card_poll_voting_safety_level: - default_availability: 10000 - -visibility_library_enable_cards_service_safety_level: - default_availability: 10000 - -visibility_library_enable_communities_safety_level: - default_availability: 10000 - -visibility_library_enable_conversation_focal_prehydration_safety_level: - default_availability: 10000 - -visibility_library_enable_conversation_focal_tweet_safety_level: - default_availability: 10000 - -visibility_library_enable_conversation_injected_tweet_safety_level: - default_availability: 10000 - -visibility_library_enable_conversation_reply_safety_level: - default_availability: 10000 - -visibility_library_curated_trends_representative_tweet: - default_availability: 10000 - -visibility_library_curation_policy_violations: - default_availability: 10000 - -visibility_library_enable_deprecated_safety_level_safety_level: - default_availability: 10000 - -visibility_library_enable_dev_platform_get_list_tweets_safety_level: - default_availability: 10000 - -visibility_library_enable_des_following_and_followers_user_list_safety_level: - default_availability: 10000 - -visibility_library_enable_des_home_timeline_safety_level: - default_availability: 10000 - -visibility_library_enable_des_quote_tweet_timeline_safety_level: - default_availability: 10000 - -visibility_library_enable_des_realtime_safety_level: - default_availability: 10000 - -visibility_library_enable_des_realtime_spam_enrichment_safety_level: - default_availability: 10000 - -visibility_library_enable_des_realtime_tweet_filter_safety_level: - default_availability: 10000 - -visibility_library_enable_des_retweeting_users_safety_level: - default_availability: 10000 - -visibility_library_enable_des_tweet_detail_safety_level: - default_availability: 10000 - -visibility_library_enable_des_tweet_liking_users_safety_level: - default_availability: 10000 - -visibility_library_enable_des_user_bookmarks_safety_level: - default_availability: 10000 - -visibility_library_enable_des_user_liked_tweets_safety_level: - default_availability: 10000 - -visibility_library_enable_des_user_mentions_safety_level: - default_availability: 10000 - -visibility_library_enable_des_user_tweets_safety_level: - default_availability: 10000 - -visibility_library_enable_dev_platform_compliance_stream_safety_level: - default_availability: 10000 - -visibility_library_enable_direct_messages_safety_level: - default_availability: 10000 - -visibility_library_enable_direct_messages_conversation_list_safety_level: - default_availability: 10000 - -visibility_library_enable_direct_messages_conversation_timeline_safety_level: - default_availability: 10000 - -visibility_library_enable_direct_messages_inbox_safety_level: - default_availability: 10000 - -visibility_library_enable_direct_messages_muted_users_safety_level: - default_availability: 10000 - -visibility_library_enable_direct_messages_pinned_safety_level: - default_availability: 10000 - -visibility_library_enable_elevated_quote_tweet_timeline_safety_level: - default_availability: 10000 - -visibility_library_enable_direct_messages_search_safety_level: - default_availability: 10000 - -visibility_library_enable_embedded_tweet_safety_level: - default_availability: 10000 - -visibility_library_enable_embeds_public_interest_notice_safety_level: - default_availability: 10000 - -visibility_library_enable_embed_tweet_markup_safety_level: - default_availability: 10000 - -visibility_library_enable_write_path_limited_actions_enforcement_safety_level: - default_availability: 10000 - -visibility_library_enable_filter_all_safety_level: - default_availability: 10000 - -visibility_library_enable_filter_all_placeholder_safety_level: - default_availability: 10000 - -visibility_library_enable_filter_default_safety_level: - default_availability: 10000 - -visibility_library_enable_filter_none_safety_level: - default_availability: 10000 - -visibility_library_enable_followed_topics_timeline_safety_level: - default_availability: 10000 - -visibility_library_enable_follower_connections_safety_level: - default_availability: 10000 - -visibility_library_enable_following_and_followers_user_list_safety_level: - default_availability: 10000 - -visibility_library_enable_for_development_only_safety_level: - default_availability: 10000 - -visibility_library_enable_friends_following_list_safety_level: - default_availability: 10000 - -visibility_library_enable_graphql_default_safety_level: - default_availability: 10000 - -visibility_library_enable_gryphon_decks_and_columns_safety_level: - default_availability: 10000 - -visibility_library_enable_humanization_nudge_safety_level: - default_availability: 10000 - -visibility_library_enable_kitchen_sink_development_safety_level: - default_availability: 10000 - -visibility_library_enable_list_header_safety_level: - default_availability: 10000 - -visibility_library_enable_list_memberships_safety_level: - default_availability: 10000 - -visibility_library_enable_list_ownerships_safety_level: - default_availability: 10000 - -visibility_library_enable_list_recommendations_safety_level: - default_availability: 10000 - -visibility_library_enable_list_search_safety_level: - default_availability: 10000 - -visibility_library_enable_list_subscriptions_safety_level: - default_availability: 10000 - -visibility_library_enable_live_pipeline_engagement_counts_safety_level: - default_availability: 10000 - -visibility_library_enable_live_video_timeline_safety_level: - default_availability: 10000 - -visibility_library_enable_magic_recs_safety_level: - default_availability: 10000 - -visibility_library_enable_magic_recs_aggressive_safety_level: - default_availability: 10000 - -visibility_library_enable_magic_recs_aggressive_v2_safety_level: - default_availability: 10000 - -visibility_library_enable_magic_recs_v2_safety_level: - default_availability: 10000 - -visibility_library_enable_minimal_safety_level: - default_availability: 10000 - -visibility_library_enable_moderated_tweets_timeline_safety_level: - default_availability: 10000 - -visibility_library_enable_moments_safety_level: - default_availability: 10000 - -visibility_library_enable_nearby_timeline_safety_level: - default_availability: 10000 - -visibility_library_enable_new_user_experience_safety_level: - default_availability: 10000 - -visibility_library_enable_notifications_ibis_safety_level: - default_availability: 10000 - -visibility_library_enable_notifications_platform_safety_level: - default_availability: 10000 - -visibility_library_enable_notifications_platform_push_safety_level: - default_availability: 10000 - -visibility_library_enable_notifications_read_safety_level: - default_availability: 10000 - -visibility_library_enable_notifications_timeline_device_follow_safety_level: - default_availability: 10000 - -visibility_library_enable_notifications_write_safety_level: - default_availability: 10000 - -visibility_library_enable_notification_writer_v2_safety_level: - default_availability: 10000 - -visibility_library_enable_notifications_writer_tweet_hydrator_safety_level: - default_availability: 10000 - -visibility_library_enable_quick_promote_tweet_eligibility_safety_level: - default_availability: 10000 - -visibility_library_enable_quote_tweet_timeline_safety_level: - default_availability: 10000 - -visibility_library_enable_quoted_tweet_rules_safety_level: - default_availability: 10000 - -visibility_library_enable_recommendations_safety_level: - default_availability: 10000 - -visibility_library_enable_recos_video_safety_level: - default_availability: 10000 - -visibility_library_enable_recos_write_path_safety_level: - default_availability: 10000 - -visibility_library_enable_replies_grouping_safety_level: - default_availability: 10000 - -visibility_library_enable_report_center_safety_level: - default_availability: 10000 - -visibility_library_enable_returning_user_experience_safety_level: - default_availability: 10000 - -visibility_library_enable_returning_user_experience_focal_tweet_safety_level: - default_availability: 10000 - -visibility_library_enable_revenue_safety_level: - default_availability: 10000 - -visibility_library_enable_rito_actioned_tweet_timeline_safety_level: - default_availability: 10000 - -visibility_library_enable_safe_search_minimal_safety_level: - default_availability: 10000 - -visibility_library_enable_safe_search_strict_safety_level: - default_availability: 10000 - -visibility_library_enable_search_hydration_safety_level: - default_availability: 10000 - -visibility_library_enable_search_latest_safety_level: - default_availability: 10000 - -visibility_library_enable_search_mixer_srp_minimal_safety_level: - default_availability: 10000 - -visibility_library_enable_search_mixer_srp_strict_safety_level: - default_availability: 10000 - -visibility_library_enable_user_search_srp_safety_level: - default_availability: 10000 - -visibility_library_enable_user_search_typeahead_safety_level: - default_availability: 10000 - -visibility_library_enable_search_people_srp_safety_level: - default_availability: 10000 - -visibility_library_enable_search_people_typeahead_safety_level: - default_availability: 10000 - -visibility_library_enable_search_photo_safety_level: - default_availability: 10000 - -visibility_library_enable_search_top_safety_level: - default_availability: 10000 - -visibility_library_enable_search_trend_takeover_promoted_tweet_safety_level: - default_availability: 10000 - -visibility_library_enable_search_video_safety_level: - default_availability: 10000 - -visibility_library_enable_search_latest_user_rules_safety_level: - default_availability: 10000 - -visibility_library_enable_shopping_manager_spy_mode_safety_level: - default_availability: 10000 - -visibility_library_enable_signals_reactions_safety_level: - default_availability: 10000 - -visibility_library_enable_signals_tweet_reacting_users_safety_level: - default_availability: 10000 - -visibility_library_enable_social_proof_safety_level: - default_availability: 10000 - -visibility_library_enable_soft_intervention_pivot_safety_level: - default_availability: 10000 - -visibility_library_enable_space_fleetline_safety_level: - default_availability: 10000 - -visibility_library_enable_space_home_timeline_upranking_safety_level: - default_availability: 10000 - -visibility_library_enable_space_join_screen_safety_level: - default_availability: 10000 - -visibility_library_enable_space_notifications_safety_level: - default_availability: 10000 - -visibility_library_enable_spaces_safety_level: - default_availability: 10000 - -visibility_library_enable_spaces_participants_safety_level: - default_availability: 0 - -visibility_library_enable_spaces_seller_application_status_safety_level: - default_availability: 10000 - -visibility_library_enable_spaces_sharing_safety_level: - default_availability: 10000 - -visibility_library_enable_space_tweet_avatar_home_timeline_safety_level: - default_availability: 10000 - -visibility_library_enable_stickers_timeline_safety_level: - default_availability: 10000 - -visibility_library_enable_strato_ext_limited_engagements_safety_level: - default_availability: 10000 - -visibility_library_enable_stream_services_safety_level: - default_availability: 10000 - -visibility_library_enable_test_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_bookmark_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_content_controls_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_conversations_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_conversations_downranking_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_conversations_downranking_minimal_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_favorites_safety_level: - default_availability: 10000 - -visibility_library_enable_self_view_timeline_favorites_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_focal_tweet_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_following_activity_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_home_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_home_communities_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_home_hydration_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_home_latest_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_home_recommendations_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_home_topic_follow_recommendations_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_scorer_safety_level: - default_availability: 10000 - -visibility_library_enable_topics_landing_page_topic_recommendations_safety_level: - default_availability: 10000 - -visibility_library_enable_explore_recommendations_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_moderated_tweets_hydration_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_injection_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_liked_by_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_lists_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_media_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_mentions_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_profile_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_profile_all_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_profile_spaces_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_profile_super_follows_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_reactive_blending_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_retweeted_by_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_super_liked_by_safety_level: - default_availability: 10000 - -visibility_library_enable_tombstoning_safety_level: - default_availability: 10000 - -visibility_library_enable_trends_representative_tweet_safety_level: - default_availability: 10000 - -visibility_library_enable_trusted_friends_user_list_safety_level: - default_availability: 10000 - -visibility_library_enable_twitter_delegate_user_list_safety_level: - default_availability: 10000 - -visibility_library_enable_tweet_detail_safety_level: - default_availability: 10000 - -visibility_library_enable_tweet_detail_non_too_safety_level: - default_availability: 10000 - -visibility_library_enable_tweet_detail_with_injections_hydration_safety_level: - default_availability: 10000 - -visibility_library_enable_tweet_engagers_safety_level: - default_availability: 10000 - -visibility_library_enable_tweet_reply_nudge_safety_level: - default_availability: 10000 - -visibility_library_enable_tweet_scoped_timeline_safety_level: - default_availability: 10000 - -visibility_library_enable_tweet_writes_api_safety_level: - default_availability: 10000 - -visibility_library_enable_twitter_article_compose_safety_level: - default_availability: 10000 - -visibility_library_enable_twitter_article_profile_tab_safety_level: - default_availability: 10000 - -visibility_library_enable_twitter_article_read_safety_level: - default_availability: 10000 - -visibility_library_enable_user_profile_header_safety_level: - default_availability: 10000 - -visibility_library_enable_user_milestone_recommendation_safety_level: - default_availability: 10000 - -visibility_library_enable_user_scoped_timeline_safety_level: - default_availability: 10000 - -visibility_library_enable_user_settings_safety_level: - default_availability: 10000 - -visibility_library_enable_video_ads_safety_level: - default_availability: 10000 - -visibility_library_enable_timeline_home_promoted_hydration_safety_level: - default_availability: 10000 - -visibility_library_enable_super_follower_connnections_safety_level: - default_availability: 10000 - -visibility_library_enable_super_like_safety_level: - default_availability: 10000 - -visibility_library_enable_topic_recommendations_safety_level: - default_availability: 10000 - -visibility_library_enable_ads_reporting_dashboard_safety_level: - default_availability: 10000 - -visibility_library_enable_search_top_qig_safety_level: - default_availability: 10000 - -visibility_library_enable_content_control_tool_install_safety_level: - default_availability: 10000 - -visibility_library_enable_conversation_control_rules: - default_availability: 10000 - -visibility_library_enable_community_tweets_rules: - default_availability: 10000 - -visibility_library_enable_drop_community_tweet_with_undefined_community_rule: - default_availability: 10000 - -visibility_library_enable_p_spammy_tweet_downrank_convos_low_quality: - default_availability: 10000 - -visibility_library_enable_high_p_spammy_tweet_score_search_tweet_label_drop_rule: - default_availability: 10000 - -visibility_library_enable_rito_actioned_tweet_downrank_convos_low_quality: - default_availability: 10000 - -visibility_library_enable_toxic_reply_filter_conversation: - default_availability: 10000 - -visibility_library_enable_toxic_reply_filter_notifications: - default_availability: 10000 - -visibility_library_enable_new_sensitive_media_settings_interstitial_rules_home_timeline: - default_availability: 10000 - -visibility_library_enable_legacy_sensitive_media_rules_home_timeline: - default_availability: 10000 - -visibility_library_enable_new_sensitive_media_settings_interstitial_rules_conversation: - default_availability: 10000 - -visibility_library_enable_legacy_sensitive_media_rules_conversation: - default_availability: 10000 - -visibility_library_enable_new_sensitive_media_settings_interstitials_rules_profile_timeline: - default_availability: 10000 - -visibility_library_enable_legacy_sensitive_media_rules_profile_timeline: - default_availability: 10000 - -visibility_library_enable_new_sensitive_media_settings_interstitials_rules_tweet_detail: - default_availability: 10000 - -visibility_library_enable_legacy_sensitive_media_rules_tweet_detail: - default_availability: 10000 - -visibility_library_enable_legacy_sensitive_media_rules_direct_messages: - default_availability: 10000 - -visibility_library_enable_smyte_spam_tweet_rule: - default_availability: 10000 - -visibility_library_enable_high_spammy_tweet_content_score_search_latest_tweet_label_drop_rule: - default_availability: 10000 - -visibility_library_enable_high_spammy_tweet_content_score_search_top_tweet_label_drop_rule: - default_availability: 10000 - -visibility_library_enable_high_spammy_tweet_content_score_convo_downrank_abusive_quality_rule: - default_availability: 10000 - -visibility_library_enable_high_cryptospam_score_convo_downrank_abusive_quality_rule: - default_availability: 10000 - -visibility_library_enable_high_spammy_tweet_content_score_trends_top_tweet_label_drop_rule: - default_availability: 10000 - -visibility_library_enable_high_spammy_tweet_content_score_trends_latest_tweet_label_drop_rule: - default_availability: 10000 - -visibility_library_enable_gore_and_violence_topic_high_recall_tweet_label_rule: - default_availability: 10000 - -visibility_library_enable_limit_replies_followers_conversation_rule: - default_availability: 10000 - -visibility_library_enable_blink_bad_downranking_rule: - default_availability: 10000 - -visibility_library_enable_blink_worst_downranking_rule: - default_availability: 10000 - -visibility_library_enable_copypasta_spam_downrank_convos_abusive_quality_rule: - default_availability: 10000 - -visibility_library_enable_copypasta_spam_search_drop_rule: - default_availability: 10000 - -visibility_library_enable_spammy_user_model_high_precision_drop_tweet_rule: - default_availability: 10000 - -visibility_library_enable_avoid_nsfw_rules: - default_availability: 10000 - -visibility_library_enable_reported_tweet_interstitial_rule: - default_availability: 10000 - -visibility_library_enable_reported_tweet_interstitial_search_rule: - default_availability: 10000 - -visibility_library_enable_drop_exclusive_tweet_content_rule: - default_availability: 10000 - -visibility_library_enable_drop_exclusive_tweet_content_rule_fail_closed: - default_availability: 10000 - -visibility_library_enable_drop_all_exclusive_tweets_rule: - default_availability: 10000 - -visibility_library_enable_drop_all_exclusive_tweets_rule_fail_closed: - default_availability: 10000 - -visibility_library_enable_tombstone_exclusive_quoted_tweet_content_rule: - default_availability: 10000 - -visibility_library_enable_downrank_spam_reply_sectioning_rule: - default_availability: 10000 - -visibility_library_enable_nsfw_text_sectioning_rule: - default_availability: 10000 - -visibility_library_enable_search_ipi_safe_search_without_user_in_query_drop_rule: - default_availability: 10000 - -visibility_library_enable_timeline_home_promoted_tweet_health_enforcement_rules: - default_availability: 10000 - -visibility_library_enable_muted_keyword_filtering_space_title_notifications_rule: - default_availability: 10000 - -visibility_library_enable_drop_tweets_with_georestricted_media_rule: - default_availability: 10000 - -visibility_library_enable_drop_all_trusted_friends_tweets_rule: - default_availability: 10000 - -visibility_library_enable_drop_all_trusted_friends_tweet_content_rule: - default_availability: 10000 - -visibility_library_enable_drop_all_collab_invitation_tweets_rule: - default_availability: 10000 - -visibility_library_enable_fetch_tweet_reported_perspective: - default_availability: 10000 - -visibility_library_enable_fetch_tweet_media_metadata: - default_availability: 10000 - -visibility_library_enable_follow_check_in_mutedkeyword: - default_availability: 10000 - -visibility_library_enable_media_interstitial_composition: - default_availability: 10000 - -visibility_library_enable_verdict_scribing_from_tweet_visibility_library: - default_availability: 0 - -visibility_library_enable_verdict_logger_event_publisher_instantiation_from_tweet_visibility_library: - default_availability: 10000 - -visibility_library_enable_verdict_scribing_from_timeline_conversations_visibility_library: - default_availability: 0 - -visibility_library_enable_verdict_logger_event_publisher_instantiation_from_timeline_conversations_visibility_library: - default_availability: 10000 - -visibility_library_enable_verdict_scribing_from_blender_visibility_library: - default_availability: 0 - -visibility_library_enable_verdict_logger_event_publisher_instantiation_from_blender_visibility_library: - default_availability: 10000 - -visibility_library_enable_verdict_scribing_from_search_visibility_library: - default_availability: 0 - -visibility_library_enable_verdict_logger_event_publisher_instantiation_from_search_visibility_library: - default_availability: 0 - -visibility_library_enable_localized_tombstones_on_visibility_results: - default_availability: 10000 - -visibility_library_enable_short_circuiting_from_tweet_visibility_library: - default_availability: 10000 - -visibility_library_enable_card_visibility_library_card_uri_parsing: - default_availability: 10000 - -visibility_library_enable_short_circuiting_from_timeline_conversations_visibility_library: - default_availability: 10000 - -visibility_library_enable_short_circuiting_from_blender_visibility_library: - default_availability: 10000 - -visibility_library_enable_short_circuiting_from_search_visibility_library: - default_availability: 0 - -visibility_library_enable_nsfw_text_high_precision_drop_rule: - default_availability: 10000 - -visibility_library_enable_spammy_tweet_rule_verdict_logging: - default_availability: 0 - -visibility_library_enable_downlevel_rule_verdict_logging: - default_availability: 0 - -visibility_library_enable_likely_likely_ivs_user_label_drop_rule: - default_availability: 10000 - -visibility_library_enable_card_uri_root_domain_deny_list_rule: - default_availability: 10000 - -visibility_library_enable_community_non_member_poll_card_rule: - default_availability: 10000 - -visibility_library_enable_community_non_member_poll_card_rule_fail_closed: - default_availability: 10000 - -visibility_library_enable_experimental_nudge_label_rule: - default_availability: 10000 - -visibility_library_enable_user_self_view_only_safety_level: - default_availability: 10000 - -visibility_library_nsfw_high_precision_user_label_avoid_tweet_rule_enabled: - default_availability: 10000 - -visibility_library_enable_new_ad_avoidance_rules: - default_availability: 10000 - -visibility_library_enable_nsfa_high_recall_ad_avoidance_rules: - default_availability: 0 - -visibility_library_enable_nsfa_keywords_high_precision_ad_avoidance_rules: - default_availability: 0 - -visibility_library_enable_stale_tweet_drop_rule: - default_availability: 10000 - -visibility_library_enable_stale_tweet_drop_rule_fail_closed: - default_availability: 10000 - -visibility_library_enable_edit_history_timeline_safety_level: - default_availability: 10000 - -visibility_library_enable_delete_state_tweet_rules: - default_availability: 10000 - -visibility_library_enable_spaces_sharing_nsfw_drop_rule: - default_availability: 10000 - -visibility_library_enable_viewer_is_soft_user_drop_rule: - default_availability: 10000 - -visibility_library_enable_backend_limited_actions: - default_availability: 10000 - -visibility_library_enable_base_qig_safety_level: - default_availability: 10000 - -visibility_library_enable_notifications_qig_safety_level: - default_availability: 10000 - -visibility_library_enable_access_internal_promoted_content_safety_level: - default_availability: 10000 - -visibility_library_enable_pdna_quoted_tweet_tombstone_rule: - default_availability: 10000 - -visibility_library_enable_spam_quoted_tweet_tombstone_rule: - default_availability: 10000 - -visibility_library_enable_nsfw_hp_quoted_tweet_drop_experiment_rule: - default_availability: 10000 - -visibility_library_enable_nsfw_hp_quoted_tweet_tombstone_experiment_rule: - default_availability: 10000 - -visibility_library_enable_inner_quoted_tweet_viewer_blocks_author_interstitial_rule: - default_availability: 10000 - -visibility_library_enable_inner_quoted_tweet_viewer_mutes_author_interstitial_rule: - default_availability: 10000 - -visibility_library_enable_experimental_rule_engine: - default_availability: 10000 - -visibility_library_enable_fosnr_rules: - default_availability: 0 - -visibility_library_enable_localized_interstitial_generator: - default_availability: 10000 - -visibility_library_convos_enable_legacy_interstitial: - default_availability: 10000 - -visibility_library_convos_enable_localized_interstitial: - default_availability: 10000 - -visibility_library_enable_profile_mixer_media_safety_level: - default_availability: 10000 - -visibility_library_enable_profile_mixer_favorites_safety_level: - default_availability: 10000 - -visibility_library_enable_zipbird_consumer_archives_safety_level: - default_availability: 10000 - -visibility_library_enable_tweet_award_safety_level: - default_availability: 10000 - -visibility_library_disable_legacy_interstitial_filtered_reason: - default_availability: 10000 - -visibility_library_enable_search_basic_block_mute_rules: - default_availability: 10000 - -visibility_library_enable_localized_interstitial_user_state_lib: - default_availability: 10000 - -visibility_library_enable_abusive_behavior_drop_rule: - default_availability: 10000 - -visibility_library_enable_abusive_behavior_interstitial_rule: - default_availability: 10000 - -visibility_library_enable_abusive_behavior_limited_engagements_rule: - default_availability: 10000 - -visibility_library_enable_not_graduated_downrank_convos_abusive_quality_rule: - default_availability: 0 - -visibility_library_enable_not_graduated_search_drop_rule: - default_availability: 0 - -visibility_library_enable_not_graduated_drop_rule: - default_availability: 0 - -visibility_library_enable_memoize_safety_level_params: - default_availability: 0 - -visibility_library_enable_author_blocks_viewer_drop_rule: - default_availability: 0 diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/BUILD deleted file mode 100644 index 47501c7d4..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/BUILD +++ /dev/null @@ -1,42 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "abdecider/src/main/scala", - "configapi/configapi-core", - "decider/src/main/scala", - "featureswitches/featureswitches-core/src/main/scala", - "servo/decider/src/main/scala", - "servo/util/src/main/scala", - "stitch/stitch-core", - "util/util-logging/src/main/scala", - "util/util-stats/src/main/scala", - "visibility/common/src/main/scala/com/twitter/visibility/common/actions", - "visibility/common/src/main/scala/com/twitter/visibility/common/stitch", - "visibility/lib/src/main/resources/config", - "visibility/lib/src/main/scala/com/twitter/visibility/builder", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/configs", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/params", - "visibility/lib/src/main/scala/com/twitter/visibility/engine", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/generators", - "visibility/lib/src/main/scala/com/twitter/visibility/models", - "visibility/lib/src/main/scala/com/twitter/visibility/rules", - "visibility/lib/src/main/scala/com/twitter/visibility/rules/generators", - "visibility/lib/src/main/scala/com/twitter/visibility/rules/providers", - "visibility/lib/src/main/scala/com/twitter/visibility/util", - ], - exports = [ - "configapi/configapi-core", - "visibility/common/src/main/scala/com/twitter/visibility/common/actions", - "visibility/lib/src/main/scala/com/twitter/visibility/builder", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/configs", - "visibility/lib/src/main/scala/com/twitter/visibility/models", - "visibility/lib/src/main/scala/com/twitter/visibility/rules", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/VisibilityLibrary.scala b/visibilitylib/src/main/scala/com/twitter/visibility/VisibilityLibrary.scala deleted file mode 100644 index 1e89c8818..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/VisibilityLibrary.scala +++ /dev/null @@ -1,387 +0,0 @@ -package com.twitter.visibility - -import com.twitter.abdecider.LoggingABDecider -import com.twitter.abdecider.NullABDecider -import com.twitter.decider.Decider -import com.twitter.decider.NullDecider -import com.twitter.featureswitches.v2.FeatureSwitches -import com.twitter.featureswitches.v2.NullFeatureSwitches -import com.twitter.finagle.stats.NullStatsReceiver -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.logging.Logger -import com.twitter.logging.NullLogger -import com.twitter.servo.util.Gate -import com.twitter.servo.util.MemoizingStatsReceiver -import com.twitter.stitch.Stitch -import com.twitter.timelines.configapi.Params -import com.twitter.util.Try -import com.twitter.visibility.builder._ -import com.twitter.visibility.common.stitch.StitchHelpers -import com.twitter.visibility.configapi.VisibilityParams -import com.twitter.visibility.configapi.configs.VisibilityDeciderGates -import com.twitter.visibility.engine.DeciderableVisibilityRuleEngine -import com.twitter.visibility.engine.VisibilityResultsMetricRecorder -import com.twitter.visibility.engine.VisibilityRuleEngine -import com.twitter.visibility.engine.VisibilityRulePreprocessor -import com.twitter.visibility.features.FeatureMap -import com.twitter.visibility.models.ContentId -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.ViewerContext -import com.twitter.visibility.rules.EvaluationContext -import com.twitter.visibility.rules.Rule -import com.twitter.visibility.rules.generators.TweetRuleGenerator -import com.twitter.visibility.rules.providers.InjectedPolicyProvider -import com.twitter.visibility.util.DeciderUtil -import com.twitter.visibility.util.FeatureSwitchUtil -import com.twitter.visibility.util.LoggingUtil - -object VisibilityLibrary { - - object Builder { - - def apply(log: Logger, statsReceiver: StatsReceiver): Builder = new Builder( - log, - new MemoizingStatsReceiver(statsReceiver) - ) - } - - case class Builder( - log: Logger, - statsReceiver: StatsReceiver, - decider: Option[Decider] = None, - abDecider: Option[LoggingABDecider] = None, - featureSwitches: Option[FeatureSwitches] = None, - enableStitchProfiling: Gate[Unit] = Gate.False, - captureDebugStats: Gate[Unit] = Gate.False, - enableComposableActions: Gate[Unit] = Gate.False, - enableFailClosed: Gate[Unit] = Gate.False, - enableShortCircuiting: Gate[Unit] = Gate.True, - memoizeSafetyLevelParams: Gate[Unit] = Gate.False) { - - def withDecider(decider: Decider): Builder = copy(decider = Some(decider)) - - @deprecated("use .withDecider and pass in a decider that is properly configured per DC") - def withDefaultDecider(isLocal: Boolean, useLocalOverrides: Boolean = false): Builder = { - if (isLocal) { - withLocalDecider - } else { - withDecider( - DeciderUtil.mkDecider( - useLocalDeciderOverrides = useLocalOverrides, - )) - } - } - - def withLocalDecider(): Builder = withDecider(DeciderUtil.mkLocalDecider) - - def withNullDecider(): Builder = - withDecider(new NullDecider(isAvail = true, availabilityDefined = true)) - - def withABDecider(abDecider: LoggingABDecider, featureSwitches: FeatureSwitches): Builder = - abDecider match { - case abd: NullABDecider => - copy(abDecider = Some(abd), featureSwitches = Some(NullFeatureSwitches)) - case _ => - copy( - abDecider = Some(abDecider), - featureSwitches = Some(featureSwitches) - ) - } - - def withABDecider(abDecider: LoggingABDecider): Builder = abDecider match { - case abd: NullABDecider => - withABDecider(abDecider = abd, featureSwitches = NullFeatureSwitches) - case _ => - withABDecider( - abDecider = abDecider, - featureSwitches = - FeatureSwitchUtil.mkVisibilityLibraryFeatureSwitches(abDecider, statsReceiver) - ) - } - - def withClientEventsLogger(clientEventsLogger: Logger): Builder = - withABDecider(DeciderUtil.mkABDecider(Some(clientEventsLogger))) - - def withDefaultABDecider(isLocal: Boolean): Builder = - if (isLocal) { - withABDecider(NullABDecider) - } else { - withClientEventsLogger(LoggingUtil.mkDefaultLogger(statsReceiver)) - } - - def withNullABDecider(): Builder = withABDecider(NullABDecider) - - def withEnableStitchProfiling(gate: Gate[Unit]): Builder = - copy(enableStitchProfiling = gate) - - def withCaptureDebugStats(gate: Gate[Unit]): Builder = - copy(captureDebugStats = gate) - - def withEnableComposableActions(gate: Gate[Unit]): Builder = - copy(enableComposableActions = gate) - - def withEnableComposableActions(gateBoolean: Boolean): Builder = { - val gate = Gate.const(gateBoolean) - copy(enableComposableActions = gate) - } - - def withEnableFailClosed(gate: Gate[Unit]): Builder = - copy(enableFailClosed = gate) - - def withEnableFailClosed(gateBoolean: Boolean): Builder = { - val gate = Gate.const(gateBoolean) - copy(enableFailClosed = gate) - } - - def withEnableShortCircuiting(gate: Gate[Unit]): Builder = - copy(enableShortCircuiting = gate) - - def withEnableShortCircuiting(gateBoolean: Boolean): Builder = { - val gate = Gate.const(gateBoolean) - copy(enableShortCircuiting = gate) - } - - def memoizeSafetyLevelParams(gate: Gate[Unit]): Builder = - copy(memoizeSafetyLevelParams = gate) - - def memoizeSafetyLevelParams(gateBoolean: Boolean): Builder = { - val gate = Gate.const(gateBoolean) - copy(memoizeSafetyLevelParams = gate) - } - - def build(): VisibilityLibrary = { - - (decider, abDecider, featureSwitches) match { - case (None, _, _) => - throw new IllegalStateException( - "Decider is unset! If intentional, please call .withNullDecider()." - ) - - case (_, None, _) => - throw new IllegalStateException( - "ABDecider is unset! If intentional, please call .withNullABDecider()." - ) - - case (_, _, None) => - throw new IllegalStateException( - "FeatureSwitches is unset! This is a bug." - ) - - case (Some(d), Some(abd), Some(fs)) => - new VisibilityLibrary( - statsReceiver, - d, - abd, - VisibilityParams(log, statsReceiver, d, abd, fs), - enableStitchProfiling = enableStitchProfiling, - captureDebugStats = captureDebugStats, - enableComposableActions = enableComposableActions, - enableFailClosed = enableFailClosed, - enableShortCircuiting = enableShortCircuiting, - memoizeSafetyLevelParams = memoizeSafetyLevelParams) - } - } - } - - val nullDecider = new NullDecider(true, true) - - lazy val NullLibrary: VisibilityLibrary = new VisibilityLibrary( - NullStatsReceiver, - nullDecider, - NullABDecider, - VisibilityParams( - NullLogger, - NullStatsReceiver, - nullDecider, - NullABDecider, - NullFeatureSwitches), - enableStitchProfiling = Gate.False, - captureDebugStats = Gate.False, - enableComposableActions = Gate.False, - enableFailClosed = Gate.False, - enableShortCircuiting = Gate.True, - memoizeSafetyLevelParams = Gate.False - ) -} - -class VisibilityLibrary private[VisibilityLibrary] ( - baseStatsReceiver: StatsReceiver, - decider: Decider, - abDecider: LoggingABDecider, - visibilityParams: VisibilityParams, - enableStitchProfiling: Gate[Unit], - captureDebugStats: Gate[Unit], - enableComposableActions: Gate[Unit], - enableFailClosed: Gate[Unit], - enableShortCircuiting: Gate[Unit], - memoizeSafetyLevelParams: Gate[Unit]) { - - val statsReceiver: StatsReceiver = - new MemoizingStatsReceiver(baseStatsReceiver.scope("visibility_library")) - - val metricsRecorder = VisibilityResultsMetricRecorder(statsReceiver, captureDebugStats) - - val visParams: VisibilityParams = visibilityParams - - val visibilityDeciderGates = VisibilityDeciderGates(decider) - - val profileStats: MemoizingStatsReceiver = new MemoizingStatsReceiver( - statsReceiver.scope("profiling")) - - val perSafetyLevelProfileStats: StatsReceiver = profileStats.scope("for_safety_level") - - val featureMapBuilder: FeatureMapBuilder.Build = - FeatureMapBuilder(statsReceiver, enableStitchProfiling) - - private lazy val tweetRuleGenerator = new TweetRuleGenerator() - lazy val policyProvider = new InjectedPolicyProvider( - visibilityDeciderGates = visibilityDeciderGates, - tweetRuleGenerator = tweetRuleGenerator) - - val candidateVisibilityRulePreprocessor: VisibilityRulePreprocessor = VisibilityRulePreprocessor( - metricsRecorder, - policyProviderOpt = Some(policyProvider) - ) - - val fallbackVisibilityRulePreprocessor: VisibilityRulePreprocessor = VisibilityRulePreprocessor( - metricsRecorder) - - lazy val candidateVisibilityRuleEngine: VisibilityRuleEngine = VisibilityRuleEngine( - Some(candidateVisibilityRulePreprocessor), - metricsRecorder, - enableComposableActions, - enableFailClosed, - policyProviderOpt = Some(policyProvider) - ) - - lazy val fallbackVisibilityRuleEngine: VisibilityRuleEngine = VisibilityRuleEngine( - Some(fallbackVisibilityRulePreprocessor), - metricsRecorder, - enableComposableActions, - enableFailClosed) - - val ruleEngineVersionStatsReceiver = statsReceiver.scope("rule_engine_version") - def isReleaseCandidateEnabled: Boolean = visibilityDeciderGates.enableExperimentalRuleEngine() - - private def visibilityRuleEngine: DeciderableVisibilityRuleEngine = { - if (isReleaseCandidateEnabled) { - ruleEngineVersionStatsReceiver.counter("release_candidate").incr() - candidateVisibilityRuleEngine - } else { - ruleEngineVersionStatsReceiver.counter("fallback").incr() - fallbackVisibilityRuleEngine - } - } - - private def profileStitch[A](result: Stitch[A], safetyLevelName: String): Stitch[A] = - if (enableStitchProfiling()) { - StitchHelpers.profileStitch( - result, - Seq(profileStats, perSafetyLevelProfileStats.scope(safetyLevelName)) - ) - } else { - result - } - - def getParams(viewerContext: ViewerContext, safetyLevel: SafetyLevel): Params = { - if (memoizeSafetyLevelParams()) { - visibilityParams.memoized(viewerContext, safetyLevel) - } else { - visibilityParams(viewerContext, safetyLevel) - } - } - - def evaluationContextBuilder(viewerContext: ViewerContext): EvaluationContext.Builder = - EvaluationContext - .Builder(statsReceiver, visibilityParams, viewerContext) - .withMemoizedParams(memoizeSafetyLevelParams) - - def runRuleEngine( - contentId: ContentId, - featureMap: FeatureMap, - evaluationContextBuilder: EvaluationContext.Builder, - safetyLevel: SafetyLevel - ): Stitch[VisibilityResult] = - profileStitch( - visibilityRuleEngine( - evaluationContextBuilder.build(safetyLevel), - safetyLevel, - new VisibilityResultBuilder(contentId, featureMap), - enableShortCircuiting - ), - safetyLevel.name - ) - - def runRuleEngine( - contentId: ContentId, - featureMap: FeatureMap, - viewerContext: ViewerContext, - safetyLevel: SafetyLevel - ): Stitch[VisibilityResult] = - profileStitch( - visibilityRuleEngine( - EvaluationContext(safetyLevel, getParams(viewerContext, safetyLevel), statsReceiver), - safetyLevel, - new VisibilityResultBuilder(contentId, featureMap), - enableShortCircuiting - ), - safetyLevel.name - ) - - def runRuleEngine( - viewerContext: ViewerContext, - safetyLevel: SafetyLevel, - preprocessedResultBuilder: VisibilityResultBuilder, - preprocessedRules: Seq[Rule] - ): Stitch[VisibilityResult] = - profileStitch( - visibilityRuleEngine( - EvaluationContext(safetyLevel, getParams(viewerContext, safetyLevel), statsReceiver), - safetyLevel, - preprocessedResultBuilder, - enableShortCircuiting, - Some(preprocessedRules) - ), - safetyLevel.name - ) - - def runRuleEngineBatch( - contentIds: Seq[ContentId], - featureMapProvider: (ContentId, SafetyLevel) => FeatureMap, - viewerContext: ViewerContext, - safetyLevel: SafetyLevel, - ): Stitch[Seq[Try[VisibilityResult]]] = { - val params = getParams(viewerContext, safetyLevel) - profileStitch( - Stitch.traverse(contentIds) { contentId => - visibilityRuleEngine( - EvaluationContext(safetyLevel, params, NullStatsReceiver), - safetyLevel, - new VisibilityResultBuilder(contentId, featureMapProvider(contentId, safetyLevel)), - enableShortCircuiting - ).liftToTry - }, - safetyLevel.name - ) - } - - def runRuleEngineBatch( - contentIds: Seq[ContentId], - featureMapProvider: (ContentId, SafetyLevel) => FeatureMap, - evaluationContextBuilder: EvaluationContext.Builder, - safetyLevel: SafetyLevel - ): Stitch[Seq[Try[VisibilityResult]]] = { - val evaluationContext = evaluationContextBuilder.build(safetyLevel) - profileStitch( - Stitch.traverse(contentIds) { contentId => - visibilityRuleEngine( - evaluationContext, - safetyLevel, - new VisibilityResultBuilder(contentId, featureMapProvider(contentId, safetyLevel)), - enableShortCircuiting - ).liftToTry - }, - safetyLevel.name - ) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/builder/BUILD deleted file mode 100644 index 46f9c1147..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/BUILD +++ /dev/null @@ -1,29 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/twitter/src/java/com/twitter/logpipeline/client:logpipeline-event-publisher-thin", - "configapi/configapi-core", - "decider/src/main/scala", - "servo/util/src/main/scala", - "src/thrift/com/twitter/search/common:constants-scala", - "src/thrift/com/twitter/spam/rtf:safety-level-scala", - "src/thrift/com/twitter/spam/rtf:safety-result-scala", - "src/thrift/com/twitter/spam/rtf:tweet-rtf-event-scala", - "stitch/stitch-core", - "util/util-stats/src/main/scala/com/twitter/finagle/stats", - "visibility/common/src/main/scala/com/twitter/visibility/common/actions", - "visibility/common/src/main/scala/com/twitter/visibility/common/actions/converter/scala", - "visibility/common/src/main/scala/com/twitter/visibility/common/stitch", - "visibility/common/src/main/thrift/com/twitter/visibility:action-scala", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/configs", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/models", - "visibility/lib/src/main/scala/com/twitter/visibility/rules", - "visibility/lib/src/main/scala/com/twitter/visibility/util", - "visibility/lib/src/main/thrift/com/twitter/visibility/logging:vf-logging-scala", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/FeatureMapBuilder.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/FeatureMapBuilder.scala deleted file mode 100644 index 946879c5e..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/FeatureMapBuilder.scala +++ /dev/null @@ -1,64 +0,0 @@ -package com.twitter.visibility.builder - -import com.twitter.finagle.stats.NullStatsReceiver -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.servo.util.Gate -import com.twitter.stitch.Stitch -import com.twitter.visibility.features._ -import com.twitter.visibility.common.stitch.StitchHelpers -import scala.collection.mutable - -object FeatureMapBuilder { - type Build = Seq[FeatureMapBuilder => FeatureMapBuilder] => FeatureMap - - def apply( - statsReceiver: StatsReceiver = NullStatsReceiver, - enableStitchProfiling: Gate[Unit] = Gate.False - ): Build = - fns => - Function - .chain(fns).apply( - new FeatureMapBuilder(statsReceiver, enableStitchProfiling) - ).build -} - -class FeatureMapBuilder private[builder] ( - statsReceiver: StatsReceiver, - enableStitchProfiling: Gate[Unit] = Gate.False) { - - private[this] val hydratedScope = - statsReceiver.scope("visibility_result_builder").scope("hydrated") - - val mapBuilder: mutable.Builder[(Feature[_], Stitch[_]), Map[Feature[_], Stitch[_]]] = - Map.newBuilder[Feature[_], Stitch[_]] - - val constantMapBuilder: mutable.Builder[(Feature[_], Any), Map[Feature[_], Any]] = - Map.newBuilder[Feature[_], Any] - - def build: FeatureMap = new FeatureMap(mapBuilder.result(), constantMapBuilder.result()) - - def withConstantFeature[T](feature: Feature[T], value: T): FeatureMapBuilder = { - val anyValue: Any = value.asInstanceOf[Any] - constantMapBuilder += (feature -> anyValue) - this - } - - def withFeature[T](feature: Feature[T], stitch: Stitch[T]): FeatureMapBuilder = { - val profiledStitch = if (enableStitchProfiling()) { - val featureScope = hydratedScope.scope(feature.name) - StitchHelpers.profileStitch(stitch, Seq(hydratedScope, featureScope)) - } else { - stitch - } - - val featureStitchRef = Stitch.ref(profiledStitch) - - mapBuilder += FeatureMap.rescueFeatureTuple(feature -> featureStitchRef) - - this - } - - def withConstantFeature[T](feature: Feature[T], option: Option[T]): FeatureMapBuilder = { - option.map(withConstantFeature(feature, _)).getOrElse(this) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/VerdictLogger.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/VerdictLogger.scala deleted file mode 100644 index a47a35fa2..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/VerdictLogger.scala +++ /dev/null @@ -1,187 +0,0 @@ -package com.twitter.visibility.builder - -import com.twitter.datatools.entityservice.entities.thriftscala.FleetInterstitial -import com.twitter.decider.Decider -import com.twitter.decider.Decider.NullDecider -import com.twitter.finagle.stats.NullStatsReceiver -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.logpipeline.client.common.EventPublisher -import com.twitter.logpipeline.client.EventPublisherManager -import com.twitter.logpipeline.client.serializers.EventLogMsgThriftStructSerializer -import com.twitter.spam.rtf.thriftscala.SafetyLevel -import com.twitter.visibility.builder.VerdictLogger.FailureCounterName -import com.twitter.visibility.builder.VerdictLogger.SuccessCounterName -import com.twitter.visibility.features.Feature -import com.twitter.visibility.logging.thriftscala.ActionSource -import com.twitter.visibility.logging.thriftscala.EntityId -import com.twitter.visibility.logging.thriftscala.EntityIdType -import com.twitter.visibility.logging.thriftscala.EntityIdValue -import com.twitter.visibility.logging.thriftscala.HealthActionType -import com.twitter.visibility.logging.thriftscala.MisinfoPolicyCategory -import com.twitter.visibility.logging.thriftscala.VFLibType -import com.twitter.visibility.logging.thriftscala.VFVerdictLogEntry -import com.twitter.visibility.models.ContentId -import com.twitter.visibility.rules._ - -object VerdictLogger { - - private val BaseStatsNamespace = "vf_verdict_logger" - private val FailureCounterName = "failures" - private val SuccessCounterName = "successes" - val LogCategoryName: String = "visibility_filtering_verdicts" - - val Empty: VerdictLogger = new VerdictLogger(NullStatsReceiver, NullDecider, None) - - def apply( - statsReceiver: StatsReceiver, - decider: Decider - ): VerdictLogger = { - val eventPublisher: EventPublisher[VFVerdictLogEntry] = - EventPublisherManager - .newScribePublisherBuilder( - LogCategoryName, - EventLogMsgThriftStructSerializer.getNewSerializer[VFVerdictLogEntry]()).build() - new VerdictLogger(statsReceiver.scope(BaseStatsNamespace), decider, Some(eventPublisher)) - } -} - -class VerdictLogger( - statsReceiver: StatsReceiver, - decider: Decider, - publisherOpt: Option[EventPublisher[VFVerdictLogEntry]]) { - - def log( - verdictLogEntry: VFVerdictLogEntry, - publisher: EventPublisher[VFVerdictLogEntry] - ): Unit = { - publisher - .publish(verdictLogEntry) - .onSuccess(_ => statsReceiver.counter(SuccessCounterName).incr()) - .onFailure { e => - statsReceiver.counter(FailureCounterName).incr() - statsReceiver.scope(FailureCounterName).counter(e.getClass.getName).incr() - } - } - - private def toEntityId(contentId: ContentId): Option[EntityId] = { - contentId match { - case ContentId.TweetId(id) => Some(EntityId(EntityIdType.TweetId, EntityIdValue.EntityId(id))) - case ContentId.UserId(id) => Some(EntityId(EntityIdType.UserId, EntityIdValue.EntityId(id))) - case ContentId.QuotedTweetRelationship(outerTweetId, _) => - Some(EntityId(EntityIdType.TweetId, EntityIdValue.EntityId(outerTweetId))) - case ContentId.NotificationId(Some(id)) => - Some(EntityId(EntityIdType.NotificationId, EntityIdValue.EntityId(id))) - case ContentId.DmId(id) => Some(EntityId(EntityIdType.DmId, EntityIdValue.EntityId(id))) - case ContentId.BlenderTweetId(id) => - Some(EntityId(EntityIdType.TweetId, EntityIdValue.EntityId(id))) - case ContentId.SpacePlusUserId(_) => - } - } - - private def getLogEntryData( - actingRule: Option[Rule], - secondaryActingRules: Seq[Rule], - verdict: Action, - secondaryVerdicts: Seq[Action], - resolvedFeatureMap: Map[Feature[_], Any] - ): (Seq[String], Seq[ActionSource], Seq[HealthActionType], Option[FleetInterstitial]) = { - actingRule - .filter { - case decideredRule: DoesLogVerdictDecidered => - decider.isAvailable(decideredRule.verdictLogDeciderKey.toString) - case rule: DoesLogVerdict => true - case _ => false - } - .map { primaryRule => - val secondaryRulesAndVerdicts = secondaryActingRules zip secondaryVerdicts - var actingRules: Seq[Rule] = Seq(primaryRule) - var actingRuleNames: Seq[String] = Seq(primaryRule.name) - var actionSources: Seq[ActionSource] = Seq() - var healthActionTypes: Seq[HealthActionType] = Seq(verdict.toHealthActionTypeThrift.get) - - val misinfoPolicyCategory: Option[FleetInterstitial] = { - verdict match { - case softIntervention: SoftIntervention => - softIntervention.fleetInterstitial - case tweetInterstitial: TweetInterstitial => - tweetInterstitial.softIntervention.flatMap(_.fleetInterstitial) - case _ => None - } - } - - secondaryRulesAndVerdicts.foreach(ruleAndVerdict => { - if (ruleAndVerdict._1.isInstanceOf[DoesLogVerdict]) { - actingRules = actingRules :+ ruleAndVerdict._1 - actingRuleNames = actingRuleNames :+ ruleAndVerdict._1.name - healthActionTypes = healthActionTypes :+ ruleAndVerdict._2.toHealthActionTypeThrift.get - } - }) - - actingRules.foreach(rule => { - rule.actionSourceBuilder - .flatMap(_.build(resolvedFeatureMap, verdict)) - .map(actionSource => { - actionSources = actionSources :+ actionSource - }) - }) - (actingRuleNames, actionSources, healthActionTypes, misinfoPolicyCategory) - } - .getOrElse((Seq.empty[String], Seq.empty[ActionSource], Seq.empty[HealthActionType], None)) - } - - def scribeVerdict( - visibilityResult: VisibilityResult, - safetyLevel: SafetyLevel, - vfLibType: VFLibType, - viewerId: Option[Long] = None - ): Unit = { - publisherOpt.foreach { publisher => - toEntityId(visibilityResult.contentId).foreach { entityId => - visibilityResult.verdict.toHealthActionTypeThrift.foreach { healthActionType => - val (actioningRules, actionSources, healthActionTypes, misinfoPolicyCategory) = - getLogEntryData( - actingRule = visibilityResult.actingRule, - secondaryActingRules = visibilityResult.secondaryActingRules, - verdict = visibilityResult.verdict, - secondaryVerdicts = visibilityResult.secondaryVerdicts, - resolvedFeatureMap = visibilityResult.resolvedFeatureMap - ) - - if (actioningRules.nonEmpty) { - log( - VFVerdictLogEntry( - entityId = entityId, - viewerId = viewerId, - timestampMsec = System.currentTimeMillis(), - vfLibType = vfLibType, - healthActionType = healthActionType, - safetyLevel = safetyLevel, - actioningRules = actioningRules, - actionSources = actionSources, - healthActionTypes = healthActionTypes, - misinfoPolicyCategory = - fleetInterstitialToMisinfoPolicyCategory(misinfoPolicyCategory) - ), - publisher - ) - } - } - } - } - } - - def fleetInterstitialToMisinfoPolicyCategory( - fleetInterstitialOption: Option[FleetInterstitial] - ): Option[MisinfoPolicyCategory] = { - fleetInterstitialOption.map { - case FleetInterstitial.Generic => - MisinfoPolicyCategory.Generic - case FleetInterstitial.Samm => - MisinfoPolicyCategory.Samm - case FleetInterstitial.CivicIntegrity => - MisinfoPolicyCategory.CivicIntegrity - case _ => MisinfoPolicyCategory.Unknown - } - } - -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/VisibilityResult.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/VisibilityResult.scala deleted file mode 100644 index bdf8764eb..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/VisibilityResult.scala +++ /dev/null @@ -1,112 +0,0 @@ -package com.twitter.visibility.builder - -import com.twitter.spam.rtf.thriftscala.SafetyResult -import com.twitter.visibility.common.actions.converter.scala.DropReasonConverter -import com.twitter.visibility.rules.ComposableActions._ -import com.twitter.visibility.features.Feature -import com.twitter.visibility.features.FeatureMap -import com.twitter.visibility.models.ContentId -import com.twitter.visibility.rules._ -import com.twitter.visibility.{thriftscala => t} - -case class VisibilityResult( - contentId: ContentId, - featureMap: FeatureMap = FeatureMap.empty, - ruleResultMap: Map[Rule, RuleResult] = Map.empty, - verdict: Action = Allow, - finished: Boolean = false, - actingRule: Option[Rule] = None, - secondaryActingRules: Seq[Rule] = Seq(), - secondaryVerdicts: Seq[Action] = Seq(), - resolvedFeatureMap: Map[Feature[_], Any] = Map.empty) { - - def getSafetyResult: SafetyResult = - verdict match { - case InterstitialLimitedEngagements(reason: Reason, _, _, _) - if PublicInterest.Reasons - .contains(reason) => - SafetyResult( - Some(PublicInterest.ReasonToSafetyResultReason(reason)), - verdict.toActionThrift() - ) - case ComposableActionsWithInterstitialLimitedEngagements(tweetInterstitial) - if PublicInterest.Reasons.contains(tweetInterstitial.reason) => - SafetyResult( - Some(PublicInterest.ReasonToSafetyResultReason(tweetInterstitial.reason)), - verdict.toActionThrift() - ) - case FreedomOfSpeechNotReachReason(appealableReason) => - SafetyResult( - Some(FreedomOfSpeechNotReach.reasonToSafetyResultReason(appealableReason)), - verdict.toActionThrift() - ) - case _ => SafetyResult(None, verdict.toActionThrift()) - } - - def getUserVisibilityResult: Option[t.UserVisibilityResult] = - (verdict match { - case Drop(reason, _) => - Some( - t.UserAction.Drop(t.Drop(Reason.toDropReason(reason).map(DropReasonConverter.toThrift)))) - case _ => None - }).map(userAction => t.UserVisibilityResult(Some(userAction))) -} - -object VisibilityResult { - class Builder { - var featureMap: FeatureMap = FeatureMap.empty - var ruleResultMap: Map[Rule, RuleResult] = Map.empty - var verdict: Action = Allow - var finished: Boolean = false - var actingRule: Option[Rule] = None - var secondaryActingRules: Seq[Rule] = Seq() - var secondaryVerdicts: Seq[Action] = Seq() - var resolvedFeatureMap: Map[Feature[_], Any] = Map.empty - - def withFeatureMap(featureMapBld: FeatureMap) = { - featureMap = featureMapBld - this - } - - def withRuleResultMap(ruleResultMapBld: Map[Rule, RuleResult]) = { - ruleResultMap = ruleResultMapBld - this - } - - def withVerdict(verdictBld: Action) = { - verdict = verdictBld - this - } - - def withFinished(finishedBld: Boolean) = { - finished = finishedBld - this - } - - def withActingRule(actingRuleBld: Option[Rule]) = { - actingRule = actingRuleBld - this - } - - def withSecondaryActingRules(secondaryActingRulesBld: Seq[Rule]) = { - secondaryActingRules = secondaryActingRulesBld - this - } - - def withSecondaryVerdicts(secondaryVerdictsBld: Seq[Action]) = { - secondaryVerdicts = secondaryVerdictsBld - this - } - - def build(contentId: ContentId) = VisibilityResult( - contentId, - featureMap, - ruleResultMap, - verdict, - finished, - actingRule, - secondaryActingRules, - secondaryVerdicts, - resolvedFeatureMap) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/VisibilityResultBuilder.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/VisibilityResultBuilder.scala deleted file mode 100644 index 83731eb88..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/VisibilityResultBuilder.scala +++ /dev/null @@ -1,114 +0,0 @@ -package com.twitter.visibility.builder - -import com.twitter.visibility.features.Feature -import com.twitter.visibility.features.FeatureMap -import com.twitter.visibility.models.ContentId -import com.twitter.visibility.rules.Action -import com.twitter.visibility.rules.Allow -import com.twitter.visibility.rules.EvaluationContext -import com.twitter.visibility.rules.FailClosedException -import com.twitter.visibility.rules.FeaturesFailedException -import com.twitter.visibility.rules.MissingFeaturesException -import com.twitter.visibility.rules.Rule -import com.twitter.visibility.rules.RuleFailedException -import com.twitter.visibility.rules.RuleResult -import com.twitter.visibility.rules.State.FeatureFailed -import com.twitter.visibility.rules.State.MissingFeature -import com.twitter.visibility.rules.State.RuleFailed - -class VisibilityResultBuilder( - val contentId: ContentId, - val featureMap: FeatureMap = FeatureMap.empty, - private var ruleResultMap: Map[Rule, RuleResult] = Map.empty) { - private var mapBuilder = Map.newBuilder[Rule, RuleResult] - mapBuilder ++= ruleResultMap - var verdict: Action = Allow - var finished: Boolean = false - var features: FeatureMap = featureMap - var actingRule: Option[Rule] = None - var secondaryVerdicts: Seq[Action] = Seq() - var secondaryActingRules: Seq[Rule] = Seq() - var resolvedFeatureMap: Map[Feature[_], Any] = Map.empty - - def ruleResults: Map[Rule, RuleResult] = mapBuilder.result() - - def withFeatureMap(featureMap: FeatureMap): VisibilityResultBuilder = { - this.features = featureMap - this - } - - def withRuleResultMap(ruleResultMap: Map[Rule, RuleResult]): VisibilityResultBuilder = { - this.ruleResultMap = ruleResultMap - mapBuilder = Map.newBuilder[Rule, RuleResult] - mapBuilder ++= ruleResultMap - this - } - - def withRuleResult(rule: Rule, result: RuleResult): VisibilityResultBuilder = { - mapBuilder += ((rule, result)) - this - } - - def withVerdict(verdict: Action, ruleOpt: Option[Rule] = None): VisibilityResultBuilder = { - this.verdict = verdict - this.actingRule = ruleOpt - this - } - - def withSecondaryVerdict(verdict: Action, rule: Rule): VisibilityResultBuilder = { - this.secondaryVerdicts = this.secondaryVerdicts :+ verdict - this.secondaryActingRules = this.secondaryActingRules :+ rule - this - } - - def withFinished(finished: Boolean): VisibilityResultBuilder = { - this.finished = finished - this - } - - def withResolvedFeatureMap( - resolvedFeatureMap: Map[Feature[_], Any] - ): VisibilityResultBuilder = { - this.resolvedFeatureMap = resolvedFeatureMap - this - } - - def isVerdictComposable(): Boolean = this.verdict.isComposable - - def failClosedException(evaluationContext: EvaluationContext): Option[FailClosedException] = { - mapBuilder - .result().collect { - case (r: Rule, RuleResult(_, MissingFeature(mf))) - if r.shouldFailClosed(evaluationContext.params) => - Some(MissingFeaturesException(r.name, mf)) - case (r: Rule, RuleResult(_, FeatureFailed(ff))) - if r.shouldFailClosed(evaluationContext.params) => - Some(FeaturesFailedException(r.name, ff)) - case (r: Rule, RuleResult(_, RuleFailed(t))) - if r.shouldFailClosed(evaluationContext.params) => - Some(RuleFailedException(r.name, t)) - }.toList.foldLeft(None: Option[FailClosedException]) { (acc, arg) => - (acc, arg) match { - case (None, Some(_)) => arg - case (Some(FeaturesFailedException(_, _)), Some(MissingFeaturesException(_, _))) => arg - case (Some(RuleFailedException(_, _)), Some(MissingFeaturesException(_, _))) => arg - case (Some(RuleFailedException(_, _)), Some(FeaturesFailedException(_, _))) => arg - case _ => acc - } - } - } - - def build: VisibilityResult = { - VisibilityResult( - contentId = contentId, - featureMap = features, - ruleResultMap = mapBuilder.result(), - verdict = verdict, - finished = finished, - actingRule = actingRule, - secondaryActingRules = secondaryActingRules, - secondaryVerdicts = secondaryVerdicts, - resolvedFeatureMap = resolvedFeatureMap - ) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/common/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/builder/common/BUILD deleted file mode 100644 index 5d44ccfd1..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/common/BUILD +++ /dev/null @@ -1,32 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/google/guava", - "communities/thrift/src/main/thrift/com/twitter/communities:thrift-scala", - "communities/thrift/src/main/thrift/com/twitter/communities/moderation:thrift-scala", - "escherbird/src/thrift/com/twitter/escherbird/softintervention:softintervention_thrift-scala", - "snowflake/src/main/scala/com/twitter/snowflake/id", - "src/thrift/com/twitter/context:twitter-context-scala", - "src/thrift/com/twitter/escherbird/common:common-scala", - "src/thrift/com/twitter/gizmoduck:user-thrift-scala", - "src/thrift/com/twitter/search/common:constants-scala", - "src/thrift/com/twitter/spam/rtf:safety-level-scala", - "src/thrift/com/twitter/spam/rtf:tweet-rtf-event-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "stitch/stitch-core", - "tweetypie/src/scala/com/twitter/tweetypie/additionalfields", - "twitter-context/src/main/scala", - "visibility/common/src/main/scala/com/twitter/visibility/common", - "visibility/common/src/main/scala/com/twitter/visibility/common/stitch", - "visibility/lib/src/main/resources/config", - "visibility/lib/src/main/scala/com/twitter/visibility", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/users", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/interfaces/common/blender", - "visibility/lib/src/main/scala/com/twitter/visibility/interfaces/common/tweets", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/common/MutedKeywordFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/common/MutedKeywordFeatures.scala deleted file mode 100644 index eb0a21663..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/common/MutedKeywordFeatures.scala +++ /dev/null @@ -1,228 +0,0 @@ -package com.twitter.visibility.builder.common - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.gizmoduck.thriftscala.MuteOption -import com.twitter.gizmoduck.thriftscala.MuteSurface -import com.twitter.gizmoduck.thriftscala.{MutedKeyword => GdMutedKeyword} -import com.twitter.servo.util.Gate -import com.twitter.stitch.Stitch -import com.twitter.tweetypie.thriftscala.Tweet -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.common._ -import com.twitter.visibility.features._ -import com.twitter.visibility.models.{MutedKeyword => VfMutedKeyword} -import java.util.Locale - -class MutedKeywordFeatures( - userSource: UserSource, - userRelationshipSource: UserRelationshipSource, - keywordMatcher: KeywordMatcher.Matcher = KeywordMatcher.TestMatcher, - statsReceiver: StatsReceiver, - enableFollowCheckInMutedKeyword: Gate[Unit] = Gate.False) { - - private[this] val scopedStatsReceiver: StatsReceiver = - statsReceiver.scope("muted_keyword_features") - - private[this] val requests = scopedStatsReceiver.counter("requests") - - private[this] val viewerMutesKeywordInTweetForHomeTimeline = - scopedStatsReceiver.scope(ViewerMutesKeywordInTweetForHomeTimeline.name).counter("requests") - private[this] val viewerMutesKeywordInTweetForTweetReplies = - scopedStatsReceiver.scope(ViewerMutesKeywordInTweetForTweetReplies.name).counter("requests") - private[this] val viewerMutesKeywordInTweetForNotifications = - scopedStatsReceiver.scope(ViewerMutesKeywordInTweetForNotifications.name).counter("requests") - private[this] val excludeFollowingForMutedKeywordsRequests = - scopedStatsReceiver.scope("exclude_following").counter("requests") - private[this] val viewerMutesKeywordInTweetForAllSurfaces = - scopedStatsReceiver.scope(ViewerMutesKeywordInTweetForAllSurfaces.name).counter("requests") - - def forTweet( - tweet: Tweet, - viewerId: Option[Long], - authorId: Long - ): FeatureMapBuilder => FeatureMapBuilder = { featureMapBuilder => - requests.incr() - viewerMutesKeywordInTweetForHomeTimeline.incr() - viewerMutesKeywordInTweetForTweetReplies.incr() - viewerMutesKeywordInTweetForNotifications.incr() - viewerMutesKeywordInTweetForAllSurfaces.incr() - - val keywordsBySurface = allMutedKeywords(viewerId) - - val keywordsWithoutDefinedSurface = allMutedKeywordsWithoutDefinedSurface(viewerId) - - featureMapBuilder - .withFeature( - ViewerMutesKeywordInTweetForHomeTimeline, - tweetContainsMutedKeyword( - tweet, - keywordsBySurface, - MuteSurface.HomeTimeline, - viewerId, - authorId - ) - ) - .withFeature( - ViewerMutesKeywordInTweetForTweetReplies, - tweetContainsMutedKeyword( - tweet, - keywordsBySurface, - MuteSurface.TweetReplies, - viewerId, - authorId - ) - ) - .withFeature( - ViewerMutesKeywordInTweetForNotifications, - tweetContainsMutedKeyword( - tweet, - keywordsBySurface, - MuteSurface.Notifications, - viewerId, - authorId - ) - ) - .withFeature( - ViewerMutesKeywordInTweetForAllSurfaces, - tweetContainsMutedKeywordWithoutDefinedSurface( - tweet, - keywordsWithoutDefinedSurface, - viewerId, - authorId - ) - ) - } - - def allMutedKeywords(viewerId: Option[Long]): Stitch[Map[MuteSurface, Seq[GdMutedKeyword]]] = - viewerId - .map { id => userSource.getAllMutedKeywords(id) }.getOrElse(Stitch.value(Map.empty)) - - def allMutedKeywordsWithoutDefinedSurface(viewerId: Option[Long]): Stitch[Seq[GdMutedKeyword]] = - viewerId - .map { id => userSource.getAllMutedKeywordsWithoutDefinedSurface(id) }.getOrElse( - Stitch.value(Seq.empty)) - - private def mutingKeywordsText( - mutedKeywords: Seq[GdMutedKeyword], - muteSurface: MuteSurface, - viewerIdOpt: Option[Long], - authorId: Long - ): Stitch[Option[String]] = { - if (muteSurface == MuteSurface.HomeTimeline && mutedKeywords.nonEmpty) { - Stitch.value(Some(mutedKeywords.map(_.keyword).mkString(","))) - } else { - mutedKeywords.partition(kw => - kw.muteOptions.contains(MuteOption.ExcludeFollowingAccounts)) match { - case (_, mutedKeywordsFromAnyone) if mutedKeywordsFromAnyone.nonEmpty => - Stitch.value(Some(mutedKeywordsFromAnyone.map(_.keyword).mkString(","))) - case (mutedKeywordsExcludeFollowing, _) - if mutedKeywordsExcludeFollowing.nonEmpty && enableFollowCheckInMutedKeyword() => - excludeFollowingForMutedKeywordsRequests.incr() - viewerIdOpt match { - case Some(viewerId) => - userRelationshipSource.follows(viewerId, authorId).map { - case true => - case false => Some(mutedKeywordsExcludeFollowing.map(_.keyword).mkString(",")) - } - case _ => Stitch.None - } - case (_, _) => Stitch.None - } - } - } - - private def mutingKeywordsTextWithoutDefinedSurface( - mutedKeywords: Seq[GdMutedKeyword], - viewerIdOpt: Option[Long], - authorId: Long - ): Stitch[Option[String]] = { - mutedKeywords.partition(kw => - kw.muteOptions.contains(MuteOption.ExcludeFollowingAccounts)) match { - case (_, mutedKeywordsFromAnyone) if mutedKeywordsFromAnyone.nonEmpty => - Stitch.value(Some(mutedKeywordsFromAnyone.map(_.keyword).mkString(","))) - case (mutedKeywordsExcludeFollowing, _) - if mutedKeywordsExcludeFollowing.nonEmpty && enableFollowCheckInMutedKeyword() => - excludeFollowingForMutedKeywordsRequests.incr() - viewerIdOpt match { - case Some(viewerId) => - userRelationshipSource.follows(viewerId, authorId).map { - case true => - case false => Some(mutedKeywordsExcludeFollowing.map(_.keyword).mkString(",")) - } - case _ => Stitch.None - } - case (_, _) => Stitch.None - } - } - - def tweetContainsMutedKeyword( - tweet: Tweet, - mutedKeywordMap: Stitch[Map[MuteSurface, Seq[GdMutedKeyword]]], - muteSurface: MuteSurface, - viewerIdOpt: Option[Long], - authorId: Long - ): Stitch[VfMutedKeyword] = { - mutedKeywordMap.flatMap { keywordMap => - if (keywordMap.isEmpty) { - Stitch.value(VfMutedKeyword(None)) - } else { - val mutedKeywords = keywordMap.getOrElse(muteSurface, Nil) - val matchTweetFn: KeywordMatcher.MatchTweet = keywordMatcher(mutedKeywords) - val locale = tweet.language.map(l => Locale.forLanguageTag(l.language)) - val text = tweet.coreData.get.text - - matchTweetFn(locale, text).flatMap { results => - mutingKeywordsText(results, muteSurface, viewerIdOpt, authorId).map(VfMutedKeyword) - } - } - } - } - - def tweetContainsMutedKeywordWithoutDefinedSurface( - tweet: Tweet, - mutedKeywordSeq: Stitch[Seq[GdMutedKeyword]], - viewerIdOpt: Option[Long], - authorId: Long - ): Stitch[VfMutedKeyword] = { - mutedKeywordSeq.flatMap { mutedKeyword => - if (mutedKeyword.isEmpty) { - Stitch.value(VfMutedKeyword(None)) - } else { - val matchTweetFn: KeywordMatcher.MatchTweet = keywordMatcher(mutedKeyword) - val locale = tweet.language.map(l => Locale.forLanguageTag(l.language)) - val text = tweet.coreData.get.text - - matchTweetFn(locale, text).flatMap { results => - mutingKeywordsTextWithoutDefinedSurface(results, viewerIdOpt, authorId).map( - VfMutedKeyword - ) - } - } - } - } - def spaceTitleContainsMutedKeyword( - spaceTitle: String, - spaceLanguageOpt: Option[String], - mutedKeywordMap: Stitch[Map[MuteSurface, Seq[GdMutedKeyword]]], - muteSurface: MuteSurface, - ): Stitch[VfMutedKeyword] = { - mutedKeywordMap.flatMap { keywordMap => - if (keywordMap.isEmpty) { - Stitch.value(VfMutedKeyword(None)) - } else { - val mutedKeywords = keywordMap.getOrElse(muteSurface, Nil) - val matchTweetFn: KeywordMatcher.MatchTweet = keywordMatcher(mutedKeywords) - - val locale = spaceLanguageOpt.map(l => Locale.forLanguageTag(l)) - matchTweetFn(locale, spaceTitle).flatMap { results => - if (results.nonEmpty) { - Stitch.value(Some(results.map(_.keyword).mkString(","))).map(VfMutedKeyword) - } else { - Stitch.None.map(VfMutedKeyword) - } - } - } - } - } - -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/dms/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/builder/dms/BUILD deleted file mode 100644 index 3c769bb73..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/dms/BUILD +++ /dev/null @@ -1,23 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "src/thrift/com/twitter/convosvc:convosvc-scala", - "src/thrift/com/twitter/convosvc/internal:internal-scala", - "src/thrift/com/twitter/spam/rtf:safety-level-scala", - "stitch/stitch-core", - "stitch/stitch-core/src/main/scala/com/twitter/stitch", - "visibility/common/src/main/scala/com/twitter/visibility/common", - "visibility/common/src/main/scala/com/twitter/visibility/common/dm_sources", - "visibility/lib/src/main/resources/config", - "visibility/lib/src/main/scala/com/twitter/visibility", - "visibility/lib/src/main/scala/com/twitter/visibility/builder", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/users", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/util", - "visibility/lib/src/main/thrift/com/twitter/visibility/safety_label_store:safety-label-store-scala", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/dms/DmConversationFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/dms/DmConversationFeatures.scala deleted file mode 100644 index ad21e40ad..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/dms/DmConversationFeatures.scala +++ /dev/null @@ -1,196 +0,0 @@ -package com.twitter.visibility.builder.dms - -import com.twitter.convosvc.thriftscala.ConversationQuery -import com.twitter.convosvc.thriftscala.ConversationQueryOptions -import com.twitter.convosvc.thriftscala.ConversationType -import com.twitter.convosvc.thriftscala.TimelineLookupState -import com.twitter.stitch.NotFound -import com.twitter.stitch.Stitch -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.builder.users.AuthorFeatures -import com.twitter.visibility.common.DmConversationId -import com.twitter.visibility.common.UserId -import com.twitter.visibility.common.dm_sources.DmConversationSource -import com.twitter.visibility.features._ - -case class InvalidDmConversationFeatureException(message: String) extends Exception(message) - -class DmConversationFeatures( - dmConversationSource: DmConversationSource, - authorFeatures: AuthorFeatures) { - - def forDmConversationId( - dmConversationId: DmConversationId, - viewerIdOpt: Option[UserId] - ): FeatureMapBuilder => FeatureMapBuilder = - _.withFeature( - DmConversationIsOneToOneConversation, - dmConversationIsOneToOneConversation(dmConversationId, viewerIdOpt)) - .withFeature( - DmConversationHasEmptyTimeline, - dmConversationHasEmptyTimeline(dmConversationId, viewerIdOpt)) - .withFeature( - DmConversationHasValidLastReadableEventId, - dmConversationHasValidLastReadableEventId(dmConversationId, viewerIdOpt)) - .withFeature( - DmConversationInfoExists, - dmConversationInfoExists(dmConversationId, viewerIdOpt)) - .withFeature( - DmConversationTimelineExists, - dmConversationTimelineExists(dmConversationId, viewerIdOpt)) - .withFeature( - AuthorIsSuspended, - dmConversationHasSuspendedParticipant(dmConversationId, viewerIdOpt)) - .withFeature( - AuthorIsDeactivated, - dmConversationHasDeactivatedParticipant(dmConversationId, viewerIdOpt)) - .withFeature( - AuthorIsErased, - dmConversationHasErasedParticipant(dmConversationId, viewerIdOpt)) - .withFeature( - ViewerIsDmConversationParticipant, - viewerIsDmConversationParticipant(dmConversationId, viewerIdOpt)) - - def dmConversationIsOneToOneConversation( - dmConversationId: DmConversationId, - viewerIdOpt: Option[UserId] - ): Stitch[Boolean] = - viewerIdOpt match { - case Some(viewerId) => - dmConversationSource.getConversationType(dmConversationId, viewerId).flatMap { - case Some(ConversationType.OneToOneDm | ConversationType.SecretOneToOneDm) => - Stitch.True - case None => - Stitch.exception(InvalidDmConversationFeatureException("Conversation type not found")) - case _ => Stitch.False - } - case _ => Stitch.exception(InvalidDmConversationFeatureException("Viewer id missing")) - } - - private[dms] def dmConversationHasEmptyTimeline( - dmConversationId: DmConversationId, - viewerIdOpt: Option[UserId] - ): Stitch[Boolean] = - dmConversationSource - .getConversationTimelineEntries( - dmConversationId, - ConversationQuery( - conversationId = Some(dmConversationId), - options = Some( - ConversationQueryOptions( - perspectivalUserId = viewerIdOpt, - hydrateEvents = Some(false), - supportsReactions = Some(true) - ) - ), - maxCount = 10 - ) - ).map(_.forall(entries => entries.isEmpty)) - - private[dms] def dmConversationHasValidLastReadableEventId( - dmConversationId: DmConversationId, - viewerIdOpt: Option[UserId] - ): Stitch[Boolean] = - viewerIdOpt match { - case Some(viewerId) => - dmConversationSource - .getConversationLastReadableEventId(dmConversationId, viewerId).map(_.exists(id => - id > 0L)) - case _ => Stitch.exception(InvalidDmConversationFeatureException("Viewer id missing")) - } - - private[dms] def dmConversationInfoExists( - dmConversationId: DmConversationId, - viewerIdOpt: Option[UserId] - ): Stitch[Boolean] = - viewerIdOpt match { - case Some(viewerId) => - dmConversationSource - .getDmConversationInfo(dmConversationId, viewerId).map(_.isDefined) - case _ => Stitch.exception(InvalidDmConversationFeatureException("Viewer id missing")) - } - - private[dms] def dmConversationTimelineExists( - dmConversationId: DmConversationId, - viewerIdOpt: Option[UserId] - ): Stitch[Boolean] = - dmConversationSource - .getConversationTimelineState( - dmConversationId, - ConversationQuery( - conversationId = Some(dmConversationId), - options = Some( - ConversationQueryOptions( - perspectivalUserId = viewerIdOpt, - hydrateEvents = Some(false), - supportsReactions = Some(true) - ) - ), - maxCount = 1 - ) - ).map { - case Some(TimelineLookupState.NotFound) | None => false - case _ => true - } - - private[dms] def anyConversationParticipantMatchesCondition( - condition: UserId => Stitch[Boolean], - dmConversationId: DmConversationId, - viewerIdOpt: Option[UserId] - ): Stitch[Boolean] = - viewerIdOpt match { - case Some(viewerId) => - dmConversationSource - .getConversationParticipantIds(dmConversationId, viewerId).flatMap { - case Some(participants) => - Stitch - .collect(participants.map(condition)).map(_.contains(true)).rescue { - case NotFound => - Stitch.exception(InvalidDmConversationFeatureException("User not found")) - } - case _ => Stitch.False - } - case _ => Stitch.exception(InvalidDmConversationFeatureException("Viewer id missing")) - } - - def dmConversationHasSuspendedParticipant( - dmConversationId: DmConversationId, - viewerIdOpt: Option[UserId] - ): Stitch[Boolean] = - anyConversationParticipantMatchesCondition( - participant => authorFeatures.authorIsSuspended(participant), - dmConversationId, - viewerIdOpt) - - def dmConversationHasDeactivatedParticipant( - dmConversationId: DmConversationId, - viewerIdOpt: Option[UserId] - ): Stitch[Boolean] = - anyConversationParticipantMatchesCondition( - participant => authorFeatures.authorIsDeactivated(participant), - dmConversationId, - viewerIdOpt) - - def dmConversationHasErasedParticipant( - dmConversationId: DmConversationId, - viewerIdOpt: Option[UserId] - ): Stitch[Boolean] = - anyConversationParticipantMatchesCondition( - participant => authorFeatures.authorIsErased(participant), - dmConversationId, - viewerIdOpt) - - def viewerIsDmConversationParticipant( - dmConversationId: DmConversationId, - viewerIdOpt: Option[UserId] - ): Stitch[Boolean] = - viewerIdOpt match { - case Some(viewerId) => - dmConversationSource - .getConversationParticipantIds(dmConversationId, viewerId).map { - case Some(participants) => participants.contains(viewerId) - case _ => false - } - case _ => Stitch.exception(InvalidDmConversationFeatureException("Viewer id missing")) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/dms/DmEventFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/dms/DmEventFeatures.scala deleted file mode 100644 index 797a52268..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/dms/DmEventFeatures.scala +++ /dev/null @@ -1,341 +0,0 @@ -package com.twitter.visibility.builder.dms - -import com.twitter.convosvc.thriftscala.Event -import com.twitter.convosvc.thriftscala.StoredDelete -import com.twitter.convosvc.thriftscala.StoredPerspectivalMessageInfo -import com.twitter.convosvc.thriftscala.PerspectivalSpamState -import com.twitter.stitch.Stitch -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.builder.users.AuthorFeatures -import com.twitter.visibility.common.DmEventId -import com.twitter.visibility.common.dm_sources.DmEventSource -import com.twitter.visibility.common.UserId -import com.twitter.convosvc.thriftscala.EventType -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.stitch.NotFound -import com.twitter.visibility.common.dm_sources.DmConversationSource -import com.twitter.visibility.features._ - -case class InvalidDmEventFeatureException(message: String) extends Exception(message) - -class DmEventFeatures( - dmEventSource: DmEventSource, - dmConversationSource: DmConversationSource, - authorFeatures: AuthorFeatures, - dmConversationFeatures: DmConversationFeatures, - statsReceiver: StatsReceiver) { - private[this] val scopedStatsReceiver = statsReceiver.scope("dm_event_features") - private[this] val requests = scopedStatsReceiver.counter("requests") - - def forDmEventId( - dmEventId: DmEventId, - viewerId: UserId - ): FeatureMapBuilder => FeatureMapBuilder = { - requests.incr() - - val dmEventStitchRef: Stitch[Option[Event]] = - Stitch.ref(dmEventSource.getDmEvent(dmEventId, viewerId)) - - _.withFeature( - DmEventIsMessageCreateEvent, - isDmEventType(dmEventStitchRef, EventType.MessageCreate)) - .withFeature( - AuthorIsSuspended, - messageCreateEventHasInactiveInitiatingUser( - dmEventStitchRef, - initiatingUser => authorFeatures.authorIsSuspended(initiatingUser)) - ) - .withFeature( - AuthorIsDeactivated, - messageCreateEventHasInactiveInitiatingUser( - dmEventStitchRef, - initiatingUser => authorFeatures.authorIsDeactivated(initiatingUser)) - ) - .withFeature( - AuthorIsErased, - messageCreateEventHasInactiveInitiatingUser( - dmEventStitchRef, - initiatingUser => authorFeatures.authorIsErased(initiatingUser)) - ) - .withFeature( - DmEventOccurredBeforeLastClearedEvent, - dmEventOccurredBeforeLastClearedEvent(dmEventStitchRef, dmEventId, viewerId) - ) - .withFeature( - DmEventOccurredBeforeJoinConversationEvent, - dmEventOccurredBeforeJoinConversationEvent(dmEventStitchRef, dmEventId, viewerId) - ) - .withFeature( - ViewerIsDmConversationParticipant, - dmEventViewerIsDmConversationParticipant(dmEventStitchRef, viewerId) - ) - .withFeature( - DmEventIsDeleted, - dmEventIsDeleted(dmEventStitchRef, dmEventId) - ) - .withFeature( - DmEventIsHidden, - dmEventIsHidden(dmEventStitchRef, dmEventId) - ) - .withFeature( - ViewerIsDmEventInitiatingUser, - viewerIsDmEventInitiatingUser(dmEventStitchRef, viewerId) - ) - .withFeature( - DmEventInOneToOneConversationWithUnavailableUser, - dmEventInOneToOneConversationWithUnavailableUser(dmEventStitchRef, viewerId) - ) - .withFeature( - DmEventIsLastMessageReadUpdateEvent, - isDmEventType(dmEventStitchRef, EventType.LastMessageReadUpdate) - ) - .withFeature( - DmEventIsJoinConversationEvent, - isDmEventType(dmEventStitchRef, EventType.JoinConversation) - ) - .withFeature( - DmEventIsWelcomeMessageCreateEvent, - isDmEventType(dmEventStitchRef, EventType.WelcomeMessageCreate) - ) - .withFeature( - DmEventIsTrustConversationEvent, - isDmEventType(dmEventStitchRef, EventType.TrustConversation) - ) - .withFeature( - DmEventIsCsFeedbackSubmitted, - isDmEventType(dmEventStitchRef, EventType.CsFeedbackSubmitted) - ) - .withFeature( - DmEventIsCsFeedbackDismissed, - isDmEventType(dmEventStitchRef, EventType.CsFeedbackDismissed) - ) - .withFeature( - DmEventIsConversationCreateEvent, - isDmEventType(dmEventStitchRef, EventType.ConversationCreate) - ) - .withFeature( - DmEventInOneToOneConversation, - dmEventInOneToOneConversation(dmEventStitchRef, viewerId) - ) - .withFeature( - DmEventIsPerspectivalJoinConversationEvent, - dmEventIsPerspectivalJoinConversationEvent(dmEventStitchRef, dmEventId, viewerId)) - - } - - private def isDmEventType( - dmEventOptStitch: Stitch[Option[Event]], - eventType: EventType - ): Stitch[Boolean] = - dmEventSource.getEventType(dmEventOptStitch).flatMap { - case Some(_: eventType.type) => - Stitch.True - case None => - Stitch.exception(InvalidDmEventFeatureException(s"$eventType event type not found")) - case _ => - Stitch.False - } - - private def dmEventIsPerspectivalJoinConversationEvent( - dmEventOptStitch: Stitch[Option[Event]], - dmEventId: DmEventId, - viewerId: UserId - ): Stitch[Boolean] = - Stitch - .join( - dmEventSource.getEventType(dmEventOptStitch), - dmEventSource.getConversationId(dmEventOptStitch)).flatMap { - case (Some(EventType.JoinConversation), conversationIdOpt) => - conversationIdOpt match { - case Some(conversationId) => - dmConversationSource - .getParticipantJoinConversationEventId(conversationId, viewerId, viewerId) - .flatMap { - case Some(joinConversationEventId) => - Stitch.value(joinConversationEventId == dmEventId) - case _ => Stitch.False - } - case _ => - Stitch.exception(InvalidDmEventFeatureException("Conversation id not found")) - } - case (None, _) => - Stitch.exception(InvalidDmEventFeatureException("Event type not found")) - case _ => Stitch.False - } - - private def messageCreateEventHasInactiveInitiatingUser( - dmEventOptStitch: Stitch[Option[Event]], - condition: UserId => Stitch[Boolean], - ): Stitch[Boolean] = - Stitch - .join( - dmEventSource.getEventType(dmEventOptStitch), - dmEventSource.getInitiatingUserId(dmEventOptStitch)).flatMap { - case (Some(EventType.MessageCreate), Some(userId)) => - condition(userId).rescue { - case NotFound => - Stitch.exception(InvalidDmEventFeatureException("initiating user not found")) - } - case (None, _) => - Stitch.exception(InvalidDmEventFeatureException("DmEvent type is missing")) - case (Some(EventType.MessageCreate), _) => - Stitch.exception(InvalidDmEventFeatureException("initiating user id is missing")) - case _ => Stitch.False - } - - private def dmEventOccurredBeforeLastClearedEvent( - dmEventOptStitch: Stitch[Option[Event]], - dmEventId: DmEventId, - viewerId: UserId - ): Stitch[Boolean] = { - dmEventSource.getConversationId(dmEventOptStitch).flatMap { - case Some(convoId) => - val lastClearedEventIdStitch = - dmConversationSource.getParticipantLastClearedEventId(convoId, viewerId, viewerId) - lastClearedEventIdStitch.flatMap { - case Some(lastClearedEventId) => Stitch(dmEventId <= lastClearedEventId) - case _ => - Stitch.False - } - case _ => Stitch.False - } - } - - private def dmEventOccurredBeforeJoinConversationEvent( - dmEventOptStitch: Stitch[Option[Event]], - dmEventId: DmEventId, - viewerId: UserId - ): Stitch[Boolean] = { - dmEventSource.getConversationId(dmEventOptStitch).flatMap { - case Some(convoId) => - val joinConversationEventIdStitch = - dmConversationSource - .getParticipantJoinConversationEventId(convoId, viewerId, viewerId) - joinConversationEventIdStitch.flatMap { - case Some(joinConversationEventId) => Stitch(dmEventId < joinConversationEventId) - case _ => Stitch.False - } - case _ => Stitch.False - } - } - - private def dmEventViewerIsDmConversationParticipant( - dmEventOptStitch: Stitch[Option[Event]], - viewerId: UserId - ): Stitch[Boolean] = { - dmEventSource.getConversationId(dmEventOptStitch).flatMap { - case Some(convoId) => - dmConversationFeatures.viewerIsDmConversationParticipant(convoId, Some(viewerId)) - case _ => Stitch.True - } - } - - private def dmEventIsDeleted( - dmEventOptStitch: Stitch[Option[Event]], - dmEventId: DmEventId - ): Stitch[Boolean] = - dmEventSource.getConversationId(dmEventOptStitch).flatMap { - case Some(convoId) => - dmConversationSource - .getDeleteInfo(convoId, dmEventId).rescue { - case e: java.lang.IllegalArgumentException => - Stitch.exception(InvalidDmEventFeatureException("Invalid conversation id")) - }.flatMap { - case Some(StoredDelete(None)) => Stitch.True - case _ => Stitch.False - } - case _ => Stitch.False - } - - private def dmEventIsHidden( - dmEventOptStitch: Stitch[Option[Event]], - dmEventId: DmEventId - ): Stitch[Boolean] = - dmEventSource.getConversationId(dmEventOptStitch).flatMap { - case Some(convoId) => - dmConversationSource - .getPerspectivalMessageInfo(convoId, dmEventId).rescue { - case e: java.lang.IllegalArgumentException => - Stitch.exception(InvalidDmEventFeatureException("Invalid conversation id")) - }.flatMap { - case Some(StoredPerspectivalMessageInfo(Some(hidden), _)) if hidden => - Stitch.True - case Some(StoredPerspectivalMessageInfo(_, Some(spamState))) - if spamState == PerspectivalSpamState.Spam => - Stitch.True - case _ => Stitch.False - } - case _ => Stitch.False - } - - private def viewerIsDmEventInitiatingUser( - dmEventOptStitch: Stitch[Option[Event]], - viewerId: UserId - ): Stitch[Boolean] = - Stitch - .join( - dmEventSource.getEventType(dmEventOptStitch), - dmEventSource.getInitiatingUserId(dmEventOptStitch)).flatMap { - case ( - Some( - EventType.TrustConversation | EventType.CsFeedbackSubmitted | - EventType.CsFeedbackDismissed | EventType.WelcomeMessageCreate | - EventType.JoinConversation), - Some(userId)) => - Stitch(viewerId == userId) - case ( - Some( - EventType.TrustConversation | EventType.CsFeedbackSubmitted | - EventType.CsFeedbackDismissed | EventType.WelcomeMessageCreate | - EventType.JoinConversation), - None) => - Stitch.exception(InvalidDmEventFeatureException("Initiating user id is missing")) - case (None, _) => - Stitch.exception(InvalidDmEventFeatureException("DmEvent type is missing")) - case _ => Stitch.True - } - - private def dmEventInOneToOneConversationWithUnavailableUser( - dmEventOptStitch: Stitch[Option[Event]], - viewerId: UserId - ): Stitch[Boolean] = - dmEventSource.getConversationId(dmEventOptStitch).flatMap { - case Some(conversationId) => - dmConversationFeatures - .dmConversationIsOneToOneConversation(conversationId, Some(viewerId)).flatMap { - isOneToOne => - if (isOneToOne) { - Stitch - .join( - dmConversationFeatures - .dmConversationHasSuspendedParticipant(conversationId, Some(viewerId)), - dmConversationFeatures - .dmConversationHasDeactivatedParticipant(conversationId, Some(viewerId)), - dmConversationFeatures - .dmConversationHasErasedParticipant(conversationId, Some(viewerId)) - ).flatMap { - case ( - convoParticipantIsSuspended, - convoParticipantIsDeactivated, - convoParticipantIsErased) => - Stitch.value( - convoParticipantIsSuspended || convoParticipantIsDeactivated || convoParticipantIsErased) - } - } else { - Stitch.False - } - } - case _ => Stitch.False - } - - private def dmEventInOneToOneConversation( - dmEventOptStitch: Stitch[Option[Event]], - viewerId: UserId - ): Stitch[Boolean] = - dmEventSource.getConversationId(dmEventOptStitch).flatMap { - case Some(conversationId) => - dmConversationFeatures - .dmConversationIsOneToOneConversation(conversationId, Some(viewerId)) - case _ => Stitch.False - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/media/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/builder/media/BUILD deleted file mode 100644 index d74c9c5d0..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/media/BUILD +++ /dev/null @@ -1,31 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/google/guava", - "mediaservices/commons/src/main/thrift:thrift-scala", - "mediaservices/media-util/src/main/scala", - "snowflake/src/main/scala/com/twitter/snowflake/id", - "src/thrift/com/twitter/context:twitter-context-scala", - "src/thrift/com/twitter/gizmoduck:user-thrift-scala", - "src/thrift/com/twitter/spam/rtf:safety-level-scala", - "src/thrift/com/twitter/spam/rtf:tweet-rtf-event-scala", - "src/thrift/com/twitter/tweetypie:service-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "stitch/stitch-core", - "tweetypie/src/scala/com/twitter/tweetypie/additionalfields", - "twitter-context/src/main/scala", - "visibility/common/src/main/scala/com/twitter/visibility/common", - "visibility/lib/src/main/resources/config", - "visibility/lib/src/main/scala/com/twitter/visibility", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/tweets", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/users", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/interfaces/common/tweets", - "visibility/lib/src/main/scala/com/twitter/visibility/util", - "visibility/lib/src/main/thrift/com/twitter/visibility/safety_label_store:safety-label-store-scala", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/media/MediaFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/media/MediaFeatures.scala deleted file mode 100644 index e20429846..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/media/MediaFeatures.scala +++ /dev/null @@ -1,90 +0,0 @@ -package com.twitter.visibility.builder.media - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.mediaservices.media_util.GenericMediaKey -import com.twitter.stitch.Stitch -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.common.MediaSafetyLabelMapSource -import com.twitter.visibility.features.MediaSafetyLabels -import com.twitter.visibility.models.MediaSafetyLabel -import com.twitter.visibility.models.MediaSafetyLabelType -import com.twitter.visibility.models.SafetyLabel - -class MediaFeatures( - mediaSafetyLabelMap: StratoMediaLabelMaps, - statsReceiver: StatsReceiver) { - - private[this] val scopedStatsReceiver = statsReceiver.scope("media_features") - - private[this] val requests = - scopedStatsReceiver - .counter("requests") - - private[this] val mediaSafetyLabelsStats = - scopedStatsReceiver - .scope(MediaSafetyLabels.name) - .counter("requests") - - private[this] val nonEmptyMediaStats = scopedStatsReceiver.scope("non_empty_media") - private[this] val nonEmptyMediaRequests = nonEmptyMediaStats.counter("requests") - private[this] val nonEmptyMediaKeysCount = nonEmptyMediaStats.counter("keys") - private[this] val nonEmptyMediaKeysLength = nonEmptyMediaStats.stat("keys_length") - - def forMediaKeys( - mediaKeys: Seq[GenericMediaKey], - ): FeatureMapBuilder => FeatureMapBuilder = { - requests.incr() - nonEmptyMediaKeysCount.incr(mediaKeys.size) - mediaSafetyLabelsStats.incr() - - if (mediaKeys.nonEmpty) { - nonEmptyMediaRequests.incr() - nonEmptyMediaKeysLength.add(mediaKeys.size) - } - - _.withFeature(MediaSafetyLabels, mediaSafetyLabelMap.forGenericMediaKeys(mediaKeys)) - } - - def forGenericMediaKey( - genericMediaKey: GenericMediaKey - ): FeatureMapBuilder => FeatureMapBuilder = { - requests.incr() - nonEmptyMediaKeysCount.incr() - mediaSafetyLabelsStats.incr() - nonEmptyMediaRequests.incr() - nonEmptyMediaKeysLength.add(1L) - - _.withFeature(MediaSafetyLabels, mediaSafetyLabelMap.forGenericMediaKey(genericMediaKey)) - } -} - -class StratoMediaLabelMaps(source: MediaSafetyLabelMapSource) { - - def forGenericMediaKeys( - mediaKeys: Seq[GenericMediaKey], - ): Stitch[Seq[MediaSafetyLabel]] = { - Stitch - .collect( - mediaKeys - .map(getFilteredSafetyLabels) - ).map(_.flatten) - } - - def forGenericMediaKey( - genericMediaKey: GenericMediaKey - ): Stitch[Seq[MediaSafetyLabel]] = { - getFilteredSafetyLabels(genericMediaKey) - } - - private def getFilteredSafetyLabels( - genericMediaKey: GenericMediaKey, - ): Stitch[Seq[MediaSafetyLabel]] = - source - .fetch(genericMediaKey).map(_.flatMap(_.labels.map { stratoSafetyLabelMap => - stratoSafetyLabelMap - .map(label => - MediaSafetyLabel( - MediaSafetyLabelType.fromThrift(label._1), - SafetyLabel.fromThrift(label._2))) - }).toSeq.flatten) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/media/MediaMetadataFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/media/MediaMetadataFeatures.scala deleted file mode 100644 index 97f35b27c..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/media/MediaMetadataFeatures.scala +++ /dev/null @@ -1,79 +0,0 @@ -package com.twitter.visibility.builder.media - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.mediaservices.media_util.GenericMediaKey -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.common.MediaMetadataSource -import com.twitter.visibility.features.HasDmcaMediaFeature -import com.twitter.visibility.features.MediaGeoRestrictionsAllowList -import com.twitter.visibility.features.MediaGeoRestrictionsDenyList -import com.twitter.visibility.features.AuthorId - -class MediaMetadataFeatures( - mediaMetadataSource: MediaMetadataSource, - statsReceiver: StatsReceiver) { - - private[this] val scopedStatsReceiver = statsReceiver.scope("media_metadata_features") - private[this] val requests = scopedStatsReceiver.counter("requests") - - private[this] val hasDmcaMedia = - scopedStatsReceiver.scope(HasDmcaMediaFeature.name).counter("requests") - private[this] val mediaGeoAllowList = - scopedStatsReceiver.scope(MediaGeoRestrictionsAllowList.name).counter("requests") - private[this] val mediaGeoDenyList = - scopedStatsReceiver.scope(MediaGeoRestrictionsDenyList.name).counter("requests") - private[this] val uploaderId = - scopedStatsReceiver.scope(AuthorId.name).counter("requests") - - def forGenericMediaKey( - genericMediaKey: GenericMediaKey - ): FeatureMapBuilder => FeatureMapBuilder = { featureMapBuilder => - requests.incr() - - featureMapBuilder.withFeature( - HasDmcaMediaFeature, - mediaIsDmca(genericMediaKey) - ) - - featureMapBuilder.withFeature( - MediaGeoRestrictionsAllowList, - geoRestrictionsAllowList(genericMediaKey) - ) - - featureMapBuilder.withFeature( - MediaGeoRestrictionsDenyList, - geoRestrictionsDenyList(genericMediaKey) - ) - - featureMapBuilder.withFeature( - AuthorId, - mediaUploaderId(genericMediaKey) - ) - } - - private def mediaIsDmca(genericMediaKey: GenericMediaKey) = { - hasDmcaMedia.incr() - mediaMetadataSource.getMediaIsDmca(genericMediaKey) - } - - private def geoRestrictionsAllowList(genericMediaKey: GenericMediaKey) = { - mediaGeoAllowList.incr() - mediaMetadataSource.getGeoRestrictionsAllowList(genericMediaKey).map { allowListOpt => - allowListOpt.getOrElse(Nil) - } - } - - private def geoRestrictionsDenyList(genericMediaKey: GenericMediaKey) = { - mediaGeoDenyList.incr() - mediaMetadataSource.getGeoRestrictionsDenyList(genericMediaKey).map { denyListOpt => - denyListOpt.getOrElse(Nil) - } - } - - private def mediaUploaderId(genericMediaKey: GenericMediaKey) = { - uploaderId.incr() - mediaMetadataSource.getMediaUploaderId(genericMediaKey).map { uploaderIdOpt => - uploaderIdOpt.map(Set(_)).getOrElse(Set.empty) - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/spaces/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/builder/spaces/BUILD deleted file mode 100644 index ec82612ef..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/spaces/BUILD +++ /dev/null @@ -1,25 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/google/guava", - "snowflake/src/main/scala/com/twitter/snowflake/id", - "src/thrift/com/twitter/context:twitter-context-scala", - "src/thrift/com/twitter/gizmoduck:user-thrift-scala", - "src/thrift/com/twitter/spam/rtf:safety-level-scala", - "src/thrift/com/twitter/spam/rtf:tweet-rtf-event-scala", - "stitch/stitch-core", - "twitter-context/src/main/scala", - "visibility/common/src/main/scala/com/twitter/visibility/common", - "visibility/lib/src/main/resources/config", - "visibility/lib/src/main/scala/com/twitter/visibility", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/common", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/users", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/util", - "visibility/lib/src/main/thrift/com/twitter/visibility/safety_label_store:safety-label-store-scala", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/spaces/SpaceFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/spaces/SpaceFeatures.scala deleted file mode 100644 index 6522f8e65..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/spaces/SpaceFeatures.scala +++ /dev/null @@ -1,131 +0,0 @@ -package com.twitter.visibility.builder.spaces - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.gizmoduck.thriftscala.Label -import com.twitter.gizmoduck.thriftscala.MuteSurface -import com.twitter.stitch.Stitch -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.builder.common.MutedKeywordFeatures -import com.twitter.visibility.builder.users.AuthorFeatures -import com.twitter.visibility.builder.users.RelationshipFeatures -import com.twitter.visibility.common.AudioSpaceSource -import com.twitter.visibility.common.SpaceId -import com.twitter.visibility.common.SpaceSafetyLabelMapSource -import com.twitter.visibility.common.UserId -import com.twitter.visibility.features._ -import com.twitter.visibility.models.{MutedKeyword => VfMutedKeyword} -import com.twitter.visibility.models.SafetyLabel -import com.twitter.visibility.models.SpaceSafetyLabel -import com.twitter.visibility.models.SpaceSafetyLabelType - -class SpaceFeatures( - spaceSafetyLabelMap: StratoSpaceLabelMaps, - authorFeatures: AuthorFeatures, - relationshipFeatures: RelationshipFeatures, - mutedKeywordFeatures: MutedKeywordFeatures, - audioSpaceSource: AudioSpaceSource) { - - def forSpaceAndAuthorIds( - spaceId: SpaceId, - viewerId: Option[UserId], - authorIds: Option[Seq[UserId]] - ): FeatureMapBuilder => FeatureMapBuilder = { - - _.withFeature(SpaceSafetyLabels, spaceSafetyLabelMap.forSpaceId(spaceId)) - .withFeature(AuthorId, getSpaceAuthors(spaceId, authorIds).map(_.toSet)) - .withFeature(AuthorUserLabels, allSpaceAuthorLabels(spaceId, authorIds)) - .withFeature(ViewerFollowsAuthor, viewerFollowsAnySpaceAuthor(spaceId, authorIds, viewerId)) - .withFeature(ViewerMutesAuthor, viewerMutesAnySpaceAuthor(spaceId, authorIds, viewerId)) - .withFeature(ViewerBlocksAuthor, viewerBlocksAnySpaceAuthor(spaceId, authorIds, viewerId)) - .withFeature(AuthorBlocksViewer, anySpaceAuthorBlocksViewer(spaceId, authorIds, viewerId)) - .withFeature( - ViewerMutesKeywordInSpaceTitleForNotifications, - titleContainsMutedKeyword( - audioSpaceSource.getSpaceTitle(spaceId), - audioSpaceSource.getSpaceLanguage(spaceId), - viewerId) - ) - } - - def titleContainsMutedKeyword( - titleOptStitch: Stitch[Option[String]], - languageOptStitch: Stitch[Option[String]], - viewerId: Option[UserId], - ): Stitch[VfMutedKeyword] = { - titleOptStitch.flatMap { - case None => Stitch.value(VfMutedKeyword(None)) - case Some(spaceTitle) => - languageOptStitch.flatMap { languageOpt => - mutedKeywordFeatures.spaceTitleContainsMutedKeyword( - spaceTitle, - languageOpt, - mutedKeywordFeatures.allMutedKeywords(viewerId), - MuteSurface.Notifications) - } - } - } - - def getSpaceAuthors( - spaceId: SpaceId, - authorIdsFromRequest: Option[Seq[UserId]] - ): Stitch[Seq[UserId]] = { - authorIdsFromRequest match { - case Some(authorIds) => Stitch.apply(authorIds) - case _ => audioSpaceSource.getAdminIds(spaceId) - } - } - - def allSpaceAuthorLabels( - spaceId: SpaceId, - authorIdsFromRequest: Option[Seq[UserId]] - ): Stitch[Seq[Label]] = { - getSpaceAuthors(spaceId, authorIdsFromRequest) - .flatMap(authorIds => - Stitch.collect(authorIds.map(authorId => authorFeatures.authorUserLabels(authorId)))).map( - _.flatten) - } - - def viewerMutesAnySpaceAuthor( - spaceId: SpaceId, - authorIdsFromRequest: Option[Seq[UserId]], - viewerId: Option[UserId] - ): Stitch[Boolean] = { - getSpaceAuthors(spaceId, authorIdsFromRequest) - .flatMap(authorIds => - Stitch.collect(authorIds.map(authorId => - relationshipFeatures.viewerMutesAuthor(authorId, viewerId)))).map(_.contains(true)) - } - - def anySpaceAuthorBlocksViewer( - spaceId: SpaceId, - authorIdsFromRequest: Option[Seq[UserId]], - viewerId: Option[UserId] - ): Stitch[Boolean] = { - getSpaceAuthors(spaceId, authorIdsFromRequest) - .flatMap(authorIds => - Stitch.collect(authorIds.map(authorId => - relationshipFeatures.authorBlocksViewer(authorId, viewerId)))).map(_.contains(true)) - } -} - -class StratoSpaceLabelMaps( - spaceSafetyLabelSource: SpaceSafetyLabelMapSource, - statsReceiver: StatsReceiver) { - - private[this] val scopedStatsReceiver = statsReceiver.scope("space_features") - private[this] val spaceSafetyLabelsStats = - scopedStatsReceiver.scope(SpaceSafetyLabels.name).counter("requests") - - def forSpaceId( - spaceId: SpaceId, - ): Stitch[Seq[SpaceSafetyLabel]] = { - spaceSafetyLabelSource - .fetch(spaceId).map(_.flatMap(_.labels.map { stratoSafetyLabelMap => - stratoSafetyLabelMap - .map(label => - SpaceSafetyLabel( - SpaceSafetyLabelType.fromThrift(label._1), - SafetyLabel.fromThrift(label._2))) - }).toSeq.flatten).ensure(spaceSafetyLabelsStats.incr) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/BUILD deleted file mode 100644 index bde1871b4..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/BUILD +++ /dev/null @@ -1,38 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/google/guava", - "communities/thrift/src/main/thrift/com/twitter/communities:thrift-scala", - "communities/thrift/src/main/thrift/com/twitter/communities/moderation:thrift-scala", - "communities/thrift/src/main/thrift/com/twitter/communities/visibility:thrift-scala", - "escherbird/src/thrift/com/twitter/escherbird/softintervention:softintervention_thrift-scala", - "mediaservices/media-util/src/main/scala", - "notificationservice/common/src/main/scala/com/twitter/notificationservice/model:alias", - "notificationservice/common/src/main/scala/com/twitter/notificationservice/model/notification", - "snowflake/src/main/scala/com/twitter/snowflake/id", - "src/thrift/com/twitter/context:twitter-context-scala", - "src/thrift/com/twitter/escherbird/common:common-scala", - "src/thrift/com/twitter/gizmoduck:user-thrift-scala", - "src/thrift/com/twitter/search/common:constants-scala", - "src/thrift/com/twitter/spam/rtf:safety-level-scala", - "src/thrift/com/twitter/spam/rtf:tweet-rtf-event-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "stitch/stitch-core", - # "tweetypie/src/scala/com/twitter/tweetypie/additionalfields", - "twitter-context/src/main/scala", - "visibility/common/src/main/scala/com/twitter/visibility/common", - "visibility/common/src/main/scala/com/twitter/visibility/common/stitch", - "visibility/lib/src/main/resources/config", - "visibility/lib/src/main/scala/com/twitter/visibility", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/users", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/interfaces/common/blender", - "visibility/lib/src/main/scala/com/twitter/visibility/interfaces/common/search", - "visibility/lib/src/main/scala/com/twitter/visibility/interfaces/common/tweets", - "visibility/lib/src/main/thrift/com/twitter/visibility/strato:vf-strato-scala", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/BlenderContextFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/BlenderContextFeatures.scala deleted file mode 100644 index 931574567..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/BlenderContextFeatures.scala +++ /dev/null @@ -1,45 +0,0 @@ -package com.twitter.visibility.builder.tweets - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.search.common.constants.thriftscala.ThriftQuerySource -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.features.SearchCandidateCount -import com.twitter.visibility.features.SearchQueryHasUser -import com.twitter.visibility.features.SearchQuerySource -import com.twitter.visibility.features.SearchResultsPageNumber -import com.twitter.visibility.interfaces.common.blender.BlenderVFRequestContext - -@Deprecated -class BlenderContextFeatures( - statsReceiver: StatsReceiver) { - private[this] val scopedStatsReceiver = statsReceiver.scope("blender_context_features") - private[this] val requests = scopedStatsReceiver.counter("requests") - private[this] val searchResultsPageNumber = - scopedStatsReceiver.scope(SearchResultsPageNumber.name).counter("requests") - private[this] val searchCandidateCount = - scopedStatsReceiver.scope(SearchCandidateCount.name).counter("requests") - private[this] val searchQuerySource = - scopedStatsReceiver.scope(SearchQuerySource.name).counter("requests") - private[this] val searchQueryHasUser = - scopedStatsReceiver.scope(SearchQueryHasUser.name).counter("requests") - - def forBlenderContext( - blenderContext: BlenderVFRequestContext - ): FeatureMapBuilder => FeatureMapBuilder = { - requests.incr() - searchResultsPageNumber.incr() - searchCandidateCount.incr() - searchQuerySource.incr() - searchQueryHasUser.incr() - - _.withConstantFeature(SearchResultsPageNumber, blenderContext.resultsPageNumber) - .withConstantFeature(SearchCandidateCount, blenderContext.candidateCount) - .withConstantFeature( - SearchQuerySource, - blenderContext.querySourceOption match { - case Some(querySource) => querySource - case _ => ThriftQuerySource.Unknown - }) - .withConstantFeature(SearchQueryHasUser, blenderContext.queryHasUser) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/CommunityNotificationFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/CommunityNotificationFeatures.scala deleted file mode 100644 index a4588620b..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/CommunityNotificationFeatures.scala +++ /dev/null @@ -1,64 +0,0 @@ -package com.twitter.visibility.builder.tweets - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.notificationservice.model.notification.ActivityNotification -import com.twitter.notificationservice.model.notification.MentionNotification -import com.twitter.notificationservice.model.notification.MentionQuoteNotification -import com.twitter.notificationservice.model.notification.Notification -import com.twitter.notificationservice.model.notification.QuoteTweetNotification -import com.twitter.servo.util.Gate -import com.twitter.stitch.Stitch -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.common.TweetSource -import com.twitter.visibility.features.NotificationIsOnCommunityTweet -import com.twitter.visibility.models.CommunityTweet - -object CommunityNotificationFeatures { - def ForNonCommunityTweetNotification: FeatureMapBuilder => FeatureMapBuilder = { - _.withConstantFeature(NotificationIsOnCommunityTweet, false) - } -} - -class CommunityNotificationFeatures( - tweetSource: TweetSource, - enableCommunityTweetHydration: Gate[Long], - statsReceiver: StatsReceiver) { - - private[this] val scopedStatsReceiver = statsReceiver.scope("community_notification_features") - private[this] val requestsCounter = scopedStatsReceiver.counter("requests") - private[this] val hydrationsCounter = scopedStatsReceiver.counter("hydrations") - private[this] val notificationIsOnCommunityTweetCounter = - scopedStatsReceiver.scope(NotificationIsOnCommunityTweet.name).counter("true") - private[this] val notificationIsNotOnCommunityTweetCounter = - scopedStatsReceiver.scope(NotificationIsOnCommunityTweet.name).counter("false") - - def forNotification(notification: Notification): FeatureMapBuilder => FeatureMapBuilder = { - requestsCounter.incr() - val isCommunityTweetResult = getTweetIdOption(notification) match { - case Some(tweetId) if enableCommunityTweetHydration(notification.target) => - hydrationsCounter.incr() - tweetSource - .getTweet(tweetId) - .map { - case Some(tweet) if CommunityTweet(tweet).nonEmpty => - notificationIsOnCommunityTweetCounter.incr() - true - case _ => - notificationIsNotOnCommunityTweetCounter.incr() - false - } - case _ => Stitch.False - } - _.withFeature(NotificationIsOnCommunityTweet, isCommunityTweetResult) - } - - private[this] def getTweetIdOption(notification: Notification): Option[Long] = { - notification match { - case n: MentionNotification => Some(n.mentioningTweetId) - case n: MentionQuoteNotification => Some(n.mentioningTweetId) - case n: QuoteTweetNotification => Some(n.quotedTweetId) - case n: ActivityNotification[_] if n.visibilityTweets.contains(n.objectId) => Some(n.objectId) - case _ => None - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/CommunityTweetFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/CommunityTweetFeatures.scala deleted file mode 100644 index 8a2c752f6..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/CommunityTweetFeatures.scala +++ /dev/null @@ -1,70 +0,0 @@ -package com.twitter.visibility.builder.tweets - -import com.twitter.tweetypie.thriftscala.Tweet -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.features.CommunityTweetAuthorIsRemoved -import com.twitter.visibility.features.CommunityTweetCommunityNotFound -import com.twitter.visibility.features.CommunityTweetCommunityDeleted -import com.twitter.visibility.features.CommunityTweetCommunitySuspended -import com.twitter.visibility.features.CommunityTweetCommunityVisible -import com.twitter.visibility.features.CommunityTweetIsHidden -import com.twitter.visibility.features.TweetIsCommunityTweet -import com.twitter.visibility.features.ViewerIsCommunityAdmin -import com.twitter.visibility.features.ViewerIsCommunityMember -import com.twitter.visibility.features.ViewerIsCommunityModerator -import com.twitter.visibility.features.ViewerIsInternalCommunitiesAdmin -import com.twitter.visibility.models.CommunityTweet -import com.twitter.visibility.models.ViewerContext - -trait CommunityTweetFeatures { - - def forTweet( - tweet: Tweet, - viewerContext: ViewerContext - ): FeatureMapBuilder => FeatureMapBuilder - - def forTweetOnly(tweet: Tweet): FeatureMapBuilder => FeatureMapBuilder = { - _.withConstantFeature( - TweetIsCommunityTweet, - CommunityTweet(tweet).isDefined - ) - } - - protected def forNonCommunityTweet(): FeatureMapBuilder => FeatureMapBuilder = { builder => - builder - .withConstantFeature( - TweetIsCommunityTweet, - false - ).withConstantFeature( - CommunityTweetCommunityNotFound, - false - ).withConstantFeature( - CommunityTweetCommunitySuspended, - false - ).withConstantFeature( - CommunityTweetCommunityDeleted, - false - ).withConstantFeature( - CommunityTweetCommunityVisible, - false - ).withConstantFeature( - ViewerIsInternalCommunitiesAdmin, - false - ).withConstantFeature( - ViewerIsCommunityAdmin, - false - ).withConstantFeature( - ViewerIsCommunityModerator, - false - ).withConstantFeature( - ViewerIsCommunityMember, - false - ).withConstantFeature( - CommunityTweetIsHidden, - false - ).withConstantFeature( - CommunityTweetAuthorIsRemoved, - false - ) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/CommunityTweetFeaturesPartitioned.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/CommunityTweetFeaturesPartitioned.scala deleted file mode 100644 index 695f724eb..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/CommunityTweetFeaturesPartitioned.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.visibility.builder.tweets - -import com.twitter.servo.util.Gate -import com.twitter.tweetypie.thriftscala.Tweet -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.models.ViewerContext - -class CommunityTweetFeaturesPartitioned( - a: CommunityTweetFeatures, - b: CommunityTweetFeatures, - bEnabled: Gate[Unit], -) extends CommunityTweetFeatures { - override def forTweet( - tweet: Tweet, - viewerContext: ViewerContext - ): FeatureMapBuilder => FeatureMapBuilder = - bEnabled.pick( - b.forTweet(tweet, viewerContext), - a.forTweet(tweet, viewerContext), - ) - - override def forTweetOnly(tweet: Tweet): FeatureMapBuilder => FeatureMapBuilder = bEnabled.pick( - b.forTweetOnly(tweet), - a.forTweetOnly(tweet), - ) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/CommunityTweetFeaturesV2.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/CommunityTweetFeaturesV2.scala deleted file mode 100644 index 407b5308c..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/CommunityTweetFeaturesV2.scala +++ /dev/null @@ -1,129 +0,0 @@ -package com.twitter.visibility.builder.tweets - -import com.twitter.communities.moderation.thriftscala.CommunityTweetModerationState -import com.twitter.communities.moderation.thriftscala.CommunityUserModerationState -import com.twitter.communities.visibility.thriftscala.CommunityVisibilityFeatures -import com.twitter.communities.visibility.thriftscala.CommunityVisibilityFeaturesV1 -import com.twitter.communities.visibility.thriftscala.CommunityVisibilityResult -import com.twitter.stitch.Stitch -import com.twitter.tweetypie.thriftscala.Tweet -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.common.CommunitiesSource -import com.twitter.visibility.features.CommunityTweetAuthorIsRemoved -import com.twitter.visibility.features.CommunityTweetCommunityNotFound -import com.twitter.visibility.features.CommunityTweetCommunityDeleted -import com.twitter.visibility.features.CommunityTweetCommunitySuspended -import com.twitter.visibility.features.CommunityTweetCommunityVisible -import com.twitter.visibility.features.CommunityTweetIsHidden -import com.twitter.visibility.features.TweetIsCommunityTweet -import com.twitter.visibility.features.ViewerIsCommunityAdmin -import com.twitter.visibility.features.ViewerIsCommunityMember -import com.twitter.visibility.features.ViewerIsCommunityModerator -import com.twitter.visibility.features.ViewerIsInternalCommunitiesAdmin -import com.twitter.visibility.models.CommunityTweet -import com.twitter.visibility.models.ViewerContext - -class CommunityTweetFeaturesV2(communitiesSource: CommunitiesSource) - extends CommunityTweetFeatures { - private[this] def forCommunityTweet( - communityTweet: CommunityTweet - ): FeatureMapBuilder => FeatureMapBuilder = { builder: FeatureMapBuilder => - { - val communityVisibilityFeaturesStitch = - communitiesSource.getCommunityVisibilityFeatures(communityTweet.communityId) - val communityTweetModerationStateStitch = - communitiesSource.getTweetModerationState(communityTweet.tweet.id) - val communityTweetAuthorModerationStateStitch = - communitiesSource.getUserModerationState( - communityTweet.authorId, - communityTweet.communityId - ) - - def getFlagFromFeatures(f: CommunityVisibilityFeaturesV1 => Boolean): Stitch[Boolean] = - communityVisibilityFeaturesStitch.map { - case Some(CommunityVisibilityFeatures.V1(v1)) => f(v1) - case _ => false - } - - def getFlagFromCommunityVisibilityResult( - f: CommunityVisibilityResult => Boolean - ): Stitch[Boolean] = getFlagFromFeatures { v => - f(v.communityVisibilityResult) - } - - builder - .withConstantFeature( - TweetIsCommunityTweet, - true - ) - .withFeature( - CommunityTweetCommunityNotFound, - getFlagFromCommunityVisibilityResult { - case CommunityVisibilityResult.NotFound => true - case _ => false - } - ) - .withFeature( - CommunityTweetCommunitySuspended, - getFlagFromCommunityVisibilityResult { - case CommunityVisibilityResult.Suspended => true - case _ => false - } - ) - .withFeature( - CommunityTweetCommunityDeleted, - getFlagFromCommunityVisibilityResult { - case CommunityVisibilityResult.Deleted => true - case _ => false - } - ) - .withFeature( - CommunityTweetCommunityVisible, - getFlagFromCommunityVisibilityResult { - case CommunityVisibilityResult.Visible => true - case _ => false - } - ) - .withFeature( - ViewerIsInternalCommunitiesAdmin, - getFlagFromFeatures { _.viewerIsInternalAdmin } - ) - .withFeature( - ViewerIsCommunityAdmin, - getFlagFromFeatures { _.viewerIsCommunityAdmin } - ) - .withFeature( - ViewerIsCommunityModerator, - getFlagFromFeatures { _.viewerIsCommunityModerator } - ) - .withFeature( - ViewerIsCommunityMember, - getFlagFromFeatures { _.viewerIsCommunityMember } - ) - .withFeature( - CommunityTweetIsHidden, - communityTweetModerationStateStitch.map { - case Some(CommunityTweetModerationState.Hidden(_)) => true - case _ => false - } - ) - .withFeature( - CommunityTweetAuthorIsRemoved, - communityTweetAuthorModerationStateStitch.map { - case Some(CommunityUserModerationState.Removed(_)) => true - case _ => false - } - ) - } - } - - def forTweet( - tweet: Tweet, - viewerContext: ViewerContext - ): FeatureMapBuilder => FeatureMapBuilder = { - CommunityTweet(tweet) match { - case None => forNonCommunityTweet() - case Some(communityTweet) => forCommunityTweet(communityTweet) - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/ConversationControlFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/ConversationControlFeatures.scala deleted file mode 100644 index 3f5ad7281..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/ConversationControlFeatures.scala +++ /dev/null @@ -1,178 +0,0 @@ -package com.twitter.visibility.builder.tweets - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.stitch.Stitch -import com.twitter.tweetypie.thriftscala.Tweet -import com.twitter.tweetypie.thriftscala.ConversationControl -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.builder.users.RelationshipFeatures -import com.twitter.visibility.common.InvitedToConversationRepo -import com.twitter.visibility.features.ConversationRootAuthorFollowsViewer -import com.twitter.visibility.features.TweetConversationViewerIsInvited -import com.twitter.visibility.features.TweetConversationViewerIsInvitedViaReplyMention -import com.twitter.visibility.features.TweetConversationViewerIsRootAuthor -import com.twitter.visibility.features.TweetHasByInvitationConversationControl -import com.twitter.visibility.features.TweetHasCommunityConversationControl -import com.twitter.visibility.features.TweetHasFollowersConversationControl -import com.twitter.visibility.features.ViewerFollowsConversationRootAuthor - -class ConversationControlFeatures( - relationshipFeatures: RelationshipFeatures, - isInvitedToConversationRepository: InvitedToConversationRepo, - statsReceiver: StatsReceiver) { - - private[this] val scopedStatsReceiver = statsReceiver.scope("conversation_control_features") - - private[this] val requests = scopedStatsReceiver.counter("requests") - - private[this] val tweetCommunityConversationRequest = - scopedStatsReceiver.scope(TweetHasCommunityConversationControl.name).counter("requests") - private[this] val tweetByInvitationConversationRequest = - scopedStatsReceiver.scope(TweetHasByInvitationConversationControl.name).counter("requests") - private[this] val tweetFollowersConversationRequest = - scopedStatsReceiver.scope(TweetHasFollowersConversationControl.name).counter("requests") - private[this] val rootAuthorFollowsViewer = - scopedStatsReceiver.scope(ConversationRootAuthorFollowsViewer.name).counter("requests") - private[this] val viewerFollowsRootAuthor = - scopedStatsReceiver.scope(ViewerFollowsConversationRootAuthor.name).counter("requests") - - def isCommunityConversation(conversationControl: Option[ConversationControl]): Boolean = - conversationControl - .collect { - case _: ConversationControl.Community => - tweetCommunityConversationRequest.incr() - true - }.getOrElse(false) - - def isByInvitationConversation(conversationControl: Option[ConversationControl]): Boolean = - conversationControl - .collect { - case _: ConversationControl.ByInvitation => - tweetByInvitationConversationRequest.incr() - true - }.getOrElse(false) - - def isFollowersConversation(conversationControl: Option[ConversationControl]): Boolean = - conversationControl - .collect { - case _: ConversationControl.Followers => - tweetFollowersConversationRequest.incr() - true - }.getOrElse(false) - - def conversationRootAuthorId( - conversationControl: Option[ConversationControl] - ): Option[Long] = - conversationControl match { - case Some(ConversationControl.Community(community)) => - Some(community.conversationTweetAuthorId) - case Some(ConversationControl.ByInvitation(byInvitation)) => - Some(byInvitation.conversationTweetAuthorId) - case Some(ConversationControl.Followers(followers)) => - Some(followers.conversationTweetAuthorId) - case _ => None - } - - def viewerIsRootAuthor( - conversationControl: Option[ConversationControl], - viewerIdOpt: Option[Long] - ): Boolean = - (conversationRootAuthorId(conversationControl), viewerIdOpt) match { - case (Some(rootAuthorId), Some(viewerId)) if rootAuthorId == viewerId => true - case _ => false - } - - def viewerIsInvited( - conversationControl: Option[ConversationControl], - viewerId: Option[Long] - ): Boolean = { - val invitedUserIds = conversationControl match { - case Some(ConversationControl.Community(community)) => - community.invitedUserIds - case Some(ConversationControl.ByInvitation(byInvitation)) => - byInvitation.invitedUserIds - case Some(ConversationControl.Followers(followers)) => - followers.invitedUserIds - case _ => Seq() - } - - viewerId.exists(invitedUserIds.contains(_)) - } - - def conversationAuthorFollows( - conversationControl: Option[ConversationControl], - viewerId: Option[Long] - ): Stitch[Boolean] = { - val conversationAuthorId = conversationControl.collect { - case ConversationControl.Community(community) => - community.conversationTweetAuthorId - } - - conversationAuthorId match { - case Some(authorId) => - rootAuthorFollowsViewer.incr() - relationshipFeatures.authorFollowsViewer(authorId, viewerId) - case None => - Stitch.False - } - } - - def followsConversationAuthor( - conversationControl: Option[ConversationControl], - viewerId: Option[Long] - ): Stitch[Boolean] = { - val conversationAuthorId = conversationControl.collect { - case ConversationControl.Followers(followers) => - followers.conversationTweetAuthorId - } - - conversationAuthorId match { - case Some(authorId) => - viewerFollowsRootAuthor.incr() - relationshipFeatures.viewerFollowsAuthor(authorId, viewerId) - case None => - Stitch.False - } - } - - def viewerIsInvitedViaReplyMention( - tweet: Tweet, - viewerIdOpt: Option[Long] - ): Stitch[Boolean] = { - val conversationIdOpt: Option[Long] = tweet.conversationControl match { - case Some(ConversationControl.Community(community)) - if community.inviteViaMention.contains(true) => - tweet.coreData.flatMap(_.conversationId) - case Some(ConversationControl.ByInvitation(invitation)) - if invitation.inviteViaMention.contains(true) => - tweet.coreData.flatMap(_.conversationId) - case Some(ConversationControl.Followers(followers)) - if followers.inviteViaMention.contains(true) => - tweet.coreData.flatMap(_.conversationId) - case _ => None - } - - (conversationIdOpt, viewerIdOpt) match { - case (Some(conversationId), Some(viewerId)) => - isInvitedToConversationRepository(conversationId, viewerId) - case _ => Stitch.False - } - } - - def forTweet(tweet: Tweet, viewerId: Option[Long]): FeatureMapBuilder => FeatureMapBuilder = { - requests.incr() - val cc = tweet.conversationControl - - _.withConstantFeature(TweetHasCommunityConversationControl, isCommunityConversation(cc)) - .withConstantFeature(TweetHasByInvitationConversationControl, isByInvitationConversation(cc)) - .withConstantFeature(TweetHasFollowersConversationControl, isFollowersConversation(cc)) - .withConstantFeature(TweetConversationViewerIsRootAuthor, viewerIsRootAuthor(cc, viewerId)) - .withConstantFeature(TweetConversationViewerIsInvited, viewerIsInvited(cc, viewerId)) - .withFeature(ConversationRootAuthorFollowsViewer, conversationAuthorFollows(cc, viewerId)) - .withFeature(ViewerFollowsConversationRootAuthor, followsConversationAuthor(cc, viewerId)) - .withFeature( - TweetConversationViewerIsInvitedViaReplyMention, - viewerIsInvitedViaReplyMention(tweet, viewerId)) - - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/EditTweetFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/EditTweetFeatures.scala deleted file mode 100644 index 224f4a9a4..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/EditTweetFeatures.scala +++ /dev/null @@ -1,71 +0,0 @@ -package com.twitter.visibility.builder.tweets - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.tweetypie.thriftscala.EditControl -import com.twitter.tweetypie.thriftscala.Tweet -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.features.TweetIsEditTweet -import com.twitter.visibility.features.TweetIsInitialTweet -import com.twitter.visibility.features.TweetIsLatestTweet -import com.twitter.visibility.features.TweetIsStaleTweet - -class EditTweetFeatures( - statsReceiver: StatsReceiver) { - - private[this] val scopedStatsReceiver = statsReceiver.scope("edit_tweet_features") - private[this] val tweetIsEditTweet = - scopedStatsReceiver.scope(TweetIsEditTweet.name).counter("requests") - private[this] val tweetIsStaleTweet = - scopedStatsReceiver.scope(TweetIsStaleTweet.name).counter("requests") - private[this] val tweetIsLatestTweet = - scopedStatsReceiver.scope(TweetIsLatestTweet.name).counter("requests") - private[this] val tweetIsInitialTweet = - scopedStatsReceiver.scope(TweetIsInitialTweet.name).counter("requests") - - def forTweet( - tweet: Tweet - ): FeatureMapBuilder => FeatureMapBuilder = { - _.withConstantFeature(TweetIsEditTweet, tweetIsEditTweet(tweet)) - .withConstantFeature(TweetIsStaleTweet, tweetIsStaleTweet(tweet)) - .withConstantFeature(TweetIsLatestTweet, tweetIsLatestTweet(tweet)) - .withConstantFeature(TweetIsInitialTweet, tweetIsInitialTweet(tweet)) - } - - def tweetIsStaleTweet(tweet: Tweet, incrementMetric: Boolean = true): Boolean = { - if (incrementMetric) tweetIsStaleTweet.incr() - - tweet.editControl match { - case None => false - case Some(ec) => - ec match { - case eci: EditControl.Initial => eci.initial.editTweetIds.last != tweet.id - case ece: EditControl.Edit => - ece.edit.editControlInitial.exists(_.editTweetIds.last != tweet.id) - case _ => false - } - } - } - - def tweetIsEditTweet(tweet: Tweet, incrementMetric: Boolean = true): Boolean = { - if (incrementMetric) tweetIsEditTweet.incr() - - tweet.editControl match { - case None => false - case Some(ec) => - ec match { - case _: EditControl.Initial => false - case _ => true - } - } - } - - def tweetIsLatestTweet(tweet: Tweet): Boolean = { - tweetIsLatestTweet.incr() - !tweetIsStaleTweet(tweet = tweet, incrementMetric = false) - } - - def tweetIsInitialTweet(tweet: Tweet): Boolean = { - tweetIsInitialTweet.incr() - !tweetIsEditTweet(tweet = tweet, incrementMetric = false) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/ExclusiveTweetFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/ExclusiveTweetFeatures.scala deleted file mode 100644 index 94aee6430..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/ExclusiveTweetFeatures.scala +++ /dev/null @@ -1,65 +0,0 @@ -package com.twitter.visibility.builder.tweets - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.stitch.Stitch -import com.twitter.tweetypie.thriftscala.Tweet -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.builder.users.ViewerVerbsAuthor -import com.twitter.visibility.common.UserRelationshipSource -import com.twitter.visibility.features.TweetIsExclusiveTweet -import com.twitter.visibility.features.ViewerIsExclusiveTweetRootAuthor -import com.twitter.visibility.features.ViewerSuperFollowsExclusiveTweetRootAuthor -import com.twitter.visibility.models.ViewerContext - -class ExclusiveTweetFeatures( - userRelationshipSource: UserRelationshipSource, - statsReceiver: StatsReceiver) { - - private[this] val scopedStatsReceiver = statsReceiver.scope("exclusive_tweet_features") - private[this] val viewerSuperFollowsAuthor = - scopedStatsReceiver.scope(ViewerSuperFollowsExclusiveTweetRootAuthor.name).counter("requests") - - def rootAuthorId(tweet: Tweet): Option[Long] = - tweet.exclusiveTweetControl.map(_.conversationAuthorId) - - def viewerIsRootAuthor( - tweet: Tweet, - viewerIdOpt: Option[Long] - ): Boolean = - (rootAuthorId(tweet), viewerIdOpt) match { - case (Some(rootAuthorId), Some(viewerId)) if rootAuthorId == viewerId => true - case _ => false - } - - def viewerSuperFollowsRootAuthor( - tweet: Tweet, - viewerId: Option[Long] - ): Stitch[Boolean] = - rootAuthorId(tweet) match { - case Some(authorId) => - ViewerVerbsAuthor( - authorId, - viewerId, - userRelationshipSource.superFollows, - viewerSuperFollowsAuthor) - case None => - Stitch.False - } - - def forTweet( - tweet: Tweet, - viewerContext: ViewerContext - ): FeatureMapBuilder => FeatureMapBuilder = { - val viewerId = viewerContext.userId - - _.withConstantFeature(TweetIsExclusiveTweet, tweet.exclusiveTweetControl.isDefined) - .withConstantFeature(ViewerIsExclusiveTweetRootAuthor, viewerIsRootAuthor(tweet, viewerId)) - .withFeature( - ViewerSuperFollowsExclusiveTweetRootAuthor, - viewerSuperFollowsRootAuthor(tweet, viewerId)) - } - - def forTweetOnly(tweet: Tweet): FeatureMapBuilder => FeatureMapBuilder = { - _.withConstantFeature(TweetIsExclusiveTweet, tweet.exclusiveTweetControl.isDefined) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/FosnrPefetchedLabelsRelationshipFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/FosnrPefetchedLabelsRelationshipFeatures.scala deleted file mode 100644 index f9a0445f9..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/FosnrPefetchedLabelsRelationshipFeatures.scala +++ /dev/null @@ -1,81 +0,0 @@ -package com.twitter.visibility.builder.tweets - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.stitch.Stitch -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.builder.users.ViewerVerbsAuthor -import com.twitter.visibility.common.UserId -import com.twitter.visibility.common.UserRelationshipSource -import com.twitter.visibility.features._ -import com.twitter.visibility.models.TweetSafetyLabel -import com.twitter.visibility.models.ViolationLevel - -class FosnrPefetchedLabelsRelationshipFeatures( - userRelationshipSource: UserRelationshipSource, - statsReceiver: StatsReceiver) { - - private[this] val scopedStatsReceiver = - statsReceiver.scope("fonsr_prefetched_relationship_features") - - private[this] val requests = scopedStatsReceiver.counter("requests") - - private[this] val viewerFollowsAuthorOfViolatingTweet = - scopedStatsReceiver.scope(ViewerFollowsAuthorOfViolatingTweet.name).counter("requests") - - private[this] val viewerDoesNotFollowAuthorOfViolatingTweet = - scopedStatsReceiver.scope(ViewerDoesNotFollowAuthorOfViolatingTweet.name).counter("requests") - - def forNonFosnr(): FeatureMapBuilder => FeatureMapBuilder = { - requests.incr() - _.withConstantFeature(ViewerFollowsAuthorOfViolatingTweet, false) - .withConstantFeature(ViewerDoesNotFollowAuthorOfViolatingTweet, false) - } - def forTweetWithSafetyLabelsAndAuthorId( - safetyLabels: Seq[TweetSafetyLabel], - authorId: Long, - viewerId: Option[Long] - ): FeatureMapBuilder => FeatureMapBuilder = { - requests.incr() - _.withFeature( - ViewerFollowsAuthorOfViolatingTweet, - viewerFollowsAuthorOfViolatingTweet(safetyLabels, authorId, viewerId)) - .withFeature( - ViewerDoesNotFollowAuthorOfViolatingTweet, - viewerDoesNotFollowAuthorOfViolatingTweet(safetyLabels, authorId, viewerId)) - } - def viewerFollowsAuthorOfViolatingTweet( - safetyLabels: Seq[TweetSafetyLabel], - authorId: UserId, - viewerId: Option[UserId] - ): Stitch[Boolean] = { - if (safetyLabels - .map(ViolationLevel.fromTweetSafetyLabelOpt).collect { - case Some(level) => level - }.isEmpty) { - return Stitch.False - } - ViewerVerbsAuthor( - authorId, - viewerId, - userRelationshipSource.follows, - viewerFollowsAuthorOfViolatingTweet) - } - def viewerDoesNotFollowAuthorOfViolatingTweet( - safetyLabels: Seq[TweetSafetyLabel], - authorId: UserId, - viewerId: Option[UserId] - ): Stitch[Boolean] = { - if (safetyLabels - .map(ViolationLevel.fromTweetSafetyLabelOpt).collect { - case Some(level) => level - }.isEmpty) { - return Stitch.False - } - ViewerVerbsAuthor( - authorId, - viewerId, - userRelationshipSource.follows, - viewerDoesNotFollowAuthorOfViolatingTweet).map(following => !following) - } - -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/FosnrRelationshipFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/FosnrRelationshipFeatures.scala deleted file mode 100644 index a6758eefa..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/FosnrRelationshipFeatures.scala +++ /dev/null @@ -1,82 +0,0 @@ -package com.twitter.visibility.builder.tweets - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.stitch.Stitch -import com.twitter.tweetypie.thriftscala.Tweet -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.builder.users.ViewerVerbsAuthor -import com.twitter.visibility.common.UserId -import com.twitter.visibility.common.UserRelationshipSource -import com.twitter.visibility.features._ -import com.twitter.visibility.models.ViolationLevel - -class FosnrRelationshipFeatures( - tweetLabels: TweetLabels, - userRelationshipSource: UserRelationshipSource, - statsReceiver: StatsReceiver) { - - private[this] val scopedStatsReceiver = statsReceiver.scope("fonsr_relationship_features") - - private[this] val requests = scopedStatsReceiver.counter("requests") - - private[this] val viewerFollowsAuthorOfViolatingTweet = - scopedStatsReceiver.scope(ViewerFollowsAuthorOfViolatingTweet.name).counter("requests") - - private[this] val viewerDoesNotFollowAuthorOfViolatingTweet = - scopedStatsReceiver.scope(ViewerDoesNotFollowAuthorOfViolatingTweet.name).counter("requests") - - def forTweetAndAuthorId( - tweet: Tweet, - authorId: Long, - viewerId: Option[Long] - ): FeatureMapBuilder => FeatureMapBuilder = { - requests.incr() - _.withFeature( - ViewerFollowsAuthorOfViolatingTweet, - viewerFollowsAuthorOfViolatingTweet(tweet, authorId, viewerId)) - .withFeature( - ViewerDoesNotFollowAuthorOfViolatingTweet, - viewerDoesNotFollowAuthorOfViolatingTweet(tweet, authorId, viewerId)) - } - - def viewerFollowsAuthorOfViolatingTweet( - tweet: Tweet, - authorId: UserId, - viewerId: Option[UserId] - ): Stitch[Boolean] = - tweetLabels.forTweet(tweet).flatMap { safetyLabels => - if (safetyLabels - .map(ViolationLevel.fromTweetSafetyLabelOpt).collect { - case Some(level) => level - }.isEmpty) { - Stitch.False - } else { - ViewerVerbsAuthor( - authorId, - viewerId, - userRelationshipSource.follows, - viewerFollowsAuthorOfViolatingTweet) - } - } - - def viewerDoesNotFollowAuthorOfViolatingTweet( - tweet: Tweet, - authorId: UserId, - viewerId: Option[UserId] - ): Stitch[Boolean] = - tweetLabels.forTweet(tweet).flatMap { safetyLabels => - if (safetyLabels - .map(ViolationLevel.fromTweetSafetyLabelOpt).collect { - case Some(level) => level - }.isEmpty) { - Stitch.False - } else { - ViewerVerbsAuthor( - authorId, - viewerId, - userRelationshipSource.follows, - viewerDoesNotFollowAuthorOfViolatingTweet).map(following => !following) - } - } - -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/MisinformationPolicyFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/MisinformationPolicyFeatures.scala deleted file mode 100644 index 49d01dc14..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/MisinformationPolicyFeatures.scala +++ /dev/null @@ -1,86 +0,0 @@ -package com.twitter.visibility.builder.tweets - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.stitch.Stitch -import com.twitter.tweetypie.thriftscala.EscherbirdEntityAnnotations -import com.twitter.tweetypie.thriftscala.Tweet -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.common.MisinformationPolicySource -import com.twitter.visibility.features._ -import com.twitter.visibility.models.MisinformationPolicy -import com.twitter.visibility.models.SemanticCoreMisinformation -import com.twitter.visibility.models.ViewerContext - -class MisinformationPolicyFeatures( - misinformationPolicySource: MisinformationPolicySource, - statsReceiver: StatsReceiver) { - - private[this] val scopedStatsReceiver = - statsReceiver.scope("misinformation_policy_features") - - private[this] val requests = scopedStatsReceiver.counter("requests") - private[this] val tweetMisinformationPolicies = - scopedStatsReceiver.scope(TweetMisinformationPolicies.name).counter("requests") - - def forTweet( - tweet: Tweet, - viewerContext: ViewerContext - ): FeatureMapBuilder => FeatureMapBuilder = { - requests.incr() - tweetMisinformationPolicies.incr() - - _.withFeature( - TweetMisinformationPolicies, - misinformationPolicy(tweet.escherbirdEntityAnnotations, viewerContext)) - .withFeature( - TweetEnglishMisinformationPolicies, - misinformationPolicyEnglishOnly(tweet.escherbirdEntityAnnotations)) - } - - def misinformationPolicyEnglishOnly( - escherbirdEntityAnnotations: Option[EscherbirdEntityAnnotations], - ): Stitch[Seq[MisinformationPolicy]] = { - val locale = Some( - MisinformationPolicySource.LanguageAndCountry( - language = Some("en"), - country = Some("us") - )) - fetchMisinformationPolicy(escherbirdEntityAnnotations, locale) - } - - def misinformationPolicy( - escherbirdEntityAnnotations: Option[EscherbirdEntityAnnotations], - viewerContext: ViewerContext - ): Stitch[Seq[MisinformationPolicy]] = { - val locale = viewerContext.requestLanguageCode.map { language => - MisinformationPolicySource.LanguageAndCountry( - language = Some(language), - country = viewerContext.requestCountryCode - ) - } - fetchMisinformationPolicy(escherbirdEntityAnnotations, locale) - } - - def fetchMisinformationPolicy( - escherbirdEntityAnnotations: Option[EscherbirdEntityAnnotations], - locale: Option[MisinformationPolicySource.LanguageAndCountry] - ): Stitch[Seq[MisinformationPolicy]] = { - Stitch.collect( - escherbirdEntityAnnotations - .map(_.entityAnnotations) - .getOrElse(Seq.empty) - .filter(_.domainId == SemanticCoreMisinformation.domainId) - .map(annotation => - misinformationPolicySource - .fetch( - annotation, - locale - ) - .map(misinformation => - MisinformationPolicy( - annotation = annotation, - misinformation = misinformation - ))) - ) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/ModerationFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/ModerationFeatures.scala deleted file mode 100644 index 08fc4ad3b..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/ModerationFeatures.scala +++ /dev/null @@ -1,23 +0,0 @@ -package com.twitter.visibility.builder.tweets - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.features.TweetIsModerated - -class ModerationFeatures(moderationSource: Long => Boolean, statsReceiver: StatsReceiver) { - - private[this] val scopedStatsReceiver: StatsReceiver = - statsReceiver.scope("moderation_features") - - private[this] val requests = scopedStatsReceiver.counter("requests") - - private[this] val tweetIsModerated = - scopedStatsReceiver.scope(TweetIsModerated.name).counter("requests") - - def forTweetId(tweetId: Long): FeatureMapBuilder => FeatureMapBuilder = { featureMapBuilder => - requests.incr() - tweetIsModerated.incr() - - featureMapBuilder.withConstantFeature(TweetIsModerated, moderationSource(tweetId)) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/SearchContextFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/SearchContextFeatures.scala deleted file mode 100644 index 8be075ceb..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/SearchContextFeatures.scala +++ /dev/null @@ -1,44 +0,0 @@ -package com.twitter.visibility.builder.tweets - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.search.common.constants.thriftscala.ThriftQuerySource -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.features.SearchCandidateCount -import com.twitter.visibility.features.SearchQueryHasUser -import com.twitter.visibility.features.SearchQuerySource -import com.twitter.visibility.features.SearchResultsPageNumber -import com.twitter.visibility.interfaces.common.search.SearchVFRequestContext - -class SearchContextFeatures( - statsReceiver: StatsReceiver) { - private[this] val scopedStatsReceiver = statsReceiver.scope("search_context_features") - private[this] val requests = scopedStatsReceiver.counter("requests") - private[this] val searchResultsPageNumber = - scopedStatsReceiver.scope(SearchResultsPageNumber.name).counter("requests") - private[this] val searchCandidateCount = - scopedStatsReceiver.scope(SearchCandidateCount.name).counter("requests") - private[this] val searchQuerySource = - scopedStatsReceiver.scope(SearchQuerySource.name).counter("requests") - private[this] val searchQueryHasUser = - scopedStatsReceiver.scope(SearchQueryHasUser.name).counter("requests") - - def forSearchContext( - searchContext: SearchVFRequestContext - ): FeatureMapBuilder => FeatureMapBuilder = { - requests.incr() - searchResultsPageNumber.incr() - searchCandidateCount.incr() - searchQuerySource.incr() - searchQueryHasUser.incr() - - _.withConstantFeature(SearchResultsPageNumber, searchContext.resultsPageNumber) - .withConstantFeature(SearchCandidateCount, searchContext.candidateCount) - .withConstantFeature( - SearchQuerySource, - searchContext.querySourceOption match { - case Some(querySource) => querySource - case _ => ThriftQuerySource.Unknown - }) - .withConstantFeature(SearchQueryHasUser, searchContext.queryHasUser) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/ToxicReplyFilterFeature.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/ToxicReplyFilterFeature.scala deleted file mode 100644 index 04af003f0..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/ToxicReplyFilterFeature.scala +++ /dev/null @@ -1,57 +0,0 @@ -package com.twitter.visibility.builder.tweets - -import com.twitter.contenthealth.toxicreplyfilter.thriftscala.FilterState -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.tweetypie.thriftscala.Tweet -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.features.ToxicReplyFilterConversationAuthorIsViewer -import com.twitter.visibility.features.ToxicReplyFilterState - -class ToxicReplyFilterFeature( - statsReceiver: StatsReceiver) { - - def forTweet(tweet: Tweet, viewerId: Option[Long]): FeatureMapBuilder => FeatureMapBuilder = { - builder => - requests.incr() - - builder - .withConstantFeature(ToxicReplyFilterState, isTweetFilteredFromAuthor(tweet)) - .withConstantFeature( - ToxicReplyFilterConversationAuthorIsViewer, - isRootAuthorViewer(tweet, viewerId)) - } - - private[this] def isRootAuthorViewer(tweet: Tweet, maybeViewerId: Option[Long]): Boolean = { - val maybeAuthorId = tweet.filteredReplyDetails.map(_.conversationAuthorId) - - (maybeViewerId, maybeAuthorId) match { - case (Some(viewerId), Some(authorId)) if viewerId == authorId => { - rootAuthorViewerStats.incr() - true - } - case _ => false - } - } - - private[this] def isTweetFilteredFromAuthor( - tweet: Tweet, - ): FilterState = { - val result = tweet.filteredReplyDetails.map(_.filterState).getOrElse(FilterState.Unfiltered) - - if (result == FilterState.FilteredFromAuthor) { - filteredFromAuthorStats.incr() - } - result - } - - private[this] val scopedStatsReceiver = - statsReceiver.scope("toxicreplyfilter") - - private[this] val requests = scopedStatsReceiver.counter("requests") - - private[this] val rootAuthorViewerStats = - scopedStatsReceiver.scope(ToxicReplyFilterConversationAuthorIsViewer.name).counter("requests") - - private[this] val filteredFromAuthorStats = - scopedStatsReceiver.scope(ToxicReplyFilterState.name).counter("requests") -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/TrustedFriendsFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/TrustedFriendsFeatures.scala deleted file mode 100644 index c381c47b3..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/TrustedFriendsFeatures.scala +++ /dev/null @@ -1,57 +0,0 @@ -package com.twitter.visibility.builder.tweets - -import com.twitter.stitch.Stitch -import com.twitter.tweetypie.thriftscala.Tweet -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.common.TrustedFriendsListId -import com.twitter.visibility.common.TrustedFriendsSource -import com.twitter.visibility.features.TweetIsTrustedFriendTweet -import com.twitter.visibility.features.ViewerIsTrustedFriendOfTweetAuthor -import com.twitter.visibility.features.ViewerIsTrustedFriendTweetAuthor - -class TrustedFriendsFeatures(trustedFriendsSource: TrustedFriendsSource) { - - private[builder] def viewerIsTrustedFriend( - tweet: Tweet, - viewerId: Option[Long] - ): Stitch[Boolean] = - (trustedFriendsListId(tweet), viewerId) match { - case (Some(tfListId), Some(userId)) => - trustedFriendsSource.isTrustedFriend(tfListId, userId) - case _ => Stitch.False - } - - private[builder] def viewerIsTrustedFriendListOwner( - tweet: Tweet, - viewerId: Option[Long] - ): Stitch[Boolean] = - (trustedFriendsListId(tweet), viewerId) match { - case (Some(tfListId), Some(userId)) => - trustedFriendsSource.isTrustedFriendListOwner(tfListId, userId) - case _ => Stitch.False - } - - private[builder] def trustedFriendsListId(tweet: Tweet): Option[TrustedFriendsListId] = - tweet.trustedFriendsControl.map(_.trustedFriendsListId) - - def forTweet( - tweet: Tweet, - viewerId: Option[Long] - ): FeatureMapBuilder => FeatureMapBuilder = { - _.withConstantFeature( - TweetIsTrustedFriendTweet, - tweet.trustedFriendsControl.isDefined - ).withFeature( - ViewerIsTrustedFriendTweetAuthor, - viewerIsTrustedFriendListOwner(tweet, viewerId) - ).withFeature( - ViewerIsTrustedFriendOfTweetAuthor, - viewerIsTrustedFriend(tweet, viewerId) - ) - } - - def forTweetOnly(tweet: Tweet): FeatureMapBuilder => FeatureMapBuilder = { - _.withConstantFeature(TweetIsTrustedFriendTweet, tweet.trustedFriendsControl.isDefined) - } - -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/TweetFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/TweetFeatures.scala deleted file mode 100644 index e28f0bda8..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/TweetFeatures.scala +++ /dev/null @@ -1,210 +0,0 @@ -package com.twitter.visibility.builder.tweets - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.snowflake.id.SnowflakeId -import com.twitter.stitch.Stitch -import com.twitter.tweetypie.thriftscala.CollabControl -import com.twitter.tweetypie.thriftscala.Tweet -import com.twitter.util.Duration -import com.twitter.util.Time -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.common.SafetyLabelMapSource -import com.twitter.visibility.common.TweetId -import com.twitter.visibility.common.UserId -import com.twitter.visibility.features._ -import com.twitter.visibility.models.SemanticCoreAnnotation -import com.twitter.visibility.models.TweetSafetyLabel - -object TweetFeatures { - - def FALLBACK_TIMESTAMP: Time = Time.epoch - - def tweetIsSelfReply(tweet: Tweet): Boolean = { - tweet.coreData match { - case Some(coreData) => - coreData.reply match { - case Some(reply) => - reply.inReplyToUserId == coreData.userId - - case None => - false - } - - case None => - false - } - } - - def tweetReplyToParentTweetDuration(tweet: Tweet): Option[Duration] = for { - coreData <- tweet.coreData - reply <- coreData.reply - inReplyToStatusId <- reply.inReplyToStatusId - replyTime <- SnowflakeId.timeFromIdOpt(tweet.id) - repliedToTime <- SnowflakeId.timeFromIdOpt(inReplyToStatusId) - } yield { - replyTime.diff(repliedToTime) - } - - def tweetReplyToRootTweetDuration(tweet: Tweet): Option[Duration] = for { - coreData <- tweet.coreData - if coreData.reply.isDefined - conversationId <- coreData.conversationId - replyTime <- SnowflakeId.timeFromIdOpt(tweet.id) - rootTime <- SnowflakeId.timeFromIdOpt(conversationId) - } yield { - replyTime.diff(rootTime) - } - - def tweetTimestamp(tweetId: Long): Time = - SnowflakeId.timeFromIdOpt(tweetId).getOrElse(FALLBACK_TIMESTAMP) - - def tweetSemanticCoreAnnotations(tweet: Tweet): Seq[SemanticCoreAnnotation] = { - tweet.escherbirdEntityAnnotations - .map(a => - a.entityAnnotations.map { annotation => - SemanticCoreAnnotation( - annotation.groupId, - annotation.domainId, - annotation.entityId - ) - }).toSeq.flatten - } - - def tweetIsNullcast(tweet: Tweet): Boolean = { - tweet.coreData match { - case Some(coreData) => - coreData.nullcast - case None => - false - } - } - - def tweetAuthorUserId(tweet: Tweet): Option[UserId] = { - tweet.coreData.map(_.userId) - } -} - -sealed trait TweetLabels { - def forTweet(tweet: Tweet): Stitch[Seq[TweetSafetyLabel]] - def forTweetId(tweetId: TweetId): Stitch[Seq[TweetSafetyLabel]] -} - -class StratoTweetLabelMaps(safetyLabelSource: SafetyLabelMapSource) extends TweetLabels { - - override def forTweet(tweet: Tweet): Stitch[Seq[TweetSafetyLabel]] = { - forTweetId(tweet.id) - } - - def forTweetId(tweetId: TweetId): Stitch[Seq[TweetSafetyLabel]] = { - safetyLabelSource - .fetch(tweetId).map( - _.map( - _.labels - .map( - _.map(sl => TweetSafetyLabel.fromTuple(sl._1, sl._2)).toSeq - ).getOrElse(Seq()) - ).getOrElse(Seq())) - } -} - -object NilTweetLabelMaps extends TweetLabels { - override def forTweet(tweet: Tweet): Stitch[Seq[TweetSafetyLabel]] = Stitch.Nil - override def forTweetId(tweetId: TweetId): Stitch[Seq[TweetSafetyLabel]] = Stitch.Nil -} - -class TweetFeatures(tweetLabels: TweetLabels, statsReceiver: StatsReceiver) { - private[this] val scopedStatsReceiver = statsReceiver.scope("tweet_features") - - private[this] val requests = scopedStatsReceiver.counter("requests") - private[this] val tweetSafetyLabels = - scopedStatsReceiver.scope(TweetSafetyLabels.name).counter("requests") - private[this] val tweetTakedownReasons = - scopedStatsReceiver.scope(TweetTakedownReasons.name).counter("requests") - private[this] val tweetIsSelfReply = - scopedStatsReceiver.scope(TweetIsSelfReply.name).counter("requests") - private[this] val tweetTimestamp = - scopedStatsReceiver.scope(TweetTimestamp.name).counter("requests") - private[this] val tweetReplyToParentTweetDuration = - scopedStatsReceiver.scope(TweetReplyToParentTweetDuration.name).counter("requests") - private[this] val tweetReplyToRootTweetDuration = - scopedStatsReceiver.scope(TweetReplyToRootTweetDuration.name).counter("requests") - private[this] val tweetSemanticCoreAnnotations = - scopedStatsReceiver.scope(TweetSemanticCoreAnnotations.name).counter("requests") - private[this] val tweetId = - scopedStatsReceiver.scope(TweetId.name).counter("requests") - private[this] val tweetHasNsfwUser = - scopedStatsReceiver.scope(TweetHasNsfwUser.name).counter("requests") - private[this] val tweetHasNsfwAdmin = - scopedStatsReceiver.scope(TweetHasNsfwAdmin.name).counter("requests") - private[this] val tweetIsNullcast = - scopedStatsReceiver.scope(TweetIsNullcast.name).counter("requests") - private[this] val tweetHasMedia = - scopedStatsReceiver.scope(TweetHasMedia.name).counter("requests") - private[this] val tweetIsCommunity = - scopedStatsReceiver.scope(TweetIsCommunityTweet.name).counter("requests") - private[this] val tweetIsCollabInvitation = - scopedStatsReceiver.scope(TweetIsCollabInvitationTweet.name).counter("requests") - - def forTweet(tweet: Tweet): FeatureMapBuilder => FeatureMapBuilder = { - forTweetWithoutSafetyLabels(tweet) - .andThen(_.withFeature(TweetSafetyLabels, tweetLabels.forTweet(tweet))) - } - - def forTweetWithoutSafetyLabels(tweet: Tweet): FeatureMapBuilder => FeatureMapBuilder = { - requests.incr() - - tweetTakedownReasons.incr() - tweetIsSelfReply.incr() - tweetTimestamp.incr() - tweetReplyToParentTweetDuration.incr() - tweetReplyToRootTweetDuration.incr() - tweetSemanticCoreAnnotations.incr() - tweetId.incr() - tweetHasNsfwUser.incr() - tweetHasNsfwAdmin.incr() - tweetIsNullcast.incr() - tweetHasMedia.incr() - tweetIsCommunity.incr() - tweetIsCollabInvitation.incr() - - _.withConstantFeature(TweetTakedownReasons, tweet.takedownReasons.getOrElse(Seq.empty)) - .withConstantFeature(TweetIsSelfReply, TweetFeatures.tweetIsSelfReply(tweet)) - .withConstantFeature(TweetTimestamp, TweetFeatures.tweetTimestamp(tweet.id)) - .withConstantFeature( - TweetReplyToParentTweetDuration, - TweetFeatures.tweetReplyToParentTweetDuration(tweet)) - .withConstantFeature( - TweetReplyToRootTweetDuration, - TweetFeatures.tweetReplyToRootTweetDuration(tweet)) - .withConstantFeature( - TweetSemanticCoreAnnotations, - TweetFeatures.tweetSemanticCoreAnnotations(tweet)) - .withConstantFeature(TweetId, tweet.id) - .withConstantFeature(TweetHasNsfwUser, tweetHasNsfwUser(tweet)) - .withConstantFeature(TweetHasNsfwAdmin, tweetHasNsfwAdmin(tweet)) - .withConstantFeature(TweetIsNullcast, TweetFeatures.tweetIsNullcast(tweet)) - .withConstantFeature(TweetHasMedia, tweetHasMedia(tweet)) - .withConstantFeature(TweetIsCommunityTweet, tweetHasCommunity(tweet)) - .withConstantFeature(TweetIsCollabInvitationTweet, tweetIsCollabInvitation(tweet)) - } - - def tweetHasNsfwUser(tweet: Tweet): Boolean = - tweet.coreData.exists(_.nsfwUser) - - def tweetHasNsfwAdmin(tweet: Tweet): Boolean = - tweet.coreData.exists(_.nsfwAdmin) - - def tweetHasMedia(tweet: Tweet): Boolean = - tweet.coreData.exists(_.hasMedia.getOrElse(false)) - - def tweetHasCommunity(tweet: Tweet): Boolean = { - tweet.communities.exists(_.communityIds.nonEmpty) - } - - def tweetIsCollabInvitation(tweet: Tweet): Boolean = { - tweet.collabControl.exists(_ match { - case CollabControl.CollabInvitation(_) => true - case _ => false - }) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/TweetIdFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/TweetIdFeatures.scala deleted file mode 100644 index b284b4ab6..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/TweetIdFeatures.scala +++ /dev/null @@ -1,76 +0,0 @@ -package com.twitter.visibility.builder.tweets - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.servo.util.Gate -import com.twitter.spam.rtf.thriftscala.SafetyLabel -import com.twitter.spam.rtf.thriftscala.SafetyLabelType -import com.twitter.spam.rtf.thriftscala.SafetyLabelValue -import com.twitter.stitch.Stitch -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.common.stitch.StitchHelpers -import com.twitter.visibility.features.TweetId -import com.twitter.visibility.features.TweetSafetyLabels -import com.twitter.visibility.features.TweetTimestamp -import com.twitter.visibility.models.TweetSafetyLabel - -class TweetIdFeatures( - statsReceiver: StatsReceiver, - enableStitchProfiling: Gate[Unit]) { - private[this] val scopedStatsReceiver: StatsReceiver = statsReceiver.scope("tweet_id_features") - - private[this] val requests = scopedStatsReceiver.counter("requests") - private[this] val tweetSafetyLabels = - scopedStatsReceiver.scope(TweetSafetyLabels.name).counter("requests") - private[this] val tweetTimestamp = - scopedStatsReceiver.scope(TweetTimestamp.name).counter("requests") - - private[this] val labelFetchScope: StatsReceiver = - scopedStatsReceiver.scope("labelFetch") - - private[this] def getTweetLabels( - tweetId: Long, - labelFetcher: Long => Stitch[Map[SafetyLabelType, SafetyLabel]] - ): Stitch[Seq[TweetSafetyLabel]] = { - val stitch = - labelFetcher(tweetId).map { labelMap => - labelMap - .map { case (labelType, label) => SafetyLabelValue(labelType, label) }.toSeq - .map(TweetSafetyLabel.fromThrift) - } - - if (enableStitchProfiling()) { - StitchHelpers.profileStitch( - stitch, - Seq(labelFetchScope) - ) - } else { - stitch - } - } - - def forTweetId( - tweetId: Long, - labelFetcher: Long => Stitch[Map[SafetyLabelType, SafetyLabel]] - ): FeatureMapBuilder => FeatureMapBuilder = { - requests.incr() - tweetSafetyLabels.incr() - tweetTimestamp.incr() - - _.withFeature(TweetSafetyLabels, getTweetLabels(tweetId, labelFetcher)) - .withConstantFeature(TweetTimestamp, TweetFeatures.tweetTimestamp(tweetId)) - .withConstantFeature(TweetId, tweetId) - } - - def forTweetId( - tweetId: Long, - constantTweetSafetyLabels: Seq[TweetSafetyLabel] - ): FeatureMapBuilder => FeatureMapBuilder = { - requests.incr() - tweetSafetyLabels.incr() - tweetTimestamp.incr() - - _.withConstantFeature(TweetSafetyLabels, constantTweetSafetyLabels) - .withConstantFeature(TweetTimestamp, TweetFeatures.tweetTimestamp(tweetId)) - .withConstantFeature(TweetId, tweetId) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/TweetMediaMetadataFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/TweetMediaMetadataFeatures.scala deleted file mode 100644 index e421bd7b6..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/TweetMediaMetadataFeatures.scala +++ /dev/null @@ -1,130 +0,0 @@ -package com.twitter.visibility.builder.tweets - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.mediaservices.commons.mediainformation.thriftscala.AdditionalMetadata -import com.twitter.mediaservices.media_util.GenericMediaKey -import com.twitter.stitch.Stitch -import com.twitter.tweetypie.thriftscala.Tweet -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.common.TweetMediaMetadataSource -import com.twitter.visibility.features.HasDmcaMediaFeature -import com.twitter.visibility.features.MediaGeoRestrictionsAllowList -import com.twitter.visibility.features.MediaGeoRestrictionsDenyList - -class TweetMediaMetadataFeatures( - mediaMetadataSource: TweetMediaMetadataSource, - statsReceiver: StatsReceiver) { - - private[this] val scopedStatsReceiver = statsReceiver.scope("tweet_media_metadata_features") - private[this] val reportedStats = scopedStatsReceiver.scope("dmcaStats") - - def forTweet( - tweet: Tweet, - mediaKeys: Seq[GenericMediaKey], - enableFetchMediaMetadata: Boolean - ): FeatureMapBuilder => FeatureMapBuilder = { featureMapBuilder => - featureMapBuilder.withFeature( - HasDmcaMediaFeature, - mediaIsDmca(tweet, mediaKeys, enableFetchMediaMetadata)) - featureMapBuilder.withFeature( - MediaGeoRestrictionsAllowList, - allowlist(tweet, mediaKeys, enableFetchMediaMetadata)) - featureMapBuilder.withFeature( - MediaGeoRestrictionsDenyList, - denylist(tweet, mediaKeys, enableFetchMediaMetadata)) - } - - private def mediaIsDmca( - tweet: Tweet, - mediaKeys: Seq[GenericMediaKey], - enableFetchMediaMetadata: Boolean - ) = getMediaAdditionalMetadata(tweet, mediaKeys, enableFetchMediaMetadata) - .map(_.exists(_.restrictions.exists(_.isDmca))) - - private def allowlist( - tweet: Tweet, - mediaKeys: Seq[GenericMediaKey], - enableFetchMediaMetadata: Boolean - ) = getMediaGeoRestrictions(tweet, mediaKeys, enableFetchMediaMetadata) - .map(_.flatMap(_.whitelistedCountryCodes)) - - private def denylist( - tweet: Tweet, - mediaKeys: Seq[GenericMediaKey], - enableFetchMediaMetadata: Boolean - ) = getMediaGeoRestrictions(tweet, mediaKeys, enableFetchMediaMetadata) - .map(_.flatMap(_.blacklistedCountryCodes)) - - private def getMediaGeoRestrictions( - tweet: Tweet, - mediaKeys: Seq[GenericMediaKey], - enableFetchMediaMetadata: Boolean - ) = { - getMediaAdditionalMetadata(tweet, mediaKeys, enableFetchMediaMetadata) - .map(additionalMetadatasSeq => { - for { - additionalMetadata <- additionalMetadatasSeq - restrictions <- additionalMetadata.restrictions - geoRestrictions <- restrictions.geoRestrictions - } yield { - geoRestrictions - } - }) - } - - private def getMediaAdditionalMetadata( - tweet: Tweet, - mediaKeys: Seq[GenericMediaKey], - enableFetchMediaMetadata: Boolean - ): Stitch[Seq[AdditionalMetadata]] = { - if (mediaKeys.isEmpty) { - reportedStats.counter("empty").incr() - Stitch.value(Seq.empty) - } else { - tweet.media.flatMap { mediaEntities => - val alreadyHydratedMetadata = mediaEntities - .filter(_.mediaKey.isDefined) - .flatMap(_.additionalMetadata) - - if (alreadyHydratedMetadata.nonEmpty) { - Some(alreadyHydratedMetadata) - } else { - None - } - } match { - case Some(additionalMetadata) => - reportedStats.counter("already_hydrated").incr() - Stitch.value(additionalMetadata) - case None => - Stitch - .collect( - mediaKeys.map(fetchAdditionalMetadata(tweet.id, _, enableFetchMediaMetadata)) - ).map(maybeMetadatas => { - maybeMetadatas - .filter(_.isDefined) - .map(_.get) - }) - } - } - } - - private def fetchAdditionalMetadata( - tweetId: Long, - genericMediaKey: GenericMediaKey, - enableFetchMediaMetadata: Boolean - ): Stitch[Option[AdditionalMetadata]] = - if (enableFetchMediaMetadata) { - genericMediaKey.toThriftMediaKey() match { - case Some(mediaKey) => - reportedStats.counter("request").incr() - mediaMetadataSource.fetch(tweetId, mediaKey) - case None => - reportedStats.counter("empty_key").incr() - Stitch.None - } - } else { - reportedStats.counter("light_request").incr() - Stitch.None - } - -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/TweetPerspectiveFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/TweetPerspectiveFeatures.scala deleted file mode 100644 index e2e25740b..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/TweetPerspectiveFeatures.scala +++ /dev/null @@ -1,54 +0,0 @@ -package com.twitter.visibility.builder.tweets - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.stitch.Stitch -import com.twitter.tweetypie.thriftscala.Tweet -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.common.TweetPerspectiveSource -import com.twitter.visibility.features.ViewerReportedTweet - -class TweetPerspectiveFeatures( - tweetPerspectiveSource: TweetPerspectiveSource, - statsReceiver: StatsReceiver) { - - private[this] val scopedStatsReceiver = statsReceiver.scope("tweet_perspective_features") - private[this] val reportedStats = scopedStatsReceiver.scope("reported") - - def forTweet( - tweet: Tweet, - viewerId: Option[Long], - enableFetchReportedPerspective: Boolean - ): FeatureMapBuilder => FeatureMapBuilder = - _.withFeature( - ViewerReportedTweet, - tweetIsReported(tweet, viewerId, enableFetchReportedPerspective)) - - private[builder] def tweetIsReported( - tweet: Tweet, - viewerId: Option[Long], - enableFetchReportedPerspective: Boolean = true - ): Stitch[Boolean] = { - ((tweet.perspective, viewerId) match { - case (Some(perspective), _) => - Stitch.value(perspective.reported).onSuccess { _ => - reportedStats.counter("already_hydrated").incr() - } - case (None, Some(viewerId)) => - if (enableFetchReportedPerspective) { - tweetPerspectiveSource.reported(tweet.id, viewerId).onSuccess { _ => - reportedStats.counter("request").incr() - } - } else { - Stitch.False.onSuccess { _ => - reportedStats.counter("light_request").incr() - } - } - case _ => - Stitch.False.onSuccess { _ => - reportedStats.counter("empty").incr() - } - }).onSuccess { _ => - reportedStats.counter("").incr() - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/TweetVisibilityNudgeSourceWrapper.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/TweetVisibilityNudgeSourceWrapper.scala deleted file mode 100644 index 99ad6a46a..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/TweetVisibilityNudgeSourceWrapper.scala +++ /dev/null @@ -1,39 +0,0 @@ -package com.twitter.visibility.builder.tweets - -import com.twitter.spam.rtf.thriftscala.SafetyLabelType -import com.twitter.spam.rtf.thriftscala.SafetyLabelType.ExperimentalNudge -import com.twitter.spam.rtf.thriftscala.SafetyLabelType.SemanticCoreMisinformation -import com.twitter.spam.rtf.thriftscala.SafetyLabelType.UnsafeUrl -import com.twitter.visibility.common.LocalizedNudgeSource -import com.twitter.visibility.common.actions.TweetVisibilityNudgeReason -import com.twitter.visibility.common.actions.TweetVisibilityNudgeReason.ExperimentalNudgeSafetyLabelReason -import com.twitter.visibility.common.actions.TweetVisibilityNudgeReason.SemanticCoreMisinformationLabelReason -import com.twitter.visibility.common.actions.TweetVisibilityNudgeReason.UnsafeURLLabelReason -import com.twitter.visibility.rules.LocalizedNudge - -class TweetVisibilityNudgeSourceWrapper(localizedNudgeSource: LocalizedNudgeSource) { - - def getLocalizedNudge( - reason: TweetVisibilityNudgeReason, - languageCode: String, - countryCode: Option[String] - ): Option[LocalizedNudge] = - reason match { - case ExperimentalNudgeSafetyLabelReason => - fetchNudge(ExperimentalNudge, languageCode, countryCode) - case SemanticCoreMisinformationLabelReason => - fetchNudge(SemanticCoreMisinformation, languageCode, countryCode) - case UnsafeURLLabelReason => - fetchNudge(UnsafeUrl, languageCode, countryCode) - } - - private def fetchNudge( - safetyLabel: SafetyLabelType, - languageCode: String, - countryCode: Option[String] - ): Option[LocalizedNudge] = { - localizedNudgeSource - .fetch(safetyLabel, languageCode, countryCode) - .map(LocalizedNudge.fromStratoThrift) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/UnmentionNotificationFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/UnmentionNotificationFeatures.scala deleted file mode 100644 index 513627009..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/tweets/UnmentionNotificationFeatures.scala +++ /dev/null @@ -1,75 +0,0 @@ -package com.twitter.visibility.builder.tweets - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.notificationservice.model.notification._ -import com.twitter.servo.util.Gate -import com.twitter.stitch.Stitch -import com.twitter.tweetypie.thriftscala.SettingsUnmentions -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.common.TweetSource -import com.twitter.visibility.features.NotificationIsOnUnmentionedViewer - -object UnmentionNotificationFeatures { - def ForNonUnmentionNotificationFeatures: FeatureMapBuilder => FeatureMapBuilder = { - _.withConstantFeature(NotificationIsOnUnmentionedViewer, false) - } -} - -class UnmentionNotificationFeatures( - tweetSource: TweetSource, - enableUnmentionHydration: Gate[Long], - statsReceiver: StatsReceiver) { - - private[this] val scopedStatsReceiver = - statsReceiver.scope("unmention_notification_features") - private[this] val requestsCounter = scopedStatsReceiver.counter("requests") - private[this] val hydrationsCounter = scopedStatsReceiver.counter("hydrations") - private[this] val notificationsUnmentionUserCounter = - scopedStatsReceiver - .scope(NotificationIsOnUnmentionedViewer.name).counter("unmentioned_users") - - def forNotification(notification: Notification): FeatureMapBuilder => FeatureMapBuilder = { - requestsCounter.incr() - - val isUnmentionNotification = tweetId(notification) match { - case Some(tweetId) if enableUnmentionHydration(notification.target) => - hydrationsCounter.incr() - tweetSource - .getTweet(tweetId) - .map { - case Some(tweet) => - tweet.settingsUnmentions match { - case Some(SettingsUnmentions(Some(unmentionedUserIds))) => - if (unmentionedUserIds.contains(notification.target)) { - notificationsUnmentionUserCounter.incr() - true - } else { - false - } - case _ => false - } - case _ => false - } - case _ => Stitch.False - } - _.withFeature(NotificationIsOnUnmentionedViewer, isUnmentionNotification) - } - - private[this] def tweetId(notification: Notification): Option[Long] = { - notification match { - case n: MentionNotification => Some(n.mentioningTweetId) - case n: FavoritedMentioningTweetNotification => Some(n.mentioningTweetId) - case n: FavoritedReplyToYourTweetNotification => Some(n.replyTweetId) - case n: MentionQuoteNotification => Some(n.mentioningTweetId) - case n: ReactionMentioningTweetNotification => Some(n.mentioningTweetId) - case n: ReplyNotification => Some(n.replyingTweetId) - case n: RetweetedMentionNotification => Some(n.mentioningTweetId) - case n: RetweetedReplyToYourTweetNotification => Some(n.replyTweetId) - case n: ReplyToConversationNotification => Some(n.replyingTweetId) - case n: ReactionReplyToYourTweetNotification => Some(n.replyTweetId) - case _ => None - } - - } - -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/AuthorDeviceFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/AuthorDeviceFeatures.scala deleted file mode 100644 index 5ffa3c107..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/AuthorDeviceFeatures.scala +++ /dev/null @@ -1,39 +0,0 @@ -package com.twitter.visibility.builder.users - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.gizmoduck.thriftscala.User -import com.twitter.stitch.Stitch -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.common.UserDeviceSource -import com.twitter.visibility.features.AuthorHasConfirmedEmail -import com.twitter.visibility.features.AuthorHasVerifiedPhone - -class AuthorDeviceFeatures(userDeviceSource: UserDeviceSource, statsReceiver: StatsReceiver) { - private[this] val scopedStatsReceiver = statsReceiver.scope("author_device_features") - - private[this] val requests = scopedStatsReceiver.counter("requests") - - private[this] val authorHasConfirmedEmailRequests = - scopedStatsReceiver.scope(AuthorHasConfirmedEmail.name).counter("requests") - private[this] val authorHasVerifiedPhoneRequests = - scopedStatsReceiver.scope(AuthorHasVerifiedPhone.name).counter("requests") - - def forAuthor(author: User): FeatureMapBuilder => FeatureMapBuilder = forAuthorId(author.id) - - def forAuthorId(authorId: Long): FeatureMapBuilder => FeatureMapBuilder = { - requests.incr() - - _.withFeature(AuthorHasConfirmedEmail, authorHasConfirmedEmail(authorId)) - .withFeature(AuthorHasVerifiedPhone, authorHasVerifiedPhone(authorId)) - } - - def authorHasConfirmedEmail(authorId: Long): Stitch[Boolean] = { - authorHasConfirmedEmailRequests.incr() - userDeviceSource.hasConfirmedEmail(authorId) - } - - def authorHasVerifiedPhone(authorId: Long): Stitch[Boolean] = { - authorHasVerifiedPhoneRequests.incr() - userDeviceSource.hasConfirmedPhone(authorId) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/AuthorFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/AuthorFeatures.scala deleted file mode 100644 index bf6529691..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/AuthorFeatures.scala +++ /dev/null @@ -1,221 +0,0 @@ -package com.twitter.visibility.builder.users - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.gizmoduck.thriftscala.Label -import com.twitter.gizmoduck.thriftscala.Labels -import com.twitter.gizmoduck.thriftscala.Profile -import com.twitter.gizmoduck.thriftscala.Safety -import com.twitter.gizmoduck.thriftscala.User -import com.twitter.stitch.NotFound -import com.twitter.stitch.Stitch -import com.twitter.tseng.withholding.thriftscala.TakedownReason -import com.twitter.util.Duration -import com.twitter.util.Time -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.common.UserSource -import com.twitter.visibility.features._ - -class AuthorFeatures(userSource: UserSource, statsReceiver: StatsReceiver) { - private[this] val scopedStatsReceiver = statsReceiver.scope("author_features") - - private[this] val requests = scopedStatsReceiver.counter("requests") - - private[this] val authorUserLabels = - scopedStatsReceiver.scope(AuthorUserLabels.name).counter("requests") - private[this] val authorIsSuspended = - scopedStatsReceiver.scope(AuthorIsSuspended.name).counter("requests") - private[this] val authorIsProtected = - scopedStatsReceiver.scope(AuthorIsProtected.name).counter("requests") - private[this] val authorIsDeactivated = - scopedStatsReceiver.scope(AuthorIsDeactivated.name).counter("requests") - private[this] val authorIsErased = - scopedStatsReceiver.scope(AuthorIsErased.name).counter("requests") - private[this] val authorIsOffboarded = - scopedStatsReceiver.scope(AuthorIsOffboarded.name).counter("requests") - private[this] val authorIsNsfwUser = - scopedStatsReceiver.scope(AuthorIsNsfwUser.name).counter("requests") - private[this] val authorIsNsfwAdmin = - scopedStatsReceiver.scope(AuthorIsNsfwAdmin.name).counter("requests") - private[this] val authorTakedownReasons = - scopedStatsReceiver.scope(AuthorTakedownReasons.name).counter("requests") - private[this] val authorHasDefaultProfileImage = - scopedStatsReceiver.scope(AuthorHasDefaultProfileImage.name).counter("requests") - private[this] val authorAccountAge = - scopedStatsReceiver.scope(AuthorAccountAge.name).counter("requests") - private[this] val authorIsVerified = - scopedStatsReceiver.scope(AuthorIsVerified.name).counter("requests") - private[this] val authorScreenName = - scopedStatsReceiver.scope(AuthorScreenName.name).counter("requests") - private[this] val authorIsBlueVerified = - scopedStatsReceiver.scope(AuthorIsBlueVerified.name).counter("requests") - - def forAuthor(author: User): FeatureMapBuilder => FeatureMapBuilder = { - requests.incr() - - _.withConstantFeature(AuthorId, Set(author.id)) - .withConstantFeature(AuthorUserLabels, authorUserLabels(author)) - .withConstantFeature(AuthorIsProtected, authorIsProtected(author)) - .withConstantFeature(AuthorIsSuspended, authorIsSuspended(author)) - .withConstantFeature(AuthorIsDeactivated, authorIsDeactivated(author)) - .withConstantFeature(AuthorIsErased, authorIsErased(author)) - .withConstantFeature(AuthorIsOffboarded, authorIsOffboarded(author)) - .withConstantFeature(AuthorTakedownReasons, authorTakedownReasons(author)) - .withConstantFeature(AuthorHasDefaultProfileImage, authorHasDefaultProfileImage(author)) - .withConstantFeature(AuthorAccountAge, authorAccountAge(author)) - .withConstantFeature(AuthorIsNsfwUser, authorIsNsfwUser(author)) - .withConstantFeature(AuthorIsNsfwAdmin, authorIsNsfwAdmin(author)) - .withConstantFeature(AuthorIsVerified, authorIsVerified(author)) - .withConstantFeature(AuthorScreenName, authorScreenName(author)) - .withConstantFeature(AuthorIsBlueVerified, authorIsBlueVerified(author)) - } - - def forAuthorNoDefaults(author: User): FeatureMapBuilder => FeatureMapBuilder = { - requests.incr() - - _.withConstantFeature(AuthorId, Set(author.id)) - .withConstantFeature(AuthorUserLabels, authorUserLabelsOpt(author)) - .withConstantFeature(AuthorIsProtected, authorIsProtectedOpt(author)) - .withConstantFeature(AuthorIsSuspended, authorIsSuspendedOpt(author)) - .withConstantFeature(AuthorIsDeactivated, authorIsDeactivatedOpt(author)) - .withConstantFeature(AuthorIsErased, authorIsErasedOpt(author)) - .withConstantFeature(AuthorIsOffboarded, authorIsOffboarded(author)) - .withConstantFeature(AuthorTakedownReasons, authorTakedownReasons(author)) - .withConstantFeature(AuthorHasDefaultProfileImage, authorHasDefaultProfileImage(author)) - .withConstantFeature(AuthorAccountAge, authorAccountAge(author)) - .withConstantFeature(AuthorIsNsfwUser, authorIsNsfwUserOpt(author)) - .withConstantFeature(AuthorIsNsfwAdmin, authorIsNsfwAdminOpt(author)) - .withConstantFeature(AuthorIsVerified, authorIsVerifiedOpt(author)) - .withConstantFeature(AuthorScreenName, authorScreenName(author)) - .withConstantFeature(AuthorIsBlueVerified, authorIsBlueVerified(author)) - } - - def forAuthorId(authorId: Long): FeatureMapBuilder => FeatureMapBuilder = { - requests.incr() - - _.withConstantFeature(AuthorId, Set(authorId)) - .withFeature(AuthorUserLabels, authorUserLabels(authorId)) - .withFeature(AuthorIsProtected, authorIsProtected(authorId)) - .withFeature(AuthorIsSuspended, authorIsSuspended(authorId)) - .withFeature(AuthorIsDeactivated, authorIsDeactivated(authorId)) - .withFeature(AuthorIsErased, authorIsErased(authorId)) - .withFeature(AuthorIsOffboarded, authorIsOffboarded(authorId)) - .withFeature(AuthorTakedownReasons, authorTakedownReasons(authorId)) - .withFeature(AuthorHasDefaultProfileImage, authorHasDefaultProfileImage(authorId)) - .withFeature(AuthorAccountAge, authorAccountAge(authorId)) - .withFeature(AuthorIsNsfwUser, authorIsNsfwUser(authorId)) - .withFeature(AuthorIsNsfwAdmin, authorIsNsfwAdmin(authorId)) - .withFeature(AuthorIsVerified, authorIsVerified(authorId)) - .withFeature(AuthorScreenName, authorScreenName(authorId)) - .withFeature(AuthorIsBlueVerified, authorIsBlueVerified(authorId)) - } - - def forNoAuthor(): FeatureMapBuilder => FeatureMapBuilder = { - _.withConstantFeature(AuthorId, Set.empty[Long]) - .withConstantFeature(AuthorUserLabels, Seq.empty) - .withConstantFeature(AuthorIsProtected, false) - .withConstantFeature(AuthorIsSuspended, false) - .withConstantFeature(AuthorIsDeactivated, false) - .withConstantFeature(AuthorIsErased, false) - .withConstantFeature(AuthorIsOffboarded, false) - .withConstantFeature(AuthorTakedownReasons, Seq.empty) - .withConstantFeature(AuthorHasDefaultProfileImage, false) - .withConstantFeature(AuthorAccountAge, Duration.Zero) - .withConstantFeature(AuthorIsNsfwUser, false) - .withConstantFeature(AuthorIsNsfwAdmin, false) - .withConstantFeature(AuthorIsVerified, false) - .withConstantFeature(AuthorIsBlueVerified, false) - } - - def authorUserLabels(author: User): Seq[Label] = - authorUserLabels(author.labels) - - def authorIsSuspended(authorId: Long): Stitch[Boolean] = - userSource.getSafety(authorId).map(safety => authorIsSuspended(Some(safety))) - - def authorIsSuspendedOpt(author: User): Option[Boolean] = { - authorIsSuspended.incr() - author.safety.map(_.suspended) - } - - private def authorIsSuspended(safety: Option[Safety]): Boolean = { - authorIsSuspended.incr() - safety.exists(_.suspended) - } - - def authorIsProtected(author: User): Boolean = - authorIsProtected(author.safety) - - def authorIsDeactivated(authorId: Long): Stitch[Boolean] = - userSource.getSafety(authorId).map(safety => authorIsDeactivated(Some(safety))) - - def authorIsDeactivatedOpt(author: User): Option[Boolean] = { - authorIsDeactivated.incr() - author.safety.map(_.deactivated) - } - - private def authorIsDeactivated(safety: Option[Safety]): Boolean = { - authorIsDeactivated.incr() - safety.exists(_.deactivated) - } - - def authorIsErased(author: User): Boolean = { - authorIsErased.incr() - author.safety.exists(_.erased) - } - - def authorIsOffboarded(authorId: Long): Stitch[Boolean] = { - userSource.getSafety(authorId).map(safety => authorIsOffboarded(Some(safety))) - } - - def authorIsNsfwUser(author: User): Boolean = { - authorIsNsfwUser(author.safety) - } - - def authorIsNsfwUser(authorId: Long): Stitch[Boolean] = { - userSource.getSafety(authorId).map(safety => authorIsNsfwUser(Some(safety))) - } - - def authorIsNsfwUser(safety: Option[Safety]): Boolean = { - authorIsNsfwUser.incr() - safety.exists(_.nsfwUser) - } - - def authorIsNsfwAdminOpt(author: User): Option[Boolean] = { - authorIsNsfwAdmin.incr() - author.safety.map(_.nsfwAdmin) - } - - def authorTakedownReasons(authorId: Long): Stitch[Seq[TakedownReason]] = { - authorTakedownReasons.incr() - userSource.getTakedownReasons(authorId) - } - - def authorHasDefaultProfileImage(authorId: Long): Stitch[Boolean] = - userSource.getProfile(authorId).map(profile => authorHasDefaultProfileImage(Some(profile))) - - def authorAccountAge(authorId: Long): Stitch[Duration] = - userSource.getCreatedAtMsec(authorId).map(authorAccountAgeFromTimestamp) - - def authorIsVerified(authorId: Long): Stitch[Boolean] = - userSource.getSafety(authorId).map(safety => authorIsVerified(Some(safety))) - - def authorIsVerifiedOpt(author: User): Option[Boolean] = { - authorIsVerified.incr() - author.safety.map(_.verified) - } - - private def authorIsVerified(safety: Option[Safety]): Boolean = { - authorIsVerified.incr() - safety.exists(_.verified) - } - - def authorScreenName(author: User): Option[String] = { - authorScreenName.incr() - author.profile.map(_.screenName) - } - - def authorScreenName(authorId: Long): Stitch[String] = { - authorScreenName.incr() - userSource.getProfile(authorId).map(profile => profile.screenName) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/BUILD deleted file mode 100644 index 9da789b38..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/BUILD +++ /dev/null @@ -1,22 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "src/scala/com/twitter/search/blender/services/strato", - "src/thrift/com/twitter/content-health/sensitivemediasettings:sensitivemediasettings-scala", - "src/thrift/com/twitter/gizmoduck:user-thrift-scala", - "stitch/stitch-core", - "visibility/common/src/main/scala/com/twitter/visibility/common", - "visibility/common/src/main/scala/com/twitter/visibility/common/user_result", - "visibility/common/src/main/thrift/com/twitter/visibility:action-scala", - "visibility/lib/src/main/resources/config", - "visibility/lib/src/main/scala/com/twitter/visibility", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/interfaces/common/blender", - "visibility/lib/src/main/scala/com/twitter/visibility/interfaces/common/search", - "visibility/lib/src/main/thrift/com/twitter/visibility/context:vf-context-scala", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/QuotedTweetFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/QuotedTweetFeatures.scala deleted file mode 100644 index aac96d26f..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/QuotedTweetFeatures.scala +++ /dev/null @@ -1,52 +0,0 @@ -package com.twitter.visibility.builder.users - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.features.AuthorBlocksOuterAuthor -import com.twitter.visibility.features.OuterAuthorFollowsAuthor -import com.twitter.visibility.features.OuterAuthorId -import com.twitter.visibility.features.OuterAuthorIsInnerAuthor - -class QuotedTweetFeatures( - relationshipFeatures: RelationshipFeatures, - statsReceiver: StatsReceiver) { - - private[this] val scopedStatsReceiver = statsReceiver.scope("quoted_tweet_features") - - private[this] val requests = scopedStatsReceiver.counter("requests") - - private[this] val outerAuthorIdStat = - scopedStatsReceiver.scope(OuterAuthorId.name).counter("requests") - private[this] val authorBlocksOuterAuthor = - scopedStatsReceiver.scope(AuthorBlocksOuterAuthor.name).counter("requests") - private[this] val outerAuthorFollowsAuthor = - scopedStatsReceiver.scope(OuterAuthorFollowsAuthor.name).counter("requests") - private[this] val outerAuthorIsInnerAuthor = - scopedStatsReceiver.scope(OuterAuthorIsInnerAuthor.name).counter("requests") - - def forOuterAuthor( - outerAuthorId: Long, - innerAuthorId: Long - ): FeatureMapBuilder => FeatureMapBuilder = { - requests.incr() - - outerAuthorIdStat.incr() - authorBlocksOuterAuthor.incr() - outerAuthorFollowsAuthor.incr() - outerAuthorIsInnerAuthor.incr() - - val viewer = Some(outerAuthorId) - - _.withConstantFeature(OuterAuthorId, outerAuthorId) - .withFeature( - AuthorBlocksOuterAuthor, - relationshipFeatures.authorBlocksViewer(innerAuthorId, viewer)) - .withFeature( - OuterAuthorFollowsAuthor, - relationshipFeatures.viewerFollowsAuthor(innerAuthorId, viewer)) - .withConstantFeature( - OuterAuthorIsInnerAuthor, - innerAuthorId == outerAuthorId - ) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/RelationshipFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/RelationshipFeatures.scala deleted file mode 100644 index 9795e9408..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/RelationshipFeatures.scala +++ /dev/null @@ -1,176 +0,0 @@ -package com.twitter.visibility.builder.users - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.gizmoduck.thriftscala.User -import com.twitter.stitch.Stitch -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.common.UserId -import com.twitter.visibility.common.UserRelationshipSource -import com.twitter.visibility.features._ - -class RelationshipFeatures( - userRelationshipSource: UserRelationshipSource, - statsReceiver: StatsReceiver) { - - private[this] val scopedStatsReceiver = statsReceiver.scope("relationship_features") - - private[this] val requests = scopedStatsReceiver.counter("requests") - - private[this] val authorFollowsViewer = - scopedStatsReceiver.scope(AuthorFollowsViewer.name).counter("requests") - private[this] val viewerFollowsAuthor = - scopedStatsReceiver.scope(ViewerFollowsAuthor.name).counter("requests") - private[this] val authorBlocksViewer = - scopedStatsReceiver.scope(AuthorBlocksViewer.name).counter("requests") - private[this] val viewerBlocksAuthor = - scopedStatsReceiver.scope(ViewerBlocksAuthor.name).counter("requests") - private[this] val authorMutesViewer = - scopedStatsReceiver.scope(AuthorMutesViewer.name).counter("requests") - private[this] val viewerMutesAuthor = - scopedStatsReceiver.scope(ViewerMutesAuthor.name).counter("requests") - private[this] val authorHasReportedViewer = - scopedStatsReceiver.scope(AuthorReportsViewerAsSpam.name).counter("requests") - private[this] val viewerHasReportedAuthor = - scopedStatsReceiver.scope(ViewerReportsAuthorAsSpam.name).counter("requests") - private[this] val viewerMutesRetweetsFromAuthor = - scopedStatsReceiver.scope(ViewerMutesRetweetsFromAuthor.name).counter("requests") - - def forAuthorId( - authorId: Long, - viewerId: Option[Long] - ): FeatureMapBuilder => FeatureMapBuilder = { - requests.incr() - - _.withFeature(AuthorFollowsViewer, authorFollowsViewer(authorId, viewerId)) - .withFeature(ViewerFollowsAuthor, viewerFollowsAuthor(authorId, viewerId)) - .withFeature(AuthorBlocksViewer, authorBlocksViewer(authorId, viewerId)) - .withFeature(ViewerBlocksAuthor, viewerBlocksAuthor(authorId, viewerId)) - .withFeature(AuthorMutesViewer, authorMutesViewer(authorId, viewerId)) - .withFeature(ViewerMutesAuthor, viewerMutesAuthor(authorId, viewerId)) - .withFeature(AuthorReportsViewerAsSpam, authorHasReportedViewer(authorId, viewerId)) - .withFeature(ViewerReportsAuthorAsSpam, viewerHasReportedAuthor(authorId, viewerId)) - .withFeature(ViewerMutesRetweetsFromAuthor, viewerMutesRetweetsFromAuthor(authorId, viewerId)) - } - - def forNoAuthor(): FeatureMapBuilder => FeatureMapBuilder = { - _.withConstantFeature(AuthorFollowsViewer, false) - .withConstantFeature(ViewerFollowsAuthor, false) - .withConstantFeature(AuthorBlocksViewer, false) - .withConstantFeature(ViewerBlocksAuthor, false) - .withConstantFeature(AuthorMutesViewer, false) - .withConstantFeature(ViewerMutesAuthor, false) - .withConstantFeature(AuthorReportsViewerAsSpam, false) - .withConstantFeature(ViewerReportsAuthorAsSpam, false) - .withConstantFeature(ViewerMutesRetweetsFromAuthor, false) - } - - def forAuthor(author: User, viewerId: Option[Long]): FeatureMapBuilder => FeatureMapBuilder = { - requests.incr() - - - _.withFeature(AuthorFollowsViewer, authorFollowsViewer(author, viewerId)) - .withFeature(ViewerFollowsAuthor, viewerFollowsAuthor(author, viewerId)) - .withFeature(AuthorBlocksViewer, authorBlocksViewer(author, viewerId)) - .withFeature(ViewerBlocksAuthor, viewerBlocksAuthor(author, viewerId)) - .withFeature(AuthorMutesViewer, authorMutesViewer(author, viewerId)) - .withFeature(ViewerMutesAuthor, viewerMutesAuthor(author, viewerId)) - .withFeature(AuthorReportsViewerAsSpam, authorHasReportedViewer(author.id, viewerId)) - .withFeature(ViewerReportsAuthorAsSpam, viewerHasReportedAuthor(author.id, viewerId)) - .withFeature(ViewerMutesRetweetsFromAuthor, viewerMutesRetweetsFromAuthor(author, viewerId)) - } - - def viewerFollowsAuthor(authorId: UserId, viewerId: Option[UserId]): Stitch[Boolean] = - ViewerVerbsAuthor(authorId, viewerId, userRelationshipSource.follows, viewerFollowsAuthor) - - def viewerFollowsAuthor(author: User, viewerId: Option[UserId]): Stitch[Boolean] = - ViewerVerbsAuthor( - author, - viewerId, - p => p.following, - userRelationshipSource.follows, - viewerFollowsAuthor) - - def authorFollowsViewer(authorId: UserId, viewerId: Option[UserId]): Stitch[Boolean] = - AuthorVerbsViewer(authorId, viewerId, userRelationshipSource.follows, authorFollowsViewer) - - def authorFollowsViewer(author: User, viewerId: Option[UserId]): Stitch[Boolean] = - AuthorVerbsViewer( - author, - viewerId, - p => p.followedBy, - userRelationshipSource.follows, - authorFollowsViewer) - - def viewerBlocksAuthor(authorId: UserId, viewerId: Option[UserId]): Stitch[Boolean] = - ViewerVerbsAuthor(authorId, viewerId, userRelationshipSource.blocks, viewerBlocksAuthor) - - def viewerBlocksAuthor(author: User, viewerId: Option[UserId]): Stitch[Boolean] = - ViewerVerbsAuthor( - author, - viewerId, - p => p.blocking, - userRelationshipSource.blocks, - viewerBlocksAuthor) - - def authorBlocksViewer(authorId: UserId, viewerId: Option[UserId]): Stitch[Boolean] = - ViewerVerbsAuthor(authorId, viewerId, userRelationshipSource.blockedBy, authorBlocksViewer) - - def authorBlocksViewer(author: User, viewerId: Option[UserId]): Stitch[Boolean] = - ViewerVerbsAuthor( - author, - viewerId, - p => p.blockedBy, - userRelationshipSource.blockedBy, - authorBlocksViewer) - - def viewerMutesAuthor(authorId: UserId, viewerId: Option[UserId]): Stitch[Boolean] = - ViewerVerbsAuthor(authorId, viewerId, userRelationshipSource.mutes, viewerMutesAuthor) - - def viewerMutesAuthor(author: User, viewerId: Option[UserId]): Stitch[Boolean] = - ViewerVerbsAuthor( - author, - viewerId, - p => p.muting, - userRelationshipSource.mutes, - viewerMutesAuthor) - - def authorMutesViewer(authorId: UserId, viewerId: Option[UserId]): Stitch[Boolean] = - ViewerVerbsAuthor(authorId, viewerId, userRelationshipSource.mutedBy, authorMutesViewer) - - def authorMutesViewer(author: User, viewerId: Option[UserId]): Stitch[Boolean] = - ViewerVerbsAuthor( - author, - viewerId, - p => p.mutedBy, - userRelationshipSource.mutedBy, - authorMutesViewer) - - def viewerHasReportedAuthor(authorId: UserId, viewerId: Option[UserId]): Stitch[Boolean] = - ViewerVerbsAuthor( - authorId, - viewerId, - userRelationshipSource.reportsAsSpam, - viewerHasReportedAuthor) - - def authorHasReportedViewer(authorId: UserId, viewerId: Option[UserId]): Stitch[Boolean] = - ViewerVerbsAuthor( - authorId, - viewerId, - userRelationshipSource.reportedAsSpamBy, - authorHasReportedViewer) - - def viewerMutesRetweetsFromAuthor(authorId: UserId, viewerId: Option[UserId]): Stitch[Boolean] = - ViewerVerbsAuthor( - authorId, - viewerId, - userRelationshipSource.noRetweetsFrom, - viewerMutesRetweetsFromAuthor) - - def viewerMutesRetweetsFromAuthor(author: User, viewerId: Option[UserId]): Stitch[Boolean] = - ViewerVerbsAuthor( - author, - viewerId, - p => p.noRetweetsFrom, - userRelationshipSource.noRetweetsFrom, - viewerMutesRetweetsFromAuthor) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/RelationshipVerbHelpers.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/RelationshipVerbHelpers.scala deleted file mode 100644 index 0e654a69f..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/RelationshipVerbHelpers.scala +++ /dev/null @@ -1,79 +0,0 @@ -package com.twitter.visibility.builder.users - -import com.twitter.finagle.stats.Counter -import com.twitter.gizmoduck.thriftscala.Perspective -import com.twitter.gizmoduck.thriftscala.User -import com.twitter.stitch.Stitch -import com.twitter.visibility.common.UserId - -case object ViewerVerbsAuthor { - def apply( - authorId: UserId, - viewerIdOpt: Option[UserId], - relationship: (UserId, UserId) => Stitch[Boolean], - relationshipCounter: Counter - ): Stitch[Boolean] = { - relationshipCounter.incr() - - viewerIdOpt match { - case Some(viewerId) => relationship(viewerId, authorId) - case _ => Stitch.False - } - } - - def apply( - author: User, - viewerId: Option[UserId], - checkPerspective: Perspective => Option[Boolean], - relationship: (UserId, UserId) => Stitch[Boolean], - relationshipCounter: Counter - ): Stitch[Boolean] = { - author.perspective match { - case Some(perspective) => - checkPerspective(perspective) match { - case Some(status) => - relationshipCounter.incr() - Stitch.value(status) - case None => - ViewerVerbsAuthor(author.id, viewerId, relationship, relationshipCounter) - } - case None => ViewerVerbsAuthor(author.id, viewerId, relationship, relationshipCounter) - } - } -} - -case object AuthorVerbsViewer { - - def apply( - authorId: UserId, - viewerIdOpt: Option[UserId], - relationship: (UserId, UserId) => Stitch[Boolean], - relationshipCounter: Counter - ): Stitch[Boolean] = { - relationshipCounter.incr() - - viewerIdOpt match { - case Some(viewerId) => relationship(authorId, viewerId) - case _ => Stitch.False - } - } - def apply( - author: User, - viewerId: Option[UserId], - checkPerspective: Perspective => Option[Boolean], - relationship: (UserId, UserId) => Stitch[Boolean], - relationshipCounter: Counter - ): Stitch[Boolean] = { - author.perspective match { - case Some(perspective) => - checkPerspective(perspective) match { - case Some(status) => - relationshipCounter.incr() - Stitch.value(status) - case None => - AuthorVerbsViewer(author.id, viewerId, relationship, relationshipCounter) - } - case None => AuthorVerbsViewer(author.id, viewerId, relationship, relationshipCounter) - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/SearchFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/SearchFeatures.scala deleted file mode 100644 index 7602f2788..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/SearchFeatures.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.visibility.builder.users - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.features._ -import com.twitter.visibility.context.thriftscala.SearchContext - -class SearchFeatures(statsReceiver: StatsReceiver) { - private[this] val scopedStatsReceiver = statsReceiver.scope("search_features") - private[this] val requests = scopedStatsReceiver.counter("requests") - private[this] val rawQueryCounter = - scopedStatsReceiver.scope(RawQuery.name).counter("requests") - - def forSearchContext( - searchContext: Option[SearchContext] - ): FeatureMapBuilder => FeatureMapBuilder = { builder => - requests.incr() - searchContext match { - case Some(context: SearchContext) => - rawQueryCounter.incr() - builder - .withConstantFeature(RawQuery, context.rawQuery) - case _ => builder - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/UserUnavailableFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/UserUnavailableFeatures.scala deleted file mode 100644 index 4a196fe5f..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/UserUnavailableFeatures.scala +++ /dev/null @@ -1,145 +0,0 @@ -package com.twitter.visibility.builder.users - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.common.user_result.UserVisibilityResultHelper -import com.twitter.visibility.features.AuthorBlocksViewer -import com.twitter.visibility.features.AuthorIsDeactivated -import com.twitter.visibility.features.AuthorIsErased -import com.twitter.visibility.features.AuthorIsOffboarded -import com.twitter.visibility.features.AuthorIsProtected -import com.twitter.visibility.features.AuthorIsSuspended -import com.twitter.visibility.features.AuthorIsUnavailable -import com.twitter.visibility.features.ViewerBlocksAuthor -import com.twitter.visibility.features.ViewerMutesAuthor -import com.twitter.visibility.models.UserUnavailableStateEnum - -case class UserUnavailableFeatures(statsReceiver: StatsReceiver) { - - private[this] val scopedStatsReceiver = statsReceiver.scope("user_unavailable_features") - private[this] val suspendedAuthorStats = scopedStatsReceiver.scope("suspended_author") - private[this] val deactivatedAuthorStats = scopedStatsReceiver.scope("deactivated_author") - private[this] val offboardedAuthorStats = scopedStatsReceiver.scope("offboarded_author") - private[this] val erasedAuthorStats = scopedStatsReceiver.scope("erased_author") - private[this] val protectedAuthorStats = scopedStatsReceiver.scope("protected_author") - private[this] val authorBlocksViewerStats = scopedStatsReceiver.scope("author_blocks_viewer") - private[this] val viewerBlocksAuthorStats = scopedStatsReceiver.scope("viewer_blocks_author") - private[this] val viewerMutesAuthorStats = scopedStatsReceiver.scope("viewer_mutes_author") - private[this] val unavailableStats = scopedStatsReceiver.scope("unavailable") - - def forState(state: UserUnavailableStateEnum): FeatureMapBuilder => FeatureMapBuilder = { - builder => - builder - .withConstantFeature(AuthorIsSuspended, isSuspended(state)) - .withConstantFeature(AuthorIsDeactivated, isDeactivated(state)) - .withConstantFeature(AuthorIsOffboarded, isOffboarded(state)) - .withConstantFeature(AuthorIsErased, isErased(state)) - .withConstantFeature(AuthorIsProtected, isProtected(state)) - .withConstantFeature(AuthorBlocksViewer, authorBlocksViewer(state)) - .withConstantFeature(ViewerBlocksAuthor, viewerBlocksAuthor(state)) - .withConstantFeature(ViewerMutesAuthor, viewerMutesAuthor(state)) - .withConstantFeature(AuthorIsUnavailable, isUnavailable(state)) - } - - private[this] def isSuspended(state: UserUnavailableStateEnum): Boolean = - state match { - case UserUnavailableStateEnum.Suspended => - suspendedAuthorStats.counter().incr() - true - case UserUnavailableStateEnum.Filtered(result) - if UserVisibilityResultHelper.isDropSuspendedAuthor(result) => - suspendedAuthorStats.counter().incr() - suspendedAuthorStats.counter("filtered").incr() - true - case _ => false - } - - private[this] def isDeactivated(state: UserUnavailableStateEnum): Boolean = - state match { - case UserUnavailableStateEnum.Deactivated => - deactivatedAuthorStats.counter().incr() - true - case _ => false - } - - private[this] def isOffboarded(state: UserUnavailableStateEnum): Boolean = - state match { - case UserUnavailableStateEnum.Offboarded => - offboardedAuthorStats.counter().incr() - true - case _ => false - } - - private[this] def isErased(state: UserUnavailableStateEnum): Boolean = - state match { - case UserUnavailableStateEnum.Erased => - erasedAuthorStats.counter().incr() - true - case _ => false - } - - private[this] def isProtected(state: UserUnavailableStateEnum): Boolean = - state match { - case UserUnavailableStateEnum.Protected => - protectedAuthorStats.counter().incr() - true - case UserUnavailableStateEnum.Filtered(result) - if UserVisibilityResultHelper.isDropProtectedAuthor(result) => - protectedAuthorStats.counter().incr() - protectedAuthorStats.counter("filtered").incr() - true - case _ => false - } - - private[this] def authorBlocksViewer(state: UserUnavailableStateEnum): Boolean = - state match { - case UserUnavailableStateEnum.AuthorBlocksViewer => - authorBlocksViewerStats.counter().incr() - true - case UserUnavailableStateEnum.Filtered(result) - if UserVisibilityResultHelper.isDropAuthorBlocksViewer(result) => - authorBlocksViewerStats.counter().incr() - authorBlocksViewerStats.counter("filtered").incr() - true - case _ => false - } - - private[this] def viewerBlocksAuthor(state: UserUnavailableStateEnum): Boolean = - state match { - case UserUnavailableStateEnum.ViewerBlocksAuthor => - viewerBlocksAuthorStats.counter().incr() - true - case UserUnavailableStateEnum.Filtered(result) - if UserVisibilityResultHelper.isDropViewerBlocksAuthor(result) => - viewerBlocksAuthorStats.counter().incr() - viewerBlocksAuthorStats.counter("filtered").incr() - true - case _ => false - } - - private[this] def viewerMutesAuthor(state: UserUnavailableStateEnum): Boolean = - state match { - case UserUnavailableStateEnum.ViewerMutesAuthor => - viewerMutesAuthorStats.counter().incr() - true - case UserUnavailableStateEnum.Filtered(result) - if UserVisibilityResultHelper.isDropViewerMutesAuthor(result) => - viewerMutesAuthorStats.counter().incr() - viewerMutesAuthorStats.counter("filtered").incr() - true - case _ => false - } - - private[this] def isUnavailable(state: UserUnavailableStateEnum): Boolean = - state match { - case UserUnavailableStateEnum.Unavailable => - unavailableStats.counter().incr() - true - case UserUnavailableStateEnum.Filtered(result) - if UserVisibilityResultHelper.isDropUnspecifiedAuthor(result) => - unavailableStats.counter().incr() - unavailableStats.counter("filtered").incr() - true - case _ => false - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/ViewerAdvancedFilteringFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/ViewerAdvancedFilteringFeatures.scala deleted file mode 100644 index 38b3106f0..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/ViewerAdvancedFilteringFeatures.scala +++ /dev/null @@ -1,92 +0,0 @@ -package com.twitter.visibility.builder.users - -import com.twitter.finagle.stats.Counter -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.gizmoduck.thriftscala.AdvancedFilters -import com.twitter.gizmoduck.thriftscala.MentionFilter -import com.twitter.stitch.NotFound -import com.twitter.stitch.Stitch -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.common.UserSource -import com.twitter.visibility.features.ViewerFiltersDefaultProfileImage -import com.twitter.visibility.features.ViewerFiltersNewUsers -import com.twitter.visibility.features.ViewerFiltersNoConfirmedEmail -import com.twitter.visibility.features.ViewerFiltersNoConfirmedPhone -import com.twitter.visibility.features.ViewerFiltersNotFollowedBy -import com.twitter.visibility.features.ViewerMentionFilter - -class ViewerAdvancedFilteringFeatures(userSource: UserSource, statsReceiver: StatsReceiver) { - private[this] val scopedStatsReceiver = statsReceiver.scope("viewer_advanced_filtering_features") - - private[this] val requests = scopedStatsReceiver.counter("requests") - - private[this] val viewerFiltersNoConfirmedEmail = - scopedStatsReceiver.scope(ViewerFiltersNoConfirmedEmail.name).counter("requests") - private[this] val viewerFiltersNoConfirmedPhone = - scopedStatsReceiver.scope(ViewerFiltersNoConfirmedPhone.name).counter("requests") - private[this] val viewerFiltersDefaultProfileImage = - scopedStatsReceiver.scope(ViewerFiltersDefaultProfileImage.name).counter("requests") - private[this] val viewerFiltersNewUsers = - scopedStatsReceiver.scope(ViewerFiltersNewUsers.name).counter("requests") - private[this] val viewerFiltersNotFollowedBy = - scopedStatsReceiver.scope(ViewerFiltersNotFollowedBy.name).counter("requests") - private[this] val viewerMentionFilter = - scopedStatsReceiver.scope(ViewerMentionFilter.name).counter("requests") - - def forViewerId(viewerId: Option[Long]): FeatureMapBuilder => FeatureMapBuilder = { - requests.incr() - - _.withFeature(ViewerFiltersNoConfirmedEmail, viewerFiltersNoConfirmedEmail(viewerId)) - .withFeature(ViewerFiltersNoConfirmedPhone, viewerFiltersNoConfirmedPhone(viewerId)) - .withFeature(ViewerFiltersDefaultProfileImage, viewerFiltersDefaultProfileImage(viewerId)) - .withFeature(ViewerFiltersNewUsers, viewerFiltersNewUsers(viewerId)) - .withFeature(ViewerFiltersNotFollowedBy, viewerFiltersNotFollowedBy(viewerId)) - .withFeature(ViewerMentionFilter, viewerMentionFilter(viewerId)) - } - - def viewerFiltersNoConfirmedEmail(viewerId: Option[Long]): Stitch[Boolean] = - viewerAdvancedFilters(viewerId, af => af.filterNoConfirmedEmail, viewerFiltersNoConfirmedEmail) - - def viewerFiltersNoConfirmedPhone(viewerId: Option[Long]): Stitch[Boolean] = - viewerAdvancedFilters(viewerId, af => af.filterNoConfirmedPhone, viewerFiltersNoConfirmedPhone) - - def viewerFiltersDefaultProfileImage(viewerId: Option[Long]): Stitch[Boolean] = - viewerAdvancedFilters( - viewerId, - af => af.filterDefaultProfileImage, - viewerFiltersDefaultProfileImage - ) - - def viewerFiltersNewUsers(viewerId: Option[Long]): Stitch[Boolean] = - viewerAdvancedFilters(viewerId, af => af.filterNewUsers, viewerFiltersNewUsers) - - def viewerFiltersNotFollowedBy(viewerId: Option[Long]): Stitch[Boolean] = - viewerAdvancedFilters(viewerId, af => af.filterNotFollowedBy, viewerFiltersNotFollowedBy) - - def viewerMentionFilter(viewerId: Option[Long]): Stitch[MentionFilter] = { - viewerMentionFilter.incr() - viewerId match { - case Some(id) => - userSource.getMentionFilter(id).handle { - case NotFound => - MentionFilter.Unfiltered - } - case _ => Stitch.value(MentionFilter.Unfiltered) - } - } - - private[this] def viewerAdvancedFilters( - viewerId: Option[Long], - advancedFilterCheck: AdvancedFilters => Boolean, - featureCounter: Counter - ): Stitch[Boolean] = { - featureCounter.incr() - - val advancedFilters = viewerId match { - case Some(id) => userSource.getAdvancedFilters(id) - case _ => Stitch.value(AdvancedFilters()) - } - - advancedFilters.map(advancedFilterCheck) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/ViewerFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/ViewerFeatures.scala deleted file mode 100644 index 4e97ce5d4..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/ViewerFeatures.scala +++ /dev/null @@ -1,245 +0,0 @@ -package com.twitter.visibility.builder.users - -import com.twitter.finagle.stats.Counter -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.gizmoduck.thriftscala.Label -import com.twitter.gizmoduck.thriftscala.Safety -import com.twitter.gizmoduck.thriftscala.UniversalQualityFiltering -import com.twitter.gizmoduck.thriftscala.User -import com.twitter.gizmoduck.thriftscala.UserType -import com.twitter.stitch.NotFound -import com.twitter.stitch.Stitch -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.common.UserId -import com.twitter.visibility.common.UserSource -import com.twitter.visibility.features._ -import com.twitter.visibility.interfaces.common.blender.BlenderVFRequestContext -import com.twitter.visibility.interfaces.common.search.SearchVFRequestContext -import com.twitter.visibility.models.UserAge -import com.twitter.visibility.models.ViewerContext - -class ViewerFeatures(userSource: UserSource, statsReceiver: StatsReceiver) { - private[this] val scopedStatsReceiver = statsReceiver.scope("viewer_features") - - private[this] val requests = scopedStatsReceiver.counter("requests") - - private[this] val viewerIdCount = - scopedStatsReceiver.scope(ViewerId.name).counter("requests") - private[this] val requestCountryCode = - scopedStatsReceiver.scope(RequestCountryCode.name).counter("requests") - private[this] val requestIsVerifiedCrawler = - scopedStatsReceiver.scope(RequestIsVerifiedCrawler.name).counter("requests") - private[this] val viewerUserLabels = - scopedStatsReceiver.scope(ViewerUserLabels.name).counter("requests") - private[this] val viewerIsDeactivated = - scopedStatsReceiver.scope(ViewerIsDeactivated.name).counter("requests") - private[this] val viewerIsProtected = - scopedStatsReceiver.scope(ViewerIsProtected.name).counter("requests") - private[this] val viewerIsSuspended = - scopedStatsReceiver.scope(ViewerIsSuspended.name).counter("requests") - private[this] val viewerRoles = - scopedStatsReceiver.scope(ViewerRoles.name).counter("requests") - private[this] val viewerCountryCode = - scopedStatsReceiver.scope(ViewerCountryCode.name).counter("requests") - private[this] val viewerAge = - scopedStatsReceiver.scope(ViewerAge.name).counter("requests") - private[this] val viewerHasUniversalQualityFilterEnabled = - scopedStatsReceiver.scope(ViewerHasUniversalQualityFilterEnabled.name).counter("requests") - private[this] val viewerIsSoftUserCtr = - scopedStatsReceiver.scope(ViewerIsSoftUser.name).counter("requests") - - def forViewerBlenderContext( - blenderContext: BlenderVFRequestContext, - viewerContext: ViewerContext - ): FeatureMapBuilder => FeatureMapBuilder = - forViewerContext(viewerContext) - .andThen( - _.withConstantFeature( - ViewerOptInBlocking, - blenderContext.userSearchSafetySettings.optInBlocking) - .withConstantFeature( - ViewerOptInFiltering, - blenderContext.userSearchSafetySettings.optInFiltering) - ) - - def forViewerSearchContext( - searchContext: SearchVFRequestContext, - viewerContext: ViewerContext - ): FeatureMapBuilder => FeatureMapBuilder = - forViewerContext(viewerContext) - .andThen( - _.withConstantFeature( - ViewerOptInBlocking, - searchContext.userSearchSafetySettings.optInBlocking) - .withConstantFeature( - ViewerOptInFiltering, - searchContext.userSearchSafetySettings.optInFiltering) - ) - - def forViewerContext(viewerContext: ViewerContext): FeatureMapBuilder => FeatureMapBuilder = - forViewerId(viewerContext.userId) - .andThen( - _.withConstantFeature(RequestCountryCode, requestCountryCode(viewerContext)) - ).andThen( - _.withConstantFeature(RequestIsVerifiedCrawler, requestIsVerifiedCrawler(viewerContext)) - ) - - def forViewerId(viewerId: Option[UserId]): FeatureMapBuilder => FeatureMapBuilder = { builder => - requests.incr() - - val builderWithFeatures = builder - .withConstantFeature(ViewerId, viewerId) - .withFeature(ViewerIsProtected, viewerIsProtected(viewerId)) - .withFeature( - ViewerHasUniversalQualityFilterEnabled, - viewerHasUniversalQualityFilterEnabled(viewerId) - ) - .withFeature(ViewerIsSuspended, viewerIsSuspended(viewerId)) - .withFeature(ViewerIsDeactivated, viewerIsDeactivated(viewerId)) - .withFeature(ViewerUserLabels, viewerUserLabels(viewerId)) - .withFeature(ViewerRoles, viewerRoles(viewerId)) - .withFeature(ViewerAge, viewerAgeInYears(viewerId)) - .withFeature(ViewerIsSoftUser, viewerIsSoftUser(viewerId)) - - viewerId match { - case Some(_) => - viewerIdCount.incr() - builderWithFeatures - .withFeature(ViewerCountryCode, viewerCountryCode(viewerId)) - - case _ => - builderWithFeatures - } - } - - def forViewerNoDefaults(viewerOpt: Option[User]): FeatureMapBuilder => FeatureMapBuilder = { - builder => - requests.incr() - - viewerOpt match { - case Some(viewer) => - builder - .withConstantFeature(ViewerId, viewer.id) - .withConstantFeature(ViewerIsProtected, viewerIsProtectedOpt(viewer)) - .withConstantFeature(ViewerIsSuspended, viewerIsSuspendedOpt(viewer)) - .withConstantFeature(ViewerIsDeactivated, viewerIsDeactivatedOpt(viewer)) - .withConstantFeature(ViewerCountryCode, viewerCountryCode(viewer)) - case None => - builder - .withConstantFeature(ViewerIsProtected, false) - .withConstantFeature(ViewerIsSuspended, false) - .withConstantFeature(ViewerIsDeactivated, false) - } - } - - private def checkSafetyValue( - viewerId: Option[UserId], - safetyCheck: Safety => Boolean, - featureCounter: Counter - ): Stitch[Boolean] = - viewerId match { - case Some(id) => - userSource.getSafety(id).map(safetyCheck).ensure { - featureCounter.incr() - } - case None => Stitch.False - } - - private def checkSafetyValue( - viewer: User, - safetyCheck: Safety => Boolean - ): Boolean = { - viewer.safety.exists(safetyCheck) - } - - def viewerIsProtected(viewerId: Option[UserId]): Stitch[Boolean] = - checkSafetyValue(viewerId, s => s.isProtected, viewerIsProtected) - - def viewerIsProtected(viewer: User): Boolean = - checkSafetyValue(viewer, s => s.isProtected) - - def viewerIsProtectedOpt(viewer: User): Option[Boolean] = - viewer.safety.map(_.isProtected) - - def viewerIsDeactivated(viewerId: Option[UserId]): Stitch[Boolean] = - checkSafetyValue(viewerId, s => s.deactivated, viewerIsDeactivated) - - def viewerIsDeactivated(viewer: User): Boolean = - checkSafetyValue(viewer, s => s.deactivated) - - def viewerIsDeactivatedOpt(viewer: User): Option[Boolean] = - viewer.safety.map(_.deactivated) - - def viewerHasUniversalQualityFilterEnabled(viewerId: Option[UserId]): Stitch[Boolean] = - checkSafetyValue( - viewerId, - s => s.universalQualityFiltering == UniversalQualityFiltering.Enabled, - viewerHasUniversalQualityFilterEnabled - ) - - def viewerUserLabels(viewerIdOpt: Option[UserId]): Stitch[Seq[Label]] = - viewerIdOpt match { - case Some(viewerId) => - userSource - .getLabels(viewerId).map(_.labels) - .handle { - case NotFound => Seq.empty - }.ensure { - viewerUserLabels.incr() - } - case _ => Stitch.value(Seq.empty) - } - - def viewerAgeInYears(viewerId: Option[UserId]): Stitch[UserAge] = - (viewerId match { - case Some(id) => - userSource - .getExtendedProfile(id).map(_.ageInYears) - .handle { - case NotFound => None - }.ensure { - viewerAge.incr() - } - case _ => Stitch.value(None) - }).map(UserAge) - - def viewerIsSoftUser(viewerId: Option[UserId]): Stitch[Boolean] = { - viewerId match { - case Some(id) => - userSource - .getUserType(id).map { userType => - userType == UserType.Soft - }.ensure { - viewerIsSoftUserCtr.incr() - } - case _ => Stitch.False - } - } - - def requestCountryCode(viewerContext: ViewerContext): Option[String] = { - requestCountryCode.incr() - viewerContext.requestCountryCode - } - - def requestIsVerifiedCrawler(viewerContext: ViewerContext): Boolean = { - requestIsVerifiedCrawler.incr() - viewerContext.isVerifiedCrawler - } - - def viewerCountryCode(viewerId: Option[UserId]): Stitch[String] = - viewerId match { - case Some(id) => - userSource - .getAccount(id).map(_.countryCode).flatMap { - case Some(countryCode) => Stitch.value(countryCode.toLowerCase) - case _ => Stitch.NotFound - }.ensure { - viewerCountryCode.incr() - } - - case _ => Stitch.NotFound - } - - def viewerCountryCode(viewer: User): Option[String] = - viewer.account.flatMap(_.countryCode) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/ViewerSearchSafetyFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/ViewerSearchSafetyFeatures.scala deleted file mode 100644 index 6cddcd74c..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/ViewerSearchSafetyFeatures.scala +++ /dev/null @@ -1,49 +0,0 @@ -package com.twitter.visibility.builder.users - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.stitch.Stitch -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.common.UserId -import com.twitter.visibility.common.UserSearchSafetySource -import com.twitter.visibility.features.ViewerId -import com.twitter.visibility.features.ViewerOptInBlocking -import com.twitter.visibility.features.ViewerOptInFiltering - -class ViewerSearchSafetyFeatures( - userSearchSafetySource: UserSearchSafetySource, - statsReceiver: StatsReceiver) { - private[this] val scopedStatsReceiver = statsReceiver.scope("viewer_search_safety_features") - - private[this] val requests = scopedStatsReceiver.counter("requests") - - private[this] val viewerOptInBlockingRequests = - scopedStatsReceiver.scope(ViewerOptInBlocking.name).counter("requests") - - private[this] val viewerOptInFilteringRequests = - scopedStatsReceiver.scope(ViewerOptInFiltering.name).counter("requests") - - def forViewerId(viewerId: Option[UserId]): FeatureMapBuilder => FeatureMapBuilder = { builder => - requests.incr() - - builder - .withConstantFeature(ViewerId, viewerId) - .withFeature(ViewerOptInBlocking, viewerOptInBlocking(viewerId)) - .withFeature(ViewerOptInFiltering, viewerOptInFiltering(viewerId)) - } - - def viewerOptInBlocking(viewerId: Option[UserId]): Stitch[Boolean] = { - viewerOptInBlockingRequests.incr() - viewerId match { - case Some(userId) => userSearchSafetySource.optInBlocking(userId) - case _ => Stitch.False - } - } - - def viewerOptInFiltering(viewerId: Option[UserId]): Stitch[Boolean] = { - viewerOptInFilteringRequests.incr() - viewerId match { - case Some(userId) => userSearchSafetySource.optInFiltering(userId) - case _ => Stitch.False - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/ViewerSensitiveMediaSettingsFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/ViewerSensitiveMediaSettingsFeatures.scala deleted file mode 100644 index 31b982886..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/builder/users/ViewerSensitiveMediaSettingsFeatures.scala +++ /dev/null @@ -1,41 +0,0 @@ -package com.twitter.visibility.builder.users - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.stitch.Stitch -import com.twitter.stitch.NotFound -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.common.UserId -import com.twitter.visibility.common.UserSensitiveMediaSettingsSource -import com.twitter.visibility.features.ViewerId -import com.twitter.visibility.features.ViewerSensitiveMediaSettings -import com.twitter.visibility.models.UserSensitiveMediaSettings - - -class ViewerSensitiveMediaSettingsFeatures( - userSensitiveMediaSettingsSource: UserSensitiveMediaSettingsSource, - statsReceiver: StatsReceiver) { - private[this] val scopedStatsReceiver = - statsReceiver.scope("viewer_sensitive_media_settings_features") - - private[this] val requests = scopedStatsReceiver.counter("requests") - - def forViewerId(viewerId: Option[UserId]): FeatureMapBuilder => FeatureMapBuilder = { builder => - requests.incr() - - builder - .withConstantFeature(ViewerId, viewerId) - .withFeature(ViewerSensitiveMediaSettings, viewerSensitiveMediaSettings(viewerId)) - } - - def viewerSensitiveMediaSettings(viewerId: Option[UserId]): Stitch[UserSensitiveMediaSettings] = { - (viewerId match { - case Some(userId) => - userSensitiveMediaSettingsSource - .userSensitiveMediaSettings(userId) - .handle { - case NotFound => None - } - case _ => Stitch.value(None) - }).map(UserSensitiveMediaSettings) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/configapi/BUILD deleted file mode 100644 index b0562b356..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/BUILD +++ /dev/null @@ -1,19 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "abdecider/src/main/scala", - "configapi/configapi-abdecider", - "configapi/configapi-core", - "configapi/configapi-featureswitches:v2", - "decider", - "featureswitches/featureswitches-core/src/main/scala", - "finagle/finagle-stats", - "servo/decider/src/main/scala", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/configs", - "visibility/lib/src/main/scala/com/twitter/visibility/models", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/ConfigBuilder.scala b/visibilitylib/src/main/scala/com/twitter/visibility/configapi/ConfigBuilder.scala deleted file mode 100644 index df634d400..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/ConfigBuilder.scala +++ /dev/null @@ -1,43 +0,0 @@ -package com.twitter.visibility.configapi - -import com.twitter.decider.Decider -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.logging.Logger -import com.twitter.servo.decider.DeciderGateBuilder -import com.twitter.timelines.configapi.CompositeConfig -import com.twitter.timelines.configapi.Config -import com.twitter.util.Memoize -import com.twitter.visibility.configapi.configs.VisibilityDeciders -import com.twitter.visibility.configapi.configs.VisibilityExperimentsConfig -import com.twitter.visibility.configapi.configs.VisibilityFeatureSwitches -import com.twitter.visibility.models.SafetyLevel - -object ConfigBuilder { - - def apply(statsReceiver: StatsReceiver, decider: Decider, logger: Logger): ConfigBuilder = { - val deciderGateBuilder: DeciderGateBuilder = - new DeciderGateBuilder(decider) - - new ConfigBuilder( - deciderGateBuilder, - statsReceiver, - logger - ) - } -} - -class ConfigBuilder( - deciderGateBuilder: DeciderGateBuilder, - statsReceiver: StatsReceiver, - logger: Logger) { - - def buildMemoized: SafetyLevel => Config = Memoize(build) - - def build(safetyLevel: SafetyLevel): Config = { - new CompositeConfig( - VisibilityExperimentsConfig.config(safetyLevel) :+ - VisibilityDeciders.config(deciderGateBuilder, logger, statsReceiver, safetyLevel) :+ - VisibilityFeatureSwitches.config(statsReceiver, logger) - ) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/VisibilityParams.scala b/visibilitylib/src/main/scala/com/twitter/visibility/configapi/VisibilityParams.scala deleted file mode 100644 index e45485b52..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/VisibilityParams.scala +++ /dev/null @@ -1,61 +0,0 @@ -package com.twitter.visibility.configapi - -import com.twitter.abdecider.LoggingABDecider -import com.twitter.decider.Decider -import com.twitter.featureswitches.v2.FeatureSwitches -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.logging.Logger -import com.twitter.servo.util.MemoizingStatsReceiver -import com.twitter.timelines.configapi.Params -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.UnitOfDiversion -import com.twitter.visibility.models.ViewerContext - -object VisibilityParams { - def apply( - log: Logger, - statsReceiver: StatsReceiver, - decider: Decider, - abDecider: LoggingABDecider, - featureSwitches: FeatureSwitches - ): VisibilityParams = - new VisibilityParams(log, statsReceiver, decider, abDecider, featureSwitches) -} - -class VisibilityParams( - log: Logger, - statsReceiver: StatsReceiver, - decider: Decider, - abDecider: LoggingABDecider, - featureSwitches: FeatureSwitches) { - - private[this] val contextFactory = new VisibilityRequestContextFactory( - abDecider, - featureSwitches - ) - - private[this] val configBuilder = ConfigBuilder(statsReceiver.scope("config"), decider, log) - - private[this] val paramStats: MemoizingStatsReceiver = new MemoizingStatsReceiver( - statsReceiver.scope("configapi_params")) - - def apply( - viewerContext: ViewerContext, - safetyLevel: SafetyLevel, - unitsOfDiversion: Seq[UnitOfDiversion] = Seq.empty - ): Params = { - val config = configBuilder.build(safetyLevel) - val requestContext = contextFactory(viewerContext, safetyLevel, unitsOfDiversion) - config.apply(requestContext, paramStats) - } - - def memoized( - viewerContext: ViewerContext, - safetyLevel: SafetyLevel, - unitsOfDiversion: Seq[UnitOfDiversion] = Seq.empty - ): Params = { - val config = configBuilder.buildMemoized(safetyLevel) - val requestContext = contextFactory(viewerContext, safetyLevel, unitsOfDiversion) - config.apply(requestContext, paramStats) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/VisibilityRequestContext.scala b/visibilitylib/src/main/scala/com/twitter/visibility/configapi/VisibilityRequestContext.scala deleted file mode 100644 index 9e9564392..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/VisibilityRequestContext.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.visibility.configapi - -import com.twitter.timelines.configapi._ - -case class VisibilityRequestContext( - userId: Option[Long], - guestId: Option[Long], - experimentContext: ExperimentContext = NullExperimentContext, - featureContext: FeatureContext = NullFeatureContext) - extends BaseRequestContext - with WithUserId - with WithGuestId - with WithExperimentContext - with WithFeatureContext diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/VisibilityRequestContextFactory.scala b/visibilitylib/src/main/scala/com/twitter/visibility/configapi/VisibilityRequestContextFactory.scala deleted file mode 100644 index 1d389d68e..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/VisibilityRequestContextFactory.scala +++ /dev/null @@ -1,64 +0,0 @@ -package com.twitter.visibility.configapi - -import com.twitter.abdecider.LoggingABDecider -import com.twitter.featureswitches.FSRecipient -import com.twitter.featureswitches.v2.FeatureSwitches -import com.twitter.timelines.configapi.abdecider.UserRecipientExperimentContextFactory -import com.twitter.timelines.configapi.featureswitches.v2.FeatureSwitchResultsFeatureContext -import com.twitter.timelines.configapi.FeatureContext -import com.twitter.timelines.configapi.NullExperimentContext -import com.twitter.timelines.configapi.UseFeatureContextExperimentContext -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.UnitOfDiversion -import com.twitter.visibility.models.ViewerContext - -class VisibilityRequestContextFactory( - loggingABDecider: LoggingABDecider, - featureSwitches: FeatureSwitches) { - private val userExperimentContextFactory = new UserRecipientExperimentContextFactory( - loggingABDecider - ) - private[this] def getFeatureContext( - context: ViewerContext, - safetyLevel: SafetyLevel, - unitsOfDiversion: Seq[UnitOfDiversion] - ): FeatureContext = { - val uodCustomFields = unitsOfDiversion.map(_.apply) - val recipient = FSRecipient( - userId = context.userId, - guestId = context.guestId, - userAgent = context.fsUserAgent, - clientApplicationId = context.clientApplicationId, - countryCode = context.requestCountryCode, - deviceId = context.deviceId, - languageCode = context.requestLanguageCode, - isTwoffice = Some(context.isTwOffice), - userRoles = context.userRoles, - ).withCustomFields(("safety_level", safetyLevel.name), uodCustomFields: _*) - - val results = featureSwitches.matchRecipient(recipient) - new FeatureSwitchResultsFeatureContext(results) - } - - def apply( - context: ViewerContext, - safetyLevel: SafetyLevel, - unitsOfDiversion: Seq[UnitOfDiversion] = Seq.empty - ): VisibilityRequestContext = { - val experimentContextBase = - context.userId - .map(userId => userExperimentContextFactory.apply(userId)).getOrElse(NullExperimentContext) - - val featureContext = getFeatureContext(context, safetyLevel, unitsOfDiversion) - - val experimentContext = - UseFeatureContextExperimentContext(experimentContextBase, featureContext) - - VisibilityRequestContext( - context.userId, - context.guestId, - experimentContext, - featureContext - ) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/BUILD deleted file mode 100644 index 89e1b7c83..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "configapi/configapi-core", - "configapi/configapi-decider", - "decider", - "finagle/finagle-stats", - "servo/decider", - "servo/decider/src/main/scala", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/params", - "visibility/lib/src/main/scala/com/twitter/visibility/models", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/DeciderKey.scala b/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/DeciderKey.scala deleted file mode 100644 index 58331779c..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/DeciderKey.scala +++ /dev/null @@ -1,1067 +0,0 @@ -package com.twitter.visibility.configapi.configs - -import com.twitter.servo.decider.DeciderKeyEnum - -private[visibility] object DeciderKey extends DeciderKeyEnum { - - val EnableAllSubscribedListsSafetyLevel: Value = Value( - "visibility_library_enable_all_subscribed_lists_safety_level" - ) - val EnableAdsBusinessSettingsSafetyLevel: Value = Value( - "visibility_library_enable_ads_business_settings_safety_level" - ) - val EnableAdsCampaignSafetyLevel: Value = Value( - "visibility_library_enable_ads_campaign_safety_level" - ) - val EnableAdsManagerSafetyLevel: Value = Value( - "visibility_library_enable_ads_manager_safety_level" - ) - val EnableAdsReportingDashboardSafetyLevel: Value = Value( - "visibility_library_enable_ads_reporting_dashboard_safety_level" - ) - val EnableAppealsSafetyLevel: Value = Value( - "visibility_library_enable_appeals_safety_level" - ) - val EnableArticleTweetTimelineSafetyLevel: Value = Value( - "visibility_library_enable_article_tweet_timeline_safety_level" - ) - val EnableBaseQig: Value = Value( - "visibility_library_enable_base_qig_safety_level" - ) - val EnableBirdwatchNoteAuthorSafetyLevel: Value = Value( - "visibility_library_enable_birdwatch_note_author_safety_level" - ) - val EnableBirdwatchNoteTweetsTimelineSafetyLevel: Value = Value( - "visibility_library_enable_birdwatch_note_tweets_timeline_safety_level" - ) - val EnableBirdwatchNeedsYourHelpNotificationsSafetyLevel: Value = Value( - "visibility_library_enable_birdwatch_needs_your_help_notifications_safety_level" - ) - val EnableBlockMuteUsersTimelineSafetyLevel: Value = Value( - "visibility_library_enable_block_mute_users_timeline_safety_level" - ) - val EnableBrandSafetySafetyLevel: Value = Value( - "visibility_library_enable_brand_safety_safety_level" - ) - val EnableCardPollVotingSafetyLevel: Value = Value( - "visibility_library_enable_card_poll_voting_safety_level" - ) - val EnableCardsServiceSafetyLevel: Value = Value( - "visibility_library_enable_cards_service_safety_level" - ) - val EnableCommunitiesSafetyLevel: Value = Value( - "visibility_library_enable_communities_safety_level" - ) - val EnableContentControlToolInstallSafetyLevel: Value = Value( - "visibility_library_enable_content_control_tool_install_safety_level" - ) - val EnableConversationFocalPrehydrationSafetyLevel: Value = Value( - "visibility_library_enable_conversation_focal_prehydration_safety_level" - ) - val EnableConversationFocalTweetSafetyLevel: Value = Value( - "visibility_library_enable_conversation_focal_tweet_safety_level" - ) - val EnableConversationInjectedTweetSafetyLevel: Value = Value( - "visibility_library_enable_conversation_injected_tweet_safety_level" - ) - val EnableConversationReplySafetyLevel: Value = Value( - "visibility_library_enable_conversation_reply_safety_level" - ) - val EnableCuratedTrendsRepresentativeTweet: Value = Value( - "visibility_library_curated_trends_representative_tweet" - ) - val EnableCurationPolicyViolations: Value = Value( - "visibility_library_curation_policy_violations" - ) - val EnableDeprecatedSafetyLevelSafetyLevel: Value = Value( - "visibility_library_enable_deprecated_safety_level_safety_level" - ) - val EnableDevPlatformGetListTweetsSafetyLevel: Value = Value( - "visibility_library_enable_dev_platform_get_list_tweets_safety_level" - ) - val EnableDesFollowingAndFollowersUserListSafetyLevel: Value = Value( - "visibility_library_enable_des_following_and_followers_user_list_safety_level" - ) - val EnableDesHomeTimelineSafetyLevel: Value = Value( - "visibility_library_enable_des_home_timeline_safety_level" - ) - val EnableDesQuoteTweetTimelineSafetyLevel: Value = Value( - "visibility_library_enable_des_quote_tweet_timeline_safety_level" - ) - val EnableDesRealtimeSafetyLevel: Value = Value( - "visibility_library_enable_des_realtime_safety_level" - ) - val EnableDesRealtimeSpamEnrichmentSafetyLevel: Value = Value( - "visibility_library_enable_des_realtime_spam_enrichment_safety_level" - ) - val EnableDesRealtimeTweetFilterSafetyLevel: Value = Value( - "visibility_library_enable_des_realtime_tweet_filter_safety_level" - ) - val EnableDesRetweetingUsersSafetyLevel: Value = Value( - "visibility_library_enable_des_retweeting_users_safety_level" - ) - val EnableDesTweetDetailSafetyLevel: Value = Value( - "visibility_library_enable_des_tweet_detail_safety_level" - ) - val EnableDesTweetLikingUsersSafetyLevel: Value = Value( - "visibility_library_enable_des_tweet_liking_users_safety_level" - ) - val EnableDesUserBookmarksSafetyLevel: Value = Value( - "visibility_library_enable_des_user_bookmarks_safety_level" - ) - val EnableDesUserLikedTweetsSafetyLevel: Value = Value( - "visibility_library_enable_des_user_liked_tweets_safety_level" - ) - val EnableDesUserMentionsSafetyLevel: Value = Value( - "visibility_library_enable_des_user_mentions_safety_level" - ) - val EnableDesUserTweetsSafetyLevel: Value = Value( - "visibility_library_enable_des_user_tweets_safety_level" - ) - val EnableDevPlatformComplianceStreamSafetyLevel: Value = Value( - "visibility_library_enable_dev_platform_compliance_stream_safety_level" - ) - val EnableDirectMessagesSafetyLevel: Value = Value( - "visibility_library_enable_direct_messages_safety_level" - ) - val EnableDirectMessagesConversationListSafetyLevel: Value = Value( - "visibility_library_enable_direct_messages_conversation_list_safety_level" - ) - val EnableDirectMessagesConversationTimelineSafetyLevel: Value = Value( - "visibility_library_enable_direct_messages_conversation_timeline_safety_level" - ) - val EnableDirectMessagesInboxSafetyLevel: Value = Value( - "visibility_library_enable_direct_messages_inbox_safety_level" - ) - val EnableDirectMessagesMutedUsersSafetyLevel: Value = Value( - "visibility_library_enable_direct_messages_muted_users_safety_level" - ) - val EnableDirectMessagesPinnedSafetyLevel: Value = Value( - "visibility_library_enable_direct_messages_pinned_safety_level" - ) - val EnableDirectMessagesSearchSafetyLevel: Value = Value( - "visibility_library_enable_direct_messages_search_safety_level" - ) - val EnableElevatedQuoteTweetTimelineSafetyLevel: Value = Value( - "visibility_library_enable_elevated_quote_tweet_timeline_safety_level" - ) - val EnableEmbeddedTweetSafetyLevel: Value = Value( - "visibility_library_enable_embedded_tweet_safety_level" - ) - val EnableEmbedsPublicInterestNoticeSafetyLevel: Value = Value( - "visibility_library_enable_embeds_public_interest_notice_safety_level" - ) - val EnableEmbedTweetMarkupSafetyLevel: Value = Value( - "visibility_library_enable_embed_tweet_markup_safety_level" - ) - val EnableWritePathLimitedActionsEnforcementSafetyLevel: Value = Value( - "visibility_library_enable_write_path_limited_actions_enforcement_safety_level" - ) - val EnableFilterDefaultSafetyLevel: Value = Value( - "visibility_library_enable_filter_default_safety_level" - ) - val EnableFilterNoneSafetyLevel: Value = Value( - "visibility_library_enable_filter_none_safety_level" - ) - - val EnableFilterAllSafetyLevel: Value = Value( - "visibility_library_enable_filter_all_safety_level" - ) - val EnableFilterAllPlaceholderSafetyLevel: Value = Value( - "visibility_library_enable_filter_all_placeholder_safety_level" - ) - - val EnableFollowedTopicsTimelineSafetyLevel: Value = Value( - "visibility_library_enable_followed_topics_timeline_safety_level" - ) - - val EnableFollowerConnectionsSafetyLevel: Value = Value( - "visibility_library_enable_follower_connections_safety_level" - ) - val EnableFollowingAndFollowersUserListSafetyLevel: Value = Value( - "visibility_library_enable_following_and_followers_user_list_safety_level" - ) - - val EnableForDevelopmentOnlySafetyLevel: Value = Value( - "visibility_library_enable_for_development_only_safety_level" - ) - - val EnableFriendsFollowingListSafetyLevel: Value = Value( - "visibility_library_enable_friends_following_list_safety_level" - ) - - val EnableGraphqlDefaultSafetyLevel: Value = Value( - "visibility_library_enable_graphql_default_safety_level" - ) - - val EnableGryphonDecksAndColumnsSafetyLevel: Value = Value( - "visibility_library_enable_gryphon_decks_and_columns_safety_level" - ) - - val EnableHumanizationNudgeSafetyLevel: Value = Value( - "visibility_library_enable_humanization_nudge_safety_level" - ) - - val EnableKitchenSinkDevelopmentSafetyLevel: Value = Value( - "visibility_library_enable_kitchen_sink_development_safety_level" - ) - - val EnableListHeaderSafetyLevel: Value = Value( - "visibility_library_enable_list_header_safety_level" - ) - - val EnableListMembershipsSafetyLevel: Value = Value( - "visibility_library_enable_list_memberships_safety_level" - ) - - val EnableListOwnershipsSafetyLevel: Value = Value( - "visibility_library_enable_list_ownerships_safety_level" - ) - - val EnableListRecommendationsSafetyLevel: Value = Value( - "visibility_library_enable_list_recommendations_safety_level" - ) - - val EnableListSearchSafetyLevel: Value = Value( - "visibility_library_enable_list_search_safety_level" - ) - - val EnableListSubscriptionsSafetyLevel: Value = Value( - "visibility_library_enable_list_subscriptions_safety_level" - ) - - val EnableLivePipelineEngagementCountsSafetyLevel: Value = Value( - "visibility_library_enable_live_pipeline_engagement_counts_safety_level" - ) - val EnableLiveVideoTimelineSafetyLevel: Value = Value( - "visibility_library_enable_live_video_timeline_safety_level" - ) - val EnableMagicRecsAggressiveSafetyLevel: Value = Value( - "visibility_library_enable_magic_recs_aggressive_safety_level" - ) - val EnableMagicRecsAggressiveV2SafetyLevel: Value = Value( - "visibility_library_enable_magic_recs_aggressive_v2_safety_level" - ) - val EnableMagicRecsSafetyLevel: Value = Value( - "visibility_library_enable_magic_recs_safety_level" - ) - val EnableMagicRecsV2SafetyLevel: Value = Value( - "visibility_library_enable_magic_recs_v2_safety_level" - ) - val EnableMinimalSafetyLevel: Value = Value( - "visibility_library_enable_minimal_safety_level" - ) - val EnableModeratedTweetsTimelineSafetyLevel: Value = Value( - "visibility_library_enable_moderated_tweets_timeline_safety_level" - ) - val EnableMomentsSafetyLevel: Value = Value( - "visibility_library_enable_moments_safety_level" - ) - val EnableNearbyTimelineSafetyLevel: Value = Value( - "visibility_library_enable_nearby_timeline_safety_level" - ) - val EnableNewUserExperienceSafetyLevel: Value = Value( - "visibility_library_enable_new_user_experience_safety_level" - ) - val EnableNotificationsIbisSafetyLevel: Value = Value( - "visibility_library_enable_notifications_ibis_safety_level" - ) - val EnableNotificationsPlatformSafetyLevel: Value = Value( - "visibility_library_enable_notifications_platform_safety_level" - ) - val EnableNotificationsPlatformPushSafetyLevel: Value = Value( - "visibility_library_enable_notifications_platform_push_safety_level" - ) - val EnableNotificationsReadSafetyLevel: Value = Value( - "visibility_library_enable_notifications_read_safety_level" - ) - val EnableNotificationsTimelineDeviceFollowSafetyLevel: Value = Value( - "visibility_library_enable_notifications_timeline_device_follow_safety_level" - ) - val EnableNotificationsWriteSafetyLevel: Value = Value( - "visibility_library_enable_notifications_write_safety_level" - ) - val EnableNotificationsWriterV2SafetyLevel: Value = Value( - "visibility_library_enable_notification_writer_v2_safety_level" - ) - val EnableNotificationsWriterTweetHydratorSafetyLevel: Value = Value( - "visibility_library_enable_notifications_writer_tweet_hydrator_safety_level" - ) - val EnableQuickPromoteTweetEligibilitySafetyLevel: Value = Value( - "visibility_library_enable_quick_promote_tweet_eligibility_safety_level" - ) - val EnableQuoteTweetTimelineSafetyLevel: Value = Value( - "visibility_library_enable_quote_tweet_timeline_safety_level" - ) - val EnableQuotedTweetRulesSafetyLevel: Value = Value( - "visibility_library_enable_quoted_tweet_rules_safety_level" - ) - val EnableRecommendationsSafetyLevel: Value = Value( - "visibility_library_enable_recommendations_safety_level" - ) - val EnableRecosVideoSafetyLevel: Value = Value( - "visibility_library_enable_recos_video_safety_level" - ) - val EnableRecosWritePathSafetyLevel: Value = Value( - "visibility_library_enable_recos_write_path_safety_level" - ) - val EnableRepliesGroupingSafetyLevel: Value = Value( - "visibility_library_enable_replies_grouping_safety_level" - ) - val EnableReportCenterSafetyLevel: Value = Value( - "visibility_library_enable_report_center_safety_level" - ) - val EnableReturningUserExperienceSafetyLevel: Value = Value( - "visibility_library_enable_returning_user_experience_safety_level" - ) - val EnableReturningUserExperienceFocalTweetSafetyLevel: Value = Value( - "visibility_library_enable_returning_user_experience_focal_tweet_safety_level" - ) - val EnableRevenueSafetyLevel: Value = Value( - "visibility_library_enable_revenue_safety_level" - ) - val EnableRitoActionedTweetTimelineSafetyLevel: Value = Value( - "visibility_library_enable_rito_actioned_tweet_timeline_safety_level" - ) - val EnableSafeSearchMinimalSafetyLevel: Value = Value( - "visibility_library_enable_safe_search_minimal_safety_level" - ) - val EnableSafeSearchStrictSafetyLevel: Value = Value( - "visibility_library_enable_safe_search_strict_safety_level" - ) - val EnableAccessInternalPromotedContentSafetyLevel: Value = Value( - "visibility_library_enable_access_internal_promoted_content_safety_level" - ) - val EnableSearchHydration: Value = Value( - "visibility_library_enable_search_hydration_safety_level" - ) - val EnableSearchLatest: Value = Value( - "visibility_library_enable_search_latest_safety_level" - ) - val EnableSearchMixerSrpMinimalSafetyLevel: Value = Value( - "visibility_library_enable_search_mixer_srp_minimal_safety_level" - ) - val EnableSearchMixerSrpStrictSafetyLevel: Value = Value( - "visibility_library_enable_search_mixer_srp_strict_safety_level" - ) - val EnableUserSearchSrpSafetyLevel: Value = Value( - "visibility_library_enable_user_search_srp_safety_level" - ) - val EnableUserSearchTypeaheadSafetyLevel: Value = Value( - "visibility_library_enable_user_search_typeahead_safety_level" - ) - val EnableSearchPeopleSrp: Value = Value( - "visibility_library_enable_search_people_srp_safety_level" - ) - val EnableSearchPeopleTypeahead: Value = Value( - "visibility_library_enable_search_people_typeahead_safety_level" - ) - val EnableSearchPhoto: Value = Value( - "visibility_library_enable_search_photo_safety_level" - ) - val EnableSearchTop: Value = Value( - "visibility_library_enable_search_top_safety_level" - ) - val EnableSearchTopQig: Value = Value( - "visibility_library_enable_search_top_qig_safety_level" - ) - val EnableSearchTrendTakeoverPromotedTweet: Value = Value( - "visibility_library_enable_search_trend_takeover_promoted_tweet_safety_level" - ) - val EnableSearchVideo: Value = Value( - "visibility_library_enable_search_video_safety_level" - ) - val EnableSearchLatestUserRules: Value = Value( - "visibility_library_enable_search_latest_user_rules_safety_level" - ) - val EnableShoppingManagerSpyModeSafetyLevel: Value = Value( - "visibility_library_enable_shopping_manager_spy_mode_safety_level" - ) - val EnableSignalsReactions: Value = Value( - "visibility_library_enable_signals_reactions_safety_level" - ) - val EnableSignalsTweetReactingUsers: Value = Value( - "visibility_library_enable_signals_tweet_reacting_users_safety_level" - ) - val EnableSocialProof: Value = Value( - "visibility_library_enable_social_proof_safety_level" - ) - val EnableSoftInterventionPivot: Value = Value( - "visibility_library_enable_soft_intervention_pivot_safety_level" - ) - val EnableSpaceFleetlineSafetyLevel: Value = Value( - "visibility_library_enable_space_fleetline_safety_level" - ) - val EnableSpaceHomeTimelineUprankingSafetyLevel: Value = Value( - "visibility_library_enable_space_home_timeline_upranking_safety_level" - ) - val EnableSpaceJoinScreenSafetyLevel: Value = Value( - "visibility_library_enable_space_join_screen_safety_level" - ) - val EnableSpaceNotificationsSafetyLevel: Value = Value( - "visibility_library_enable_space_notifications_safety_level" - ) - val EnableSpacesSafetyLevel: Value = Value( - "visibility_library_enable_spaces_safety_level" - ) - val EnableSpacesParticipantsSafetyLevel: Value = Value( - "visibility_library_enable_spaces_participants_safety_level" - ) - val EnableSpacesSellerApplicationStatus: Value = Value( - "visibility_library_enable_spaces_seller_application_status_safety_level" - ) - val EnableSpacesSharingSafetyLevel: Value = Value( - "visibility_library_enable_spaces_sharing_safety_level" - ) - val EnableSpaceTweetAvatarHomeTimelineSafetyLevel: Value = Value( - "visibility_library_enable_space_tweet_avatar_home_timeline_safety_level" - ) - val EnableStickersTimelineSafetyLevel: Value = Value( - "visibility_library_enable_stickers_timeline_safety_level" - ) - val EnableStratoExtLimitedEngagementsSafetyLevel: Value = Value( - "visibility_library_enable_strato_ext_limited_engagements_safety_level" - ) - val EnableStreamServicesSafetyLevel: Value = Value( - "visibility_library_enable_stream_services_safety_level" - ) - val EnableTestSafetyLevel: Value = Value( - "visibility_library_enable_test_safety_level" - ) - val EnableTimelineBookmarkSafetyLevel: Value = Value( - "visibility_library_enable_timeline_bookmark_safety_level" - ) - val EnableTimelineContentControlsSafetyLevel: Value = Value( - "visibility_library_enable_timeline_content_controls_safety_level" - ) - val EnableTimelineConversationsSafetyLevel: Value = Value( - "visibility_library_enable_timeline_conversations_safety_level" - ) - val EnableTimelineConversationsDownrankingSafetyLevel: Value = Value( - "visibility_library_enable_timeline_conversations_downranking_safety_level" - ) - val EnableTimelineConversationsDownrankingMinimalSafetyLevel: Value = Value( - "visibility_library_enable_timeline_conversations_downranking_minimal_safety_level" - ) - val EnableTimelineFavoritesSafetyLevel: Value = Value( - "visibility_library_enable_timeline_favorites_safety_level" - ) - val EnableSelfViewTimelineFavoritesSafetyLevel: Value = Value( - "visibility_library_enable_self_view_timeline_favorites_safety_level" - ) - val EnableTweetTimelineFocalTweetSafetyLevel: Value = Value( - "visibility_library_enable_timeline_focal_tweet_safety_level" - ) - val EnableTweetScopedTimelineSafetyLevel: Value = Value( - "visibility_library_enable_tweet_scoped_timeline_safety_level" - ) - val EnableTimelineFollowingActivitySafetyLevel: Value = Value( - "visibility_library_enable_timeline_following_activity_safety_level" - ) - val EnableTimelineHomeSafetyLevel: Value = Value( - "visibility_library_enable_timeline_home_safety_level" - ) - val EnableTimelineHomeCommunitiesSafetyLevel: Value = Value( - "visibility_library_enable_timeline_home_communities_safety_level" - ) - val EnableTimelineHomeHydrationSafetyLevel: Value = Value( - "visibility_library_enable_timeline_home_hydration_safety_level" - ) - val EnableTimelineHomeLatestSafetyLevel: Value = Value( - "visibility_library_enable_timeline_home_latest_safety_level" - ) - val EnableTimelineHomeRecommendationsSafetyLevel: Value = Value( - "visibility_library_enable_timeline_home_recommendations_safety_level" - ) - val EnableTimelineHomeTopicFollowRecommendationsSafetyLevel: Value = Value( - "visibility_library_enable_timeline_home_topic_follow_recommendations_safety_level" - ) - val EnableTimelineScorerSafetyLevel: Value = Value( - "visibility_library_enable_timeline_scorer_safety_level" - ) - val EnableTopicsLandingPageTopicRecommendationsSafetyLevel: Value = Value( - "visibility_library_enable_topics_landing_page_topic_recommendations_safety_level" - ) - val EnableExploreRecommendationsSafetyLevel: Value = Value( - "visibility_library_enable_explore_recommendations_safety_level" - ) - val EnableTimelineInjectionSafetyLevel: Value = Value( - "visibility_library_enable_timeline_injection_safety_level" - ) - val EnableTimelineLikedBySafetyLevel: Value = Value( - "visibility_library_enable_timeline_liked_by_safety_level" - ) - val EnableTimelineListsSafetyLevel: Value = Value( - "visibility_library_enable_timeline_lists_safety_level" - ) - val EnableTimelineMediaSafetyLevel: Value = Value( - "visibility_library_enable_timeline_media_safety_level" - ) - val EnableTimelineMentionsSafetyLevel: Value = Value( - "visibility_library_enable_timeline_mentions_safety_level" - ) - val EnableTimelineModeratedTweetsHydrationSafetyLevel: Value = Value( - "visibility_library_enable_timeline_moderated_tweets_hydration_safety_level" - ) - val EnableTimelineProfileSafetyLevel: Value = Value( - "visibility_library_enable_timeline_profile_safety_level" - ) - val EnableTimelineProfileAllSafetyLevel: Value = Value( - "visibility_library_enable_timeline_profile_all_safety_level" - ) - val EnableTimelineProfileSpacesSafetyLevel: Value = Value( - "visibility_library_enable_timeline_profile_spaces_safety_level") - val EnableTimelineProfileSuperFollowsSafetyLevel: Value = Value( - "visibility_library_enable_timeline_profile_super_follows_safety_level" - ) - val EnableTimelineReactiveBlendingSafetyLevel: Value = Value( - "visibility_library_enable_timeline_reactive_blending_safety_level" - ) - val EnableTimelineRetweetedBySafetyLevel: Value = Value( - "visibility_library_enable_timeline_retweeted_by_safety_level" - ) - val EnableTimelineSuperLikedBySafetyLevel: Value = Value( - "visibility_library_enable_timeline_super_liked_by_safety_level" - ) - val EnableTombstoningSafetyLevel: Value = Value( - "visibility_library_enable_tombstoning_safety_level" - ) - val EnableTopicRecommendationsSafetyLevel: Value = Value( - "visibility_library_enable_topic_recommendations_safety_level" - ) - val EnableTrendsRepresentativeTweetSafetyLevel: Value = Value( - "visibility_library_enable_trends_representative_tweet_safety_level" - ) - val EnableTrustedFriendsUserListSafetyLevel: Value = Value( - "visibility_library_enable_trusted_friends_user_list_safety_level" - ) - val EnableTwitterDelegateUserListSafetyLevel: Value = Value( - "visibility_library_enable_twitter_delegate_user_list_safety_level" - ) - val EnableTweetDetailSafetyLevel: Value = Value( - "visibility_library_enable_tweet_detail_safety_level" - ) - val EnableTweetDetailNonTooSafetyLevel: Value = Value( - "visibility_library_enable_tweet_detail_non_too_safety_level" - ) - val EnableTweetDetailWithInjectionsHydrationSafetyLevel: Value = Value( - "visibility_library_enable_tweet_detail_with_injections_hydration_safety_level" - ) - val EnableTweetEngagersSafetyLevel: Value = Value( - "visibility_library_enable_tweet_engagers_safety_level" - ) - val EnableTweetReplyNudgeSafetyLevel: Value = Value( - "visibility_library_enable_tweet_reply_nudge_safety_level" - ) - val EnableTweetWritesApiSafetyLevel: Value = Value( - "visibility_library_enable_tweet_writes_api_safety_level" - ) - val EnableTwitterArticleComposeSafetyLevel: Value = Value( - "visibility_library_enable_twitter_article_compose_safety_level" - ) - val EnableTwitterArticleProfileTabSafetyLevel: Value = Value( - "visibility_library_enable_twitter_article_profile_tab_safety_level" - ) - val EnableTwitterArticleReadSafetyLevel: Value = Value( - "visibility_library_enable_twitter_article_read_safety_level" - ) - val EnableUserProfileHeaderSafetyLevel: Value = Value( - "visibility_library_enable_user_profile_header_safety_level" - ) - val EnableUserMilestoneRecommendationSafetyLevel: Value = Value( - "visibility_library_enable_user_milestone_recommendation_safety_level" - ) - val EnableUserScopedTimelineSafetyLevel: Value = Value( - "visibility_library_enable_user_scoped_timeline_safety_level" - ) - val EnableUserSettingsSafetyLevel: Value = Value( - "visibility_library_enable_user_settings_safety_level" - ) - val EnableVideoAdsSafetyLevel: Value = Value( - "visibility_library_enable_video_ads_safety_level" - ) - val EnableTimelineHomePromotedHydrationSafetyLevel: Value = Value( - "visibility_library_enable_timeline_home_promoted_hydration_safety_level" - ) - - val EnableSuperFollowerConnectionsSafetyLevel: Value = Value( - "visibility_library_enable_super_follower_connnections_safety_level" - ) - - val EnableSuperLikeSafetyLevel: Value = Value( - "visibility_library_enable_super_like_safety_level" - ) - - val EnableZipbirdConsumerArchivesSafetyLevel: Value = Value( - "visibility_library_enable_zipbird_consumer_archives_safety_level" - ) - - val EnableTweetAwardSafetyLevel: Value = Value( - "visibility_library_enable_tweet_award_safety_level" - ) - - val EnableTweetConversationControlRules: Value = Value( - "visibility_library_enable_conversation_control_rules" - ) - val EnableCommunityTweetsControlRules: Value = Value( - "visibility_library_enable_community_tweets_rules" - ) - val EnableDropCommunityTweetWithUndefinedCommunityRule: Value = Value( - "visibility_library_enable_drop_community_tweet_with_undefined_community_rule" - ) - val EnablePSpammyTweetDownrankConvosLowQuality: Value = Value( - "visibility_library_enable_p_spammy_tweet_downrank_convos_low_quality" - ) - val EnableHighPSpammyTweetScoreSearchTweetLabelDropRule: Value = Value( - "visibility_library_enable_high_p_spammy_tweet_score_search_tweet_label_drop_rule" - ) - - val EnableRitoActionedTweetDownrankConvosLowQuality: Value = Value( - "visibility_library_enable_rito_actioned_tweet_downrank_convos_low_quality" - ) - - val EnableNewSensitiveMediaSettingsInterstitialRulesHomeTimeline: Value = Value( - "visibility_library_enable_new_sensitive_media_settings_interstitial_rules_home_timeline") - - val EnableLegacySensitiveMediaRulesHomeTimeline: Value = Value( - "visibility_library_enable_legacy_sensitive_media_rules_home_timeline" - ) - - val EnableNewSensitiveMediaSettingsInterstitialRulesConversation: Value = Value( - "visibility_library_enable_new_sensitive_media_settings_interstitial_rules_conversation" - ) - - val EnableLegacySensitiveMediaRulesConversation: Value = Value( - "visibility_library_enable_legacy_sensitive_media_rules_conversation" - ) - - val EnableNewSensitiveMediaSettingsInterstitialRulesProfileTimeline: Value = Value( - "visibility_library_enable_new_sensitive_media_settings_interstitials_rules_profile_timeline" - ) - - val EnableLegacySensitiveMediaRulesProfileTimeline: Value = Value( - "visibility_library_enable_legacy_sensitive_media_rules_profile_timeline" - ) - - val EnableNewSensitiveMediaSettingsInterstitialRulesTweetDetail: Value = Value( - "visibility_library_enable_new_sensitive_media_settings_interstitials_rules_tweet_detail" - ) - - val EnableLegacySensitiveMediaRulesTweetDetail: Value = Value( - "visibility_library_enable_legacy_sensitive_media_rules_tweet_detail" - ) - - val EnableLegacySensitiveMediaRulesDirectMessages: Value = Value( - "visibility_library_enable_legacy_sensitive_media_rules_direct_messages" - ) - - val VisibilityLibraryEnableToxicReplyFilterConversation: Value = Value( - "visibility_library_enable_toxic_reply_filter_conversation" - ) - - val VisibilityLibraryEnableToxicReplyFilterNotifications: Value = Value( - "visibility_library_enable_toxic_reply_filter_notifications" - ) - - val EnableSmyteSpamTweetRule: Value = Value( - "visibility_library_enable_smyte_spam_tweet_rule" - ) - - val EnableHighSpammyTweetContentScoreSearchLatestTweetLabelDropRule: Value = Value( - "visibility_library_enable_high_spammy_tweet_content_score_search_latest_tweet_label_drop_rule" - ) - val EnableHighSpammyTweetContentScoreSearchTopTweetLabelDropRule: Value = Value( - "visibility_library_enable_high_spammy_tweet_content_score_search_top_tweet_label_drop_rule" - ) - val EnableHighSpammyTweetContentScoreConvoDownrankAbusiveQualityRule: Value = Value( - "visibility_library_enable_high_spammy_tweet_content_score_convo_downrank_abusive_quality_rule" - ) - - val EnableHighCryptospamScoreConvoDownrankAbusiveQualityRule: Value = Value( - "visibility_library_enable_high_cryptospam_score_convo_downrank_abusive_quality_rule" - ) - val EnableHighSpammyTweetContentScoreTrendsTopTweetLabelDropRule: Value = Value( - "visibility_library_enable_high_spammy_tweet_content_score_trends_top_tweet_label_drop_rule" - ) - - val EnableHighSpammyTweetContentScoreTrendsLatestTweetLabelDropRule: Value = Value( - "visibility_library_enable_high_spammy_tweet_content_score_trends_latest_tweet_label_drop_rule" - ) - - val EnableGoreAndViolenceTopicHighRecallTweetLabelRule: Value = Value( - "visibility_library_enable_gore_and_violence_topic_high_recall_tweet_label_rule" - ) - - val EnableLimitRepliesFollowersConversationRule: Value = Value( - "visibility_library_enable_limit_replies_followers_conversation_rule" - ) - - val EnableBlinkBadDownrankingRule: Value = Value( - "visibility_library_enable_blink_bad_downranking_rule" - ) - - val EnableBlinkWorstDownrankingRule: Value = Value( - "visibility_library_enable_blink_worst_downranking_rule" - ) - - val EnableCopypastaSpamDownrankConvosAbusiveQualityRule: Value = Value( - "visibility_library_enable_copypasta_spam_downrank_convos_abusive_quality_rule" - ) - - val EnableCopypastaSpamSearchDropRule: Value = Value( - "visibility_library_enable_copypasta_spam_search_drop_rule" - ) - - val EnableSpammyUserModelHighPrecisionDropTweetRule: Value = Value( - "visibility_library_enable_spammy_user_model_high_precision_drop_tweet_rule" - ) - - val EnableAvoidNsfwRules: Value = Value( - "visibility_library_enable_avoid_nsfw_rules" - ) - - val EnableReportedTweetInterstitialRule: Value = Value( - "visibility_library_enable_reported_tweet_interstitial_rule" - ) - - val EnableReportedTweetInterstitialSearchRule: Value = Value( - "visibility_library_enable_reported_tweet_interstitial_search_rule" - ) - - val EnableDropExclusiveTweetContentRule: Value = Value( - "visibility_library_enable_drop_exclusive_tweet_content_rule" - ) - - val EnableDropExclusiveTweetContentRuleFailClosed: Value = Value( - "visibility_library_enable_drop_exclusive_tweet_content_rule_fail_closed" - ) - - val EnableTombstoneExclusiveQtProfileTimelineParam: Value = Value( - "visibility_library_enable_tombstone_exclusive_quoted_tweet_content_rule" - ) - - val EnableDropAllExclusiveTweetsRule: Value = Value( - "visibility_library_enable_drop_all_exclusive_tweets_rule" - ) - - val EnableDropAllExclusiveTweetsRuleFailClosed: Value = Value( - "visibility_library_enable_drop_all_exclusive_tweets_rule_fail_closed" - ) - - val EnableDownrankSpamReplySectioningRule: Value = Value( - "visibility_library_enable_downrank_spam_reply_sectioning_rule" - ) - - val EnableNsfwTextSectioningRule: Value = Value( - "visibility_library_enable_nsfw_text_sectioning_rule" - ) - - val EnableNsfwAgeBasedMediaDropRules: Value = Value( - "visibility_library_enable_nsfw_age_based_media_drop_rules" - ) - - val EnableNsfwUnderageRules: Value = Value( - "visibility_library_enable_nsfw_underage_rules" - ) - - val EnableNsfwUnderageMediaRules: Value = Value( - "visibility_library_enable_nsfw_underage_media_rules" - ) - - val EnableNsfwMissingAgeRules: Value = Value( - "visibility_library_enable_nsfw_missing_age_rules" - ) - - val EnableNsfwMissingAgeMediaRules: Value = Value( - "visibility_library_enable_nsfw_missing_age_media_rules" - ) - - val EnableSearchIpiSafeSearchWithoutUserInQueryDropRule: Value = Value( - "visibility_library_enable_search_ipi_safe_search_without_user_in_query_drop_rule" - ) - - val EnableTimelineHomePromotedTweetHealthEnforcementRules: Value = Value( - "visibility_library_enable_timeline_home_promoted_tweet_health_enforcement_rules" - ) - - val EnableMutedKeywordFilteringSpaceTitleNotificationsRule: Value = Value( - "visibility_library_enable_muted_keyword_filtering_space_title_notifications_rule" - ) - - val EnableDropTweetsWithGeoRestrictedMediaRule: Value = Value( - "visibility_library_enable_drop_tweets_with_georestricted_media_rule" - ) - val EnableDropAllTrustedFriendsTweetsRule: Value = Value( - "visibility_library_enable_drop_all_trusted_friends_tweets_rule" - ) - - val EnableDropTrustedFriendsTweetContentRule: Value = Value( - "visibility_library_enable_drop_all_trusted_friends_tweet_content_rule" - ) - - val EnableDropCollabInvitationTweetsRule: Value = Value( - "visibility_library_enable_drop_all_collab_invitation_tweets_rule" - ) - - val EnableFetchTweetReportedPerspective: Value = Value( - "visibility_library_enable_fetch_tweet_reported_perspective" - ) - - val EnableFetchTweetMediaMetadata: Value = Value( - "visibility_library_enable_fetch_tweet_media_metadata" - ) - - val VisibilityLibraryEnableFollowCheckInMutedKeyword: Value = Value( - "visibility_library_enable_follow_check_in_mutedkeyword" - ) - - val VisibilityLibraryEnableMediaInterstitialComposition: Value = Value( - "visibility_library_enable_media_interstitial_composition" - ) - - val EnableVerdictScribingFromTweetVisibilityLibrary: Value = Value( - "visibility_library_enable_verdict_scribing_from_tweet_visibility_library" - ) - - val EnableVerdictLoggerEventPublisherInstantiationFromTweetVisibilityLibrary: Value = Value( - "visibility_library_enable_verdict_logger_event_publisher_instantiation_from_tweet_visibility_library" - ) - - val EnableVerdictScribingFromTimelineConversationsVisibilityLibrary: Value = Value( - "visibility_library_enable_verdict_scribing_from_timeline_conversations_visibility_library" - ) - - val EnableVerdictLoggerEventPublisherInstantiationFromTimelineConversationsVisibilityLibrary: Value = - Value( - "visibility_library_enable_verdict_logger_event_publisher_instantiation_from_timeline_conversations_visibility_library" - ) - - val EnableVerdictScribingFromBlenderVisibilityLibrary: Value = Value( - "visibility_library_enable_verdict_scribing_from_blender_visibility_library" - ) - - val EnableVerdictScribingFromSearchVisibilityLibrary: Value = Value( - "visibility_library_enable_verdict_scribing_from_search_visibility_library" - ) - - val EnableVerdictLoggerEventPublisherInstantiationFromBlenderVisibilityLibrary: Value = Value( - "visibility_library_enable_verdict_logger_event_publisher_instantiation_from_blender_visibility_library" - ) - - val EnableVerdictLoggerEventPublisherInstantiationFromSearchVisibilityLibrary: Value = Value( - "visibility_library_enable_verdict_logger_event_publisher_instantiation_from_search_visibility_library" - ) - - val EnableLocalizedTombstoneOnVisibilityResults: Value = Value( - "visibility_library_enable_localized_tombstones_on_visibility_results" - ) - - val EnableShortCircuitingFromTweetVisibilityLibrary: Value = Value( - "visibility_library_enable_short_circuiting_from_tweet_visibility_library" - ) - - val EnableShortCircuitingFromTimelineConversationsVisibilityLibrary: Value = Value( - "visibility_library_enable_short_circuiting_from_timeline_conversations_visibility_library" - ) - - val EnableShortCircuitingFromBlenderVisibilityLibrary: Value = Value( - "visibility_library_enable_short_circuiting_from_blender_visibility_library" - ) - - val EnableShortCircuitingFromSearchVisibilityLibrary: Value = Value( - "visibility_library_enable_short_circuiting_from_search_visibility_library" - ) - - val EnableNsfwTextHighPrecisionDropRule: Value = Value( - "visibility_library_enable_nsfw_text_high_precision_drop_rule" - ) - - val EnableSpammyTweetRuleVerdictLogging: Value = Value( - "visibility_library_enable_spammy_tweet_rule_verdict_logging" - ) - - val EnableDownlevelRuleVerdictLogging: Value = Value( - "visibility_library_enable_downlevel_rule_verdict_logging" - ) - - val EnableLikelyIvsUserLabelDropRule: Value = Value( - "visibility_library_enable_likely_likely_ivs_user_label_drop_rule" - ) - - val EnableCardVisibilityLibraryCardUriParsing: Value = Value( - "visibility_library_enable_card_visibility_library_card_uri_parsing" - ) - - val EnableCardUriRootDomainDenylistRule: Value = Value( - "visibility_library_enable_card_uri_root_domain_deny_list_rule" - ) - - val EnableCommunityNonMemberPollCardRule: Value = Value( - "visibility_library_enable_community_non_member_poll_card_rule" - ) - - val EnableCommunityNonMemberPollCardRuleFailClosed: Value = Value( - "visibility_library_enable_community_non_member_poll_card_rule_fail_closed" - ) - - val EnableExperimentalNudgeLabelRule: Value = Value( - "visibility_library_enable_experimental_nudge_label_rule" - ) - - val NsfwHighPrecisionUserLabelAvoidTweetRuleEnabledParam: Value = Value( - "visibility_library_nsfw_high_precision_user_label_avoid_tweet_rule_enabled" - ) - - val EnableUserSelfViewOnlySafetyLevel: Value = Value( - "visibility_library_enable_user_self_view_only_safety_level" - ) - - val EnableNewAdAvoidanceRules: Value = Value( - "visibility_library_enable_new_ad_avoidance_rules" - ) - - val EnableNsfaHighRecallAdAvoidanceParam: Value = Value( - "visibility_library_enable_nsfa_high_recall_ad_avoidance_rules" - ) - - val EnableNsfaKeywordsHighPrecisionAdAvoidanceParam: Value = Value( - "visibility_library_enable_nsfa_keywords_high_precision_ad_avoidance_rules" - ) - - val EnableStaleTweetDropRuleParam: Value = Value( - "visibility_library_enable_stale_tweet_drop_rule" - ) - - val EnableStaleTweetDropRuleFailClosedParam: Value = Value( - "visibility_library_enable_stale_tweet_drop_rule_fail_closed" - ) - - val EnableEditHistoryTimelineSafetyLevel: Value = Value( - "visibility_library_enable_edit_history_timeline_safety_level" - ) - - val EnableDeleteStateTweetRules: Value = Value( - "visibility_library_enable_delete_state_tweet_rules" - ) - - val EnableSpacesSharingNsfwDropRulesParam: Value = Value( - "visibility_library_enable_spaces_sharing_nsfw_drop_rule" - ) - - val EnableDropMediaLegalRulesParam: Value = Value( - "visibility_library_enable_drop_media_legal_rules" - ) - - val EnableTombstoneMediaLegalRulesParam: Value = Value( - "visibility_library_enable_tombstone_media_legal_rules" - ) - - val EnableInterstitialMediaLegalRulesParam: Value = Value( - "visibility_library_enable_interstitial_media_legal_rules" - ) - - val EnableViewerIsSoftUserDropRuleParam: Value = Value( - "visibility_library_enable_viewer_is_soft_user_drop_rule" - ) - - val EnableBackendLimitedActions: Value = Value( - "visibility_library_enable_backend_limited_actions" - ) - - val EnableNotificationsQig: Value = Value( - "visibility_library_enable_notifications_qig_safety_level" - ) - - val EnablePdnaQuotedTweetTombstoneRule: Value = Value( - "visibility_library_enable_pdna_quoted_tweet_tombstone_rule" - ) - - val EnableSpamQuotedTweetTombstoneRule: Value = Value( - "visibility_library_enable_spam_quoted_tweet_tombstone_rule" - ) - - val EnableNsfwHpQuotedTweetDropRule: Value = Value( - "visibility_library_enable_nsfw_hp_quoted_tweet_drop_experiment_rule" - ) - val EnableNsfwHpQuotedTweetTombstoneRule: Value = Value( - "visibility_library_enable_nsfw_hp_quoted_tweet_tombstone_experiment_rule" - ) - - val EnableExperimentalRuleEngine: Value = Value( - "visibility_library_enable_experimental_rule_engine" - ) - - val EnableFosnrRules: Value = Value( - "visibility_library_enable_fosnr_rules" - ) - - val EnableInnerQuotedTweetViewerBlocksAuthorInterstitialRule: Value = Value( - "visibility_library_enable_inner_quoted_tweet_viewer_blocks_author_interstitial_rule" - ) - - val EnableInnerQuotedTweetViewerMutesAuthorInterstitialRule: Value = Value( - "visibility_library_enable_inner_quoted_tweet_viewer_mutes_author_interstitial_rule" - ) - - val EnableLocalizedInterstitialGenerator: Value = Value( - "visibility_library_enable_localized_interstitial_generator" - ) - - val EnableProfileMixeMediaSafetyLevel: Value = Value( - "visibility_library_enable_profile_mixer_media_safety_level") - - val EnableConvosLocalizedInterstitial: Value = Value( - "visibility_library_convos_enable_localized_interstitial" - ) - - val EnableConvosLegacyInterstitial: Value = Value( - "visibility_library_convos_enable_legacy_interstitial" - ) - - val DisableLegacyInterstitialFilteredReason: Value = Value( - "visibility_library_disable_legacy_interstitial_filtered_reason" - ) - - val EnableSearchBasicBlockMuteRules: Value = Value( - "visibility_library_enable_search_basic_block_mute_rules" - ) - - val EnableLocalizedInterstitialInUserStateLib: Value = Value( - "visibility_library_enable_localized_interstitial_user_state_lib" - ) - - val EnableProfileMixerFavoritesSafetyLevel: Value = Value( - "visibility_library_enable_profile_mixer_favorites_safety_level") - - val EnableAbusiveBehaviorDropRule: Value = Value( - "visibility_library_enable_abusive_behavior_drop_rule" - ) - - val EnableAbusiveBehaviorInterstitialRule: Value = Value( - "visibility_library_enable_abusive_behavior_interstitial_rule" - ) - - val EnableAbusiveBehaviorLimitedEngagementsRule: Value = Value( - "visibility_library_enable_abusive_behavior_limited_engagements_rule" - ) - - val EnableNotGraduatedDownrankConvosAbusiveQualityRule: Value = Value( - "visibility_library_enable_not_graduated_downrank_convos_abusive_quality_rule" - ) - - val EnableNotGraduatedSearchDropRule: Value = Value( - "visibility_library_enable_not_graduated_search_drop_rule" - ) - - val EnableNotGraduatedDropRule: Value = Value( - "visibility_library_enable_not_graduated_drop_rule" - ) - - val EnableMemoizeSafetyLevelParams: Value = Value( - "visibility_library_enable_memoize_safety_level_params" - ) - - val EnableAuthorBlocksViewerDropRule: Value = Value( - "visibility_library_enable_author_blocks_viewer_drop_rule" - ) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/ExperimentsHelper.scala b/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/ExperimentsHelper.scala deleted file mode 100644 index f2240311b..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/ExperimentsHelper.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.visibility.configapi.configs - -import com.twitter.timelines.configapi.Config -import com.twitter.timelines.configapi.ExperimentConfigBuilder -import com.twitter.timelines.configapi.Param -import com.twitter.visibility.configapi.params.VisibilityExperiment -import com.twitter.visibility.models.SafetyLevel - -object ExperimentsHelper { - - def mkABExperimentConfig(experiment: VisibilityExperiment, param: Param[Boolean]): Config = { - ExperimentConfigBuilder(experiment) - .addBucket( - experiment.ControlBucket, - param := true - ) - .addBucket( - experiment.TreatmentBucket, - param := false - ) - .build - } - - def mkABExperimentConfig(experiment: VisibilityExperiment, safetyLevel: SafetyLevel): Config = - mkABExperimentConfig(experiment, safetyLevel.enabledParam) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/VisibilityDeciderGates.scala b/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/VisibilityDeciderGates.scala deleted file mode 100644 index 7df596ce0..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/VisibilityDeciderGates.scala +++ /dev/null @@ -1,73 +0,0 @@ -package com.twitter.visibility.configapi.configs - -import com.twitter.decider.Decider -import com.twitter.servo.gate.DeciderGate -import com.twitter.servo.util.Gate - -case class VisibilityDeciderGates(decider: Decider) { - import DeciderKey._ - - private[this] def feature(deciderKey: Value) = decider.feature(deciderKey.toString) - - val enableFetchTweetReportedPerspective: Gate[Unit] = - DeciderGate.linear(feature(DeciderKey.EnableFetchTweetReportedPerspective)) - val enableFetchTweetMediaMetadata: Gate[Unit] = - DeciderGate.linear(feature(DeciderKey.EnableFetchTweetMediaMetadata)) - val enableFollowCheckInMutedKeyword: Gate[Unit] = - DeciderGate.linear(feature(DeciderKey.VisibilityLibraryEnableFollowCheckInMutedKeyword)) - val enableMediaInterstitialComposition: Gate[Unit] = - DeciderGate.linear(feature(DeciderKey.VisibilityLibraryEnableMediaInterstitialComposition)) - val enableExperimentalRuleEngine: Gate[Unit] = - DeciderGate.linear(feature(DeciderKey.EnableExperimentalRuleEngine)) - - val enableLocalizedInterstitialGenerator: Gate[Unit] = - DeciderGate.linear(feature(DeciderKey.EnableLocalizedInterstitialGenerator)) - - val enableShortCircuitingTVL: Gate[Unit] = - DeciderGate.linear(feature(EnableShortCircuitingFromTweetVisibilityLibrary)) - val enableVerdictLoggerTVL = DeciderGate.linear( - feature(DeciderKey.EnableVerdictLoggerEventPublisherInstantiationFromTweetVisibilityLibrary)) - val enableVerdictScribingTVL = - DeciderGate.linear(feature(DeciderKey.EnableVerdictScribingFromTweetVisibilityLibrary)) - val enableBackendLimitedActions = - DeciderGate.linear(feature(DeciderKey.EnableBackendLimitedActions)) - val enableMemoizeSafetyLevelParams: Gate[Unit] = - DeciderGate.linear(feature(DeciderKey.EnableMemoizeSafetyLevelParams)) - - val enableShortCircuitingBVL: Gate[Unit] = - DeciderGate.linear(feature(EnableShortCircuitingFromBlenderVisibilityLibrary)) - val enableVerdictLoggerBVL = DeciderGate.linear( - feature(DeciderKey.EnableVerdictLoggerEventPublisherInstantiationFromBlenderVisibilityLibrary)) - val enableVerdictScribingBVL = - DeciderGate.linear(feature(DeciderKey.EnableVerdictScribingFromBlenderVisibilityLibrary)) - - val enableShortCircuitingSVL: Gate[Unit] = - DeciderGate.linear(feature(EnableShortCircuitingFromSearchVisibilityLibrary)) - val enableVerdictLoggerSVL = DeciderGate.linear( - feature(DeciderKey.EnableVerdictLoggerEventPublisherInstantiationFromSearchVisibilityLibrary)) - val enableVerdictScribingSVL = - DeciderGate.linear(feature(DeciderKey.EnableVerdictScribingFromSearchVisibilityLibrary)) - - val enableShortCircuitingTCVL: Gate[Unit] = - DeciderGate.linear(feature(EnableShortCircuitingFromTimelineConversationsVisibilityLibrary)) - val enableVerdictLoggerTCVL = DeciderGate.linear(feature( - DeciderKey.EnableVerdictLoggerEventPublisherInstantiationFromTimelineConversationsVisibilityLibrary)) - val enableVerdictScribingTCVL = - DeciderGate.linear( - feature(DeciderKey.EnableVerdictScribingFromTimelineConversationsVisibilityLibrary)) - - val enableCardVisibilityLibraryCardUriParsing = - DeciderGate.linear(feature(DeciderKey.EnableCardVisibilityLibraryCardUriParsing)) - - val enableConvosLocalizedInterstitial: Gate[Unit] = - DeciderGate.linear(feature(DeciderKey.EnableConvosLocalizedInterstitial)) - - val enableConvosLegacyInterstitial: Gate[Unit] = - DeciderGate.linear(feature(DeciderKey.EnableConvosLegacyInterstitial)) - - val disableLegacyInterstitialFilteredReason: Gate[Unit] = - DeciderGate.linear(feature(DeciderKey.DisableLegacyInterstitialFilteredReason)) - - val enableLocalizedInterstitialInUserStateLibrary: Gate[Unit] = - DeciderGate.linear(feature(DeciderKey.EnableLocalizedInterstitialInUserStateLib)) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/VisibilityDeciders.scala b/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/VisibilityDeciders.scala deleted file mode 100644 index e359d443d..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/VisibilityDeciders.scala +++ /dev/null @@ -1,390 +0,0 @@ -package com.twitter.visibility.configapi.configs - -import com.twitter.decider.Recipient -import com.twitter.decider.SimpleRecipient -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.logging.Logger -import com.twitter.servo.decider.DeciderGateBuilder -import com.twitter.timelines.configapi.BaseConfigBuilder -import com.twitter.timelines.configapi.BaseRequestContext -import com.twitter.timelines.configapi.Config -import com.twitter.timelines.configapi.Param -import com.twitter.timelines.configapi.WithGuestId -import com.twitter.timelines.configapi.WithUserId -import com.twitter.timelines.configapi.decider.DeciderSwitchOverrideValue -import com.twitter.timelines.configapi.decider.GuestRecipient -import com.twitter.timelines.configapi.decider.RecipientBuilder -import com.twitter.visibility.configapi.params.RuleParams -import com.twitter.visibility.configapi.params.TimelineConversationsDownrankingSpecificParams -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.SafetyLevel._ - -private[visibility] object VisibilityDeciders { - val SafetyLevelToDeciderMap: Map[SafetyLevel, DeciderKey.Value] = Map( - AllSubscribedLists -> DeciderKey.EnableAllSubscribedListsSafetyLevel, - AccessInternalPromotedContent -> DeciderKey.EnableAccessInternalPromotedContentSafetyLevel, - AdsBusinessSettings -> DeciderKey.EnableAdsBusinessSettingsSafetyLevel, - AdsCampaign -> DeciderKey.EnableAdsCampaignSafetyLevel, - AdsManager -> DeciderKey.EnableAdsManagerSafetyLevel, - AdsReportingDashboard -> DeciderKey.EnableAdsReportingDashboardSafetyLevel, - Appeals -> DeciderKey.EnableAppealsSafetyLevel, - ArticleTweetTimeline -> DeciderKey.EnableArticleTweetTimelineSafetyLevel, - BaseQig -> DeciderKey.EnableBaseQig, - BirdwatchNoteAuthor -> DeciderKey.EnableBirdwatchNoteAuthorSafetyLevel, - BirdwatchNoteTweetsTimeline -> DeciderKey.EnableBirdwatchNoteTweetsTimelineSafetyLevel, - BirdwatchNeedsYourHelpNotifications -> DeciderKey.EnableBirdwatchNeedsYourHelpNotificationsSafetyLevel, - BlockMuteUsersTimeline -> DeciderKey.EnableBlockMuteUsersTimelineSafetyLevel, - BrandSafety -> DeciderKey.EnableBrandSafetySafetyLevel, - CardPollVoting -> DeciderKey.EnableCardPollVotingSafetyLevel, - CardsService -> DeciderKey.EnableCardsServiceSafetyLevel, - Communities -> DeciderKey.EnableCommunitiesSafetyLevel, - ContentControlToolInstall -> DeciderKey.EnableContentControlToolInstallSafetyLevel, - ConversationFocalPrehydration -> DeciderKey.EnableConversationFocalPrehydrationSafetyLevel, - ConversationFocalTweet -> DeciderKey.EnableConversationFocalTweetSafetyLevel, - ConversationInjectedTweet -> DeciderKey.EnableConversationInjectedTweetSafetyLevel, - ConversationReply -> DeciderKey.EnableConversationReplySafetyLevel, - CuratedTrendsRepresentativeTweet -> DeciderKey.EnableCuratedTrendsRepresentativeTweet, - CurationPolicyViolations -> DeciderKey.EnableCurationPolicyViolations, - DeprecatedSafetyLevel -> DeciderKey.EnableDeprecatedSafetyLevelSafetyLevel, - DevPlatformGetListTweets -> DeciderKey.EnableDevPlatformGetListTweetsSafetyLevel, - DesFollowingAndFollowersUserList -> DeciderKey.EnableDesFollowingAndFollowersUserListSafetyLevel, - DesHomeTimeline -> DeciderKey.EnableDesHomeTimelineSafetyLevel, - DesQuoteTweetTimeline -> DeciderKey.EnableDesQuoteTweetTimelineSafetyLevel, - DesRealtime -> DeciderKey.EnableDesRealtimeSafetyLevel, - DesRealtimeSpamEnrichment -> DeciderKey.EnableDesRealtimeSpamEnrichmentSafetyLevel, - DesRealtimeTweetFilter -> DeciderKey.EnableDesRealtimeTweetFilterSafetyLevel, - DesRetweetingUsers -> DeciderKey.EnableDesRetweetingUsersSafetyLevel, - DesTweetDetail -> DeciderKey.EnableDesTweetDetailSafetyLevel, - DesTweetLikingUsers -> DeciderKey.EnableDesTweetLikingUsersSafetyLevel, - DesUserBookmarks -> DeciderKey.EnableDesUserBookmarksSafetyLevel, - DesUserLikedTweets -> DeciderKey.EnableDesUserLikedTweetsSafetyLevel, - DesUserMentions -> DeciderKey.EnableDesUserMentionsSafetyLevel, - DesUserTweets -> DeciderKey.EnableDesUserTweetsSafetyLevel, - DevPlatformComplianceStream -> DeciderKey.EnableDevPlatformComplianceStreamSafetyLevel, - DirectMessages -> DeciderKey.EnableDirectMessagesSafetyLevel, - DirectMessagesConversationList -> DeciderKey.EnableDirectMessagesConversationListSafetyLevel, - DirectMessagesConversationTimeline -> DeciderKey.EnableDirectMessagesConversationTimelineSafetyLevel, - DirectMessagesInbox -> DeciderKey.EnableDirectMessagesInboxSafetyLevel, - DirectMessagesMutedUsers -> DeciderKey.EnableDirectMessagesMutedUsersSafetyLevel, - DirectMessagesPinned -> DeciderKey.EnableDirectMessagesPinnedSafetyLevel, - DirectMessagesSearch -> DeciderKey.EnableDirectMessagesSearchSafetyLevel, - EditHistoryTimeline -> DeciderKey.EnableEditHistoryTimelineSafetyLevel, - ElevatedQuoteTweetTimeline -> DeciderKey.EnableElevatedQuoteTweetTimelineSafetyLevel, - EmbeddedTweet -> DeciderKey.EnableEmbeddedTweetSafetyLevel, - EmbedsPublicInterestNotice -> DeciderKey.EnableEmbedsPublicInterestNoticeSafetyLevel, - EmbedTweetMarkup -> DeciderKey.EnableEmbedTweetMarkupSafetyLevel, - FilterAll -> DeciderKey.EnableFilterAllSafetyLevel, - FilterAllPlaceholder -> DeciderKey.EnableFilterAllPlaceholderSafetyLevel, - FilterNone -> DeciderKey.EnableFilterNoneSafetyLevel, - FilterDefault -> DeciderKey.EnableFilterDefaultSafetyLevel, - FollowedTopicsTimeline -> DeciderKey.EnableFollowedTopicsTimelineSafetyLevel, - FollowerConnections -> DeciderKey.EnableFollowerConnectionsSafetyLevel, - FollowingAndFollowersUserList -> DeciderKey.EnableFollowingAndFollowersUserListSafetyLevel, - ForDevelopmentOnly -> DeciderKey.EnableForDevelopmentOnlySafetyLevel, - FriendsFollowingList -> DeciderKey.EnableFriendsFollowingListSafetyLevel, - GraphqlDefault -> DeciderKey.EnableGraphqlDefaultSafetyLevel, - GryphonDecksAndColumns -> DeciderKey.EnableGryphonDecksAndColumnsSafetyLevel, - HumanizationNudge -> DeciderKey.EnableHumanizationNudgeSafetyLevel, - KitchenSinkDevelopment -> DeciderKey.EnableKitchenSinkDevelopmentSafetyLevel, - ListHeader -> DeciderKey.EnableListHeaderSafetyLevel, - ListMemberships -> DeciderKey.EnableListMembershipsSafetyLevel, - ListOwnerships -> DeciderKey.EnableListOwnershipsSafetyLevel, - ListRecommendations -> DeciderKey.EnableListRecommendationsSafetyLevel, - ListSearch -> DeciderKey.EnableListSearchSafetyLevel, - ListSubscriptions -> DeciderKey.EnableListSubscriptionsSafetyLevel, - LiveVideoTimeline -> DeciderKey.EnableLiveVideoTimelineSafetyLevel, - LivePipelineEngagementCounts -> DeciderKey.EnableLivePipelineEngagementCountsSafetyLevel, - MagicRecs -> DeciderKey.EnableMagicRecsSafetyLevel, - MagicRecsAggressive -> DeciderKey.EnableMagicRecsAggressiveSafetyLevel, - MagicRecsAggressiveV2 -> DeciderKey.EnableMagicRecsAggressiveV2SafetyLevel, - MagicRecsV2 -> DeciderKey.EnableMagicRecsV2SafetyLevel, - Minimal -> DeciderKey.EnableMinimalSafetyLevel, - ModeratedTweetsTimeline -> DeciderKey.EnableModeratedTweetsTimelineSafetyLevel, - Moments -> DeciderKey.EnableMomentsSafetyLevel, - NearbyTimeline -> DeciderKey.EnableNearbyTimelineSafetyLevel, - NewUserExperience -> DeciderKey.EnableNewUserExperienceSafetyLevel, - NotificationsIbis -> DeciderKey.EnableNotificationsIbisSafetyLevel, - NotificationsPlatform -> DeciderKey.EnableNotificationsPlatformSafetyLevel, - NotificationsPlatformPush -> DeciderKey.EnableNotificationsPlatformPushSafetyLevel, - NotificationsQig -> DeciderKey.EnableNotificationsQig, - NotificationsRead -> DeciderKey.EnableNotificationsReadSafetyLevel, - NotificationsTimelineDeviceFollow -> DeciderKey.EnableNotificationsTimelineDeviceFollowSafetyLevel, - NotificationsWrite -> DeciderKey.EnableNotificationsWriteSafetyLevel, - NotificationsWriterV2 -> DeciderKey.EnableNotificationsWriterV2SafetyLevel, - NotificationsWriterTweetHydrator -> DeciderKey.EnableNotificationsWriterTweetHydratorSafetyLevel, - ProfileMixerMedia -> DeciderKey.EnableProfileMixeMediaSafetyLevel, - ProfileMixerFavorites -> DeciderKey.EnableProfileMixerFavoritesSafetyLevel, - QuickPromoteTweetEligibility -> DeciderKey.EnableQuickPromoteTweetEligibilitySafetyLevel, - QuoteTweetTimeline -> DeciderKey.EnableQuoteTweetTimelineSafetyLevel, - QuotedTweetRules -> DeciderKey.EnableQuotedTweetRulesSafetyLevel, - Recommendations -> DeciderKey.EnableRecommendationsSafetyLevel, - RecosVideo -> DeciderKey.EnableRecosVideoSafetyLevel, - RecosWritePath -> DeciderKey.EnableRecosWritePathSafetyLevel, - RepliesGrouping -> DeciderKey.EnableRepliesGroupingSafetyLevel, - ReportCenter -> DeciderKey.EnableReportCenterSafetyLevel, - ReturningUserExperience -> DeciderKey.EnableReturningUserExperienceSafetyLevel, - ReturningUserExperienceFocalTweet -> DeciderKey.EnableReturningUserExperienceFocalTweetSafetyLevel, - Revenue -> DeciderKey.EnableRevenueSafetyLevel, - RitoActionedTweetTimeline -> DeciderKey.EnableRitoActionedTweetTimelineSafetyLevel, - SafeSearchMinimal -> DeciderKey.EnableSafeSearchMinimalSafetyLevel, - SafeSearchStrict -> DeciderKey.EnableSafeSearchStrictSafetyLevel, - SearchMixerSrpMinimal -> DeciderKey.EnableSearchMixerSrpMinimalSafetyLevel, - SearchMixerSrpStrict -> DeciderKey.EnableSearchMixerSrpStrictSafetyLevel, - SearchHydration -> DeciderKey.EnableSearchHydration, - SearchLatest -> DeciderKey.EnableSearchLatest, - SearchPeopleSrp -> DeciderKey.EnableSearchPeopleSrp, - SearchPeopleTypeahead -> DeciderKey.EnableSearchPeopleTypeahead, - SearchPhoto -> DeciderKey.EnableSearchPhoto, - SearchTrendTakeoverPromotedTweet -> DeciderKey.EnableSearchTrendTakeoverPromotedTweet, - SearchTop -> DeciderKey.EnableSearchTop, - SearchTopQig -> DeciderKey.EnableSearchTopQig, - SearchVideo -> DeciderKey.EnableSearchVideo, - SearchBlenderUserRules -> DeciderKey.EnableSearchLatestUserRules, - SearchLatestUserRules -> DeciderKey.EnableSearchLatestUserRules, - ShoppingManagerSpyMode -> DeciderKey.EnableShoppingManagerSpyModeSafetyLevel, - SignalsReactions -> DeciderKey.EnableSignalsReactions, - SignalsTweetReactingUsers -> DeciderKey.EnableSignalsTweetReactingUsers, - SocialProof -> DeciderKey.EnableSocialProof, - SoftInterventionPivot -> DeciderKey.EnableSoftInterventionPivot, - SpaceFleetline -> DeciderKey.EnableSpaceFleetlineSafetyLevel, - SpaceHomeTimelineUpranking -> DeciderKey.EnableSpaceHomeTimelineUprankingSafetyLevel, - SpaceJoinScreen -> DeciderKey.EnableSpaceJoinScreenSafetyLevel, - SpaceNotifications -> DeciderKey.EnableSpaceNotificationsSafetyLevel, - Spaces -> DeciderKey.EnableSpacesSafetyLevel, - SpacesParticipants -> DeciderKey.EnableSpacesParticipantsSafetyLevel, - SpacesSellerApplicationStatus -> DeciderKey.EnableSpacesSellerApplicationStatus, - SpacesSharing -> DeciderKey.EnableSpacesSharingSafetyLevel, - SpaceTweetAvatarHomeTimeline -> DeciderKey.EnableSpaceTweetAvatarHomeTimelineSafetyLevel, - StickersTimeline -> DeciderKey.EnableStickersTimelineSafetyLevel, - StratoExtLimitedEngagements -> DeciderKey.EnableStratoExtLimitedEngagementsSafetyLevel, - StreamServices -> DeciderKey.EnableStreamServicesSafetyLevel, - SuperFollowerConnections -> DeciderKey.EnableSuperFollowerConnectionsSafetyLevel, - SuperLike -> DeciderKey.EnableSuperLikeSafetyLevel, - Test -> DeciderKey.EnableTestSafetyLevel, - TimelineContentControls -> DeciderKey.EnableTimelineContentControlsSafetyLevel, - TimelineConversations -> DeciderKey.EnableTimelineConversationsSafetyLevel, - TimelineConversationsDownranking -> DeciderKey.EnableTimelineConversationsDownrankingSafetyLevel, - TimelineConversationsDownrankingMinimal -> DeciderKey.EnableTimelineConversationsDownrankingMinimalSafetyLevel, - TimelineFollowingActivity -> DeciderKey.EnableTimelineFollowingActivitySafetyLevel, - TimelineHome -> DeciderKey.EnableTimelineHomeSafetyLevel, - TimelineHomeCommunities -> DeciderKey.EnableTimelineHomeCommunitiesSafetyLevel, - TimelineHomeHydration -> DeciderKey.EnableTimelineHomeHydrationSafetyLevel, - TimelineHomePromotedHydration -> DeciderKey.EnableTimelineHomePromotedHydrationSafetyLevel, - TimelineHomeRecommendations -> DeciderKey.EnableTimelineHomeRecommendationsSafetyLevel, - TimelineHomeTopicFollowRecommendations -> DeciderKey.EnableTimelineHomeTopicFollowRecommendationsSafetyLevel, - TimelineScorer -> DeciderKey.EnableTimelineScorerSafetyLevel, - TopicsLandingPageTopicRecommendations -> DeciderKey.EnableTopicsLandingPageTopicRecommendationsSafetyLevel, - ExploreRecommendations -> DeciderKey.EnableExploreRecommendationsSafetyLevel, - TimelineInjection -> DeciderKey.EnableTimelineInjectionSafetyLevel, - TimelineMentions -> DeciderKey.EnableTimelineMentionsSafetyLevel, - TimelineModeratedTweetsHydration -> DeciderKey.EnableTimelineModeratedTweetsHydrationSafetyLevel, - TimelineHomeLatest -> DeciderKey.EnableTimelineHomeLatestSafetyLevel, - TimelineLikedBy -> DeciderKey.EnableTimelineLikedBySafetyLevel, - TimelineRetweetedBy -> DeciderKey.EnableTimelineRetweetedBySafetyLevel, - TimelineSuperLikedBy -> DeciderKey.EnableTimelineSuperLikedBySafetyLevel, - TimelineBookmark -> DeciderKey.EnableTimelineBookmarkSafetyLevel, - TimelineMedia -> DeciderKey.EnableTimelineMediaSafetyLevel, - TimelineReactiveBlending -> DeciderKey.EnableTimelineReactiveBlendingSafetyLevel, - TimelineFavorites -> DeciderKey.EnableTimelineFavoritesSafetyLevel, - TimelineFavoritesSelfView -> DeciderKey.EnableSelfViewTimelineFavoritesSafetyLevel, - TimelineLists -> DeciderKey.EnableTimelineListsSafetyLevel, - TimelineProfile -> DeciderKey.EnableTimelineProfileSafetyLevel, - TimelineProfileAll -> DeciderKey.EnableTimelineProfileAllSafetyLevel, - TimelineProfileSpaces -> DeciderKey.EnableTimelineProfileSpacesSafetyLevel, - TimelineProfileSuperFollows -> DeciderKey.EnableTimelineProfileSuperFollowsSafetyLevel, - TimelineFocalTweet -> DeciderKey.EnableTweetTimelineFocalTweetSafetyLevel, - TweetDetailWithInjectionsHydration -> DeciderKey.EnableTweetDetailWithInjectionsHydrationSafetyLevel, - Tombstoning -> DeciderKey.EnableTombstoningSafetyLevel, - TopicRecommendations -> DeciderKey.EnableTopicRecommendationsSafetyLevel, - TrendsRepresentativeTweet -> DeciderKey.EnableTrendsRepresentativeTweetSafetyLevel, - TrustedFriendsUserList -> DeciderKey.EnableTrustedFriendsUserListSafetyLevel, - TwitterDelegateUserList -> DeciderKey.EnableTwitterDelegateUserListSafetyLevel, - TweetDetail -> DeciderKey.EnableTweetDetailSafetyLevel, - TweetDetailNonToo -> DeciderKey.EnableTweetDetailNonTooSafetyLevel, - TweetEngagers -> DeciderKey.EnableTweetEngagersSafetyLevel, - TweetReplyNudge -> DeciderKey.EnableTweetReplyNudgeSafetyLevel, - TweetScopedTimeline -> DeciderKey.EnableTweetScopedTimelineSafetyLevel, - TweetWritesApi -> DeciderKey.EnableTweetWritesApiSafetyLevel, - TwitterArticleCompose -> DeciderKey.EnableTwitterArticleComposeSafetyLevel, - TwitterArticleProfileTab -> DeciderKey.EnableTwitterArticleProfileTabSafetyLevel, - TwitterArticleRead -> DeciderKey.EnableTwitterArticleReadSafetyLevel, - UserProfileHeader -> DeciderKey.EnableUserProfileHeaderSafetyLevel, - UserMilestoneRecommendation -> DeciderKey.EnableUserMilestoneRecommendationSafetyLevel, - UserScopedTimeline -> DeciderKey.EnableUserScopedTimelineSafetyLevel, - UserSearchSrp -> DeciderKey.EnableUserSearchSrpSafetyLevel, - UserSearchTypeahead -> DeciderKey.EnableUserSearchTypeaheadSafetyLevel, - UserSelfViewOnly -> DeciderKey.EnableUserSelfViewOnlySafetyLevel, - UserSettings -> DeciderKey.EnableUserSettingsSafetyLevel, - VideoAds -> DeciderKey.EnableVideoAdsSafetyLevel, - WritePathLimitedActionsEnforcement -> DeciderKey.EnableWritePathLimitedActionsEnforcementSafetyLevel, - ZipbirdConsumerArchives -> DeciderKey.EnableZipbirdConsumerArchivesSafetyLevel, - TweetAward -> DeciderKey.EnableTweetAwardSafetyLevel, - ) - - val BoolToDeciderMap: Map[Param[Boolean], DeciderKey.Value] = Map( - RuleParams.TweetConversationControlEnabledParam -> - DeciderKey.EnableTweetConversationControlRules, - RuleParams.CommunityTweetsEnabledParam -> - DeciderKey.EnableCommunityTweetsControlRules, - RuleParams.DropCommunityTweetWithUndefinedCommunityRuleEnabledParam -> - DeciderKey.EnableDropCommunityTweetWithUndefinedCommunityRule, - TimelineConversationsDownrankingSpecificParams.EnablePSpammyTweetDownrankConvosLowQualityParam -> - DeciderKey.EnablePSpammyTweetDownrankConvosLowQuality, - RuleParams.EnableHighPSpammyTweetScoreSearchTweetLabelDropRuleParam -> - DeciderKey.EnableHighPSpammyTweetScoreSearchTweetLabelDropRule, - TimelineConversationsDownrankingSpecificParams.EnableRitoActionedTweetDownrankConvosLowQualityParam -> - DeciderKey.EnableRitoActionedTweetDownrankConvosLowQuality, - RuleParams.EnableSmyteSpamTweetRuleParam -> - DeciderKey.EnableSmyteSpamTweetRule, - RuleParams.EnableHighSpammyTweetContentScoreSearchLatestTweetLabelDropRuleParam -> - DeciderKey.EnableHighSpammyTweetContentScoreSearchLatestTweetLabelDropRule, - RuleParams.EnableHighSpammyTweetContentScoreSearchTopTweetLabelDropRuleParam -> - DeciderKey.EnableHighSpammyTweetContentScoreSearchTopTweetLabelDropRule, - RuleParams.EnableHighSpammyTweetContentScoreTrendsTopTweetLabelDropRuleParam -> - DeciderKey.EnableHighSpammyTweetContentScoreTrendsTopTweetLabelDropRule, - RuleParams.EnableHighSpammyTweetContentScoreTrendsLatestTweetLabelDropRuleParam -> - DeciderKey.EnableHighSpammyTweetContentScoreTrendsLatestTweetLabelDropRule, - TimelineConversationsDownrankingSpecificParams.EnableHighSpammyTweetContentScoreConvoDownrankAbusiveQualityRuleParam -> - DeciderKey.EnableHighSpammyTweetContentScoreConvoDownrankAbusiveQualityRule, - TimelineConversationsDownrankingSpecificParams.EnableHighCryptospamScoreConvoDownrankAbusiveQualityRuleParam -> - DeciderKey.EnableHighCryptospamScoreConvoDownrankAbusiveQualityRule, - RuleParams.EnableGoreAndViolenceTopicHighRecallTweetLabelRule -> - DeciderKey.EnableGoreAndViolenceTopicHighRecallTweetLabelRule, - RuleParams.EnableLimitRepliesFollowersConversationRule -> - DeciderKey.EnableLimitRepliesFollowersConversationRule, - RuleParams.EnableSearchBasicBlockMuteRulesParam -> DeciderKey.EnableSearchBasicBlockMuteRules, - RuleParams.EnableBlinkBadDownrankingRuleParam -> - DeciderKey.EnableBlinkBadDownrankingRule, - RuleParams.EnableBlinkWorstDownrankingRuleParam -> - DeciderKey.EnableBlinkWorstDownrankingRule, - RuleParams.EnableCopypastaSpamDownrankConvosAbusiveQualityRule -> - DeciderKey.EnableCopypastaSpamDownrankConvosAbusiveQualityRule, - RuleParams.EnableCopypastaSpamSearchDropRule -> - DeciderKey.EnableCopypastaSpamSearchDropRule, - RuleParams.EnableSpammyUserModelTweetDropRuleParam -> - DeciderKey.EnableSpammyUserModelHighPrecisionDropTweetRule, - RuleParams.EnableAvoidNsfwRulesParam -> - DeciderKey.EnableAvoidNsfwRules, - RuleParams.EnableReportedTweetInterstitialRule -> - DeciderKey.EnableReportedTweetInterstitialRule, - RuleParams.EnableReportedTweetInterstitialSearchRule -> - DeciderKey.EnableReportedTweetInterstitialSearchRule, - RuleParams.EnableDropExclusiveTweetContentRule -> - DeciderKey.EnableDropExclusiveTweetContentRule, - RuleParams.EnableDropExclusiveTweetContentRuleFailClosed -> - DeciderKey.EnableDropExclusiveTweetContentRuleFailClosed, - RuleParams.EnableTombstoneExclusiveQtProfileTimelineParam -> - DeciderKey.EnableTombstoneExclusiveQtProfileTimelineParam, - RuleParams.EnableDropAllExclusiveTweetsRuleParam -> DeciderKey.EnableDropAllExclusiveTweetsRule, - RuleParams.EnableDropAllExclusiveTweetsRuleFailClosedParam -> DeciderKey.EnableDropAllExclusiveTweetsRuleFailClosed, - RuleParams.EnableDownrankSpamReplySectioningRuleParam -> - DeciderKey.EnableDownrankSpamReplySectioningRule, - RuleParams.EnableNsfwTextSectioningRuleParam -> - DeciderKey.EnableNsfwTextSectioningRule, - RuleParams.EnableSearchIpiSafeSearchWithoutUserInQueryDropRule -> DeciderKey.EnableSearchIpiSafeSearchWithoutUserInQueryDropRule, - RuleParams.EnableTimelineHomePromotedTweetHealthEnforcementRules -> DeciderKey.EnableTimelineHomePromotedTweetHealthEnforcementRules, - RuleParams.EnableMutedKeywordFilteringSpaceTitleNotificationsRuleParam -> DeciderKey.EnableMutedKeywordFilteringSpaceTitleNotificationsRule, - RuleParams.EnableDropTweetsWithGeoRestrictedMediaRuleParam -> DeciderKey.EnableDropTweetsWithGeoRestrictedMediaRule, - RuleParams.EnableDropAllTrustedFriendsTweetsRuleParam -> DeciderKey.EnableDropAllTrustedFriendsTweetsRule, - RuleParams.EnableDropTrustedFriendsTweetContentRuleParam -> DeciderKey.EnableDropTrustedFriendsTweetContentRule, - RuleParams.EnableDropAllCollabInvitationTweetsRuleParam -> DeciderKey.EnableDropCollabInvitationTweetsRule, - RuleParams.EnableNsfwTextHighPrecisionDropRuleParam -> DeciderKey.EnableNsfwTextHighPrecisionDropRule, - RuleParams.EnableLikelyIvsUserLabelDropRule -> DeciderKey.EnableLikelyIvsUserLabelDropRule, - RuleParams.EnableCardUriRootDomainCardDenylistRule -> DeciderKey.EnableCardUriRootDomainDenylistRule, - RuleParams.EnableCommunityNonMemberPollCardRule -> DeciderKey.EnableCommunityNonMemberPollCardRule, - RuleParams.EnableCommunityNonMemberPollCardRuleFailClosed -> DeciderKey.EnableCommunityNonMemberPollCardRuleFailClosed, - RuleParams.EnableExperimentalNudgeEnabledParam -> DeciderKey.EnableExperimentalNudgeLabelRule, - RuleParams.NsfwHighPrecisionUserLabelAvoidTweetRuleEnabledParam -> DeciderKey.NsfwHighPrecisionUserLabelAvoidTweetRuleEnabledParam, - RuleParams.EnableNewAdAvoidanceRulesParam -> DeciderKey.EnableNewAdAvoidanceRules, - RuleParams.EnableNsfaHighRecallAdAvoidanceParam -> DeciderKey.EnableNsfaHighRecallAdAvoidanceParam, - RuleParams.EnableNsfaKeywordsHighPrecisionAdAvoidanceParam -> DeciderKey.EnableNsfaKeywordsHighPrecisionAdAvoidanceParam, - RuleParams.EnableStaleTweetDropRuleParam -> DeciderKey.EnableStaleTweetDropRuleParam, - RuleParams.EnableStaleTweetDropRuleFailClosedParam -> DeciderKey.EnableStaleTweetDropRuleFailClosedParam, - RuleParams.EnableDeleteStateTweetRulesParam -> DeciderKey.EnableDeleteStateTweetRules, - RuleParams.EnableSpacesSharingNsfwDropRulesParam -> DeciderKey.EnableSpacesSharingNsfwDropRulesParam, - RuleParams.EnableViewerIsSoftUserDropRuleParam -> DeciderKey.EnableViewerIsSoftUserDropRuleParam, - RuleParams.EnablePdnaQuotedTweetTombstoneRuleParam -> DeciderKey.EnablePdnaQuotedTweetTombstoneRule, - RuleParams.EnableSpamQuotedTweetTombstoneRuleParam -> DeciderKey.EnableSpamQuotedTweetTombstoneRule, - RuleParams.EnableNsfwHpQuotedTweetDropRuleParam -> DeciderKey.EnableNsfwHpQuotedTweetDropRule, - RuleParams.EnableNsfwHpQuotedTweetTombstoneRuleParam -> DeciderKey.EnableNsfwHpQuotedTweetTombstoneRule, - RuleParams.EnableInnerQuotedTweetViewerBlocksAuthorInterstitialRuleParam -> DeciderKey.EnableInnerQuotedTweetViewerBlocksAuthorInterstitialRule, - RuleParams.EnableInnerQuotedTweetViewerMutesAuthorInterstitialRuleParam -> DeciderKey.EnableInnerQuotedTweetViewerMutesAuthorInterstitialRule, - RuleParams.EnableToxicReplyFilteringConversationRulesParam -> DeciderKey.VisibilityLibraryEnableToxicReplyFilterConversation, - RuleParams.EnableToxicReplyFilteringNotificationsRulesParam -> DeciderKey.VisibilityLibraryEnableToxicReplyFilterNotifications, - RuleParams.EnableLegacySensitiveMediaHomeTimelineRulesParam -> DeciderKey.EnableLegacySensitiveMediaRulesHomeTimeline, - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsHomeTimelineRulesParam -> DeciderKey.EnableNewSensitiveMediaSettingsInterstitialRulesHomeTimeline, - RuleParams.EnableLegacySensitiveMediaConversationRulesParam -> DeciderKey.EnableLegacySensitiveMediaRulesConversation, - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsConversationRulesParam -> DeciderKey.EnableNewSensitiveMediaSettingsInterstitialRulesConversation, - RuleParams.EnableLegacySensitiveMediaProfileTimelineRulesParam -> DeciderKey.EnableLegacySensitiveMediaRulesProfileTimeline, - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsProfileTimelineRulesParam -> DeciderKey.EnableNewSensitiveMediaSettingsInterstitialRulesProfileTimeline, - RuleParams.EnableLegacySensitiveMediaTweetDetailRulesParam -> DeciderKey.EnableLegacySensitiveMediaRulesTweetDetail, - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsTweetDetailRulesParam -> DeciderKey.EnableNewSensitiveMediaSettingsInterstitialRulesTweetDetail, - RuleParams.EnableLegacySensitiveMediaDirectMessagesRulesParam -> DeciderKey.EnableLegacySensitiveMediaRulesDirectMessages, - RuleParams.EnableAbusiveBehaviorDropRuleParam -> DeciderKey.EnableAbusiveBehaviorDropRule, - RuleParams.EnableAbusiveBehaviorInterstitialRuleParam -> DeciderKey.EnableAbusiveBehaviorInterstitialRule, - RuleParams.EnableAbusiveBehaviorLimitedEngagementsRuleParam -> DeciderKey.EnableAbusiveBehaviorLimitedEngagementsRule, - RuleParams.EnableNotGraduatedDownrankConvosAbusiveQualityRuleParam -> DeciderKey.EnableNotGraduatedDownrankConvosAbusiveQualityRule, - RuleParams.EnableNotGraduatedSearchDropRuleParam -> DeciderKey.EnableNotGraduatedSearchDropRule, - RuleParams.EnableNotGraduatedDropRuleParam -> DeciderKey.EnableNotGraduatedDropRule, - RuleParams.EnableFosnrRuleParam -> DeciderKey.EnableFosnrRules, - RuleParams.EnableAuthorBlocksViewerDropRuleParam -> DeciderKey.EnableAuthorBlocksViewerDropRule - ) - - def config( - deciderGateBuilder: DeciderGateBuilder, - logger: Logger, - statsReceiver: StatsReceiver, - SafetyLevel: SafetyLevel - ): Config = { - - object UserOrGuestOrRequest extends RecipientBuilder { - private val scopedStats = statsReceiver.scope("decider_recipient") - private val userIdDefinedCounter = scopedStats.counter("user_id_defined") - private val userIdNotDefinedCounter = scopedStats.counter("user_id_undefined") - private val guestIdDefinedCounter = scopedStats.counter("guest_id_defined") - private val guestIdNotDefinedCounter = scopedStats.counter("guest_id_undefined") - private val noIdCounter = scopedStats.counter("no_id_defined") - - def apply(requestContext: BaseRequestContext): Option[Recipient] = requestContext match { - case c: WithUserId if c.userId.isDefined => - userIdDefinedCounter.incr() - c.userId.map(SimpleRecipient) - case c: WithGuestId if c.guestId.isDefined => - guestIdDefinedCounter.incr() - c.guestId.map(GuestRecipient) - case c: WithGuestId => - guestIdNotDefinedCounter.incr() - RecipientBuilder.Request(c) - case _: WithUserId => - userIdNotDefinedCounter.incr() - None - case _ => - logger.warning("Request Context with no user or guest id trait found: " + requestContext) - noIdCounter.incr() - None - } - } - - val boolOverrides = BoolToDeciderMap.map { - case (param, deciderKey) => - param.optionalOverrideValue( - DeciderSwitchOverrideValue( - feature = deciderGateBuilder.keyToFeature(deciderKey), - enabledValue = true, - disabledValueOption = Some(false), - recipientBuilder = UserOrGuestOrRequest - ) - ) - }.toSeq - - val safetyLevelOverride = SafetyLevel.enabledParam.optionalOverrideValue( - DeciderSwitchOverrideValue( - feature = deciderGateBuilder.keyToFeature(SafetyLevelToDeciderMap(SafetyLevel)), - enabledValue = true, - recipientBuilder = UserOrGuestOrRequest - ) - ) - - BaseConfigBuilder(boolOverrides :+ safetyLevelOverride).build("VisibilityDeciders") - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/VisibilityExperimentsConfig.scala b/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/VisibilityExperimentsConfig.scala deleted file mode 100644 index faf25ee2a..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/VisibilityExperimentsConfig.scala +++ /dev/null @@ -1,33 +0,0 @@ -package com.twitter.visibility.configapi.configs - -import com.twitter.timelines.configapi.Config -import com.twitter.visibility.configapi.params.RuleParams._ -import com.twitter.visibility.configapi.params.VisibilityExperiments._ -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.SafetyLevel._ - -private[visibility] object VisibilityExperimentsConfig { - import ExperimentsHelper._ - - val TestExperimentConfig: Config = mkABExperimentConfig(TestExperiment, TestHoldbackParam) - - val NotGraduatedUserLabelRuleHoldbackExperimentConfig: Config = - mkABExperimentConfig( - NotGraduatedUserLabelRuleExperiment, - NotGraduatedUserLabelRuleHoldbackExperimentParam - ) - - def config(safetyLevel: SafetyLevel): Seq[Config] = { - - val experimentConfigs = safetyLevel match { - - case Test => - Seq(TestExperimentConfig) - - case _ => Seq(NotGraduatedUserLabelRuleHoldbackExperimentConfig) - } - - experimentConfigs - } - -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/VisibilityFeatureSwitches.scala b/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/VisibilityFeatureSwitches.scala deleted file mode 100644 index 2fa33cd57..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/VisibilityFeatureSwitches.scala +++ /dev/null @@ -1,74 +0,0 @@ -package com.twitter.visibility.configapi.configs - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.logging.Logger -import com.twitter.timelines.configapi._ -import com.twitter.util.Time -import com.twitter.visibility.configapi.params.FSEnumRuleParam -import com.twitter.visibility.configapi.params.FSRuleParams._ - -private[visibility] object VisibilityFeatureSwitches { - - val booleanFsOverrides: Seq[OptionalOverride[Boolean]] = - FeatureSwitchOverrideUtil.getBooleanFSOverrides( - AgeGatingAdultContentExperimentRuleEnabledParam, - CommunityTweetCommunityUnavailableLimitedActionsRulesEnabledParam, - CommunityTweetDropProtectedRuleEnabledParam, - CommunityTweetDropRuleEnabledParam, - CommunityTweetLimitedActionsRulesEnabledParam, - CommunityTweetMemberRemovedLimitedActionsRulesEnabledParam, - CommunityTweetNonMemberLimitedActionsRuleEnabledParam, - NsfwAgeBasedDropRulesHoldbackParam, - SkipTweetDetailLimitedEngagementRuleEnabledParam, - StaleTweetLimitedActionsRulesEnabledParam, - TrustedFriendsTweetLimitedEngagementsRuleEnabledParam, - FosnrFallbackDropRulesEnabledParam, - FosnrRulesEnabledParam - ) - - val doubleFsOverrides: Seq[OptionalOverride[Double]] = - FeatureSwitchOverrideUtil.getBoundedDoubleFSOverrides( - HighSpammyTweetContentScoreSearchTopProdTweetLabelDropRuleThresholdParam, - HighSpammyTweetContentScoreSearchLatestProdTweetLabelDropRuleThresholdParam, - HighSpammyTweetContentScoreTrendTopTweetLabelDropRuleThresholdParam, - HighSpammyTweetContentScoreTrendLatestTweetLabelDropRuleThresholdParam, - HighSpammyTweetContentScoreConvoDownrankAbusiveQualityThresholdParam, - HighToxicityModelScoreSpaceThresholdParam, - AdAvoidanceHighToxicityModelScoreThresholdParam, - AdAvoidanceReportedTweetModelScoreThresholdParam, - ) - - val timeFsOverrides: Seq[OptionalOverride[Time]] = - FeatureSwitchOverrideUtil.getTimeFromStringFSOverrides() - - val stringSeqFeatureSwitchOverrides: Seq[OptionalOverride[Seq[String]]] = - FeatureSwitchOverrideUtil.getStringSeqFSOverrides( - CountrySpecificNsfwContentGatingCountriesParam, - AgeGatingAdultContentExperimentCountriesParam, - CardUriRootDomainDenyListParam - ) - - val enumFsParams: Seq[FSEnumRuleParam[_ <: Enumeration]] = Seq() - - val mkOptionalEnumFsOverrides: (StatsReceiver, Logger) => Seq[OptionalOverride[_]] = { - (statsReceiver: StatsReceiver, logger: Logger) => - FeatureSwitchOverrideUtil.getEnumFSOverrides( - statsReceiver, - logger, - enumFsParams: _* - ) - } - - def overrides(statsReceiver: StatsReceiver, logger: Logger): Seq[OptionalOverride[_]] = { - val enumOverrides = mkOptionalEnumFsOverrides(statsReceiver, logger) - booleanFsOverrides ++ - doubleFsOverrides ++ - timeFsOverrides ++ - stringSeqFeatureSwitchOverrides ++ - enumOverrides - } - - def config(statsReceiver: StatsReceiver, logger: Logger): BaseConfig = - BaseConfigBuilder(overrides(statsReceiver.scope("features_switches"), logger)) - .build("VisibilityFeatureSwitches") -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/overrides/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/overrides/BUILD deleted file mode 100644 index b59bedb48..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/overrides/BUILD +++ /dev/null @@ -1,9 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "decider", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/overrides/VisibilityLibraryDeciderOverrides.scala b/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/overrides/VisibilityLibraryDeciderOverrides.scala deleted file mode 100644 index 842309be7..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/configs/overrides/VisibilityLibraryDeciderOverrides.scala +++ /dev/null @@ -1,24 +0,0 @@ -package com.twitter.visibility.configapi.configs.overrides - -import com.twitter.decider.LocalOverrides - -object VisibilityLibraryDeciderOverrides - extends LocalOverrides.Namespace("visibility-library", "") { - - val EnableLocalizedTombstoneOnVisibilityResults = feature( - "visibility_library_enable_localized_tombstones_on_visibility_results") - - val EnableLocalizedInterstitialGenerator: LocalOverrides.Override = - feature("visibility_library_enable_localized_interstitial_generator") - - val EnableInnerQuotedTweetViewerBlocksAuthorInterstitialRule: LocalOverrides.Override = - feature("visibility_library_enable_inner_quoted_tweet_viewer_blocks_author_interstitial_rule") - val EnableInnerQuotedTweetViewerMutesAuthorInterstitialRule: LocalOverrides.Override = - feature("visibility_library_enable_inner_quoted_tweet_viewer_mutes_author_interstitial_rule") - - val EnableBackendLimitedActions: LocalOverrides.Override = - feature("visibility_library_enable_backend_limited_actions") - - val disableLegacyInterstitialFilteredReason: LocalOverrides.Override = feature( - "visibility_library_disable_legacy_interstitial_filtered_reason") -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/BUILD deleted file mode 100644 index b2855c4c6..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/BUILD +++ /dev/null @@ -1,15 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "configapi/configapi-core", - "finagle/finagle-stats", - "visibility/common/src/main/scala/com/twitter/visibility/common:model_thresholds", - ], - exports = [ - "visibility/common/src/main/scala/com/twitter/visibility/common:model_thresholds", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/FSRuleParams.scala b/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/FSRuleParams.scala deleted file mode 100644 index 270db45aa..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/FSRuleParams.scala +++ /dev/null @@ -1,213 +0,0 @@ -package com.twitter.visibility.configapi.params - -import com.twitter.timelines.configapi.Bounded -import com.twitter.timelines.configapi.FSBoundedParam -import com.twitter.timelines.configapi.FSName -import com.twitter.timelines.configapi.FeatureName -import com.twitter.timelines.configapi.HasTimeConversion -import com.twitter.timelines.configapi.TimeConversion -import com.twitter.util.Time -import com.twitter.visibility.common.ModelScoreThresholds - -private[visibility] object FeatureSwitchKey extends Enumeration { - type FeatureSwitchKey = String - - final val HighSpammyTweetContentScoreSearchTopProdTweetLabelDropFuleThreshold = - "high_spammy_tweet_content_score_search_top_prod_tweet_label_drop_rule_threshold" - final val HighSpammyTweetContentScoreSearchLatestProdTweetLabelDropRuleThreshold = - "high_spammy_tweet_content_score_search_latest_prod_tweet_label_drop_rule_threshold" - final val HighSpammyTweetContentScoreTrendTopTweetLabelDropRuleThreshold = - "high_spammy_tweet_content_score_trend_top_tweet_label_drop_rule_threshold" - final val HighSpammyTweetContentScoreTrendLatestTweetLabelDropRuleThreshold = - "high_spammy_tweet_content_score_trend_latest_tweet_label_drop_rule_threshold" - final val HighSpammyTweetContentScoreConvoDownrankAbusiveQualityThreshold = - "high_spammy_tweet_content_score_convos_downranking_abusive_quality_threshold" - - final val NsfwAgeBasedDropRulesHoldbackParam = - "nsfw_age_based_drop_rules_holdback" - - final val CommunityTweetDropRuleEnabled = - "community_tweet_drop_rule_enabled" - final val CommunityTweetDropProtectedRuleEnabled = - "community_tweet_drop_protected_rule_enabled" - final val CommunityTweetLimitedActionsRulesEnabled = - "community_tweet_limited_actions_rules_enabled" - final val CommunityTweetMemberRemovedLimitedActionsRulesEnabled = - "community_tweet_member_removed_limited_actions_rules_enabled" - final val CommunityTweetCommunityUnavailableLimitedActionsRulesEnabled = - "community_tweet_community_unavailable_limited_actions_rules_enabled" - final val CommunityTweetNonMemberLimitedActionsRuleEnabled = - "community_tweet_non_member_limited_actions_rule_enabled" - - final val TrustedFriendsTweetLimitedEngagementsRuleEnabled = - "trusted_friends_tweet_limited_engagements_rule_enabled" - - final val CountrySpecificNsfwContentGatingCountries = - "country_specific_nsfw_content_gating_countries" - - final val AgeGatingAdultContentExperimentCountries = - "age_gating_adult_content_experiment_countries" - final val AgeGatingAdultContentExperimentEnabled = - "age_gating_adult_content_experiment_enabled" - - final val HighToxicityModelScoreSpaceThreshold = - "high_toxicity_model_score_space_threshold" - - final val CardUriRootDomainDenyList = "card_uri_root_domain_deny_list" - - final val SkipTweetDetailLimitedEngagementsRuleEnabled = - "skip_tweet_detail_limited_engagements_rule_enabled" - - final val AdAvoidanceHighToxicityModelScoreThreshold = - "ad_avoidance_model_thresholds_high_toxicity_model" - final val AdAvoidanceReportedTweetModelScoreThreshold = - "ad_avoidance_model_thresholds_reported_tweet_model" - - final val StaleTweetLimitedActionsRulesEnabled = - "stale_tweet_limited_actions_rules_enabled" - - final val FosnrFallbackDropRulesEnabled = - "freedom_of_speech_not_reach_fallback_drop_rules_enabled" - final val FosnrRulesEnabled = - "freedom_of_speech_not_reach_rules_enabled" -} - -abstract class FSRuleParam[T](override val name: FeatureName, override val default: T) - extends RuleParam(default) - with FSName - -abstract class FSBoundedRuleParam[T]( - override val name: FeatureName, - override val default: T, - override val min: T, - override val max: T -)( - implicit override val ordering: Ordering[T]) - extends RuleParam(default) - with Bounded[T] - with FSName - -abstract class FSTimeRuleParam[T]( - override val name: FeatureName, - override val default: Time, - override val timeConversion: TimeConversion[T]) - extends RuleParam(default) - with HasTimeConversion[T] - with FSName - -abstract class FSEnumRuleParam[T <: Enumeration]( - override val name: FeatureName, - override val default: T#Value, - override val enum: T) - extends EnumRuleParam(default, enum) - with FSName - -private[visibility] object FSRuleParams { - object HighSpammyTweetContentScoreSearchTopProdTweetLabelDropRuleThresholdParam - extends FSBoundedParam( - FeatureSwitchKey.HighSpammyTweetContentScoreSearchTopProdTweetLabelDropFuleThreshold, - default = ModelScoreThresholds.HighSpammyTweetContentScoreDefaultThreshold, - min = 0, - max = 1) - object HighSpammyTweetContentScoreSearchLatestProdTweetLabelDropRuleThresholdParam - extends FSBoundedParam( - FeatureSwitchKey.HighSpammyTweetContentScoreSearchLatestProdTweetLabelDropRuleThreshold, - default = ModelScoreThresholds.HighSpammyTweetContentScoreDefaultThreshold, - min = 0, - max = 1) - object HighSpammyTweetContentScoreTrendTopTweetLabelDropRuleThresholdParam - extends FSBoundedParam( - FeatureSwitchKey.HighSpammyTweetContentScoreTrendTopTweetLabelDropRuleThreshold, - default = ModelScoreThresholds.HighSpammyTweetContentScoreDefaultThreshold, - min = 0, - max = 1) - object HighSpammyTweetContentScoreTrendLatestTweetLabelDropRuleThresholdParam - extends FSBoundedParam( - FeatureSwitchKey.HighSpammyTweetContentScoreTrendLatestTweetLabelDropRuleThreshold, - default = ModelScoreThresholds.HighSpammyTweetContentScoreDefaultThreshold, - min = 0, - max = 1) - object HighSpammyTweetContentScoreConvoDownrankAbusiveQualityThresholdParam - extends FSBoundedParam( - FeatureSwitchKey.HighSpammyTweetContentScoreConvoDownrankAbusiveQualityThreshold, - default = ModelScoreThresholds.HighSpammyTweetContentScoreDefaultThreshold, - min = 0, - max = 1) - - object CommunityTweetDropRuleEnabledParam - extends FSRuleParam(FeatureSwitchKey.CommunityTweetDropRuleEnabled, true) - - object CommunityTweetDropProtectedRuleEnabledParam - extends FSRuleParam(FeatureSwitchKey.CommunityTweetDropProtectedRuleEnabled, true) - - object CommunityTweetLimitedActionsRulesEnabledParam - extends FSRuleParam(FeatureSwitchKey.CommunityTweetLimitedActionsRulesEnabled, false) - - object CommunityTweetMemberRemovedLimitedActionsRulesEnabledParam - extends FSRuleParam( - FeatureSwitchKey.CommunityTweetMemberRemovedLimitedActionsRulesEnabled, - false) - - object CommunityTweetCommunityUnavailableLimitedActionsRulesEnabledParam - extends FSRuleParam( - FeatureSwitchKey.CommunityTweetCommunityUnavailableLimitedActionsRulesEnabled, - false) - - object CommunityTweetNonMemberLimitedActionsRuleEnabledParam - extends FSRuleParam(FeatureSwitchKey.CommunityTweetNonMemberLimitedActionsRuleEnabled, false) - - object TrustedFriendsTweetLimitedEngagementsRuleEnabledParam - extends FSRuleParam(FeatureSwitchKey.TrustedFriendsTweetLimitedEngagementsRuleEnabled, false) - - object SkipTweetDetailLimitedEngagementRuleEnabledParam - extends FSRuleParam(FeatureSwitchKey.SkipTweetDetailLimitedEngagementsRuleEnabled, false) - - - object NsfwAgeBasedDropRulesHoldbackParam - extends FSRuleParam(FeatureSwitchKey.NsfwAgeBasedDropRulesHoldbackParam, true) - - object CountrySpecificNsfwContentGatingCountriesParam - extends FSRuleParam[Seq[String]]( - FeatureSwitchKey.CountrySpecificNsfwContentGatingCountries, - default = Seq("au")) - - object AgeGatingAdultContentExperimentCountriesParam - extends FSRuleParam[Seq[String]]( - FeatureSwitchKey.AgeGatingAdultContentExperimentCountries, - default = Seq.empty) - object AgeGatingAdultContentExperimentRuleEnabledParam - extends FSRuleParam(FeatureSwitchKey.AgeGatingAdultContentExperimentEnabled, default = false) - - object HighToxicityModelScoreSpaceThresholdParam - extends FSBoundedParam( - FeatureSwitchKey.HighToxicityModelScoreSpaceThreshold, - default = ModelScoreThresholds.HighToxicityModelScoreSpaceDefaultThreshold, - min = 0, - max = 1) - - object CardUriRootDomainDenyListParam - extends FSRuleParam[Seq[String]]( - FeatureSwitchKey.CardUriRootDomainDenyList, - default = Seq.empty) - - object AdAvoidanceHighToxicityModelScoreThresholdParam - extends FSBoundedParam( - FeatureSwitchKey.AdAvoidanceHighToxicityModelScoreThreshold, - default = ModelScoreThresholds.AdAvoidanceHighToxicityModelScoreDefaultThreshold, - min = 0, - max = 1) - - object AdAvoidanceReportedTweetModelScoreThresholdParam - extends FSBoundedParam( - FeatureSwitchKey.AdAvoidanceReportedTweetModelScoreThreshold, - default = ModelScoreThresholds.AdAvoidanceReportedTweetModelScoreDefaultThreshold, - min = 0, - max = 1) - - object StaleTweetLimitedActionsRulesEnabledParam - extends FSRuleParam(FeatureSwitchKey.StaleTweetLimitedActionsRulesEnabled, false) - - object FosnrFallbackDropRulesEnabledParam - extends FSRuleParam(FeatureSwitchKey.FosnrFallbackDropRulesEnabled, false) - object FosnrRulesEnabledParam extends FSRuleParam(FeatureSwitchKey.FosnrRulesEnabled, true) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/GlobalParams.scala b/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/GlobalParams.scala deleted file mode 100644 index c6a960486..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/GlobalParams.scala +++ /dev/null @@ -1,11 +0,0 @@ -package com.twitter.visibility.configapi.params - -import com.twitter.timelines.configapi.Param - -abstract class GlobalParam[T](override val default: T) extends Param(default) { - override val statName: String = s"GlobalParam/${this.getClass.getSimpleName}" -} - -private[visibility] object GlobalParams { - object EnableFetchingLabelMap extends GlobalParam(false) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/LabelSourceParams.scala b/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/LabelSourceParams.scala deleted file mode 100644 index 0f0eaaa2d..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/LabelSourceParams.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.visibility.configapi.params - -import com.twitter.timelines.configapi.Param - -abstract class LabelSourceParam(override val default: Boolean) extends Param(default) { - override val statName: String = s"LabelSourceParam/${this.getClass.getSimpleName}" -} - -private[visibility] object LabelSourceParams { - object FilterLabelsFromBot7174Param extends LabelSourceParam(false) - - object FilterTweetsSmyteAutomationParamA extends LabelSourceParam(false) - object FilterTweetsSmyteAutomationParamB extends LabelSourceParam(false) - object FilterTweetsSmyteAutomationParamAB extends LabelSourceParam(false) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/RuleParams.scala b/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/RuleParams.scala deleted file mode 100644 index a4e28e690..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/RuleParams.scala +++ /dev/null @@ -1,164 +0,0 @@ -package com.twitter.visibility.configapi.params - -import com.twitter.timelines.configapi.EnumParam -import com.twitter.timelines.configapi.Param - -abstract class RuleParam[T](override val default: T) extends Param(default) { - override val statName: String = s"RuleParam/${this.getClass.getSimpleName}" -} - -abstract class EnumRuleParam[T <: Enumeration](override val default: T#Value, override val enum: T) - extends EnumParam(default, enum) { - override val statName: String = s"RuleParam/${this.getClass.getSimpleName}" -} - -private[visibility] object RuleParams { - object True extends RuleParam(true) - object False extends RuleParam(false) - - object TestHoldbackParam extends RuleParam(true) - - object TweetConversationControlEnabledParam extends RuleParam(default = false) - - object EnableLimitRepliesFollowersConversationRule extends RuleParam(default = false) - - object CommunityTweetsEnabledParam extends RuleParam(default = false) - - object DropCommunityTweetWithUndefinedCommunityRuleEnabledParam extends RuleParam(default = false) - - object EnableHighPSpammyTweetScoreSearchTweetLabelDropRuleParam extends RuleParam(false) - - object EnableSmyteSpamTweetRuleParam extends RuleParam(false) - - object EnableHighSpammyTweetContentScoreSearchLatestTweetLabelDropRuleParam - extends RuleParam(false) - - object EnableHighSpammyTweetContentScoreSearchTopTweetLabelDropRuleParam extends RuleParam(false) - - object NotGraduatedUserLabelRuleHoldbackExperimentParam extends RuleParam(default = false) - - object EnableGoreAndViolenceTopicHighRecallTweetLabelRule extends RuleParam(default = false) - - object EnableBlinkBadDownrankingRuleParam extends RuleParam(false) - object EnableBlinkWorstDownrankingRuleParam extends RuleParam(false) - - object EnableHighSpammyTweetContentScoreTrendsTopTweetLabelDropRuleParam - extends RuleParam(default = false) - - object EnableHighSpammyTweetContentScoreTrendsLatestTweetLabelDropRuleParam - extends RuleParam(default = false) - - object EnableCopypastaSpamDownrankConvosAbusiveQualityRule extends RuleParam(default = false) - object EnableCopypastaSpamSearchDropRule extends RuleParam(default = false) - - object EnableSpammyUserModelTweetDropRuleParam extends RuleParam(default = false) - - object EnableAvoidNsfwRulesParam extends RuleParam(false) - - object EnableReportedTweetInterstitialRule extends RuleParam(default = false) - - object EnableReportedTweetInterstitialSearchRule extends RuleParam(default = false) - - object EnableDropExclusiveTweetContentRule extends RuleParam(default = false) - - object EnableDropExclusiveTweetContentRuleFailClosed extends RuleParam(default = false) - - object EnableTombstoneExclusiveQtProfileTimelineParam extends RuleParam(default = false) - - object EnableDropAllExclusiveTweetsRuleParam extends RuleParam(false) - object EnableDropAllExclusiveTweetsRuleFailClosedParam extends RuleParam(false) - - object EnableDownrankSpamReplySectioningRuleParam extends RuleParam(default = false) - object EnableNsfwTextSectioningRuleParam extends RuleParam(default = false) - - object EnableSearchIpiSafeSearchWithoutUserInQueryDropRule extends RuleParam(false) - - object PromotedTweetHealthEnforcementHoldback extends RuleParam(default = true) - object EnableTimelineHomePromotedTweetHealthEnforcementRules extends RuleParam(default = false) - - object EnableMutedKeywordFilteringSpaceTitleNotificationsRuleParam extends RuleParam(false) - - object EnableDropTweetsWithGeoRestrictedMediaRuleParam extends RuleParam(default = false) - - object EnableDropAllTrustedFriendsTweetsRuleParam extends RuleParam(false) - object EnableDropTrustedFriendsTweetContentRuleParam extends RuleParam(false) - - object EnableDropAllCollabInvitationTweetsRuleParam extends RuleParam(false) - - object EnableNsfwTextHighPrecisionDropRuleParam extends RuleParam(false) - - object EnableLikelyIvsUserLabelDropRule extends RuleParam(false) - - object EnableCardUriRootDomainCardDenylistRule extends RuleParam(false) - object EnableCommunityNonMemberPollCardRule extends RuleParam(false) - object EnableCommunityNonMemberPollCardRuleFailClosed extends RuleParam(false) - - object EnableExperimentalNudgeEnabledParam extends RuleParam(false) - - object NsfwHighPrecisionUserLabelAvoidTweetRuleEnabledParam extends RuleParam(default = false) - - object EnableNewAdAvoidanceRulesParam extends RuleParam(false) - - object EnableNsfaHighRecallAdAvoidanceParam extends RuleParam(false) - - object EnableNsfaKeywordsHighPrecisionAdAvoidanceParam extends RuleParam(false) - - object EnableStaleTweetDropRuleParam extends RuleParam(false) - object EnableStaleTweetDropRuleFailClosedParam extends RuleParam(false) - - object EnableDeleteStateTweetRulesParam extends RuleParam(default = false) - - object EnableSpacesSharingNsfwDropRulesParam extends RuleParam(default = true) - - object EnableViewerIsSoftUserDropRuleParam extends RuleParam(default = false) - - object EnablePdnaQuotedTweetTombstoneRuleParam extends RuleParam(default = true) - object EnableSpamQuotedTweetTombstoneRuleParam extends RuleParam(default = true) - - object EnableNsfwHpQuotedTweetDropRuleParam extends RuleParam(default = false) - object EnableNsfwHpQuotedTweetTombstoneRuleParam extends RuleParam(default = false) - - object EnableInnerQuotedTweetViewerBlocksAuthorInterstitialRuleParam - extends RuleParam(default = false) - object EnableInnerQuotedTweetViewerMutesAuthorInterstitialRuleParam - extends RuleParam(default = false) - - - object EnableNewSensitiveMediaSettingsInterstitialsHomeTimelineRulesParam extends RuleParam(false) - - object EnableNewSensitiveMediaSettingsInterstitialsConversationRulesParam extends RuleParam(false) - - object EnableNewSensitiveMediaSettingsInterstitialsProfileTimelineRulesParam - extends RuleParam(false) - - object EnableNewSensitiveMediaSettingsInterstitialsTweetDetailRulesParam extends RuleParam(false) - - object EnableLegacySensitiveMediaHomeTimelineRulesParam extends RuleParam(true) - - object EnableLegacySensitiveMediaConversationRulesParam extends RuleParam(true) - - object EnableLegacySensitiveMediaProfileTimelineRulesParam extends RuleParam(true) - - object EnableLegacySensitiveMediaTweetDetailRulesParam extends RuleParam(true) - - object EnableLegacySensitiveMediaDirectMessagesRulesParam extends RuleParam(true) - - object EnableToxicReplyFilteringConversationRulesParam extends RuleParam(false) - object EnableToxicReplyFilteringNotificationsRulesParam extends RuleParam(false) - - object EnableSearchQueryMatchesTweetAuthorConditionParam extends RuleParam(default = false) - - object EnableSearchBasicBlockMuteRulesParam extends RuleParam(default = false) - - object EnableAbusiveBehaviorDropRuleParam extends RuleParam(default = false) - object EnableAbusiveBehaviorInterstitialRuleParam extends RuleParam(default = false) - object EnableAbusiveBehaviorLimitedEngagementsRuleParam extends RuleParam(default = false) - - object EnableNotGraduatedDownrankConvosAbusiveQualityRuleParam extends RuleParam(default = false) - object EnableNotGraduatedSearchDropRuleParam extends RuleParam(default = false) - object EnableNotGraduatedDropRuleParam extends RuleParam(default = false) - - object EnableFosnrRuleParam extends RuleParam(default = false) - - object EnableAuthorBlocksViewerDropRuleParam extends RuleParam(default = false) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/SafetyLevelParams.scala b/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/SafetyLevelParams.scala deleted file mode 100644 index ae54ffd34..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/SafetyLevelParams.scala +++ /dev/null @@ -1,215 +0,0 @@ -package com.twitter.visibility.configapi.params - -import com.twitter.timelines.configapi.Param - -abstract class SafetyLevelParam(override val default: Boolean) extends Param(default) { - override val statName: String = s"SafetyLevelParam/${this.getClass.getSimpleName}" -} - -private[visibility] object SafetyLevelParams { - object EnableAccessInternalPromotedContentSafetyLevelParam extends SafetyLevelParam(false) - object EnableAdsBusinessSettingsSafetyLevelParam extends SafetyLevelParam(false) - object EnableAdsCampaignSafetyLevelParam extends SafetyLevelParam(false) - object EnableAdsManagerSafetyLevelParam extends SafetyLevelParam(false) - object EnableAdsReportingDashboardSafetyLevelParam extends SafetyLevelParam(false) - object EnableAllSubscribedListsSafetyLevelParam extends SafetyLevelParam(false) - object EnableAppealsSafetyLevelParam extends SafetyLevelParam(false) - object EnableArticleTweetTimelineSafetyLevelParam extends SafetyLevelParam(false) - object EnableBaseQigSafetyLevelParam extends SafetyLevelParam(false) - object EnableBirdwatchNoteAuthorSafetyLevel extends SafetyLevelParam(false) - object EnableBirdwatchNoteTweetsTimelineSafetyLevel extends SafetyLevelParam(false) - object EnableBirdwatchNeedsYourHelpNotificationsSafetyLevel extends SafetyLevelParam(false) - object EnableBlockMuteUsersTimelineSafetyLevelParam extends SafetyLevelParam(false) - object EnableBrandSafetySafetyLevelParam extends SafetyLevelParam(false) - object EnableCardPollVotingSafetyLevelParam extends SafetyLevelParam(false) - object EnableCardsServiceSafetyLevelParam extends SafetyLevelParam(false) - object EnableCommunitiesSafetyLevelParam extends SafetyLevelParam(false) - object EnableContentControlToolInstallSafetyLevelParam extends SafetyLevelParam(false) - object EnableConversationFocalPrehydrationSafetyLevelParam extends SafetyLevelParam(false) - object EnableConversationFocalTweetSafetyLevelParam extends SafetyLevelParam(false) - object EnableConversationInjectedTweetSafetyLevelParam extends SafetyLevelParam(false) - object EnableConversationReplySafetyLevelParam extends SafetyLevelParam(false) - object EnableCuratedTrendsRepresentativeTweet extends SafetyLevelParam(default = false) - object EnableCurationPolicyViolations extends SafetyLevelParam(default = false) - object EnableDevPlatformGetListTweetsSafetyLevelParam extends SafetyLevelParam(false) - object EnableDESFollowingAndFollowersUserListSafetyLevelParam extends SafetyLevelParam(false) - object EnableDESHomeTimelineSafetyLevelParam extends SafetyLevelParam(false) - object EnableDESQuoteTweetTimelineSafetyLevelParam extends SafetyLevelParam(false) - object EnableDESRealtimeSafetyLevelParam extends SafetyLevelParam(false) - object EnableDESRealtimeSpamEnrichmentSafetyLevelParam extends SafetyLevelParam(false) - object EnableDESRealtimeTweetFilterSafetyLevelParam extends SafetyLevelParam(false) - object EnableDESRetweetingUsersSafetyLevelParam extends SafetyLevelParam(false) - object EnableDesTweetDetailSafetyLevelParam extends SafetyLevelParam(false) - object EnableDESTweetLikingUsersSafetyLevelParam extends SafetyLevelParam(false) - object EnableDESUserBookmarksSafetyLevelParam extends SafetyLevelParam(false) - object EnableDESUserLikedTweetSafetyLevelParam extends SafetyLevelParam(false) - object EnableDESUserMentionsSafetyLevelParam extends SafetyLevelParam(false) - object EnableDESUserTweetsSafetyLevelParam extends SafetyLevelParam(false) - object EnableDevPlatformComplianceStreamSafetyLevelParam extends SafetyLevelParam(false) - object EnableDirectMessagesSafetyLevelParam extends SafetyLevelParam(false) - object EnableDirectMessagesConversationListSafetyLevelParam extends SafetyLevelParam(false) - object EnableDirectMessagesConversationTimelineSafetyLevelParam extends SafetyLevelParam(false) - object EnableDirectMessagesInboxSafetyLevelParam extends SafetyLevelParam(false) - object EnableDirectMessagesMutedUsersSafetyLevelParam extends SafetyLevelParam(false) - object EnableDirectMessagesPinnedSafetyLevelParam extends SafetyLevelParam(false) - object EnableDirectMessagesSearchSafetyLevelParam extends SafetyLevelParam(false) - object EnableEditHistoryTimelineSafetyLevelParam extends SafetyLevelParam(false) - object EnableElevatedQuoteTweetTimelineSafetyLevelParam extends SafetyLevelParam(false) - object EnableEmbeddedTweetSafetyLevelParam extends SafetyLevelParam(false) - object EnableEmbedsPublicInterestNoticeSafetyLevelParam extends SafetyLevelParam(false) - object EnableEmbedTweetMarkupSafetyLevelParam extends SafetyLevelParam(false) - object EnableWritePathLimitedActionsEnforcementSafetyLevelParam extends SafetyLevelParam(false) - object EnableFilterAllSafetyLevelParam extends SafetyLevelParam(false) - object EnableFilterAllPlaceholderSafetyLevelParam extends SafetyLevelParam(false) - object EnableFilterDefaultSafetyLevelParam extends SafetyLevelParam(false) - object EnableFilterNoneSafetyLevelParam extends SafetyLevelParam(false) - object EnableFollowedTopicsTimelineSafetyLevelParam extends SafetyLevelParam(false) - object EnableFollowerConnectionsSafetyLevelParam extends SafetyLevelParam(false) - object EnableFollowingAndFollowersUserListSafetyLevelParam extends SafetyLevelParam(false) - object EnableForDevelopmentOnlySafetyLevelParam extends SafetyLevelParam(false) - object EnableFriendsFollowingListSafetyLevelParam extends SafetyLevelParam(false) - object EnableGraphqlDefaultSafetyLevelParam extends SafetyLevelParam(false) - object EnableGryphonDecksAndColumnsSafetyLevelParam extends SafetyLevelParam(false) - object EnableHumanizationNudgeSafetyLevelParam extends SafetyLevelParam(false) - object EnableKitchenSinkDevelopmentSafetyLevelParam extends SafetyLevelParam(false) - object EnableListHeaderSafetyLevelParam extends SafetyLevelParam(false) - object EnableListMembershipsSafetyLevelParam extends SafetyLevelParam(false) - object EnableListOwnershipsSafetyLevelParam extends SafetyLevelParam(false) - object EnableListRecommendationsSafetyLevelParam extends SafetyLevelParam(false) - object EnableListSearchSafetyLevelParam extends SafetyLevelParam(false) - object EnableListSubscriptionsSafetyLevelParam extends SafetyLevelParam(false) - object EnableLivePipelineEngagementCountsSafetyLevelParam extends SafetyLevelParam(false) - object EnableLiveVideoTimelineSafetyLevelParam extends SafetyLevelParam(false) - object EnableMagicRecsAggressiveSafetyLevelParam extends SafetyLevelParam(false) - object EnableMagicRecsAggressiveV2SafetyLevelParam extends SafetyLevelParam(false) - object EnableMagicRecsSafetyLevelParam extends SafetyLevelParam(false) - object EnableMagicRecsV2SafetyLevelParam extends SafetyLevelParam(false) - object EnableMinimalSafetyLevelParam extends SafetyLevelParam(false) - object EnableModeratedTweetsTimelineSafetyLevelParam extends SafetyLevelParam(false) - object EnableMomentsSafetyLevelParam extends SafetyLevelParam(false) - object EnableNearbySafetyLevelParam extends SafetyLevelParam(false) - object EnableNewUserExperienceSafetyLevelParam extends SafetyLevelParam(false) - object EnableNotificationsIbisSafetyLevelParam extends SafetyLevelParam(false) - object EnableNotificationsPlatformSafetyLevelParam extends SafetyLevelParam(false) - object EnableNotificationsPlatformPushSafetyLevelParam extends SafetyLevelParam(false) - object EnableNotificationsQigSafetyLevelParam extends SafetyLevelParam(false) - object EnableNotificationsReadSafetyLevelParam extends SafetyLevelParam(false) - object EnableNotificationsTimelineDeviceFollowSafetyLevelParam extends SafetyLevelParam(false) - object EnableNotificationsWriteSafetyLevelParam extends SafetyLevelParam(false) - object EnableNotificationsWriterTweetHydratorSafetyLevelParam extends SafetyLevelParam(false) - object EnableNotificationsWriterV2SafetyLevelParam extends SafetyLevelParam(false) - object EnableQuickPromoteTweetEligibilitySafetyLevelParam extends SafetyLevelParam(false) - object EnableQuoteTweetTimelineSafetyLevelParam extends SafetyLevelParam(false) - object EnableRecommendationsSafetyLevelParam extends SafetyLevelParam(false) - object EnableRecommendationsWithoutNsfaSafetyLevelParam extends SafetyLevelParam(false) - object EnableRecosVideoSafetyLevelParam extends SafetyLevelParam(false) - object EnableRecosWritePathSafetyLevelParam extends SafetyLevelParam(false) - object EnableRepliesGroupingSafetyLevelParam extends SafetyLevelParam(false) - object EnableReportCenterSafetyLevelParam extends SafetyLevelParam(false) - object EnableReturningUserExperienceFocalTweetSafetyLevelParam extends SafetyLevelParam(false) - object EnableReturningUserExperienceSafetyLevelParam extends SafetyLevelParam(false) - object EnableRevenueSafetyLevelParam extends SafetyLevelParam(false) - object EnableRitoActionedTweetTimelineParam extends SafetyLevelParam(false) - object EnableSafeSearchMinimalSafetyLevelParam extends SafetyLevelParam(false) - object EnableSafeSearchStrictSafetyLevelParam extends SafetyLevelParam(false) - object EnableSearchHydrationSafetyLevelParam extends SafetyLevelParam(false) - object EnableSearchLatestSafetyLevelParam extends SafetyLevelParam(false) - object EnableSearchTopSafetyLevelParam extends SafetyLevelParam(false) - object EnableSearchTopQigSafetyLevelParam extends SafetyLevelParam(false) - object EnableSearchPhotoSafetyLevelParam extends SafetyLevelParam(false) - object SearchTrendTakeoverPromotedTweetSafetyLevelParam extends SafetyLevelParam(false) - object EnableSearchVideoSafetyLevelParam extends SafetyLevelParam(false) - object EnableSearchBlenderUserRulesSafetyLevelParam extends SafetyLevelParam(false) - object EnableSearchLatestUserRulesSafetyLevelParam extends SafetyLevelParam(false) - object EnableSearchPeopleSearchResultPageSafetyLevelParam extends SafetyLevelParam(false) - object EnableSearchPeopleTypeaheadSafetyLevelParam extends SafetyLevelParam(false) - object EnableUserSearchSrpSafetyLevelParam extends SafetyLevelParam(false) - object EnableUserSearchTypeaheadSafetyLevelParam extends SafetyLevelParam(false) - object EnableSearchMixerSrpMinimalSafetyLevelParam extends SafetyLevelParam(false) - object EnableSearchMixerSrpStrictSafetyLevelParam extends SafetyLevelParam(false) - object EnableShoppingManagerSpyModeSafetyLevelParam extends SafetyLevelParam(false) - object EnableSignalsReactionsSafetyLevelParam extends SafetyLevelParam(false) - object EnableSignalsTweetReactingUsersSafetyLevelParam extends SafetyLevelParam(false) - object EnableSocialProofSafetyLevelParam extends SafetyLevelParam(false) - object EnableSoftInterventionPivotSafetyLevelParam extends SafetyLevelParam(false) - object EnableSpaceFleetlineSafetyLevelParam extends SafetyLevelParam(false) - object EnableSpaceHomeTimelineUprankingSafetyLevelParam extends SafetyLevelParam(false) - object EnableSpaceJoinScreenSafetyLevelParam extends SafetyLevelParam(false) - object EnableSpaceNotificationsSafetyLevelParam extends SafetyLevelParam(false) - object EnableSpacesSafetyLevelParam extends SafetyLevelParam(false) - object EnableSpacesParticipantsSafetyLevelParam extends SafetyLevelParam(false) - object EnableSpaceNotificationSafetyLevelParam extends SafetyLevelParam(false) - object EnableSpacesSellerApplicationStatusSafetyLevelParam extends SafetyLevelParam(false) - object EnableSpacesSharingSafetyLevelParam extends SafetyLevelParam(false) - object EnableSpaceTweetAvatarHomeTimelineSafetyLevelParam extends SafetyLevelParam(false) - object EnableStickersTimelineSafetyLevelParam extends SafetyLevelParam(false) - object EnableStratoExtLimitedEngagementsSafetyLevelParam extends SafetyLevelParam(false) - object EnableStreamServicesSafetyLevelParam extends SafetyLevelParam(false) - object EnableSuperFollowerConnectionsSafetyLevelParam extends SafetyLevelParam(false) - object EnableSuperLikeSafetyLevelParam extends SafetyLevelParam(false) - object EnableTestSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineBookmarkSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineConversationsDownrankingSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineContentControlsSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineConversationsDownrankingMinimalSafetyLevelParam - extends SafetyLevelParam(false) - object EnableTimelineConversationsSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineFavoritesSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineFavoritesSelfViewSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineFocalTweetSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineFollowingActivitySafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineHomeCommunitiesSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineHomeHydrationSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineHomeLatestSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineHomePromotedHydrationSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineHomeRecommendationsSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineHomeSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineHomeTopicFollowRecommendationsSafetyLevelParam - extends SafetyLevelParam(false) - object EnableTimelineScorerSafetyLevelParam extends SafetyLevelParam(false) - object EnableTopicsLandingPageTopicRecommendationsSafetyLevelParam extends SafetyLevelParam(false) - object EnableExploreRecommendationsSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineInjectionSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineLikedBySafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineListsSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineMediaSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineMentionsSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineModeratedTweetsHydrationSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineProfileSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineProfileAllSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineProfileSpacesSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineProfileSuperFollowsSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineReactiveBlendingSafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineRetweetedBySafetyLevelParam extends SafetyLevelParam(false) - object EnableTimelineSuperLikedBySafetyLevelParam extends SafetyLevelParam(false) - object EnableTombstoningSafetyLevelParam extends SafetyLevelParam(false) - object EnableTopicRecommendationsSafetyLevelParam extends SafetyLevelParam(false) - object EnableTrendsRepresentativeTweetSafetyLevelParam extends SafetyLevelParam(false) - object EnableTrustedFriendsUserListSafetyLevelParam extends SafetyLevelParam(false) - object EnableTwitterDelegateUserListSafetyLevelParam extends SafetyLevelParam(false) - object EnableTweetDetailSafetyLevelParam extends SafetyLevelParam(false) - object EnableTweetDetailNonTooSafetyLevelParam extends SafetyLevelParam(false) - object EnableTweetDetailWithInjectionsHydrationSafetyLevelParam extends SafetyLevelParam(false) - object EnableTweetEngagersSafetyLevelParam extends SafetyLevelParam(false) - object EnableTweetReplyNudgeParam extends SafetyLevelParam(false) - object EnableTweetScopedTimelineSafetyLevelParam extends SafetyLevelParam(false) - object EnableTweetWritesApiSafetyLevelParam extends SafetyLevelParam(false) - object EnableTwitterArticleComposeSafetyLevelParam extends SafetyLevelParam(false) - object EnableTwitterArticleProfileTabSafetyLevelParam extends SafetyLevelParam(false) - object EnableTwitterArticleReadSafetyLevelParam extends SafetyLevelParam(false) - object EnableUserProfileHeaderSafetyLevelParam extends SafetyLevelParam(false) - object EnableProfileMixerMediaSafetyLevelParam extends SafetyLevelParam(false) - object EnableProfileMixerFavoritesSafetyLevelParam extends SafetyLevelParam(false) - object EnableUserMilestoneRecommendationSafetyLevelParam extends SafetyLevelParam(false) - object EnableUserScopedTimelineSafetyLevelParam extends SafetyLevelParam(false) - object EnableUserSelfViewOnlySafetyLevelParam extends SafetyLevelParam(false) - object EnableUserSettingsSafetyLevelParam extends SafetyLevelParam(false) - object EnableVideoAdsSafetyLevelParam extends SafetyLevelParam(false) - object EnableZipbirdConsumerArchivesSafetyLevelParam extends SafetyLevelParam(false) - object EnableTweetAwardSafetyLevelParam extends SafetyLevelParam(false) - - object EnableDeprecatedSafetyLevel extends SafetyLevelParam(true) - object EnableQuotedTweetRulesParam extends SafetyLevelParam(true) - object EnableUnsupportedSafetyLevel extends SafetyLevelParam(true) - object EnableUnknownSafetyLevel$ extends SafetyLevelParam(true) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/TimelineConversationsDownrankingSpecificParams.scala b/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/TimelineConversationsDownrankingSpecificParams.scala deleted file mode 100644 index eacabbabd..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/TimelineConversationsDownrankingSpecificParams.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.visibility.configapi.params - -private[visibility] object TimelineConversationsDownrankingSpecificParams { - - object EnablePSpammyTweetDownrankConvosLowQualityParam extends RuleParam(false) - - object EnableRitoActionedTweetDownrankConvosLowQualityParam extends RuleParam(false) - - object EnableHighSpammyTweetContentScoreConvoDownrankAbusiveQualityRuleParam - extends RuleParam(false) - - object EnableHighCryptospamScoreConvoDownrankAbusiveQualityRuleParam extends RuleParam(false) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/VisibilityExperiment.scala b/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/VisibilityExperiment.scala deleted file mode 100644 index 39af78a6b..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/VisibilityExperiment.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.visibility.configapi.params - -import com.twitter.timelines.configapi.BucketName -import com.twitter.timelines.configapi.Experiment -import com.twitter.timelines.configapi.UseFeatureContext - -object VisibilityExperiment { - val Control = "control" - val Treatment = "treatment" -} - -abstract class VisibilityExperiment(experimentKey: String) - extends Experiment(experimentKey) - with UseFeatureContext { - val TreatmentBucket: String = VisibilityExperiment.Treatment - override def experimentBuckets: Set[BucketName] = Set(TreatmentBucket) - val ControlBucket: String = VisibilityExperiment.Control - override def controlBuckets: Set[BucketName] = Set(ControlBucket) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/VisibilityExperiments.scala b/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/VisibilityExperiments.scala deleted file mode 100644 index b287783e6..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/configapi/params/VisibilityExperiments.scala +++ /dev/null @@ -1,16 +0,0 @@ -package com.twitter.visibility.configapi.params - -private[visibility] object VisibilityExperiments { - - case object TestExperiment extends VisibilityExperiment("vf_test_ddg_7727") - - object CommonBucketId extends Enumeration { - type CommonBucketId = Value - val Control = Value("control") - val Treatment = Value("treatment") - val None = Value("none") - } - - case object NotGraduatedUserLabelRuleExperiment - extends VisibilityExperiment("not_graduated_user_holdback_16332") -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/engine/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/engine/BUILD deleted file mode 100644 index 5e3503374..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/engine/BUILD +++ /dev/null @@ -1,22 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "abdecider/src/main/scala", - "configapi/configapi-core", - "servo/util/src/main/scala", - "src/thrift/com/twitter/search/common:constants-scala", - "src/thrift/com/twitter/spam/rtf:safety-level-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "stitch/stitch-core", - "visibility/lib/src/main/scala/com/twitter/visibility/builder", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/params", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/models", - "visibility/lib/src/main/scala/com/twitter/visibility/rules", - "visibility/lib/src/main/scala/com/twitter/visibility/rules/providers", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/engine/DeciderableVisibilityRuleEngine.scala b/visibilitylib/src/main/scala/com/twitter/visibility/engine/DeciderableVisibilityRuleEngine.scala deleted file mode 100644 index cb1119ce3..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/engine/DeciderableVisibilityRuleEngine.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.visibility.engine - -import com.twitter.servo.util.Gate -import com.twitter.spam.rtf.thriftscala.{SafetyLevel => ThriftSafetyLevel} -import com.twitter.stitch.Stitch -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.builder.VisibilityResultBuilder -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.rules.EvaluationContext -import com.twitter.visibility.rules.Rule - -trait DeciderableVisibilityRuleEngine { - def apply( - evaluationContext: EvaluationContext, - safetyLevel: SafetyLevel, - visibilityResultBuilder: VisibilityResultBuilder, - enableShortCircuiting: Gate[Unit] = Gate.True, - preprocessedRules: Option[Seq[Rule]] = None - ): Stitch[VisibilityResult] - - def apply( - evaluationContext: EvaluationContext, - thriftSafetyLevel: ThriftSafetyLevel, - visibilityResultBuilder: VisibilityResultBuilder - ): Stitch[VisibilityResult] -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/engine/VisibilityResultsMetricRecorder.scala b/visibilitylib/src/main/scala/com/twitter/visibility/engine/VisibilityResultsMetricRecorder.scala deleted file mode 100644 index 97af1d024..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/engine/VisibilityResultsMetricRecorder.scala +++ /dev/null @@ -1,179 +0,0 @@ -package com.twitter.visibility.engine - -import com.twitter.finagle.stats.NullStatsReceiver -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.finagle.stats.Verbosity -import com.twitter.servo.util.Gate -import com.twitter.servo.util.MemoizingStatsReceiver -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.features.Feature -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.rules.NotEvaluated -import com.twitter.visibility.rules.RuleResult -import com.twitter.visibility.rules.State -import com.twitter.visibility.rules.State.Disabled -import com.twitter.visibility.rules.State.FeatureFailed -import com.twitter.visibility.rules.State.MissingFeature -import com.twitter.visibility.rules.State.RuleFailed -import com.twitter.visibility.rules.Action - - -case class VisibilityResultsMetricRecorder( - statsReceiver: StatsReceiver, - captureDebugStats: Gate[Unit]) { - - private val scopedStatsReceiver = new MemoizingStatsReceiver( - statsReceiver.scope("visibility_rule_engine") - ) - private val actionStats: StatsReceiver = scopedStatsReceiver.scope("by_action") - private val featureFailureReceiver: StatsReceiver = - scopedStatsReceiver.scope("feature_failed") - private val safetyLevelStatsReceiver: StatsReceiver = - scopedStatsReceiver.scope("from_safety_level") - private val ruleStatsReceiver: StatsReceiver = scopedStatsReceiver.scope("for_rule") - private val ruleFailureReceiver: StatsReceiver = - scopedStatsReceiver.scope("rule_failures") - private val failClosedReceiver: StatsReceiver = - scopedStatsReceiver.scope("fail_closed") - private val ruleStatsBySafetyLevelReceiver: StatsReceiver = - scopedStatsReceiver.scope("for_rule_by_safety_level") - - def recordSuccess( - safetyLevel: SafetyLevel, - result: VisibilityResult - ): Unit = { - recordAction(safetyLevel, result.verdict.fullName) - - val isFeatureFailure = result.ruleResultMap.values - .collectFirst { - case RuleResult(_, FeatureFailed(_)) => - ruleFailureReceiver.counter("feature_failed").incr() - true - }.getOrElse(false) - - val isMissingFeature = result.ruleResultMap.values - .collectFirst { - case RuleResult(_, MissingFeature(_)) => - ruleFailureReceiver.counter("missing_feature").incr() - true - }.getOrElse(false) - - val isRuleFailed = result.ruleResultMap.values - .collectFirst { - case RuleResult(_, RuleFailed(_)) => - ruleFailureReceiver.counter("rule_failed").incr() - true - }.getOrElse(false) - - if (isFeatureFailure || isMissingFeature || isRuleFailed) { - ruleFailureReceiver.counter().incr() - } - - if (captureDebugStats()) { - val ruleBySafetyLevelStat = - ruleStatsBySafetyLevelReceiver.scope(safetyLevel.name) - result.ruleResultMap.foreach { - case (rule, ruleResult) => { - ruleBySafetyLevelStat - .scope(rule.name) - .scope("action") - .counter(Verbosity.Debug, ruleResult.action.fullName).incr() - ruleBySafetyLevelStat - .scope(rule.name) - .scope("state") - .counter(Verbosity.Debug, ruleResult.state.name).incr() - } - } - } - } - - def recordFailedFeature( - failedFeature: Feature[_], - exception: Throwable - ): Unit = { - featureFailureReceiver.counter().incr() - - val featureStat = featureFailureReceiver.scope(failedFeature.name) - featureStat.counter().incr() - featureStat.counter(exception.getClass.getName).incr() - } - - def recordAction( - safetyLevel: SafetyLevel, - action: String - ): Unit = { - safetyLevelStatsReceiver.scope(safetyLevel.name).counter(action).incr() - actionStats.counter(action).incr() - } - - def recordUnknownSafetyLevel( - safetyLevel: SafetyLevel - ): Unit = { - safetyLevelStatsReceiver - .scope("unknown_safety_level") - .counter(safetyLevel.name.toLowerCase).incr() - } - - def recordRuleMissingFeatures( - ruleName: String, - missingFeatures: Set[Feature[_]] - ): Unit = { - val ruleStat = ruleStatsReceiver.scope(ruleName) - missingFeatures.foreach { featureId => - ruleStat.scope("missing_feature").counter(featureId.name).incr() - } - ruleStat.scope("action").counter(NotEvaluated.fullName).incr() - ruleStat.scope("state").counter(MissingFeature(missingFeatures).name).incr() - } - - def recordRuleFailedFeatures( - ruleName: String, - failedFeatures: Map[Feature[_], Throwable] - ): Unit = { - val ruleStat = ruleStatsReceiver.scope(ruleName) - - ruleStat.scope("action").counter(NotEvaluated.fullName).incr() - ruleStat.scope("state").counter(FeatureFailed(failedFeatures).name).incr() - } - - def recordFailClosed(rule: String, state: State) { - failClosedReceiver.scope(state.name).counter(rule).incr(); - } - - def recordRuleEvaluation( - ruleName: String, - action: Action, - state: State - ): Unit = { - val ruleStat = ruleStatsReceiver.scope(ruleName) - ruleStat.scope("action").counter(action.fullName).incr() - ruleStat.scope("state").counter(state.name).incr() - } - - - def recordRuleFallbackAction( - ruleName: String - ): Unit = { - val ruleStat = ruleStatsReceiver.scope(ruleName) - ruleStat.counter("fallback_action").incr() - } - - def recordRuleHoldBack( - ruleName: String - ): Unit = { - ruleStatsReceiver.scope(ruleName).counter("heldback").incr() - } - - def recordRuleFailed( - ruleName: String - ): Unit = { - ruleStatsReceiver.scope(ruleName).counter("failed").incr() - } - - def recordDisabledRule( - ruleName: String - ): Unit = recordRuleEvaluation(ruleName, NotEvaluated, Disabled) -} - -object NullVisibilityResultsMetricsRecorder - extends VisibilityResultsMetricRecorder(NullStatsReceiver, Gate.False) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/engine/VisibilityRuleEngine.scala b/visibilitylib/src/main/scala/com/twitter/visibility/engine/VisibilityRuleEngine.scala deleted file mode 100644 index d1c33017b..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/engine/VisibilityRuleEngine.scala +++ /dev/null @@ -1,266 +0,0 @@ -package com.twitter.visibility.engine - -import com.twitter.servo.util.Gate -import com.twitter.spam.rtf.thriftscala.{SafetyLevel => ThriftSafetyLevel} -import com.twitter.stitch.Stitch -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.builder.VisibilityResultBuilder -import com.twitter.visibility.features._ -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.SafetyLevel.DeprecatedSafetyLevel -import com.twitter.visibility.rules.EvaluationContext -import com.twitter.visibility.rules.State._ -import com.twitter.visibility.rules._ -import com.twitter.visibility.rules.providers.ProvidedEvaluationContext -import com.twitter.visibility.rules.providers.PolicyProvider - -class VisibilityRuleEngine private[VisibilityRuleEngine] ( - rulePreprocessor: VisibilityRulePreprocessor, - metricsRecorder: VisibilityResultsMetricRecorder, - enableComposableActions: Gate[Unit], - enableFailClosed: Gate[Unit], - policyProviderOpt: Option[PolicyProvider] = None) - extends DeciderableVisibilityRuleEngine { - - private[visibility] def apply( - evaluationContext: ProvidedEvaluationContext, - visibilityPolicy: VisibilityPolicy, - visibilityResultBuilder: VisibilityResultBuilder, - enableShortCircuiting: Gate[Unit], - preprocessedRules: Option[Seq[Rule]] - ): Stitch[VisibilityResult] = { - val (resultBuilder, rules) = preprocessedRules match { - case Some(r) => - (visibilityResultBuilder, r) - case None => - rulePreprocessor.evaluate(evaluationContext, visibilityPolicy, visibilityResultBuilder) - } - evaluate(evaluationContext, resultBuilder, rules, enableShortCircuiting) - } - - def apply( - evaluationContext: EvaluationContext, - safetyLevel: SafetyLevel, - visibilityResultBuilder: VisibilityResultBuilder, - enableShortCircuiting: Gate[Unit] = Gate.True, - preprocessedRules: Option[Seq[Rule]] = None - ): Stitch[VisibilityResult] = { - val visibilityPolicy = policyProviderOpt match { - case Some(policyProvider) => - policyProvider.policyForSurface(safetyLevel) - case None => RuleBase.RuleMap(safetyLevel) - } - if (evaluationContext.params(safetyLevel.enabledParam)) { - apply( - ProvidedEvaluationContext.injectRuntimeRulesIntoEvaluationContext( - evaluationContext = evaluationContext, - safetyLevel = Some(safetyLevel), - policyProviderOpt = policyProviderOpt - ), - visibilityPolicy, - visibilityResultBuilder, - enableShortCircuiting, - preprocessedRules - ).onSuccess { result => - metricsRecorder.recordSuccess(safetyLevel, result) - } - .onFailure { _ => - metricsRecorder.recordAction(safetyLevel, "failure") - } - } else { - metricsRecorder.recordAction(safetyLevel, "disabled") - val rules: Seq[Rule] = visibilityPolicy.forContentId(visibilityResultBuilder.contentId) - Stitch.value( - visibilityResultBuilder - .withRuleResultMap(rules.map(r => r -> RuleResult(Allow, Skipped)).toMap) - .withVerdict(verdict = Allow) - .withFinished(finished = true) - .build - ) - } - } - - def apply( - evaluationContext: EvaluationContext, - thriftSafetyLevel: ThriftSafetyLevel, - visibilityResultBuilder: VisibilityResultBuilder - ): Stitch[VisibilityResult] = { - val safetyLevel: SafetyLevel = SafetyLevel.fromThrift(thriftSafetyLevel) - safetyLevel match { - case DeprecatedSafetyLevel => - metricsRecorder.recordUnknownSafetyLevel(safetyLevel) - Stitch.value( - visibilityResultBuilder - .withVerdict(verdict = Allow) - .withFinished(finished = true) - .build - ) - - case thriftSafetyLevel: SafetyLevel => - this( - ProvidedEvaluationContext.injectRuntimeRulesIntoEvaluationContext( - evaluationContext = evaluationContext, - safetyLevel = Some(safetyLevel), - policyProviderOpt = policyProviderOpt - ), - thriftSafetyLevel, - visibilityResultBuilder - ) - } - } - - private[visibility] def evaluateRules( - evaluationContext: ProvidedEvaluationContext, - resolvedFeatureMap: Map[Feature[_], Any], - failedFeatures: Map[Feature[_], Throwable], - resultBuilderWithoutFailedFeatures: VisibilityResultBuilder, - preprocessedRules: Seq[Rule], - enableShortCircuiting: Gate[Unit] - ): VisibilityResultBuilder = { - preprocessedRules - .foldLeft(resultBuilderWithoutFailedFeatures) { (builder, rule) => - builder.ruleResults.get(rule) match { - case Some(RuleResult(_, state)) if state == Evaluated || state == ShortCircuited => - builder - - case _ => - val failedFeatureDependencies: Map[Feature[_], Throwable] = - failedFeatures.filterKeys(key => rule.featureDependencies.contains(key)) - - val shortCircuit = - builder.finished && enableShortCircuiting() && - !(enableComposableActions() && builder.isVerdictComposable()) - - if (failedFeatureDependencies.nonEmpty && rule.fallbackActionBuilder.isEmpty) { - metricsRecorder.recordRuleFailedFeatures(rule.name, failedFeatureDependencies) - builder.withRuleResult( - rule, - RuleResult(NotEvaluated, FeatureFailed(failedFeatureDependencies))) - - } else if (shortCircuit) { - - metricsRecorder.recordRuleEvaluation(rule.name, NotEvaluated, ShortCircuited) - builder.withRuleResult(rule, RuleResult(builder.verdict, ShortCircuited)) - } else { - - if (failedFeatureDependencies.nonEmpty && rule.fallbackActionBuilder.nonEmpty) { - metricsRecorder.recordRuleFallbackAction(rule.name) - } - - - val ruleResult = - rule.evaluate(evaluationContext, resolvedFeatureMap) - metricsRecorder - .recordRuleEvaluation(rule.name, ruleResult.action, ruleResult.state) - val nextBuilder = (ruleResult.action, builder.finished) match { - case (NotEvaluated | Allow, _) => - ruleResult.state match { - case Heldback => - metricsRecorder.recordRuleHoldBack(rule.name) - case RuleFailed(_) => - metricsRecorder.recordRuleFailed(rule.name) - case _ => - } - builder.withRuleResult(rule, ruleResult) - - case (_, true) => - builder - .withRuleResult(rule, ruleResult) - .withSecondaryVerdict(ruleResult.action, rule) - - case _ => - builder - .withRuleResult(rule, ruleResult) - .withVerdict(ruleResult.action, Some(rule)) - .withFinished(true) - } - - nextBuilder - } - } - }.withResolvedFeatureMap(resolvedFeatureMap) - } - - private[visibility] def evaluateFailClosed( - evaluationContext: ProvidedEvaluationContext - ): VisibilityResultBuilder => Stitch[VisibilityResultBuilder] = { builder => - builder.failClosedException(evaluationContext) match { - case Some(e: FailClosedException) if enableFailClosed() => - metricsRecorder.recordFailClosed(e.getRuleName, e.getState); - Stitch.exception(e) - case _ => Stitch.value(builder) - } - } - - private[visibility] def checkMarkFinished( - builder: VisibilityResultBuilder - ): VisibilityResult = { - val allRulesEvaluated: Boolean = builder.ruleResults.values.forall { - case RuleResult(_, state) => - state == Evaluated || state == Disabled || state == Skipped - case _ => - false - } - - if (allRulesEvaluated) { - builder.withFinished(true).build - } else { - builder.build - } - } - - private[visibility] def evaluate( - evaluationContext: ProvidedEvaluationContext, - visibilityResultBuilder: VisibilityResultBuilder, - preprocessedRules: Seq[Rule], - enableShortCircuiting: Gate[Unit] = Gate.True - ): Stitch[VisibilityResult] = { - - val finalBuilder = - FeatureMap.resolve(visibilityResultBuilder.features, evaluationContext.statsReceiver).map { - resolvedFeatureMap => - val (failedFeatureMap, successfulFeatureMap) = resolvedFeatureMap.constantMap.partition({ - case (_, _: FeatureFailedPlaceholderObject) => true - case _ => false - }) - - val failedFeatures: Map[Feature[_], Throwable] = - failedFeatureMap.mapValues({ - case failurePlaceholder: FeatureFailedPlaceholderObject => - failurePlaceholder.throwable - }) - - val resultBuilderWithoutFailedFeatures = - visibilityResultBuilder.withFeatureMap(ResolvedFeatureMap(successfulFeatureMap)) - - evaluateRules( - evaluationContext, - successfulFeatureMap, - failedFeatures, - resultBuilderWithoutFailedFeatures, - preprocessedRules, - enableShortCircuiting - ) - } - - finalBuilder.flatMap(evaluateFailClosed(evaluationContext)).map(checkMarkFinished) - } -} - -object VisibilityRuleEngine { - - def apply( - rulePreprocessor: Option[VisibilityRulePreprocessor] = None, - metricsRecorder: VisibilityResultsMetricRecorder = NullVisibilityResultsMetricsRecorder, - enableComposableActions: Gate[Unit] = Gate.False, - enableFailClosed: Gate[Unit] = Gate.False, - policyProviderOpt: Option[PolicyProvider] = None, - ): VisibilityRuleEngine = { - new VisibilityRuleEngine( - rulePreprocessor.getOrElse(VisibilityRulePreprocessor(metricsRecorder)), - metricsRecorder, - enableComposableActions, - enableFailClosed, - policyProviderOpt = policyProviderOpt) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/engine/VisibilityRulePreprocessor.scala b/visibilitylib/src/main/scala/com/twitter/visibility/engine/VisibilityRulePreprocessor.scala deleted file mode 100644 index 115c37605..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/engine/VisibilityRulePreprocessor.scala +++ /dev/null @@ -1,156 +0,0 @@ -package com.twitter.visibility.engine - -import com.twitter.abdecider.NullABDecider -import com.twitter.util.Return -import com.twitter.util.Throw -import com.twitter.util.Try -import com.twitter.visibility.builder.VisibilityResultBuilder -import com.twitter.visibility.features._ -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.rules.Rule.DisabledRuleResult -import com.twitter.visibility.rules.Rule.EvaluatedRuleResult -import com.twitter.visibility.rules.State._ -import com.twitter.visibility.rules._ -import com.twitter.visibility.rules.providers.ProvidedEvaluationContext -import com.twitter.visibility.rules.providers.PolicyProvider - -class VisibilityRulePreprocessor private ( - metricsRecorder: VisibilityResultsMetricRecorder, - policyProviderOpt: Option[PolicyProvider] = None) { - - private[engine] def filterEvaluableRules( - evaluationContext: ProvidedEvaluationContext, - resultBuilder: VisibilityResultBuilder, - rules: Seq[Rule] - ): (VisibilityResultBuilder, Seq[Rule]) = { - val (builder, ruleList) = rules.foldLeft((resultBuilder, Seq.empty[Rule])) { - case ((builder, nextPassRules), rule) => - if (evaluationContext.ruleEnabledInContext(rule)) { - val missingFeatures: Set[Feature[_]] = rule.featureDependencies.collect { - case feature: Feature[_] if !builder.featureMap.contains(feature) => feature - } - - if (missingFeatures.isEmpty) { - (builder, nextPassRules :+ rule) - } else { - metricsRecorder.recordRuleMissingFeatures(rule.name, missingFeatures) - ( - builder.withRuleResult( - rule, - RuleResult(NotEvaluated, MissingFeature(missingFeatures)) - ), - nextPassRules - ) - } - } else { - (builder.withRuleResult(rule, DisabledRuleResult), nextPassRules) - } - } - (builder, ruleList) - } - - private[visibility] def preFilterRules( - evaluationContext: ProvidedEvaluationContext, - resolvedFeatureMap: Map[Feature[_], Any], - resultBuilder: VisibilityResultBuilder, - rules: Seq[Rule] - ): (VisibilityResultBuilder, Seq[Rule]) = { - val isResolvedFeatureMap = resultBuilder.featureMap.isInstanceOf[ResolvedFeatureMap] - val (builder, ruleList) = rules.foldLeft((resultBuilder, Seq.empty[Rule])) { - case ((builder, nextPassRules), rule) => - rule.preFilter(evaluationContext, resolvedFeatureMap, NullABDecider) match { - case NeedsFullEvaluation => - (builder, nextPassRules :+ rule) - case NotFiltered => - (builder, nextPassRules :+ rule) - case Filtered if isResolvedFeatureMap => - (builder, nextPassRules :+ rule) - case Filtered => - (builder.withRuleResult(rule, EvaluatedRuleResult), nextPassRules) - } - } - (builder, ruleList) - } - - private[visibility] def evaluate( - evaluationContext: ProvidedEvaluationContext, - safetyLevel: SafetyLevel, - resultBuilder: VisibilityResultBuilder - ): (VisibilityResultBuilder, Seq[Rule]) = { - val visibilityPolicy = policyProviderOpt match { - case Some(policyProvider) => - policyProvider.policyForSurface(safetyLevel) - case None => RuleBase.RuleMap(safetyLevel) - } - - if (evaluationContext.params(safetyLevel.enabledParam)) { - evaluate(evaluationContext, visibilityPolicy, resultBuilder) - } else { - metricsRecorder.recordAction(safetyLevel, "disabled") - - val rules: Seq[Rule] = visibilityPolicy.forContentId(resultBuilder.contentId) - val skippedResultBuilder = resultBuilder - .withRuleResultMap(rules.map(r => r -> RuleResult(Allow, Skipped)).toMap) - .withVerdict(verdict = Allow) - .withFinished(finished = true) - - (skippedResultBuilder, rules) - } - } - - private[visibility] def evaluate( - evaluationContext: ProvidedEvaluationContext, - visibilityPolicy: VisibilityPolicy, - resultBuilder: VisibilityResultBuilder, - ): (VisibilityResultBuilder, Seq[Rule]) = { - - val rules: Seq[Rule] = visibilityPolicy.forContentId(resultBuilder.contentId) - - val (secondPassBuilder, secondPassRules) = - filterEvaluableRules(evaluationContext, resultBuilder, rules) - - val secondPassFeatureMap = secondPassBuilder.featureMap - - val secondPassConstantFeatures: Set[Feature[_]] = RuleBase - .getFeaturesForRules(secondPassRules) - .filter(secondPassFeatureMap.containsConstant(_)) - - val secondPassFeatureValues: Set[(Feature[_], Any)] = secondPassConstantFeatures.map { - feature => - Try(secondPassFeatureMap.getConstant(feature)) match { - case Return(value) => (feature, value) - case Throw(ex) => - metricsRecorder.recordFailedFeature(feature, ex) - (feature, FeatureFailedPlaceholderObject(ex)) - } - } - - val resolvedFeatureMap: Map[Feature[_], Any] = - secondPassFeatureValues.filterNot { - case (_, value) => value.isInstanceOf[FeatureFailedPlaceholderObject] - }.toMap - - val (preFilteredResultBuilder, preFilteredRules) = preFilterRules( - evaluationContext, - resolvedFeatureMap, - secondPassBuilder, - secondPassRules - ) - - val preFilteredFeatureMap = - RuleBase.removeUnusedFeaturesFromFeatureMap( - preFilteredResultBuilder.featureMap, - preFilteredRules) - - (preFilteredResultBuilder.withFeatureMap(preFilteredFeatureMap), preFilteredRules) - } -} - -object VisibilityRulePreprocessor { - def apply( - metricsRecorder: VisibilityResultsMetricRecorder, - policyProviderOpt: Option[PolicyProvider] = None - ): VisibilityRulePreprocessor = { - new VisibilityRulePreprocessor(metricsRecorder, policyProviderOpt) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/features/AdvancedFilteringFeatures.scala b/visibilitylib/src/main/scala/com/twitter/visibility/features/AdvancedFilteringFeatures.scala deleted file mode 100644 index 4e6a33ba9..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/features/AdvancedFilteringFeatures.scala +++ /dev/null @@ -1,24 +0,0 @@ -package com.twitter.visibility.features - -import com.twitter.gizmoduck.thriftscala.MentionFilter -import com.twitter.util.Duration - -case object ViewerFiltersNoConfirmedEmail extends Feature[Boolean] - -case object ViewerFiltersNoConfirmedPhone extends Feature[Boolean] - -case object ViewerFiltersDefaultProfileImage extends Feature[Boolean] - -case object ViewerFiltersNewUsers extends Feature[Boolean] - -case object ViewerFiltersNotFollowedBy extends Feature[Boolean] - -case object ViewerMentionFilter extends Feature[MentionFilter] - -case object AuthorHasConfirmedEmail extends Feature[Boolean] - -case object AuthorHasVerifiedPhone extends Feature[Boolean] - -case object AuthorHasDefaultProfileImage extends Feature[Boolean] - -case object AuthorAccountAge extends Feature[Duration] diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/features/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/features/BUILD deleted file mode 100644 index 3573bb0db..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/features/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/squareup/okhttp:okhttp3", - "finagle/finagle-mux/src/main/scala", - "src/thrift/com/twitter/gizmoduck:user-thrift-scala", - "src/thrift/com/twitter/search/common:constants-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "stitch/stitch-core", - "visibility/lib/src/main/scala/com/twitter/visibility/models", - "visibility/lib/src/main/scala/com/twitter/visibility/util", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/features/Feature.scala b/visibilitylib/src/main/scala/com/twitter/visibility/features/Feature.scala deleted file mode 100644 index 151718814..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/features/Feature.scala +++ /dev/null @@ -1,11 +0,0 @@ -package com.twitter.visibility.features - -import com.twitter.visibility.util.NamingUtils - -abstract class Feature[T] protected ()(implicit val manifest: Manifest[T]) { - - lazy val name: String = NamingUtils.getFriendlyName(this) - - override lazy val toString: String = - "Feature[%s](name=%s)".format(manifest, getClass.getSimpleName) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/features/FeatureMap.scala b/visibilitylib/src/main/scala/com/twitter/visibility/features/FeatureMap.scala deleted file mode 100644 index 1b4ffd182..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/features/FeatureMap.scala +++ /dev/null @@ -1,121 +0,0 @@ -package com.twitter.visibility.features - -import com.twitter.finagle.mux.ClientDiscardedRequestException -import com.twitter.finagle.stats.NullStatsReceiver -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.stitch.Stitch -import scala.language.existentials - -class MissingFeatureException(feature: Feature[_]) extends Exception("Missing value for " + feature) - -case class FeatureFailedException(feature: Feature[_], exception: Throwable) extends Exception - -private[visibility] case class FeatureFailedPlaceholderObject(throwable: Throwable) - -class FeatureMap( - val map: Map[Feature[_], Stitch[_]], - val constantMap: Map[Feature[_], Any]) { - - def contains[T](feature: Feature[T]): Boolean = - constantMap.contains(feature) || map.contains(feature) - - def containsConstant[T](feature: Feature[T]): Boolean = constantMap.contains(feature) - - lazy val size: Int = keys.size - - lazy val keys: Set[Feature[_]] = constantMap.keySet ++ map.keySet - - def get[T](feature: Feature[T]): Stitch[T] = { - map.get(feature) match { - case _ if constantMap.contains(feature) => - Stitch.value(getConstant(feature)) - case Some(x) => - x.asInstanceOf[Stitch[T]] - case _ => - Stitch.exception(new MissingFeatureException(feature)) - } - } - - def getConstant[T](feature: Feature[T]): T = { - constantMap.get(feature) match { - case Some(x) => - x.asInstanceOf[T] - case _ => - throw new MissingFeatureException(feature) - } - } - - def -[T](key: Feature[T]): FeatureMap = new FeatureMap(map - key, constantMap - key) - - override def toString: String = "FeatureMap(%s, %s)".format(map, constantMap) -} - -object FeatureMap { - - def empty: FeatureMap = new FeatureMap(Map.empty, Map.empty) - - def resolve( - featureMap: FeatureMap, - statsReceiver: StatsReceiver = NullStatsReceiver - ): Stitch[ResolvedFeatureMap] = { - val featureMapHydrationStatsReceiver = statsReceiver.scope("feature_map_hydration") - - Stitch - .traverse(featureMap.map.toSeq) { - case (feature, value: Stitch[_]) => - val featureStatsReceiver = featureMapHydrationStatsReceiver.scope(feature.name) - lazy val featureFailureStat = featureStatsReceiver.scope("failures") - val featureStitch: Stitch[(Feature[_], Any)] = value - .map { resolvedValue => - featureStatsReceiver.counter("success").incr() - (feature, resolvedValue) - } - - featureStitch - .handle { - case ffe: FeatureFailedException => - featureFailureStat.counter().incr() - featureFailureStat.counter(ffe.exception.getClass.getName).incr() - (feature, FeatureFailedPlaceholderObject(ffe.exception)) - } - .ensure { - featureStatsReceiver.counter("requests").incr() - } - } - .map { resolvedFeatures: Seq[(Feature[_], Any)] => - new ResolvedFeatureMap(resolvedFeatures.toMap ++ featureMap.constantMap) - } - } - - def rescueFeatureTuple(kv: (Feature[_], Stitch[_])): (Feature[_], Stitch[_]) = { - val (k, v) = kv - - val rescueValue = v.rescue { - case e => - e match { - case cdre: ClientDiscardedRequestException => Stitch.exception(cdre) - case _ => Stitch.exception(FeatureFailedException(k, e)) - } - } - - (k, rescueValue) - } -} - -class ResolvedFeatureMap(private[visibility] val resolvedMap: Map[Feature[_], Any]) - extends FeatureMap(Map.empty, resolvedMap) { - - override def equals(other: Any): Boolean = other match { - case otherResolvedFeatureMap: ResolvedFeatureMap => - this.resolvedMap.equals(otherResolvedFeatureMap.resolvedMap) - case _ => false - } - - override def toString: String = "ResolvedFeatureMap(%s)".format(resolvedMap) -} - -object ResolvedFeatureMap { - def apply(resolvedMap: Map[Feature[_], Any]): ResolvedFeatureMap = { - new ResolvedFeatureMap(resolvedMap) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/features/Features.scala b/visibilitylib/src/main/scala/com/twitter/visibility/features/Features.scala deleted file mode 100644 index ae26dfe78..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/features/Features.scala +++ /dev/null @@ -1,269 +0,0 @@ -package com.twitter.visibility.features - -import com.twitter.contenthealth.toxicreplyfilter.thriftscala.FilterState -import com.twitter.gizmoduck.thriftscala.Label -import com.twitter.search.common.constants.thriftscala.ThriftQuerySource -import com.twitter.tseng.withholding.thriftscala.TakedownReason -import com.twitter.util.Duration -import com.twitter.util.Time -import com.twitter.visibility.models.TweetDeleteReason.TweetDeleteReason -import com.twitter.visibility.models._ - -case object AuthorId extends Feature[Set[Long]] - -case object ViewerId extends Feature[Long] - -case object AuthorIsProtected extends Feature[Boolean] - -case object AuthorIsSuspended extends Feature[Boolean] - -case object AuthorIsUnavailable extends Feature[Boolean] - -case object AuthorIsDeactivated extends Feature[Boolean] - -case object AuthorIsErased extends Feature[Boolean] - -case object AuthorIsOffboarded extends Feature[Boolean] - -case object AuthorIsVerified extends Feature[Boolean] - -case object AuthorIsBlueVerified extends Feature[Boolean] - -case object ViewerIsSuspended extends Feature[Boolean] - -case object ViewerIsDeactivated extends Feature[Boolean] - -case object AuthorFollowsViewer extends Feature[Boolean] - -case object AuthorUserLabels extends Feature[Seq[Label]] - -case object ViewerFollowsAuthorOfViolatingTweet extends Feature[Boolean] - -case object ViewerDoesNotFollowAuthorOfViolatingTweet extends Feature[Boolean] - -case object ViewerFollowsAuthor extends Feature[Boolean] - -case object ViewerBlocksAuthor extends Feature[Boolean] - -case object AuthorBlocksViewer extends Feature[Boolean] - -case object AuthorMutesViewer extends Feature[Boolean] - -case object ViewerMutesAuthor extends Feature[Boolean] - -case object AuthorReportsViewerAsSpam extends Feature[Boolean] - -case object ViewerReportsAuthorAsSpam extends Feature[Boolean] - -case object ViewerReportedTweet extends Feature[Boolean] - -case object ViewerMutesRetweetsFromAuthor extends Feature[Boolean] - -case object ViewerHasUniversalQualityFilterEnabled extends Feature[Boolean] - -case object ViewerIsProtected extends Feature[Boolean] - -case object ViewerIsSoftUser extends Feature[Boolean] - -case object TweetSafetyLabels extends Feature[Seq[TweetSafetyLabel]] - -case object SpaceSafetyLabels extends Feature[Seq[SpaceSafetyLabel]] - -case object MediaSafetyLabels extends Feature[Seq[MediaSafetyLabel]] - -case object TweetTakedownReasons extends Feature[Seq[TakedownReason]] - -case object AuthorTakedownReasons extends Feature[Seq[TakedownReason]] - -case object AuthorIsNsfwUser extends Feature[Boolean] - -case object AuthorIsNsfwAdmin extends Feature[Boolean] - -case object TweetHasNsfwUser extends Feature[Boolean] - -case object TweetHasNsfwAdmin extends Feature[Boolean] - -case object TweetHasMedia extends Feature[Boolean] - -case object CardHasMedia extends Feature[Boolean] - -case object TweetHasCard extends Feature[Boolean] - -case object ViewerMutesKeywordInTweetForHomeTimeline extends Feature[MutedKeyword] - -case object ViewerMutesKeywordInTweetForTweetReplies extends Feature[MutedKeyword] - -case object ViewerMutesKeywordInTweetForNotifications extends Feature[MutedKeyword] - -case object ViewerMutesKeywordInSpaceTitleForNotifications extends Feature[MutedKeyword] - -case object ViewerMutesKeywordInTweetForAllSurfaces extends Feature[MutedKeyword] - -case object ViewerUserLabels extends Feature[Seq[Label]] - -case object RequestCountryCode extends Feature[String] - -case object RequestIsVerifiedCrawler extends Feature[Boolean] - -case object ViewerCountryCode extends Feature[String] - -case object TweetIsSelfReply extends Feature[Boolean] - -case object TweetIsNullcast extends Feature[Boolean] - -case object TweetTimestamp extends Feature[Time] - -case object TweetIsInnerQuotedTweet extends Feature[Boolean] - -case object TweetIsRetweet extends Feature[Boolean] - -case object TweetIsSourceTweet extends Feature[Boolean] - -case object TweetDeleteReason extends Feature[TweetDeleteReason] - -case object TweetReplyToParentTweetDuration extends Feature[Duration] - -case object TweetReplyToRootTweetDuration extends Feature[Duration] - -case object TweetHasCommunityConversationControl extends Feature[Boolean] -case object TweetHasByInvitationConversationControl extends Feature[Boolean] -case object TweetHasFollowersConversationControl extends Feature[Boolean] -case object TweetConversationViewerIsInvited extends Feature[Boolean] -case object TweetConversationViewerIsInvitedViaReplyMention extends Feature[Boolean] -case object TweetConversationViewerIsRootAuthor extends Feature[Boolean] -case object ConversationRootAuthorFollowsViewer extends Feature[Boolean] -case object ViewerFollowsConversationRootAuthor extends Feature[Boolean] - -case object TweetIsExclusiveTweet extends Feature[Boolean] -case object ViewerIsExclusiveTweetRootAuthor extends Feature[Boolean] -case object ViewerSuperFollowsExclusiveTweetRootAuthor extends Feature[Boolean] - -case object TweetIsCommunityTweet extends Feature[Boolean] - -case object CommunityTweetCommunityNotFound extends Feature[Boolean] - -case object CommunityTweetCommunityDeleted extends Feature[Boolean] - -case object CommunityTweetCommunitySuspended extends Feature[Boolean] - -case object CommunityTweetCommunityVisible extends Feature[Boolean] - -case object CommunityTweetIsHidden extends Feature[Boolean] - -case object ViewerIsInternalCommunitiesAdmin extends Feature[Boolean] - -case object ViewerIsCommunityAdmin extends Feature[Boolean] - -case object ViewerIsCommunityModerator extends Feature[Boolean] - -case object ViewerIsCommunityMember extends Feature[Boolean] - -case object CommunityTweetAuthorIsRemoved extends Feature[Boolean] - -case object NotificationIsOnCommunityTweet extends Feature[Boolean] - -case object NotificationIsOnUnmentionedViewer extends Feature[Boolean] - -case object SearchResultsPageNumber extends Feature[Int] - -case object SearchCandidateCount extends Feature[Int] - -case object SearchQuerySource extends Feature[ThriftQuerySource] - -case object SearchQueryHasUser extends Feature[Boolean] - -case object TweetSemanticCoreAnnotations extends Feature[Seq[SemanticCoreAnnotation]] - -case object OuterAuthorId extends Feature[Long] - -case object AuthorBlocksOuterAuthor extends Feature[Boolean] - -case object OuterAuthorFollowsAuthor extends Feature[Boolean] - -case object OuterAuthorIsInnerAuthor extends Feature[Boolean] - -case object TweetIsModerated extends Feature[Boolean] -case object FocalTweetId extends Feature[Long] - -case object TweetId extends Feature[Long] - -case object TweetConversationId extends Feature[Long] -case object TweetParentId extends Feature[Long] -case object ConversationRootAuthorIsVerified extends Feature[Boolean] - -case object ViewerOptInBlocking extends Feature[Boolean] - -case object ViewerOptInFiltering extends Feature[Boolean] - -case object ViewerRoles extends Feature[Seq[String]] { - val EmployeeRole = "employee" -} - -case object TweetMisinformationPolicies extends Feature[Seq[MisinformationPolicy]] - -case object TweetEnglishMisinformationPolicies extends Feature[Seq[MisinformationPolicy]] - -case object HasInnerCircleOfFriendsRelationship extends Feature[Boolean] - -case object ViewerAge extends Feature[UserAge] - -case object HasDmcaMediaFeature extends Feature[Boolean] - -case object MediaGeoRestrictionsAllowList extends Feature[Seq[String]] -case object MediaGeoRestrictionsDenyList extends Feature[Seq[String]] - -case object TweetIsTrustedFriendTweet extends Feature[Boolean] -case object ViewerIsTrustedFriendTweetAuthor extends Feature[Boolean] -case object ViewerIsTrustedFriendOfTweetAuthor extends Feature[Boolean] - -case object DmConversationIsOneToOneConversation extends Feature[Boolean] -case object DmConversationHasEmptyTimeline extends Feature[Boolean] -case object DmConversationHasValidLastReadableEventId extends Feature[Boolean] -case object DmConversationInfoExists extends Feature[Boolean] -case object DmConversationTimelineExists extends Feature[Boolean] -case object ViewerIsDmConversationParticipant extends Feature[Boolean] - -case object DmEventIsMessageCreateEvent extends Feature[Boolean] -case object DmEventIsWelcomeMessageCreateEvent extends Feature[Boolean] -case object DmEventIsLastMessageReadUpdateEvent extends Feature[Boolean] -case object DmEventIsDeleted extends Feature[Boolean] -case object DmEventIsHidden extends Feature[Boolean] -case object ViewerIsDmEventInitiatingUser extends Feature[Boolean] -case object DmEventInOneToOneConversationWithUnavailableUser extends Feature[Boolean] -case object DmEventIsJoinConversationEvent extends Feature[Boolean] -case object DmEventIsConversationCreateEvent extends Feature[Boolean] -case object DmEventInOneToOneConversation extends Feature[Boolean] -case object DmEventIsTrustConversationEvent extends Feature[Boolean] -case object DmEventIsCsFeedbackSubmitted extends Feature[Boolean] -case object DmEventIsCsFeedbackDismissed extends Feature[Boolean] -case object DmEventIsPerspectivalJoinConversationEvent extends Feature[Boolean] - -case object DmEventOccurredBeforeLastClearedEvent extends Feature[Boolean] -case object DmEventOccurredBeforeJoinConversationEvent extends Feature[Boolean] - -case object CardUriHost extends Feature[String] -case object CardIsPoll extends Feature[Boolean] - -case object TweetIsStaleTweet extends Feature[Boolean] - -case object TweetIsEditTweet extends Feature[Boolean] - -case object TweetIsLatestTweet extends Feature[Boolean] - -case object TweetIsInitialTweet extends Feature[Boolean] - -case object TweetIsCollabInvitationTweet extends Feature[Boolean] - -case object ViewerSensitiveMediaSettings extends Feature[UserSensitiveMediaSettings] - - -case object ToxicReplyFilterState extends Feature[FilterState] - - -case object ToxicReplyFilterConversationAuthorIsViewer extends Feature[Boolean] - -case object RawQuery extends Feature[String] - -case object AuthorScreenName extends Feature[String] - -case object TweetIsInternalPromotedContent extends Feature[Boolean] diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/generators/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/generators/BUILD deleted file mode 100644 index c53b6b59d..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/generators/BUILD +++ /dev/null @@ -1,30 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/ibm/icu:icu4j", - "configapi/configapi-core", - "decider/src/main/scala", - "src/thrift/com/twitter/gizmoduck:thrift-scala", - "src/thrift/com/twitter/gizmoduck:user-thrift-scala", - "src/thrift/com/twitter/spam/rtf:safety-result-scala", - "stitch/stitch-core", - "strato/src/main/scala/com/twitter/strato/client", - "twitter-config/yaml", - "visibility/common/src/main/scala/com/twitter/visibility/common", - "visibility/common/src/main/scala/com/twitter/visibility/common/actions", - "visibility/common/src/main/scala/com/twitter/visibility/common/user_result", - "visibility/common/src/main/thrift/com/twitter/visibility:action-scala", - "visibility/lib/src/main/scala/com/twitter/visibility/builder", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/configs", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/models", - "visibility/lib/src/main/scala/com/twitter/visibility/rules", - "visibility/results/src/main/scala/com/twitter/visibility/results/richtext", - "visibility/results/src/main/scala/com/twitter/visibility/results/translation", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/generators/CountryNameGenerator.scala b/visibilitylib/src/main/scala/com/twitter/visibility/generators/CountryNameGenerator.scala deleted file mode 100644 index 014533a43..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/generators/CountryNameGenerator.scala +++ /dev/null @@ -1,58 +0,0 @@ -package com.twitter.visibility.generators - -import com.ibm.icu.util.ULocale -import com.twitter.config.yaml.YamlMap -import com.twitter.finagle.stats.StatsReceiver - -object CountryNameGenerator { - - private val AuroraFilesystemPath = "/usr/local/twitter-config/twitter/config/" - - private val ContentBlockingSupportedCountryList = "takedown_countries.yml" - - def providesFromConfigBus(statsReceiver: StatsReceiver): CountryNameGenerator = { - fromFile(AuroraFilesystemPath + ContentBlockingSupportedCountryList, statsReceiver) - } - - def providesWithCustomMap(countryCodeMap: Map[String, String], statsReceiver: StatsReceiver) = { - new CountryNameGenerator(countryCodeMap, statsReceiver) - } - - private def fromFile(fileName: String, statsReceiver: StatsReceiver) = { - val yamlConfig = YamlMap.load(fileName) - val countryCodeMap: Map[String, String] = yamlConfig.keySet.map { countryCode: String => - val normalizedCode = countryCode.toUpperCase - val countryName: Option[String] = - yamlConfig.get(Seq(countryCode, "name")).asInstanceOf[Option[String]] - (normalizedCode, countryName.getOrElse(normalizedCode)) - }.toMap - new CountryNameGenerator(countryCodeMap, statsReceiver) - } -} - -class CountryNameGenerator(countryCodeMap: Map[String, String], statsReceiver: StatsReceiver) { - - private val scopedStatsReceiver = statsReceiver.scope("country_name_generator") - private val foundCountryReceiver = scopedStatsReceiver.counter("found") - private val missingCountryReceiver = scopedStatsReceiver.counter("missing") - - def getCountryName(code: String): String = { - val normalizedCode = code.toUpperCase - countryCodeMap.get(normalizedCode) match { - case Some(retrievedName) => { - foundCountryReceiver.incr() - retrievedName - } - case _ => { - missingCountryReceiver.incr() - val fallbackName = - new ULocale("", normalizedCode).getDisplayCountry(ULocale.forLanguageTag("en")) - - if (fallbackName == "") - normalizedCode - else - fallbackName - } - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/generators/EpitaphToLocalizedMessage.scala b/visibilitylib/src/main/scala/com/twitter/visibility/generators/EpitaphToLocalizedMessage.scala deleted file mode 100644 index af5266848..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/generators/EpitaphToLocalizedMessage.scala +++ /dev/null @@ -1,66 +0,0 @@ -package com.twitter.visibility.generators - -import com.twitter.visibility.common.actions.LocalizedMessage -import com.twitter.visibility.common.actions.MessageLink -import com.twitter.visibility.results.translation.Translator -import com.twitter.visibility.results.richtext.EpitaphToRichText -import com.twitter.visibility.results.translation.Resource -import com.twitter.visibility.results.translation.LearnMoreLink -import com.twitter.visibility.rules.Epitaph -import com.twitter.visibility.results.richtext.EpitaphToRichText.Copy - -object EpitaphToLocalizedMessage { - def apply( - epitaph: Epitaph, - languageTag: String, - ): LocalizedMessage = { - val copy = - EpitaphToRichText.EpitaphToPolicyMap.getOrElse(epitaph, EpitaphToRichText.FallbackPolicy) - val text = Translator.translate( - copy.resource, - languageTag - ) - localizeWithCopyAndText(copy, languageTag, text) - } - - def apply( - epitaph: Epitaph, - languageTag: String, - applicableCountries: Seq[String], - ): LocalizedMessage = { - val copy = - EpitaphToRichText.EpitaphToPolicyMap.getOrElse(epitaph, EpitaphToRichText.FallbackPolicy) - val text = Translator.translateWithSimplePlaceholderReplacement( - copy.resource, - languageTag, - Map((Resource.ApplicableCountriesPlaceholder -> applicableCountries.mkString(", "))) - ) - localizeWithCopyAndText(copy, languageTag, text) - } - - private def localizeWithCopyAndText( - copy: Copy, - languageTag: String, - text: String - ): LocalizedMessage = { - val learnMore = Translator.translate(LearnMoreLink, languageTag) - - val links = copy.additionalLinks match { - case links if links.nonEmpty => - MessageLink(Resource.LearnMorePlaceholder, learnMore, copy.link) +: - links.map { - case EpitaphToRichText.Link(placeholder, copyResource, link) => - val copyText = Translator.translate(copyResource, languageTag) - MessageLink(placeholder, copyText, link) - } - case _ => - Seq( - MessageLink( - key = Resource.LearnMorePlaceholder, - displayText = learnMore, - uri = copy.link)) - } - - LocalizedMessage(message = text, language = languageTag, links = links) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/generators/InterstitialReasonToLocalizedMessage.scala b/visibilitylib/src/main/scala/com/twitter/visibility/generators/InterstitialReasonToLocalizedMessage.scala deleted file mode 100644 index f4e000338..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/generators/InterstitialReasonToLocalizedMessage.scala +++ /dev/null @@ -1,47 +0,0 @@ -package com.twitter.visibility.generators - -import com.twitter.visibility.common.actions.InterstitialReason -import com.twitter.visibility.common.actions.LocalizedMessage -import com.twitter.visibility.common.actions.MessageLink -import com.twitter.visibility.results.richtext.InterstitialReasonToRichText -import com.twitter.visibility.results.richtext.InterstitialReasonToRichText.InterstitialCopy -import com.twitter.visibility.results.richtext.InterstitialReasonToRichText.InterstitialLink -import com.twitter.visibility.results.translation.LearnMoreLink -import com.twitter.visibility.results.translation.Resource -import com.twitter.visibility.results.translation.Translator - -object InterstitialReasonToLocalizedMessage { - def apply( - reason: InterstitialReason, - languageTag: String, - ): Option[LocalizedMessage] = { - InterstitialReasonToRichText.reasonToCopy(reason).map { copy => - val text = Translator.translate( - copy.resource, - languageTag - ) - localizeWithCopyAndText(copy, languageTag, text) - } - } - - private def localizeWithCopyAndText( - copy: InterstitialCopy, - languageTag: String, - text: String - ): LocalizedMessage = { - val learnMore = Translator.translate(LearnMoreLink, languageTag) - - val learnMoreLinkOpt = - copy.link.map { link => - MessageLink(key = Resource.LearnMorePlaceholder, displayText = learnMore, uri = link) - } - val additionalLinks = copy.additionalLinks.map { - case InterstitialLink(placeholder, copyResource, link) => - val copyText = Translator.translate(copyResource, languageTag) - MessageLink(key = placeholder, displayText = copyText, uri = link) - } - - val links = learnMoreLinkOpt.toSeq ++ additionalLinks - LocalizedMessage(message = text, language = languageTag, links = links) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/generators/LocalizedInterstitialGenerator.scala b/visibilitylib/src/main/scala/com/twitter/visibility/generators/LocalizedInterstitialGenerator.scala deleted file mode 100644 index 6d381642e..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/generators/LocalizedInterstitialGenerator.scala +++ /dev/null @@ -1,151 +0,0 @@ -package com.twitter.visibility.generators - -import com.twitter.decider.Decider -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.common.actions.LocalizedMessage -import com.twitter.visibility.common.actions.MessageLink -import com.twitter.visibility.configapi.configs.VisibilityDeciderGates -import com.twitter.visibility.results.richtext.PublicInterestReasonToRichText -import com.twitter.visibility.results.translation.LearnMoreLink -import com.twitter.visibility.results.translation.Resource -import com.twitter.visibility.results.translation.SafetyResultReasonToResource -import com.twitter.visibility.results.translation.Translator -import com.twitter.visibility.rules.EmergencyDynamicInterstitial -import com.twitter.visibility.rules.Interstitial -import com.twitter.visibility.rules.InterstitialLimitedEngagements -import com.twitter.visibility.rules.PublicInterest -import com.twitter.visibility.rules.Reason -import com.twitter.visibility.rules.TweetInterstitial - -object LocalizedInterstitialGenerator { - def apply( - visibilityDecider: Decider, - baseStatsReceiver: StatsReceiver, - ): LocalizedInterstitialGenerator = { - new LocalizedInterstitialGenerator(visibilityDecider, baseStatsReceiver) - } -} - -class LocalizedInterstitialGenerator private ( - val visibilityDecider: Decider, - val baseStatsReceiver: StatsReceiver) { - - private val visibilityDeciderGates = VisibilityDeciderGates(visibilityDecider) - private val localizationStatsReceiver = baseStatsReceiver.scope("interstitial_localization") - private val publicInterestInterstitialStats = - localizationStatsReceiver.scope("public_interest_copy") - private val emergencyDynamicInterstitialStats = - localizationStatsReceiver.scope("emergency_dynamic_copy") - private val regularInterstitialStats = localizationStatsReceiver.scope("interstitial_copy") - - def apply(visibilityResult: VisibilityResult, languageTag: String): VisibilityResult = { - if (!visibilityDeciderGates.enableLocalizedInterstitialGenerator()) { - return visibilityResult - } - - visibilityResult.verdict match { - case ipi: InterstitialLimitedEngagements if PublicInterest.Reasons.contains(ipi.reason) => - visibilityResult.copy( - verdict = ipi.copy( - localizedMessage = Some(localizePublicInterestCopyInResult(ipi, languageTag)) - )) - case edi: EmergencyDynamicInterstitial => - visibilityResult.copy( - verdict = EmergencyDynamicInterstitial( - edi.copy, - edi.linkOpt, - Some(localizeEmergencyDynamicCopyInResult(edi, languageTag)) - )) - case interstitial: Interstitial => - visibilityResult.copy( - verdict = interstitial.copy( - localizedMessage = localizeInterstitialCopyInResult(interstitial, languageTag) - )) - case tweetInterstitial: TweetInterstitial if tweetInterstitial.interstitial.isDefined => - tweetInterstitial.interstitial.get match { - case ipi: InterstitialLimitedEngagements if PublicInterest.Reasons.contains(ipi.reason) => - visibilityResult.copy( - verdict = tweetInterstitial.copy( - interstitial = Some( - ipi.copy( - localizedMessage = Some(localizePublicInterestCopyInResult(ipi, languageTag)) - )) - )) - case edi: EmergencyDynamicInterstitial => - visibilityResult.copy( - verdict = tweetInterstitial.copy( - interstitial = Some( - EmergencyDynamicInterstitial( - edi.copy, - edi.linkOpt, - Some(localizeEmergencyDynamicCopyInResult(edi, languageTag)) - )) - )) - case interstitial: Interstitial => - visibilityResult.copy( - verdict = tweetInterstitial.copy( - interstitial = Some( - interstitial.copy( - localizedMessage = localizeInterstitialCopyInResult(interstitial, languageTag) - )) - )) - case _ => visibilityResult - } - case _ => visibilityResult - } - } - - private def localizeEmergencyDynamicCopyInResult( - edi: EmergencyDynamicInterstitial, - languageTag: String - ): LocalizedMessage = { - val text = edi.linkOpt - .map(_ => s"${edi.copy} {${Resource.LearnMorePlaceholder}}") - .getOrElse(edi.copy) - - val messageLinks = edi.linkOpt - .map { link => - val learnMoreText = Translator.translate(LearnMoreLink, languageTag) - Seq(MessageLink(Resource.LearnMorePlaceholder, learnMoreText, link)) - }.getOrElse(Seq.empty) - - emergencyDynamicInterstitialStats.counter("localized").incr() - LocalizedMessage(text, languageTag, messageLinks) - } - - private def localizePublicInterestCopyInResult( - ipi: InterstitialLimitedEngagements, - languageTag: String - ): LocalizedMessage = { - val safetyResultReason = PublicInterest.ReasonToSafetyResultReason(ipi.reason) - val text = Translator.translate( - SafetyResultReasonToResource.resource(safetyResultReason), - languageTag, - ) - - val learnMoreLink = PublicInterestReasonToRichText.toLearnMoreLink(safetyResultReason) - val learnMoreText = Translator.translate(LearnMoreLink, languageTag) - val messageLinks = Seq(MessageLink(Resource.LearnMorePlaceholder, learnMoreText, learnMoreLink)) - - publicInterestInterstitialStats.counter("localized").incr() - LocalizedMessage(text, languageTag, messageLinks) - } - - private def localizeInterstitialCopyInResult( - interstitial: Interstitial, - languageTag: String - ): Option[LocalizedMessage] = { - val localizedMessageOpt = Reason - .toInterstitialReason(interstitial.reason) - .flatMap(InterstitialReasonToLocalizedMessage(_, languageTag)) - - if (localizedMessageOpt.isDefined) { - regularInterstitialStats.counter("localized").incr() - localizedMessageOpt - } else { - regularInterstitialStats.counter("empty").incr() - None - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/generators/TombstoneGenerator.scala b/visibilitylib/src/main/scala/com/twitter/visibility/generators/TombstoneGenerator.scala deleted file mode 100644 index 9d52cc217..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/generators/TombstoneGenerator.scala +++ /dev/null @@ -1,94 +0,0 @@ -package com.twitter.visibility.generators - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.servo.util.MemoizingStatsReceiver -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.common.actions.TombstoneReason -import com.twitter.visibility.configapi.VisibilityParams -import com.twitter.visibility.rules.Epitaph -import com.twitter.visibility.rules.LocalizedTombstone -import com.twitter.visibility.rules.Tombstone - -object TombstoneGenerator { - def apply( - visibilityParams: VisibilityParams, - countryNameGenerator: CountryNameGenerator, - statsReceiver: StatsReceiver - ): TombstoneGenerator = { - new TombstoneGenerator(visibilityParams, countryNameGenerator, statsReceiver) - } -} - -class TombstoneGenerator( - paramsFactory: VisibilityParams, - countryNameGenerator: CountryNameGenerator, - baseStatsReceiver: StatsReceiver) { - - private[this] val statsReceiver = new MemoizingStatsReceiver( - baseStatsReceiver.scope("tombstone_generator")) - private[this] val deletedReceiver = statsReceiver.scope("deleted_state") - private[this] val authorStateReceiver = statsReceiver.scope("tweet_author_state") - private[this] val visResultReceiver = statsReceiver.scope("visibility_result") - - def apply( - result: VisibilityResult, - language: String - ): VisibilityResult = { - - result.verdict match { - case tombstone: Tombstone => - val epitaph = tombstone.epitaph - visResultReceiver.scope("tombstone").counter(epitaph.name.toLowerCase()) - - val overriddenLanguage = epitaph match { - case Epitaph.LegalDemandsWithheldMedia | Epitaph.LocalLawsWithheldMedia => "en" - case _ => language - } - - tombstone.applicableCountryCodes match { - case Some(countryCodes) => { - val countryNames = countryCodes.map(countryNameGenerator.getCountryName(_)) - - result.copy(verdict = LocalizedTombstone( - reason = epitaphToTombstoneReason(epitaph), - message = EpitaphToLocalizedMessage(epitaph, overriddenLanguage, countryNames))) - } - case _ => { - result.copy(verdict = LocalizedTombstone( - reason = epitaphToTombstoneReason(epitaph), - message = EpitaphToLocalizedMessage(epitaph, overriddenLanguage))) - } - } - case _ => - result - } - } - - private def epitaphToTombstoneReason(epitaph: Epitaph): TombstoneReason = { - epitaph match { - case Epitaph.Deleted => TombstoneReason.Deleted - case Epitaph.Bounced => TombstoneReason.Bounced - case Epitaph.BounceDeleted => TombstoneReason.BounceDeleted - case Epitaph.Protected => TombstoneReason.ProtectedAuthor - case Epitaph.Suspended => TombstoneReason.SuspendedAuthor - case Epitaph.BlockedBy => TombstoneReason.AuthorBlocksViewer - case Epitaph.SuperFollowsContent => TombstoneReason.ExclusiveTweet - case Epitaph.Underage => TombstoneReason.NsfwViewerIsUnderage - case Epitaph.NoStatedAge => TombstoneReason.NsfwViewerHasNoStatedAge - case Epitaph.LoggedOutAge => TombstoneReason.NsfwLoggedOut - case Epitaph.Deactivated => TombstoneReason.DeactivatedAuthor - case Epitaph.CommunityTweetHidden => TombstoneReason.CommunityTweetHidden - case Epitaph.CommunityTweetCommunityIsSuspended => - TombstoneReason.CommunityTweetCommunityIsSuspended - case Epitaph.DevelopmentOnly => TombstoneReason.DevelopmentOnly - case Epitaph.AdultMedia => TombstoneReason.AdultMedia - case Epitaph.ViolentMedia => TombstoneReason.ViolentMedia - case Epitaph.OtherSensitiveMedia => TombstoneReason.OtherSensitiveMedia - case Epitaph.DmcaWithheldMedia => TombstoneReason.DmcaWithheldMedia - case Epitaph.LegalDemandsWithheldMedia => TombstoneReason.LegalDemandsWithheldMedia - case Epitaph.LocalLawsWithheldMedia => TombstoneReason.LocalLawsWithheldMedia - case Epitaph.ToxicReplyFiltered => TombstoneReason.ReplyFiltered - case _ => TombstoneReason.Unspecified - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/blender/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/blender/BUILD deleted file mode 100644 index 545aee9e5..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/blender/BUILD +++ /dev/null @@ -1,34 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/twitter/src/java/com/twitter/logpipeline/client:logpipeline-event-publisher-thin", - "decider/src/main/scala", - "mediaservices/media-util/src/main/scala", - "servo/decider/src/main/scala", - "src/thrift/com/twitter/escherbird:media-annotation-structs-scala", - "src/thrift/com/twitter/spam/rtf:safety-level-scala", - "src/thrift/com/twitter/spam/rtf:tweet-rtf-event-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "stitch/stitch-core", - "strato/src/main/scala/com/twitter/strato/client", - "visibility/common/src/main/scala/com/twitter/visibility/common", - "visibility/lib/src/main/resources/config", - "visibility/lib/src/main/scala/com/twitter/visibility", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/media", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/tweets", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/users", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/configs", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/interfaces/common/blender", - "visibility/lib/src/main/scala/com/twitter/visibility/interfaces/common/tweets", - "visibility/lib/src/main/thrift/com/twitter/visibility/logging:vf-logging-scala", - ], - exports = [ - "visibility/common/src/main/scala/com/twitter/visibility/common", - "visibility/lib/src/main/scala/com/twitter/visibility", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/blender/BlenderVisibilityLibrary.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/blender/BlenderVisibilityLibrary.scala deleted file mode 100644 index c83756818..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/blender/BlenderVisibilityLibrary.scala +++ /dev/null @@ -1,416 +0,0 @@ -package com.twitter.visibility.interfaces.blender - -import com.twitter.decider.Decider -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.mediaservices.media_util.GenericMediaKey -import com.twitter.servo.util.Gate -import com.twitter.stitch.Stitch -import com.twitter.strato.client.{Client => StratoClient} -import com.twitter.tweetypie.thriftscala.Tweet -import com.twitter.util.Stopwatch -import com.twitter.visibility.VisibilityLibrary -import com.twitter.visibility.builder.VerdictLogger -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.builder.media.MediaFeatures -import com.twitter.visibility.builder.media.StratoMediaLabelMaps -import com.twitter.visibility.builder.tweets._ -import com.twitter.visibility.builder.users.AuthorFeatures -import com.twitter.visibility.builder.users.RelationshipFeatures -import com.twitter.visibility.builder.users.ViewerFeatures -import com.twitter.visibility.common.MediaSafetyLabelMapSource -import com.twitter.visibility.common.MisinformationPolicySource -import com.twitter.visibility.common.SafetyLabelMapSource -import com.twitter.visibility.common.TrustedFriendsSource -import com.twitter.visibility.common.UserRelationshipSource -import com.twitter.visibility.common.UserSource -import com.twitter.visibility.rules.ComposableActions.ComposableActionsWithInterstitial -import com.twitter.visibility.configapi.configs.VisibilityDeciderGates -import com.twitter.visibility.features.FeatureMap -import com.twitter.visibility.features.TweetIsInnerQuotedTweet -import com.twitter.visibility.features.TweetIsRetweet -import com.twitter.visibility.features.TweetIsSourceTweet -import com.twitter.visibility.logging.thriftscala.VFLibType -import com.twitter.visibility.models.ContentId -import com.twitter.visibility.models.ContentId.BlenderTweetId -import com.twitter.visibility.models.ContentId.TweetId -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.SafetyLevel.toThrift -import com.twitter.visibility.rules.Action -import com.twitter.visibility.rules.Allow -import com.twitter.visibility.rules.Drop -import com.twitter.visibility.rules.Interstitial -import com.twitter.visibility.rules.TweetInterstitial - -object TweetType extends Enumeration { - type TweetType = Value - val ORIGINAL, SOURCE, QUOTED = Value -} -import com.twitter.visibility.interfaces.blender.TweetType._ - -object BlenderVisibilityLibrary { - def buildWithStratoClient( - visibilityLibrary: VisibilityLibrary, - decider: Decider, - stratoClient: StratoClient, - userSource: UserSource, - userRelationshipSource: UserRelationshipSource - ): BlenderVisibilityLibrary = new BlenderVisibilityLibrary( - visibilityLibrary, - decider, - stratoClient, - userSource, - userRelationshipSource, - None - ) - - def buildWithSafetyLabelMapSource( - visibilityLibrary: VisibilityLibrary, - decider: Decider, - stratoClient: StratoClient, - userSource: UserSource, - userRelationshipSource: UserRelationshipSource, - safetyLabelMapSource: SafetyLabelMapSource - ): BlenderVisibilityLibrary = new BlenderVisibilityLibrary( - visibilityLibrary, - decider, - stratoClient, - userSource, - userRelationshipSource, - Some(safetyLabelMapSource) - ) - - def createVerdictLogger( - enableVerdictLogger: Gate[Unit], - decider: Decider, - statsReceiver: StatsReceiver - ): VerdictLogger = { - if (enableVerdictLogger()) { - VerdictLogger(statsReceiver, decider) - } else { - VerdictLogger.Empty - } - } - - def scribeVisibilityVerdict( - result: CombinedVisibilityResult, - enableVerdictScribing: Gate[Unit], - verdictLogger: VerdictLogger, - viewerId: Option[Long], - safetyLevel: SafetyLevel - ): Unit = if (enableVerdictScribing()) { - verdictLogger.scribeVerdict( - visibilityResult = result.tweetVisibilityResult, - viewerId = viewerId, - safetyLevel = toThrift(safetyLevel), - vfLibType = VFLibType.BlenderVisibilityLibrary) - - result.quotedTweetVisibilityResult.map(quotedTweetVisibilityResult => - verdictLogger.scribeVerdict( - visibilityResult = quotedTweetVisibilityResult, - viewerId = viewerId, - safetyLevel = toThrift(safetyLevel), - vfLibType = VFLibType.BlenderVisibilityLibrary)) - } -} - -class BlenderVisibilityLibrary( - visibilityLibrary: VisibilityLibrary, - decider: Decider, - stratoClient: StratoClient, - userSource: UserSource, - userRelationshipSource: UserRelationshipSource, - safetyLabelMapSourceOption: Option[SafetyLabelMapSource]) { - - val libraryStatsReceiver = visibilityLibrary.statsReceiver - val stratoClientStatsReceiver = visibilityLibrary.statsReceiver.scope("strato") - val vfEngineCounter = libraryStatsReceiver.counter("vf_engine_requests") - val bvlRequestCounter = libraryStatsReceiver.counter("bvl_requests") - val vfLatencyOverallStat = libraryStatsReceiver.stat("vf_latency_overall") - val vfLatencyStitchBuildStat = libraryStatsReceiver.stat("vf_latency_stitch_build") - val vfLatencyStitchRunStat = libraryStatsReceiver.stat("vf_latency_stitch_run") - val visibilityDeciderGates = VisibilityDeciderGates(decider) - val verdictLogger = BlenderVisibilityLibrary.createVerdictLogger( - visibilityDeciderGates.enableVerdictLoggerBVL, - decider, - libraryStatsReceiver) - - val tweetLabels = safetyLabelMapSourceOption match { - case Some(safetyLabelMapSource) => - new StratoTweetLabelMaps(safetyLabelMapSource) - case None => - new StratoTweetLabelMaps( - SafetyLabelMapSource.fromStrato(stratoClient, stratoClientStatsReceiver)) - } - - val mediaLabelMaps = new StratoMediaLabelMaps( - MediaSafetyLabelMapSource.fromStrato(stratoClient, stratoClientStatsReceiver)) - - val tweetFeatures = new TweetFeatures(tweetLabels, libraryStatsReceiver) - val blenderContextFeatures = new BlenderContextFeatures(libraryStatsReceiver) - val authorFeatures = new AuthorFeatures(userSource, libraryStatsReceiver) - val viewerFeatures = new ViewerFeatures(userSource, libraryStatsReceiver) - val relationshipFeatures = - new RelationshipFeatures(userRelationshipSource, libraryStatsReceiver) - val fonsrRelationshipFeatures = - new FosnrRelationshipFeatures( - tweetLabels = tweetLabels, - userRelationshipSource = userRelationshipSource, - statsReceiver = libraryStatsReceiver) - val misinfoPolicySource = - MisinformationPolicySource.fromStrato(stratoClient, stratoClientStatsReceiver) - val misinfoPolicyFeatures = - new MisinformationPolicyFeatures(misinfoPolicySource, stratoClientStatsReceiver) - val exclusiveTweetFeatures = - new ExclusiveTweetFeatures(userRelationshipSource, libraryStatsReceiver) - val mediaFeatures = new MediaFeatures(mediaLabelMaps, libraryStatsReceiver) - val trustedFriendsTweetFeatures = new TrustedFriendsFeatures( - trustedFriendsSource = TrustedFriendsSource.fromStrato(stratoClient, stratoClientStatsReceiver)) - val editTweetFeatures = new EditTweetFeatures(libraryStatsReceiver) - - def getCombinedVisibilityResult( - bvRequest: BlenderVisibilityRequest - ): Stitch[CombinedVisibilityResult] = { - val elapsed = Stopwatch.start() - bvlRequestCounter.incr() - - val ( - requestTweetVisibilityResult, - quotedTweetVisibilityResultOption, - sourceTweetVisibilityResultOption - ) = getAllVisibilityResults(bvRequest: BlenderVisibilityRequest) - - val response: Stitch[CombinedVisibilityResult] = { - ( - requestTweetVisibilityResult, - quotedTweetVisibilityResultOption, - sourceTweetVisibilityResultOption) match { - case (requestTweetVisResult, Some(quotedTweetVisResult), Some(sourceTweetVisResult)) => { - Stitch - .join( - requestTweetVisResult, - quotedTweetVisResult, - sourceTweetVisResult - ).map { - case (requestTweetVisResult, quotedTweetVisResult, sourceTweetVisResult) => { - requestTweetVisResult.verdict match { - case Allow => - CombinedVisibilityResult(sourceTweetVisResult, Some(quotedTweetVisResult)) - case _ => - CombinedVisibilityResult(requestTweetVisResult, Some(quotedTweetVisResult)) - } - } - } - } - - case (requestTweetVisResult, None, Some(sourceTweetVisResult)) => { - Stitch - .join( - requestTweetVisResult, - sourceTweetVisResult - ).map { - case (requestTweetVisResult, sourceTweetVisResult) => { - requestTweetVisResult.verdict match { - case Allow => - CombinedVisibilityResult(sourceTweetVisResult, None) - case _ => - CombinedVisibilityResult(requestTweetVisResult, None) - } - } - } - } - - case (requestTweetVisResult, Some(quotedTweetVisResult), None) => { - Stitch - .join( - requestTweetVisResult, - quotedTweetVisResult - ).map { - case (requestTweetVisResult, quotedTweetVisResult) => { - CombinedVisibilityResult(requestTweetVisResult, Some(quotedTweetVisResult)) - } - } - } - - case (requestTweetVisResult, None, None) => { - requestTweetVisResult.map { - CombinedVisibilityResult(_, None) - } - } - } - } - val runStitchStartMs = elapsed().inMilliseconds - val buildStitchStatMs = elapsed().inMilliseconds - vfLatencyStitchBuildStat.add(buildStitchStatMs) - - response - .onSuccess(_ => { - val overallMs = elapsed().inMilliseconds - vfLatencyOverallStat.add(overallMs) - val stitchRunMs = elapsed().inMilliseconds - runStitchStartMs - vfLatencyStitchRunStat.add(stitchRunMs) - }) - .onSuccess( - BlenderVisibilityLibrary.scribeVisibilityVerdict( - _, - visibilityDeciderGates.enableVerdictScribingBVL, - verdictLogger, - bvRequest.viewerContext.userId, - bvRequest.safetyLevel)) - } - - def getContentId(viewerId: Option[Long], authorId: Long, tweet: Tweet): ContentId = { - if (viewerId.contains(authorId)) - TweetId(tweet.id) - else BlenderTweetId(tweet.id) - } - - def getAllVisibilityResults(bvRequest: BlenderVisibilityRequest): ( - Stitch[VisibilityResult], - Option[Stitch[VisibilityResult]], - Option[Stitch[VisibilityResult]] - ) = { - val tweetContentId = getContentId( - viewerId = bvRequest.viewerContext.userId, - authorId = bvRequest.tweet.coreData.get.userId, - tweet = bvRequest.tweet) - - val tweetFeatureMap = - buildFeatureMap(bvRequest, bvRequest.tweet, ORIGINAL) - vfEngineCounter.incr() - val requestTweetVisibilityResult = visibilityLibrary - .runRuleEngine( - tweetContentId, - tweetFeatureMap, - bvRequest.viewerContext, - bvRequest.safetyLevel - ).map(handleComposableVisibilityResult) - - val quotedTweetVisibilityResultOption = bvRequest.quotedTweet.map(quotedTweet => { - val quotedTweetContentId = getContentId( - viewerId = bvRequest.viewerContext.userId, - authorId = quotedTweet.coreData.get.userId, - tweet = quotedTweet) - - val quotedInnerTweetFeatureMap = - buildFeatureMap(bvRequest, quotedTweet, QUOTED) - vfEngineCounter.incr() - visibilityLibrary - .runRuleEngine( - quotedTweetContentId, - quotedInnerTweetFeatureMap, - bvRequest.viewerContext, - bvRequest.safetyLevel - ) - .map(handleComposableVisibilityResult) - .map(handleInnerQuotedTweetVisibilityResult) - }) - - val sourceTweetVisibilityResultOption = bvRequest.retweetSourceTweet.map(sourceTweet => { - val sourceTweetContentId = getContentId( - viewerId = bvRequest.viewerContext.userId, - authorId = sourceTweet.coreData.get.userId, - tweet = sourceTweet) - - val sourceTweetFeatureMap = - buildFeatureMap(bvRequest, sourceTweet, SOURCE) - vfEngineCounter.incr() - visibilityLibrary - .runRuleEngine( - sourceTweetContentId, - sourceTweetFeatureMap, - bvRequest.viewerContext, - bvRequest.safetyLevel - ) - .map(handleComposableVisibilityResult) - }) - - ( - requestTweetVisibilityResult, - quotedTweetVisibilityResultOption, - sourceTweetVisibilityResultOption) - } - - def buildFeatureMap( - bvRequest: BlenderVisibilityRequest, - tweet: Tweet, - tweetType: TweetType - ): FeatureMap = { - val authorId = tweet.coreData.get.userId - val viewerId = bvRequest.viewerContext.userId - val isRetweet = if (tweetType.equals(ORIGINAL)) bvRequest.isRetweet else false - val isSourceTweet = tweetType.equals(SOURCE) - val isQuotedTweet = tweetType.equals(QUOTED) - val tweetMediaKeys: Seq[GenericMediaKey] = tweet.media - .getOrElse(Seq.empty) - .flatMap(_.mediaKey.map(GenericMediaKey.apply)) - - visibilityLibrary.featureMapBuilder( - Seq( - viewerFeatures - .forViewerBlenderContext(bvRequest.blenderVFRequestContext, bvRequest.viewerContext), - relationshipFeatures.forAuthorId(authorId, viewerId), - fonsrRelationshipFeatures - .forTweetAndAuthorId(tweet = tweet, authorId = authorId, viewerId = viewerId), - tweetFeatures.forTweet(tweet), - mediaFeatures.forMediaKeys(tweetMediaKeys), - authorFeatures.forAuthorId(authorId), - blenderContextFeatures.forBlenderContext(bvRequest.blenderVFRequestContext), - _.withConstantFeature(TweetIsRetweet, isRetweet), - misinfoPolicyFeatures.forTweet(tweet, bvRequest.viewerContext), - exclusiveTweetFeatures.forTweet(tweet, bvRequest.viewerContext), - trustedFriendsTweetFeatures.forTweet(tweet, viewerId), - editTweetFeatures.forTweet(tweet), - _.withConstantFeature(TweetIsInnerQuotedTweet, isQuotedTweet), - _.withConstantFeature(TweetIsSourceTweet, isSourceTweet), - ) - ) - } - - def handleComposableVisibilityResult(result: VisibilityResult): VisibilityResult = { - if (result.secondaryVerdicts.nonEmpty) { - result.copy(verdict = composeActions(result.verdict, result.secondaryVerdicts)) - } else { - result - } - } - - private def composeActions(primary: Action, secondary: Seq[Action]): Action = { - if (primary.isComposable && secondary.nonEmpty) { - val actions = Seq[Action] { primary } ++ secondary - val interstitialOpt = Action.getFirstInterstitial(actions: _*) - val softInterventionOpt = Action.getFirstSoftIntervention(actions: _*) - val limitedEngagementsOpt = Action.getFirstLimitedEngagements(actions: _*) - val avoidOpt = Action.getFirstAvoid(actions: _*) - - val numActions = - Seq[Option[_]](interstitialOpt, softInterventionOpt, limitedEngagementsOpt, avoidOpt) - .count(_.isDefined) - if (numActions > 1) { - TweetInterstitial( - interstitialOpt, - softInterventionOpt, - limitedEngagementsOpt, - None, - avoidOpt - ) - } else { - primary - } - } else { - primary - } - } - - def handleInnerQuotedTweetVisibilityResult( - result: VisibilityResult - ): VisibilityResult = { - val newVerdict: Action = - result.verdict match { - case interstitial: Interstitial => Drop(interstitial.reason) - case ComposableActionsWithInterstitial(tweetInterstitial) => Drop(tweetInterstitial.reason) - case verdict => verdict - } - - result.copy(verdict = newVerdict) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/blender/BlenderVisibilityRequest.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/blender/BlenderVisibilityRequest.scala deleted file mode 100644 index aa6e604a5..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/blender/BlenderVisibilityRequest.scala +++ /dev/null @@ -1,42 +0,0 @@ -package com.twitter.visibility.interfaces.blender - -import com.twitter.tweetypie.thriftscala.Tweet -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.ViewerContext -import com.twitter.visibility.interfaces.common.blender.BlenderVFRequestContext - -case class BlenderVisibilityRequest( - tweet: Tweet, - quotedTweet: Option[Tweet], - retweetSourceTweet: Option[Tweet] = None, - isRetweet: Boolean, - safetyLevel: SafetyLevel, - viewerContext: ViewerContext, - blenderVFRequestContext: BlenderVFRequestContext) { - - def getTweetID: Long = tweet.id - - def hasQuotedTweet: Boolean = { - quotedTweet.nonEmpty - } - def hasSourceTweet: Boolean = { - retweetSourceTweet.nonEmpty - } - - def getQuotedTweetId: Long = { - quotedTweet match { - case Some(qTweet) => - qTweet.id - case None => - -1 - } - } - def getSourceTweetId: Long = { - retweetSourceTweet match { - case Some(sourceTweet) => - sourceTweet.id - case None => - -1 - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/blender/CombinedVisibilityResult.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/blender/CombinedVisibilityResult.scala deleted file mode 100644 index 6868b67ec..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/blender/CombinedVisibilityResult.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.visibility.interfaces.blender - -import com.twitter.visibility.builder.VisibilityResult - -case class CombinedVisibilityResult( - tweetVisibilityResult: VisibilityResult, - quotedTweetVisibilityResult: Option[VisibilityResult]) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/cards/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/cards/BUILD deleted file mode 100644 index b2b0f998f..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/cards/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = False, - tags = ["bazel-compatible"], - dependencies = [ - "appsec/sanitization-lib/src/main/scala", - "src/thrift/com/twitter/expandodo:cards-scala", - "stitch/stitch-core", - "visibility/lib/src/main/resources/config", - "visibility/lib/src/main/scala/com/twitter/visibility", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/tweets", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/users", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/cards/CardVisibilityLibrary.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/cards/CardVisibilityLibrary.scala deleted file mode 100644 index 575356901..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/cards/CardVisibilityLibrary.scala +++ /dev/null @@ -1,187 +0,0 @@ -package com.twitter.visibility.interfaces.cards - -import com.twitter.appsec.sanitization.URLSafety -import com.twitter.decider.Decider -import com.twitter.servo.util.Gate -import com.twitter.stitch.Stitch -import com.twitter.tweetypie.{thriftscala => tweetypiethrift} -import com.twitter.util.Stopwatch -import com.twitter.visibility.VisibilityLibrary -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.builder.tweets.CommunityTweetFeatures -import com.twitter.visibility.builder.tweets.CommunityTweetFeaturesV2 -import com.twitter.visibility.builder.tweets.NilTweetLabelMaps -import com.twitter.visibility.builder.tweets.TweetFeatures -import com.twitter.visibility.builder.users.AuthorFeatures -import com.twitter.visibility.builder.users.RelationshipFeatures -import com.twitter.visibility.builder.users.ViewerFeatures -import com.twitter.visibility.common.CommunitiesSource -import com.twitter.visibility.common.UserId -import com.twitter.visibility.common.UserRelationshipSource -import com.twitter.visibility.common.UserSource -import com.twitter.visibility.configapi.configs.VisibilityDeciderGates -import com.twitter.visibility.features.CardIsPoll -import com.twitter.visibility.features.CardUriHost -import com.twitter.visibility.features.FeatureMap -import com.twitter.visibility.models.ContentId.CardId -import com.twitter.visibility.models.ViewerContext - -object CardVisibilityLibrary { - type Type = CardVisibilityRequest => Stitch[VisibilityResult] - - private[this] def getAuthorFeatures( - authorIdOpt: Option[Long], - authorFeatures: AuthorFeatures - ): FeatureMapBuilder => FeatureMapBuilder = { - authorIdOpt match { - case Some(authorId) => authorFeatures.forAuthorId(authorId) - case _ => authorFeatures.forNoAuthor() - } - } - - private[this] def getCardUriFeatures( - cardUri: String, - enableCardVisibilityLibraryCardUriParsing: Boolean, - trackCardUriHost: Option[String] => Unit - ): FeatureMapBuilder => FeatureMapBuilder = { - if (enableCardVisibilityLibraryCardUriParsing) { - val safeCardUriHost = URLSafety.getHostSafe(cardUri) - trackCardUriHost(safeCardUriHost) - - _.withConstantFeature(CardUriHost, safeCardUriHost) - } else { - identity - } - } - - private[this] def getRelationshipFeatures( - authorIdOpt: Option[Long], - viewerIdOpt: Option[Long], - relationshipFeatures: RelationshipFeatures - ): FeatureMapBuilder => FeatureMapBuilder = { - authorIdOpt match { - case Some(authorId) => relationshipFeatures.forAuthorId(authorId, viewerIdOpt) - case _ => relationshipFeatures.forNoAuthor() - } - } - - private[this] def getTweetFeatures( - tweetOpt: Option[tweetypiethrift.Tweet], - tweetFeatures: TweetFeatures - ): FeatureMapBuilder => FeatureMapBuilder = { - tweetOpt match { - case Some(tweet) => tweetFeatures.forTweet(tweet) - case _ => identity - } - } - - private[this] def getCommunityFeatures( - tweetOpt: Option[tweetypiethrift.Tweet], - viewerContext: ViewerContext, - communityTweetFeatures: CommunityTweetFeatures - ): FeatureMapBuilder => FeatureMapBuilder = { - tweetOpt match { - case Some(tweet) => communityTweetFeatures.forTweet(tweet, viewerContext) - case _ => identity - } - } - - def apply( - visibilityLibrary: VisibilityLibrary, - userSource: UserSource = UserSource.empty, - userRelationshipSource: UserRelationshipSource = UserRelationshipSource.empty, - communitiesSource: CommunitiesSource = CommunitiesSource.empty, - enableVfParityTest: Gate[Unit] = Gate.False, - enableVfFeatureHydration: Gate[Unit] = Gate.False, - decider: Decider - ): Type = { - val libraryStatsReceiver = visibilityLibrary.statsReceiver - val vfLatencyOverallStat = libraryStatsReceiver.stat("vf_latency_overall") - val vfLatencyStitchBuildStat = libraryStatsReceiver.stat("vf_latency_stitch_build") - val vfLatencyStitchRunStat = libraryStatsReceiver.stat("vf_latency_stitch_run") - val cardUriStats = libraryStatsReceiver.scope("card_uri") - val visibilityDeciderGates = VisibilityDeciderGates(decider) - - val authorFeatures = new AuthorFeatures(userSource, libraryStatsReceiver) - val viewerFeatures = new ViewerFeatures(userSource, libraryStatsReceiver) - val tweetFeatures = new TweetFeatures(NilTweetLabelMaps, libraryStatsReceiver) - val communityTweetFeatures = new CommunityTweetFeaturesV2( - communitiesSource = communitiesSource, - ) - val relationshipFeatures = - new RelationshipFeatures(userRelationshipSource, libraryStatsReceiver) - val parityTest = new CardVisibilityLibraryParityTest(libraryStatsReceiver) - - { r: CardVisibilityRequest => - val elapsed = Stopwatch.start() - var runStitchStartMs = 0L - - val viewerId: Option[UserId] = r.viewerContext.userId - - val featureMap = - visibilityLibrary - .featureMapBuilder( - Seq( - viewerFeatures.forViewerId(viewerId), - getAuthorFeatures(r.authorId, authorFeatures), - getCardUriFeatures( - cardUri = r.cardUri, - enableCardVisibilityLibraryCardUriParsing = - visibilityDeciderGates.enableCardVisibilityLibraryCardUriParsing(), - trackCardUriHost = { safeCardUriHost: Option[String] => - if (safeCardUriHost.isEmpty) { - cardUriStats.counter("empty").incr() - } - } - ), - getCommunityFeatures(r.tweetOpt, r.viewerContext, communityTweetFeatures), - getRelationshipFeatures(r.authorId, r.viewerContext.userId, relationshipFeatures), - getTweetFeatures(r.tweetOpt, tweetFeatures), - _.withConstantFeature(CardIsPoll, r.isPollCardType) - ) - ) - - val response = visibilityLibrary - .runRuleEngine( - CardId(r.cardUri), - featureMap, - r.viewerContext, - r.safetyLevel - ) - .onSuccess(_ => { - val overallStatMs = elapsed().inMilliseconds - vfLatencyOverallStat.add(overallStatMs) - val runStitchEndMs = elapsed().inMilliseconds - vfLatencyStitchRunStat.add(runStitchEndMs - runStitchStartMs) - }) - - runStitchStartMs = elapsed().inMilliseconds - val buildStitchStatMs = elapsed().inMilliseconds - vfLatencyStitchBuildStat.add(buildStitchStatMs) - - lazy val hydratedFeatureResponse: Stitch[VisibilityResult] = - FeatureMap.resolve(featureMap, libraryStatsReceiver).flatMap { resolvedFeatureMap => - visibilityLibrary.runRuleEngine( - CardId(r.cardUri), - resolvedFeatureMap, - r.viewerContext, - r.safetyLevel - ) - } - - val isVfParityTestEnabled = enableVfParityTest() - val isVfFeatureHydrationEnabled = enableVfFeatureHydration() - - if (!isVfParityTestEnabled && !isVfFeatureHydrationEnabled) { - response - } else if (isVfParityTestEnabled && !isVfFeatureHydrationEnabled) { - response.applyEffect { resp => - Stitch.async(parityTest.runParityTest(hydratedFeatureResponse, resp)) - } - } else { - hydratedFeatureResponse - } - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/cards/CardVisibilityLibraryParityTest.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/cards/CardVisibilityLibraryParityTest.scala deleted file mode 100644 index 4dc3f6baf..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/cards/CardVisibilityLibraryParityTest.scala +++ /dev/null @@ -1,35 +0,0 @@ -package com.twitter.visibility.interfaces.cards - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.stitch.Stitch -import com.twitter.visibility.builder.VisibilityResult - -class CardVisibilityLibraryParityTest(statsReceiver: StatsReceiver) { - private val parityTestScope = statsReceiver.scope("card_visibility_library_parity") - private val requests = parityTestScope.counter("requests") - private val equal = parityTestScope.counter("equal") - private val incorrect = parityTestScope.counter("incorrect") - private val failures = parityTestScope.counter("failures") - - def runParityTest( - preHydratedFeatureVisibilityResult: Stitch[VisibilityResult], - resp: VisibilityResult - ): Stitch[Unit] = { - requests.incr() - - preHydratedFeatureVisibilityResult - .flatMap { parityResponse => - if (parityResponse.verdict == resp.verdict) { - equal.incr() - } else { - incorrect.incr() - } - - Stitch.Done - }.rescue { - case t: Throwable => - failures.incr() - Stitch.Done - }.unit - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/cards/CardVisibilityRequest.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/cards/CardVisibilityRequest.scala deleted file mode 100644 index c3cef91d2..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/cards/CardVisibilityRequest.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.visibility.interfaces.cards - -import com.twitter.tweetypie.{thriftscala => tweetypiethrift} -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.ViewerContext - -case class CardVisibilityRequest( - cardUri: String, - authorId: Option[Long], - tweetOpt: Option[tweetypiethrift.Tweet], - isPollCardType: Boolean, - safetyLevel: SafetyLevel, - viewerContext: ViewerContext) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/BUILD.bazel b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/BUILD.bazel deleted file mode 100644 index e8d9d1b25..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/BUILD.bazel +++ /dev/null @@ -1,15 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - dependencies = [ - "src/scala/com/twitter/search/blender/services/strato", - "src/thrift/com/twitter/spam/rtf:safety-label-scala", - "src/thrift/com/twitter/spam/rtf:tweet-rtf-event-scala", - "stitch/stitch-core", - "strato/src/main/scala/com/twitter/strato/catalog", - "strato/src/main/scala/com/twitter/strato/client", - "strato/src/main/scala/com/twitter/strato/data", - "strato/src/main/scala/com/twitter/strato/thrift", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/blender/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/blender/BUILD deleted file mode 100644 index c0f745c39..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/blender/BUILD +++ /dev/null @@ -1,14 +0,0 @@ -scala_library( - sources = [ - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "src/scala/com/twitter/search/blender/services/strato", - "src/thrift/com/twitter/search/common:constants-scala", - "stitch/stitch-core", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/blender/BlenderVFRequestContext.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/blender/BlenderVFRequestContext.scala deleted file mode 100644 index 05e98c17d..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/blender/BlenderVFRequestContext.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.visibility.interfaces.common.blender - -import com.twitter.search.blender.services.strato.UserSearchSafetySettings -import com.twitter.search.common.constants.thriftscala.ThriftQuerySource - -case class BlenderVFRequestContext( - resultsPageNumber: Int, - candidateCount: Int, - querySourceOption: Option[ThriftQuerySource], - userSearchSafetySettings: UserSearchSafetySettings, - queryHasUser: Boolean = false) { - - def this( - resultsPageNumber: Int, - candidateCount: Int, - querySourceOption: Option[ThriftQuerySource], - userSearchSafetySettings: UserSearchSafetySettings - ) = this(resultsPageNumber, candidateCount, querySourceOption, userSearchSafetySettings, false) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/search/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/search/BUILD deleted file mode 100644 index c0f745c39..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/search/BUILD +++ /dev/null @@ -1,14 +0,0 @@ -scala_library( - sources = [ - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "src/scala/com/twitter/search/blender/services/strato", - "src/thrift/com/twitter/search/common:constants-scala", - "stitch/stitch-core", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/search/SearchVFRequestContext.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/search/SearchVFRequestContext.scala deleted file mode 100644 index ef06b0b3b..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/search/SearchVFRequestContext.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.visibility.interfaces.common.search - -import com.twitter.search.blender.services.strato.UserSearchSafetySettings -import com.twitter.search.common.constants.thriftscala.ThriftQuerySource - -case class SearchVFRequestContext( - resultsPageNumber: Int, - candidateCount: Int, - querySourceOption: Option[ThriftQuerySource], - userSearchSafetySettings: UserSearchSafetySettings, - queryHasUser: Boolean = false) { - - def this( - resultsPageNumber: Int, - candidateCount: Int, - querySourceOption: Option[ThriftQuerySource], - userSearchSafetySettings: UserSearchSafetySettings - ) = this(resultsPageNumber, candidateCount, querySourceOption, userSearchSafetySettings, false) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/tweets/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/tweets/BUILD deleted file mode 100644 index 64400fae2..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/tweets/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "src/scala/com/twitter/search/blender/services/strato", - "src/thrift/com/twitter/spam/rtf:safety-label-scala", - "src/thrift/com/twitter/spam/rtf:tweet-rtf-event-scala", - "stitch/stitch-core", - "strato/src/main/scala/com/twitter/strato/catalog", - "strato/src/main/scala/com/twitter/strato/client", - "strato/src/main/scala/com/twitter/strato/data", - "strato/src/main/scala/com/twitter/strato/thrift", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/tweets/StratoSafetyLabelFetcher.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/tweets/StratoSafetyLabelFetcher.scala deleted file mode 100644 index 324620892..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/tweets/StratoSafetyLabelFetcher.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.visibility.interfaces.common.tweets - -import com.twitter.spam.rtf.thriftscala.SafetyLabel -import com.twitter.spam.rtf.thriftscala.SafetyLabelType -import com.twitter.strato.client.Fetcher -import com.twitter.strato.client.{Client => StratoClient} -import com.twitter.strato.thrift.ScroogeConvImplicits._ -import com.twitter.util.Memoize - -object StratoSafetyLabelFetcher { - def apply(client: StratoClient): SafetyLabelFetcherType = { - val getFetcher: SafetyLabelType => Fetcher[Long, Unit, SafetyLabel] = - Memoize((safetyLabelType: SafetyLabelType) => - client.fetcher[Long, SafetyLabel](s"visibility/${safetyLabelType.name}.Tweet")) - - (tweetId, safetyLabelType) => getFetcher(safetyLabelType).fetch(tweetId).map(_.v) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/tweets/StratoSafetyLabelMapFetcher.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/tweets/StratoSafetyLabelMapFetcher.scala deleted file mode 100644 index a76ad92a9..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/tweets/StratoSafetyLabelMapFetcher.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.visibility.interfaces.common.tweets - -import com.twitter.spam.rtf.thriftscala.SafetyLabelMap -import com.twitter.strato.client.Fetcher -import com.twitter.strato.client.{Client => StratoClient} -import com.twitter.strato.thrift.ScroogeConvImplicits._ - -object StratoSafetyLabelMapFetcher { - val column = "visibility/baseTweetSafetyLabelMap" - - def apply(client: StratoClient): SafetyLabelMapFetcherType = { - val fetcher: Fetcher[Long, Unit, SafetyLabelMap] = - client.fetcher[Long, SafetyLabelMap](column) - - tweetId => fetcher.fetch(tweetId).map(_.v) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/tweets/package.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/tweets/package.scala deleted file mode 100644 index 82a8033d6..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/common/tweets/package.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.visibility.interfaces.common - -import com.twitter.search.blender.services.strato.UserSearchSafetySettings -import com.twitter.spam.rtf.thriftscala.SafetyLabel -import com.twitter.spam.rtf.thriftscala.SafetyLabelMap -import com.twitter.spam.rtf.thriftscala.SafetyLabelType -import com.twitter.stitch.Stitch - -package object tweets { - type SafetyLabelFetcherType = (Long, SafetyLabelType) => Stitch[Option[SafetyLabel]] - type SafetyLabelMapFetcherType = Long => Stitch[Option[SafetyLabelMap]] - type UserSearchSafetySettingsFetcherType = Long => Stitch[UserSearchSafetySettings] -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/conversations/AdAvoidanceLibrary.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/conversations/AdAvoidanceLibrary.scala deleted file mode 100644 index 067fa833f..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/conversations/AdAvoidanceLibrary.scala +++ /dev/null @@ -1,158 +0,0 @@ -package com.twitter.visibility.interfaces.conversations - -import com.google.common.annotations.VisibleForTesting -import com.twitter.decider.Decider -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.gizmoduck.thriftscala.User -import com.twitter.spam.rtf.thriftscala.SafetyLevel -import com.twitter.stitch.Stitch -import com.twitter.tweetypie.thriftscala.GetTweetFieldsResult -import com.twitter.tweetypie.thriftscala.TweetFieldsResultFound -import com.twitter.tweetypie.thriftscala.TweetFieldsResultState -import com.twitter.util.Stopwatch -import com.twitter.visibility.VisibilityLibrary -import com.twitter.visibility.common.filtered_reason.FilteredReasonHelper -import com.twitter.visibility.models.ViewerContext -import com.twitter.visibility.rules.Interstitial -import com.twitter.visibility.rules.Tombstone - -case class AdAvoidanceRequest( - conversationId: Long, - focalTweetId: Long, - tweets: Seq[(GetTweetFieldsResult, Option[SafetyLevel])], - authorMap: Map[ - Long, - User - ], - moderatedTweetIds: Seq[Long], - viewerContext: ViewerContext, - useRichText: Boolean = true) - -case class AdAvoidanceResponse(dropAd: Map[Long, Boolean]) - -object AdAvoidanceLibrary { - type Type = - AdAvoidanceRequest => Stitch[AdAvoidanceResponse] - - private def shouldAvoid( - result: TweetFieldsResultState, - tombstoneOpt: Option[VfTombstone], - statsReceiver: StatsReceiver - ): Boolean = { - shouldAvoid(result, statsReceiver) || shouldAvoid(tombstoneOpt, statsReceiver) - } - - private def shouldAvoid( - result: TweetFieldsResultState, - statsReceiver: StatsReceiver - ): Boolean = { - result match { - case TweetFieldsResultState.Found(TweetFieldsResultFound(_, _, Some(filteredReason))) - if FilteredReasonHelper.isAvoid(filteredReason) => - statsReceiver.counter("avoid").incr() - true - case _ => false - } - } - - private def shouldAvoid( - tombstoneOpt: Option[VfTombstone], - statsReceiver: StatsReceiver, - ): Boolean = { - tombstoneOpt - .map(_.action).collect { - case Tombstone(epitaph, _) => - statsReceiver.scope("tombstone").counter(epitaph.name).incr() - true - case interstitial: Interstitial => - statsReceiver.scope("interstitial").counter(interstitial.reason.name).incr() - true - case _ => false - }.getOrElse(false) - } - - private def runTombstoneVisLib( - request: AdAvoidanceRequest, - tombstoneVisibilityLibrary: TombstoneVisibilityLibrary, - ): Stitch[TombstoneVisibilityResponse] = { - val tombstoneRequest = TombstoneVisibilityRequest( - conversationId = request.conversationId, - focalTweetId = request.focalTweetId, - tweets = request.tweets, - authorMap = request.authorMap, - moderatedTweetIds = request.moderatedTweetIds, - viewerContext = request.viewerContext, - useRichText = request.useRichText - ) - - tombstoneVisibilityLibrary(tombstoneRequest) - } - - def buildTweetAdAvoidanceMap(tweets: Seq[GetTweetFieldsResult]): Map[Long, Boolean] = tweets - .map(tweet => { - val shouldAvoid = tweet.tweetResult match { - case TweetFieldsResultState.Found(TweetFieldsResultFound(_, _, Some(filteredReason))) => - FilteredReasonHelper.isAvoid(filteredReason) - case _ => false - } - - tweet.tweetId -> shouldAvoid - }).toMap - - def apply(visibilityLibrary: VisibilityLibrary, decider: Decider): Type = { - val tvl = - TombstoneVisibilityLibrary(visibilityLibrary, visibilityLibrary.statsReceiver, decider) - buildLibrary(tvl, visibilityLibrary.statsReceiver) - } - - @VisibleForTesting - def buildLibrary( - tvl: TombstoneVisibilityLibrary, - libraryStatsReceiver: StatsReceiver - ): AdAvoidanceLibrary.Type = { - - val statsReceiver = libraryStatsReceiver.scope("AdAvoidanceLibrary") - val reasonsStatsReceiver = statsReceiver.scope("reasons") - val latencyStatsReceiver = statsReceiver.scope("latency") - val vfLatencyOverallStat = latencyStatsReceiver.stat("vf_latency_overall") - val vfLatencyStitchBuildStat = latencyStatsReceiver.stat("vf_latency_stitch_build") - val vfLatencyStitchRunStat = latencyStatsReceiver.stat("vf_latency_stitch_run") - - request: AdAvoidanceRequest => { - val elapsed = Stopwatch.start() - - var runStitchStartMs = 0L - - val tombstoneResponse: Stitch[TombstoneVisibilityResponse] = - runTombstoneVisLib(request, tvl) - - val response = tombstoneResponse - .map({ response: TombstoneVisibilityResponse => - statsReceiver.counter("requests").incr(request.tweets.size) - - val dropResults: Seq[(Long, Boolean)] = request.tweets.map(tweetAndSafetyLevel => { - val tweet = tweetAndSafetyLevel._1 - tweet.tweetId -> - shouldAvoid( - tweet.tweetResult, - response.tweetVerdicts.get(tweet.tweetId), - reasonsStatsReceiver) - }) - - AdAvoidanceResponse(dropAd = dropResults.toMap) - }) - .onSuccess(_ => { - val overallStatMs = elapsed().inMilliseconds - vfLatencyOverallStat.add(overallStatMs) - val runStitchEndMs = elapsed().inMilliseconds - vfLatencyStitchRunStat.add(runStitchEndMs - runStitchStartMs) - }) - - runStitchStartMs = elapsed().inMilliseconds - val buildStitchStatMs = elapsed().inMilliseconds - vfLatencyStitchBuildStat.add(buildStitchStatMs) - - response - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/conversations/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/conversations/BUILD deleted file mode 100644 index eae843def..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/conversations/BUILD +++ /dev/null @@ -1,46 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/google/guava", - "3rdparty/jvm/com/ibm/icu:icu4j", - "decider/src/main/scala", - "servo/decider/src/main/scala", - "servo/repo", - "src/thrift/com/twitter/context:twitter-context-scala", - "src/thrift/com/twitter/gizmoduck:thrift-scala", - "src/thrift/com/twitter/spam/rtf:safety-level-scala", - "src/thrift/com/twitter/spam/rtf:tweet-rtf-event-scala", - "src/thrift/com/twitter/timelines/render:thrift-scala", - "src/thrift/com/twitter/tweetypie:service-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "stitch/stitch-core", - "translation/src/main/scala", - "twitter-config/yaml", - "twitter-context/src/main/scala", - "urt/richtext/src/main/scala/com/twitter/urt/richtext", - "visibility/common/src/main/scala/com/twitter/visibility/common", - "visibility/common/src/main/scala/com/twitter/visibility/common/actions", - "visibility/common/src/main/scala/com/twitter/visibility/common/filtered_reason", - "visibility/common/src/main/thrift/com/twitter/visibility:action-scala", - "visibility/lib/src/main/resources/config", - "visibility/lib/src/main/scala/com/twitter/visibility", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/tweets", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/users", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/configs", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/params", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/interfaces/common/tweets", - "visibility/lib/src/main/thrift/com/twitter/visibility/logging:vf-logging-scala", - "visibility/results/src/main/scala/com/twitter/visibility/results/richtext", - "visibility/results/src/main/scala/com/twitter/visibility/results/translation", - "visibility/results/src/main/scala/com/twitter/visibility/results/urt", - ], - exports = [ - "visibility/common/src/main/thrift/com/twitter/visibility:action-scala", - "visibility/lib/src/main/scala/com/twitter/visibility", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/conversations/TimelineConversationsVisibilityLibrary.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/conversations/TimelineConversationsVisibilityLibrary.scala deleted file mode 100644 index cefe6d762..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/conversations/TimelineConversationsVisibilityLibrary.scala +++ /dev/null @@ -1,260 +0,0 @@ -package com.twitter.visibility.interfaces.conversations - -import com.twitter.decider.Decider -import com.twitter.finagle.stats.NullStatsReceiver -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.gizmoduck.thriftscala.Label -import com.twitter.servo.repository.KeyValueResult -import com.twitter.servo.util.Gate -import com.twitter.spam.rtf.thriftscala.SafetyLabel -import com.twitter.spam.rtf.thriftscala.SafetyLabelType -import com.twitter.spam.rtf.thriftscala.SafetyLabelValue -import com.twitter.stitch.Stitch -import com.twitter.util.Future -import com.twitter.util.Return -import com.twitter.util.Stopwatch -import com.twitter.util.Try -import com.twitter.visibility.VisibilityLibrary -import com.twitter.visibility.builder.tweets.TweetIdFeatures -import com.twitter.visibility.builder.FeatureMapBuilder -import com.twitter.visibility.builder.VerdictLogger -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.builder.tweets.FosnrPefetchedLabelsRelationshipFeatures -import com.twitter.visibility.builder.users.AuthorFeatures -import com.twitter.visibility.common.UserRelationshipSource -import com.twitter.visibility.common.UserSource -import com.twitter.visibility.configapi.configs.VisibilityDeciderGates -import com.twitter.visibility.features.AuthorUserLabels -import com.twitter.visibility.features.ConversationRootAuthorIsVerified -import com.twitter.visibility.features.FeatureMap -import com.twitter.visibility.features.HasInnerCircleOfFriendsRelationship -import com.twitter.visibility.features.TweetConversationId -import com.twitter.visibility.features.TweetParentId -import com.twitter.visibility.logging.thriftscala.VFLibType -import com.twitter.visibility.models.ContentId.TweetId -import com.twitter.visibility.models.SafetyLevel.TimelineConversationsDownranking -import com.twitter.visibility.models.SafetyLevel.TimelineConversationsDownrankingMinimal -import com.twitter.visibility.models.SafetyLevel.toThrift -import com.twitter.visibility.models.ContentId -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.TweetSafetyLabel -import com.twitter.visibility.models.UnitOfDiversion - -object TimelineConversationsVisibilityLibrary { - type Type = - TimelineConversationsVisibilityRequest => Stitch[TimelineConversationsVisibilityResponse] - - def apply( - visibilityLibrary: VisibilityLibrary, - batchSafetyLabelRepository: BatchSafetyLabelRepository, - decider: Decider, - userRelationshipSource: UserRelationshipSource = UserRelationshipSource.empty, - userSource: UserSource = UserSource.empty - ): Type = { - val libraryStatsReceiver = visibilityLibrary.statsReceiver - val tweetIdFeatures = new TweetIdFeatures( - statsReceiver = libraryStatsReceiver, - enableStitchProfiling = Gate.False - ) - val tweetIdFeaturesMinimal = new TweetIdFeatures( - statsReceiver = libraryStatsReceiver, - enableStitchProfiling = Gate.False - ) - val vfLatencyOverallStat = libraryStatsReceiver.stat("vf_latency_overall") - val vfLatencyStitchBuildStat = libraryStatsReceiver.stat("vf_latency_stitch_build") - val vfLatencyStitchRunStat = libraryStatsReceiver.stat("vf_latency_stitch_run") - - val visibilityDeciderGates = VisibilityDeciderGates(decider) - val verdictLogger = - createVerdictLogger( - visibilityDeciderGates.enableVerdictLoggerTCVL, - decider, - libraryStatsReceiver) - - request: TimelineConversationsVisibilityRequest => - val elapsed = Stopwatch.start() - var runStitchStartMs = 0L - - val future = request.prefetchedSafetyLabels match { - case Some(labels) => Future.value(labels) - case _ => - batchSafetyLabelRepository((request.conversationId, request.tweetIds)) - } - - val fosnrPefetchedLabelsRelationshipFeatures = - new FosnrPefetchedLabelsRelationshipFeatures( - userRelationshipSource = userRelationshipSource, - statsReceiver = libraryStatsReceiver) - - val authorFeatures = new AuthorFeatures(userSource, libraryStatsReceiver) - - Stitch.callFuture(future).flatMap { - kvr: KeyValueResult[Long, scala.collection.Map[SafetyLabelType, SafetyLabel]] => - val featureMapProvider: (ContentId, SafetyLevel) => FeatureMap = { - case (TweetId(tweetId), safetyLevel) => - val constantTweetSafetyLabels: Seq[TweetSafetyLabel] = - kvr.found.getOrElse(tweetId, Map.empty).toSeq.map { - case (safetyLabelType, safetyLabel) => - TweetSafetyLabel.fromThrift(SafetyLabelValue(safetyLabelType, safetyLabel)) - } - - val replyAuthor = request.tweetAuthors.flatMap { - _(tweetId) match { - case Return(Some(userId)) => Some(userId) - case _ => None - } - } - - val fosnrPefetchedLabelsRelationshipFeatureConf = replyAuthor match { - case Some(authorId) if visibilityLibrary.isReleaseCandidateEnabled => - fosnrPefetchedLabelsRelationshipFeatures - .forTweetWithSafetyLabelsAndAuthorId( - safetyLabels = constantTweetSafetyLabels, - authorId = authorId, - viewerId = request.viewerContext.userId) - case _ => fosnrPefetchedLabelsRelationshipFeatures.forNonFosnr() - } - - val authorFeatureConf = replyAuthor match { - case Some(authorId) if visibilityLibrary.isReleaseCandidateEnabled => - authorFeatures.forAuthorId(authorId) - case _ => authorFeatures.forNoAuthor() - } - - val baseBuilderArguments = (safetyLevel match { - case TimelineConversationsDownranking => - Seq(tweetIdFeatures.forTweetId(tweetId, constantTweetSafetyLabels)) - case TimelineConversationsDownrankingMinimal => - Seq(tweetIdFeaturesMinimal.forTweetId(tweetId, constantTweetSafetyLabels)) - case _ => Nil - }) :+ fosnrPefetchedLabelsRelationshipFeatureConf :+ authorFeatureConf - - val tweetAuthorUserLabels: Option[Seq[Label]] = - request.prefetchedTweetAuthorUserLabels.flatMap { - _.apply(tweetId) match { - case Return(Some(labelMap)) => - Some(labelMap.values.toSeq) - case _ => - None - } - } - - val hasInnerCircleOfFriendsRelationship: Boolean = - request.innerCircleOfFriendsRelationships match { - case Some(keyValueResult) => - keyValueResult(tweetId) match { - case Return(Some(true)) => true - case _ => false - } - case None => false - } - - val builderArguments: Seq[FeatureMapBuilder => FeatureMapBuilder] = - tweetAuthorUserLabels match { - case Some(labels) => - baseBuilderArguments :+ { (fmb: FeatureMapBuilder) => - fmb.withConstantFeature(AuthorUserLabels, labels) - } - - case None => - baseBuilderArguments :+ { (fmb: FeatureMapBuilder) => - fmb.withConstantFeature(AuthorUserLabels, Seq.empty) - } - case _ => - baseBuilderArguments - } - - val tweetParentIdOpt: Option[Long] = - request.tweetParentIdMap.flatMap(tweetParentIdMap => tweetParentIdMap(tweetId)) - - visibilityLibrary.featureMapBuilder(builderArguments :+ { (fmb: FeatureMapBuilder) => - fmb.withConstantFeature( - HasInnerCircleOfFriendsRelationship, - hasInnerCircleOfFriendsRelationship) - fmb.withConstantFeature(TweetConversationId, request.conversationId) - fmb.withConstantFeature(TweetParentId, tweetParentIdOpt) - fmb.withConstantFeature( - ConversationRootAuthorIsVerified, - request.rootAuthorIsVerified) - }) - case _ => - visibilityLibrary.featureMapBuilder(Nil) - } - val safetyLevel = - if (request.minimalSectioningOnly) TimelineConversationsDownrankingMinimal - else TimelineConversationsDownranking - - val evaluationContextBuilder = visibilityLibrary - .evaluationContextBuilder(request.viewerContext) - .withUnitOfDiversion(UnitOfDiversion.ConversationId(request.conversationId)) - - visibilityLibrary - .runRuleEngineBatch( - request.tweetIds.map(TweetId), - featureMapProvider, - evaluationContextBuilder, - safetyLevel - ) - .map { results: Seq[Try[VisibilityResult]] => - val (succeededRequests, _) = results.partition(_.exists(_.finished)) - val visibilityResultMap = succeededRequests.flatMap { - case Return(result) => - scribeVisibilityVerdict( - result, - visibilityDeciderGates.enableVerdictScribingTCVL, - verdictLogger, - request.viewerContext.userId, - safetyLevel) - result.contentId match { - case TweetId(id) => Some((id, result)) - case _ => None - } - case _ => None - }.toMap - val failedTweetIds = request.tweetIds diff visibilityResultMap.keys.toSeq - val response = TimelineConversationsVisibilityResponse( - visibilityResults = visibilityResultMap, - failedTweetIds = failedTweetIds - ) - - runStitchStartMs = elapsed().inMilliseconds - val buildStitchStatMs = elapsed().inMilliseconds - vfLatencyStitchBuildStat.add(buildStitchStatMs) - - response - } - .onSuccess(_ => { - val overallStatMs = elapsed().inMilliseconds - vfLatencyOverallStat.add(overallStatMs) - val runStitchEndMs = elapsed().inMilliseconds - vfLatencyStitchRunStat.add(runStitchEndMs - runStitchStartMs) - }) - } - } - - def scribeVisibilityVerdict( - visibilityResult: VisibilityResult, - enableVerdictScribing: Gate[Unit], - verdictLogger: VerdictLogger, - viewerId: Option[Long], - safetyLevel: SafetyLevel - ): Unit = if (enableVerdictScribing()) { - verdictLogger.scribeVerdict( - visibilityResult = visibilityResult, - viewerId = viewerId, - safetyLevel = toThrift(safetyLevel), - vfLibType = VFLibType.TimelineConversationsVisibilityLibrary) - } - - def createVerdictLogger( - enableVerdictLogger: Gate[Unit], - decider: Decider, - statsReceiver: StatsReceiver - ): VerdictLogger = { - if (enableVerdictLogger()) { - VerdictLogger(statsReceiver, decider) - } else { - VerdictLogger.Empty - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/conversations/TimelineConversationsVisibilityRequest.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/conversations/TimelineConversationsVisibilityRequest.scala deleted file mode 100644 index 217296f8b..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/conversations/TimelineConversationsVisibilityRequest.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.visibility.interfaces.conversations - -import com.twitter.gizmoduck.thriftscala.Label -import com.twitter.gizmoduck.thriftscala.LabelValue -import com.twitter.servo.repository.KeyValueResult -import com.twitter.spam.rtf.thriftscala.SafetyLabel -import com.twitter.spam.rtf.thriftscala.SafetyLabelType -import com.twitter.visibility.models.ViewerContext - -case class TimelineConversationsVisibilityRequest( - conversationId: Long, - tweetIds: Seq[Long], - viewerContext: ViewerContext, - minimalSectioningOnly: Boolean = false, - prefetchedSafetyLabels: Option[KeyValueResult[Long, Map[SafetyLabelType, SafetyLabel]]] = None, - prefetchedTweetAuthorUserLabels: Option[KeyValueResult[Long, Map[LabelValue, Label]]] = None, - innerCircleOfFriendsRelationships: Option[KeyValueResult[Long, Boolean]] = None, - tweetParentIdMap: Option[Map[Long, Option[Long]]] = None, - rootAuthorIsVerified: Boolean = false, - tweetAuthors: Option[KeyValueResult[Long, Long]] = None) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/conversations/TimelineConversationsVisibilityResponse.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/conversations/TimelineConversationsVisibilityResponse.scala deleted file mode 100644 index f086c792c..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/conversations/TimelineConversationsVisibilityResponse.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.visibility.interfaces.conversations - -import com.twitter.visibility.builder.VisibilityResult - -case class TimelineConversationsVisibilityResponse( - visibilityResults: Map[Long, VisibilityResult], - failedTweetIds: Seq[Long]) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/conversations/Tombstone.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/conversations/Tombstone.scala deleted file mode 100644 index 1d3274ed2..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/conversations/Tombstone.scala +++ /dev/null @@ -1,35 +0,0 @@ -package com.twitter.visibility.interfaces.conversations - -import com.twitter.timelines.render.thriftscala.TombstoneDisplayType -import com.twitter.timelines.render.thriftscala.TombstoneInfo -import com.twitter.visibility.rules._ - -case class VfTombstone( - tombstoneId: Long, - includeTweet: Boolean, - action: Action, - tombstoneInfo: Option[TombstoneInfo] = None, - tombstoneDisplayType: TombstoneDisplayType = TombstoneDisplayType.Inline, - truncateDescendantsWhenFocal: Boolean = false) { - - val isTruncatable: Boolean = action match { - case Interstitial(Reason.ViewerBlocksAuthor, _, _) => true - case Interstitial(Reason.ViewerHardMutedAuthor, _, _) => true - case Interstitial(Reason.MutedKeyword, _, _) => true - case Tombstone(Epitaph.NotFound, _) => true - case Tombstone(Epitaph.Unavailable, _) => true - case Tombstone(Epitaph.Suspended, _) => true - case Tombstone(Epitaph.Protected, _) => true - case Tombstone(Epitaph.Deactivated, _) => true - case Tombstone(Epitaph.BlockedBy, _) => true - case Tombstone(Epitaph.Moderated, _) => true - case Tombstone(Epitaph.Deleted, _) => true - case Tombstone(Epitaph.Underage, _) => true - case Tombstone(Epitaph.NoStatedAge, _) => true - case Tombstone(Epitaph.LoggedOutAge, _) => true - case Tombstone(Epitaph.SuperFollowsContent, _) => true - case Tombstone(Epitaph.CommunityTweetHidden, _) => true - case _: LocalizedTombstone => true - case _ => false - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/conversations/TombstoneVisibilityLibrary.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/conversations/TombstoneVisibilityLibrary.scala deleted file mode 100644 index 3f228670d..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/conversations/TombstoneVisibilityLibrary.scala +++ /dev/null @@ -1,633 +0,0 @@ -package com.twitter.visibility.interfaces.conversations - -import com.twitter.decider.Decider -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.gizmoduck.thriftscala.User -import com.twitter.spam.rtf.thriftscala.FilteredReason -import com.twitter.spam.rtf.thriftscala.FilteredReason.UnspecifiedReason -import com.twitter.spam.rtf.thriftscala.SafetyLevel -import com.twitter.spam.rtf.thriftscala.SafetyResult -import com.twitter.stitch.Stitch -import com.twitter.timelines.render.thriftscala.RichText -import com.twitter.timelines.render.thriftscala.TombstoneDisplayType -import com.twitter.timelines.render.thriftscala.TombstoneInfo -import com.twitter.tweetypie.thriftscala.GetTweetFieldsResult -import com.twitter.tweetypie.thriftscala.TweetFieldsResultFailed -import com.twitter.tweetypie.thriftscala.TweetFieldsResultFiltered -import com.twitter.tweetypie.thriftscala.TweetFieldsResultFound -import com.twitter.tweetypie.thriftscala.TweetFieldsResultNotFound -import com.twitter.tweetypie.thriftscala.TweetFieldsResultState -import com.twitter.visibility.VisibilityLibrary -import com.twitter.visibility.builder.tweets.ModerationFeatures -import com.twitter.visibility.builder.users.AuthorFeatures -import com.twitter.visibility.builder.users.RelationshipFeatures -import com.twitter.visibility.builder.users.ViewerFeatures -import com.twitter.visibility.common.UserRelationshipSource -import com.twitter.visibility.common.UserSource -import com.twitter.visibility.common.actions.InterstitialReason -import com.twitter.visibility.common.actions.LimitedEngagementReason -import com.twitter.visibility.common.actions.TombstoneReason -import com.twitter.visibility.common.actions.converter.scala.InterstitialReasonConverter -import com.twitter.visibility.common.actions.converter.scala.LocalizedMessageConverter -import com.twitter.visibility.common.actions.converter.scala.TombstoneReasonConverter -import com.twitter.visibility.common.filtered_reason.FilteredReasonHelper -import com.twitter.visibility.configapi.configs.VisibilityDeciderGates -import com.twitter.visibility.features.FocalTweetId -import com.twitter.visibility.features.TweetId -import com.twitter.visibility.models.ContentId -import com.twitter.visibility.models.SafetyLevel.Tombstoning -import com.twitter.visibility.models.ViewerContext -import com.twitter.visibility.results.richtext.EpitaphToRichText -import com.twitter.visibility.results.richtext.LocalizedMessageToRichText -import com.twitter.visibility.results.urt.ReasonToUrtParser -import com.twitter.visibility.results.urt.SafetyResultToUrtParser -import com.twitter.visibility.rules._ -import com.twitter.visibility.{thriftscala => t} - -case class TombstoneVisibilityRequest( - conversationId: Long, - focalTweetId: Long, - tweets: Seq[(GetTweetFieldsResult, Option[SafetyLevel])], - authorMap: Map[ - Long, - User - ], - moderatedTweetIds: Seq[Long], - viewerContext: ViewerContext, - useRichText: Boolean = true) - -case class TombstoneVisibilityResponse(tweetVerdicts: Map[Long, VfTombstone]) - -case class TombstoneVisibilityLibrary( - visibilityLibrary: VisibilityLibrary, - statsReceiver: StatsReceiver, - decider: Decider) { - - private case class TombstoneType( - tweetId: Long, - tombstoneId: Long, - action: Action) { - - lazy val isInnerTombstone: Boolean = tweetId != tombstoneId - - lazy val tombstoneDisplayType: TombstoneDisplayType = action match { - case _: InterstitialLimitedEngagements | _: EmergencyDynamicInterstitial => - TombstoneDisplayType.NonCompliant - case _ => TombstoneDisplayType.Inline - } - } - - val En: String = "en" - val View: String = "View" - val relationshipFeatures = - new RelationshipFeatures( - statsReceiver) - val visibilityDeciderGates = VisibilityDeciderGates(decider) - - - def toAction( - filteredReason: FilteredReason, - actionStatsReceiver: StatsReceiver - ): Option[Action] = { - - val enableLocalizedInterstitials = - visibilityDeciderGates.enableConvosLocalizedInterstitial() - val enableLegacyInterstitials = - visibilityDeciderGates.enableConvosLegacyInterstitial() - - val tombstoneStatsReceiver = actionStatsReceiver.scope("tombstone") - val interstitialLocalStatsReceiver = - actionStatsReceiver.scope("interstitial").scope("localized") - val interstitialLegacyStatsReceiver = - actionStatsReceiver.scope("interstitial").scope("legacy") - - filteredReason match { - case _ if FilteredReasonHelper.isTombstone(filteredReason) => - createLocalizedTombstone(filteredReason, tombstoneStatsReceiver) match { - case tombstoneOpt @ Some(LocalizedTombstone(_, _)) => tombstoneOpt - case _ => - createTombstone(Epitaph.Unavailable, tombstoneStatsReceiver, Some("emptyTombstone")) - } - - case _ - if enableLocalizedInterstitials && - FilteredReasonHelper.isLocalizedSuppressedReasonInterstitial(filteredReason) => - FilteredReasonHelper.getLocalizedSuppressedReasonInterstitial(filteredReason) match { - case Some(t.Interstitial(reasonOpt, Some(message))) => - InterstitialReasonConverter.fromThrift(reasonOpt).map { interstitialReason => - interstitialLocalStatsReceiver.counter("interstitial").incr() - Interstitial( - Reason.fromInterstitialReason(interstitialReason), - Some(LocalizedMessageConverter.fromThrift(message))) - } - - case _ => None - } - - case _ if FilteredReasonHelper.containNsfwMedia(filteredReason) => - None - - case _ if FilteredReasonHelper.possiblyUndesirable(filteredReason) => - None - - case _ if FilteredReasonHelper.reportedTweet(filteredReason) => - filteredReason match { - case FilteredReason.ReportedTweet(true) => - interstitialLegacyStatsReceiver.counter("fr_reported").incr() - Some(Interstitial(Reason.ViewerReportedAuthor)) - - case FilteredReason.SafetyResult(safetyResult: SafetyResult) - if enableLegacyInterstitials => - val safetyResultReported = InterstitialReasonConverter - .fromAction(safetyResult.action).collect { - case InterstitialReason.ViewerReportedTweet => true - case InterstitialReason.ViewerReportedAuthor => true - }.getOrElse(false) - - if (safetyResultReported) { - interstitialLegacyStatsReceiver.counter("reported_author").incr() - Some(Interstitial(Reason.ViewerReportedAuthor)) - } else None - - case _ => None - } - - case _ if FilteredReasonHelper.tweetMatchesViewerMutedKeyword(filteredReason) => - filteredReason match { - case FilteredReason.TweetMatchesViewerMutedKeyword(_) => - interstitialLegacyStatsReceiver.counter("fr_muted_keyword").incr() - Some(Interstitial(Reason.MutedKeyword)) - - case FilteredReason.SafetyResult(safetyResult: SafetyResult) - if enableLegacyInterstitials => - val safetyResultMutedKeyword = InterstitialReasonConverter - .fromAction(safetyResult.action).collect { - case _: InterstitialReason.MatchesMutedKeyword => true - }.getOrElse(false) - - if (safetyResultMutedKeyword) { - interstitialLegacyStatsReceiver.counter("muted_keyword").incr() - Some(Interstitial(Reason.MutedKeyword)) - } else None - - case _ => None - } - - case _ => - None - } - } - - def toAction( - tfrs: TweetFieldsResultState, - actionStatsReceiver: StatsReceiver - ): Option[Action] = { - - val enableLocalizedInterstitials = visibilityDeciderGates.enableConvosLocalizedInterstitial() - val enableLegacyInterstitials = visibilityDeciderGates.enableConvosLegacyInterstitial() - - val tombstoneStatsReceiver = actionStatsReceiver.scope("tombstone") - val interstitialLocalStatsReceiver = - actionStatsReceiver.scope("interstitial").scope("localized") - val interstitialLegacyStatsReceiver = - actionStatsReceiver.scope("interstitial").scope("legacy") - - tfrs match { - - case TweetFieldsResultState.NotFound(TweetFieldsResultNotFound(_, _, Some(filteredReason))) - if FilteredReasonHelper.isTombstone(filteredReason) => - createLocalizedTombstone(filteredReason, tombstoneStatsReceiver) - - case TweetFieldsResultState.NotFound(tfr: TweetFieldsResultNotFound) if tfr.deleted => - createTombstone(Epitaph.Deleted, tombstoneStatsReceiver) - - case TweetFieldsResultState.NotFound(_: TweetFieldsResultNotFound) => - createTombstone(Epitaph.NotFound, tombstoneStatsReceiver) - - case TweetFieldsResultState.Failed(TweetFieldsResultFailed(_, _, _)) => - createTombstone(Epitaph.Unavailable, tombstoneStatsReceiver, Some("failed")) - - case TweetFieldsResultState.Filtered(TweetFieldsResultFiltered(UnspecifiedReason(true))) => - createTombstone(Epitaph.Unavailable, tombstoneStatsReceiver, Some("filtered")) - - case TweetFieldsResultState.Filtered(TweetFieldsResultFiltered(filteredReason)) => - toAction(filteredReason, actionStatsReceiver) - - case TweetFieldsResultState.Found(TweetFieldsResultFound(_, _, Some(filteredReason))) - if enableLocalizedInterstitials && - FilteredReasonHelper.isSuppressedReasonPublicInterestInterstial(filteredReason) => - interstitialLocalStatsReceiver.counter("ipi").incr() - FilteredReasonHelper - .getSafetyResult(filteredReason) - .flatMap(_.reason) - .flatMap(PublicInterest.SafetyResultReasonToReason.get) match { - case Some(safetyResultReason) => - FilteredReasonHelper - .getSuppressedReasonPublicInterestInterstial(filteredReason) - .map(edi => edi.localizedMessage) - .map(tlm => LocalizedMessageConverter.fromThrift(tlm)) - .map(lm => - InterstitialLimitedEngagements( - safetyResultReason, - Some(LimitedEngagementReason.NonCompliant), - lm)) - case _ => None - } - - case TweetFieldsResultState.Found(TweetFieldsResultFound(_, _, Some(filteredReason))) - if enableLegacyInterstitials && - FilteredReasonHelper.isSuppressedReasonPublicInterestInterstial(filteredReason) => - interstitialLegacyStatsReceiver.counter("ipi").incr() - FilteredReasonHelper - .getSafetyResult(filteredReason) - .flatMap(_.reason) - .flatMap(PublicInterest.SafetyResultReasonToReason.get) - .map(InterstitialLimitedEngagements(_, Some(LimitedEngagementReason.NonCompliant))) - - case TweetFieldsResultState.Found(TweetFieldsResultFound(_, _, Some(filteredReason))) - if enableLocalizedInterstitials && - FilteredReasonHelper.isLocalizedSuppressedReasonEmergencyDynamicInterstitial( - filteredReason) => - interstitialLocalStatsReceiver.counter("edi").incr() - FilteredReasonHelper - .getSuppressedReasonEmergencyDynamicInterstitial(filteredReason) - .map(e => - EmergencyDynamicInterstitial( - e.copy, - e.link, - LocalizedMessageConverter.fromThrift(e.localizedMessage))) - - case TweetFieldsResultState.Found(TweetFieldsResultFound(_, _, Some(filteredReason))) - if enableLegacyInterstitials && - FilteredReasonHelper.isSuppressedReasonEmergencyDynamicInterstitial(filteredReason) => - interstitialLegacyStatsReceiver.counter("edi").incr() - FilteredReasonHelper - .getSuppressedReasonEmergencyDynamicInterstitial(filteredReason) - .map(e => EmergencyDynamicInterstitial(e.copy, e.link)) - - case TweetFieldsResultState.Found(TweetFieldsResultFound(tweet, _, _)) - if tweet.perspective.exists(_.reported) => - interstitialLegacyStatsReceiver.counter("reported").incr() - Some(Interstitial(Reason.ViewerReportedAuthor)) - - case TweetFieldsResultState.Found( - TweetFieldsResultFound(_, _, Some(UnspecifiedReason(true)))) => - None - - case TweetFieldsResultState.Found(TweetFieldsResultFound(_, _, Some(filteredReason))) => - toAction(filteredReason, actionStatsReceiver) - - case _ => - None - } - } - - private[conversations] def shouldTruncateDescendantsWhenFocal(action: Action): Boolean = - action match { - case _: InterstitialLimitedEngagements | _: EmergencyDynamicInterstitial => - true - case Tombstone(Epitaph.Bounced, _) | Tombstone(Epitaph.BounceDeleted, _) => - true - case LocalizedTombstone(TombstoneReason.Bounced, _) | - LocalizedTombstone(TombstoneReason.BounceDeleted, _) => - true - case LimitedEngagements(LimitedEngagementReason.NonCompliant, _) => - true - case _ => false - } - - def apply(request: TombstoneVisibilityRequest): Stitch[TombstoneVisibilityResponse] = { - - val moderationFeatures = new ModerationFeatures( - moderationSource = request.moderatedTweetIds.contains, - statsReceiver = statsReceiver - ) - - val userSource = UserSource.fromFunction({ - case (userId, _) => - request.authorMap - .get(userId) - .map(Stitch.value).getOrElse(Stitch.NotFound) - }) - - val authorFeatures = new AuthorFeatures(userSource, statsReceiver) - val viewerFeatures = new ViewerFeatures(userSource, statsReceiver) - - val languageTag = request.viewerContext.requestCountryCode.getOrElse(En) - val firstRound: Seq[(GetTweetFieldsResult, Option[TombstoneType])] = request.tweets.map { - case (gtfr, safetyLevel) => - val actionStats = statsReceiver - .scope("action") - .scope(safetyLevel.map(_.toString().toLowerCase()).getOrElse("unknown_safety_level")) - toAction(gtfr.tweetResult, actionStats) match { - case Some(action) => - (gtfr, Some(TombstoneType(gtfr.tweetId, gtfr.tweetId, action))) - - case None => - val quotedTweetId: Option[Long] = gtfr.tweetResult match { - case TweetFieldsResultState.Found(TweetFieldsResultFound(tweet, _, _)) => - tweet.quotedTweet.map(_.tweetId) - case _ => None - } - - (quotedTweetId, gtfr.quotedTweetResult) match { - case (Some(quotedTweetId), Some(tfrs)) => - val qtActionStats = actionStats.scope("quoted") - toAction(tfrs, qtActionStats) match { - case None => - (gtfr, None) - - case Some(action) => - (gtfr, Some(TombstoneType(gtfr.tweetId, quotedTweetId, action))) - } - - case _ => - (gtfr, None) - } - } - } - - val (firstRoundActions, secondRoundInput) = firstRound.partition { - case (_, Some(tombstoneType)) => - !tombstoneType.isInnerTombstone - case (_, None) => false - } - - def invokeVisibilityLibrary(tweetId: Long, author: User): Stitch[Action] = { - visibilityLibrary - .runRuleEngine( - ContentId.TweetId(tweetId), - visibilityLibrary.featureMapBuilder( - Seq( - viewerFeatures.forViewerContext(request.viewerContext), - moderationFeatures.forTweetId(tweetId), - authorFeatures.forAuthor(author), - relationshipFeatures - .forAuthor(author, request.viewerContext.userId), - _.withConstantFeature(TweetId, tweetId), - _.withConstantFeature(FocalTweetId, request.focalTweetId) - ) - ), - request.viewerContext, - Tombstoning - ).map(_.verdict) - } - - val secondRoundActions: Stitch[Seq[(GetTweetFieldsResult, Option[TombstoneType])]] = - Stitch.traverse(secondRoundInput) { - case (gtfr: GetTweetFieldsResult, firstRoundTombstone: Option[TombstoneType]) => - val secondRoundTombstone: Stitch[Option[TombstoneType]] = gtfr.tweetResult match { - case TweetFieldsResultState.Found(TweetFieldsResultFound(tweet, _, _)) => - val tweetId = tweet.id - - tweet.coreData - .flatMap { coreData => request.authorMap.get(coreData.userId) } match { - case Some(author) => - invokeVisibilityLibrary(tweetId, author).flatMap { - case Allow => - val quotedTweetId = tweet.quotedTweet.map(_.tweetId) - val quotedTweetAuthor = tweet.quotedTweet.flatMap { qt => - request.authorMap.get(qt.userId) - } - - (quotedTweetId, quotedTweetAuthor) match { - case (Some(quotedTweetId), Some(quotedTweetAuthor)) => - invokeVisibilityLibrary(quotedTweetId, quotedTweetAuthor).flatMap { - case Allow => - Stitch.None - - case reason => - Stitch.value(Some(TombstoneType(tweetId, quotedTweetId, reason))) - } - - case _ => - Stitch.None - } - - case reason => - Stitch.value(Some(TombstoneType(tweetId, tweetId, reason))) - } - - case None => - Stitch.None - } - - case _ => - Stitch.None - } - - secondRoundTombstone.map { opt => opt.orElse(firstRoundTombstone) }.map { opt => - (gtfr, opt) - } - } - - secondRoundActions.map { secondRound => - val tombstones: Seq[(Long, VfTombstone)] = (firstRoundActions ++ secondRound).flatMap { - case (gtfr, tombstoneTypeOpt) => { - - val nonCompliantLimitedEngagementsOpt = gtfr.tweetResult match { - case TweetFieldsResultState.Found(TweetFieldsResultFound(_, _, Some(filteredReason))) - if FilteredReasonHelper.isLimitedEngagementsNonCompliant(filteredReason) => - Some(LimitedEngagements(LimitedEngagementReason.NonCompliant)) - case _ => None - } - - (tombstoneTypeOpt, nonCompliantLimitedEngagementsOpt) match { - case (Some(tombstoneType), nonCompliantOpt) => - val tombstoneId = tombstoneType.tombstoneId - val action = tombstoneType.action - val textOpt: Option[RichText] = action match { - - case InterstitialLimitedEngagements(_, _, Some(localizedMessage), _) => - Some(LocalizedMessageToRichText(localizedMessage)) - case ipi: InterstitialLimitedEngagements => - Some( - SafetyResultToUrtParser.fromSafetyResultToRichText( - SafetyResult( - Some(PublicInterest.ReasonToSafetyResultReason(ipi.reason)), - ipi.toActionThrift() - ), - languageTag - ) - ) - - case EmergencyDynamicInterstitial(_, _, Some(localizedMessage), _) => - Some(LocalizedMessageToRichText(localizedMessage)) - case edi: EmergencyDynamicInterstitial => - Some( - SafetyResultToUrtParser.fromSafetyResultToRichText( - SafetyResult( - None, - edi.toActionThrift() - ), - languageTag - ) - ) - - case Tombstone(epitaph, _) => - if (request.useRichText) - Some(EpitaphToRichText(epitaph, languageTag)) - else - Some(EpitaphToRichText(Epitaph.UnavailableWithoutLink, languageTag)) - - case LocalizedTombstone(_, message) => - if (request.useRichText) - Some(LocalizedMessageToRichText(LocalizedMessageConverter.toThrift(message))) - else - Some(EpitaphToRichText(Epitaph.UnavailableWithoutLink, languageTag)) - - case Interstitial(_, Some(localizedMessage), _) => - Some(LocalizedMessageToRichText.apply(localizedMessage)) - - case interstitial: Interstitial => - ReasonToUrtParser.fromReasonToRichText(interstitial.reason, languageTag) - - case _ => - None - } - - val isRoot: Boolean = gtfr.tweetId == request.conversationId - val isOuter: Boolean = tombstoneId == request.conversationId - val revealTextOpt: Option[RichText] = action match { - case _: InterstitialLimitedEngagements | _: EmergencyDynamicInterstitial - if isRoot && isOuter => - None - - case _: Interstitial | _: InterstitialLimitedEngagements | - _: EmergencyDynamicInterstitial => - Some(ReasonToUrtParser.getRichRevealText(languageTag)) - - case _ => - None - } - - val includeTweet = action match { - case _: Interstitial | _: InterstitialLimitedEngagements | - _: EmergencyDynamicInterstitial => - true - case _ => false - } - - val truncateForAction: Boolean = - shouldTruncateDescendantsWhenFocal(action) - val truncateForNonCompliant: Boolean = - nonCompliantOpt - .map(shouldTruncateDescendantsWhenFocal).getOrElse(false) - val truncateDescendants: Boolean = - truncateForAction || truncateForNonCompliant - - val tombstone = textOpt match { - case Some(_) if request.useRichText => - VfTombstone( - includeTweet = includeTweet, - action = action, - tombstoneInfo = Some( - TombstoneInfo( - cta = None, - revealText = None, - richText = textOpt, - richRevealText = revealTextOpt - ) - ), - tombstoneDisplayType = tombstoneType.tombstoneDisplayType, - truncateDescendantsWhenFocal = truncateDescendants - ) - case Some(_) => - VfTombstone( - includeTweet = includeTweet, - action = action, - tombstoneInfo = Some( - TombstoneInfo( - text = textOpt - .map(richText => richText.text).getOrElse( - "" - cta = None, - revealText = revealTextOpt.map(_.text), - richText = None, - richRevealText = None - ) - ), - tombstoneDisplayType = tombstoneType.tombstoneDisplayType, - truncateDescendantsWhenFocal = truncateDescendants - ) - - case None => - VfTombstone( - includeTweet = false, - action = action, - tombstoneInfo = Some( - TombstoneInfo( - cta = None, - revealText = None, - richText = Some(EpitaphToRichText(Epitaph.Unavailable, languageTag)), - richRevealText = None - ) - ), - tombstoneDisplayType = tombstoneType.tombstoneDisplayType, - truncateDescendantsWhenFocal = truncateDescendants - ) - } - - Some((gtfr.tweetId, tombstone)) - - case (None, Some(limitedEngagements)) - if shouldTruncateDescendantsWhenFocal(limitedEngagements) => - val tombstone = VfTombstone( - tombstoneId = gtfr.tweetId, - includeTweet = true, - action = limitedEngagements, - tombstoneInfo = None, - tombstoneDisplayType = TombstoneDisplayType.NonCompliant, - truncateDescendantsWhenFocal = true - ) - Some((gtfr.tweetId, tombstone)) - - case _ => - None - } - } - } - - TombstoneVisibilityResponse( - tweetVerdicts = tombstones.toMap - ) - } - } - - private def createLocalizedTombstone( - filteredReason: FilteredReason, - tombstoneStats: StatsReceiver, - ): Option[LocalizedTombstone] = { - - val tombstoneOpt = FilteredReasonHelper.getTombstone(filteredReason) - tombstoneOpt match { - case Some(t.Tombstone(reasonOpt, Some(message))) => - TombstoneReasonConverter.fromThrift(reasonOpt).map { localReason => - tombstoneStats - .scope("localized").counter(localReason.toString().toLowerCase()).incr() - LocalizedTombstone(localReason, LocalizedMessageConverter.fromThrift(message)) - } - - case _ => None - } - } - - private def createTombstone( - epitaph: Epitaph, - tombstoneStats: StatsReceiver, - extraCounterOpt: Option[String] = None - ): Option[Action] = { - tombstoneStats - .scope("legacy") - .counter(epitaph.toString().toLowerCase()) - .incr() - extraCounterOpt.map { extraCounter => - tombstoneStats - .scope("legacy") - .scope(epitaph.toString().toLowerCase()) - .counter(extraCounter) - .incr() - } - Some(Tombstone(epitaph)) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/conversations/package.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/conversations/package.scala deleted file mode 100644 index 4064fc33b..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/conversations/package.scala +++ /dev/null @@ -1,11 +0,0 @@ -package com.twitter.visibility.interfaces - -import com.twitter.servo.repository.KeyValueRepository -import com.twitter.spam.rtf.thriftscala.SafetyLabel -import com.twitter.spam.rtf.thriftscala.SafetyLabelType -import scala.collection.Map - -package object conversations { - type BatchSafetyLabelRepository = - KeyValueRepository[(Long, Seq[Long]), Long, Map[SafetyLabelType, SafetyLabel]] -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/des/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/des/BUILD deleted file mode 100644 index 2d2dfacf8..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/des/BUILD +++ /dev/null @@ -1,23 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "src/thrift/com/twitter/spam/rtf:tweet-rtf-event-scala", - "src/thrift/com/twitter/tweetypie:events-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "stitch/stitch-core", - "visibility/common/src/main/scala/com/twitter/visibility/common", - "visibility/common/src/main/thrift/com/twitter/visibility:action-scala", - "visibility/lib/src/main/resources/config", - "visibility/lib/src/main/scala/com/twitter/visibility", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/tweets", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/users", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/interfaces/common/tweets", - ], - exports = [ - "visibility/lib/src/main/scala/com/twitter/visibility", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/des/DESRealtimeVisibilityLibrary.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/des/DESRealtimeVisibilityLibrary.scala deleted file mode 100644 index dd6cc68de..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/des/DESRealtimeVisibilityLibrary.scala +++ /dev/null @@ -1,99 +0,0 @@ -package com.twitter.visibility.interfaces.des - -import com.twitter.gizmoduck.thriftscala.User -import com.twitter.stitch.Stitch -import com.twitter.tweetypie.thriftscala.Tweet -import com.twitter.visibility.VisibilityLibrary -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.builder.tweets.CommunityTweetFeaturesV2 -import com.twitter.visibility.builder.tweets.EditTweetFeatures -import com.twitter.visibility.builder.tweets.ExclusiveTweetFeatures -import com.twitter.visibility.builder.tweets.NilTweetLabelMaps -import com.twitter.visibility.builder.tweets.TrustedFriendsFeatures -import com.twitter.visibility.builder.tweets.TweetFeatures -import com.twitter.visibility.builder.users.AuthorFeatures -import com.twitter.visibility.builder.users.ViewerFeatures -import com.twitter.visibility.common.CommunitiesSource -import com.twitter.visibility.common.TrustedFriendsSource -import com.twitter.visibility.common.UserRelationshipSource -import com.twitter.visibility.common.UserSource -import com.twitter.visibility.models.ContentId -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.ViewerContext -import com.twitter.visibility.rules.Allow -import com.twitter.visibility.{thriftscala => vfthrift} - -case class DESRealtimeVisibilityRequest(tweet: Tweet, author: User, viewer: Option[User]) - -object DESRealtimeVisibilityLibrary { - type Type = DESRealtimeVisibilityRequest => Stitch[vfthrift.Action] - - private[this] val safetyLevel = SafetyLevel.DesRealtime - - def apply(visibilityLibrary: VisibilityLibrary): Type = { - val libraryStatsReceiver = visibilityLibrary.statsReceiver - val vfEngineCounter = libraryStatsReceiver.counter("vf_engine_requests") - - val tweetFeatures = new TweetFeatures(NilTweetLabelMaps, libraryStatsReceiver) - - val authorFeatures = new AuthorFeatures(UserSource.empty, libraryStatsReceiver) - val viewerFeatures = new ViewerFeatures(UserSource.empty, libraryStatsReceiver) - val communityTweetFeatures = new CommunityTweetFeaturesV2(CommunitiesSource.empty) - val exclusiveTweetFeatures = - new ExclusiveTweetFeatures(UserRelationshipSource.empty, libraryStatsReceiver) - val trustedFriendsTweetFeatures = new TrustedFriendsFeatures(TrustedFriendsSource.empty) - val editTweetFeatures = new EditTweetFeatures(libraryStatsReceiver) - - { request: DESRealtimeVisibilityRequest => - vfEngineCounter.incr() - - val tweet = request.tweet - val author = request.author - val viewer = request.viewer - val viewerContext = ViewerContext.fromContext - - val featureMap = - visibilityLibrary.featureMapBuilder( - Seq( - tweetFeatures.forTweetWithoutSafetyLabels(tweet), - authorFeatures.forAuthorNoDefaults(author), - viewerFeatures.forViewerNoDefaults(viewer), - communityTweetFeatures.forTweetOnly(tweet), - exclusiveTweetFeatures.forTweetOnly(tweet), - trustedFriendsTweetFeatures.forTweetOnly(tweet), - editTweetFeatures.forTweet(tweet), - ) - ) - - val tweetResult = visibilityLibrary.runRuleEngine( - ContentId.TweetId(tweet.id), - featureMap, - viewerContext, - safetyLevel - ) - val authorResult = visibilityLibrary.runRuleEngine( - ContentId.UserId(author.id), - featureMap, - viewerContext, - safetyLevel - ) - - Stitch.join(tweetResult, authorResult).map { - case (tweetResult, authorResult) => mergeResults(tweetResult, authorResult) - } - } - } - - def mergeResults( - tweetResult: VisibilityResult, - authorResult: VisibilityResult, - ): vfthrift.Action = { - Set(tweetResult.verdict, authorResult.verdict) - .find { - case Allow => false - case _ => true - } - .map(_.toActionThrift()) - .getOrElse(Allow.toActionThrift()) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/des/DESVisibilityLibrary.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/des/DESVisibilityLibrary.scala deleted file mode 100644 index b3297c67c..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/des/DESVisibilityLibrary.scala +++ /dev/null @@ -1,72 +0,0 @@ -package com.twitter.visibility.interfaces.des - -import com.twitter.stitch.Stitch -import com.twitter.tweetypie.thriftscala.Tweet -import com.twitter.visibility.VisibilityLibrary -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.builder.tweets.StratoTweetLabelMaps -import com.twitter.visibility.builder.tweets.TweetFeatures -import com.twitter.visibility.common.SafetyLabelMapSource -import com.twitter.visibility.features.AuthorId -import com.twitter.visibility.features.FeatureMap -import com.twitter.visibility.interfaces.common.tweets.SafetyLabelMapFetcherType -import com.twitter.visibility.models.ContentId.TweetId -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.ViewerContext - -case class DESVisibilityRequest( - tweet: Tweet, - visibilitySurface: SafetyLevel, - viewerContext: ViewerContext) - -object DESVisibilityLibrary { - type Type = DESVisibilityRequest => Stitch[VisibilityResult] - - def apply( - visibilityLibrary: VisibilityLibrary, - getLabelMap: SafetyLabelMapFetcherType, - enableShimFeatureHydration: Any => Boolean = _ => false - ): Type = { - val libraryStatsReceiver = visibilityLibrary.statsReceiver - val vfEngineCounter = libraryStatsReceiver.counter("vf_engine_requests") - - val tweetLabelMap = new StratoTweetLabelMaps( - SafetyLabelMapSource.fromSafetyLabelMapFetcher(getLabelMap)) - val tweetFeatures = new TweetFeatures(tweetLabelMap, libraryStatsReceiver) - - { request: DESVisibilityRequest => - vfEngineCounter.incr() - - val contentId = TweetId(request.tweet.id) - val authorId = coreData.userId - - val featureMap = - visibilityLibrary.featureMapBuilder( - Seq( - tweetFeatures.forTweet(request.tweet), - _.withConstantFeature(AuthorId, Set(authorId)) - ) - ) - - val isShimFeatureHydrationEnabled = enableShimFeatureHydration() - - if (isShimFeatureHydrationEnabled) { - FeatureMap.resolve(featureMap, libraryStatsReceiver).flatMap { resolvedFeatureMap => - visibilityLibrary.runRuleEngine( - contentId, - resolvedFeatureMap, - request.viewerContext, - request.visibilitySurface - ) - } - } else { - visibilityLibrary.runRuleEngine( - contentId, - featureMap, - request.viewerContext, - request.visibilitySurface - ) - } - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/dms/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/dms/BUILD deleted file mode 100644 index 5a3dcb977..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/dms/BUILD +++ /dev/null @@ -1,32 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "decider/src/main/scala", - "stitch/stitch-core", - "strato/src/main/scala/com/twitter/strato/catalog", - "strato/src/main/scala/com/twitter/strato/client", - "strato/src/main/scala/com/twitter/strato/data", - "strato/src/main/scala/com/twitter/strato/thrift", - "visibility/common/src/main/scala/com/twitter/visibility/common", - "visibility/common/src/main/scala/com/twitter/visibility/common/dm_sources", - "visibility/common/src/main/scala/com/twitter/visibility/common/stitch", - "visibility/lib/src/main/resources/config", - "visibility/lib/src/main/scala/com/twitter/visibility", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/dms", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/users", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/configs", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/rules/providers", - "visibility/lib/src/main/scala/com/twitter/visibility/rules/utils", - "visibility/lib/src/main/scala/com/twitter/visibility/util", - "visibility/lib/src/main/thrift/com/twitter/visibility/safety_label_store:safety-label-store-scala", - ], - exports = [ - "visibility/common/src/main/scala/com/twitter/visibility/common", - "visibility/lib/src/main/scala/com/twitter/visibility", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/dms/DmConversationVisibilityLibrary.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/dms/DmConversationVisibilityLibrary.scala deleted file mode 100644 index 23d547c3e..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/dms/DmConversationVisibilityLibrary.scala +++ /dev/null @@ -1,94 +0,0 @@ -package com.twitter.visibility.interfaces.dms - -import com.twitter.servo.util.Gate -import com.twitter.stitch.Stitch -import com.twitter.strato.client.{Client => StratoClient} -import com.twitter.visibility.VisibilityLibrary -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.builder.dms.DmConversationFeatures -import com.twitter.visibility.builder.users.AuthorFeatures -import com.twitter.visibility.common.UserSource -import com.twitter.visibility.common.dm_sources.DmConversationSource -import com.twitter.visibility.common.stitch.StitchHelpers -import com.twitter.visibility.features.FeatureMap -import com.twitter.visibility.models.ContentId.DmConversationId -import com.twitter.visibility.rules.Drop -import com.twitter.visibility.rules.EvaluationContext -import com.twitter.visibility.rules.Reason -import com.twitter.visibility.rules.RuleBase -import com.twitter.visibility.rules.providers.ProvidedEvaluationContext -import com.twitter.visibility.rules.utils.ShimUtils - -object DmConversationVisibilityLibrary { - type Type = DmConversationVisibilityRequest => Stitch[VisibilityResult] - - def apply( - visibilityLibrary: VisibilityLibrary, - stratoClient: StratoClient, - userSource: UserSource, - enableVfFeatureHydrationInShim: Gate[Unit] = Gate.False - ): Type = { - val libraryStatsReceiver = visibilityLibrary.statsReceiver - val stratoClientStatsReceiver = visibilityLibrary.statsReceiver.scope("strato") - val vfLatencyStatsReceiver = visibilityLibrary.statsReceiver.scope("vf_latency") - val vfEngineCounter = libraryStatsReceiver.counter("vf_engine_requests") - - val dmConversationSource = - DmConversationSource.fromStrato(stratoClient, stratoClientStatsReceiver) - val authorFeatures = new AuthorFeatures(userSource, libraryStatsReceiver) - val dmConversationFeatures = new DmConversationFeatures(dmConversationSource, authorFeatures) - - { req: DmConversationVisibilityRequest => - val dmConversationId = req.dmConversationId - val contentId = DmConversationId(dmConversationId) - val safetyLevel = req.safetyLevel - - if (!RuleBase.hasDmConversationRules(safetyLevel)) { - Stitch.value(VisibilityResult(contentId = contentId, verdict = Drop(Reason.Unspecified))) - } else { - vfEngineCounter.incr() - - val viewerContext = req.viewerContext - val viewerId = viewerContext.userId - val isVfFeatureHydrationEnabled: Boolean = - enableVfFeatureHydrationInShim() - - val featureMap = visibilityLibrary.featureMapBuilder( - Seq(dmConversationFeatures.forDmConversationId(dmConversationId, viewerId))) - - val resp = if (isVfFeatureHydrationEnabled) { - val evaluationContext = ProvidedEvaluationContext.injectRuntimeRulesIntoEvaluationContext( - evaluationContext = EvaluationContext( - safetyLevel, - visibilityLibrary.getParams(viewerContext, safetyLevel), - visibilityLibrary.statsReceiver) - ) - - val preFilteredFeatureMap = - ShimUtils.preFilterFeatureMap(featureMap, safetyLevel, contentId, evaluationContext) - - FeatureMap.resolve(preFilteredFeatureMap, libraryStatsReceiver).flatMap { - resolvedFeatureMap => - visibilityLibrary - .runRuleEngine( - contentId, - resolvedFeatureMap, - viewerContext, - safetyLevel - ) - } - } else { - visibilityLibrary - .runRuleEngine( - contentId, - featureMap, - viewerContext, - safetyLevel - ) - } - - StitchHelpers.profileStitch(resp, Seq(vfLatencyStatsReceiver)) - } - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/dms/DmConversationVisibilityRequest.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/dms/DmConversationVisibilityRequest.scala deleted file mode 100644 index 0b3eac66c..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/dms/DmConversationVisibilityRequest.scala +++ /dev/null @@ -1,9 +0,0 @@ -package com.twitter.visibility.interfaces.dms - -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.ViewerContext - -case class DmConversationVisibilityRequest( - dmConversationId: String, - safetyLevel: SafetyLevel, - viewerContext: ViewerContext) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/dms/DmEventVisibilityLibrary.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/dms/DmEventVisibilityLibrary.scala deleted file mode 100644 index d66539459..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/dms/DmEventVisibilityLibrary.scala +++ /dev/null @@ -1,80 +0,0 @@ -package com.twitter.visibility.interfaces.dms - -import com.twitter.stitch.Stitch -import com.twitter.strato.client.{Client => StratoClient} -import com.twitter.visibility.VisibilityLibrary -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.builder.dms.DmConversationFeatures -import com.twitter.visibility.builder.dms.DmEventFeatures -import com.twitter.visibility.builder.dms.InvalidDmEventFeatureException -import com.twitter.visibility.builder.users.AuthorFeatures -import com.twitter.visibility.common.UserSource -import com.twitter.visibility.common.dm_sources.DmConversationSource -import com.twitter.visibility.common.dm_sources.DmEventSource -import com.twitter.visibility.common.stitch.StitchHelpers -import com.twitter.visibility.models.ContentId.DmEventId -import com.twitter.visibility.rules.Drop -import com.twitter.visibility.rules.Reason -import com.twitter.visibility.rules.RuleBase - -object DmEventVisibilityLibrary { - type Type = DmEventVisibilityRequest => Stitch[VisibilityResult] - - def apply( - visibilityLibrary: VisibilityLibrary, - stratoClient: StratoClient, - userSource: UserSource - ): Type = { - val libraryStatsReceiver = visibilityLibrary.statsReceiver - val stratoClientStatsReceiver = visibilityLibrary.statsReceiver.scope("strato") - val vfLatencyStatsReceiver = visibilityLibrary.statsReceiver.scope("vf_latency") - val vfEngineCounter = libraryStatsReceiver.counter("vf_engine_requests") - val dmConversationSource = { - DmConversationSource.fromStrato(stratoClient, stratoClientStatsReceiver) - } - val dmEventSource = { - DmEventSource.fromStrato(stratoClient, stratoClientStatsReceiver) - } - val authorFeatures = new AuthorFeatures(userSource, libraryStatsReceiver) - val dmConversationFeatures = new DmConversationFeatures(dmConversationSource, authorFeatures) - val dmEventFeatures = - new DmEventFeatures( - dmEventSource, - dmConversationSource, - authorFeatures, - dmConversationFeatures, - libraryStatsReceiver) - - { req: DmEventVisibilityRequest => - val dmEventId = req.dmEventId - val contentId = DmEventId(dmEventId) - val safetyLevel = req.safetyLevel - - if (!RuleBase.hasDmEventRules(safetyLevel)) { - Stitch.value(VisibilityResult(contentId = contentId, verdict = Drop(Reason.Unspecified))) - } else { - vfEngineCounter.incr() - - val viewerContext = req.viewerContext - val viewerIdOpt = viewerContext.userId - - viewerIdOpt match { - case Some(viewerId) => - val featureMap = visibilityLibrary.featureMapBuilder( - Seq(dmEventFeatures.forDmEventId(dmEventId, viewerId))) - - val resp = visibilityLibrary - .runRuleEngine( - contentId, - featureMap, - viewerContext, - safetyLevel - ) - StitchHelpers.profileStitch(resp, Seq(vfLatencyStatsReceiver)) - - case None => Stitch.exception(InvalidDmEventFeatureException("Viewer id is missing")) - } - } - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/dms/DmEventVisibilityRequest.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/dms/DmEventVisibilityRequest.scala deleted file mode 100644 index c7e9c65af..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/dms/DmEventVisibilityRequest.scala +++ /dev/null @@ -1,9 +0,0 @@ -package com.twitter.visibility.interfaces.dms - -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.ViewerContext - -case class DmEventVisibilityRequest( - dmEventId: Long, - safetyLevel: SafetyLevel, - viewerContext: ViewerContext) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/dms/DmVisibilityLibrary.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/dms/DmVisibilityLibrary.scala deleted file mode 100644 index d6a7d3ce5..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/dms/DmVisibilityLibrary.scala +++ /dev/null @@ -1,88 +0,0 @@ -package com.twitter.visibility.interfaces.dms - -import com.twitter.servo.util.Gate -import com.twitter.stitch.Stitch -import com.twitter.strato.client.{Client => StratoClient} -import com.twitter.visibility.VisibilityLibrary -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.builder.users.AuthorFeatures -import com.twitter.visibility.common.DmId -import com.twitter.visibility.common.UserId -import com.twitter.visibility.common.UserSource -import com.twitter.visibility.features.FeatureMap -import com.twitter.visibility.models.ContentId.{DmId => DmContentId} -import com.twitter.visibility.models.SafetyLevel.DirectMessages -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.ViewerContext -import com.twitter.visibility.rules.Drop -import com.twitter.visibility.rules.Reason.DeactivatedAuthor -import com.twitter.visibility.rules.Reason.ErasedAuthor -import com.twitter.visibility.rules.Reason.Nsfw - -object DmVisibilityLibrary { - type Type = DmVisibilityRequest => Stitch[DmVisibilityResponse] - - case class DmVisibilityRequest( - dmId: DmId, - dmAuthorUserId: UserId, - viewerContext: ViewerContext) - - case class DmVisibilityResponse(isMessageNsfw: Boolean) - - val DefaultSafetyLevel: SafetyLevel = DirectMessages - - def apply( - visibilityLibrary: VisibilityLibrary, - stratoClient: StratoClient, - userSource: UserSource, - enableVfFeatureHydrationInShim: Gate[Unit] = Gate.False - ): Type = { - val libraryStatsReceiver = visibilityLibrary.statsReceiver - val vfEngineCounter = libraryStatsReceiver.counter("vf_engine_requests") - - val authorFeatures = new AuthorFeatures(userSource, libraryStatsReceiver) - - { r: DmVisibilityRequest => - vfEngineCounter.incr() - - val contentId = DmContentId(r.dmId) - val dmAuthorUserId = r.dmAuthorUserId - val isVfFeatureHydrationEnabled = enableVfFeatureHydrationInShim() - - val featureMap = - visibilityLibrary.featureMapBuilder( - Seq(authorFeatures.forAuthorId(dmAuthorUserId)) - ) - - val resp = if (isVfFeatureHydrationEnabled) { - FeatureMap.resolve(featureMap, libraryStatsReceiver).flatMap { resolvedFeatureMap => - visibilityLibrary.runRuleEngine( - contentId, - resolvedFeatureMap, - r.viewerContext, - DefaultSafetyLevel - ) - } - } else { - visibilityLibrary - .runRuleEngine( - contentId, - featureMap, - r.viewerContext, - DefaultSafetyLevel - ) - } - - resp.map(buildResponse) - } - } - - private[this] def buildResponse(visibilityResult: VisibilityResult) = - visibilityResult.verdict match { - case Drop(Nsfw | ErasedAuthor | DeactivatedAuthor, _) => - DmVisibilityResponse(isMessageNsfw = true) - case _ => - DmVisibilityResponse(isMessageNsfw = false) - } - -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/dms/package.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/dms/package.scala deleted file mode 100644 index 0b8f4b410..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/dms/package.scala +++ /dev/null @@ -1,12 +0,0 @@ -package com.twitter.visibility.interfaces - -import com.twitter.stitch.Stitch -import com.twitter.visibility.common.DmId -import com.twitter.visibility.safety_label_store.thriftscala.DmSafetyLabelMap - -package object dms { - type DmSafetyLabelMapFetcherType = DmId => Stitch[Option[DmSafetyLabelMap]] - - val DmSafetyLabelMapFetcherStratoColumn = - "visibility/safety-label-store/vflib/dm/safetyLabelMap.Dm" -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/media/BUILD.bazel b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/media/BUILD.bazel deleted file mode 100644 index 1fe0d3dd8..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/media/BUILD.bazel +++ /dev/null @@ -1,16 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = False, - tags = ["bazel-compatible"], - dependencies = [ - "mediaservices/media-util", - "stitch/stitch-core", - "visibility/lib/src/main/scala/com/twitter/visibility", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/media", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/users", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/rules/providers", - "visibility/lib/src/main/scala/com/twitter/visibility/rules/utils", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/media/MediaVisibilityLibrary.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/media/MediaVisibilityLibrary.scala deleted file mode 100644 index 79f25d3ea..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/media/MediaVisibilityLibrary.scala +++ /dev/null @@ -1,89 +0,0 @@ -package com.twitter.visibility.interfaces.media - -import com.twitter.stitch.Stitch -import com.twitter.strato.client.{Client => StratoClient} -import com.twitter.util.Stopwatch -import com.twitter.visibility.VisibilityLibrary -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.builder.users.ViewerFeatures -import com.twitter.visibility.builder.media.MediaFeatures -import com.twitter.visibility.builder.media.MediaMetadataFeatures -import com.twitter.visibility.builder.media.StratoMediaLabelMaps -import com.twitter.visibility.common.MediaMetadataSource -import com.twitter.visibility.common.MediaSafetyLabelMapSource -import com.twitter.visibility.common.UserSource -import com.twitter.visibility.features.FeatureMap -import com.twitter.visibility.generators.TombstoneGenerator -import com.twitter.visibility.models.ContentId.MediaId -import com.twitter.visibility.rules.EvaluationContext -import com.twitter.visibility.rules.providers.ProvidedEvaluationContext -import com.twitter.visibility.rules.utils.ShimUtils - -object MediaVisibilityLibrary { - type Type = MediaVisibilityRequest => Stitch[VisibilityResult] - - def apply( - visibilityLibrary: VisibilityLibrary, - userSource: UserSource, - tombstoneGenerator: TombstoneGenerator, - stratoClient: StratoClient, - ): Type = { - val libraryStatsReceiver = visibilityLibrary.statsReceiver - val vfEngineCounter = libraryStatsReceiver.counter("vf_engine_requests") - val vfLatencyOverallStat = libraryStatsReceiver.stat("vf_latency_overall") - val vfLatencyStitchRunStat = libraryStatsReceiver.stat("vf_latency_stitch_run") - - val stratoClientStatsReceiver = libraryStatsReceiver.scope("strato") - - val mediaMetadataFeatures = new MediaMetadataFeatures( - MediaMetadataSource.fromStrato(stratoClient, stratoClientStatsReceiver), - libraryStatsReceiver) - - val mediaLabelMaps = new StratoMediaLabelMaps( - MediaSafetyLabelMapSource.fromStrato(stratoClient, stratoClientStatsReceiver)) - val mediaFeatures = new MediaFeatures(mediaLabelMaps, libraryStatsReceiver) - - val viewerFeatures = new ViewerFeatures(userSource, libraryStatsReceiver) - - { r: MediaVisibilityRequest => - vfEngineCounter.incr() - - val contentId = MediaId(r.mediaKey.toStringKey) - val languageCode = r.viewerContext.requestLanguageCode.getOrElse("en") - - val featureMap = visibilityLibrary.featureMapBuilder( - Seq( - viewerFeatures.forViewerContext(r.viewerContext), - mediaFeatures.forGenericMediaKey(r.mediaKey), - mediaMetadataFeatures.forGenericMediaKey(r.mediaKey), - ) - ) - - val evaluationContext = ProvidedEvaluationContext.injectRuntimeRulesIntoEvaluationContext( - evaluationContext = EvaluationContext( - r.safetyLevel, - visibilityLibrary.getParams(r.viewerContext, r.safetyLevel), - visibilityLibrary.statsReceiver) - ) - - val preFilteredFeatureMap = - ShimUtils.preFilterFeatureMap(featureMap, r.safetyLevel, contentId, evaluationContext) - - val elapsed = Stopwatch.start() - FeatureMap.resolve(preFilteredFeatureMap, libraryStatsReceiver).flatMap { - resolvedFeatureMap => - vfLatencyStitchRunStat.add(elapsed().inMilliseconds) - - visibilityLibrary - .runRuleEngine( - contentId, - resolvedFeatureMap, - r.viewerContext, - r.safetyLevel - ) - .map(tombstoneGenerator(_, languageCode)) - .onSuccess(_ => vfLatencyOverallStat.add(elapsed().inMilliseconds)) - } - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/media/MediaVisibilityRequest.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/media/MediaVisibilityRequest.scala deleted file mode 100644 index 0f6b78f77..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/media/MediaVisibilityRequest.scala +++ /dev/null @@ -1,10 +0,0 @@ -package com.twitter.visibility.interfaces.media - -import com.twitter.mediaservices.media_util.GenericMediaKey -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.ViewerContext - -case class MediaVisibilityRequest( - mediaKey: GenericMediaKey, - safetyLevel: SafetyLevel, - viewerContext: ViewerContext) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/notifications/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/notifications/BUILD deleted file mode 100644 index 37b3f5dba..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/notifications/BUILD +++ /dev/null @@ -1,31 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/google/guava", - "notificationservice/common/src/main/scala/com/twitter/notificationservice/model:alias", - "notificationservice/common/src/main/scala/com/twitter/notificationservice/model/notification", - "src/thrift/com/twitter/gizmoduck:thrift-scala", - "src/thrift/com/twitter/socialgraph:thrift-scala", - "src/thrift/com/twitter/spam/rtf:safety-label-scala", - "stitch/stitch-core", - "stitch/stitch-gizmoduck/src/main/scala", - "stitch/stitch-socialgraph", - "stitch/stitch-socialgraph/src/main/scala", - "visibility/common/src/main/scala/com/twitter/visibility/common", - "visibility/common/src/main/thrift/com/twitter/visibility:action-scala", - "visibility/lib/src/main/resources/config", - "visibility/lib/src/main/scala/com/twitter/visibility", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/tweets", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/users", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/params", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/interfaces/common/tweets", - ], - exports = [ - "visibility/lib/src/main/scala/com/twitter/visibility", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/notifications/NotificationVFRequest.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/notifications/NotificationVFRequest.scala deleted file mode 100644 index edf92aeab..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/notifications/NotificationVFRequest.scala +++ /dev/null @@ -1,9 +0,0 @@ -package com.twitter.visibility.interfaces.notifications - -import com.twitter.visibility.models.ContentId -import com.twitter.visibility.models.SafetyLevel - -case class NotificationVFRequest( - recipientId: Long, - subject: ContentId.UserId, - safetyLevel: SafetyLevel) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/notifications/NotificationsFilteringResponse.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/notifications/NotificationsFilteringResponse.scala deleted file mode 100644 index bc500cce6..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/notifications/NotificationsFilteringResponse.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.visibility.interfaces.notifications - -import com.twitter.visibility.features.Feature -import com.twitter.visibility.rules.Action -import scala.collection.immutable.Set - -sealed trait NotificationsFilteringResponse - -case object Allow extends NotificationsFilteringResponse - -case class Filtered(action: Action) extends NotificationsFilteringResponse - -case class Failed(features: Set[Feature[_]]) extends NotificationsFilteringResponse diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/notifications/NotificationsPlatformFilteringResponse.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/notifications/NotificationsPlatformFilteringResponse.scala deleted file mode 100644 index 0a5624e49..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/notifications/NotificationsPlatformFilteringResponse.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.visibility.interfaces.notifications - -import com.twitter.visibility.features.Feature -import com.twitter.visibility.rules.Action - -trait NotificationsPlatformFilteringResponse - -case object AllowVerdict extends NotificationsPlatformFilteringResponse - -case class FilteredVerdict(action: Action) extends NotificationsPlatformFilteringResponse - -case class FailedVerdict(featuresMap: Map[Feature[_], String]) - extends NotificationsPlatformFilteringResponse diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/notifications/NotificationsPlatformVisibilityLibrary.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/notifications/NotificationsPlatformVisibilityLibrary.scala deleted file mode 100644 index bdd2f59f1..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/notifications/NotificationsPlatformVisibilityLibrary.scala +++ /dev/null @@ -1,157 +0,0 @@ -package com.twitter.visibility.interfaces.notifications - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.servo.util.Gate -import com.twitter.stitch.Stitch -import com.twitter.util.Throwables -import com.twitter.visibility.VisibilityLibrary -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.builder.tweets.CommunityNotificationFeatures -import com.twitter.visibility.builder.tweets.UnmentionNotificationFeatures -import com.twitter.visibility.builder.users.AuthorDeviceFeatures -import com.twitter.visibility.builder.users.AuthorFeatures -import com.twitter.visibility.builder.users.RelationshipFeatures -import com.twitter.visibility.builder.users.ViewerAdvancedFilteringFeatures -import com.twitter.visibility.builder.users.ViewerFeatures -import com.twitter.visibility.common.UserDeviceSource -import com.twitter.visibility.common.UserRelationshipSource -import com.twitter.visibility.common.UserSource -import com.twitter.visibility.features.AuthorUserLabels -import com.twitter.visibility.features.Feature -import com.twitter.visibility.features.FeatureMap -import com.twitter.visibility.models.ViewerContext -import com.twitter.visibility.rules.State.FeatureFailed -import com.twitter.visibility.rules.State.MissingFeature -import com.twitter.visibility.rules.Action -import com.twitter.visibility.rules.RuleResult -import com.twitter.visibility.rules.{Allow => AllowAction} - -object NotificationsPlatformVisibilityLibrary { - type NotificationsPlatformVFType = - NotificationVFRequest => Stitch[NotificationsPlatformFilteringResponse] - - private val AllowResponse: Stitch[NotificationsPlatformFilteringResponse] = - Stitch.value(AllowVerdict) - - def apply( - userSource: UserSource, - userRelationshipSource: UserRelationshipSource, - userDeviceSource: UserDeviceSource, - visibilityLibrary: VisibilityLibrary, - enableShimFeatureHydration: Gate[Unit] = Gate.False - ): NotificationsPlatformVFType = { - val libraryStatsReceiver = visibilityLibrary.statsReceiver - val vfEngineCounter = libraryStatsReceiver.counter("vf_engine_requests") - - val authorFeatures = new AuthorFeatures(userSource, libraryStatsReceiver) - val authorDeviceFeatures = new AuthorDeviceFeatures(userDeviceSource, libraryStatsReceiver) - val viewerFeatures = new ViewerFeatures(userSource, libraryStatsReceiver) - - val viewerAdvancedFilteringFeatures = - new ViewerAdvancedFilteringFeatures(userSource, libraryStatsReceiver) - val relationshipFeatures = - new RelationshipFeatures(userRelationshipSource, libraryStatsReceiver) - - val isShimFeatureHydrationEnabled = enableShimFeatureHydration() - - def runRuleEngine(candidate: NotificationVFRequest): Stitch[VisibilityResult] = { - val featureMap = - visibilityLibrary.featureMapBuilder( - Seq( - viewerFeatures.forViewerId(Some(candidate.recipientId)), - viewerAdvancedFilteringFeatures.forViewerId(Some(candidate.recipientId)), - authorFeatures.forAuthorId(candidate.subject.id), - authorDeviceFeatures.forAuthorId(candidate.subject.id), - relationshipFeatures.forAuthorId(candidate.subject.id, Some(candidate.recipientId)), - CommunityNotificationFeatures.ForNonCommunityTweetNotification, - UnmentionNotificationFeatures.ForNonUnmentionNotificationFeatures - ) - ) - - vfEngineCounter.incr() - - if (isShimFeatureHydrationEnabled) { - FeatureMap.resolve(featureMap, libraryStatsReceiver).flatMap { resolvedFeatureMap => - visibilityLibrary.runRuleEngine( - contentId = candidate.subject, - featureMap = resolvedFeatureMap, - viewerContext = - ViewerContext.fromContextWithViewerIdFallback(Some(candidate.recipientId)), - safetyLevel = candidate.safetyLevel - ) - } - } else { - visibilityLibrary.runRuleEngine( - contentId = candidate.subject, - featureMap = featureMap, - viewerContext = - ViewerContext.fromContextWithViewerIdFallback(Some(candidate.recipientId)), - safetyLevel = candidate.safetyLevel - ) - } - } - - { - case candidate: NotificationVFRequest => - runRuleEngine(candidate).flatMap(failCloseForFailures(_, libraryStatsReceiver)) - case _ => - AllowResponse - } - } - - private def failCloseForFailures( - visibilityResult: VisibilityResult, - stats: StatsReceiver - ): Stitch[NotificationsPlatformFilteringResponse] = { - lazy val vfEngineSuccess = stats.counter("vf_engine_success") - lazy val vfEngineFailures = stats.counter("vf_engine_failures") - lazy val vfEngineFailuresMissing = stats.scope("vf_engine_failures").counter("missing") - lazy val vfEngineFailuresFailed = stats.scope("vf_engine_failures").counter("failed") - lazy val vfEngineFiltered = stats.counter("vf_engine_filtered") - - val isFailedOrMissingFeature: RuleResult => Boolean = { - case RuleResult(_, FeatureFailed(features)) => - !(features.contains(AuthorUserLabels) && features.size == 1) - case RuleResult(_, MissingFeature(_)) => true - case _ => false - } - - val failedRuleResults = - visibilityResult.ruleResultMap.values.filter(isFailedOrMissingFeature(_)) - - val (failedFeatures, missingFeatures) = failedRuleResults.partition { - case RuleResult(_, FeatureFailed(_)) => true - case RuleResult(_, MissingFeature(_)) => false - case _ => false - } - - val failedOrMissingFeatures: Map[Feature[_], String] = failedRuleResults - .collect { - case RuleResult(_, FeatureFailed(features)) => - features.map { - case (feature: Feature[_], throwable: Throwable) => - feature -> Throwables.mkString(throwable).mkString(" -> ") - }.toSet - case RuleResult(_, MissingFeature(features)) => features.map(_ -> "Feature missing.") - }.flatten.toMap - - visibilityResult.verdict match { - case AllowAction if failedOrMissingFeatures.isEmpty => - vfEngineSuccess.incr() - AllowResponse - case AllowAction if failedOrMissingFeatures.nonEmpty => - vfEngineFailures.incr() - if (missingFeatures.nonEmpty) { - vfEngineFailuresMissing.incr() - } - if (failedFeatures.nonEmpty) { - vfEngineFailuresFailed.incr() - } - - Stitch.value(FailedVerdict(failedOrMissingFeatures)) - case action: Action => - vfEngineFiltered.incr() - Stitch.value(FilteredVerdict(action)) - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/notifications/NotificationsVisibilityLibrary.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/notifications/NotificationsVisibilityLibrary.scala deleted file mode 100644 index c6b99044c..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/notifications/NotificationsVisibilityLibrary.scala +++ /dev/null @@ -1,181 +0,0 @@ -package com.twitter.visibility.interfaces.notifications - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.notificationservice.model.notification.Notification -import com.twitter.notificationservice.model.notification.NotificationType -import com.twitter.notificationservice.model.notification.SimpleActivityNotification -import com.twitter.servo.util.Gate -import com.twitter.stitch.Stitch -import com.twitter.visibility.VisibilityLibrary -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.builder.tweets.CommunityNotificationFeatures -import com.twitter.visibility.builder.tweets.UnmentionNotificationFeatures -import com.twitter.visibility.builder.users.AuthorDeviceFeatures -import com.twitter.visibility.builder.users.AuthorFeatures -import com.twitter.visibility.builder.users.RelationshipFeatures -import com.twitter.visibility.builder.users.ViewerAdvancedFilteringFeatures -import com.twitter.visibility.builder.users.ViewerFeatures -import com.twitter.visibility.common.TweetSource -import com.twitter.visibility.common.UserDeviceSource -import com.twitter.visibility.common.UserRelationshipSource -import com.twitter.visibility.common.UserSource -import com.twitter.visibility.features.AuthorUserLabels -import com.twitter.visibility.features.FeatureMap -import com.twitter.visibility.models.ContentId.NotificationId -import com.twitter.visibility.models.SafetyLevel.NotificationsWriterV2 -import com.twitter.visibility.models.ViewerContext -import com.twitter.visibility.rules.State.FeatureFailed -import com.twitter.visibility.rules.State.MissingFeature -import com.twitter.visibility.rules.Action -import com.twitter.visibility.rules.RuleResult -import com.twitter.visibility.rules.{Allow => AllowAction} - -object NotificationsVisibilityLibrary { - type Type = Notification => Stitch[NotificationsFilteringResponse] - - private val AllowResponse: Stitch[NotificationsFilteringResponse] = Stitch.value(Allow) - - def isApplicableOrganicNotificationType(notificationType: NotificationType): Boolean = { - NotificationType.isTlsActivityType(notificationType) || - NotificationType.isReactionType(notificationType) - } - - def apply( - visibilityLibrary: VisibilityLibrary, - userSource: UserSource, - userRelationshipSource: UserRelationshipSource, - userDeviceSource: UserDeviceSource, - tweetSource: TweetSource, - enableShimFeatureHydration: Gate[Unit] = Gate.False, - enableCommunityTweetHydration: Gate[Long] = Gate.False, - enableUnmentionHydration: Gate[Long] = Gate.False, - ): Type = { - val libraryStatsReceiver = visibilityLibrary.statsReceiver - lazy val vfEngineCounter = libraryStatsReceiver.counter("vf_engine_requests") - - val authorFeatures = new AuthorFeatures(userSource, libraryStatsReceiver) - val authorDeviceFeatures = new AuthorDeviceFeatures(userDeviceSource, libraryStatsReceiver) - val viewerFeatures = new ViewerFeatures(userSource, libraryStatsReceiver) - val communityNotificationFeatures = - new CommunityNotificationFeatures( - tweetSource, - enableCommunityTweetHydration, - libraryStatsReceiver) - - val unmentionNotificationFeatures = new UnmentionNotificationFeatures( - tweetSource = tweetSource, - enableUnmentionHydration = enableUnmentionHydration, - statsReceiver = libraryStatsReceiver - ) - - val viewerAdvancedFilteringFeatures = - new ViewerAdvancedFilteringFeatures(userSource, libraryStatsReceiver) - val relationshipFeatures = - new RelationshipFeatures(userRelationshipSource, libraryStatsReceiver) - - val isShimFeatureHydrationEnabled = enableShimFeatureHydration() - - def runRuleEngine( - visibilityLibrary: VisibilityLibrary, - candidate: Notification - ): Stitch[VisibilityResult] = { - candidate match { - case notification: SimpleActivityNotification[_] => - vfEngineCounter.incr() - - val featureMap = visibilityLibrary.featureMapBuilder( - Seq( - viewerFeatures.forViewerId(Some(notification.target)), - viewerAdvancedFilteringFeatures.forViewerId(Some(notification.target)), - authorFeatures.forAuthorId(notification.subjectId), - authorDeviceFeatures.forAuthorId(notification.subjectId), - relationshipFeatures - .forAuthorId(notification.subjectId, Some(notification.target)), - communityNotificationFeatures.forNotification(notification), - unmentionNotificationFeatures.forNotification(notification) - ) - ) - - if (isShimFeatureHydrationEnabled) { - FeatureMap.resolve(featureMap, libraryStatsReceiver).flatMap { resolvedFeatureMap => - visibilityLibrary.runRuleEngine( - contentId = - featureMap = resolvedFeatureMap, - viewerContext = - ViewerContext.fromContextWithViewerIdFallback(Some(notification.target)), - safetyLevel = NotificationsWriterV2 - ) - } - } else { - visibilityLibrary.runRuleEngine( - contentId = NotificationId(tweetId = None), - featureMap = featureMap, - viewerContext = - ViewerContext.fromContextWithViewerIdFallback(Some(notification.target)), - safetyLevel = NotificationsWriterV2 - ) - } - } - } - - { - case candidate if isApplicableOrganicNotificationType(candidate.notificationType) => - runRuleEngine(visibilityLibrary, candidate) - .flatMap(failCloseForFailures(_, libraryStatsReceiver)) - case _ => - AllowResponse - } - } - - def failCloseForFailures( - visibilityResult: VisibilityResult, - stats: StatsReceiver - ): Stitch[NotificationsFilteringResponse] = { - lazy val vfEngineSuccess = stats.counter("vf_engine_success") - lazy val vfEngineFailures = stats.counter("vf_engine_failures") - lazy val vfEngineFailuresMissing = stats.scope("vf_engine_failures").counter("missing") - lazy val vfEngineFailuresFailed = stats.scope("vf_engine_failures").counter("failed") - lazy val vfEngineFiltered = stats.counter("vf_engine_filtered") - - val isFailedOrMissingFeature: RuleResult => Boolean = { - case RuleResult(_, FeatureFailed(features)) => - !(features.contains(AuthorUserLabels) && features.size == 1) - case RuleResult(_, MissingFeature(_)) => true - case _ => false - } - - val failedRuleResults = - visibilityResult.ruleResultMap.values.filter(isFailedOrMissingFeature(_)) - - val (failedFeatures, missingFeatures) = failedRuleResults.partition { - case RuleResult(_, FeatureFailed(_)) => true - case RuleResult(_, MissingFeature(_)) => false - case _ => false - } - - val failedOrMissingFeatures = failedRuleResults - .collect { - case RuleResult(_, FeatureFailed(features)) => features.keySet - case RuleResult(_, MissingFeature(features)) => features - }.toSet.flatten - - visibilityResult.verdict match { - case AllowAction if failedOrMissingFeatures.isEmpty => - vfEngineSuccess.incr() - AllowResponse - case AllowAction if failedOrMissingFeatures.nonEmpty => - vfEngineFailures.incr() - if (missingFeatures.nonEmpty) { - vfEngineFailuresMissing.incr() - } - if (failedFeatures.nonEmpty) { - vfEngineFailuresFailed.incr() - } - - Stitch.value(Failed(failedOrMissingFeatures)) - case action: Action => - vfEngineFiltered.incr() - Stitch.value(Filtered(action)) - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/BUILD.bazel b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/BUILD.bazel deleted file mode 100644 index 0436ca3c7..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/BUILD.bazel +++ /dev/null @@ -1,31 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/twitter/storehaus:core", - "src/thrift/com/twitter/spam/rtf:tweet-rtf-event-scala", - "src/thrift/com/twitter/tweetypie:events-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "stitch/stitch-core", - "stitch/stitch-tweetypie/src/main/scala", - "strato/src/main/scala/com/twitter/strato/catalog", - "strato/src/main/scala/com/twitter/strato/client", - "visibility/common/src/main/scala/com/twitter/visibility/common", - "visibility/common/src/main/scala/com/twitter/visibility/common/stitch", - "visibility/common/src/main/thrift/com/twitter/visibility:action-scala", - "visibility/lib/src/main/resources/config", - "visibility/lib/src/main/scala/com/twitter/visibility", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/media", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/tweets", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/users", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/params", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/interfaces/common/tweets", - ], - exports = [ - "visibility/common/src/main/scala/com/twitter/visibility/common", - "visibility/lib/src/main/scala/com/twitter/visibility", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceSafetyLabelMapFetcher.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceSafetyLabelMapFetcher.scala deleted file mode 100644 index f7ce43392..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceSafetyLabelMapFetcher.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.visibility.interfaces.push_service - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.spam.rtf.thriftscala.SafetyLabelMap -import com.twitter.stitch.Stitch -import com.twitter.strato.client.{Client => StratoClient} -import com.twitter.strato.thrift.ScroogeConvImplicits._ -import com.twitter.visibility.common.stitch.StitchHelpers - -object PushServiceSafetyLabelMapFetcher { - val Column = "frigate/magicrecs/tweetSafetyLabels" - - def apply( - client: StratoClient, - statsReceiver: StatsReceiver - ): Long => Stitch[Option[SafetyLabelMap]] = { - val stats = statsReceiver.scope("strato_tweet_safety_labels") - lazy val fetcher = client.fetcher[Long, SafetyLabelMap](Column) - tweetId => StitchHelpers.observe(stats)(fetcher.fetch(tweetId).map(_.v)) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityLibrary.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityLibrary.scala deleted file mode 100644 index 42b2d16ca..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityLibrary.scala +++ /dev/null @@ -1,179 +0,0 @@ -package com.twitter.visibility.interfaces.push_service - -import com.twitter.gizmoduck.thriftscala.User -import com.twitter.servo.util.Gate -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.stitch.Stitch -import com.twitter.stitch.tweetypie.TweetyPie.TweetyPieResult -import com.twitter.storehaus.ReadableStore -import com.twitter.strato.client.{Client => StratoClient} -import com.twitter.tweetypie.thriftscala.Tweet -import com.twitter.visibility.VisibilityLibrary -import com.twitter.visibility.builder.tweets.TweetFeatures -import com.twitter.visibility.builder.tweets.StratoTweetLabelMaps -import com.twitter.visibility.builder.users.AuthorFeatures -import com.twitter.visibility.builder.users.RelationshipFeatures -import com.twitter.visibility.builder.users.ViewerFeatures -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.common._ -import com.twitter.visibility.common.UserRelationshipSource -import com.twitter.visibility.common.UserSource -import com.twitter.visibility.features.FeatureMap -import com.twitter.visibility.features.TweetIsInnerQuotedTweet -import com.twitter.visibility.features.TweetIsRetweet -import com.twitter.visibility.features.TweetIsSourceTweet -import com.twitter.visibility.interfaces.push_service.PushServiceVisibilityLibraryUtil._ -import com.twitter.visibility.models.ContentId -import com.twitter.visibility.models.ViewerContext - -object TweetType extends Enumeration { - type TweetType = Value - val ORIGINAL, SOURCE, QUOTED = Value -} -import com.twitter.visibility.interfaces.push_service.TweetType._ - -object PushServiceVisibilityLibrary { - type Type = PushServiceVisibilityRequest => Stitch[PushServiceVisibilityResponse] - - def apply( - visibilityLibrary: VisibilityLibrary, - userSource: UserSource, - userRelationshipSource: UserRelationshipSource, - stratoClient: StratoClient, - enableParityTest: Gate[Unit] = Gate.False, - cachedTweetyPieStoreV2: ReadableStore[Long, TweetyPieResult] = ReadableStore.empty, - safeCachedTweetyPieStoreV2: ReadableStore[Long, TweetyPieResult] = ReadableStore.empty, - )( - implicit statsReceiver: StatsReceiver - ): Type = { - val stats = statsReceiver.scope("push_service_vf") - val candidateTweetCounter = stats.counter("request_cnt") - val allowedTweetCounter = stats.counter("allow_cnt") - val droppedTweetCounter = stats.counter("drop_cnt") - val failedTweetCounter = stats.counter("fail_cnt") - val authorLabelsEmptyCount = stats.counter("author_labels_empty_cnt") - val authorLabelsCount = stats.counter("author_labels_cnt") - - val tweetLabelMaps = new StratoTweetLabelMaps( - SafetyLabelMapSource.fromSafetyLabelMapFetcher( - PushServiceSafetyLabelMapFetcher(stratoClient, stats))) - - val viewerFeatures = new ViewerFeatures(UserSource.empty, stats) - val tweetFeatures = new TweetFeatures(tweetLabelMaps, stats) - val authorFeatures = new AuthorFeatures(userSource, stats) - val relationshipFeatures = new RelationshipFeatures(UserRelationshipSource.empty, stats) - - val parityTester = new PushServiceVisibilityLibraryParity( - cachedTweetyPieStoreV2, - safeCachedTweetyPieStoreV2 - )(statsReceiver) - - def buildFeatureMap( - request: PushServiceVisibilityRequest, - tweet: Tweet, - tweetType: TweetType, - author: Option[User] = None, - ): FeatureMap = { - val authorId = author.map(_.id) orElse getAuthorId(tweet) - (author.map(authorFeatures.forAuthor(_)) orElse - getAuthorId(tweet).map(authorFeatures.forAuthorId(_))) match { - case Some(authorVisibilityFeatures) => - visibilityLibrary.featureMapBuilder( - Seq( - viewerFeatures.forViewerContext(ViewerContext.fromContextWithViewerIdFallback(None)), - tweetFeatures.forTweet(tweet), - authorVisibilityFeatures, - relationshipFeatures.forAuthorId(authorId.get, None), - _.withConstantFeature(TweetIsInnerQuotedTweet, tweetType == QUOTED), - _.withConstantFeature(TweetIsRetweet, request.isRetweet), - _.withConstantFeature(TweetIsSourceTweet, tweetType == SOURCE) - ) - ) - case _ => - visibilityLibrary.featureMapBuilder( - Seq( - viewerFeatures.forViewerContext(ViewerContext.fromContextWithViewerIdFallback(None)), - tweetFeatures.forTweet(tweet), - _.withConstantFeature(TweetIsInnerQuotedTweet, tweetType == QUOTED), - _.withConstantFeature(TweetIsRetweet, request.isRetweet), - _.withConstantFeature(TweetIsSourceTweet, tweetType == SOURCE) - ) - ) - } - } - - def runRuleEngineForTweet( - request: PushServiceVisibilityRequest, - tweet: Tweet, - tweetType: TweetType, - author: Option[User] = None, - ): Stitch[VisibilityResult] = { - val featureMap = buildFeatureMap(request, tweet, tweetType, author) - val contentId = ContentId.TweetId(tweet.id) - visibilityLibrary.runRuleEngine( - contentId, - featureMap, - request.viewerContext, - request.safetyLevel) - } - - def runRuleEngineForAuthor( - request: PushServiceVisibilityRequest, - tweet: Tweet, - tweetType: TweetType, - author: Option[User] = None, - ): Stitch[VisibilityResult] = { - val featureMap = buildFeatureMap(request, tweet, tweetType, author) - val authorId = author.map(_.id).getOrElse(getAuthorId(tweet).get) - val contentId = ContentId.UserId(authorId) - visibilityLibrary.runRuleEngine( - contentId, - featureMap, - request.viewerContext, - request.safetyLevel) - } - - def getAllVisibilityFilters( - request: PushServiceVisibilityRequest - ): Stitch[PushServiceVisibilityResponse] = { - val tweetResult = - runRuleEngineForTweet(request, request.tweet, ORIGINAL, Some(request.author)) - val authorResult = - runRuleEngineForAuthor(request, request.tweet, ORIGINAL, Some(request.author)) - val sourceTweetResult = request.sourceTweet - .map(runRuleEngineForTweet(request, _, SOURCE).map(Some(_))).getOrElse(Stitch.None) - val quotedTweetResult = request.quotedTweet - .map(runRuleEngineForTweet(request, _, QUOTED).map(Some(_))).getOrElse(Stitch.None) - - Stitch.join(tweetResult, authorResult, sourceTweetResult, quotedTweetResult).map { - case (tweetResult, authorResult, sourceTweetResult, quotedTweetResult) => - PushServiceVisibilityResponse( - tweetResult, - authorResult, - sourceTweetResult, - quotedTweetResult) - } - } - - { request: PushServiceVisibilityRequest => - candidateTweetCounter.incr() - - request.author.labels match { - case Some(labels) if (!labels._1.isEmpty) => authorLabelsCount.incr() - case _ => authorLabelsEmptyCount.incr() - } - - val response = getAllVisibilityFilters(request) - .onSuccess { response => - if (response.shouldAllow) allowedTweetCounter.incr() else droppedTweetCounter.incr() - }.onFailure { _ => failedTweetCounter.incr() } - - if (enableParityTest()) { - response.applyEffect { resp => Stitch.async(parityTester.runParityTest(request, resp)) } - } else { - response - } - - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityLibraryParity.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityLibraryParity.scala deleted file mode 100644 index cc1b27e24..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityLibraryParity.scala +++ /dev/null @@ -1,74 +0,0 @@ -package com.twitter.visibility.interfaces.push_service - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.stitch.Stitch -import com.twitter.stitch.tweetypie.TweetyPie.TweetyPieResult -import com.twitter.storehaus.ReadableStore -import com.twitter.logging.Logger -import com.twitter.visibility.models.SafetyLevel - -class PushServiceVisibilityLibraryParity( - magicRecsV2tweetyPieStore: ReadableStore[Long, TweetyPieResult], - magicRecsAggressiveV2tweetyPieStore: ReadableStore[Long, TweetyPieResult] -)( - implicit statsReceiver: StatsReceiver) { - - private val stats = statsReceiver.scope("push_service_vf_parity") - private val requests = stats.counter("requests") - private val equal = stats.counter("equal") - private val notEqual = stats.counter("notEqual") - private val failures = stats.counter("failures") - private val bothAllow = stats.counter("bothAllow") - private val bothReject = stats.counter("bothReject") - private val onlyTweetypieRejects = stats.counter("onlyTweetypieRejects") - private val onlyPushServiceRejects = stats.counter("onlyPushServiceRejects") - - val log = Logger.get("pushservice_vf_parity") - - def runParityTest( - req: PushServiceVisibilityRequest, - resp: PushServiceVisibilityResponse - ): Stitch[Unit] = { - requests.incr() - getTweetypieResult(req).map { tweetypieResult => - val isSameVerdict = (tweetypieResult == resp.shouldAllow) - isSameVerdict match { - case true => equal.incr() - case false => notEqual.incr() - } - (tweetypieResult, resp.shouldAllow) match { - case (true, true) => bothAllow.incr() - case (true, false) => onlyPushServiceRejects.incr() - case (false, true) => onlyTweetypieRejects.incr() - case (false, false) => bothReject.incr() - } - - resp.getDropRules.foreach { dropRule => - stats.counter(s"rules/${dropRule.name}/requests").incr() - stats - .counter( - s"rules/${dropRule.name}/" ++ (if (isSameVerdict) "equal" else "notEqual")).incr() - } - - if (!isSameVerdict) { - val dropRuleNames = resp.getDropRules.map("<<" ++ _.name ++ ">>").mkString(",") - val safetyLevelStr = req.safetyLevel match { - case SafetyLevel.MagicRecsAggressiveV2 => "aggr" - case _ => " " - } - log.info( - s"ttweetId:${req.tweet.id} () push:${resp.shouldAllow}, tweety:${tweetypieResult}, rules=[${dropRuleNames}] lvl=${safetyLevelStr}") - } - } - - } - - def getTweetypieResult(request: PushServiceVisibilityRequest): Stitch[Boolean] = { - val tweetypieStore = request.safetyLevel match { - case SafetyLevel.MagicRecsAggressiveV2 => magicRecsAggressiveV2tweetyPieStore - case _ => magicRecsV2tweetyPieStore - } - Stitch.callFuture( - tweetypieStore.get(request.tweet.id).onFailure(_ => failures.incr()).map(x => x.isDefined)) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityLibraryUtil.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityLibraryUtil.scala deleted file mode 100644 index 0f0321afe..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityLibraryUtil.scala +++ /dev/null @@ -1,57 +0,0 @@ -package com.twitter.visibility.interfaces.push_service - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.tweetypie.thriftscala.Tweet -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.rules.Rule -import com.twitter.visibility.rules.RuleResult -import com.twitter.visibility.rules.State - -object PushServiceVisibilityLibraryUtil { - def ruleEnabled(ruleResult: RuleResult): Boolean = { - ruleResult.state match { - case State.Disabled => false - case State.ShortCircuited => false - case _ => true - } - } - def getMissingFeatures(ruleResult: RuleResult): Set[String] = { - ruleResult.state match { - case State.MissingFeature(features) => features.map(f => f.name) - case _ => Set.empty - } - } - def getMissingFeatureCounts(results: Seq[VisibilityResult]): Map[String, Int] = { - results - .flatMap(_.ruleResultMap.values.toList) - .flatMap(getMissingFeatures(_).toList).groupBy(identity).mapValues(_.length) - } - - def logAllStats( - response: PushServiceVisibilityResponse - )( - implicit statsReceiver: StatsReceiver - ) = { - val rulesStatsReceiver = statsReceiver.scope("rules") - logStats(response.tweetVisibilityResult, rulesStatsReceiver.scope("tweet")) - logStats(response.authorVisibilityResult, rulesStatsReceiver.scope("author")) - } - - def logStats(result: VisibilityResult, statsReceiver: StatsReceiver) = { - result.ruleResultMap.toList - .filter { case (_, ruleResult) => ruleEnabled(ruleResult) } - .flatMap { case (rule, ruleResult) => getCounters(rule, ruleResult) } - .foreach(statsReceiver.counter(_).incr()) - } - - def getCounters(rule: Rule, ruleResult: RuleResult): List[String] = { - val missingFeatures = getMissingFeatures(ruleResult) - List(s"${rule.name}/${ruleResult.action.name}") ++ - missingFeatures.map(feat => s"${rule.name}/${feat}") ++ - missingFeatures - } - - def getAuthorId(tweet: Tweet): Option[Long] = tweet.coreData.map(_.userId) - def isRetweet(tweet: Tweet): Boolean = tweet.coreData.flatMap(_.share).isDefined - def isQuotedTweet(tweet: Tweet): Boolean = tweet.quotedTweet.isDefined -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityRequest.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityRequest.scala deleted file mode 100644 index b773deec9..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityRequest.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.visibility.interfaces.push_service - -import com.twitter.gizmoduck.thriftscala.User -import com.twitter.tweetypie.thriftscala.Tweet -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.ViewerContext - -case class PushServiceVisibilityRequest( - tweet: Tweet, - author: User, - viewerContext: ViewerContext, - safetyLevel: SafetyLevel, - sourceTweet: Option[Tweet] = None, - quotedTweet: Option[Tweet] = None, - isRetweet: Boolean = false, - isInnerQuotedTweet: Boolean = false, - isSourceTweet: Boolean = false, - isOutOfNetworkTweet: Boolean = true, -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityResponse.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityResponse.scala deleted file mode 100644 index a3598fd61..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityResponse.scala +++ /dev/null @@ -1,52 +0,0 @@ -package com.twitter.visibility.interfaces.push_service - -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.rules.Action -import com.twitter.visibility.rules.Allow -import com.twitter.visibility.rules.Drop -import com.twitter.visibility.rules.Rule -import com.twitter.visibility.rules.RuleResult - -case class PushServiceVisibilityResponse( - tweetVisibilityResult: VisibilityResult, - authorVisibilityResult: VisibilityResult, - sourceTweetVisibilityResult: Option[VisibilityResult] = None, - quotedTweetVisibilityResult: Option[VisibilityResult] = None, -) { - - def allVisibilityResults: List[VisibilityResult] = { - List( - Some(tweetVisibilityResult), - Some(authorVisibilityResult), - sourceTweetVisibilityResult, - quotedTweetVisibilityResult, - ).collect { case Some(result) => result } - } - - val shouldAllow: Boolean = !allVisibilityResults.exists(isDrop(_)) - - def isDrop(response: VisibilityResult): Boolean = response.verdict match { - case _: Drop => true - case Allow => false - case _ => false - } - def isDrop(response: Option[VisibilityResult]): Boolean = response.map(isDrop(_)).getOrElse(false) - - def getDropRules(visibilityResult: VisibilityResult): List[Rule] = { - val ruleResultMap = visibilityResult.ruleResultMap - val ruleResults = ruleResultMap.toList - val denyRules = ruleResults.collect { case (rule, RuleResult(Drop(_, _), _)) => rule } - denyRules - } - def getAuthorDropRules: List[Rule] = getDropRules(authorVisibilityResult) - def getTweetDropRules: List[Rule] = getDropRules(tweetVisibilityResult) - def getDropRules: List[Rule] = getAuthorDropRules ++ getTweetDropRules - def getVerdict: Action = { - if (isDrop(authorVisibilityResult)) authorVisibilityResult.verdict - else tweetVisibilityResult.verdict - } - - def missingFeatures: Map[String, Int] = PushServiceVisibilityLibraryUtil.getMissingFeatureCounts( - Seq(tweetVisibilityResult, authorVisibilityResult)) - -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/BUILD deleted file mode 100644 index 2e758bc84..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/BUILD +++ /dev/null @@ -1,34 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/twitter/src/java/com/twitter/logpipeline/client:logpipeline-event-publisher-thin", - "decider/src/main/scala", - "mediaservices/media-util/src/main/scala", - "servo/decider/src/main/scala", - "src/thrift/com/twitter/escherbird:media-annotation-structs-scala", - "src/thrift/com/twitter/spam/rtf:safety-level-scala", - "src/thrift/com/twitter/spam/rtf:tweet-rtf-event-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "stitch/stitch-core", - "strato/src/main/scala/com/twitter/strato/client", - "visibility/common/src/main/scala/com/twitter/visibility/common", - "visibility/lib/src/main/resources/config", - "visibility/lib/src/main/scala/com/twitter/visibility", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/media", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/tweets", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/users", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/configs", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/interfaces/common/search", - "visibility/lib/src/main/scala/com/twitter/visibility/interfaces/common/tweets", - "visibility/lib/src/main/thrift/com/twitter/visibility/logging:vf-logging-scala", - ], - exports = [ - "visibility/common/src/main/scala/com/twitter/visibility/common", - "visibility/lib/src/main/scala/com/twitter/visibility", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/BatchSearchVisibilityRequest.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/BatchSearchVisibilityRequest.scala deleted file mode 100644 index 37a294825..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/BatchSearchVisibilityRequest.scala +++ /dev/null @@ -1,9 +0,0 @@ -package com.twitter.visibility.interfaces.search - -import com.twitter.visibility.interfaces.common.search.SearchVFRequestContext -import com.twitter.visibility.models.ViewerContext - -case class BatchSearchVisibilityRequest( - tweetContexts: Seq[TweetContext], - viewerContext: ViewerContext, - searchVFRequestContext: SearchVFRequestContext) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/BatchSearchVisibilityResponse.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/BatchSearchVisibilityResponse.scala deleted file mode 100644 index 3eb7918dc..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/BatchSearchVisibilityResponse.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.visibility.interfaces.search - -case class BatchSearchVisibilityResponse( - visibilityResults: Map[Long, CombinedVisibilityResult], - failedTweetIds: Seq[Long]) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/CombinedVisibilityResult.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/CombinedVisibilityResult.scala deleted file mode 100644 index e71841783..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/CombinedVisibilityResult.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.visibility.interfaces.search - -import com.twitter.visibility.builder.VisibilityResult - -case class CombinedVisibilityResult( - tweetVisibilityResult: VisibilityResult, - quotedTweetVisibilityResult: Option[VisibilityResult]) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/SearchVisibilityLibrary.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/SearchVisibilityLibrary.scala deleted file mode 100644 index ea46ab741..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/SearchVisibilityLibrary.scala +++ /dev/null @@ -1,466 +0,0 @@ -package com.twitter.visibility.interfaces.search - -import com.twitter.decider.Decider -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.mediaservices.media_util.GenericMediaKey -import com.twitter.servo.util.Gate -import com.twitter.stitch.Stitch -import com.twitter.strato.client.{Client => StratoClient} -import com.twitter.tweetypie.thriftscala.Tweet -import com.twitter.util.Return -import com.twitter.util.Stopwatch -import com.twitter.util.Try -import com.twitter.visibility.VisibilityLibrary -import com.twitter.visibility.builder.VerdictLogger -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.builder.media.MediaFeatures -import com.twitter.visibility.builder.media.StratoMediaLabelMaps -import com.twitter.visibility.builder.tweets._ -import com.twitter.visibility.builder.users.AuthorFeatures -import com.twitter.visibility.builder.users.RelationshipFeatures -import com.twitter.visibility.builder.users.ViewerFeatures -import com.twitter.visibility.common.MediaSafetyLabelMapSource -import com.twitter.visibility.common.MisinformationPolicySource -import com.twitter.visibility.common.SafetyLabelMapSource -import com.twitter.visibility.common.TrustedFriendsSource -import com.twitter.visibility.common.UserRelationshipSource -import com.twitter.visibility.common.UserSource -import com.twitter.visibility.rules.ComposableActions._ -import com.twitter.visibility.configapi.configs.VisibilityDeciderGates -import com.twitter.visibility.features.FeatureMap -import com.twitter.visibility.features.TweetIsInnerQuotedTweet -import com.twitter.visibility.features.TweetIsRetweet -import com.twitter.visibility.features.TweetIsSourceTweet -import com.twitter.visibility.interfaces.common.search.SearchVFRequestContext -import com.twitter.visibility.interfaces.search.SearchVisibilityLibrary.EvaluateTweet -import com.twitter.visibility.interfaces.search.SearchVisibilityLibrary.RequestTweetId -import com.twitter.visibility.interfaces.search.TweetType.EvaluateTweetType -import com.twitter.visibility.logging.thriftscala.VFLibType -import com.twitter.visibility.models.ContentId -import com.twitter.visibility.models.ContentId.BlenderTweetId -import com.twitter.visibility.models.ContentId.TweetId -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.SafetyLevel.toThrift -import com.twitter.visibility.models.ViewerContext -import com.twitter.visibility.rules.Action -import com.twitter.visibility.rules.Allow -import com.twitter.visibility.rules.Drop -import com.twitter.visibility.rules.Interstitial -import com.twitter.visibility.rules.TweetInterstitial - -object TweetType extends Enumeration { - type EvaluateTweetType = Value - val REQUEST: TweetType.Value = Value(1) - val QUOTED: TweetType.Value = Value(2) - val SOURCE: TweetType.Value = Value(3) -} - -import com.twitter.visibility.interfaces.search.TweetType._ - -object SearchVisibilityLibrary { - type RequestTweetId = Long - type EvaluateTweetId = Long - type EvaluateTweet = Tweet - - def buildWithStratoClient( - visibilityLibrary: VisibilityLibrary, - decider: Decider, - stratoClient: StratoClient, - userSource: UserSource, - userRelationshipSource: UserRelationshipSource - ): SearchVisibilityLibrary = new SearchVisibilityLibrary( - visibilityLibrary, - decider, - stratoClient, - userSource, - userRelationshipSource, - None - ) - - def buildWithSafetyLabelMapSource( - visibilityLibrary: VisibilityLibrary, - decider: Decider, - stratoClient: StratoClient, - userSource: UserSource, - userRelationshipSource: UserRelationshipSource, - safetyLabelMapSource: SafetyLabelMapSource - ): SearchVisibilityLibrary = new SearchVisibilityLibrary( - visibilityLibrary, - decider, - stratoClient, - userSource, - userRelationshipSource, - Some(safetyLabelMapSource) - ) - - def createVerdictLogger( - enableVerdictLogger: Gate[Unit], - decider: Decider, - statsReceiver: StatsReceiver - ): VerdictLogger = { - if (enableVerdictLogger()) { - VerdictLogger(statsReceiver, decider) - } else { - VerdictLogger.Empty - } - } - - def scribeVisibilityVerdict( - result: CombinedVisibilityResult, - enableVerdictScribing: Gate[Unit], - verdictLogger: VerdictLogger, - viewerId: Option[Long], - safetyLevel: SafetyLevel - ): Unit = if (enableVerdictScribing()) { - verdictLogger.scribeVerdict( - visibilityResult = result.tweetVisibilityResult, - viewerId = viewerId, - safetyLevel = toThrift(safetyLevel), - vfLibType = VFLibType.SearchVisibilityLibrary) - - result.quotedTweetVisibilityResult.map(quotedTweetVisibilityResult => - verdictLogger.scribeVerdict( - visibilityResult = quotedTweetVisibilityResult, - viewerId = viewerId, - safetyLevel = toThrift(safetyLevel), - vfLibType = VFLibType.SearchVisibilityLibrary)) - } -} - -class SearchVisibilityLibrary( - visibilityLibrary: VisibilityLibrary, - decider: Decider, - stratoClient: StratoClient, - userSource: UserSource, - userRelationshipSource: UserRelationshipSource, - safetyLabelMapSourceOption: Option[SafetyLabelMapSource]) { - - val libraryStatsReceiver = visibilityLibrary.statsReceiver - val stratoClientStatsReceiver = visibilityLibrary.statsReceiver.scope("strato") - val vfEngineCounter = libraryStatsReceiver.counter("vf_engine_requests") - val svlRequestCounter = libraryStatsReceiver.counter("svl_requests") - val vfLatencyOverallStat = libraryStatsReceiver.stat("vf_latency_overall") - val vfLatencyStitchBuildStat = libraryStatsReceiver.stat("vf_latency_stitch_build") - val vfLatencyStitchRunStat = libraryStatsReceiver.stat("vf_latency_stitch_run") - val visibilityDeciderGates = VisibilityDeciderGates(decider) - val verdictLogger = SearchVisibilityLibrary.createVerdictLogger( - visibilityDeciderGates.enableVerdictLoggerSVL, - decider, - libraryStatsReceiver) - - val tweetLabels = safetyLabelMapSourceOption match { - case Some(safetyLabelMapSource) => - new StratoTweetLabelMaps(safetyLabelMapSource) - case None => - new StratoTweetLabelMaps( - SafetyLabelMapSource.fromStrato(stratoClient, stratoClientStatsReceiver)) - } - - val mediaLabelMaps = new StratoMediaLabelMaps( - MediaSafetyLabelMapSource.fromStrato(stratoClient, stratoClientStatsReceiver)) - - val tweetFeatures = new TweetFeatures(tweetLabels, libraryStatsReceiver) - val searchContextFeatures = new SearchContextFeatures(libraryStatsReceiver) - val authorFeatures = new AuthorFeatures(userSource, libraryStatsReceiver) - val viewerFeatures = new ViewerFeatures(userSource, libraryStatsReceiver) - val relationshipFeatures = - new RelationshipFeatures(userRelationshipSource, libraryStatsReceiver) - val misinfoPolicySource = - MisinformationPolicySource.fromStrato(stratoClient, stratoClientStatsReceiver) - val misinfoPolicyFeatures = - new MisinformationPolicyFeatures(misinfoPolicySource, stratoClientStatsReceiver) - val exclusiveTweetFeatures = - new ExclusiveTweetFeatures(userRelationshipSource, libraryStatsReceiver) - val mediaFeatures = new MediaFeatures(mediaLabelMaps, libraryStatsReceiver) - val trustedFriendsTweetFeatures = new TrustedFriendsFeatures( - trustedFriendsSource = TrustedFriendsSource.fromStrato(stratoClient, stratoClientStatsReceiver)) - val editTweetFeatures = new EditTweetFeatures(libraryStatsReceiver) - - def batchProcessSearchVisibilityRequest( - batchSvRequest: BatchSearchVisibilityRequest - ): Stitch[BatchSearchVisibilityResponse] = { - val elapsed = Stopwatch.start() - svlRequestCounter.incr() - - val response: Stitch[BatchSearchVisibilityResponse] = - batchSvRequest.tweetContexts.groupBy(tweetContext => tweetContext.safetyLevel) map { - case (safetyLevel: SafetyLevel, tweetContexts: Seq[TweetContext]) => - val (contentsToBeEvaluated, contentVisResultTypes) = - extractContentsToBeEvaluated(tweetContexts, batchSvRequest.viewerContext) - - getVisibilityResult( - contentsToBeEvaluated, - safetyLevel, - batchSvRequest.viewerContext, - batchSvRequest.searchVFRequestContext) - .map { contentVisResults: Seq[Try[VisibilityResult]] => - (contentVisResultTypes zip contentVisResults) - .map(handleVisibilityResultByTweetType) - .groupBy { - case (requestTweetId: RequestTweetId, (_, _)) => requestTweetId - }.mapValues(combineVisibilityResult) - }.onSuccess(res => - res.values.flatten.foreach(_ => - SearchVisibilityLibrary.scribeVisibilityVerdict( - _, - visibilityDeciderGates.enableVerdictScribingSVL, - verdictLogger, - batchSvRequest.viewerContext.userId, - safetyLevel))) - } reduceLeft { (left, right) => - Stitch.joinMap(left, right)((visResultsA, visResultsB) => visResultsA ++ visResultsB) - } map { visResults => - val (succeed, failed) = visResults.partition { case (_, visResult) => visResult.nonEmpty } - val failedTweetIds: Seq[Long] = failed.keys.toSeq - BatchSearchVisibilityResponse( - visibilityResults = succeed.mapValues(visResult => visResult.get), - failedTweetIds = failedTweetIds - ) - } - - val runStitchStartMs = elapsed().inMilliseconds - val buildStitchStatMs = elapsed().inMilliseconds - vfLatencyStitchBuildStat.add(buildStitchStatMs) - - response - .onSuccess(_ => { - val overallMs = elapsed().inMilliseconds - vfLatencyOverallStat.add(overallMs) - val stitchRunMs = elapsed().inMilliseconds - runStitchStartMs - vfLatencyStitchRunStat.add(stitchRunMs) - }) - } - - private def extractContentsToBeEvaluated( - tweetContexts: Seq[TweetContext], - viewerContext: ViewerContext - ): ( - Seq[(TweetContext, EvaluateTweetType, EvaluateTweet, ContentId)], - Seq[ - (RequestTweetId, EvaluateTweetType) - ] - ) = { - val contentsToBeEvaluated: Seq[ - (TweetContext, EvaluateTweetType, EvaluateTweet, ContentId) - ] = tweetContexts.map(tc => - ( - tc, - REQUEST, - tc.tweet, - getContentId( - viewerId = viewerContext.userId, - authorId = tc.tweet.coreData.get.userId, - tweet = tc.tweet))) ++ - tweetContexts - .filter(tc => tc.quotedTweet.nonEmpty).map(tc => - ( - tc, - QUOTED, - tc.quotedTweet.get, - getContentId( - viewerId = viewerContext.userId, - authorId = tc.quotedTweet.get.coreData.get.userId, - tweet = tc.quotedTweet.get))) ++ - tweetContexts - .filter(tc => tc.retweetSourceTweet.nonEmpty).map(tc => - ( - tc, - SOURCE, - tc.retweetSourceTweet.get, - getContentId( - viewerId = viewerContext.userId, - authorId = tc.retweetSourceTweet.get.coreData.get.userId, - tweet = tc.retweetSourceTweet.get))) - - val contentVisResultTypes: Seq[(RequestTweetId, EvaluateTweetType)] = { - contentsToBeEvaluated.map { - case (tc: TweetContext, tweetType: EvaluateTweetType, _, _) => - (tc.tweet.id, tweetType) - } - } - - (contentsToBeEvaluated, contentVisResultTypes) - } - - private def combineVisibilityResult( - visResults: Seq[(RequestTweetId, (EvaluateTweetType, Try[VisibilityResult]))] - ): Option[CombinedVisibilityResult] = { - visResults.sortBy(_._2._1)(ValueOrdering) match { - case Seq( - (_, (REQUEST, Return(requestTweetVisResult))), - (_, (QUOTED, Return(quotedTweetVisResult))), - (_, (SOURCE, Return(sourceTweetVisResult)))) => - requestTweetVisResult.verdict match { - case Allow => - Some(CombinedVisibilityResult(sourceTweetVisResult, Some(quotedTweetVisResult))) - case _ => - Some(CombinedVisibilityResult(requestTweetVisResult, Some(quotedTweetVisResult))) - } - case Seq( - (_, (REQUEST, Return(requestTweetVisResult))), - (_, (QUOTED, Return(quotedTweetVisResult)))) => - Some(CombinedVisibilityResult(requestTweetVisResult, Some(quotedTweetVisResult))) - case Seq( - (_, (REQUEST, Return(requestTweetVisResult))), - (_, (SOURCE, Return(sourceTweetVisResult)))) => - requestTweetVisResult.verdict match { - case Allow => - Some(CombinedVisibilityResult(sourceTweetVisResult, None)) - case _ => - Some(CombinedVisibilityResult(requestTweetVisResult, None)) - } - - case Seq((_, (REQUEST, Return(requestTweetVisResult)))) => - Some(CombinedVisibilityResult(requestTweetVisResult, None)) - case _ => None - } - } - - private def getVisibilityResult( - contents: Seq[(TweetContext, EvaluateTweetType, EvaluateTweet, ContentId)], - safetyLevel: SafetyLevel, - viewerContext: ViewerContext, - svRequestContext: SearchVFRequestContext - ): Stitch[Seq[Try[VisibilityResult]]] = { - - val contentContext: Map[ContentId, (TweetContext, EvaluateTweetType, EvaluateTweet)] = - contents.map { - case ( - tweetContext: TweetContext, - tweetType: EvaluateTweetType, - tweet: EvaluateTweet, - contentId: ContentId) => - contentId -> ((tweetContext, tweetType, tweet)) - }.toMap - - val featureMapProvider: (ContentId, SafetyLevel) => FeatureMap = { - case (contentId: ContentId, _) => - val (tweetContext, tweetType, tweet) = contentContext(contentId) - buildFeatureMap( - evaluatedTweet = tweet, - tweetType = tweetType, - tweetContext = tweetContext, - viewerContext = viewerContext, - svRequestContext = svRequestContext - ) - } - - visibilityLibrary.runRuleEngineBatch( - contentIds = contents.map { case (_, _, _, id: ContentId) => id }, - featureMapProvider = featureMapProvider, - viewerContext = viewerContext, - safetyLevel = safetyLevel - ) - } - - private def getContentId(viewerId: Option[Long], authorId: Long, tweet: Tweet): ContentId = { - if (viewerId.contains(authorId)) - TweetId(tweet.id) - else BlenderTweetId(tweet.id) - } - - private def buildFeatureMap( - evaluatedTweet: Tweet, - tweetType: EvaluateTweetType, - tweetContext: TweetContext, - viewerContext: ViewerContext, - svRequestContext: SearchVFRequestContext - ): FeatureMap = { - val authorId = evaluatedTweet.coreData.get.userId - val viewerId = viewerContext.userId - val isRetweet = - if (tweetType.equals(REQUEST)) tweetContext.retweetSourceTweet.nonEmpty else false - val isSourceTweet = tweetType.equals(SOURCE) - val isQuotedTweet = tweetType.equals(QUOTED) - val tweetMediaKeys: Seq[GenericMediaKey] = evaluatedTweet.media - .getOrElse(Seq.empty) - .flatMap(_.mediaKey.map(GenericMediaKey.apply)) - - visibilityLibrary.featureMapBuilder( - Seq( - viewerFeatures - .forViewerSearchContext(svRequestContext, viewerContext), - relationshipFeatures.forAuthorId(authorId, viewerId), - tweetFeatures.forTweet(evaluatedTweet), - mediaFeatures.forMediaKeys(tweetMediaKeys), - authorFeatures.forAuthorId(authorId), - searchContextFeatures.forSearchContext(svRequestContext), - _.withConstantFeature(TweetIsRetweet, isRetweet), - misinfoPolicyFeatures.forTweet(evaluatedTweet, viewerContext), - exclusiveTweetFeatures.forTweet(evaluatedTweet, viewerContext), - trustedFriendsTweetFeatures.forTweet(evaluatedTweet, viewerId), - editTweetFeatures.forTweet(evaluatedTweet), - _.withConstantFeature(TweetIsInnerQuotedTweet, isQuotedTweet), - _.withConstantFeature(TweetIsSourceTweet, isSourceTweet), - ) - ) - } - - private def handleVisibilityResultByTweetType( - zipVisResult: ((RequestTweetId, EvaluateTweetType), Try[VisibilityResult]) - ): (RequestTweetId, (EvaluateTweetType, Try[VisibilityResult])) = { - zipVisResult match { - case ((id: RequestTweetId, REQUEST), Return(visResult)) => - (id, (REQUEST, Return(handleComposableVisibilityResult(visResult)))) - case ((id: RequestTweetId, QUOTED), Return(visResult)) => - ( - id, - ( - QUOTED, - Return( - handleInnerQuotedTweetVisibilityResult(handleComposableVisibilityResult(visResult))))) - case ((id: RequestTweetId, SOURCE), Return(visResult)) => - (id, (SOURCE, Return(handleComposableVisibilityResult(visResult)))) - case ((id: RequestTweetId, tweetType: EvaluateTweetType), result: Try[VisibilityResult]) => - (id, (tweetType, result)) - } - } - - private def handleComposableVisibilityResult(result: VisibilityResult): VisibilityResult = { - if (result.secondaryVerdicts.nonEmpty) { - result.copy(verdict = composeActions(result.verdict, result.secondaryVerdicts)) - } else { - result - } - } - - private def composeActions(primary: Action, secondary: Seq[Action]): Action = { - if (primary.isComposable && secondary.nonEmpty) { - val actions = Seq[Action] { primary } ++ secondary - val interstitialOpt = Action.getFirstInterstitial(actions: _*) - val softInterventionOpt = Action.getFirstSoftIntervention(actions: _*) - val limitedEngagementsOpt = Action.getFirstLimitedEngagements(actions: _*) - val avoidOpt = Action.getFirstAvoid(actions: _*) - - val numActions = - Seq[Option[_]](interstitialOpt, softInterventionOpt, limitedEngagementsOpt, avoidOpt) - .count(_.isDefined) - if (numActions > 1) { - TweetInterstitial( - interstitialOpt, - softInterventionOpt, - limitedEngagementsOpt, - None, - avoidOpt - ) - } else { - primary - } - } else { - primary - } - } - - private def handleInnerQuotedTweetVisibilityResult( - result: VisibilityResult - ): VisibilityResult = { - val newVerdict: Action = - result.verdict match { - case interstitial: Interstitial => Drop(interstitial.reason) - case ComposableActionsWithInterstitial(tweetInterstitial) => Drop(tweetInterstitial.reason) - case verdict => verdict - } - - result.copy(verdict = newVerdict) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/TweetContext.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/TweetContext.scala deleted file mode 100644 index b2afda131..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/TweetContext.scala +++ /dev/null @@ -1,10 +0,0 @@ -package com.twitter.visibility.interfaces.search - -import com.twitter.tweetypie.thriftscala.Tweet -import com.twitter.visibility.models.SafetyLevel - -case class TweetContext( - tweet: Tweet, - quotedTweet: Option[Tweet], - retweetSourceTweet: Option[Tweet] = None, - safetyLevel: SafetyLevel) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/spaces/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/spaces/BUILD deleted file mode 100644 index ae742d9be..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/spaces/BUILD +++ /dev/null @@ -1,37 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "decider/src/main/scala", - "servo/decider/src/main/scala", - "src/scala/com/twitter/search/blender/services/strato", - "src/thrift/com/twitter/escherbird:media-annotation-structs-scala", - "src/thrift/com/twitter/gizmoduck:user-thrift-scala", - "src/thrift/com/twitter/spam/rtf:safety-level-scala", - "src/thrift/com/twitter/spam/rtf:tweet-rtf-event-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "stitch/stitch-core", - "strato/src/main/scala/com/twitter/strato/client", - "visibility/common/src/main/scala/com/twitter/visibility/common", - "visibility/common/src/main/scala/com/twitter/visibility/common/stitch", - "visibility/lib/src/main/resources/config", - "visibility/lib/src/main/scala/com/twitter/visibility", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/common", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/spaces", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/tweets", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/users", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/configs", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/interfaces/common/tweets", - "visibility/lib/src/main/scala/com/twitter/visibility/rules/providers", - "visibility/lib/src/main/scala/com/twitter/visibility/rules/utils", - "visibility/lib/src/main/scala/com/twitter/visibility/util", - ], - exports = [ - "visibility/common/src/main/scala/com/twitter/visibility/common", - "visibility/lib/src/main/scala/com/twitter/visibility", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/spaces/SpaceVisibilityLibrary.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/spaces/SpaceVisibilityLibrary.scala deleted file mode 100644 index 8d0273095..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/spaces/SpaceVisibilityLibrary.scala +++ /dev/null @@ -1,117 +0,0 @@ -package com.twitter.visibility.interfaces.spaces - -import com.twitter.servo.util.Gate -import com.twitter.stitch.Stitch -import com.twitter.strato.client.{Client => StratoClient} -import com.twitter.visibility.VisibilityLibrary -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.builder.common.MutedKeywordFeatures -import com.twitter.visibility.builder.spaces.SpaceFeatures -import com.twitter.visibility.builder.spaces.StratoSpaceLabelMaps -import com.twitter.visibility.builder.users.AuthorFeatures -import com.twitter.visibility.builder.users.RelationshipFeatures -import com.twitter.visibility.builder.users.ViewerFeatures -import com.twitter.visibility.common._ -import com.twitter.visibility.common.stitch.StitchHelpers -import com.twitter.visibility.features.FeatureMap -import com.twitter.visibility.models.ContentId.SpaceId -import com.twitter.visibility.models.ContentId.SpacePlusUserId -import com.twitter.visibility.rules.EvaluationContext -import com.twitter.visibility.rules.providers.ProvidedEvaluationContext -import com.twitter.visibility.rules.utils.ShimUtils - -object SpaceVisibilityLibrary { - type Type = SpaceVisibilityRequest => Stitch[VisibilityResult] - - def apply( - visibilityLibrary: VisibilityLibrary, - stratoClient: StratoClient, - userSource: UserSource, - userRelationshipSource: UserRelationshipSource, - enableVfFeatureHydrationSpaceShim: Gate[Unit] = Gate.False - ): Type = { - val libraryStatsReceiver = visibilityLibrary.statsReceiver - val stratoClientStatsReceiver = visibilityLibrary.statsReceiver.scope("strato") - val vfLatencyStatsReceiver = visibilityLibrary.statsReceiver.scope("vf_latency") - val vfEngineCounter = libraryStatsReceiver.counter("vf_engine_requests") - - val spaceLabelMaps = new StratoSpaceLabelMaps( - SpaceSafetyLabelMapSource.fromStrato(stratoClient, stratoClientStatsReceiver), - libraryStatsReceiver) - val audioSpaceSource = AudioSpaceSource.fromStrato(stratoClient, stratoClientStatsReceiver) - - val viewerFeatures = new ViewerFeatures(userSource, libraryStatsReceiver) - val authorFeatures = new AuthorFeatures(userSource, libraryStatsReceiver) - val relationshipFeatures = - new RelationshipFeatures(userRelationshipSource, libraryStatsReceiver) - val mutedKeywordFeatures = new MutedKeywordFeatures( - userSource, - userRelationshipSource, - KeywordMatcher.matcher(libraryStatsReceiver), - libraryStatsReceiver, - Gate.False - ) - val spaceFeatures = - new SpaceFeatures( - spaceLabelMaps, - authorFeatures, - relationshipFeatures, - mutedKeywordFeatures, - audioSpaceSource) - - { r: SpaceVisibilityRequest => - vfEngineCounter.incr() - - val isVfFeatureHydrationEnabled = enableVfFeatureHydrationSpaceShim() - val viewerId = r.viewerContext.userId - val authorIds: Option[Seq[Long]] = r.spaceHostAndAdminUserIds - val contentId = { - (viewerId, authorIds) match { - case (Some(viewer), Some(authors)) if authors.contains(viewer) => SpaceId(r.spaceId) - case _ => SpacePlusUserId(r.spaceId) - } - } - - val featureMap = - visibilityLibrary.featureMapBuilder( - Seq( - spaceFeatures.forSpaceAndAuthorIds(r.spaceId, viewerId, authorIds), - viewerFeatures.forViewerContext(r.viewerContext), - ) - ) - - val resp = if (isVfFeatureHydrationEnabled) { - val evaluationContext = ProvidedEvaluationContext.injectRuntimeRulesIntoEvaluationContext( - evaluationContext = EvaluationContext( - r.safetyLevel, - visibilityLibrary.getParams(r.viewerContext, r.safetyLevel), - visibilityLibrary.statsReceiver) - ) - - val preFilteredFeatureMap = - ShimUtils.preFilterFeatureMap(featureMap, r.safetyLevel, contentId, evaluationContext) - - FeatureMap - .resolve(preFilteredFeatureMap, libraryStatsReceiver).flatMap { resolvedFeatureMap => - visibilityLibrary - .runRuleEngine( - contentId, - resolvedFeatureMap, - r.viewerContext, - r.safetyLevel - ) - } - } else { - visibilityLibrary - .runRuleEngine( - contentId, - featureMap, - r.viewerContext, - r.safetyLevel - ) - } - - StitchHelpers.profileStitch(resp, Seq(vfLatencyStatsReceiver)) - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/spaces/SpaceVisibilityRequest.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/spaces/SpaceVisibilityRequest.scala deleted file mode 100644 index 7e8f91269..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/spaces/SpaceVisibilityRequest.scala +++ /dev/null @@ -1,10 +0,0 @@ -package com.twitter.visibility.interfaces.spaces - -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.ViewerContext - -case class SpaceVisibilityRequest( - spaceId: String, - safetyLevel: SafetyLevel, - viewerContext: ViewerContext, - spaceHostAndAdminUserIds: Option[Seq[Long]]) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/BUILD deleted file mode 100644 index 5e9b8cc14..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/BUILD +++ /dev/null @@ -1,47 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/twitter/src/java/com/twitter/logpipeline/client:logpipeline-event-publisher-thin", - "decider/src/main/scala", - "featureswitches/featureswitches-core/src/main/scala", - "mediaservices/media-util/src/main/scala", - "servo/decider/src/main/scala", - "src/thrift/com/twitter/context:twitter-context-scala", - "src/thrift/com/twitter/escherbird:media-annotation-structs-scala", - "src/thrift/com/twitter/gizmoduck:user-thrift-scala", - "src/thrift/com/twitter/spam/rtf:safety-level-scala", - "src/thrift/com/twitter/spam/rtf:tweet-rtf-event-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "stitch/stitch-core", - "strato/src/main/scala/com/twitter/strato/catalog", - "strato/src/main/scala/com/twitter/strato/client", - "twitter-context/src/main/scala", - "visibility/common/src/main/scala/com/twitter/visibility/common", - "visibility/common/src/main/scala/com/twitter/visibility/common/actions/converter/scala", - "visibility/common/src/main/scala/com/twitter/visibility/common/tweets", - "visibility/common/src/main/thrift/com/twitter/visibility/tweets:tweets-scala", - "visibility/lib/src/main/resources/config", - "visibility/lib/src/main/scala/com/twitter/visibility", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/common", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/media", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/tweets", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/users", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/configs", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/generators", - "visibility/lib/src/main/scala/com/twitter/visibility/interfaces/common/tweets", - "visibility/lib/src/main/scala/com/twitter/visibility/interfaces/tweets/enrichments", - "visibility/lib/src/main/scala/com/twitter/visibility/rules/providers", - "visibility/lib/src/main/scala/com/twitter/visibility/rules/utils", - "visibility/lib/src/main/scala/com/twitter/visibility/util", - "visibility/lib/src/main/thrift/com/twitter/visibility/logging:vf-logging-scala", - ], - exports = [ - "visibility/common/src/main/scala/com/twitter/visibility/common", - "visibility/lib/src/main/scala/com/twitter/visibility", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/DeletedTweetVisibilityLibrary.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/DeletedTweetVisibilityLibrary.scala deleted file mode 100644 index 4ebc81ee6..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/DeletedTweetVisibilityLibrary.scala +++ /dev/null @@ -1,59 +0,0 @@ -package com.twitter.visibility.interfaces.tweets - -import com.twitter.decider.Decider -import com.twitter.stitch.Stitch -import com.twitter.visibility.VisibilityLibrary -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.features.TweetDeleteReason -import com.twitter.visibility.features.TweetIsInnerQuotedTweet -import com.twitter.visibility.features.TweetIsRetweet -import com.twitter.visibility.generators.TombstoneGenerator -import com.twitter.visibility.models.ContentId.DeleteTweetId -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.TweetDeleteReason.TweetDeleteReason -import com.twitter.visibility.models.ViewerContext - -object DeletedTweetVisibilityLibrary { - type Type = DeletedTweetVisibilityLibrary.Request => Stitch[VisibilityResult] - - case class Request( - tweetId: Long, - safetyLevel: SafetyLevel, - viewerContext: ViewerContext, - tweetDeleteReason: TweetDeleteReason, - isRetweet: Boolean, - isInnerQuotedTweet: Boolean, - ) - - def apply( - visibilityLibrary: VisibilityLibrary, - decider: Decider, - tombstoneGenerator: TombstoneGenerator, - ): Type = { - val vfEngineCounter = visibilityLibrary.statsReceiver.counter("vf_engine_requests") - - (request: Request) => { - vfEngineCounter.incr() - val contentId = DeleteTweetId(request.tweetId) - val language = request.viewerContext.requestLanguageCode.getOrElse("en") - - val featureMap = - visibilityLibrary.featureMapBuilder( - Seq( - _.withConstantFeature(TweetIsInnerQuotedTweet, request.isInnerQuotedTweet), - _.withConstantFeature(TweetIsRetweet, request.isRetweet), - _.withConstantFeature(TweetDeleteReason, request.tweetDeleteReason) - ) - ) - - visibilityLibrary - .runRuleEngine( - contentId, - featureMap, - request.viewerContext, - request.safetyLevel - ) - .map(tombstoneGenerator(_, language)) - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/QuotedTweetVisibilityLibrary.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/QuotedTweetVisibilityLibrary.scala deleted file mode 100644 index dcdc960fb..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/QuotedTweetVisibilityLibrary.scala +++ /dev/null @@ -1,150 +0,0 @@ -package com.twitter.visibility.interfaces.tweets - -import com.twitter.decider.Decider -import com.twitter.servo.util.Gate -import com.twitter.stitch.Stitch -import com.twitter.visibility.VisibilityLibrary -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.builder.users.AuthorFeatures -import com.twitter.visibility.builder.users.QuotedTweetFeatures -import com.twitter.visibility.builder.users.RelationshipFeatures -import com.twitter.visibility.builder.users.ViewerFeatures -import com.twitter.visibility.common.UserRelationshipSource -import com.twitter.visibility.common.UserSource -import com.twitter.visibility.configapi.configs.VisibilityDeciderGates -import com.twitter.visibility.features.FeatureMap -import com.twitter.visibility.models.ContentId.QuotedTweetRelationship -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.UserUnavailableStateEnum -import com.twitter.visibility.models.ViewerContext -import com.twitter.visibility.rules.Drop -import com.twitter.visibility.rules.EvaluationContext -import com.twitter.visibility.rules.Reason.AuthorBlocksViewer -import com.twitter.visibility.rules.Reason.DeactivatedAuthor -import com.twitter.visibility.rules.Reason.ErasedAuthor -import com.twitter.visibility.rules.Reason.OffboardedAuthor -import com.twitter.visibility.rules.Reason.ProtectedAuthor -import com.twitter.visibility.rules.Reason.SuspendedAuthor -import com.twitter.visibility.rules.Reason.ViewerBlocksAuthor -import com.twitter.visibility.rules.Reason.ViewerHardMutedAuthor -import com.twitter.visibility.rules.Reason.ViewerMutesAuthor -import com.twitter.visibility.rules.providers.ProvidedEvaluationContext -import com.twitter.visibility.rules.utils.ShimUtils - -case class TweetAndAuthor(tweetId: Long, authorId: Long) - -case class QuotedTweetVisibilityRequest( - quotedTweet: TweetAndAuthor, - outerTweet: TweetAndAuthor, - viewerContext: ViewerContext, - safetyLevel: SafetyLevel) - -object QuotedTweetVisibilityLibrary { - - type Type = QuotedTweetVisibilityRequest => Stitch[VisibilityResult] - - def apply( - visibilityLibrary: VisibilityLibrary, - userSource: UserSource, - userRelationshipSource: UserRelationshipSource, - decider: Decider, - userStateVisibilityLibrary: UserUnavailableStateVisibilityLibrary.Type, - enableVfFeatureHydration: Gate[Unit] = Gate.False - ): Type = { - val libraryStatsReceiver = visibilityLibrary.statsReceiver - val visibilityDeciderGates = VisibilityDeciderGates(decider) - val vfEngineCounter = libraryStatsReceiver.counter("vf_engine_requests") - - { - case QuotedTweetVisibilityRequest(quotedTweet, outerTweet, viewerContext, safetyLevel) => - vfEngineCounter.incr() - val contentId = QuotedTweetRelationship( - outer = outerTweet.tweetId, - inner = quotedTweet.tweetId - ) - - val innerAuthorId = quotedTweet.authorId - val outerAuthorId = outerTweet.authorId - val viewerId = viewerContext.userId - val isFeatureHydrationInShimEnabled = enableVfFeatureHydration() - - val authorFeatures = new AuthorFeatures(userSource, libraryStatsReceiver) - val viewerFeatures = new ViewerFeatures(userSource, libraryStatsReceiver) - val relationshipFeatures = - new RelationshipFeatures(userRelationshipSource, libraryStatsReceiver) - val quotedTweetFeatures = - new QuotedTweetFeatures(relationshipFeatures, libraryStatsReceiver) - - val featureMap = visibilityLibrary.featureMapBuilder( - Seq( - viewerFeatures.forViewerContext(viewerContext), - authorFeatures.forAuthorId(innerAuthorId), - relationshipFeatures.forAuthorId(innerAuthorId, viewerId), - quotedTweetFeatures.forOuterAuthor(outerAuthorId, innerAuthorId) - ) - ) - - val resp = if (isFeatureHydrationInShimEnabled) { - val evaluationContext = ProvidedEvaluationContext.injectRuntimeRulesIntoEvaluationContext( - evaluationContext = EvaluationContext( - SafetyLevel.QuotedTweetRules, - visibilityLibrary.getParams(viewerContext, SafetyLevel.QuotedTweetRules), - visibilityLibrary.statsReceiver) - ) - - val preFilteredFeatureMap = - ShimUtils.preFilterFeatureMap( - featureMap, - SafetyLevel.QuotedTweetRules, - contentId, - evaluationContext) - - FeatureMap.resolve(preFilteredFeatureMap, libraryStatsReceiver).flatMap { - resolvedFeatureMap => - visibilityLibrary - .runRuleEngine( - contentId, - resolvedFeatureMap, - viewerContext, - SafetyLevel.QuotedTweetRules - ) - } - } else { - visibilityLibrary - .runRuleEngine( - contentId, - featureMap, - viewerContext, - SafetyLevel.QuotedTweetRules - ) - } - - resp.flatMap { visResult => - val userStateOpt = visResult.verdict match { - case Drop(DeactivatedAuthor, _) => Some(UserUnavailableStateEnum.Deactivated) - case Drop(OffboardedAuthor, _) => Some(UserUnavailableStateEnum.Offboarded) - case Drop(ErasedAuthor, _) => Some(UserUnavailableStateEnum.Erased) - case Drop(ProtectedAuthor, _) => Some(UserUnavailableStateEnum.Protected) - case Drop(SuspendedAuthor, _) => Some(UserUnavailableStateEnum.Suspended) - case Drop(AuthorBlocksViewer, _) => Some(UserUnavailableStateEnum.AuthorBlocksViewer) - case Drop(ViewerBlocksAuthor, _) => Some(UserUnavailableStateEnum.ViewerBlocksAuthor) - case Drop(ViewerMutesAuthor, _) => Some(UserUnavailableStateEnum.ViewerMutesAuthor) - case Drop(ViewerHardMutedAuthor, _) => Some(UserUnavailableStateEnum.ViewerMutesAuthor) - case _ => None - } - - userStateOpt - .map(userState => - userStateVisibilityLibrary( - UserUnavailableStateVisibilityRequest( - safetyLevel, - quotedTweet.tweetId, - viewerContext, - userState, - isRetweet = false, - isInnerQuotedTweet = true, - ))).getOrElse(Stitch.value(visResult)) - } - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/TweetVisibilityLibrary.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/TweetVisibilityLibrary.scala deleted file mode 100644 index 09d717b76..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/TweetVisibilityLibrary.scala +++ /dev/null @@ -1,421 +0,0 @@ -package com.twitter.visibility.interfaces.tweets - -import com.twitter.decider.Decider -import com.twitter.featureswitches.v2.FeatureSwitches -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.mediaservices.media_util.GenericMediaKey -import com.twitter.servo.util.Gate -import com.twitter.stitch.Stitch -import com.twitter.strato.client.{Client => StratoClient} -import com.twitter.util.Stopwatch -import com.twitter.visibility.VisibilityLibrary -import com.twitter.visibility.builder.VerdictLogger -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.builder.common.MutedKeywordFeatures -import com.twitter.visibility.builder.media._ -import com.twitter.visibility.builder.tweets.TweetVisibilityNudgeSourceWrapper -import com.twitter.visibility.builder.tweets._ -import com.twitter.visibility.builder.users.AuthorFeatures -import com.twitter.visibility.builder.users.RelationshipFeatures -import com.twitter.visibility.builder.users.ViewerFeatures -import com.twitter.visibility.builder.users.ViewerSearchSafetyFeatures -import com.twitter.visibility.builder.users.ViewerSensitiveMediaSettingsFeatures -import com.twitter.visibility.common._ -import com.twitter.visibility.common.actions.LimitedAction -import com.twitter.visibility.common.actions.LimitedActionType -import com.twitter.visibility.common.actions.LimitedActionsPolicy -import com.twitter.visibility.rules.ComposableActions._ -import com.twitter.visibility.configapi.configs.VisibilityDeciderGates -import com.twitter.visibility.features.TweetIsInnerQuotedTweet -import com.twitter.visibility.features.TweetIsRetweet -import com.twitter.visibility.features.TweetIsSourceTweet -import com.twitter.visibility.generators.LocalizedInterstitialGenerator -import com.twitter.visibility.generators.TombstoneGenerator -import com.twitter.visibility.interfaces.tweets.enrichments.ComplianceTweetNoticeEnrichment -import com.twitter.visibility.interfaces.tweets.enrichments.LimitedActionsPolicyEnrichment -import com.twitter.visibility.interfaces.tweets.enrichments.TweetVisibilityNudgeEnrichment -import com.twitter.visibility.logging.thriftscala.VFLibType -import com.twitter.visibility.models.ContentId.TweetId -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.SafetyLevel.toThrift -import com.twitter.visibility.rules._ - -object TweetVisibilityLibrary { - type Type = TweetVisibilityRequest => Stitch[VisibilityResult] - - def apply( - visibilityLibrary: VisibilityLibrary, - userSource: UserSource, - userRelationshipSource: UserRelationshipSource, - keywordMatcher: KeywordMatcher.Matcher, - invitedToConversationRepo: InvitedToConversationRepo, - decider: Decider, - stratoClient: StratoClient, - localizationSource: LocalizationSource, - tweetPerspectiveSource: TweetPerspectiveSource, - tweetMediaMetadataSource: TweetMediaMetadataSource, - tombstoneGenerator: TombstoneGenerator, - interstitialGenerator: LocalizedInterstitialGenerator, - limitedActionsFeatureSwitches: FeatureSwitches, - enableParityTest: Gate[Unit] = Gate.False - ): Type = { - val libraryStatsReceiver = visibilityLibrary.statsReceiver - val stratoClientStatsReceiver = visibilityLibrary.statsReceiver.scope("strato") - val vfEngineCounter = libraryStatsReceiver.counter("vf_engine_requests") - val vfLatencyOverallStat = libraryStatsReceiver.stat("vf_latency_overall") - val vfLatencyStitchBuildStat = libraryStatsReceiver.stat("vf_latency_stitch_build") - val vfLatencyStitchRunStat = libraryStatsReceiver.stat("vf_latency_stitch_run") - val visibilityDeciderGates = VisibilityDeciderGates(decider) - val verdictLogger = - createVerdictLogger( - visibilityDeciderGates.enableVerdictLoggerTVL, - decider, - libraryStatsReceiver) - - val tweetLabelMaps = new StratoTweetLabelMaps( - SafetyLabelMapSource.fromStrato(stratoClient, stratoClientStatsReceiver)) - - val mediaLabelMaps = new StratoMediaLabelMaps( - MediaSafetyLabelMapSource.fromStrato(stratoClient, stratoClientStatsReceiver)) - - val tweetFeatures = new TweetFeatures(tweetLabelMaps, libraryStatsReceiver) - val tweetPerspectiveFeatures = - new TweetPerspectiveFeatures(tweetPerspectiveSource, libraryStatsReceiver) - val mediaFeatures = new MediaFeatures(mediaLabelMaps, libraryStatsReceiver) - val tweetMediaMetadataFeatures = - new TweetMediaMetadataFeatures(tweetMediaMetadataSource, libraryStatsReceiver) - val authorFeatures = new AuthorFeatures(userSource, libraryStatsReceiver) - val viewerFeatures = new ViewerFeatures(userSource, libraryStatsReceiver) - val mutedKeywordFeatures = - new MutedKeywordFeatures( - userSource, - userRelationshipSource, - keywordMatcher, - libraryStatsReceiver, - visibilityDeciderGates.enableFollowCheckInMutedKeyword - ) - val relationshipFeatures = - new RelationshipFeatures(userRelationshipSource, libraryStatsReceiver) - val fonsrRelationshipFeatures = - new FosnrRelationshipFeatures( - tweetLabels = tweetLabelMaps, - userRelationshipSource = userRelationshipSource, - statsReceiver = libraryStatsReceiver) - val conversationControlFeatures = - new ConversationControlFeatures( - relationshipFeatures, - invitedToConversationRepo, - libraryStatsReceiver - ) - val exclusiveTweetFeatures = - new ExclusiveTweetFeatures(userRelationshipSource, libraryStatsReceiver) - - val viewerSearchSafetyFeatures = new ViewerSearchSafetyFeatures( - UserSearchSafetySource.fromStrato(stratoClient, stratoClientStatsReceiver), - libraryStatsReceiver) - - val viewerSensitiveMediaSettingsFeatures = new ViewerSensitiveMediaSettingsFeatures( - UserSensitiveMediaSettingsSource.fromStrato(stratoClient, stratoClientStatsReceiver), - libraryStatsReceiver) - - val toxicReplyFilterFeature = new ToxicReplyFilterFeature(statsReceiver = libraryStatsReceiver) - - val misinfoPolicySource = - MisinformationPolicySource.fromStrato(stratoClient, stratoClientStatsReceiver) - val misinfoPolicyFeatures = - new MisinformationPolicyFeatures(misinfoPolicySource, stratoClientStatsReceiver) - - val communityTweetFeatures = new CommunityTweetFeaturesV2( - communitiesSource = CommunitiesSource.fromStrato( - stratoClient, - stratoClientStatsReceiver - ) - ) - - val trustedFriendsTweetFeatures = new TrustedFriendsFeatures( - trustedFriendsSource = - TrustedFriendsSource.fromStrato(stratoClient, stratoClientStatsReceiver)) - - val editTweetFeatures = new EditTweetFeatures(libraryStatsReceiver) - - val parityTest = new TweetVisibilityLibraryParityTest(libraryStatsReceiver, stratoClient) - - val localizedNudgeSource = - LocalizedNudgeSource.fromLocalizationSource(localizationSource) - val tweetVisibilityNudgeFeatures = - new TweetVisibilityNudgeSourceWrapper(localizedNudgeSource) - - val localizedLimitedActionsSource = - LocalizedLimitedActionsSource.fromLocalizationSource(localizationSource) - - { r: TweetVisibilityRequest => - val elapsed = Stopwatch.start() - var runStitchStartMs = 0L - vfEngineCounter.incr() - - val contentId = TweetId(r.tweet.id) - val viewerId = r.viewerContext.userId - val authorId = coreData.userId - val tweetGenericMediaKeys = r.tweet.mediaRefs - .getOrElse(Seq.empty) - .flatMap { mediaRef => - GenericMediaKey.fromStringKey(mediaRef.genericMediaKey) - } - - val tpf = - tweetPerspectiveFeatures.forTweet( - r.tweet, - viewerId, - visibilityDeciderGates.enableFetchTweetReportedPerspective()) - - val featureMap = - visibilityLibrary.featureMapBuilder( - Seq( - mutedKeywordFeatures.forTweet(r.tweet, viewerId, authorId), - viewerFeatures.forViewerContext(r.viewerContext), - viewerSearchSafetyFeatures.forViewerId(viewerId), - viewerSensitiveMediaSettingsFeatures.forViewerId(viewerId), - relationshipFeatures.forAuthorId(authorId, viewerId), - fonsrRelationshipFeatures - .forTweetAndAuthorId(tweet = r.tweet, authorId = authorId, viewerId = viewerId), - tweetFeatures.forTweet(r.tweet), - tpf, - mediaFeatures.forMediaKeys(tweetGenericMediaKeys), - authorFeatures.forAuthorId(authorId), - conversationControlFeatures.forTweet(r.tweet, viewerId), - _.withConstantFeature(TweetIsInnerQuotedTweet, r.isInnerQuotedTweet), - _.withConstantFeature(TweetIsRetweet, r.isRetweet), - _.withConstantFeature(TweetIsSourceTweet, r.isSourceTweet), - misinfoPolicyFeatures.forTweet(r.tweet, r.viewerContext), - exclusiveTweetFeatures.forTweet(r.tweet, r.viewerContext), - communityTweetFeatures.forTweet(r.tweet, r.viewerContext), - tweetMediaMetadataFeatures - .forTweet( - r.tweet, - tweetGenericMediaKeys, - visibilityDeciderGates.enableFetchTweetMediaMetadata()), - trustedFriendsTweetFeatures.forTweet(r.tweet, viewerId), - editTweetFeatures.forTweet(r.tweet), - toxicReplyFilterFeature.forTweet(r.tweet, viewerId), - ) - ) - - val languageCode = r.viewerContext.requestLanguageCode.getOrElse("en") - val countryCode = r.viewerContext.requestCountryCode - - val response = visibilityLibrary - .runRuleEngine( - contentId, - featureMap, - r.viewerContext, - r.safetyLevel - ) - .map( - TweetVisibilityNudgeEnrichment( - _, - tweetVisibilityNudgeFeatures, - languageCode, - countryCode)) - .map(verdict => { - if (visibilityDeciderGates.enableBackendLimitedActions()) { - LimitedActionsPolicyEnrichment( - verdict, - localizedLimitedActionsSource, - languageCode, - countryCode, - limitedActionsFeatureSwitches, - libraryStatsReceiver) - } else { - verdict - } - }) - .map( - handleComposableVisibilityResult( - _, - visibilityDeciderGates.enableMediaInterstitialComposition(), - visibilityDeciderGates.enableBackendLimitedActions())) - .map(handleInnerQuotedTweetVisibilityResult(_, r.isInnerQuotedTweet)) - .map(tombstoneGenerator(_, languageCode)) - .map(interstitialGenerator(_, languageCode)) - .map(ComplianceTweetNoticeEnrichment(_, libraryStatsReceiver)) - .onSuccess(_ => { - val overallStatMs = elapsed().inMilliseconds - vfLatencyOverallStat.add(overallStatMs) - val runStitchEndMs = elapsed().inMilliseconds - vfLatencyStitchRunStat.add(runStitchEndMs - runStitchStartMs) - }) - .onSuccess( - scribeVisibilityVerdict( - _, - visibilityDeciderGates.enableVerdictScribingTVL, - verdictLogger, - r.viewerContext.userId, - r.safetyLevel)) - - runStitchStartMs = elapsed().inMilliseconds - val buildStitchStatMs = elapsed().inMilliseconds - vfLatencyStitchBuildStat.add(buildStitchStatMs) - - if (enableParityTest()) { - response.applyEffect { resp => - Stitch.async(parityTest.runParityTest(r, resp)) - } - } else { - response - } - } - } - - def handleComposableVisibilityResult( - result: VisibilityResult, - enableMediaInterstitialComposition: Boolean, - enableBackendLimitedActions: Boolean - ): VisibilityResult = { - if (result.secondaryVerdicts.nonEmpty || enableBackendLimitedActions) { - result.copy(verdict = composeActions( - result.verdict, - result.secondaryVerdicts, - enableMediaInterstitialComposition, - enableBackendLimitedActions)) - } else { - result - } - } - - def handleInnerQuotedTweetVisibilityResult( - result: VisibilityResult, - isInnerQuotedTweet: Boolean - ): VisibilityResult = { - val newVerdict: Action = - result.verdict match { - case Interstitial(Reason.Nsfw | Reason.NsfwMedia, _, _) if isInnerQuotedTweet => - Drop(Reason.Nsfw) - case ComposableActionsWithInterstitial(tweetInterstitial) - if isInnerQuotedTweet && (tweetInterstitial.reason == Reason.Nsfw || tweetInterstitial.reason == Reason.NsfwMedia) => - Drop(Reason.Nsfw) - case verdict => verdict - } - - result.copy(verdict = newVerdict) - } - - def hasTweetRules(safetyLevel: SafetyLevel): Boolean = RuleBase.hasTweetRules(safetyLevel) - - def composeActions( - primary: Action, - secondary: Seq[Action], - enableMediaInterstitialComposition: Boolean, - enableBackendLimitedActions: Boolean - ): Action = { - if (primary.isComposable && (secondary.nonEmpty || enableBackendLimitedActions)) { - val actions = Seq[Action] { primary } ++ secondary - val interstitialOpt = Action.getFirstInterstitial(actions: _*) - val softInterventionOpt = Action.getFirstSoftIntervention(actions: _*) - val downrankOpt = Action.getFirstDownrankHomeTimeline(actions: _*) - val avoidOpt = Action.getFirstAvoid(actions: _*) - val tweetVisibilityNudgeOpt = Action.getFirstTweetVisibilityNudge(actions: _*) - - val mediaInterstitialOpt = { - val firstMediaInterstitialOpt = Action.getFirstMediaInterstitial(actions: _*) - if (enableMediaInterstitialComposition && interstitialOpt != firstMediaInterstitialOpt) { - firstMediaInterstitialOpt - } else { - None - } - } - - val limitedEngagementsOpt = enableBackendLimitedActions match { - case true => buildCompositeLimitedEngagements(Action.getAllLimitedEngagements(actions: _*)) - case false => Action.getFirstLimitedEngagements(actions: _*) - } - - val abusiveQualityOpt = { - if (actions.contains(ConversationSectionAbusiveQuality)) { - Some(ConversationSectionAbusiveQuality) - } else { - None - } - } - - val numActions = - Seq[Option[_]]( - interstitialOpt, - softInterventionOpt, - limitedEngagementsOpt, - downrankOpt, - avoidOpt, - mediaInterstitialOpt, - tweetVisibilityNudgeOpt, - abusiveQualityOpt) - .count(_.isDefined) - if (numActions > 1) { - TweetInterstitial( - interstitialOpt, - softInterventionOpt, - limitedEngagementsOpt, - downrankOpt, - avoidOpt, - mediaInterstitialOpt, - tweetVisibilityNudgeOpt, - abusiveQualityOpt - ) - } else { - if (enableBackendLimitedActions) { - limitedEngagementsOpt.getOrElse(primary) - } else { - primary - } - } - } else { - primary - } - } - - def scribeVisibilityVerdict( - result: VisibilityResult, - enableVerdictScribing: Gate[Unit], - verdictLogger: VerdictLogger, - viewerId: Option[Long], - safetyLevel: SafetyLevel - ): Unit = if (enableVerdictScribing()) { - verdictLogger.scribeVerdict( - visibilityResult = result, - viewerId = viewerId, - safetyLevel = toThrift(safetyLevel), - vfLibType = VFLibType.TweetVisibilityLibrary) - } - - def buildCompositeLimitedEngagements( - limitedEngagements: Seq[IsLimitedEngagements] - ): Option[LimitedEngagements] = { - limitedEngagements.headOption.flatMap { limitedEngagement => - val distinctLimitedActions = limitedEngagements - .collect({ case IsLimitedEngagements(Some(policy), _) => policy.limitedActions }) - .flatten - .foldRight(Map.empty[LimitedActionType, LimitedAction])({ (limitedAction, acc) => - acc + ((limitedAction.limitedActionType, limitedAction)) - }) - .values - .toSeq - - if (distinctLimitedActions.nonEmpty) { - val limitedActionsPolicy = Some(LimitedActionsPolicy(distinctLimitedActions)) - Some(LimitedEngagements(limitedEngagement.getLimitedEngagementReason, limitedActionsPolicy)) - } else { - None - } - } - } - - def createVerdictLogger( - enableVerdictLogger: Gate[Unit], - decider: Decider, - statsReceiver: StatsReceiver - ): VerdictLogger = { - if (enableVerdictLogger()) { - VerdictLogger(statsReceiver, decider) - } else { - VerdictLogger.Empty - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/TweetVisibilityLibraryParityTest.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/TweetVisibilityLibraryParityTest.scala deleted file mode 100644 index 621ed9f9b..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/TweetVisibilityLibraryParityTest.scala +++ /dev/null @@ -1,109 +0,0 @@ -package com.twitter.visibility.interfaces.tweets - -import com.twitter.spam.rtf.{thriftscala => t} -import com.twitter.context.TwitterContext -import com.twitter.context.thriftscala.Viewer -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.stitch.Stitch -import com.twitter.strato.catalog.Fetch -import com.twitter.strato.client.Client -import com.twitter.strato.client.Fetcher -import com.twitter.strato.thrift.ScroogeConvImplicits._ -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.common.tweets.TweetVisibilityResultMapper -import com.twitter.visibility.models.SafetyLevel.toThrift -import com.twitter.visibility.models.ViewerContext -import com.twitter.visibility.thriftscala.TweetVisibilityResult - -class TweetVisibilityLibraryParityTest(statsReceiver: StatsReceiver, stratoClient: Client) { - - private val parityTestScope = statsReceiver.scope("tweet_visibility_library_parity") - private val requests = parityTestScope.counter("requests") - private val equal = parityTestScope.counter("equal") - private val incorrect = parityTestScope.counter("incorrect") - private val empty = parityTestScope.counter("empty") - private val failures = parityTestScope.counter("failures") - - private val fetcher: Fetcher[Long, t.SafetyLevel, TweetVisibilityResult] = - stratoClient.fetcher[Long, t.SafetyLevel, TweetVisibilityResult]( - "visibility/service/TweetVisibilityResult.Tweet" - ) - - def runParityTest( - req: TweetVisibilityRequest, - resp: VisibilityResult - ): Stitch[Unit] = { - requests.incr() - - val twitterContext = TwitterContext(TwitterContextPermit) - - val viewer: Option[Viewer] = { - - val remoteViewerContext = ViewerContext.fromContext - - if (remoteViewerContext != req.viewerContext) { - val updatedRemoteViewerContext = remoteViewerContext.copy( - userId = req.viewerContext.userId - ) - - if (updatedRemoteViewerContext == req.viewerContext) { - twitterContext() match { - case None => - Some(Viewer(userId = req.viewerContext.userId)) - case Some(v) => - Some(v.copy(userId = req.viewerContext.userId)) - } - } else { - None - } - } else { - None - } - } - - val tweetypieContext = TweetypieContext( - isQuotedTweet = req.isInnerQuotedTweet, - isRetweet = req.isRetweet, - hydrateConversationControl = req.hydrateConversationControl - ) - - val parityCheck: Stitch[Fetch.Result[TweetVisibilityResult]] = { - Stitch.callFuture { - TweetypieContext.let(tweetypieContext) { - viewer match { - case Some(viewer) => - twitterContext.let(viewer) { - Stitch.run(fetcher.fetch(req.tweet.id, toThrift(req.safetyLevel))) - } - case None => - Stitch.run(fetcher.fetch(req.tweet.id, toThrift(req.safetyLevel))) - } - } - } - } - - parityCheck - .flatMap { parityResponse => - val tvr = TweetVisibilityResultMapper.fromAction(resp.verdict.toActionThrift()) - - parityResponse.v match { - case Some(ptvr) => - if (tvr == ptvr) { - equal.incr() - } else { - incorrect.incr() - } - - case None => - empty.incr() - } - - Stitch.Done - }.rescue { - case t: Throwable => - failures.incr() - Stitch.Done - - }.unit - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/TweetVisibilityRequest.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/TweetVisibilityRequest.scala deleted file mode 100644 index d10b28082..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/TweetVisibilityRequest.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.visibility.interfaces.tweets - -import com.twitter.tweetypie.thriftscala.Tweet -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.ViewerContext - -case class TweetVisibilityRequest( - tweet: Tweet, - safetyLevel: SafetyLevel, - viewerContext: ViewerContext, - isInnerQuotedTweet: Boolean, - isRetweet: Boolean, - hydrateConversationControl: Boolean = false, - isSourceTweet: Boolean = false) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/TweetypieContext.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/TweetypieContext.scala deleted file mode 100644 index e7178bb20..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/TweetypieContext.scala +++ /dev/null @@ -1,59 +0,0 @@ -package com.twitter.visibility.interfaces.tweets - -import com.twitter.finagle.context.Contexts -import com.twitter.io.Buf -import com.twitter.io.BufByteWriter -import com.twitter.io.ByteReader -import com.twitter.util.Future -import com.twitter.util.Return -import com.twitter.util.Throw -import com.twitter.util.Try - -case class TweetypieContext( - isQuotedTweet: Boolean, - isRetweet: Boolean, - hydrateConversationControl: Boolean) - -object TweetypieContext { - - def let[U](value: TweetypieContext)(f: => Future[U]): Future[U] = - Contexts.broadcast.let(TweetypieContextKey, value)(f) - - def get(): Option[TweetypieContext] = - Contexts.broadcast.get(TweetypieContextKey) -} - -object TweetypieContextKey - extends Contexts.broadcast.Key[TweetypieContext]( - "com.twitter.visibility.interfaces.tweets.TweetypieContext" - ) { - - override def marshal(value: TweetypieContext): Buf = { - val bw = BufByteWriter.fixed(1) - val byte = - ((if (value.isQuotedTweet) 1 else 0) << 0) | - ((if (value.isRetweet) 1 else 0) << 1) | - ((if (value.hydrateConversationControl) 1 else 0) << 2) - bw.writeByte(byte) - bw.owned() - } - - override def tryUnmarshal(buf: Buf): Try[TweetypieContext] = { - if (buf.length != 1) { - Throw( - new IllegalArgumentException( - s"Could not extract Boolean from Buf. Length ${buf.length} but required 1" - ) - ) - } else { - val byte: Byte = ByteReader(buf).readByte() - Return( - TweetypieContext( - isQuotedTweet = ((byte & 1) == 1), - isRetweet = ((byte & 2) == 2), - hydrateConversationControl = ((byte & 4) == 4) - ) - ) - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/UserUnavailableStateVisibilityLibrary.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/UserUnavailableStateVisibilityLibrary.scala deleted file mode 100644 index 959c76812..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/UserUnavailableStateVisibilityLibrary.scala +++ /dev/null @@ -1,138 +0,0 @@ -package com.twitter.visibility.interfaces.tweets - -import com.twitter.decider.Decider -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.stitch.Stitch -import com.twitter.visibility.VisibilityLibrary -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.builder.users.UserUnavailableFeatures -import com.twitter.visibility.common.actions.converter.scala.DropReasonConverter -import com.twitter.visibility.configapi.configs.VisibilityDeciderGates -import com.twitter.visibility.features.TweetIsInnerQuotedTweet -import com.twitter.visibility.features.TweetIsRetweet -import com.twitter.visibility.generators.LocalizedInterstitialGenerator -import com.twitter.visibility.generators.TombstoneGenerator -import com.twitter.visibility.models.ContentId.UserUnavailableState -import com.twitter.visibility.models.UserUnavailableStateEnum -import com.twitter.visibility.rules.Drop -import com.twitter.visibility.rules.Interstitial -import com.twitter.visibility.rules.Reason -import com.twitter.visibility.rules.Tombstone -import com.twitter.visibility.thriftscala.UserVisibilityResult - -object UserUnavailableStateVisibilityLibrary { - type Type = UserUnavailableStateVisibilityRequest => Stitch[VisibilityResult] - - def apply( - visibilityLibrary: VisibilityLibrary, - decider: Decider, - tombstoneGenerator: TombstoneGenerator, - interstitialGenerator: LocalizedInterstitialGenerator - ): Type = { - val libraryStatsReceiver = visibilityLibrary.statsReceiver.scope("user_unavailable_vis_library") - val defaultDropScope = visibilityLibrary.statsReceiver.scope("default_drop") - val vfEngineCounter = libraryStatsReceiver.counter("vf_engine_requests") - - val userUnavailableFeatures = UserUnavailableFeatures(libraryStatsReceiver) - val visibilityDeciderGates = VisibilityDeciderGates(decider) - - { r: UserUnavailableStateVisibilityRequest => - vfEngineCounter.incr() - val contentId = UserUnavailableState(r.tweetId) - - val featureMap = - visibilityLibrary.featureMapBuilder( - Seq( - _.withConstantFeature(TweetIsInnerQuotedTweet, r.isInnerQuotedTweet), - _.withConstantFeature(TweetIsRetweet, r.isRetweet), - userUnavailableFeatures.forState(r.userUnavailableState) - ) - ) - - val language = r.viewerContext.requestLanguageCode.getOrElse("en") - - val reason = visibilityLibrary - .runRuleEngine( - contentId, - featureMap, - r.viewerContext, - r.safetyLevel - ).map(defaultToDrop(r.userUnavailableState, defaultDropScope)) - .map(tombstoneGenerator(_, language)) - .map(visibilityResult => { - if (visibilityDeciderGates.enableLocalizedInterstitialInUserStateLibrary()) { - interstitialGenerator(visibilityResult, language) - } else { - visibilityResult - } - }) - - reason - } - } - - def defaultToDrop( - userUnavailableState: UserUnavailableStateEnum, - defaultDropScope: StatsReceiver - )( - result: VisibilityResult - ): VisibilityResult = - result.verdict match { - case _: Drop | _: Tombstone => result - - case _: Interstitial => result - case _ => - result.copy(verdict = - Drop(userUnavailableStateToDropReason(userUnavailableState, defaultDropScope))) - } - - private[this] def userUnavailableStateToDropReason( - userUnavailableState: UserUnavailableStateEnum, - stats: StatsReceiver - ): Reason = - userUnavailableState match { - case UserUnavailableStateEnum.Erased => - stats.counter("erased").incr() - Reason.ErasedAuthor - case UserUnavailableStateEnum.Protected => - stats.counter("protected").incr() - Reason.ProtectedAuthor - case UserUnavailableStateEnum.Offboarded => - stats.counter("offboarded").incr() - Reason.OffboardedAuthor - case UserUnavailableStateEnum.AuthorBlocksViewer => - stats.counter("author_blocks_viewer").incr() - Reason.AuthorBlocksViewer - case UserUnavailableStateEnum.Suspended => - stats.counter("suspended_author").incr() - Reason.SuspendedAuthor - case UserUnavailableStateEnum.Deactivated => - stats.counter("deactivated_author").incr() - Reason.DeactivatedAuthor - case UserUnavailableStateEnum.Filtered(result) => - stats.counter("filtered").incr() - userVisibilityResultToDropReason(result, stats.scope("filtered")) - case UserUnavailableStateEnum.Unavailable => - stats.counter("unspecified").incr() - Reason.Unspecified - case _ => - stats.counter("unknown").incr() - stats.scope("unknown").counter(userUnavailableState.name).incr() - Reason.Unspecified - } - - private[this] def userVisibilityResultToDropReason( - result: UserVisibilityResult, - stats: StatsReceiver - ): Reason = - result.action - .flatMap(DropReasonConverter.fromAction) - .map { dropReason => - val reason = Reason.fromDropReason(dropReason) - stats.counter(reason.name).incr() - reason - }.getOrElse { - stats.counter("empty") - Reason.Unspecified - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/UserUnavailableStateVisibilityRequest.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/UserUnavailableStateVisibilityRequest.scala deleted file mode 100644 index b419859f6..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/UserUnavailableStateVisibilityRequest.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.visibility.interfaces.tweets - -import com.twitter.visibility.models.UserUnavailableStateEnum -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.ViewerContext - -case class UserUnavailableStateVisibilityRequest( - safetyLevel: SafetyLevel, - tweetId: Long, - viewerContext: ViewerContext, - userUnavailableState: UserUnavailableStateEnum, - isRetweet: Boolean, - isInnerQuotedTweet: Boolean, -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/enrichments/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/enrichments/BUILD deleted file mode 100644 index fcf16cd5a..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/enrichments/BUILD +++ /dev/null @@ -1,25 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "featureswitches/featureswitches-core/src/main/scala", - "src/thrift/com/twitter/spam/rtf:safety-result-scala", - "stitch/stitch-core", - "visibility/common/src/main/scala/com/twitter/visibility/common", - "visibility/common/src/main/scala/com/twitter/visibility/common/actions", - "visibility/common/src/main/scala/com/twitter/visibility/common/actions/converter/scala", - "visibility/lib/src/main/scala/com/twitter/visibility", - "visibility/lib/src/main/scala/com/twitter/visibility/builder", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/tweets", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/rules", - "visibility/results/src/main/scala/com/twitter/visibility/results/richtext", - ], - exports = [ - "featureswitches/featureswitches-core/src/main/scala", - "visibility/lib/src/main/scala/com/twitter/visibility/builder", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/enrichments/ComplianceTweetNoticeEnrichment.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/enrichments/ComplianceTweetNoticeEnrichment.scala deleted file mode 100644 index a38459068..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/enrichments/ComplianceTweetNoticeEnrichment.scala +++ /dev/null @@ -1,55 +0,0 @@ -package com.twitter.visibility.interfaces.tweets.enrichments - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.results.richtext.PublicInterestReasonToPlainText -import com.twitter.visibility.rules.Action -import com.twitter.visibility.rules.ComplianceTweetNoticePreEnrichment -import com.twitter.visibility.rules.PublicInterest -import com.twitter.visibility.rules.Reason - -object ComplianceTweetNoticeEnrichment { - val ComplianceTweetNoticeEnrichmentScope = "compliance_tweet_notice_enrichment" - val ComplianceTweetNoticePreEnrichmentActionScope = - "compliance_tweet_notice_pre_enrichment_action" - - val englishLanguageTag = "en" - - def apply(result: VisibilityResult, statsReceiver: StatsReceiver): VisibilityResult = { - val scopedStatsReceiver = statsReceiver.scope(ComplianceTweetNoticeEnrichmentScope) - - val enrichedVerdict = enrichVerdict(result.verdict, scopedStatsReceiver) - result.copy(verdict = enrichedVerdict) - } - - private def enrichVerdict( - verdict: Action, - statsReceiver: StatsReceiver - ): Action = { - val preEnrichmentActionScope = - statsReceiver.scope(ComplianceTweetNoticePreEnrichmentActionScope) - - verdict match { - case complianceTweetNoticePreEnrichmentVerdict: ComplianceTweetNoticePreEnrichment => - preEnrichmentActionScope.counter("").incr() - - val verdictWithDetailsAndUrl = complianceTweetNoticePreEnrichmentVerdict.reason match { - case Reason.Unspecified => - preEnrichmentActionScope.counter("reason_unspecified").incr() - complianceTweetNoticePreEnrichmentVerdict - - case reason => - preEnrichmentActionScope.counter("reason_specified").incr() - val safetyResultReason = PublicInterest.ReasonToSafetyResultReason(reason) - val (details, url) = - PublicInterestReasonToPlainText(safetyResultReason, englishLanguageTag) - complianceTweetNoticePreEnrichmentVerdict.copy( - details = Some(details), - extendedDetailsUrl = Some(url)) - } - verdictWithDetailsAndUrl.toComplianceTweetNotice() - - case _ => verdict - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/enrichments/LimitedActionsPolicyEnrichment.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/enrichments/LimitedActionsPolicyEnrichment.scala deleted file mode 100644 index 62eda043d..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/enrichments/LimitedActionsPolicyEnrichment.scala +++ /dev/null @@ -1,173 +0,0 @@ -package com.twitter.visibility.interfaces.tweets.enrichments - -import com.twitter.featureswitches.FSRecipient -import com.twitter.featureswitches.v2.FeatureSwitches -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.common.LocalizedLimitedActionsSource -import com.twitter.visibility.common.actions.converter.scala.LimitedActionTypeConverter -import com.twitter.visibility.common.actions.LimitedActionsPolicy -import com.twitter.visibility.common.actions.LimitedActionType -import com.twitter.visibility.common.actions.LimitedEngagementReason -import com.twitter.visibility.rules.Action -import com.twitter.visibility.rules.EmergencyDynamicInterstitial -import com.twitter.visibility.rules.InterstitialLimitedEngagements -import com.twitter.visibility.rules.LimitedEngagements - -case class PolicyFeatureSwitchResults( - limitedActionTypes: Option[Seq[LimitedActionType]], - copyNamespace: String, - promptType: String, - learnMoreUrl: Option[String]) - -object LimitedActionsPolicyEnrichment { - object FeatureSwitchKeys { - val LimitedActionTypes = "limited_actions_policy_limited_actions" - val CopyNamespace = "limited_actions_policy_copy_namespace" - val PromptType = "limited_actions_policy_prompt_type" - val LearnMoreUrl = "limited_actions_policy_prompt_learn_more_url" - } - - val DefaultCopyNameSpace = "Default" - val DefaultPromptType = "basic" - val LimitedActionsPolicyEnrichmentScope = "limited_actions_policy_enrichment" - val MissingLimitedActionTypesScope = "missing_limited_action_types" - val ExecutedScope = "executed" - - def apply( - result: VisibilityResult, - localizedLimitedActionSource: LocalizedLimitedActionsSource, - languageCode: String, - countryCode: Option[String], - featureSwitches: FeatureSwitches, - statsReceiver: StatsReceiver - ): VisibilityResult = { - val scopedStatsReceiver = statsReceiver.scope(LimitedActionsPolicyEnrichmentScope) - - val enrichVerdict_ = enrichVerdict( - _: Action, - localizedLimitedActionSource, - languageCode, - countryCode, - featureSwitches, - scopedStatsReceiver - ) - - result.copy( - verdict = enrichVerdict_(result.verdict), - secondaryVerdicts = result.secondaryVerdicts.map(enrichVerdict_) - ) - } - - private def enrichVerdict( - verdict: Action, - localizedLimitedActionsSource: LocalizedLimitedActionsSource, - languageCode: String, - countryCode: Option[String], - featureSwitches: FeatureSwitches, - statsReceiver: StatsReceiver - ): Action = { - val limitedActionsPolicyForReason_ = limitedActionsPolicyForReason( - _: LimitedEngagementReason, - localizedLimitedActionsSource, - languageCode, - countryCode, - featureSwitches, - statsReceiver - ) - val executedCounter = statsReceiver.scope(ExecutedScope) - - verdict match { - case le: LimitedEngagements => { - executedCounter.counter("").incr() - executedCounter.counter(le.name).incr() - le.copy( - policy = limitedActionsPolicyForReason_(le.getLimitedEngagementReason) - ) - } - case ile: InterstitialLimitedEngagements => { - executedCounter.counter("").incr() - executedCounter.counter(ile.name).incr() - ile.copy( - policy = limitedActionsPolicyForReason_( - ile.getLimitedEngagementReason - ) - ) - } - case edi: EmergencyDynamicInterstitial => { - executedCounter.counter("").incr() - executedCounter.counter(edi.name).incr() - EmergencyDynamicInterstitial( - copy = edi.copy, - linkOpt = edi.linkOpt, - localizedMessage = edi.localizedMessage, - policy = limitedActionsPolicyForReason_(edi.getLimitedEngagementReason) - ) - } - case _ => verdict - } - } - - private def limitedActionsPolicyForReason( - reason: LimitedEngagementReason, - localizedLimitedActionsSource: LocalizedLimitedActionsSource, - languageCode: String, - countryCode: Option[String], - featureSwitches: FeatureSwitches, - statsReceiver: StatsReceiver - ): Option[LimitedActionsPolicy] = { - val policyConfig = getPolicyFeatureSwitchResults(featureSwitches, reason) - - policyConfig.limitedActionTypes match { - case Some(limitedActionTypes) if limitedActionTypes.nonEmpty => - Some( - LimitedActionsPolicy( - limitedActionTypes.map( - localizedLimitedActionsSource.fetch( - _, - languageCode, - countryCode, - policyConfig.promptType, - policyConfig.copyNamespace, - policyConfig.learnMoreUrl - ) - ) - ) - ) - case _ => { - statsReceiver - .scope(MissingLimitedActionTypesScope).counter(reason.toLimitedActionsString).incr() - None - } - } - } - - private def getPolicyFeatureSwitchResults( - featureSwitches: FeatureSwitches, - reason: LimitedEngagementReason - ): PolicyFeatureSwitchResults = { - val recipient = FSRecipient().withCustomFields( - ("LimitedEngagementReason", reason.toLimitedActionsString) - ) - val featureSwitchesResults = featureSwitches - .matchRecipient(recipient) - - val limitedActionTypes = featureSwitchesResults - .getStringArray(FeatureSwitchKeys.LimitedActionTypes) - .map(_.map(LimitedActionTypeConverter.fromString).flatten) - - val copyNamespace = featureSwitchesResults - .getString(FeatureSwitchKeys.CopyNamespace) - .getOrElse(DefaultCopyNameSpace) - - val promptType = featureSwitchesResults - .getString(FeatureSwitchKeys.PromptType) - .getOrElse(DefaultPromptType) - - val learnMoreUrl = featureSwitchesResults - .getString(FeatureSwitchKeys.LearnMoreUrl) - .filter(_.nonEmpty) - - PolicyFeatureSwitchResults(limitedActionTypes, copyNamespace, promptType, learnMoreUrl) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/enrichments/TweetVisibilityNudgeEnrichment.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/enrichments/TweetVisibilityNudgeEnrichment.scala deleted file mode 100644 index e8f513848..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/enrichments/TweetVisibilityNudgeEnrichment.scala +++ /dev/null @@ -1,96 +0,0 @@ -package com.twitter.visibility.interfaces.tweets.enrichments - -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.builder.tweets.TweetVisibilityNudgeSourceWrapper -import com.twitter.visibility.common.actions.TweetVisibilityNudgeReason.SemanticCoreMisinformationLabelReason -import com.twitter.visibility.rules.Action -import com.twitter.visibility.rules.LocalizedNudge -import com.twitter.visibility.rules.SoftIntervention -import com.twitter.visibility.rules.TweetVisibilityNudge - -object TweetVisibilityNudgeEnrichment { - - def apply( - result: VisibilityResult, - tweetVisibilityNudgeSourceWrapper: TweetVisibilityNudgeSourceWrapper, - languageCode: String, - countryCode: Option[String] - ): VisibilityResult = { - - val softIntervention = extractSoftIntervention(result.verdict, result.secondaryVerdicts) - - val enrichedPrimaryVerdict = enrichAction( - result.verdict, - tweetVisibilityNudgeSourceWrapper, - softIntervention, - languageCode, - countryCode) - - val enrichedSecondaryVerdicts: Seq[Action] = - result.secondaryVerdicts.map(sv => - enrichAction( - sv, - tweetVisibilityNudgeSourceWrapper, - softIntervention, - languageCode, - countryCode)) - - result.copy(verdict = enrichedPrimaryVerdict, secondaryVerdicts = enrichedSecondaryVerdicts) - } - - private def extractSoftIntervention( - primary: Action, - secondaries: Seq[Action] - ): Option[SoftIntervention] = { - primary match { - case si: SoftIntervention => Some(si) - case _ => - secondaries.collectFirst { - case sv: SoftIntervention => sv - } - } - } - - private def enrichAction( - action: Action, - tweetVisibilityNudgeSourceWrapper: TweetVisibilityNudgeSourceWrapper, - softIntervention: Option[SoftIntervention], - languageCode: String, - countryCode: Option[String] - ): Action = { - action match { - case TweetVisibilityNudge(reason, None) => - val localizedNudge = - tweetVisibilityNudgeSourceWrapper.getLocalizedNudge(reason, languageCode, countryCode) - if (reason == SemanticCoreMisinformationLabelReason) - TweetVisibilityNudge( - reason, - enrichLocalizedMisInfoNudge(localizedNudge, softIntervention)) - else - TweetVisibilityNudge(reason, localizedNudge) - case _ => action - } - } - - private def enrichLocalizedMisInfoNudge( - localizedNudge: Option[LocalizedNudge], - softIntervention: Option[SoftIntervention] - ): Option[LocalizedNudge] = { - softIntervention match { - case Some(si) => { - val enrichedLocalizedNudge = localizedNudge.map { ln => - val enrichedLocalizedNudgeActions = ln.localizedNudgeActions.map { na => - val enrichedPayload = na.nudgeActionPayload.map { payload => - payload.copy(ctaUrl = si.detailsUrl, heading = si.warning) - } - na.copy(nudgeActionPayload = enrichedPayload) - } - ln.copy(localizedNudgeActions = enrichedLocalizedNudgeActions) - } - enrichedLocalizedNudge - } - case None => localizedNudge - } - } - -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/users/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/users/BUILD deleted file mode 100644 index 5bdeef86e..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/users/BUILD +++ /dev/null @@ -1,21 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "decider/src/main/scala", - "servo/decider/src/main/scala", - "src/thrift/com/twitter/gizmoduck:user-thrift-scala", - "stitch/stitch-core", - "strato/src/main/scala/com/twitter/strato/client", - "visibility/common/src/main/scala/com/twitter/visibility/common", - "visibility/lib/src/main/resources/config", - "visibility/lib/src/main/scala/com/twitter/visibility", - "visibility/lib/src/main/scala/com/twitter/visibility/builder/users", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/configs", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/thrift/com/twitter/visibility/context:vf-context-scala", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/users/UserVisibilityLibrary.scala b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/users/UserVisibilityLibrary.scala deleted file mode 100644 index 1c8801939..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/users/UserVisibilityLibrary.scala +++ /dev/null @@ -1,111 +0,0 @@ -package com.twitter.visibility.interfaces.users - -import com.twitter.decider.Decider -import com.twitter.gizmoduck.thriftscala.User -import com.twitter.servo.decider.DeciderGateBuilder -import com.twitter.stitch.Stitch -import com.twitter.strato.client.Client -import com.twitter.visibility.VisibilityLibrary -import com.twitter.visibility.builder.users.AuthorFeatures -import com.twitter.visibility.builder.users.RelationshipFeatures -import com.twitter.visibility.builder.users.ViewerAdvancedFilteringFeatures -import com.twitter.visibility.builder.users.ViewerFeatures -import com.twitter.visibility.builder.users.ViewerSearchSafetyFeatures -import com.twitter.visibility.builder.VisibilityResult -import com.twitter.visibility.builder.users.SearchFeatures -import com.twitter.visibility.common.UserRelationshipSource -import com.twitter.visibility.common.UserSearchSafetySource -import com.twitter.visibility.common.UserSource -import com.twitter.visibility.configapi.configs.VisibilityDeciderGates -import com.twitter.visibility.context.thriftscala.UserVisibilityFilteringContext -import com.twitter.visibility.models.ContentId.UserId -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.ViewerContext -import com.twitter.visibility.rules.Reason.Unspecified -import com.twitter.visibility.rules.Allow -import com.twitter.visibility.rules.Drop -import com.twitter.visibility.rules.RuleBase - -object UserVisibilityLibrary { - type Type = - (User, SafetyLevel, ViewerContext, UserVisibilityFilteringContext) => Stitch[VisibilityResult] - - def apply( - visibilityLibrary: VisibilityLibrary, - userSource: UserSource = UserSource.empty, - userRelationshipSource: UserRelationshipSource = UserRelationshipSource.empty, - stratoClient: Client, - decider: Decider - ): Type = { - val libraryStatsReceiver = visibilityLibrary.statsReceiver.scope("user_library") - val stratoClientStatsReceiver = visibilityLibrary.statsReceiver.scope("strato") - - val visibilityDeciderGates = VisibilityDeciderGates(decider) - - val vfEngineCounter = libraryStatsReceiver.counter("vf_engine_requests") - val noUserRulesCounter = libraryStatsReceiver.counter("no_user_rules_requests") - val viewerIsAuthorCounter = libraryStatsReceiver.counter("viewer_is_author_requests") - - val authorFeatures = new AuthorFeatures(userSource, libraryStatsReceiver) - val viewerFeatures = new ViewerFeatures(userSource, libraryStatsReceiver) - val relationshipFeatures = - new RelationshipFeatures(userRelationshipSource, libraryStatsReceiver) - val searchFeatures = new SearchFeatures(libraryStatsReceiver) - - val viewerSafeSearchFeatures = new ViewerSearchSafetyFeatures( - UserSearchSafetySource.fromStrato(stratoClient, stratoClientStatsReceiver), - libraryStatsReceiver) - - val deciderGateBuilder = new DeciderGateBuilder(decider) - val advancedFilteringFeatures = - new ViewerAdvancedFilteringFeatures(userSource, libraryStatsReceiver) - - (user, safetyLevel, viewerContext, userVisibilityFilteringContext) => { - val contentId = UserId(user.id) - val viewerId = viewerContext.userId - - if (!RuleBase.hasUserRules(safetyLevel)) { - noUserRulesCounter.incr() - Stitch.value(VisibilityResult(contentId = contentId, verdict = Allow)) - } else { - if (viewerId.contains(user.id)) { - viewerIsAuthorCounter.incr() - - Stitch.value(VisibilityResult(contentId = contentId, verdict = Allow)) - } else { - vfEngineCounter.incr() - - val featureMap = - visibilityLibrary.featureMapBuilder( - Seq( - viewerFeatures.forViewerContext(viewerContext), - viewerSafeSearchFeatures.forViewerId(viewerId), - relationshipFeatures.forAuthor(user, viewerId), - authorFeatures.forAuthor(user), - advancedFilteringFeatures.forViewerId(viewerId), - searchFeatures.forSearchContext(userVisibilityFilteringContext.searchContext) - ) - ) - - visibilityLibrary.runRuleEngine( - contentId, - featureMap, - viewerContext, - safetyLevel - ) - - } - } - } - } - - def Const(shouldDrop: Boolean): Type = - (user, _, _, _) => - Stitch.value( - VisibilityResult( - contentId = UserId(user.id), - verdict = if (shouldDrop) Drop(Unspecified) else Allow, - finished = true - ) - ) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/models/BUILD deleted file mode 100644 index 847043fc6..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/BUILD +++ /dev/null @@ -1,32 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "configapi/configapi-core", - "datatools/src/thrift/com/twitter/datatools/entityservice:entity-entities-thrift-scala", - "escherbird/src/thrift/com/twitter/escherbird/softintervention:softintervention_thrift-scala", - "featureswitches/featureswitches-core", - "finatra-internal/request/src/main/scala", - "src/thrift/com/twitter/content-health/sensitivemediasettings:sensitivemediasettings-scala", - "src/thrift/com/twitter/context:twitter-context-scala", - "src/thrift/com/twitter/escherbird:tweet-annotation-scala", - "src/thrift/com/twitter/escherbird/common:common-scala", - "src/thrift/com/twitter/gizmoduck:user-thrift-scala", - "src/thrift/com/twitter/spam/rtf:safety-level-scala", - "src/thrift/com/twitter/spam/rtf:safety-result-scala", - "src/thrift/com/twitter/spam/rtf:tweet-rtf-event-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "timelines/src/main/scala/com/twitter/timelines/model/candidate", - "timelines/src/main/scala/com/twitter/timelines/util/client_info", - "twitter-context/src/main/scala", - "visibility/common/src/main/scala/com/twitter/visibility/common/actions", - "visibility/common/src/main/thrift/com/twitter/visibility:action-scala", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/params", - "visibility/lib/src/main/scala/com/twitter/visibility/util", - "visibility/lib/src/main/thrift/com/twitter/visibility/safety_label_store:safety-label-store-scala", - "visibility/lib/src/main/thrift/com/twitter/visibility/strato:vf-strato-scala", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/CommunityTweet.scala b/visibilitylib/src/main/scala/com/twitter/visibility/models/CommunityTweet.scala deleted file mode 100644 index fbb4dc6ac..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/CommunityTweet.scala +++ /dev/null @@ -1,23 +0,0 @@ -package com.twitter.visibility.models - -import com.twitter.tweetypie.thriftscala.Communities -import com.twitter.tweetypie.thriftscala.Tweet - -object CommunityTweet { - def getCommunityId(communities: Communities): Option[CommunityId] = - communities.communityIds.headOption - - def getCommunityId(tweet: Tweet): Option[CommunityId] = - tweet.communities.flatMap(getCommunityId) - - def apply(tweet: Tweet): Option[CommunityTweet] = - getCommunityId(tweet).map { communityId => - val authorId = tweet.coreData.get.userId - CommunityTweet(tweet, communityId, authorId) - } -} - -case class CommunityTweet( - tweet: Tweet, - communityId: CommunityId, - authorId: Long) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/ContentId.scala b/visibilitylib/src/main/scala/com/twitter/visibility/models/ContentId.scala deleted file mode 100644 index b08e2b9ca..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/ContentId.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.visibility.models - -sealed trait ContentId - -object ContentId { - case class TweetId(id: Long) extends ContentId - case class UserId(id: Long) extends ContentId - case class CardId(url: String) extends ContentId - case class QuotedTweetRelationship(outer: Long, inner: Long) extends ContentId - case class NotificationId(tweetId: Option[Long]) extends ContentId - case class DmId(id: Long) extends ContentId - case class BlenderTweetId(id: Long) extends ContentId - case class SpaceId(id: String) extends ContentId - case class SpacePlusUserId(id: String) extends ContentId - case class DmConversationId(id: String) extends ContentId - case class DmEventId(id: Long) extends ContentId - case class UserUnavailableState(tweetId: Long) extends ContentId - case class TwitterArticleId(id: Long) extends ContentId - case class DeleteTweetId(tweetId: Long) extends ContentId - case class MediaId(id: String) extends ContentId - case class CommunityId(communityId: Long) extends ContentId -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/LabelSource.scala b/visibilitylib/src/main/scala/com/twitter/visibility/models/LabelSource.scala deleted file mode 100644 index 0a85a024d..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/LabelSource.scala +++ /dev/null @@ -1,61 +0,0 @@ -package com.twitter.visibility.models - -import com.twitter.spam.rtf.thriftscala.SafetyResultReason -import java.util.regex.Pattern - -sealed trait LabelSource { - val name: String -} - -object LabelSource { - val BotRulePrefix = "bot_id_" - val AbusePrefix = "Abuse" - val HSEPrefix = "hse" - val AgentSourceNames = Set( - SafetyResultReason.OneOff.name, - SafetyResultReason.VotingMisinformation.name, - SafetyResultReason.HackedMaterials.name, - SafetyResultReason.Scams.name, - SafetyResultReason.PlatformManipulation.name - ) - - val Regex = "\\|" - val pattern: Pattern = Pattern.compile(Regex) - - def fromString(name: String): Option[LabelSource] = Some(name) collect { - case _ if name.startsWith(BotRulePrefix) => - BotMakerRule(name.substring(BotRulePrefix.length).toLong) - case _ if name == "A" || name == "B" || name == "AB" => - SmyteSource(name) - case _ if name.startsWith(AbusePrefix) => - AbuseSource(name) - case _ if name.startsWith(HSEPrefix) => - HSESource(name) - case _ if AgentSourceNames.contains(name) => - AgentSource(name) - case _ => - StringSource(name) - } - - def parseStringSource(source: String): (String, Option[String]) = { - pattern.split(source, 2) match { - case Array(copy, "") => (copy, None) - case Array(copy, link) => (copy, Some(link)) - case Array(copy) => (copy, None) - } - } - - case class BotMakerRule(ruleId: Long) extends LabelSource { - override lazy val name: String = s"${BotRulePrefix}${ruleId}" - } - - case class SmyteSource(name: String) extends LabelSource - - case class AbuseSource(name: String) extends LabelSource - - case class AgentSource(name: String) extends LabelSource - - case class HSESource(name: String) extends LabelSource - - case class StringSource(name: String) extends LabelSource -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/MediaSafetyLabelType.scala b/visibilitylib/src/main/scala/com/twitter/visibility/models/MediaSafetyLabelType.scala deleted file mode 100644 index 18df9d511..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/MediaSafetyLabelType.scala +++ /dev/null @@ -1,89 +0,0 @@ -package com.twitter.visibility.models - -import com.twitter.visibility.safety_label_store.{thriftscala => s} -import com.twitter.visibility.util.NamingUtils - -sealed trait MediaSafetyLabelType extends SafetyLabelType { - lazy val name: String = NamingUtils.getFriendlyName(this) -} - -object MediaSafetyLabelType extends SafetyLabelType { - - val List: List[MediaSafetyLabelType] = s.MediaSafetyLabelType.list.map(fromThrift) - - val ActiveLabels: List[MediaSafetyLabelType] = List.filter { labelType => - labelType != Unknown && labelType != Deprecated - } - - private lazy val nameToValueMap: Map[String, MediaSafetyLabelType] = - List.map(l => l.name.toLowerCase -> l).toMap - def fromName(name: String): Option[MediaSafetyLabelType] = nameToValueMap.get(name.toLowerCase) - - private val UnknownThriftSafetyLabelType = - s.MediaSafetyLabelType.EnumUnknownMediaSafetyLabelType(UnknownEnumValue) - - private lazy val thriftToModelMap: Map[s.MediaSafetyLabelType, MediaSafetyLabelType] = Map( - s.MediaSafetyLabelType.NsfwHighPrecision -> NsfwHighPrecision, - s.MediaSafetyLabelType.NsfwHighRecall -> NsfwHighRecall, - s.MediaSafetyLabelType.NsfwNearPerfect -> NsfwNearPerfect, - s.MediaSafetyLabelType.NsfwCardImage -> NsfwCardImage, - s.MediaSafetyLabelType.Pdna -> Pdna, - s.MediaSafetyLabelType.PdnaNoTreatmentIfVerified -> PdnaNoTreatmentIfVerified, - s.MediaSafetyLabelType.DmcaWithheld -> DmcaWithheld, - s.MediaSafetyLabelType.LegalDemandsWithheld -> LegalDemandsWithheld, - s.MediaSafetyLabelType.LocalLawsWithheld -> LocalLawsWithheld, - s.MediaSafetyLabelType.Reserved10 -> Deprecated, - s.MediaSafetyLabelType.Reserved11 -> Deprecated, - s.MediaSafetyLabelType.Reserved12 -> Deprecated, - s.MediaSafetyLabelType.Reserved13 -> Deprecated, - s.MediaSafetyLabelType.Reserved14 -> Deprecated, - s.MediaSafetyLabelType.Reserved15 -> Deprecated, - s.MediaSafetyLabelType.Reserved16 -> Deprecated, - s.MediaSafetyLabelType.Reserved17 -> Deprecated, - s.MediaSafetyLabelType.Reserved18 -> Deprecated, - s.MediaSafetyLabelType.Reserved19 -> Deprecated, - s.MediaSafetyLabelType.Reserved20 -> Deprecated, - s.MediaSafetyLabelType.Reserved21 -> Deprecated, - s.MediaSafetyLabelType.Reserved22 -> Deprecated, - s.MediaSafetyLabelType.Reserved23 -> Deprecated, - s.MediaSafetyLabelType.Reserved24 -> Deprecated, - s.MediaSafetyLabelType.Reserved25 -> Deprecated, - s.MediaSafetyLabelType.Reserved26 -> Deprecated, - s.MediaSafetyLabelType.Reserved27 -> Deprecated, - ) - - private lazy val modelToThriftMap: Map[MediaSafetyLabelType, s.MediaSafetyLabelType] = - (for ((k, v) <- thriftToModelMap) yield (v, k)) ++ Map( - Deprecated -> s.MediaSafetyLabelType.EnumUnknownMediaSafetyLabelType(DeprecatedEnumValue), - ) - - case object NsfwHighPrecision extends MediaSafetyLabelType - case object NsfwHighRecall extends MediaSafetyLabelType - case object NsfwNearPerfect extends MediaSafetyLabelType - case object NsfwCardImage extends MediaSafetyLabelType - case object Pdna extends MediaSafetyLabelType - case object PdnaNoTreatmentIfVerified extends MediaSafetyLabelType - case object DmcaWithheld extends MediaSafetyLabelType - case object LegalDemandsWithheld extends MediaSafetyLabelType - case object LocalLawsWithheld extends MediaSafetyLabelType - - case object Deprecated extends MediaSafetyLabelType - case object Unknown extends MediaSafetyLabelType - - def fromThrift(safetyLabelType: s.MediaSafetyLabelType): MediaSafetyLabelType = - thriftToModelMap.get(safetyLabelType) match { - case Some(mediaSafetyLabelType) => mediaSafetyLabelType - case _ => - safetyLabelType match { - case s.MediaSafetyLabelType.EnumUnknownMediaSafetyLabelType(DeprecatedEnumValue) => - Deprecated - case _ => - Unknown - } - } - - def toThrift(safetyLabelType: MediaSafetyLabelType): s.MediaSafetyLabelType = { - modelToThriftMap - .get(safetyLabelType).getOrElse(UnknownThriftSafetyLabelType) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/MisinformationPolicy.scala b/visibilitylib/src/main/scala/com/twitter/visibility/models/MisinformationPolicy.scala deleted file mode 100644 index 7ce381bfc..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/MisinformationPolicy.scala +++ /dev/null @@ -1,179 +0,0 @@ -package com.twitter.visibility.models - -import com.twitter.datatools.entityservice.entities.thriftscala.FleetInterstitial -import com.twitter.datatools.entityservice.entities.{thriftscala => t} -import com.twitter.escherbird.softintervention.thriftscala.MisinformationLocalizedPolicy -import com.twitter.escherbird.thriftscala.TweetEntityAnnotation - -case class MisinformationPolicy( - semanticCoreAnnotation: SemanticCoreAnnotation, - priority: Long = MisinformationPolicy.DefaultPriority, - filteringLevel: Int = MisinformationPolicy.DefaultFilteringLevel, - publishedState: PublishedState = MisinformationPolicy.DefaultPublishedState, - engagementNudge: Boolean = MisinformationPolicy.DefaultEngagementNudge, - suppressAutoplay: Boolean = MisinformationPolicy.DefaultSuppressAutoplay, - warning: Option[String] = None, - detailsUrl: Option[String] = None, - displayType: Option[MisinfoPolicyDisplayType] = None, - applicableCountries: Seq[String] = Seq.empty, - fleetInterstitial: Option[FleetInterstitial] = None) - -object MisinformationPolicy { - private val DefaultPriority = 0 - private val DefaultFilteringLevel = 1 - private val DefaultPublishedState = PublishedState.Published - private val DefaultEngagementNudge = true - private val DefaultSuppressAutoplay = true - - def apply( - annotation: TweetEntityAnnotation, - misinformation: MisinformationLocalizedPolicy - ): MisinformationPolicy = { - MisinformationPolicy( - semanticCoreAnnotation = SemanticCoreAnnotation( - groupId = annotation.groupId, - domainId = annotation.domainId, - entityId = annotation.entityId - ), - priority = misinformation.priority.getOrElse(DefaultPriority), - filteringLevel = misinformation.filteringLevel.getOrElse(DefaultFilteringLevel), - publishedState = misinformation.publishedState match { - case Some(t.PublishedState.Draft) => PublishedState.Draft - case Some(t.PublishedState.Dogfood) => PublishedState.Dogfood - case Some(t.PublishedState.Published) => PublishedState.Published - case _ => DefaultPublishedState - }, - displayType = misinformation.displayType collect { - case t.MisinformationDisplayType.GetTheLatest => MisinfoPolicyDisplayType.GetTheLatest - case t.MisinformationDisplayType.StayInformed => MisinfoPolicyDisplayType.StayInformed - case t.MisinformationDisplayType.Misleading => MisinfoPolicyDisplayType.Misleading - case t.MisinformationDisplayType.GovernmentRequested => - MisinfoPolicyDisplayType.GovernmentRequested - }, - applicableCountries = misinformation.applicableCountries match { - case Some(countries) => countries.map(countryCode => countryCode.toLowerCase) - case _ => Seq.empty - }, - fleetInterstitial = misinformation.fleetInterstitial, - engagementNudge = misinformation.engagementNudge.getOrElse(DefaultEngagementNudge), - suppressAutoplay = misinformation.suppressAutoplay.getOrElse(DefaultSuppressAutoplay), - warning = misinformation.warning, - detailsUrl = misinformation.detailsUrl, - ) - } -} - -trait MisinformationPolicyTransform { - def apply(policies: Seq[MisinformationPolicy]): Seq[MisinformationPolicy] - def andThen(transform: MisinformationPolicyTransform): MisinformationPolicyTransform = - (policies: Seq[MisinformationPolicy]) => transform(this.apply(policies)) -} - -object MisinformationPolicyTransform { - - def prioritize: MisinformationPolicyTransform = - (policies: Seq[MisinformationPolicy]) => - policies - .sortBy(p => p.filteringLevel)(Ordering[Int].reverse) - .sortBy(p => p.priority)(Ordering[Long].reverse) - - def filter(filters: Seq[MisinformationPolicy => Boolean]): MisinformationPolicyTransform = - (policies: Seq[MisinformationPolicy]) => - policies.filter { policy => filters.forall { filter => filter(policy) } } - - def filterLevelAndState( - filteringLevel: Int, - publishedStates: Seq[PublishedState] - ): MisinformationPolicyTransform = - filter( - Seq( - hasFilteringLevelAtLeast(filteringLevel), - hasPublishedStates(publishedStates) - )) - - def filterLevelAndStateAndLocalized( - filteringLevel: Int, - publishedStates: Seq[PublishedState] - ): MisinformationPolicyTransform = - filter( - Seq( - hasFilteringLevelAtLeast(filteringLevel), - hasPublishedStates(publishedStates), - hasNonEmptyLocalization, - )) - - def filterState( - publishedStates: Seq[PublishedState] - ): MisinformationPolicyTransform = - filter( - Seq( - hasPublishedStates(publishedStates) - )) - - def filterStateAndLocalized( - publishedStates: Seq[PublishedState] - ): MisinformationPolicyTransform = - filter( - Seq( - hasPublishedStates(publishedStates), - hasNonEmptyLocalization, - )) - - def filterApplicableCountries( - countryCode: Option[String], - ): MisinformationPolicyTransform = - filter(Seq(policyAppliesToCountry(countryCode))) - - def filterOutGeoSpecific(): MisinformationPolicyTransform = - filter(Seq(policyIsGlobal())) - - def filterNonEngagementNudges(): MisinformationPolicyTransform = - filter( - Seq( - hasEngagementNudge, - )) - - def policyAppliesToCountry(countryCode: Option[String]): MisinformationPolicy => Boolean = - policy => - policy.applicableCountries.isEmpty || - (countryCode.nonEmpty && policy.applicableCountries.contains(countryCode.get)) - - def policyIsGlobal(): MisinformationPolicy => Boolean = - policy => policy.applicableCountries.isEmpty - - def hasFilteringLevelAtLeast(filteringLevel: Int): MisinformationPolicy => Boolean = - _.filteringLevel >= filteringLevel - - def hasPublishedStates( - publishedStates: Seq[PublishedState] - ): MisinformationPolicy => Boolean = - policy => publishedStates.contains(policy.publishedState) - - def hasNonEmptyLocalization: MisinformationPolicy => Boolean = - policy => policy.warning.nonEmpty && policy.detailsUrl.nonEmpty - - def hasEngagementNudge: MisinformationPolicy => Boolean = - policy => policy.engagementNudge - -} - -sealed trait PublishedState -object PublishedState { - case object Draft extends PublishedState - case object Dogfood extends PublishedState - case object Published extends PublishedState - - val PublicPublishedStates = Seq(PublishedState.Published) - val EmployeePublishedStates = Seq(PublishedState.Published, PublishedState.Dogfood) -} -sealed trait MisinfoPolicyDisplayType -object MisinfoPolicyDisplayType { - case object GetTheLatest extends MisinfoPolicyDisplayType - case object StayInformed extends MisinfoPolicyDisplayType - case object Misleading extends MisinfoPolicyDisplayType - case object GovernmentRequested extends MisinfoPolicyDisplayType -} - -object SemanticCoreMisinformation { - val domainId: Long = 148L -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/MutedKeyword.scala b/visibilitylib/src/main/scala/com/twitter/visibility/models/MutedKeyword.scala deleted file mode 100644 index 2dcb6f9b2..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/MutedKeyword.scala +++ /dev/null @@ -1,3 +0,0 @@ -package com.twitter.visibility.models - -case class MutedKeyword(keyword: Option[String]) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLabel.scala b/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLabel.scala deleted file mode 100644 index 06eb2492d..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLabel.scala +++ /dev/null @@ -1,90 +0,0 @@ -package com.twitter.visibility.models - -import com.twitter.spam.rtf.{thriftscala => s} -import com.twitter.visibility.safety_label_store.{thriftscala => store} - -case class SafetyLabel( - score: Option[Double] = None, - applicableUsers: Set[Long] = Set.empty, - source: Option[LabelSource] = None, - modelMetadata: Option[TweetModelMetadata] = None, - createdAtMsec: Option[Long] = None, - expiresAtMsec: Option[Long] = None, - labelMetadata: Option[SafetyLabelMetadata] = None, - applicableCountries: Option[Seq[String]] = None) - -object SafetyLabel { - def fromThrift(safetyLabel: s.SafetyLabel): SafetyLabel = { - SafetyLabel( - score = safetyLabel.score, - applicableUsers = safetyLabel.applicableUsers - .map { perspectivalUsers => - (perspectivalUsers map { - _.userId - }).toSet - }.getOrElse(Set.empty), - source = safetyLabel.source.flatMap(LabelSource.fromString), - modelMetadata = safetyLabel.modelMetadata.flatMap(TweetModelMetadata.fromThrift), - createdAtMsec = safetyLabel.createdAtMsec, - expiresAtMsec = safetyLabel.expiresAtMsec, - labelMetadata = safetyLabel.labelMetadata.map(SafetyLabelMetadata.fromThrift(_)), - applicableCountries = safetyLabel.applicableCountries - ) - } - - def toThrift(safetyLabel: SafetyLabel): s.SafetyLabel = { - s.SafetyLabel( - score = safetyLabel.score, - applicableUsers = if (safetyLabel.applicableUsers.nonEmpty) { - Some(safetyLabel.applicableUsers.toSeq.map { - s.PerspectivalUser(_) - }) - } else { - None - }, - source = safetyLabel.source.map(_.name), - modelMetadata = safetyLabel.modelMetadata.map(TweetModelMetadata.toThrift), - createdAtMsec = safetyLabel.createdAtMsec, - expiresAtMsec = safetyLabel.expiresAtMsec, - labelMetadata = safetyLabel.labelMetadata.map(_.toThrift), - applicableCountries = safetyLabel.applicableCountries - ) - } -} - -trait SafetyLabelWithType[EntitySafetyLabelType <: SafetyLabelType] { - val safetyLabelType: EntitySafetyLabelType - val safetyLabel: SafetyLabel -} - -case class MediaSafetyLabel( - override val safetyLabelType: MediaSafetyLabelType, - override val safetyLabel: SafetyLabel) - extends SafetyLabelWithType[MediaSafetyLabelType] { - - def fromThrift( - thriftType: store.MediaSafetyLabelType, - thriftLabel: s.SafetyLabel - ): MediaSafetyLabel = { - MediaSafetyLabel( - MediaSafetyLabelType.fromThrift(thriftType), - SafetyLabel.fromThrift(thriftLabel) - ) - } -} - -case class SpaceSafetyLabel( - override val safetyLabelType: SpaceSafetyLabelType, - override val safetyLabel: SafetyLabel) - extends SafetyLabelWithType[SpaceSafetyLabelType] { - - def fromThrift( - thriftType: store.SpaceSafetyLabelType, - thriftLabel: s.SafetyLabel - ): SpaceSafetyLabel = { - SpaceSafetyLabel( - SpaceSafetyLabelType.fromThrift(thriftType), - SafetyLabel.fromThrift(thriftLabel) - ) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLabelMetadata.scala b/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLabelMetadata.scala deleted file mode 100644 index b35986aba..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLabelMetadata.scala +++ /dev/null @@ -1,25 +0,0 @@ -package com.twitter.visibility.models - -import com.twitter.guano.commons.thriftscala.PolicyInViolation -import com.twitter.spam.rtf.{thriftscala => s} - -case class SafetyLabelMetadata( - policyInViolation: Option[PolicyInViolation] = None, - policyUrl: Option[String] = None) { - - def toThrift: s.SafetyLabelMetadata = { - s.SafetyLabelMetadata( - policyInViolation, - policyUrl - ) - } -} - -object SafetyLabelMetadata { - def fromThrift(metadata: s.SafetyLabelMetadata): SafetyLabelMetadata = { - SafetyLabelMetadata( - metadata.policyInViolation, - metadata.policyUrl - ) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLabelType.scala b/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLabelType.scala deleted file mode 100644 index d79bbd153..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLabelType.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.visibility.models - -trait SafetyLabelType { - val DeprecatedEnumValue: Short = -1 - val UnknownEnumValue: Short = -2 - val StratoOnlyLabelEnumValue: Short = -3 -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLevel.scala b/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLevel.scala deleted file mode 100644 index 805b17497..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLevel.scala +++ /dev/null @@ -1,855 +0,0 @@ -package com.twitter.visibility.models - -import com.twitter.spam.rtf.thriftscala.{SafetyLevel => ThriftSafetyLevel} -import com.twitter.visibility.configapi.params.SafetyLevelParam -import com.twitter.visibility.configapi.params.SafetyLevelParams._ - -sealed trait SafetyLevel { - val name: String = this.getClass.getSimpleName.dropRight(1) - def enabledParam: SafetyLevelParam -} - -object SafetyLevel { - private lazy val nameToSafetyLevelMap: Map[String, SafetyLevel] = - SafetyLevel.List.map(s => s.name.toLowerCase -> s).toMap - def fromName(name: String): Option[SafetyLevel] = { - nameToSafetyLevelMap.get(name.toLowerCase) - } - - private val DeprecatedEnumValue = -1 - - private lazy val thriftToModelMap: Map[ThriftSafetyLevel, SafetyLevel] = Map( - ThriftSafetyLevel.AccessInternalPromotedContent -> AccessInternalPromotedContent, - ThriftSafetyLevel.AdsBusinessSettings -> AdsBusinessSettings, - ThriftSafetyLevel.AdsCampaign -> AdsCampaign, - ThriftSafetyLevel.AdsManager -> AdsManager, - ThriftSafetyLevel.AdsReportingDashboard -> AdsReportingDashboard, - ThriftSafetyLevel.AllSubscribedLists -> AllSubscribedLists, - ThriftSafetyLevel.Appeals -> Appeals, - ThriftSafetyLevel.ArticleTweetTimeline -> ArticleTweetTimeline, - ThriftSafetyLevel.BaseQig -> BaseQig, - ThriftSafetyLevel.BirdwatchNoteAuthor -> BirdwatchNoteAuthor, - ThriftSafetyLevel.BirdwatchNoteTweetsTimeline -> BirdwatchNoteTweetsTimeline, - ThriftSafetyLevel.BirdwatchNeedsYourHelpNotifications -> BirdwatchNeedsYourHelpNotifications, - ThriftSafetyLevel.BlockMuteUsersTimeline -> BlockMuteUsersTimeline, - ThriftSafetyLevel.BrandSafety -> BrandSafety, - ThriftSafetyLevel.CardPollVoting -> CardPollVoting, - ThriftSafetyLevel.CardsService -> CardsService, - ThriftSafetyLevel.Communities -> Communities, - ThriftSafetyLevel.ContentControlToolInstall -> ContentControlToolInstall, - ThriftSafetyLevel.ConversationFocalPrehydration -> ConversationFocalPrehydration, - ThriftSafetyLevel.ConversationFocalTweet -> ConversationFocalTweet, - ThriftSafetyLevel.ConversationInjectedTweet -> ConversationInjectedTweet, - ThriftSafetyLevel.ConversationReply -> ConversationReply, - ThriftSafetyLevel.CuratedTrendsRepresentativeTweet -> CuratedTrendsRepresentativeTweet, - ThriftSafetyLevel.CurationPolicyViolations -> CurationPolicyViolations, - ThriftSafetyLevel.DevPlatformGetListTweets -> DevPlatformGetListTweets, - ThriftSafetyLevel.DesFollowingAndFollowersUserList -> DesFollowingAndFollowersUserList, - ThriftSafetyLevel.DesHomeTimeline -> DesHomeTimeline, - ThriftSafetyLevel.DesQuoteTweetTimeline -> DesQuoteTweetTimeline, - ThriftSafetyLevel.DesRealtime -> DesRealtime, - ThriftSafetyLevel.DesRealtimeSpamEnrichment -> DesRealtimeSpamEnrichment, - ThriftSafetyLevel.DesRealtimeTweetFilter -> DesRealtimeTweetFilter, - ThriftSafetyLevel.DesRetweetingUsers -> DesRetweetingUsers, - ThriftSafetyLevel.DesTweetDetail -> DesTweetDetail, - ThriftSafetyLevel.DesTweetLikingUsers -> DesTweetLikingUsers, - ThriftSafetyLevel.DesUserBookmarks -> DesUserBookmarks, - ThriftSafetyLevel.DesUserLikedTweets -> DesUserLikedTweets, - ThriftSafetyLevel.DesUserMentions -> DesUserMentions, - ThriftSafetyLevel.DesUserTweets -> DesUserTweets, - ThriftSafetyLevel.DevPlatformComplianceStream -> DevPlatformComplianceStream, - ThriftSafetyLevel.DirectMessages -> DirectMessages, - ThriftSafetyLevel.DirectMessagesConversationList -> DirectMessagesConversationList, - ThriftSafetyLevel.DirectMessagesConversationTimeline -> DirectMessagesConversationTimeline, - ThriftSafetyLevel.DirectMessagesInbox -> DirectMessagesInbox, - ThriftSafetyLevel.DirectMessagesMutedUsers -> DirectMessagesMutedUsers, - ThriftSafetyLevel.DirectMessagesPinned -> DirectMessagesPinned, - ThriftSafetyLevel.DirectMessagesSearch -> DirectMessagesSearch, - ThriftSafetyLevel.EditHistoryTimeline -> EditHistoryTimeline, - ThriftSafetyLevel.ElevatedQuoteTweetTimeline -> ElevatedQuoteTweetTimeline, - ThriftSafetyLevel.EmbeddedTweet -> EmbeddedTweet, - ThriftSafetyLevel.EmbedsPublicInterestNotice -> EmbedsPublicInterestNotice, - ThriftSafetyLevel.EmbedTweetMarkup -> EmbedTweetMarkup, - ThriftSafetyLevel.ExploreRecommendations -> ExploreRecommendations, - ThriftSafetyLevel.WritePathLimitedActionsEnforcement -> WritePathLimitedActionsEnforcement, - ThriftSafetyLevel.FilterAll -> FilterAll, - ThriftSafetyLevel.FilterAllPlaceholder -> FilterAllPlaceholder, - ThriftSafetyLevel.FilterDefault -> FilterDefault, - ThriftSafetyLevel.FilterNone -> FilterNone, - ThriftSafetyLevel.FollowedTopicsTimeline -> FollowedTopicsTimeline, - ThriftSafetyLevel.FollowerConnections -> FollowerConnections, - ThriftSafetyLevel.FollowingAndFollowersUserList -> FollowingAndFollowersUserList, - ThriftSafetyLevel.ForDevelopmentOnly -> ForDevelopmentOnly, - ThriftSafetyLevel.FriendsFollowingList -> FriendsFollowingList, - ThriftSafetyLevel.GraphqlDefault -> GraphqlDefault, - ThriftSafetyLevel.HumanizationNudge -> HumanizationNudge, - ThriftSafetyLevel.KitchenSinkDevelopment -> KitchenSinkDevelopment, - ThriftSafetyLevel.ListHeader -> ListHeader, - ThriftSafetyLevel.ListMemberships -> ListMemberships, - ThriftSafetyLevel.ListOwnerships -> ListOwnerships, - ThriftSafetyLevel.ListRecommendations -> ListRecommendations, - ThriftSafetyLevel.ListSearch -> ListSearch, - ThriftSafetyLevel.ListSubscriptions -> ListSubscriptions, - ThriftSafetyLevel.LivePipelineEngagementCounts -> LivePipelineEngagementCounts, - ThriftSafetyLevel.LiveVideoTimeline -> LiveVideoTimeline, - ThriftSafetyLevel.MagicRecs -> MagicRecs, - ThriftSafetyLevel.MagicRecsV2 -> MagicRecsV2, - ThriftSafetyLevel.MagicRecsAggressive -> MagicRecsAggressive, - ThriftSafetyLevel.MagicRecsAggressiveV2 -> MagicRecsAggressiveV2, - ThriftSafetyLevel.Minimal -> Minimal, - ThriftSafetyLevel.ModeratedTweetsTimeline -> ModeratedTweetsTimeline, - ThriftSafetyLevel.Moments -> Moments, - ThriftSafetyLevel.NearbyTimeline -> NearbyTimeline, - ThriftSafetyLevel.NewUserExperience -> NewUserExperience, - ThriftSafetyLevel.NotificationsIbis -> NotificationsIbis, - ThriftSafetyLevel.NotificationsPlatform -> NotificationsPlatform, - ThriftSafetyLevel.NotificationsPlatformPush -> NotificationsPlatformPush, - ThriftSafetyLevel.NotificationsQig -> NotificationsQig, - ThriftSafetyLevel.NotificationsRead -> NotificationsRead, - ThriftSafetyLevel.NotificationsTimelineDeviceFollow -> NotificationsTimelineDeviceFollow, - ThriftSafetyLevel.NotificationsWrite -> NotificationsWrite, - ThriftSafetyLevel.NotificationsWriterTweetHydrator -> NotificationsWriterTweetHydrator, - ThriftSafetyLevel.NotificationsWriterV2 -> NotificationsWriterV2, - ThriftSafetyLevel.ProfileMixerMedia -> ProfileMixerMedia, - ThriftSafetyLevel.ProfileMixerFavorites -> ProfileMixerFavorites, - ThriftSafetyLevel.QuickPromoteTweetEligibility -> QuickPromoteTweetEligibility, - ThriftSafetyLevel.QuoteTweetTimeline -> QuoteTweetTimeline, - ThriftSafetyLevel.QuotedTweetRules -> QuotedTweetRules, - ThriftSafetyLevel.Recommendations -> Recommendations, - ThriftSafetyLevel.RecosVideo -> RecosVideo, - ThriftSafetyLevel.RecosWritePath -> RecosWritePath, - ThriftSafetyLevel.RepliesGrouping -> RepliesGrouping, - ThriftSafetyLevel.ReportCenter -> ReportCenter, - ThriftSafetyLevel.ReturningUserExperience -> ReturningUserExperience, - ThriftSafetyLevel.ReturningUserExperienceFocalTweet -> ReturningUserExperienceFocalTweet, - ThriftSafetyLevel.Revenue -> Revenue, - ThriftSafetyLevel.RitoActionedTweetTimeline -> RitoActionedTweetTimeline, - ThriftSafetyLevel.SafeSearchMinimal -> SafeSearchMinimal, - ThriftSafetyLevel.SafeSearchStrict -> SafeSearchStrict, - ThriftSafetyLevel.SearchHydration -> SearchHydration, - ThriftSafetyLevel.SearchLatest -> SearchLatest, - ThriftSafetyLevel.SearchTop -> SearchTop, - ThriftSafetyLevel.SearchTopQig -> SearchTopQig, - ThriftSafetyLevel.SearchMixerSrpMinimal -> SearchMixerSrpMinimal, - ThriftSafetyLevel.SearchMixerSrpStrict -> SearchMixerSrpStrict, - ThriftSafetyLevel.SearchPeopleSrp -> SearchPeopleSrp, - ThriftSafetyLevel.SearchPeopleTypeahead -> SearchPeopleTypeahead, - ThriftSafetyLevel.SearchPhoto -> SearchPhoto, - ThriftSafetyLevel.SearchTrendTakeoverPromotedTweet -> SearchTrendTakeoverPromotedTweet, - ThriftSafetyLevel.SearchVideo -> SearchVideo, - ThriftSafetyLevel.SearchBlenderUserRules -> SearchBlenderUserRules, - ThriftSafetyLevel.SearchLatestUserRules -> SearchLatestUserRules, - ThriftSafetyLevel.ShoppingManagerSpyMode -> ShoppingManagerSpyMode, - ThriftSafetyLevel.SignalsReactions -> SignalsReactions, - ThriftSafetyLevel.SignalsTweetReactingUsers -> SignalsTweetReactingUsers, - ThriftSafetyLevel.SocialProof -> SocialProof, - ThriftSafetyLevel.SoftInterventionPivot -> SoftInterventionPivot, - ThriftSafetyLevel.SpaceFleetline -> SpaceFleetline, - ThriftSafetyLevel.SpaceHomeTimelineUpranking -> SpaceHomeTimelineUpranking, - ThriftSafetyLevel.SpaceJoinScreen -> SpaceJoinScreen, - ThriftSafetyLevel.SpaceNotifications -> SpaceNotifications, - ThriftSafetyLevel.Spaces -> Spaces, - ThriftSafetyLevel.SpacesParticipants -> SpacesParticipants, - ThriftSafetyLevel.SpacesSellerApplicationStatus -> SpacesSellerApplicationStatus, - ThriftSafetyLevel.SpacesSharing -> SpacesSharing, - ThriftSafetyLevel.SpaceTweetAvatarHomeTimeline -> SpaceTweetAvatarHomeTimeline, - ThriftSafetyLevel.StickersTimeline -> StickersTimeline, - ThriftSafetyLevel.StratoExtLimitedEngagements -> StratoExtLimitedEngagements, - ThriftSafetyLevel.StreamServices -> StreamServices, - ThriftSafetyLevel.SuperFollowerConnections -> SuperFollowerConnections, - ThriftSafetyLevel.SuperLike -> SuperLike, - ThriftSafetyLevel.Test -> Test, - ThriftSafetyLevel.TimelineBookmark -> TimelineBookmark, - ThriftSafetyLevel.TimelineContentControls -> TimelineContentControls, - ThriftSafetyLevel.TimelineConversations -> TimelineConversations, - ThriftSafetyLevel.TimelineConversationsDownranking -> TimelineConversationsDownranking, - ThriftSafetyLevel.TimelineConversationsDownrankingMinimal -> TimelineConversationsDownrankingMinimal, - ThriftSafetyLevel.TimelineFavorites -> TimelineFavorites, - ThriftSafetyLevel.TimelineFavoritesSelfView -> TimelineFavoritesSelfView, - ThriftSafetyLevel.TimelineFocalTweet -> TimelineFocalTweet, - ThriftSafetyLevel.TimelineFollowingActivity -> TimelineFollowingActivity, - ThriftSafetyLevel.TimelineHome -> TimelineHome, - ThriftSafetyLevel.TimelineHomeCommunities -> TimelineHomeCommunities, - ThriftSafetyLevel.TimelineHomeHydration -> TimelineHomeHydration, - ThriftSafetyLevel.TimelineHomeLatest -> TimelineHomeLatest, - ThriftSafetyLevel.TimelineHomePromotedHydration -> TimelineHomePromotedHydration, - ThriftSafetyLevel.TimelineHomeRecommendations -> TimelineHomeRecommendations, - ThriftSafetyLevel.TimelineHomeTopicFollowRecommendations -> TimelineHomeTopicFollowRecommendations, - ThriftSafetyLevel.TimelineScorer -> TimelineScorer, - ThriftSafetyLevel.TimelineInjection -> TimelineInjection, - ThriftSafetyLevel.TimelineLikedBy -> TimelineLikedBy, - ThriftSafetyLevel.TimelineLists -> TimelineLists, - ThriftSafetyLevel.TimelineMedia -> TimelineMedia, - ThriftSafetyLevel.TimelineMentions -> TimelineMentions, - ThriftSafetyLevel.TimelineModeratedTweetsHydration -> TimelineModeratedTweetsHydration, - ThriftSafetyLevel.TimelineProfile -> TimelineProfile, - ThriftSafetyLevel.TimelineProfileAll -> TimelineProfileAll, - ThriftSafetyLevel.TimelineProfileSpaces -> TimelineProfileSpaces, - ThriftSafetyLevel.TimelineProfileSuperFollows -> TimelineProfileSuperFollows, - ThriftSafetyLevel.TimelineReactiveBlending -> TimelineReactiveBlending, - ThriftSafetyLevel.TimelineRetweetedBy -> TimelineRetweetedBy, - ThriftSafetyLevel.TimelineSuperLikedBy -> TimelineSuperLikedBy, - ThriftSafetyLevel.Tombstoning -> Tombstoning, - ThriftSafetyLevel.TopicRecommendations -> TopicRecommendations, - ThriftSafetyLevel.TopicsLandingPageTopicRecommendations -> TopicsLandingPageTopicRecommendations, - ThriftSafetyLevel.TrendsRepresentativeTweet -> TrendsRepresentativeTweet, - ThriftSafetyLevel.TrustedFriendsUserList -> TrustedFriendsUserList, - ThriftSafetyLevel.TwitterDelegateUserList -> TwitterDelegateUserList, - ThriftSafetyLevel.GryphonDecksAndColumns -> GryphonDecksAndColumns, - ThriftSafetyLevel.TweetDetail -> TweetDetail, - ThriftSafetyLevel.TweetDetailNonToo -> TweetDetailNonToo, - ThriftSafetyLevel.TweetDetailWithInjectionsHydration -> TweetDetailWithInjectionsHydration, - ThriftSafetyLevel.TweetEngagers -> TweetEngagers, - ThriftSafetyLevel.TweetReplyNudge -> TweetReplyNudge, - ThriftSafetyLevel.TweetScopedTimeline -> TweetScopedTimeline, - ThriftSafetyLevel.TweetWritesApi -> TweetWritesApi, - ThriftSafetyLevel.TwitterArticleCompose -> TwitterArticleCompose, - ThriftSafetyLevel.TwitterArticleProfileTab -> TwitterArticleProfileTab, - ThriftSafetyLevel.TwitterArticleRead -> TwitterArticleRead, - ThriftSafetyLevel.UserProfileHeader -> UserProfileHeader, - ThriftSafetyLevel.UserMilestoneRecommendation -> UserMilestoneRecommendation, - ThriftSafetyLevel.UserScopedTimeline -> UserScopedTimeline, - ThriftSafetyLevel.UserSearchSrp -> UserSearchSrp, - ThriftSafetyLevel.UserSearchTypeahead -> UserSearchTypeahead, - ThriftSafetyLevel.UserSelfViewOnly -> UserSelfViewOnly, - ThriftSafetyLevel.UserSettings -> UserSettings, - ThriftSafetyLevel.VideoAds -> VideoAds, - ThriftSafetyLevel.ZipbirdConsumerArchives -> ZipbirdConsumerArchives, - ThriftSafetyLevel.TweetAward -> TweetAward, - ) - - private lazy val modelToThriftMap: Map[SafetyLevel, ThriftSafetyLevel] = - for ((k, v) <- thriftToModelMap) yield (v, k) - - case object AdsBusinessSettings extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableAdsBusinessSettingsSafetyLevelParam - } - case object AdsCampaign extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableAdsCampaignSafetyLevelParam - } - case object AdsManager extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableAdsManagerSafetyLevelParam - } - case object AdsReportingDashboard extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableAdsReportingDashboardSafetyLevelParam - } - case object AllSubscribedLists extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableAllSubscribedListsSafetyLevelParam - } - case object Appeals extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableAppealsSafetyLevelParam - } - case object ArticleTweetTimeline extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableArticleTweetTimelineSafetyLevelParam - } - case object BaseQig extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableBaseQigSafetyLevelParam - } - case object BirdwatchNoteAuthor extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableBirdwatchNoteAuthorSafetyLevel - } - case object BirdwatchNoteTweetsTimeline extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableBirdwatchNoteTweetsTimelineSafetyLevel - } - case object BirdwatchNeedsYourHelpNotifications extends SafetyLevel { - override val enabledParam: SafetyLevelParam = - EnableBirdwatchNeedsYourHelpNotificationsSafetyLevel - } - case object BlockMuteUsersTimeline extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableBlockMuteUsersTimelineSafetyLevelParam - } - case object BrandSafety extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableBrandSafetySafetyLevelParam - } - case object CardPollVoting extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableCardPollVotingSafetyLevelParam - } - case object CardsService extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableCardsServiceSafetyLevelParam - } - case object Communities extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableCommunitiesSafetyLevelParam - } - case object ContentControlToolInstall extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableContentControlToolInstallSafetyLevelParam - } - case object ConversationFocalPrehydration extends SafetyLevel { - override val enabledParam: SafetyLevelParam = - EnableConversationFocalPrehydrationSafetyLevelParam - } - case object ConversationFocalTweet extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableConversationFocalTweetSafetyLevelParam - } - case object ConversationInjectedTweet extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableConversationInjectedTweetSafetyLevelParam - } - case object ConversationReply extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableConversationReplySafetyLevelParam - } - case object AccessInternalPromotedContent extends SafetyLevel { - override val enabledParam: SafetyLevelParam = - EnableAccessInternalPromotedContentSafetyLevelParam - } - case object CuratedTrendsRepresentativeTweet extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableCuratedTrendsRepresentativeTweet - } - case object CurationPolicyViolations extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableCurationPolicyViolations - } - case object DevPlatformGetListTweets extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableDevPlatformGetListTweetsSafetyLevelParam - } - case object DesFollowingAndFollowersUserList extends SafetyLevel { - override val enabledParam: SafetyLevelParam = - EnableDESFollowingAndFollowersUserListSafetyLevelParam - } - case object DesHomeTimeline extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableDESHomeTimelineSafetyLevelParam - } - case object DesQuoteTweetTimeline extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableDESQuoteTweetTimelineSafetyLevelParam - } - case object DesRealtime extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableDESRealtimeSafetyLevelParam - } - case object DesRealtimeSpamEnrichment extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableDESRealtimeSpamEnrichmentSafetyLevelParam - } - case object DesRealtimeTweetFilter extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableDESRealtimeTweetFilterSafetyLevelParam - } - case object DesRetweetingUsers extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableDESRetweetingUsersSafetyLevelParam - } - case object DesTweetDetail extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableDesTweetDetailSafetyLevelParam - } - case object DesTweetLikingUsers extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableDESTweetLikingUsersSafetyLevelParam - } - case object DesUserBookmarks extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableDESUserBookmarksSafetyLevelParam - } - case object DesUserLikedTweets extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableDESUserLikedTweetSafetyLevelParam - } - case object DesUserMentions extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableDESUserMentionsSafetyLevelParam - } - case object DesUserTweets extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableDESUserTweetsSafetyLevelParam - } - case object DevPlatformComplianceStream extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableDevPlatformComplianceStreamSafetyLevelParam - } - case object DirectMessages extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableDirectMessagesSafetyLevelParam - } - case object DirectMessagesConversationList extends SafetyLevel { - override val enabledParam: SafetyLevelParam = - EnableDirectMessagesConversationListSafetyLevelParam - } - case object DirectMessagesConversationTimeline extends SafetyLevel { - override val enabledParam: SafetyLevelParam = - EnableDirectMessagesConversationTimelineSafetyLevelParam - } - case object DirectMessagesInbox extends SafetyLevel { - override val enabledParam: SafetyLevelParam = - EnableDirectMessagesInboxSafetyLevelParam - } - case object DirectMessagesMutedUsers extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableDirectMessagesMutedUsersSafetyLevelParam - } - case object DirectMessagesPinned extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableDirectMessagesPinnedSafetyLevelParam - } - case object DirectMessagesSearch extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableDirectMessagesSearchSafetyLevelParam - } - case object EditHistoryTimeline extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableEditHistoryTimelineSafetyLevelParam - } - case object ElevatedQuoteTweetTimeline extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableElevatedQuoteTweetTimelineSafetyLevelParam - } - case object EmbeddedTweet extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableEmbeddedTweetSafetyLevelParam - } - case object EmbedsPublicInterestNotice extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableEmbedsPublicInterestNoticeSafetyLevelParam - } - case object EmbedTweetMarkup extends SafetyLevel { - override def enabledParam: SafetyLevelParam = EnableEmbedTweetMarkupSafetyLevelParam - } - case object WritePathLimitedActionsEnforcement extends SafetyLevel { - override def enabledParam: SafetyLevelParam = - EnableWritePathLimitedActionsEnforcementSafetyLevelParam - } - case object FilterNone extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableFilterNoneSafetyLevelParam - } - case object FilterAll extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableFilterAllSafetyLevelParam - } - case object FilterAllPlaceholder extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableFilterDefaultSafetyLevelParam - } - case object FilterDefault extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableFilterDefaultSafetyLevelParam - } - case object FollowedTopicsTimeline extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableFollowedTopicsTimelineSafetyLevelParam - } - case object FollowerConnections extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableFollowerConnectionsSafetyLevelParam - } - case object FollowingAndFollowersUserList extends SafetyLevel { - override val enabledParam: SafetyLevelParam = - EnableFollowingAndFollowersUserListSafetyLevelParam - } - case object ForDevelopmentOnly extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableForDevelopmentOnlySafetyLevelParam - } - case object FriendsFollowingList extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableFriendsFollowingListSafetyLevelParam - } - case object GraphqlDefault extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableGraphqlDefaultSafetyLevelParam - } - case object GryphonDecksAndColumns extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableGryphonDecksAndColumnsSafetyLevelParam - } - case object HumanizationNudge extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableHumanizationNudgeSafetyLevelParam - } - case object KitchenSinkDevelopment extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableKitchenSinkDevelopmentSafetyLevelParam - } - case object ListHeader extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableListHeaderSafetyLevelParam - } - case object ListMemberships extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableListMembershipsSafetyLevelParam - } - case object ListOwnerships extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableListOwnershipsSafetyLevelParam - } - case object ListRecommendations extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableListRecommendationsSafetyLevelParam - } - case object ListSearch extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableListSearchSafetyLevelParam - } - case object ListSubscriptions extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableListSubscriptionsSafetyLevelParam - } - case object LivePipelineEngagementCounts extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableLivePipelineEngagementCountsSafetyLevelParam - } - case object LiveVideoTimeline extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableLiveVideoTimelineSafetyLevelParam - } - case object MagicRecs extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableMagicRecsSafetyLevelParam - } - case object MagicRecsAggressive extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableMagicRecsAggressiveSafetyLevelParam - } - case object MagicRecsAggressiveV2 extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableMagicRecsAggressiveV2SafetyLevelParam - } - case object MagicRecsV2 extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableMagicRecsV2SafetyLevelParam - } - case object Minimal extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableMinimalSafetyLevelParam - } - case object ModeratedTweetsTimeline extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableModeratedTweetsTimelineSafetyLevelParam - } - case object Moments extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableMomentsSafetyLevelParam - } - case object NearbyTimeline extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableNearbySafetyLevelParam - } - case object NewUserExperience extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableNewUserExperienceSafetyLevelParam - } - case object NotificationsIbis extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableNotificationsIbisSafetyLevelParam - } - case object NotificationsPlatform extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableNotificationsPlatformSafetyLevelParam - } - case object NotificationsPlatformPush extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableNotificationsPlatformPushSafetyLevelParam - } - case object NotificationsQig extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableNotificationsQigSafetyLevelParam - } - case object NotificationsRead extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableNotificationsReadSafetyLevelParam - } - case object NotificationsTimelineDeviceFollow extends SafetyLevel { - override val enabledParam: SafetyLevelParam = - EnableNotificationsTimelineDeviceFollowSafetyLevelParam - } - case object NotificationsWrite extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableNotificationsWriteSafetyLevelParam - } - case object NotificationsWriterV2 extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableNotificationsWriterV2SafetyLevelParam - } - case object NotificationsWriterTweetHydrator extends SafetyLevel { - override val enabledParam: SafetyLevelParam = - EnableNotificationsWriterTweetHydratorSafetyLevelParam - } - case object ProfileMixerMedia extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableProfileMixerMediaSafetyLevelParam - } - case object ProfileMixerFavorites extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableProfileMixerFavoritesSafetyLevelParam - } - case object QuickPromoteTweetEligibility extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableQuickPromoteTweetEligibilitySafetyLevelParam - } - case object QuoteTweetTimeline extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableQuoteTweetTimelineSafetyLevelParam - } - case object QuotedTweetRules extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableQuotedTweetRulesParam - } - case object Recommendations extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableRecommendationsSafetyLevelParam - } - case object RecosVideo extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableRecosVideoSafetyLevelParam - } - case object RecosWritePath extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableRecosWritePathSafetyLevelParam - } - case object RepliesGrouping extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableRepliesGroupingSafetyLevelParam - } - case object ReportCenter extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableReportCenterSafetyLevelParam - } - case object ReturningUserExperience extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableReturningUserExperienceSafetyLevelParam - } - case object ReturningUserExperienceFocalTweet extends SafetyLevel { - override val enabledParam: SafetyLevelParam = - EnableReturningUserExperienceFocalTweetSafetyLevelParam - } - case object Revenue extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableRevenueSafetyLevelParam - } - case object RitoActionedTweetTimeline extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableRitoActionedTweetTimelineParam - } - case object SafeSearchMinimal extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSafeSearchMinimalSafetyLevelParam - } - case object SafeSearchStrict extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSafeSearchStrictSafetyLevelParam - } - case object SearchHydration extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSearchHydrationSafetyLevelParam - } - case object SearchLatest extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSearchLatestSafetyLevelParam - } - case object SearchMixerSrpMinimal extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSearchMixerSrpMinimalSafetyLevelParam - } - case object SearchMixerSrpStrict extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSearchMixerSrpStrictSafetyLevelParam - } - case object SearchPeopleSrp extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSearchPeopleSearchResultPageSafetyLevelParam - } - case object SearchPeopleTypeahead extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSearchPeopleTypeaheadSafetyLevelParam - } - case object SearchPhoto extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSearchPhotoSafetyLevelParam - } - case object ShoppingManagerSpyMode extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableShoppingManagerSpyModeSafetyLevelParam - } - case object StratoExtLimitedEngagements extends SafetyLevel { - override val enabledParam: SafetyLevelParam = - EnableStratoExtLimitedEngagementsSafetyLevelParam - } - case object SearchTop extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSearchTopSafetyLevelParam - } - case object SearchTopQig extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSearchTopQigSafetyLevelParam - } - case object SearchTrendTakeoverPromotedTweet extends SafetyLevel { - override val enabledParam: SafetyLevelParam = SearchTrendTakeoverPromotedTweetSafetyLevelParam - } - case object SearchVideo extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSearchVideoSafetyLevelParam - } - case object SearchBlenderUserRules extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSearchBlenderUserRulesSafetyLevelParam - } - case object SearchLatestUserRules extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSearchLatestUserRulesSafetyLevelParam - } - case object SignalsReactions extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSignalsReactionsSafetyLevelParam - } - case object SignalsTweetReactingUsers extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSignalsTweetReactingUsersSafetyLevelParam - } - case object SocialProof extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSocialProofSafetyLevelParam - } - case object SoftInterventionPivot extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSoftInterventionPivotSafetyLevelParam - } - case object SpaceFleetline extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSpaceFleetlineSafetyLevelParam - } - case object SpaceHomeTimelineUpranking extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSpaceHomeTimelineUprankingSafetyLevelParam - } - case object SpaceJoinScreen extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSpaceJoinScreenSafetyLevelParam - } - case object SpaceNotifications extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSpaceNotificationSafetyLevelParam - } - case object Spaces extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSpacesSafetyLevelParam - } - case object SpacesParticipants extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSpacesParticipantsSafetyLevelParam - } - case object SpacesSellerApplicationStatus extends SafetyLevel { - override val enabledParam: SafetyLevelParam = - EnableSpacesSellerApplicationStatusSafetyLevelParam - } - case object SpacesSharing extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSpacesSharingSafetyLevelParam - } - case object SpaceTweetAvatarHomeTimeline extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSpaceTweetAvatarHomeTimelineSafetyLevelParam - } - case object StickersTimeline extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableStickersTimelineSafetyLevelParam - } - case object StreamServices extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableStreamServicesSafetyLevelParam - } - case object SuperFollowerConnections extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSuperFollowerConnectionsSafetyLevelParam - } - case object SuperLike extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableSuperLikeSafetyLevelParam - } - case object Test extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTestSafetyLevelParam - } - case object TimelineConversations extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTimelineConversationsSafetyLevelParam - } - case object TimelineConversationsDownranking extends SafetyLevel { - override val enabledParam: SafetyLevelParam = - EnableTimelineConversationsDownrankingSafetyLevelParam - } - case object TimelineConversationsDownrankingMinimal extends SafetyLevel { - override val enabledParam: SafetyLevelParam = - EnableTimelineConversationsDownrankingMinimalSafetyLevelParam - } - case object TimelineFollowingActivity extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTimelineFollowingActivitySafetyLevelParam - } - case object TimelineHome extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTimelineHomeSafetyLevelParam - } - case object TimelineHomeCommunities extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTimelineHomeCommunitiesSafetyLevelParam - } - case object TimelineHomeHydration extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTimelineHomeHydrationSafetyLevelParam - } - case object TimelineHomePromotedHydration extends SafetyLevel { - override val enabledParam: SafetyLevelParam = - EnableTimelineHomePromotedHydrationSafetyLevelParam - } - case object TimelineHomeRecommendations extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTimelineHomeRecommendationsSafetyLevelParam - } - case object TimelineHomeTopicFollowRecommendations extends SafetyLevel { - override val enabledParam: SafetyLevelParam = - EnableTimelineHomeTopicFollowRecommendationsSafetyLevelParam - } - case object TimelineScorer extends SafetyLevel { - override val enabledParam: SafetyLevelParam = - EnableTimelineScorerSafetyLevelParam - } - case object TopicsLandingPageTopicRecommendations extends SafetyLevel { - override val enabledParam: SafetyLevelParam = - EnableTopicsLandingPageTopicRecommendationsSafetyLevelParam - } - case object ExploreRecommendations extends SafetyLevel { - override val enabledParam: SafetyLevelParam = - EnableExploreRecommendationsSafetyLevelParam - } - case object TimelineModeratedTweetsHydration extends SafetyLevel { - override val enabledParam: SafetyLevelParam = - EnableTimelineModeratedTweetsHydrationSafetyLevelParam - } - case object TimelineInjection extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTimelineInjectionSafetyLevelParam - } - case object TimelineMentions extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTimelineMentionsSafetyLevelParam - } - case object TimelineHomeLatest extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTimelineHomeLatestSafetyLevelParam - } - case object TimelineLikedBy extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTimelineLikedBySafetyLevelParam - } - case object TimelineRetweetedBy extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTimelineRetweetedBySafetyLevelParam - } - case object TimelineSuperLikedBy extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTimelineLikedBySafetyLevelParam - } - case object TimelineBookmark extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTimelineBookmarkSafetyLevelParam - } - case object TimelineContentControls extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTimelineContentControlsSafetyLevelParam - } - case object TimelineMedia extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTimelineMediaSafetyLevelParam - } - case object TimelineReactiveBlending extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTimelineReactiveBlendingSafetyLevelParam - } - case object TimelineFavorites extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTimelineFavoritesSafetyLevelParam - } - case object TimelineFavoritesSelfView extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTimelineFavoritesSelfViewSafetyLevelParam - } - case object TimelineLists extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTimelineListsSafetyLevelParam - } - case object TimelineProfile extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTimelineProfileSafetyLevelParam - } - case object TimelineProfileAll extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTimelineProfileAllSafetyLevelParam - } - - case object TimelineProfileSpaces extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTimelineProfileSpacesSafetyLevelParam - } - - case object TimelineProfileSuperFollows extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTimelineProfileSuperFollowsSafetyLevelParam - } - case object TimelineFocalTweet extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTimelineFocalTweetSafetyLevelParam - } - case object Tombstoning extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTombstoningSafetyLevelParam - } - case object TopicRecommendations extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTopicRecommendationsSafetyLevelParam - } - case object TrendsRepresentativeTweet extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTrendsRepresentativeTweetSafetyLevelParam - } - case object TrustedFriendsUserList extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTrustedFriendsUserListSafetyLevelParam - } - case object TwitterDelegateUserList extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTwitterDelegateUserListSafetyLevelParam - } - case object TweetDetail extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTweetDetailSafetyLevelParam - } - case object TweetDetailNonToo extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTweetDetailNonTooSafetyLevelParam - } - case object TweetDetailWithInjectionsHydration extends SafetyLevel { - override val enabledParam: SafetyLevelParam = - EnableTweetDetailWithInjectionsHydrationSafetyLevelParam - } - case object TweetEngagers extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTweetEngagersSafetyLevelParam - } - case object TweetReplyNudge extends SafetyLevel { - override def enabledParam: SafetyLevelParam = EnableTweetReplyNudgeParam - } - case object TweetScopedTimeline extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTweetScopedTimelineSafetyLevelParam - } - case object TweetWritesApi extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTweetWritesApiSafetyLevelParam - } - case object TwitterArticleCompose extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTwitterArticleComposeSafetyLevelParam - } - case object TwitterArticleProfileTab extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTwitterArticleProfileTabSafetyLevelParam - } - case object TwitterArticleRead extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTwitterArticleReadSafetyLevelParam - } - case object UserProfileHeader extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableUserProfileHeaderSafetyLevelParam - } - case object UserMilestoneRecommendation extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableUserMilestoneRecommendationSafetyLevelParam - } - case object UserScopedTimeline extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableUserScopedTimelineSafetyLevelParam - } - case object UserSearchSrp extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableUserSearchSrpSafetyLevelParam - } - case object UserSearchTypeahead extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableUserSearchTypeaheadSafetyLevelParam - } - case object UserSelfViewOnly extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableUserSelfViewOnlySafetyLevelParam - } - case object UserSettings extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableUserSettingsSafetyLevelParam - } - case object VideoAds extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableVideoAdsSafetyLevelParam - } - case object ZipbirdConsumerArchives extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableZipbirdConsumerArchivesSafetyLevelParam - } - case object TweetAward extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableTweetAwardSafetyLevelParam - } - - case object DeprecatedSafetyLevel extends SafetyLevel { - override val enabledParam: SafetyLevelParam = EnableDeprecatedSafetyLevel - } - - - def fromThrift(safetyLevel: ThriftSafetyLevel): SafetyLevel = - thriftToModelMap.get(safetyLevel).getOrElse(DeprecatedSafetyLevel) - - def toThrift(safetyLevel: SafetyLevel): ThriftSafetyLevel = - modelToThriftMap - .get(safetyLevel).getOrElse(ThriftSafetyLevel.EnumUnknownSafetyLevel(DeprecatedEnumValue)) - - val List: Seq[SafetyLevel] = - ThriftSafetyLevel.list.map(fromThrift).filter(_ != DeprecatedSafetyLevel) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLevelGroup.scala b/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLevelGroup.scala deleted file mode 100644 index a9ebfa85c..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLevelGroup.scala +++ /dev/null @@ -1,554 +0,0 @@ -package com.twitter.visibility.models - -import com.twitter.visibility.models.SafetyLevel.AccessInternalPromotedContent -import com.twitter.visibility.models.SafetyLevel.AdsBusinessSettings -import com.twitter.visibility.models.SafetyLevel.AdsCampaign -import com.twitter.visibility.models.SafetyLevel.AdsManager -import com.twitter.visibility.models.SafetyLevel.AdsReportingDashboard -import com.twitter.visibility.models.SafetyLevel.AllSubscribedLists -import com.twitter.visibility.models.SafetyLevel.Appeals -import com.twitter.visibility.models.SafetyLevel.ArticleTweetTimeline -import com.twitter.visibility.models.SafetyLevel.BaseQig -import com.twitter.visibility.models.SafetyLevel.BirdwatchNeedsYourHelpNotifications -import com.twitter.visibility.models.SafetyLevel.BirdwatchNoteAuthor -import com.twitter.visibility.models.SafetyLevel.BirdwatchNoteTweetsTimeline -import com.twitter.visibility.models.SafetyLevel.BlockMuteUsersTimeline -import com.twitter.visibility.models.SafetyLevel.BrandSafety -import com.twitter.visibility.models.SafetyLevel.CardPollVoting -import com.twitter.visibility.models.SafetyLevel.CardsService -import com.twitter.visibility.models.SafetyLevel.ContentControlToolInstall -import com.twitter.visibility.models.SafetyLevel.ConversationFocalPrehydration -import com.twitter.visibility.models.SafetyLevel.ConversationFocalTweet -import com.twitter.visibility.models.SafetyLevel.ConversationInjectedTweet -import com.twitter.visibility.models.SafetyLevel.ConversationReply -import com.twitter.visibility.models.SafetyLevel.CuratedTrendsRepresentativeTweet -import com.twitter.visibility.models.SafetyLevel.CurationPolicyViolations -import com.twitter.visibility.models.SafetyLevel.DesFollowingAndFollowersUserList -import com.twitter.visibility.models.SafetyLevel.DesHomeTimeline -import com.twitter.visibility.models.SafetyLevel.DesQuoteTweetTimeline -import com.twitter.visibility.models.SafetyLevel.DesRealtime -import com.twitter.visibility.models.SafetyLevel.DesRealtimeSpamEnrichment -import com.twitter.visibility.models.SafetyLevel.DesRealtimeTweetFilter -import com.twitter.visibility.models.SafetyLevel.DesRetweetingUsers -import com.twitter.visibility.models.SafetyLevel.DesTweetDetail -import com.twitter.visibility.models.SafetyLevel.DesTweetLikingUsers -import com.twitter.visibility.models.SafetyLevel.DesUserBookmarks -import com.twitter.visibility.models.SafetyLevel.DesUserLikedTweets -import com.twitter.visibility.models.SafetyLevel.DesUserMentions -import com.twitter.visibility.models.SafetyLevel.DesUserTweets -import com.twitter.visibility.models.SafetyLevel.DevPlatformComplianceStream -import com.twitter.visibility.models.SafetyLevel.DevPlatformGetListTweets -import com.twitter.visibility.models.SafetyLevel.DirectMessages -import com.twitter.visibility.models.SafetyLevel.DirectMessagesConversationList -import com.twitter.visibility.models.SafetyLevel.DirectMessagesConversationTimeline -import com.twitter.visibility.models.SafetyLevel.DirectMessagesInbox -import com.twitter.visibility.models.SafetyLevel.DirectMessagesMutedUsers -import com.twitter.visibility.models.SafetyLevel.DirectMessagesPinned -import com.twitter.visibility.models.SafetyLevel.DirectMessagesSearch -import com.twitter.visibility.models.SafetyLevel.EditHistoryTimeline -import com.twitter.visibility.models.SafetyLevel.ElevatedQuoteTweetTimeline -import com.twitter.visibility.models.SafetyLevel.EmbedTweetMarkup -import com.twitter.visibility.models.SafetyLevel.EmbeddedTweet -import com.twitter.visibility.models.SafetyLevel.EmbedsPublicInterestNotice -import com.twitter.visibility.models.SafetyLevel.ExploreRecommendations -import com.twitter.visibility.models.SafetyLevel.FilterAll -import com.twitter.visibility.models.SafetyLevel.FilterAllPlaceholder -import com.twitter.visibility.models.SafetyLevel.FilterDefault -import com.twitter.visibility.models.SafetyLevel.FilterNone -import com.twitter.visibility.models.SafetyLevel.FollowedTopicsTimeline -import com.twitter.visibility.models.SafetyLevel.FollowerConnections -import com.twitter.visibility.models.SafetyLevel.FollowingAndFollowersUserList -import com.twitter.visibility.models.SafetyLevel.ForDevelopmentOnly -import com.twitter.visibility.models.SafetyLevel.FriendsFollowingList -import com.twitter.visibility.models.SafetyLevel.GraphqlDefault -import com.twitter.visibility.models.SafetyLevel.GryphonDecksAndColumns -import com.twitter.visibility.models.SafetyLevel.HumanizationNudge -import com.twitter.visibility.models.SafetyLevel.KitchenSinkDevelopment -import com.twitter.visibility.models.SafetyLevel.ListHeader -import com.twitter.visibility.models.SafetyLevel.ListMemberships -import com.twitter.visibility.models.SafetyLevel.ListOwnerships -import com.twitter.visibility.models.SafetyLevel.ListRecommendations -import com.twitter.visibility.models.SafetyLevel.ListSearch -import com.twitter.visibility.models.SafetyLevel.ListSubscriptions -import com.twitter.visibility.models.SafetyLevel.LivePipelineEngagementCounts -import com.twitter.visibility.models.SafetyLevel.LiveVideoTimeline -import com.twitter.visibility.models.SafetyLevel.MagicRecs -import com.twitter.visibility.models.SafetyLevel.MagicRecsAggressive -import com.twitter.visibility.models.SafetyLevel.MagicRecsAggressiveV2 -import com.twitter.visibility.models.SafetyLevel.MagicRecsV2 -import com.twitter.visibility.models.SafetyLevel.Minimal -import com.twitter.visibility.models.SafetyLevel.ModeratedTweetsTimeline -import com.twitter.visibility.models.SafetyLevel.Moments -import com.twitter.visibility.models.SafetyLevel.NearbyTimeline -import com.twitter.visibility.models.SafetyLevel.NewUserExperience -import com.twitter.visibility.models.SafetyLevel.NotificationsIbis -import com.twitter.visibility.models.SafetyLevel.NotificationsPlatform -import com.twitter.visibility.models.SafetyLevel.NotificationsPlatformPush -import com.twitter.visibility.models.SafetyLevel.NotificationsQig -import com.twitter.visibility.models.SafetyLevel.NotificationsRead -import com.twitter.visibility.models.SafetyLevel.NotificationsTimelineDeviceFollow -import com.twitter.visibility.models.SafetyLevel.NotificationsWrite -import com.twitter.visibility.models.SafetyLevel.NotificationsWriterTweetHydrator -import com.twitter.visibility.models.SafetyLevel.NotificationsWriterV2 -import com.twitter.visibility.models.SafetyLevel.ProfileMixerFavorites -import com.twitter.visibility.models.SafetyLevel.ProfileMixerMedia -import com.twitter.visibility.models.SafetyLevel.QuickPromoteTweetEligibility -import com.twitter.visibility.models.SafetyLevel.QuoteTweetTimeline -import com.twitter.visibility.models.SafetyLevel.QuotedTweetRules -import com.twitter.visibility.models.SafetyLevel.RecosVideo -import com.twitter.visibility.models.SafetyLevel.RecosWritePath -import com.twitter.visibility.models.SafetyLevel.RepliesGrouping -import com.twitter.visibility.models.SafetyLevel.ReportCenter -import com.twitter.visibility.models.SafetyLevel.ReturningUserExperienceFocalTweet -import com.twitter.visibility.models.SafetyLevel.Revenue -import com.twitter.visibility.models.SafetyLevel.SafeSearchMinimal -import com.twitter.visibility.models.SafetyLevel.SafeSearchStrict -import com.twitter.visibility.models.SafetyLevel.SearchBlenderUserRules -import com.twitter.visibility.models.SafetyLevel.SearchHydration -import com.twitter.visibility.models.SafetyLevel.SearchLatest -import com.twitter.visibility.models.SafetyLevel.SearchLatestUserRules -import com.twitter.visibility.models.SafetyLevel.SearchMixerSrpMinimal -import com.twitter.visibility.models.SafetyLevel.SearchMixerSrpStrict -import com.twitter.visibility.models.SafetyLevel.SearchPeopleSrp -import com.twitter.visibility.models.SafetyLevel.SearchPeopleTypeahead -import com.twitter.visibility.models.SafetyLevel.SearchPhoto -import com.twitter.visibility.models.SafetyLevel.SearchTop -import com.twitter.visibility.models.SafetyLevel.SearchTopQig -import com.twitter.visibility.models.SafetyLevel.SearchTrendTakeoverPromotedTweet -import com.twitter.visibility.models.SafetyLevel.SearchVideo -import com.twitter.visibility.models.SafetyLevel.ShoppingManagerSpyMode -import com.twitter.visibility.models.SafetyLevel.SignalsReactions -import com.twitter.visibility.models.SafetyLevel.SignalsTweetReactingUsers -import com.twitter.visibility.models.SafetyLevel.SoftInterventionPivot -import com.twitter.visibility.models.SafetyLevel.SpaceFleetline -import com.twitter.visibility.models.SafetyLevel.SpaceHomeTimelineUpranking -import com.twitter.visibility.models.SafetyLevel.SpaceJoinScreen -import com.twitter.visibility.models.SafetyLevel.SpaceNotifications -import com.twitter.visibility.models.SafetyLevel.SpaceTweetAvatarHomeTimeline -import com.twitter.visibility.models.SafetyLevel.SpacesParticipants -import com.twitter.visibility.models.SafetyLevel.SpacesSellerApplicationStatus -import com.twitter.visibility.models.SafetyLevel.SpacesSharing -import com.twitter.visibility.models.SafetyLevel.StickersTimeline -import com.twitter.visibility.models.SafetyLevel.StratoExtLimitedEngagements -import com.twitter.visibility.models.SafetyLevel.StreamServices -import com.twitter.visibility.models.SafetyLevel.SuperFollowerConnections -import com.twitter.visibility.models.SafetyLevel.SuperLike -import com.twitter.visibility.models.SafetyLevel.Test -import com.twitter.visibility.models.SafetyLevel.TimelineBookmark -import com.twitter.visibility.models.SafetyLevel.TimelineContentControls -import com.twitter.visibility.models.SafetyLevel.TimelineConversations -import com.twitter.visibility.models.SafetyLevel.TimelineConversationsDownranking -import com.twitter.visibility.models.SafetyLevel.TimelineConversationsDownrankingMinimal -import com.twitter.visibility.models.SafetyLevel.TimelineFavorites -import com.twitter.visibility.models.SafetyLevel.TimelineFavoritesSelfView -import com.twitter.visibility.models.SafetyLevel.TimelineFocalTweet -import com.twitter.visibility.models.SafetyLevel.TimelineFollowingActivity -import com.twitter.visibility.models.SafetyLevel.TimelineHomeCommunities -import com.twitter.visibility.models.SafetyLevel.TimelineHomeHydration -import com.twitter.visibility.models.SafetyLevel.TimelineHomeLatest -import com.twitter.visibility.models.SafetyLevel.TimelineHomePromotedHydration -import com.twitter.visibility.models.SafetyLevel.TimelineHomeRecommendations -import com.twitter.visibility.models.SafetyLevel.TimelineHomeTopicFollowRecommendations -import com.twitter.visibility.models.SafetyLevel.TimelineInjection -import com.twitter.visibility.models.SafetyLevel.TimelineLikedBy -import com.twitter.visibility.models.SafetyLevel.TimelineLists -import com.twitter.visibility.models.SafetyLevel.TimelineMedia -import com.twitter.visibility.models.SafetyLevel.TimelineMentions -import com.twitter.visibility.models.SafetyLevel.TimelineModeratedTweetsHydration -import com.twitter.visibility.models.SafetyLevel.TimelineProfileAll -import com.twitter.visibility.models.SafetyLevel.TimelineProfileSpaces -import com.twitter.visibility.models.SafetyLevel.TimelineProfileSuperFollows -import com.twitter.visibility.models.SafetyLevel.TimelineScorer -import com.twitter.visibility.models.SafetyLevel.Tombstoning -import com.twitter.visibility.models.SafetyLevel.TopicsLandingPageTopicRecommendations -import com.twitter.visibility.models.SafetyLevel.TrendsRepresentativeTweet -import com.twitter.visibility.models.SafetyLevel.TrustedFriendsUserList -import com.twitter.visibility.models.SafetyLevel.TweetDetail -import com.twitter.visibility.models.SafetyLevel.TweetDetailNonToo -import com.twitter.visibility.models.SafetyLevel.TweetDetailWithInjectionsHydration -import com.twitter.visibility.models.SafetyLevel.TweetEngagers -import com.twitter.visibility.models.SafetyLevel.TweetReplyNudge -import com.twitter.visibility.models.SafetyLevel.TweetWritesApi -import com.twitter.visibility.models.SafetyLevel.TwitterArticleCompose -import com.twitter.visibility.models.SafetyLevel.TwitterArticleProfileTab -import com.twitter.visibility.models.SafetyLevel.TwitterArticleRead -import com.twitter.visibility.models.SafetyLevel.UserMilestoneRecommendation -import com.twitter.visibility.models.SafetyLevel.UserProfileHeader -import com.twitter.visibility.models.SafetyLevel.UserSelfViewOnly -import com.twitter.visibility.models.SafetyLevel.UserSettings -import com.twitter.visibility.models.SafetyLevel.VideoAds -import com.twitter.visibility.models.SafetyLevel.WritePathLimitedActionsEnforcement -import com.twitter.visibility.models.SafetyLevel.ZipbirdConsumerArchives - -sealed trait SafetyLevelGroup { val levels: Set[SafetyLevel] } - -object SafetyLevelGroup { - case object Ads extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - AdsBusinessSettings, - AdsCampaign, - AdsManager, - AdsReportingDashboard, - BrandSafety, - VideoAds, - QuickPromoteTweetEligibility - ) - } - - case object ArticleTimeline extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - ArticleTweetTimeline, - ) - } - - case object ArticleTweets extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - TwitterArticleCompose, - TwitterArticleProfileTab, - TwitterArticleRead, - ) - } - - case object Birdwatch extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - BirdwatchNoteAuthor, - BirdwatchNoteTweetsTimeline, - BirdwatchNeedsYourHelpNotifications, - ) - } - - case object Cards extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - CardPollVoting, - CardsService, - ) - } - - case object Communities extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - SafetyLevel.Communities - ) - } - - case object Conversation extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - ConversationFocalPrehydration, - ConversationFocalTweet, - ConversationInjectedTweet, - ConversationReply, - Tombstoning, - ) - } - - case object CreativeContainerService extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - AccessInternalPromotedContent - ) - } - - case object Des extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - DevPlatformGetListTweets, - DesFollowingAndFollowersUserList, - DesHomeTimeline, - DesQuoteTweetTimeline, - DesRetweetingUsers, - DesTweetDetail, - DesTweetLikingUsers, - DesUserBookmarks, - DesUserLikedTweets, - DesUserMentions, - DesUserTweets, - DevPlatformComplianceStream, - ) - } - - case object DesStream extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - DesRealtime, - DesRealtimeSpamEnrichment, - DesRealtimeTweetFilter, - ) - } - - case object Dm extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - DirectMessages, - DirectMessagesConversationList, - DirectMessagesConversationTimeline, - DirectMessagesInbox, - DirectMessagesMutedUsers, - DirectMessagesPinned, - DirectMessagesSearch, - ) - } - - case object Followers extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - FollowedTopicsTimeline, - FollowerConnections, - FollowingAndFollowersUserList, - FriendsFollowingList, - ) - } - - case object Graphql extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - FilterDefault, - GraphqlDefault, - SoftInterventionPivot, - ) - } - - case object Jiminy extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - HumanizationNudge, - TweetReplyNudge, - ) - } - - case object Lists extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - AllSubscribedLists, - ListHeader, - ListMemberships, - ListOwnerships, - ListRecommendations, - ListSearch, - ListSubscriptions, - ) - } - - case object Notifications extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - NotificationsIbis, - NotificationsPlatform, - NotificationsPlatformPush, - NotificationsQig, - NotificationsRead, - NotificationsTimelineDeviceFollow, - NotificationsWrite, - NotificationsWriterTweetHydrator, - NotificationsWriterV2, - ) - } - - case object Other extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - CuratedTrendsRepresentativeTweet, - CurationPolicyViolations, - BaseQig, - Appeals, - ContentControlToolInstall, - EditHistoryTimeline, - ElevatedQuoteTweetTimeline, - EmbeddedTweet, - EmbedsPublicInterestNotice, - EmbedTweetMarkup, - ExploreRecommendations, - WritePathLimitedActionsEnforcement, - LiveVideoTimeline, - LivePipelineEngagementCounts, - Minimal, - Moments, - NearbyTimeline, - NewUserExperience, - QuoteTweetTimeline, - QuotedTweetRules, - ReportCenter, - Revenue, - ShoppingManagerSpyMode, - StickersTimeline, - SuperLike, - TrendsRepresentativeTweet, - TrustedFriendsUserList, - GryphonDecksAndColumns, - TweetEngagers, - TweetWritesApi, - UserMilestoneRecommendation, - StreamServices, - ZipbirdConsumerArchives - ) - } - - case object Profile extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - UserProfileHeader, - UserSelfViewOnly, - UserSettings, - ) - } - - case object Reactions extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - SignalsReactions, - SignalsTweetReactingUsers, - ) - } - - case object Recommendations extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - MagicRecs, - MagicRecsV2, - MagicRecsAggressive, - MagicRecsAggressiveV2, - SafetyLevel.Recommendations, - RecosVideo, - RecosWritePath, - ) - } - - case object ReturningUserExperience extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - SafetyLevel.ReturningUserExperience, - ReturningUserExperienceFocalTweet, - ) - } - - case object SafeSearch extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - SafeSearchMinimal, - SafeSearchStrict, - ) - } - - case object Search extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - SearchHydration, - SearchLatest, - SearchTop, - SearchTopQig, - SearchPeopleSrp, - SearchPeopleTypeahead, - SearchPhoto, - SearchTrendTakeoverPromotedTweet, - SearchVideo, - SearchBlenderUserRules, - SearchLatestUserRules, - ) - } - - case object SearchMixer extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - SearchMixerSrpMinimal, - SearchMixerSrpStrict, - ) - } - - case object Socialproof extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - SafetyLevel.SocialProof - ) - } - - case object Spaces extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - SpaceFleetline, - SpaceHomeTimelineUpranking, - SpaceJoinScreen, - SpaceNotifications, - SafetyLevel.Spaces, - SpacesParticipants, - SpacesSellerApplicationStatus, - SpacesSharing, - SpaceTweetAvatarHomeTimeline, - ) - } - - case object Strato extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - StratoExtLimitedEngagements - ) - } - - case object Superfollows extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - SuperFollowerConnections, - TimelineProfileSuperFollows, - ) - } - - case object Testing extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - ForDevelopmentOnly, - KitchenSinkDevelopment, - Test, - ) - } - - case object Timeline extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - BlockMuteUsersTimeline, - TimelineBookmark, - TimelineContentControls, - TimelineConversationsDownranking, - TimelineConversationsDownrankingMinimal, - TimelineFavorites, - TimelineFavoritesSelfView, - TimelineFollowingActivity, - TimelineScorer, - TimelineInjection, - TimelineLikedBy, - TimelineLists, - TimelineMedia, - TimelineMentions, - ModeratedTweetsTimeline, - TimelineModeratedTweetsHydration, - ) - } - - case object TopicRecommendations extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - SafetyLevel.TopicRecommendations, - TopicsLandingPageTopicRecommendations, - ) - } - - case object TimelineProfile extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - SafetyLevel.TimelineProfile, - TimelineProfileAll, - TimelineProfileSpaces, - TimelineMedia, - ProfileMixerMedia, - TimelineFavorites, - ProfileMixerFavorites - ) - } - - case object TimelineHome extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - SafetyLevel.TimelineHome, - TimelineHomeCommunities, - TimelineHomeHydration, - TimelineHomeLatest, - TimelineHomePromotedHydration, - TimelineHomeRecommendations, - TimelineHomeTopicFollowRecommendations, - ) - } - - case object TlsApi extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - TimelineConversations, - TimelineFocalTweet, - ) - } - - case object TweetDetails extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - TweetDetail, - TweetDetailNonToo, - TweetDetailWithInjectionsHydration, - RepliesGrouping, - ) - } - - case object Special extends SafetyLevelGroup { - override val levels: Set[SafetyLevel] = Set( - FilterAll, - FilterAllPlaceholder, - FilterNone, - ) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/SemanticCoreAnnotation.scala b/visibilitylib/src/main/scala/com/twitter/visibility/models/SemanticCoreAnnotation.scala deleted file mode 100644 index c3d651422..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/SemanticCoreAnnotation.scala +++ /dev/null @@ -1,3 +0,0 @@ -package com.twitter.visibility.models - -case class SemanticCoreAnnotation(groupId: Long, domainId: Long, entityId: Long) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/SpaceSafetyLabelType.scala b/visibilitylib/src/main/scala/com/twitter/visibility/models/SpaceSafetyLabelType.scala deleted file mode 100644 index bab719e21..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/SpaceSafetyLabelType.scala +++ /dev/null @@ -1,91 +0,0 @@ -package com.twitter.visibility.models - -import com.twitter.visibility.safety_label_store.{thriftscala => s} -import com.twitter.visibility.util.NamingUtils - -sealed trait SpaceSafetyLabelType extends SafetyLabelType { - lazy val name: String = NamingUtils.getFriendlyName(this) -} - -object SpaceSafetyLabelType extends SafetyLabelType { - - val List: List[SpaceSafetyLabelType] = s.SpaceSafetyLabelType.list.map(fromThrift) - - val ActiveLabels: List[SpaceSafetyLabelType] = List.filter { labelType => - labelType != Unknown && labelType != Deprecated - } - - private lazy val nameToValueMap: Map[String, SpaceSafetyLabelType] = - List.map(l => l.name.toLowerCase -> l).toMap - def fromName(name: String): Option[SpaceSafetyLabelType] = nameToValueMap.get(name.toLowerCase) - - private val UnknownThriftSafetyLabelType = - s.SpaceSafetyLabelType.EnumUnknownSpaceSafetyLabelType(UnknownEnumValue) - - private lazy val thriftToModelMap: Map[s.SpaceSafetyLabelType, SpaceSafetyLabelType] = Map( - s.SpaceSafetyLabelType.DoNotAmplify -> DoNotAmplify, - s.SpaceSafetyLabelType.CoordinatedHarmfulActivityHighRecall -> CoordinatedHarmfulActivityHighRecall, - s.SpaceSafetyLabelType.UntrustedUrl -> UntrustedUrl, - s.SpaceSafetyLabelType.MisleadingHighRecall -> MisleadingHighRecall, - s.SpaceSafetyLabelType.NsfwHighPrecision -> NsfwHighPrecision, - s.SpaceSafetyLabelType.NsfwHighRecall -> NsfwHighRecall, - s.SpaceSafetyLabelType.CivicIntegrityMisinfo -> CivicIntegrityMisinfo, - s.SpaceSafetyLabelType.MedicalMisinfo -> MedicalMisinfo, - s.SpaceSafetyLabelType.GenericMisinfo -> GenericMisinfo, - s.SpaceSafetyLabelType.DmcaWithheld -> DmcaWithheld, - s.SpaceSafetyLabelType.HatefulHighRecall -> HatefulHighRecall, - s.SpaceSafetyLabelType.ViolenceHighRecall -> ViolenceHighRecall, - s.SpaceSafetyLabelType.HighToxicityModelScore -> HighToxicityModelScore, - s.SpaceSafetyLabelType.DeprecatedSpaceSafetyLabel14 -> Deprecated, - s.SpaceSafetyLabelType.DeprecatedSpaceSafetyLabel15 -> Deprecated, - s.SpaceSafetyLabelType.Reserved16 -> Deprecated, - s.SpaceSafetyLabelType.Reserved17 -> Deprecated, - s.SpaceSafetyLabelType.Reserved18 -> Deprecated, - s.SpaceSafetyLabelType.Reserved19 -> Deprecated, - s.SpaceSafetyLabelType.Reserved20 -> Deprecated, - s.SpaceSafetyLabelType.Reserved21 -> Deprecated, - s.SpaceSafetyLabelType.Reserved22 -> Deprecated, - s.SpaceSafetyLabelType.Reserved23 -> Deprecated, - s.SpaceSafetyLabelType.Reserved24 -> Deprecated, - s.SpaceSafetyLabelType.Reserved25 -> Deprecated, - ) - - private lazy val modelToThriftMap: Map[SpaceSafetyLabelType, s.SpaceSafetyLabelType] = - (for ((k, v) <- thriftToModelMap) yield (v, k)) ++ Map( - Deprecated -> s.SpaceSafetyLabelType.EnumUnknownSpaceSafetyLabelType(DeprecatedEnumValue), - ) - - case object DoNotAmplify extends SpaceSafetyLabelType - case object CoordinatedHarmfulActivityHighRecall extends SpaceSafetyLabelType - case object UntrustedUrl extends SpaceSafetyLabelType - case object MisleadingHighRecall extends SpaceSafetyLabelType - case object NsfwHighPrecision extends SpaceSafetyLabelType - case object NsfwHighRecall extends SpaceSafetyLabelType - case object CivicIntegrityMisinfo extends SpaceSafetyLabelType - case object MedicalMisinfo extends SpaceSafetyLabelType - case object GenericMisinfo extends SpaceSafetyLabelType - case object DmcaWithheld extends SpaceSafetyLabelType - case object HatefulHighRecall extends SpaceSafetyLabelType - case object ViolenceHighRecall extends SpaceSafetyLabelType - case object HighToxicityModelScore extends SpaceSafetyLabelType - - case object Deprecated extends SpaceSafetyLabelType - case object Unknown extends SpaceSafetyLabelType - - def fromThrift(safetyLabelType: s.SpaceSafetyLabelType): SpaceSafetyLabelType = - thriftToModelMap.get(safetyLabelType) match { - case Some(spaceSafetyLabelType) => spaceSafetyLabelType - case _ => - safetyLabelType match { - case s.SpaceSafetyLabelType.EnumUnknownSpaceSafetyLabelType(DeprecatedEnumValue) => - Deprecated - case _ => - Unknown - } - } - - def toThrift(safetyLabelType: SpaceSafetyLabelType): s.SpaceSafetyLabelType = { - modelToThriftMap - .get(safetyLabelType).getOrElse(UnknownThriftSafetyLabelType) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/TweetDeleteReason.scala b/visibilitylib/src/main/scala/com/twitter/visibility/models/TweetDeleteReason.scala deleted file mode 100644 index 26cfbe709..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/TweetDeleteReason.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.visibility.models - -object TweetDeleteReason extends Enumeration { - type TweetDeleteReason = Value - val Deleted, BounceDeleted = Value -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/TweetModelMetadata.scala b/visibilitylib/src/main/scala/com/twitter/visibility/models/TweetModelMetadata.scala deleted file mode 100644 index e6303a03d..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/TweetModelMetadata.scala +++ /dev/null @@ -1,23 +0,0 @@ -package com.twitter.visibility.models - -import com.twitter.spam.rtf.{thriftscala => s} - -case class TweetModelMetadata( - version: Option[Int] = None, - calibratedLanguage: Option[String] = None) - -object TweetModelMetadata { - - def fromThrift(metadata: s.ModelMetadata): Option[TweetModelMetadata] = { - metadata match { - case s.ModelMetadata.ModelMetadataV1(s.ModelMetadataV1(version, calibratedLanguage)) => - Some(TweetModelMetadata(version, calibratedLanguage)) - case _ => None - } - } - - def toThrift(metadata: TweetModelMetadata): s.ModelMetadata = { - s.ModelMetadata.ModelMetadataV1( - s.ModelMetadataV1(metadata.version, metadata.calibratedLanguage)) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/TweetSafetyLabel.scala b/visibilitylib/src/main/scala/com/twitter/visibility/models/TweetSafetyLabel.scala deleted file mode 100644 index b830eb5e2..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/TweetSafetyLabel.scala +++ /dev/null @@ -1,360 +0,0 @@ -package com.twitter.visibility.models - -import com.twitter.spam.rtf.thriftscala.SafetyLabelSource -import com.twitter.spam.rtf.{thriftscala => s} -import com.twitter.util.Time -import com.twitter.visibility.util.NamingUtils - -sealed trait TweetSafetyLabelType extends SafetyLabelType with Product with Serializable { - lazy val name: String = NamingUtils.getFriendlyName(this) -} - -case class TweetSafetyLabel( - labelType: TweetSafetyLabelType, - source: Option[LabelSource] = None, - applicableUsers: Set[Long] = Set.empty, - modelMetadata: Option[TweetModelMetadata] = None, - score: Option[Double] = None, - safetyLabelSource: Option[SafetyLabelSource] = None) - -object TweetSafetyLabelType extends SafetyLabelType { - - val List: List[TweetSafetyLabelType] = s.SafetyLabelType.list.map(fromThrift) - - val ActiveLabels: List[TweetSafetyLabelType] = List.filter { labelType => - labelType != Unknown && labelType != Deprecated - } - - private lazy val nameToValueMap: Map[String, TweetSafetyLabelType] = - List.map(l => l.name.toLowerCase -> l).toMap - def fromName(name: String): Option[TweetSafetyLabelType] = nameToValueMap.get(name.toLowerCase) - - private val UnknownThriftSafetyLabelType = - s.SafetyLabelType.EnumUnknownSafetyLabelType(UnknownEnumValue) - - private lazy val thriftToModelMap: Map[s.SafetyLabelType, TweetSafetyLabelType] = Map( - s.SafetyLabelType.Abusive -> Abusive, - s.SafetyLabelType.AbusiveBehavior -> AbusiveBehavior, - s.SafetyLabelType.AbusiveBehaviorInsults -> AbusiveBehaviorInsults, - s.SafetyLabelType.AbusiveBehaviorViolentThreat -> AbusiveBehaviorViolentThreat, - s.SafetyLabelType.AbusiveBehaviorMajorAbuse -> AbusiveBehaviorMajorAbuse, - s.SafetyLabelType.AbusiveHighRecall -> AbusiveHighRecall, - s.SafetyLabelType.AdsManagerDenyList -> AdsManagerDenyList, - s.SafetyLabelType.AgathaSpam -> AgathaSpam, - s.SafetyLabelType.Automation -> Automation, - s.SafetyLabelType.AutomationHighRecall -> AutomationHighRecall, - s.SafetyLabelType.Bounce -> Bounce, - s.SafetyLabelType.BounceEdits -> BounceEdits, - s.SafetyLabelType.BrandSafetyNsfaAggregate -> BrandSafetyNsfaAggregate, - s.SafetyLabelType.BrandSafetyExperimental1 -> BrandSafetyExperimental1, - s.SafetyLabelType.BrandSafetyExperimental2 -> BrandSafetyExperimental2, - s.SafetyLabelType.BrandSafetyExperimental3 -> BrandSafetyExperimental3, - s.SafetyLabelType.BrandSafetyExperimental4 -> BrandSafetyExperimental4, - s.SafetyLabelType.BystanderAbusive -> BystanderAbusive, - s.SafetyLabelType.CopypastaSpam -> CopypastaSpam, - s.SafetyLabelType.DoNotAmplify -> DoNotAmplify, - s.SafetyLabelType.DownrankSpamReply -> DownrankSpamReply, - s.SafetyLabelType.DuplicateContent -> DuplicateContent, - s.SafetyLabelType.DuplicateMention -> DuplicateMention, - s.SafetyLabelType.DynamicProductAd -> DynamicProductAd, - s.SafetyLabelType.EdiDevelopmentOnly -> EdiDevelopmentOnly, - s.SafetyLabelType.ExperimentalNudge -> ExperimentalNudge, - s.SafetyLabelType.ExperimentalSensitiveIllegal2 -> ExperimentalSensitiveIllegal2, - s.SafetyLabelType.ForEmergencyUseOnly -> ForEmergencyUseOnly, - s.SafetyLabelType.GoreAndViolence -> GoreAndViolence, - s.SafetyLabelType.GoreAndViolenceHighPrecision -> GoreAndViolenceHighPrecision, - s.SafetyLabelType.GoreAndViolenceHighRecall -> GoreAndViolenceHighRecall, - s.SafetyLabelType.GoreAndViolenceReportedHeuristics -> GoreAndViolenceReportedHeuristics, - s.SafetyLabelType.GoreAndViolenceTopicHighRecall -> GoreAndViolenceTopicHighRecall, - s.SafetyLabelType.HatefulConduct -> HatefulConduct, - s.SafetyLabelType.HatefulConductViolentThreat -> HatefulConductViolentThreat, - s.SafetyLabelType.HighCryptospamScore -> HighCryptospamScore, - s.SafetyLabelType.HighPReportedTweetScore -> HighPReportedTweetScore, - s.SafetyLabelType.HighPSpammyTweetScore -> HighPSpammyTweetScore, - s.SafetyLabelType.HighPblockScore -> HighPblockScore, - s.SafetyLabelType.HighProactiveTosScore -> HighProactiveTosScore, - s.SafetyLabelType.HighSpammyTweetContentScore -> HighSpammyTweetContentScore, - s.SafetyLabelType.HighToxicityScore -> HighToxicityScore, - s.SafetyLabelType.HighlyReportedAndMidhighToxicityScore -> HighlyReportedAndMidhighToxicityScore, - s.SafetyLabelType.HighlyReportedTweet -> HighlyReportedTweet, - s.SafetyLabelType.InterstitialDevelopmentOnly -> InterstitialDevelopmentOnly, - s.SafetyLabelType.IpiDevelopmentOnly -> IpiDevelopmentOnly, - s.SafetyLabelType.LiveLowQuality -> LiveLowQuality, - s.SafetyLabelType.LowQuality -> LowQuality, - s.SafetyLabelType.LowQualityMention -> LowQualityMention, - s.SafetyLabelType.MisinfoCivic -> MisinfoCivic, - s.SafetyLabelType.MisinfoCrisis -> MisinfoCrisis, - s.SafetyLabelType.MisinfoGeneric -> MisinfoGeneric, - s.SafetyLabelType.MisinfoMedical -> MisinfoMedical, - s.SafetyLabelType.NsfaHighPrecision -> NsfaHighPrecision, - s.SafetyLabelType.NsfaHighRecall -> NsfaHighRecall, - s.SafetyLabelType.NsfwCardImage -> NsfwCardImage, - s.SafetyLabelType.NsfwHighPrecision -> NsfwHighPrecision, - s.SafetyLabelType.NsfwHighRecall -> NsfwHighRecall, - s.SafetyLabelType.NsfwReportedHeuristics -> NsfwReportedHeuristics, - s.SafetyLabelType.NsfwText -> NsfwText, - s.SafetyLabelType.NsfwTextHighPrecision -> NsfwTextHighPrecision, - s.SafetyLabelType.NsfwVideo -> NsfwVideo, - s.SafetyLabelType.PNegMultimodalHighPrecision -> PNegMultimodalHighPrecision, - s.SafetyLabelType.PNegMultimodalHighRecall -> PNegMultimodalHighRecall, - s.SafetyLabelType.Pdna -> Pdna, - s.SafetyLabelType.RecommendationsLowQuality -> RecommendationsLowQuality, - s.SafetyLabelType.RitoActionedTweet -> RitoActionedTweet, - s.SafetyLabelType.SafetyCrisis -> SafetyCrisis, - s.SafetyLabelType.SearchBlacklist -> SearchBlacklist, - s.SafetyLabelType.SearchBlacklistHighRecall -> SearchBlacklistHighRecall, - s.SafetyLabelType.SemanticCoreMisinformation -> SemanticCoreMisinformation, - s.SafetyLabelType.SmyteSpamTweet -> SmyteSpamTweet, - s.SafetyLabelType.Spam -> Spam, - s.SafetyLabelType.SpamHighRecall -> SpamHighRecall, - s.SafetyLabelType.TombstoneDevelopmentOnly -> TombstoneDevelopmentOnly, - s.SafetyLabelType.TweetContainsHatefulConductSlurHighSeverity -> TweetContainsHatefulConductSlurHighSeverity, - s.SafetyLabelType.TweetContainsHatefulConductSlurMediumSeverity -> TweetContainsHatefulConductSlurMediumSeverity, - s.SafetyLabelType.TweetContainsHatefulConductSlurLowSeverity -> TweetContainsHatefulConductSlurLowSeverity, - s.SafetyLabelType.UnsafeUrl -> UnsafeUrl, - s.SafetyLabelType.UntrustedUrl -> UntrustedUrl, - s.SafetyLabelType.FosnrHatefulConduct -> FosnrHatefulConduct, - s.SafetyLabelType.FosnrHatefulConductLowSeveritySlur -> FosnrHatefulConductLowSeveritySlur, - s.SafetyLabelType.AbusiveHighRecall2 -> Deprecated, - s.SafetyLabelType.AbusiveHighRecall3 -> Deprecated, - s.SafetyLabelType.BrazilianPoliticalTweet -> Deprecated, - s.SafetyLabelType.BystanderAbusive2 -> Deprecated, - s.SafetyLabelType.BystanderAbusive3 -> Deprecated, - s.SafetyLabelType.DeprecatedLabel144 -> Deprecated, - s.SafetyLabelType.Experimental10Seh -> Deprecated, - s.SafetyLabelType.Experimental11Seh -> Deprecated, - s.SafetyLabelType.Experimental12Seh -> Deprecated, - s.SafetyLabelType.Experimental13Seh -> Deprecated, - s.SafetyLabelType.Experimental14Seh -> Deprecated, - s.SafetyLabelType.Experimental15Seh -> Deprecated, - s.SafetyLabelType.Experimental16Seh -> Deprecated, - s.SafetyLabelType.Experimental17Seh -> Deprecated, - s.SafetyLabelType.Experimental18Seh -> Deprecated, - s.SafetyLabelType.Experimental19Seh -> Deprecated, - s.SafetyLabelType.Experimental1Seh -> Deprecated, - s.SafetyLabelType.Experimental20Seh -> Deprecated, - s.SafetyLabelType.Experimental21Seh -> Deprecated, - s.SafetyLabelType.Experimental22Seh -> Deprecated, - s.SafetyLabelType.Experimental23Seh -> Deprecated, - s.SafetyLabelType.Experimental24Seh -> Deprecated, - s.SafetyLabelType.Experimental25Seh -> Deprecated, - s.SafetyLabelType.Experimental2Seh -> Deprecated, - s.SafetyLabelType.Experimental3Seh -> Deprecated, - s.SafetyLabelType.Experimental4Seh -> Deprecated, - s.SafetyLabelType.Experimental5Seh -> Deprecated, - s.SafetyLabelType.Experimental6Seh -> Deprecated, - s.SafetyLabelType.Experimental7Seh -> Deprecated, - s.SafetyLabelType.Experimental8Seh -> Deprecated, - s.SafetyLabelType.Experimental9Seh -> Deprecated, - s.SafetyLabelType.ExperimentalHighHealthModelScore1 -> Deprecated, - s.SafetyLabelType.ExperimentalHighHealthModelScore10 -> Deprecated, - s.SafetyLabelType.ExperimentalHighHealthModelScore2 -> Deprecated, - s.SafetyLabelType.ExperimentalHighHealthModelScore3 -> Deprecated, - s.SafetyLabelType.ExperimentalHighHealthModelScore4 -> Deprecated, - s.SafetyLabelType.ExperimentalHighHealthModelScore5 -> Deprecated, - s.SafetyLabelType.ExperimentalHighHealthModelScore6 -> Deprecated, - s.SafetyLabelType.ExperimentalHighHealthModelScore7 -> Deprecated, - s.SafetyLabelType.ExperimentalHighHealthModelScore8 -> Deprecated, - s.SafetyLabelType.ExperimentalHighHealthModelScore9 -> Deprecated, - s.SafetyLabelType.ExperimentalSensitiveIllegal1 -> Deprecated, - s.SafetyLabelType.ExperimentalSensitiveIllegal3 -> Deprecated, - s.SafetyLabelType.ExperimentalSensitiveIllegal4 -> Deprecated, - s.SafetyLabelType.ExperimentalSensitiveIllegal5 -> Deprecated, - s.SafetyLabelType.ExperimentalSensitiveIllegal6 -> Deprecated, - s.SafetyLabelType.ExperimentalSpam1 -> Deprecated, - s.SafetyLabelType.ExperimentalSpam2 -> Deprecated, - s.SafetyLabelType.ExperimentalSpam3 -> Deprecated, - s.SafetyLabelType.Experimentation -> Deprecated, - s.SafetyLabelType.Experimentation2 -> Deprecated, - s.SafetyLabelType.Experimentation3 -> Deprecated, - s.SafetyLabelType.HighlyReportedImage -> Deprecated, - s.SafetyLabelType.HighToxicityHoldbackModelScore -> Deprecated, - s.SafetyLabelType.LowQualityHighRecall -> Deprecated, - s.SafetyLabelType.MagicRecsDenylist -> Deprecated, - s.SafetyLabelType.MisinfoCovid19 -> Deprecated, - s.SafetyLabelType.MsnfoBrazilianElection -> Deprecated, - s.SafetyLabelType.MsnfoCovid19Vaccine -> Deprecated, - s.SafetyLabelType.MsnfoFrenchElection -> Deprecated, - s.SafetyLabelType.MsnfoPhilippineElection -> Deprecated, - s.SafetyLabelType.MsnfoUsElection -> Deprecated, - s.SafetyLabelType.NsfwNearPerfect -> Deprecated, - s.SafetyLabelType.PersonaNonGrata -> Deprecated, - s.SafetyLabelType.PMisinfoCombined15 -> Deprecated, - s.SafetyLabelType.PMisinfoCombined30 -> Deprecated, - s.SafetyLabelType.PMisinfoCombined50 -> Deprecated, - s.SafetyLabelType.PMisinfoDenylist -> Deprecated, - s.SafetyLabelType.PMisinfoPVeracityNudge -> Deprecated, - s.SafetyLabelType.PoliticalTweetExperimental1 -> Deprecated, - s.SafetyLabelType.ProactiveTosHighRecall -> Deprecated, - s.SafetyLabelType.ProactiveTosHighRecallContainsSelfHarm -> Deprecated, - s.SafetyLabelType.ProactiveTosHighRecallEncourageSelfHarm -> Deprecated, - s.SafetyLabelType.ProactiveTosHighRecallEpisodic -> Deprecated, - s.SafetyLabelType.ProactiveTosHighRecallEpisodicHatefulConduct -> Deprecated, - s.SafetyLabelType.ProactiveTosHighRecallOtherAbusePolicy -> Deprecated, - s.SafetyLabelType.ProjectLibra -> Deprecated, - s.SafetyLabelType.SearchHighVisibilityDenylist -> Deprecated, - s.SafetyLabelType.SearchHighVisibilityHighRecallDenylist -> Deprecated, - s.SafetyLabelType.Reserved162 -> Deprecated, - s.SafetyLabelType.Reserved163 -> Deprecated, - s.SafetyLabelType.Reserved164 -> Deprecated, - s.SafetyLabelType.Reserved165 -> Deprecated, - s.SafetyLabelType.Reserved166 -> Deprecated, - s.SafetyLabelType.Reserved167 -> Deprecated, - s.SafetyLabelType.Reserved168 -> Deprecated, - s.SafetyLabelType.Reserved169 -> Deprecated, - s.SafetyLabelType.Reserved170 -> Deprecated, - ) - - private lazy val modelToThriftMap: Map[TweetSafetyLabelType, s.SafetyLabelType] = - (for ((k, v) <- thriftToModelMap) yield (v, k)) ++ Map( - Deprecated -> s.SafetyLabelType.EnumUnknownSafetyLabelType(DeprecatedEnumValue), - ) - - case object Abusive extends TweetSafetyLabelType - case object AbusiveBehavior extends TweetSafetyLabelType - case object AbusiveBehaviorInsults extends TweetSafetyLabelType - case object AbusiveBehaviorViolentThreat extends TweetSafetyLabelType - case object AbusiveBehaviorMajorAbuse extends TweetSafetyLabelType - case object AbusiveHighRecall extends TweetSafetyLabelType - case object Automation extends TweetSafetyLabelType - case object AutomationHighRecall extends TweetSafetyLabelType - case object Bounce extends TweetSafetyLabelType - case object BystanderAbusive extends TweetSafetyLabelType - case object NsfaHighRecall extends TweetSafetyLabelType - case object DuplicateContent extends TweetSafetyLabelType - case object DuplicateMention extends TweetSafetyLabelType - case object GoreAndViolence extends TweetSafetyLabelType { - - val DeprecatedAt: Time = Time.at("2019-09-12 00:00:00 UTC") - } - case object GoreAndViolenceHighRecall extends TweetSafetyLabelType - case object LiveLowQuality extends TweetSafetyLabelType - case object LowQuality extends TweetSafetyLabelType - case object LowQualityMention extends TweetSafetyLabelType - case object NsfwCardImage extends TweetSafetyLabelType - case object NsfwHighRecall extends TweetSafetyLabelType - case object NsfwHighPrecision extends TweetSafetyLabelType - case object NsfwVideo extends TweetSafetyLabelType - case object Pdna extends TweetSafetyLabelType - - case object RecommendationsLowQuality extends TweetSafetyLabelType - case object SearchBlacklist extends TweetSafetyLabelType - case object Spam extends TweetSafetyLabelType - case object SpamHighRecall extends TweetSafetyLabelType - case object UntrustedUrl extends TweetSafetyLabelType - case object HighToxicityScore extends TweetSafetyLabelType - case object HighPblockScore extends TweetSafetyLabelType - case object SearchBlacklistHighRecall extends TweetSafetyLabelType - case object ForEmergencyUseOnly extends TweetSafetyLabelType - case object HighProactiveTosScore extends TweetSafetyLabelType - case object SafetyCrisis extends TweetSafetyLabelType - case object MisinfoCivic extends TweetSafetyLabelType - case object MisinfoCrisis extends TweetSafetyLabelType - case object MisinfoGeneric extends TweetSafetyLabelType - case object MisinfoMedical extends TweetSafetyLabelType - case object AdsManagerDenyList extends TweetSafetyLabelType - case object GoreAndViolenceHighPrecision extends TweetSafetyLabelType - case object NsfwReportedHeuristics extends TweetSafetyLabelType - case object GoreAndViolenceReportedHeuristics extends TweetSafetyLabelType - case object HighPSpammyTweetScore extends TweetSafetyLabelType - case object DoNotAmplify extends TweetSafetyLabelType - case object HighlyReportedTweet extends TweetSafetyLabelType - case object AgathaSpam extends TweetSafetyLabelType - case object SmyteSpamTweet extends TweetSafetyLabelType - case object SemanticCoreMisinformation extends TweetSafetyLabelType - case object HighPReportedTweetScore extends TweetSafetyLabelType - case object HighSpammyTweetContentScore extends TweetSafetyLabelType - case object GoreAndViolenceTopicHighRecall extends TweetSafetyLabelType - case object CopypastaSpam extends TweetSafetyLabelType - case object ExperimentalSensitiveIllegal2 extends TweetSafetyLabelType - case object DownrankSpamReply extends TweetSafetyLabelType - case object NsfwText extends TweetSafetyLabelType - case object HighlyReportedAndMidhighToxicityScore extends TweetSafetyLabelType - case object DynamicProductAd extends TweetSafetyLabelType - case object TombstoneDevelopmentOnly extends TweetSafetyLabelType - case object TweetContainsHatefulConductSlurHighSeverity extends TweetSafetyLabelType - case object TweetContainsHatefulConductSlurMediumSeverity extends TweetSafetyLabelType - case object TweetContainsHatefulConductSlurLowSeverity extends TweetSafetyLabelType - case object RitoActionedTweet extends TweetSafetyLabelType - case object ExperimentalNudge extends TweetSafetyLabelType - case object PNegMultimodalHighPrecision extends TweetSafetyLabelType - case object PNegMultimodalHighRecall extends TweetSafetyLabelType - case object BrandSafetyNsfaAggregate extends TweetSafetyLabelType - case object HighCryptospamScore extends TweetSafetyLabelType - case object IpiDevelopmentOnly extends TweetSafetyLabelType - case object BounceEdits extends TweetSafetyLabelType - case object UnsafeUrl extends TweetSafetyLabelType - case object InterstitialDevelopmentOnly extends TweetSafetyLabelType - case object EdiDevelopmentOnly extends TweetSafetyLabelType - case object NsfwTextHighPrecision extends TweetSafetyLabelType - case object HatefulConduct extends TweetSafetyLabelType - case object HatefulConductViolentThreat extends TweetSafetyLabelType - case object NsfaHighPrecision extends TweetSafetyLabelType - case object BrandSafetyExperimental1 extends TweetSafetyLabelType - case object BrandSafetyExperimental2 extends TweetSafetyLabelType - case object BrandSafetyExperimental3 extends TweetSafetyLabelType - case object BrandSafetyExperimental4 extends TweetSafetyLabelType - - case object FosnrHatefulConduct extends TweetSafetyLabelType - case object FosnrHatefulConductLowSeveritySlur extends TweetSafetyLabelType - - case object Deprecated extends TweetSafetyLabelType - case object Unknown extends TweetSafetyLabelType - - def fromThrift(safetyLabelType: s.SafetyLabelType): TweetSafetyLabelType = - thriftToModelMap.get(safetyLabelType) match { - case Some(tweetSafetyLabelType) => tweetSafetyLabelType - case _ => - safetyLabelType match { - case s.SafetyLabelType.EnumUnknownSafetyLabelType(DeprecatedEnumValue) => Deprecated - case _ => - Unknown - } - } - - def toThrift(safetyLabelType: TweetSafetyLabelType): s.SafetyLabelType = { - modelToThriftMap.getOrElse(safetyLabelType, UnknownThriftSafetyLabelType) - } -} - -object TweetSafetyLabel { - def fromThrift(safetyLabelValue: s.SafetyLabelValue): TweetSafetyLabel = - fromTuple(safetyLabelValue.labelType, safetyLabelValue.label) - - def fromTuple( - safetyLabelType: s.SafetyLabelType, - safetyLabel: s.SafetyLabel - ): TweetSafetyLabel = { - TweetSafetyLabel( - labelType = TweetSafetyLabelType.fromThrift(safetyLabelType), - source = safetyLabel.source.flatMap(LabelSource.fromString), - safetyLabelSource = safetyLabel.safetyLabelSource, - applicableUsers = safetyLabel.applicableUsers - .map { perspectivalUsers => - (perspectivalUsers map { - _.userId - }).toSet - }.getOrElse(Set.empty), - score = safetyLabel.score, - modelMetadata = safetyLabel.modelMetadata.flatMap(TweetModelMetadata.fromThrift) - ) - } - - def toThrift(tweetSafetyLabel: TweetSafetyLabel): s.SafetyLabelValue = { - s.SafetyLabelValue( - labelType = TweetSafetyLabelType.toThrift(tweetSafetyLabel.labelType), - label = s.SafetyLabel( - applicableUsers = if (tweetSafetyLabel.applicableUsers.nonEmpty) { - Some(tweetSafetyLabel.applicableUsers.toSeq.map { - s.PerspectivalUser(_) - }) - } else { - None - }, - source = tweetSafetyLabel.source.map(_.name), - score = tweetSafetyLabel.score, - modelMetadata = tweetSafetyLabel.modelMetadata.map(TweetModelMetadata.toThrift) - ) - ) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/UnitOfDiversion.scala b/visibilitylib/src/main/scala/com/twitter/visibility/models/UnitOfDiversion.scala deleted file mode 100644 index 5d7f1caba..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/UnitOfDiversion.scala +++ /dev/null @@ -1,16 +0,0 @@ -package com.twitter.visibility.models - -trait UnitOfDiversion { - - def apply: (String, Any) -} - -object UnitOfDiversion { - case class ConversationId(conversationId: Long) extends UnitOfDiversion { - override def apply: (String, Any) = ("conversation_id", conversationId) - } - - case class TweetId(tweetId: Long) extends UnitOfDiversion { - override def apply: (String, Any) = ("tweet_id", tweetId) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/UserAge.scala b/visibilitylib/src/main/scala/com/twitter/visibility/models/UserAge.scala deleted file mode 100644 index b2cdbb785..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/UserAge.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.visibility.models - -case class UserAge(ageInYears: Option[Int]) { - def hasAge: Boolean = ageInYears.isDefined - - def isGte(ageToCompare: Int): Boolean = - ageInYears - .collectFirst { - case age if age > ageToCompare => true - }.getOrElse(false) - - def unapply(userAge: UserAge): Option[Int] = { - ageInYears - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/UserLabel.scala b/visibilitylib/src/main/scala/com/twitter/visibility/models/UserLabel.scala deleted file mode 100644 index 738f73e9e..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/UserLabel.scala +++ /dev/null @@ -1,244 +0,0 @@ -package com.twitter.visibility.models - -import com.twitter.gizmoduck.{thriftscala => t} -import com.twitter.util.Time -import com.twitter.visibility.util.NamingUtils - -sealed trait UserLabelValue extends SafetyLabelType { - lazy val name: String = NamingUtils.getFriendlyName(this) -} - -case class UserLabel( - id: Long, - createdAt: Time, - createdBy: String, - labelValue: UserLabelValue, - source: Option[LabelSource] = None) - -object UserLabelValue extends SafetyLabelType { - - private lazy val nameToValueMap: Map[String, UserLabelValue] = - List.map(l => l.name.toLowerCase -> l).toMap - def fromName(name: String): Option[UserLabelValue] = nameToValueMap.get(name.toLowerCase) - - private val UnknownThriftUserLabelValue = - t.LabelValue.EnumUnknownLabelValue(UnknownEnumValue) - - private lazy val thriftToModelMap: Map[t.LabelValue, UserLabelValue] = Map( - t.LabelValue.Abusive -> Abusive, - t.LabelValue.AbusiveHighRecall -> AbusiveHighRecall, - t.LabelValue.AgathaSpamTopUser -> AgathaSpamTopUser, - t.LabelValue.BirdwatchDisabled -> BirdwatchDisabled, - t.LabelValue.BlinkBad -> BlinkBad, - t.LabelValue.BlinkQuestionable -> BlinkQuestionable, - t.LabelValue.BlinkWorst -> BlinkWorst, - t.LabelValue.Compromised -> Compromised, - t.LabelValue.DelayedRemediation -> DelayedRemediation, - t.LabelValue.DoNotCharge -> DoNotCharge, - t.LabelValue.DoNotAmplify -> DoNotAmplify, - t.LabelValue.DownrankSpamReply -> DownrankSpamReply, - t.LabelValue.DuplicateContent -> DuplicateContent, - t.LabelValue.EngagementSpammer -> EngagementSpammer, - t.LabelValue.EngagementSpammerHighRecall -> EngagementSpammerHighRecall, - t.LabelValue.ExperimentalPfmUser1 -> ExperimentalPfmUser1, - t.LabelValue.ExperimentalPfmUser2 -> ExperimentalPfmUser2, - t.LabelValue.ExperimentalPfmUser3 -> ExperimentalPfmUser3, - t.LabelValue.ExperimentalPfmUser4 -> ExperimentalPfmUser4, - t.LabelValue.ExperimentalSeh1 -> ExperimentalSeh1, - t.LabelValue.ExperimentalSeh2 -> ExperimentalSeh2, - t.LabelValue.ExperimentalSeh3 -> ExperimentalSeh3, - t.LabelValue.ExperimentalSehUser4 -> ExperimentalSehUser4, - t.LabelValue.ExperimentalSehUser5 -> ExperimentalSehUser5, - t.LabelValue.ExperimentalSensitiveIllegal1 -> ExperimentalSensitiveIllegal1, - t.LabelValue.ExperimentalSensitiveIllegal2 -> ExperimentalSensitiveIllegal2, - t.LabelValue.FakeSignupDeferredRemediation -> FakeSignupDeferredRemediation, - t.LabelValue.FakeSignupHoldback -> FakeSignupHoldback, - t.LabelValue.GoreAndViolenceHighPrecision -> GoreAndViolenceHighPrecision, - t.LabelValue.GoreAndViolenceReportedHeuristics -> GoreAndViolenceReportedHeuristics, - t.LabelValue.HealthExperimentation1 -> HealthExperimentation1, - t.LabelValue.HealthExperimentation2 -> HealthExperimentation2, - t.LabelValue.HighRiskVerification -> HighRiskVerification, - t.LabelValue.LikelyIvs -> LikelyIvs, - t.LabelValue.LiveLowQuality -> LiveLowQuality, - t.LabelValue.LowQuality -> LowQuality, - t.LabelValue.LowQualityHighRecall -> LowQualityHighRecall, - t.LabelValue.NotGraduated -> NotGraduated, - t.LabelValue.NotificationSpamHeuristics -> NotificationSpamHeuristics, - t.LabelValue.NsfwAvatarImage -> NsfwAvatarImage, - t.LabelValue.NsfwBannerImage -> NsfwBannerImage, - t.LabelValue.NsfwHighPrecision -> NsfwHighPrecision, - t.LabelValue.NsfwHighRecall -> NsfwHighRecall, - t.LabelValue.NsfwNearPerfect -> NsfwNearPerfect, - t.LabelValue.NsfwReportedHeuristics -> NsfwReportedHeuristics, - t.LabelValue.NsfwSensitive -> NsfwSensitive, - t.LabelValue.NsfwText -> NsfwText, - t.LabelValue.ReadOnly -> ReadOnly, - t.LabelValue.RecentAbuseStrike -> RecentAbuseStrike, - t.LabelValue.RecentMisinfoStrike -> RecentMisinfoStrike, - t.LabelValue.RecentProfileModification -> RecentProfileModification, - t.LabelValue.RecentSuspension -> RecentSuspension, - t.LabelValue.RecommendationsBlacklist -> RecommendationsBlacklist, - t.LabelValue.SearchBlacklist -> SearchBlacklist, - t.LabelValue.SoftReadOnly -> SoftReadOnly, - t.LabelValue.SpamHighRecall -> SpamHighRecall, - t.LabelValue.SpammyUserModelHighPrecision -> SpammyUserModelHighPrecision, - t.LabelValue.StateMediaAccount -> StateMediaAccount, - t.LabelValue.TsViolation -> TsViolation, - t.LabelValue.UnconfirmedEmailSignup -> UnconfirmedEmailSignup, - t.LabelValue.LegalOpsCase -> LegalOpsCase, - t.LabelValue.AutomationHighRecall -> Deprecated, - t.LabelValue.AutomationHighRecallHoldback -> Deprecated, - t.LabelValue.BouncerUserFiltered -> Deprecated, - t.LabelValue.DeprecatedListBannerPdna -> Deprecated, - t.LabelValue.DeprecatedMigration50 -> Deprecated, - t.LabelValue.DmSpammer -> Deprecated, - t.LabelValue.DuplicateContentHoldback -> Deprecated, - t.LabelValue.FakeAccountExperiment -> Deprecated, - t.LabelValue.FakeAccountReadonly -> Deprecated, - t.LabelValue.FakeAccountRecaptcha -> Deprecated, - t.LabelValue.FakeAccountSspc -> Deprecated, - t.LabelValue.FakeAccountVoiceReadonly -> Deprecated, - t.LabelValue.FakeEngagement -> Deprecated, - t.LabelValue.HasBeenSuspended -> Deprecated, - t.LabelValue.HighProfile -> Deprecated, - t.LabelValue.NotificationsSpike -> Deprecated, - t.LabelValue.NsfaProfileHighRecall -> Deprecated, - t.LabelValue.NsfwUserName -> Deprecated, - t.LabelValue.PotentiallyCompromised -> Deprecated, - t.LabelValue.ProfileAdsBlacklist -> Deprecated, - t.LabelValue.RatelimitDms -> Deprecated, - t.LabelValue.RatelimitFavorites -> Deprecated, - t.LabelValue.RatelimitFollows -> Deprecated, - t.LabelValue.RatelimitRetweets -> Deprecated, - t.LabelValue.RatelimitTweets -> Deprecated, - t.LabelValue.RecentCompromised -> Deprecated, - t.LabelValue.RevenueOnlyHsSignal -> Deprecated, - t.LabelValue.SearchBlacklistHoldback -> Deprecated, - t.LabelValue.SpamHighRecallHoldback -> Deprecated, - t.LabelValue.SpamRepeatOffender -> Deprecated, - t.LabelValue.SpammerExperiment -> Deprecated, - t.LabelValue.TrendBlacklist -> Deprecated, - t.LabelValue.VerifiedDeceptiveIdentity -> Deprecated, - t.LabelValue.BrandSafetyNsfaAggregate -> Deprecated, - t.LabelValue.Pcf -> Deprecated, - t.LabelValue.Reserved97 -> Deprecated, - t.LabelValue.Reserved98 -> Deprecated, - t.LabelValue.Reserved99 -> Deprecated, - t.LabelValue.Reserved100 -> Deprecated, - t.LabelValue.Reserved101 -> Deprecated, - t.LabelValue.Reserved102 -> Deprecated, - t.LabelValue.Reserved103 -> Deprecated, - t.LabelValue.Reserved104 -> Deprecated, - t.LabelValue.Reserved105 -> Deprecated, - t.LabelValue.Reserved106 -> Deprecated - ) - - private lazy val modelToThriftMap: Map[UserLabelValue, t.LabelValue] = - (for ((k, v) <- thriftToModelMap) yield (v, k)) ++ Map( - Deprecated -> t.LabelValue.EnumUnknownLabelValue(DeprecatedEnumValue), - ) - - case object Abusive extends UserLabelValue - case object AbusiveHighRecall extends UserLabelValue - case object AgathaSpamTopUser extends UserLabelValue - case object BirdwatchDisabled extends UserLabelValue - case object BlinkBad extends UserLabelValue - case object BlinkQuestionable extends UserLabelValue - case object BlinkWorst extends UserLabelValue - case object Compromised extends UserLabelValue - case object DelayedRemediation extends UserLabelValue - case object DoNotAmplify extends UserLabelValue - case object DoNotCharge extends UserLabelValue - case object DownrankSpamReply extends UserLabelValue - case object DuplicateContent extends UserLabelValue - case object EngagementSpammer extends UserLabelValue - case object EngagementSpammerHighRecall extends UserLabelValue - case object ExperimentalPfmUser1 extends UserLabelValue - case object ExperimentalPfmUser2 extends UserLabelValue - case object ExperimentalPfmUser3 extends UserLabelValue - case object ExperimentalPfmUser4 extends UserLabelValue - case object ExperimentalSeh1 extends UserLabelValue - case object ExperimentalSeh2 extends UserLabelValue - case object ExperimentalSeh3 extends UserLabelValue - case object ExperimentalSehUser4 extends UserLabelValue - case object ExperimentalSehUser5 extends UserLabelValue - case object ExperimentalSensitiveIllegal1 extends UserLabelValue - case object ExperimentalSensitiveIllegal2 extends UserLabelValue - case object FakeSignupDeferredRemediation extends UserLabelValue - case object FakeSignupHoldback extends UserLabelValue - case object GoreAndViolenceHighPrecision extends UserLabelValue - case object GoreAndViolenceReportedHeuristics extends UserLabelValue - case object HealthExperimentation1 extends UserLabelValue - case object HealthExperimentation2 extends UserLabelValue - case object HighRiskVerification extends UserLabelValue - case object LegalOpsCase extends UserLabelValue - case object LikelyIvs extends UserLabelValue - case object LiveLowQuality extends UserLabelValue - case object LowQuality extends UserLabelValue - case object LowQualityHighRecall extends UserLabelValue - case object NotificationSpamHeuristics extends UserLabelValue - case object NotGraduated extends UserLabelValue - case object NsfwAvatarImage extends UserLabelValue - case object NsfwBannerImage extends UserLabelValue - case object NsfwHighPrecision extends UserLabelValue - case object NsfwHighRecall extends UserLabelValue - case object NsfwNearPerfect extends UserLabelValue - case object NsfwReportedHeuristics extends UserLabelValue - case object NsfwSensitive extends UserLabelValue - case object NsfwText extends UserLabelValue - case object ReadOnly extends UserLabelValue - case object RecentAbuseStrike extends UserLabelValue - case object RecentProfileModification extends UserLabelValue - case object RecentMisinfoStrike extends UserLabelValue - case object RecentSuspension extends UserLabelValue - case object RecommendationsBlacklist extends UserLabelValue - case object SearchBlacklist extends UserLabelValue - case object SoftReadOnly extends UserLabelValue - case object SpamHighRecall extends UserLabelValue - case object SpammyUserModelHighPrecision extends UserLabelValue - case object StateMediaAccount extends UserLabelValue - case object TsViolation extends UserLabelValue - case object UnconfirmedEmailSignup extends UserLabelValue - - case object Deprecated extends UserLabelValue - case object Unknown extends UserLabelValue - - def fromThrift(userLabelValue: t.LabelValue): UserLabelValue = { - thriftToModelMap.get(userLabelValue) match { - case Some(safetyLabelType) => safetyLabelType - case _ => - userLabelValue match { - case t.LabelValue.EnumUnknownLabelValue(DeprecatedEnumValue) => Deprecated - case _ => - Unknown - } - } - } - - def toThrift(userLabelValue: UserLabelValue): t.LabelValue = - modelToThriftMap.get((userLabelValue)).getOrElse(UnknownThriftUserLabelValue) - - val List: List[UserLabelValue] = t.LabelValue.list.map(fromThrift) -} - -object UserLabel { - def fromThrift(userLabel: t.Label): UserLabel = { - UserLabel( - userLabel.id, - Time.fromMilliseconds(userLabel.createdAtMsec), - userLabel.byUser, - UserLabelValue.fromThrift(userLabel.labelValue), - userLabel.source.flatMap(LabelSource.fromString) - ) - } - - def toThrift(userLabel: UserLabel): t.Label = { - t.Label( - userLabel.id, - UserLabelValue.toThrift(userLabel.labelValue), - userLabel.createdAt.inMillis, - byUser = userLabel.createdBy, - source = userLabel.source.map(_.name) - ) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/UserSensitiveMediaSettings.scala b/visibilitylib/src/main/scala/com/twitter/visibility/models/UserSensitiveMediaSettings.scala deleted file mode 100644 index 85981a007..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/UserSensitiveMediaSettings.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.visibility.models - -import com.twitter.contenthealth.sensitivemediasettings.thriftscala.SensitiveMediaSettings - - -case class UserSensitiveMediaSettings(sensitiveMediaSettings: Option[SensitiveMediaSettings]) { - - def unapply( - userSensitiveMediaSettings: UserSensitiveMediaSettings - ): Option[SensitiveMediaSettings] = { - sensitiveMediaSettings - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/UserUnavailableStateEnum.scala b/visibilitylib/src/main/scala/com/twitter/visibility/models/UserUnavailableStateEnum.scala deleted file mode 100644 index 492ffac32..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/UserUnavailableStateEnum.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.visibility.models - -import com.twitter.visibility.thriftscala.UserVisibilityResult -import com.twitter.visibility.util.NamingUtils - -sealed trait UserUnavailableStateEnum { - lazy val name: String = NamingUtils.getFriendlyName(this) -} -object UserUnavailableStateEnum { - case object Deleted extends UserUnavailableStateEnum - case object BounceDeleted extends UserUnavailableStateEnum - case object Deactivated extends UserUnavailableStateEnum - case object Offboarded extends UserUnavailableStateEnum - case object Erased extends UserUnavailableStateEnum - case object Suspended extends UserUnavailableStateEnum - case object Protected extends UserUnavailableStateEnum - case object AuthorBlocksViewer extends UserUnavailableStateEnum - case object ViewerBlocksAuthor extends UserUnavailableStateEnum - case object ViewerMutesAuthor extends UserUnavailableStateEnum - case class Filtered(result: UserVisibilityResult) extends UserUnavailableStateEnum - case object Unavailable extends UserUnavailableStateEnum -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/ViewerContext.scala b/visibilitylib/src/main/scala/com/twitter/visibility/models/ViewerContext.scala deleted file mode 100644 index 4da5210c9..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/ViewerContext.scala +++ /dev/null @@ -1,53 +0,0 @@ -package com.twitter.visibility.models - -import com.twitter.context.TwitterContext -import com.twitter.context.thriftscala.Viewer -import com.twitter.featureswitches.{UserAgent => FSUserAgent} -import com.twitter.finatra.request.util.AddressUtils - -case class ViewerContext( - userId: Option[Long] = None, - guestId: Option[Long] = None, - userAgentStr: Option[String] = None, - clientApplicationId: Option[Long] = None, - auditIp: String = "0.0.0.0", - requestCountryCode: Option[String] = None, - requestLanguageCode: Option[String] = None, - deviceId: Option[String] = None, - ipTags: Set[String] = Set.empty, - isVerifiedCrawler: Boolean = false, - userRoles: Option[Set[String]] = None) { - val fsUserAgent: Option[FSUserAgent] = userAgentStr.flatMap(ua => FSUserAgent(userAgent = ua)) - - val isTwOffice: Boolean = ipTags.contains(AddressUtils.TwofficeIpTag) -} - -object ViewerContext { - def fromContext: ViewerContext = viewerContext.getOrElse(ViewerContext()) - - def fromContextWithViewerIdFallback(viewerId: Option[Long]): ViewerContext = - viewerContext - .map { viewer => - if (viewer.userId.isEmpty) { - viewer.copy(userId = viewerId) - } else { - viewer - } - }.getOrElse(ViewerContext(viewerId)) - - private def viewerContext: Option[ViewerContext] = - TwitterContext(TwitterContextPermit)().map(apply) - - def apply(viewer: Viewer): ViewerContext = new ViewerContext( - userId = viewer.userId, - guestId = viewer.guestId, - userAgentStr = viewer.userAgent, - clientApplicationId = viewer.clientApplicationId, - auditIp = viewer.auditIp.getOrElse("0.0.0.0"), - requestCountryCode = viewer.requestCountryCode collect { case value => value.toLowerCase }, - requestLanguageCode = viewer.requestLanguageCode collect { case value => value.toLowerCase }, - deviceId = viewer.deviceId, - ipTags = viewer.ipTags.toSet, - isVerifiedCrawler = viewer.isVerifiedCrawler.getOrElse(false) - ) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/ViolationLevel.scala b/visibilitylib/src/main/scala/com/twitter/visibility/models/ViolationLevel.scala deleted file mode 100644 index f42faf6c7..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/ViolationLevel.scala +++ /dev/null @@ -1,51 +0,0 @@ -package com.twitter.visibility.models - -sealed trait ViolationLevel extends Product with Serializable { - val level: Int -} - -object ViolationLevel { - - case object DefaultLevel extends ViolationLevel { - override val level: Int = 0 - } - - case object Level1 extends ViolationLevel { - override val level: Int = 1 - } - - case object Level2 extends ViolationLevel { - override val level: Int = 2 - } - - case object Level3 extends ViolationLevel { - override val level: Int = 3 - } - - case object Level4 extends ViolationLevel { - override val level: Int = 4 - } - - private val safetyLabelToViolationLevel: Map[TweetSafetyLabelType, ViolationLevel] = Map( - TweetSafetyLabelType.FosnrHatefulConduct -> Level3, - TweetSafetyLabelType.FosnrHatefulConductLowSeveritySlur -> Level1, - ) - - val violationLevelToSafetyLabels: Map[ViolationLevel, Set[TweetSafetyLabelType]] = - safetyLabelToViolationLevel.groupBy { case (_, violationLevel) => violationLevel }.map { - case (violationLevel, collection) => (violationLevel, collection.keySet) - } - - def fromTweetSafetyLabel( - tweetSafetyLabel: TweetSafetyLabel - ): ViolationLevel = { - safetyLabelToViolationLevel.getOrElse(tweetSafetyLabel.labelType, DefaultLevel) - } - - def fromTweetSafetyLabelOpt( - tweetSafetyLabel: TweetSafetyLabel - ): Option[ViolationLevel] = { - safetyLabelToViolationLevel.get(tweetSafetyLabel.labelType) - } - -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/package.scala b/visibilitylib/src/main/scala/com/twitter/visibility/models/package.scala deleted file mode 100644 index 8eb72126d..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/models/package.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.visibility - -package object models { - type CommunityId = Long -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/Action.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/Action.scala deleted file mode 100644 index 47446832a..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/Action.scala +++ /dev/null @@ -1,916 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.datatools.entityservice.entities.thriftscala.FleetInterstitial -import com.twitter.scrooge.ThriftStruct -import com.twitter.visibility.common.actions.LocalizedMessage -import com.twitter.visibility.common.actions._ -import com.twitter.visibility.common.actions.converter.scala.AppealableReasonConverter -import com.twitter.visibility.common.actions.converter.scala.AvoidReasonConverter -import com.twitter.visibility.common.actions.converter.scala.ComplianceTweetNoticeEventTypeConverter -import com.twitter.visibility.common.actions.converter.scala.DownrankHomeTimelineReasonConverter -import com.twitter.visibility.common.actions.converter.scala.DropReasonConverter -import com.twitter.visibility.common.actions.converter.scala.InterstitialReasonConverter -import com.twitter.visibility.common.actions.converter.scala.LimitedActionsPolicyConverter -import com.twitter.visibility.common.actions.converter.scala.LimitedEngagementReasonConverter -import com.twitter.visibility.common.actions.converter.scala.LocalizedMessageConverter -import com.twitter.visibility.common.actions.converter.scala.SoftInterventionDisplayTypeConverter -import com.twitter.visibility.common.actions.converter.scala.SoftInterventionReasonConverter -import com.twitter.visibility.common.actions.converter.scala.TombstoneReasonConverter -import com.twitter.visibility.features.Feature -import com.twitter.visibility.logging.thriftscala.HealthActionType -import com.twitter.visibility.models.ViolationLevel -import com.twitter.visibility.strato.thriftscala.NudgeActionType.EnumUnknownNudgeActionType -import com.twitter.visibility.strato.thriftscala.{Nudge => StratoNudge} -import com.twitter.visibility.strato.thriftscala.{NudgeAction => StratoNudgeAction} -import com.twitter.visibility.strato.thriftscala.{NudgeActionType => StratoNudgeActionType} -import com.twitter.visibility.strato.thriftscala.{NudgeActionPayload => StratoNudgeActionPayload} -import com.twitter.visibility.thriftscala -import com.twitter.visibility.util.NamingUtils - -sealed trait Action { - lazy val name: String = NamingUtils.getFriendlyName(this) - lazy val fullName: String = NamingUtils.getFriendlyName(this) - - val severity: Int - def toActionThrift(): thriftscala.Action - - def isComposable: Boolean = false - - def toHealthActionTypeThrift: Option[HealthActionType] -} - -sealed trait Reason { - lazy val name: String = NamingUtils.getFriendlyName(this) -} - -sealed abstract class ActionWithReason(reason: Reason) extends Action { - override lazy val fullName: String = s"${this.name}/${reason.name}" -} - -object Reason { - - case object Bounce extends Reason - - case object ViewerReportedAuthor extends Reason - case object ViewerReportedTweet extends Reason - - case object DeactivatedAuthor extends Reason - case object OffboardedAuthor extends Reason - case object ErasedAuthor extends Reason - case object ProtectedAuthor extends Reason - case object SuspendedAuthor extends Reason - case object ViewerIsUnmentioned extends Reason - - case object Nsfw extends Reason - case object NsfwMedia extends Reason - case object NsfwViewerIsUnderage extends Reason - case object NsfwViewerHasNoStatedAge extends Reason - case object NsfwLoggedOut extends Reason - case object PossiblyUndesirable extends Reason - - case object AbuseEpisodic extends Reason - case object AbuseEpisodicEncourageSelfHarm extends Reason - case object AbuseEpisodicHatefulConduct extends Reason - case object AbuseGlorificationOfViolence extends Reason - case object AbuseGratuitousGore extends Reason - case object AbuseMobHarassment extends Reason - case object AbuseMomentOfDeathOrDeceasedUser extends Reason - case object AbusePrivateInformation extends Reason - case object AbuseRightToPrivacy extends Reason - case object AbuseThreatToExpose extends Reason - case object AbuseViolentSexualConduct extends Reason - case object AbuseViolentThreatHatefulConduct extends Reason - case object AbuseViolentThreatOrBounty extends Reason - - case object MutedKeyword extends Reason - case object Unspecified extends Reason - - case object UntrustedUrl extends Reason - - case object SpamReplyDownRank extends Reason - - case object LowQualityTweet extends Reason - - case object LowQualityMention extends Reason - - case object SpamHighRecallTweet extends Reason - - case object TweetLabelDuplicateContent extends Reason - - case object TweetLabelDuplicateMention extends Reason - - case object PdnaTweet extends Reason - - case object TweetLabeledSpam extends Reason - - case object OneOff extends Reason - case object VotingMisinformation extends Reason - case object HackedMaterials extends Reason - case object Scams extends Reason - case object PlatformManipulation extends Reason - - case object FirstPageSearchResult extends Reason - - case object MisinfoCivic extends Reason - case object MisinfoCrisis extends Reason - case object MisinfoGeneric extends Reason - case object MisinfoMedical extends Reason - case object Misleading extends Reason - case object ExclusiveTweet extends Reason - case object CommunityNotAMember extends Reason - case object CommunityTweetHidden extends Reason - case object CommunityTweetCommunityIsSuspended extends Reason - case object CommunityTweetAuthorRemoved extends Reason - case object InternalPromotedContent extends Reason - case object TrustedFriendsTweet extends Reason - case object Toxicity extends Reason - case object StaleTweet extends Reason - case object DmcaWithheld extends Reason - case object LegalDemandsWithheld extends Reason - case object LocalLawsWithheld extends Reason - case object HatefulConduct extends Reason - case object AbusiveBehavior extends Reason - - case object NotSupportedOnDevice extends Reason - - case object IpiDevelopmentOnly extends Reason - case object InterstitialDevelopmentOnly extends Reason - - case class FosnrReason(appealableReason: AppealableReason) extends Reason - - def toDropReason(reason: Reason): Option[DropReason] = - reason match { - case AuthorBlocksViewer => Some(DropReason.AuthorBlocksViewer) - case CommunityTweetHidden => Some(DropReason.CommunityTweetHidden) - case CommunityTweetCommunityIsSuspended => Some(DropReason.CommunityTweetCommunityIsSuspended) - case DmcaWithheld => Some(DropReason.DmcaWithheld) - case ExclusiveTweet => Some(DropReason.ExclusiveTweet) - case InternalPromotedContent => Some(DropReason.InternalPromotedContent) - case LegalDemandsWithheld => Some(DropReason.LegalDemandsWithheld) - case LocalLawsWithheld => Some(DropReason.LocalLawsWithheld) - case Nsfw => Some(DropReason.NsfwAuthor) - case NsfwLoggedOut => Some(DropReason.NsfwLoggedOut) - case NsfwViewerHasNoStatedAge => Some(DropReason.NsfwViewerHasNoStatedAge) - case NsfwViewerIsUnderage => Some(DropReason.NsfwViewerIsUnderage) - case ProtectedAuthor => Some(DropReason.ProtectedAuthor) - case StaleTweet => Some(DropReason.StaleTweet) - case SuspendedAuthor => Some(DropReason.SuspendedAuthor) - case Unspecified => Some(DropReason.Unspecified) - case ViewerBlocksAuthor => Some(DropReason.ViewerBlocksAuthor) - case ViewerHardMutedAuthor => Some(DropReason.ViewerMutesAuthor) - case ViewerMutesAuthor => Some(DropReason.ViewerMutesAuthor) - case TrustedFriendsTweet => Some(DropReason.TrustedFriendsTweet) - case _ => Some(DropReason.Unspecified) - } - - def fromDropReason(dropReason: DropReason): Reason = - dropReason match { - case DropReason.AuthorBlocksViewer => AuthorBlocksViewer - case DropReason.CommunityTweetHidden => CommunityTweetHidden - case DropReason.CommunityTweetCommunityIsSuspended => CommunityTweetCommunityIsSuspended - case DropReason.DmcaWithheld => DmcaWithheld - case DropReason.ExclusiveTweet => ExclusiveTweet - case DropReason.InternalPromotedContent => InternalPromotedContent - case DropReason.LegalDemandsWithheld => LegalDemandsWithheld - case DropReason.LocalLawsWithheld => LocalLawsWithheld - case DropReason.NsfwAuthor => Nsfw - case DropReason.NsfwLoggedOut => NsfwLoggedOut - case DropReason.NsfwViewerHasNoStatedAge => NsfwViewerHasNoStatedAge - case DropReason.NsfwViewerIsUnderage => NsfwViewerIsUnderage - case DropReason.ProtectedAuthor => ProtectedAuthor - case DropReason.StaleTweet => StaleTweet - case DropReason.SuspendedAuthor => SuspendedAuthor - case DropReason.ViewerBlocksAuthor => ViewerBlocksAuthor - case DropReason.ViewerMutesAuthor => ViewerMutesAuthor - case DropReason.TrustedFriendsTweet => TrustedFriendsTweet - case DropReason.Unspecified => Unspecified - } - - def toAppealableReason(reason: Reason, violationLevel: ViolationLevel): Option[AppealableReason] = - reason match { - case HatefulConduct => Some(AppealableReason.HatefulConduct(violationLevel.level)) - case AbusiveBehavior => Some(AppealableReason.AbusiveBehavior(violationLevel.level)) - case _ => Some(AppealableReason.Unspecified(violationLevel.level)) - } - - def fromAppealableReason(appealableReason: AppealableReason): Reason = - appealableReason match { - case AppealableReason.HatefulConduct(level) => HatefulConduct - case AppealableReason.AbusiveBehavior(level) => AbusiveBehavior - case AppealableReason.Unspecified(level) => Unspecified - } - - def toSoftInterventionReason(appealableReason: AppealableReason): SoftInterventionReason = - appealableReason match { - case AppealableReason.HatefulConduct(level) => - SoftInterventionReason.FosnrReason(appealableReason) - case AppealableReason.AbusiveBehavior(level) => - SoftInterventionReason.FosnrReason(appealableReason) - case AppealableReason.Unspecified(level) => - SoftInterventionReason.FosnrReason(appealableReason) - } - - def toLimitedEngagementReason(appealableReason: AppealableReason): LimitedEngagementReason = - appealableReason match { - case AppealableReason.HatefulConduct(level) => - LimitedEngagementReason.FosnrReason(appealableReason) - case AppealableReason.AbusiveBehavior(level) => - LimitedEngagementReason.FosnrReason(appealableReason) - case AppealableReason.Unspecified(level) => - LimitedEngagementReason.FosnrReason(appealableReason) - } - - val NSFW_MEDIA: Set[Reason] = Set(Nsfw, NsfwMedia) - - def toInterstitialReason(reason: Reason): Option[InterstitialReason] = - reason match { - case r if NSFW_MEDIA.contains(r) => Some(InterstitialReason.ContainsNsfwMedia) - case PossiblyUndesirable => Some(InterstitialReason.PossiblyUndesirable) - case MutedKeyword => Some(InterstitialReason.MatchesMutedKeyword("")) - case ViewerReportedAuthor => Some(InterstitialReason.ViewerReportedAuthor) - case ViewerReportedTweet => Some(InterstitialReason.ViewerReportedTweet) - case ViewerBlocksAuthor => Some(InterstitialReason.ViewerBlocksAuthor) - case ViewerMutesAuthor => Some(InterstitialReason.ViewerMutesAuthor) - case ViewerHardMutedAuthor => Some(InterstitialReason.ViewerMutesAuthor) - case InterstitialDevelopmentOnly => Some(InterstitialReason.DevelopmentOnly) - case DmcaWithheld => Some(InterstitialReason.DmcaWithheld) - case LegalDemandsWithheld => Some(InterstitialReason.LegalDemandsWithheld) - case LocalLawsWithheld => Some(InterstitialReason.LocalLawsWithheld) - case HatefulConduct => Some(InterstitialReason.HatefulConduct) - case AbusiveBehavior => Some(InterstitialReason.AbusiveBehavior) - case FosnrReason(appealableReason) => Some(InterstitialReason.FosnrReason(appealableReason)) - case _ => None - } - - def fromInterstitialReason(interstitialReason: InterstitialReason): Reason = - interstitialReason match { - case InterstitialReason.ContainsNsfwMedia => Reason.NsfwMedia - case InterstitialReason.PossiblyUndesirable => Reason.PossiblyUndesirable - case InterstitialReason.MatchesMutedKeyword(_) => Reason.MutedKeyword - case InterstitialReason.ViewerReportedAuthor => Reason.ViewerReportedAuthor - case InterstitialReason.ViewerReportedTweet => Reason.ViewerReportedTweet - case InterstitialReason.ViewerBlocksAuthor => Reason.ViewerBlocksAuthor - case InterstitialReason.ViewerMutesAuthor => Reason.ViewerMutesAuthor - case InterstitialReason.DevelopmentOnly => Reason.InterstitialDevelopmentOnly - case InterstitialReason.DmcaWithheld => Reason.DmcaWithheld - case InterstitialReason.LegalDemandsWithheld => Reason.LegalDemandsWithheld - case InterstitialReason.LocalLawsWithheld => Reason.LocalLawsWithheld - case InterstitialReason.HatefulConduct => Reason.HatefulConduct - case InterstitialReason.AbusiveBehavior => Reason.AbusiveBehavior - case InterstitialReason.FosnrReason(reason) => Reason.fromAppealableReason(reason) - } - -} - -sealed trait Epitaph { - lazy val name: String = NamingUtils.getFriendlyName(this) -} - -object Epitaph { - - case object Unavailable extends Epitaph - - case object Blocked extends Epitaph - case object BlockedBy extends Epitaph - case object Reported extends Epitaph - - case object BounceDeleted extends Epitaph - case object Deleted extends Epitaph - case object NotFound extends Epitaph - case object PublicInterest extends Epitaph - - case object Bounced extends Epitaph - case object Protected extends Epitaph - case object Suspended extends Epitaph - case object Offboarded extends Epitaph - case object Deactivated extends Epitaph - - case object MutedKeyword extends Epitaph - case object Underage extends Epitaph - case object NoStatedAge extends Epitaph - case object LoggedOutAge extends Epitaph - case object SuperFollowsContent extends Epitaph - - case object Moderated extends Epitaph - case object ForEmergencyUseOnly extends Epitaph - case object UnavailableWithoutLink extends Epitaph - case object CommunityTweetHidden extends Epitaph - case object CommunityTweetMemberRemoved extends Epitaph - case object CommunityTweetCommunityIsSuspended extends Epitaph - - case object UserSuspended extends Epitaph - - case object DevelopmentOnly extends Epitaph - - case object AdultMedia extends Epitaph - case object ViolentMedia extends Epitaph - case object OtherSensitiveMedia extends Epitaph - - case object DmcaWithheldMedia extends Epitaph - case object LegalDemandsWithheldMedia extends Epitaph - case object LocalLawsWithheldMedia extends Epitaph - - case object ToxicReplyFiltered extends Epitaph -} - -sealed trait IsInterstitial { - def toInterstitialThriftWrapper(): thriftscala.AnyInterstitial - def toInterstitialThrift(): ThriftStruct -} - -sealed trait IsAppealable { - def toAppealableThrift(): thriftscala.Appealable -} - -sealed trait IsLimitedEngagements { - def policy: Option[LimitedActionsPolicy] - def getLimitedEngagementReason: LimitedEngagementReason -} - -object IsLimitedEngagements { - def unapply( - ile: IsLimitedEngagements - ): Option[(Option[LimitedActionsPolicy], LimitedEngagementReason)] = { - Some((ile.policy, ile.getLimitedEngagementReason)) - } -} - -sealed abstract class ActionWithEpitaph(epitaph: Epitaph) extends Action { - override lazy val fullName: String = s"${this.name}/${epitaph.name}" -} - -case class Appealable( - reason: Reason, - violationLevel: ViolationLevel, - localizedMessage: Option[LocalizedMessage] = None) - extends ActionWithReason(reason) - with IsAppealable { - - override val severity: Int = 17 - override def toActionThrift(): thriftscala.Action = - thriftscala.Action.Appealable(toAppealableThrift()) - - override def toAppealableThrift(): thriftscala.Appealable = - thriftscala.Appealable( - Reason.toAppealableReason(reason, violationLevel).map(AppealableReasonConverter.toThrift), - localizedMessage.map(LocalizedMessageConverter.toThrift) - ) - - override def toHealthActionTypeThrift: Option[HealthActionType] = Some( - HealthActionType.Appealable) -} - -case class Drop(reason: Reason, applicableCountries: Option[Seq[String]] = None) - extends ActionWithReason(reason) { - - override val severity: Int = 16 - override def toActionThrift(): thriftscala.Action = - thriftscala.Action.Drop( - thriftscala.Drop( - Reason.toDropReason(reason).map(DropReasonConverter.toThrift), - applicableCountries - )) - - override def toHealthActionTypeThrift: Option[HealthActionType] = Some(HealthActionType.Drop) -} - -case class Interstitial( - reason: Reason, - localizedMessage: Option[LocalizedMessage] = None, - applicableCountries: Option[Seq[String]] = None) - extends ActionWithReason(reason) - with IsInterstitial { - - override val severity: Int = 10 - override def toInterstitialThriftWrapper(): thriftscala.AnyInterstitial = - thriftscala.AnyInterstitial.Interstitial( - toInterstitialThrift() - ) - - override def toInterstitialThrift(): thriftscala.Interstitial = - thriftscala.Interstitial( - Reason.toInterstitialReason(reason).map(InterstitialReasonConverter.toThrift), - localizedMessage.map(LocalizedMessageConverter.toThrift) - ) - - override def toActionThrift(): thriftscala.Action = - thriftscala.Action.Interstitial(toInterstitialThrift()) - - def toMediaActionThrift(): thriftscala.MediaAction = - thriftscala.MediaAction.Interstitial(toInterstitialThrift()) - - override def isComposable: Boolean = true - - override def toHealthActionTypeThrift: Option[HealthActionType] = Some( - HealthActionType.TweetInterstitial) -} - -case class InterstitialLimitedEngagements( - reason: Reason, - limitedEngagementReason: Option[LimitedEngagementReason], - localizedMessage: Option[LocalizedMessage] = None, - policy: Option[LimitedActionsPolicy] = None) - extends ActionWithReason(reason) - with IsInterstitial - with IsLimitedEngagements { - - override val severity: Int = 11 - override def toInterstitialThriftWrapper(): thriftscala.AnyInterstitial = - thriftscala.AnyInterstitial.InterstitialLimitedEngagements( - toInterstitialThrift() - ) - - override def toInterstitialThrift(): thriftscala.InterstitialLimitedEngagements = - thriftscala.InterstitialLimitedEngagements( - limitedEngagementReason.map(LimitedEngagementReasonConverter.toThrift), - localizedMessage.map(LocalizedMessageConverter.toThrift) - ) - - override def toActionThrift(): thriftscala.Action = - thriftscala.Action.InterstitialLimitedEngagements(toInterstitialThrift()) - - override def isComposable: Boolean = true - - override def toHealthActionTypeThrift: Option[HealthActionType] = Some( - HealthActionType.LimitedEngagements) - - def getLimitedEngagementReason: LimitedEngagementReason = limitedEngagementReason.getOrElse( - LimitedEngagementReason.NonCompliant - ) -} - -case object Allow extends Action { - - override val severity: Int = -1 - override def toActionThrift(): thriftscala.Action = - thriftscala.Action.Allow(thriftscala.Allow()) - - override def toHealthActionTypeThrift: Option[HealthActionType] = None -} - -case object NotEvaluated extends Action { - - override val severity: Int = -1 - override def toActionThrift(): thriftscala.Action = - thriftscala.Action.NotEvaluated(thriftscala.NotEvaluated()) - - override def toHealthActionTypeThrift: Option[HealthActionType] = None -} - -case class Tombstone(epitaph: Epitaph, applicableCountryCodes: Option[Seq[String]] = None) - extends ActionWithEpitaph(epitaph) { - - override val severity: Int = 15 - override def toActionThrift(): thriftscala.Action = - thriftscala.Action.Tombstone(thriftscala.Tombstone()) - - override def toHealthActionTypeThrift: Option[HealthActionType] = Some(HealthActionType.Tombstone) -} - -case class LocalizedTombstone(reason: TombstoneReason, message: LocalizedMessage) extends Action { - override lazy val fullName: String = s"${this.name}/${NamingUtils.getFriendlyName(reason)}" - - override val severity: Int = 15 - override def toActionThrift(): thriftscala.Action = - thriftscala.Action.Tombstone( - thriftscala.Tombstone( - reason = TombstoneReasonConverter.toThrift(Some(reason)), - message = Some(LocalizedMessageConverter.toThrift(message)) - )) - - override def toHealthActionTypeThrift: Option[HealthActionType] = Some(HealthActionType.Tombstone) -} - -case class DownrankHomeTimeline(reason: Option[DownrankHomeTimelineReason]) extends Action { - - override val severity: Int = 9 - override def toActionThrift(): thriftscala.Action = - thriftscala.Action.DownrankHomeTimeline(toDownrankThrift()) - - def toDownrankThrift(): thriftscala.DownrankHomeTimeline = - thriftscala.DownrankHomeTimeline( - reason.map(DownrankHomeTimelineReasonConverter.toThrift) - ) - - override def isComposable: Boolean = true - - override def toHealthActionTypeThrift: Option[HealthActionType] = Some(HealthActionType.Downrank) -} - -case class Avoid(avoidReason: Option[AvoidReason] = None) extends Action { - - override val severity: Int = 1 - override def toActionThrift(): thriftscala.Action = - thriftscala.Action.Avoid(toAvoidThrift()) - - def toAvoidThrift(): thriftscala.Avoid = - thriftscala.Avoid( - avoidReason.map(AvoidReasonConverter.toThrift) - ) - - override def isComposable: Boolean = true - - override def toHealthActionTypeThrift: Option[HealthActionType] = Some(HealthActionType.Avoid) -} - -case object Downrank extends Action { - - override val severity: Int = 0 - override def toActionThrift(): thriftscala.Action = - thriftscala.Action.Downrank(thriftscala.Downrank()) - - override def toHealthActionTypeThrift: Option[HealthActionType] = Some(HealthActionType.Downrank) -} - -case object ConversationSectionLowQuality extends Action { - - override val severity: Int = 4 - override def toActionThrift(): thriftscala.Action = - thriftscala.Action.ConversationSectionLowQuality(thriftscala.ConversationSectionLowQuality()) - - override def toHealthActionTypeThrift: Option[HealthActionType] = Some( - HealthActionType.ConversationSectionLowQuality) -} - -case object ConversationSectionAbusiveQuality extends Action { - - override val severity: Int = 5 - override def toActionThrift(): thriftscala.Action = - thriftscala.Action.ConversationSectionAbusiveQuality( - thriftscala.ConversationSectionAbusiveQuality()) - - override def toHealthActionTypeThrift: Option[HealthActionType] = Some( - HealthActionType.ConversationSectionAbusiveQuality) - - def toConversationSectionAbusiveQualityThrift(): thriftscala.ConversationSectionAbusiveQuality = - thriftscala.ConversationSectionAbusiveQuality() -} - -case class LimitedEngagements( - reason: LimitedEngagementReason, - policy: Option[LimitedActionsPolicy] = None) - extends Action - with IsLimitedEngagements { - - override val severity: Int = 6 - override def toActionThrift(): thriftscala.Action = - thriftscala.Action.LimitedEngagements(toLimitedEngagementsThrift()) - - def toLimitedEngagementsThrift(): thriftscala.LimitedEngagements = - thriftscala.LimitedEngagements( - Some(LimitedEngagementReasonConverter.toThrift(reason)), - policy.map(LimitedActionsPolicyConverter.toThrift), - Some(reason.toLimitedActionsString) - ) - - override def isComposable: Boolean = true - - override def toHealthActionTypeThrift: Option[HealthActionType] = Some( - HealthActionType.LimitedEngagements) - - def getLimitedEngagementReason: LimitedEngagementReason = reason -} - -case class EmergencyDynamicInterstitial( - copy: String, - linkOpt: Option[String], - localizedMessage: Option[LocalizedMessage] = None, - policy: Option[LimitedActionsPolicy] = None) - extends Action - with IsInterstitial - with IsLimitedEngagements { - - override val severity: Int = 11 - override def toInterstitialThriftWrapper(): thriftscala.AnyInterstitial = - thriftscala.AnyInterstitial.EmergencyDynamicInterstitial( - toInterstitialThrift() - ) - - override def toInterstitialThrift(): thriftscala.EmergencyDynamicInterstitial = - thriftscala.EmergencyDynamicInterstitial( - copy, - linkOpt, - localizedMessage.map(LocalizedMessageConverter.toThrift) - ) - - override def toActionThrift(): thriftscala.Action = - thriftscala.Action.EmergencyDynamicInterstitial(toInterstitialThrift()) - - override def isComposable: Boolean = true - - override def toHealthActionTypeThrift: Option[HealthActionType] = Some( - HealthActionType.TweetInterstitial) - - def getLimitedEngagementReason: LimitedEngagementReason = LimitedEngagementReason.NonCompliant -} - -case class SoftIntervention( - reason: SoftInterventionReason, - engagementNudge: Boolean, - suppressAutoplay: Boolean, - warning: Option[String] = None, - detailsUrl: Option[String] = None, - displayType: Option[SoftInterventionDisplayType] = None, - fleetInterstitial: Option[FleetInterstitial] = None) - extends Action { - - override val severity: Int = 7 - def toSoftInterventionThrift(): thriftscala.SoftIntervention = - thriftscala.SoftIntervention( - Some(SoftInterventionReasonConverter.toThrift(reason)), - engagementNudge = Some(engagementNudge), - suppressAutoplay = Some(suppressAutoplay), - warning = warning, - detailsUrl = detailsUrl, - displayType = SoftInterventionDisplayTypeConverter.toThrift(displayType) - ) - - override def toActionThrift(): thriftscala.Action = - thriftscala.Action.SoftIntervention(toSoftInterventionThrift()) - - override def isComposable: Boolean = true - - override def toHealthActionTypeThrift: Option[HealthActionType] = Some( - HealthActionType.SoftIntervention) -} - -case class TweetInterstitial( - interstitial: Option[IsInterstitial], - softIntervention: Option[SoftIntervention], - limitedEngagements: Option[LimitedEngagements], - downrank: Option[DownrankHomeTimeline], - avoid: Option[Avoid], - mediaInterstitial: Option[Interstitial] = None, - tweetVisibilityNudge: Option[TweetVisibilityNudge] = None, - abusiveQuality: Option[ConversationSectionAbusiveQuality.type] = None, - appealable: Option[Appealable] = None) - extends Action { - - override val severity: Int = 12 - override def toActionThrift(): thriftscala.Action = - thriftscala.Action.TweetInterstitial( - thriftscala.TweetInterstitial( - interstitial.map(_.toInterstitialThriftWrapper()), - softIntervention.map(_.toSoftInterventionThrift()), - limitedEngagements.map(_.toLimitedEngagementsThrift()), - downrank.map(_.toDownrankThrift()), - avoid.map(_.toAvoidThrift()), - mediaInterstitial.map(_.toMediaActionThrift()), - tweetVisibilityNudge.map(_.toTweetVisbilityNudgeThrift()), - abusiveQuality.map(_.toConversationSectionAbusiveQualityThrift()), - appealable.map(_.toAppealableThrift()) - ) - ) - - override def toHealthActionTypeThrift: Option[HealthActionType] = Some( - HealthActionType.TweetInterstitial) -} - -sealed trait LocalizedNudgeActionType -object LocalizedNudgeActionType { - case object Reply extends LocalizedNudgeActionType - case object Retweet extends LocalizedNudgeActionType - case object Like extends LocalizedNudgeActionType - case object Share extends LocalizedNudgeActionType - case object Unspecified extends LocalizedNudgeActionType - - def toThrift( - localizedNudgeActionType: LocalizedNudgeActionType - ): thriftscala.TweetVisibilityNudgeActionType = - localizedNudgeActionType match { - case Reply => thriftscala.TweetVisibilityNudgeActionType.Reply - case Retweet => thriftscala.TweetVisibilityNudgeActionType.Retweet - case Like => thriftscala.TweetVisibilityNudgeActionType.Like - case Share => thriftscala.TweetVisibilityNudgeActionType.Share - case Unspecified => - thriftscala.TweetVisibilityNudgeActionType.EnumUnknownTweetVisibilityNudgeActionType(5) - } - - def fromStratoThrift(stratoNudgeActionType: StratoNudgeActionType): LocalizedNudgeActionType = - stratoNudgeActionType match { - case StratoNudgeActionType.Reply => Reply - case StratoNudgeActionType.Retweet => Retweet - case StratoNudgeActionType.Like => Like - case StratoNudgeActionType.Share => Share - case EnumUnknownNudgeActionType(_) => Unspecified - } -} - -case class LocalizedNudgeActionPayload( - heading: Option[String], - subheading: Option[String], - iconName: Option[String], - ctaTitle: Option[String], - ctaUrl: Option[String], - postCtaText: Option[String]) { - - def toThrift(): thriftscala.TweetVisibilityNudgeActionPayload = { - thriftscala.TweetVisibilityNudgeActionPayload( - heading = heading, - subheading = subheading, - iconName = iconName, - ctaTitle = ctaTitle, - ctaUrl = ctaUrl, - postCtaText = postCtaText - ) - } -} - -object LocalizedNudgeActionPayload { - def fromStratoThrift( - stratoNudgeActionPayload: StratoNudgeActionPayload - ): LocalizedNudgeActionPayload = - LocalizedNudgeActionPayload( - heading = stratoNudgeActionPayload.heading, - subheading = stratoNudgeActionPayload.subheading, - iconName = stratoNudgeActionPayload.iconName, - ctaTitle = stratoNudgeActionPayload.ctaTitle, - ctaUrl = stratoNudgeActionPayload.ctaUrl, - postCtaText = stratoNudgeActionPayload.postCtaText - ) -} - -case class LocalizedNudgeAction( - nudgeActionType: LocalizedNudgeActionType, - nudgeActionPayload: Option[LocalizedNudgeActionPayload]) { - def toThrift(): thriftscala.TweetVisibilityNudgeAction = { - thriftscala.TweetVisibilityNudgeAction( - tweetVisibilitynudgeActionType = LocalizedNudgeActionType.toThrift(nudgeActionType), - tweetVisibilityNudgeActionPayload = nudgeActionPayload.map(_.toThrift) - ) - } -} - -object LocalizedNudgeAction { - def fromStratoThrift(stratoNudgeAction: StratoNudgeAction): LocalizedNudgeAction = - LocalizedNudgeAction( - nudgeActionType = - LocalizedNudgeActionType.fromStratoThrift(stratoNudgeAction.nudgeActionType), - nudgeActionPayload = - stratoNudgeAction.nudgeActionPayload.map(LocalizedNudgeActionPayload.fromStratoThrift) - ) -} - -case class LocalizedNudge(localizedNudgeActions: Seq[LocalizedNudgeAction]) - -case object LocalizedNudge { - def fromStratoThrift(stratoNudge: StratoNudge): LocalizedNudge = - LocalizedNudge(localizedNudgeActions = - stratoNudge.nudgeActions.map(LocalizedNudgeAction.fromStratoThrift)) -} - -case class TweetVisibilityNudge( - reason: TweetVisibilityNudgeReason, - localizedNudge: Option[LocalizedNudge] = None) - extends Action { - - override val severity: Int = 3 - override def toActionThrift(): thriftscala.Action = - thriftscala.Action.TweetVisibilityNudge( - localizedNudge match { - case Some(nudge) => - thriftscala.TweetVisibilityNudge( - tweetVisibilityNudgeActions = Some(nudge.localizedNudgeActions.map(_.toThrift())) - ) - case _ => thriftscala.TweetVisibilityNudge(tweetVisibilityNudgeActions = None) - } - ) - - override def toHealthActionTypeThrift: Option[HealthActionType] = - Some(HealthActionType.TweetVisibilityNudge) - - def toTweetVisbilityNudgeThrift(): thriftscala.TweetVisibilityNudge = - thriftscala.TweetVisibilityNudge(tweetVisibilityNudgeActions = - localizedNudge.map(_.localizedNudgeActions.map(_.toThrift()))) -} - -trait BaseComplianceTweetNotice { - val complianceTweetNoticeEventType: ComplianceTweetNoticeEventType - val details: Option[String] - val extendedDetailsUrl: Option[String] -} - -case class ComplianceTweetNoticePreEnrichment( - reason: Reason, - complianceTweetNoticeEventType: ComplianceTweetNoticeEventType, - details: Option[String] = None, - extendedDetailsUrl: Option[String] = None) - extends Action - with BaseComplianceTweetNotice { - - override val severity: Int = 2 - def toComplianceTweetNoticeThrift(): thriftscala.ComplianceTweetNotice = - thriftscala.ComplianceTweetNotice( - ComplianceTweetNoticeEventTypeConverter.toThrift(complianceTweetNoticeEventType), - ComplianceTweetNoticeEventTypeConverter.eventTypeToLabelTitle(complianceTweetNoticeEventType), - details, - extendedDetailsUrl - ) - - override def toActionThrift(): thriftscala.Action = - thriftscala.Action.ComplianceTweetNotice( - toComplianceTweetNoticeThrift() - ) - - override def toHealthActionTypeThrift: Option[HealthActionType] = None - - def toComplianceTweetNotice(): ComplianceTweetNotice = { - ComplianceTweetNotice( - complianceTweetNoticeEventType = complianceTweetNoticeEventType, - labelTitle = ComplianceTweetNoticeEventTypeConverter.eventTypeToLabelTitle( - complianceTweetNoticeEventType), - details = details, - extendedDetailsUrl = extendedDetailsUrl - ) - } -} - -case class ComplianceTweetNotice( - complianceTweetNoticeEventType: ComplianceTweetNoticeEventType, - labelTitle: Option[String] = None, - details: Option[String] = None, - extendedDetailsUrl: Option[String] = None) - extends Action - with BaseComplianceTweetNotice { - - override val severity: Int = 2 - def toComplianceTweetNoticeThrift(): thriftscala.ComplianceTweetNotice = - thriftscala.ComplianceTweetNotice( - ComplianceTweetNoticeEventTypeConverter.toThrift(complianceTweetNoticeEventType), - labelTitle, - details, - extendedDetailsUrl - ) - - override def toActionThrift(): thriftscala.Action = - thriftscala.Action.ComplianceTweetNotice( - toComplianceTweetNoticeThrift() - ) - - override def toHealthActionTypeThrift: Option[HealthActionType] = None -} - -object Action { - def toThrift[T <: Action](action: T): thriftscala.Action = - action.toActionThrift() - - def getFirstInterstitial(actions: Action*): Option[IsInterstitial] = - actions.collectFirst { - case ile: InterstitialLimitedEngagements => ile - case edi: EmergencyDynamicInterstitial => edi - case i: Interstitial => i - } - - def getFirstSoftIntervention(actions: Action*): Option[SoftIntervention] = - actions.collectFirst { - case si: SoftIntervention => si - } - - def getFirstLimitedEngagements(actions: Action*): Option[LimitedEngagements] = - actions.collectFirst { - case le: LimitedEngagements => le - } - - def getAllLimitedEngagements(actions: Action*): Seq[IsLimitedEngagements] = - actions.collect { - case ile: IsLimitedEngagements => ile - } - - def getFirstDownrankHomeTimeline(actions: Action*): Option[DownrankHomeTimeline] = - actions.collectFirst { - case dr: DownrankHomeTimeline => dr - } - - def getFirstAvoid(actions: Action*): Option[Avoid] = - actions.collectFirst { - case a: Avoid => a - } - - def getFirstMediaInterstitial(actions: Action*): Option[Interstitial] = - actions.collectFirst { - case i: Interstitial if Reason.NSFW_MEDIA.contains(i.reason) => i - } - - def getFirstTweetVisibilityNudge(actions: Action*): Option[TweetVisibilityNudge] = - actions.collectFirst { - case n: TweetVisibilityNudge => n - } -} - -sealed trait State { - lazy val name: String = NamingUtils.getFriendlyName(this) -} - -object State { - case object Pending extends State - case object Disabled extends State - final case class MissingFeature(features: Set[Feature[_]]) extends State - final case class FeatureFailed(features: Map[Feature[_], Throwable]) extends State - final case class RuleFailed(throwable: Throwable) extends State - case object Skipped extends State - case object ShortCircuited extends State - case object Heldback extends State - case object Evaluated extends State -} - -case class RuleResult(action: Action, state: State) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/AdvancedFilteringRules.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/AdvancedFilteringRules.scala deleted file mode 100644 index f3e3da102..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/AdvancedFilteringRules.scala +++ /dev/null @@ -1,71 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.gizmoduck.thriftscala.MentionFilter.Following -import com.twitter.visibility.features.ViewerMentionFilter -import com.twitter.visibility.rules.Condition._ -import com.twitter.visibility.rules.Reason.Unspecified - -object NoConfirmedEmailRule - extends RuleWithConstantAction( - Drop(Unspecified), - And( - NonAuthorViewer, - Not(ViewerDoesFollowAuthor), - ViewerFiltersNoConfirmedEmail, - Not(AuthorHasConfirmedEmail) - ) - ) - -object NoConfirmedPhoneRule - extends RuleWithConstantAction( - Drop(Unspecified), - And( - NonAuthorViewer, - Not(ViewerDoesFollowAuthor), - ViewerFiltersNoConfirmedPhone, - Not(AuthorHasVerifiedPhone) - ) - ) - -object NoDefaultProfileImageRule - extends RuleWithConstantAction( - Drop(Unspecified), - And( - NonAuthorViewer, - Not(ViewerDoesFollowAuthor), - ViewerFiltersDefaultProfileImage, - AuthorHasDefaultProfileImage - ) - ) - -object NoNewUsersRule - extends RuleWithConstantAction( - Drop(Unspecified), - And( - NonAuthorViewer, - Not(ViewerDoesFollowAuthor), - AuthorIsNewAccount - ) - ) - -object NoNotFollowedByRule - extends RuleWithConstantAction( - Drop(Unspecified), - And( - NonAuthorViewer, - Not(ViewerDoesFollowAuthor), - ViewerFiltersNotFollowedBy, - Not(AuthorDoesFollowViewer) - ) - ) - -object OnlyPeopleIFollowRule - extends RuleWithConstantAction( - Drop(Unspecified), - And( - NonAuthorViewer, - Not(ViewerDoesFollowAuthor), - Equals(ViewerMentionFilter, Following), - Not(NotificationIsOnCommunityTweet) - ) - ) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/rules/BUILD deleted file mode 100644 index a8c1c0ac1..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/BUILD +++ /dev/null @@ -1,37 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/google/guava", - "3rdparty/jvm/com/squareup/okhttp:okhttp3", - "abdecider/src/main/scala", - "configapi/configapi-core", - "decider/src/main/scala", - "health-platform-manipulation/src/main/scala/com/twitter/health/platform_manipulation/stcm_tweet_holdback", - "scribelib/marshallers/src/main/scala/com/twitter/scribelib/marshallers", - "servo/decider/src/main/scala", - "snowflake/src/main/scala/com/twitter/snowflake/id", - "src/scala/com/twitter/takedown/util", - "src/thrift/com/twitter/content-health/sensitivemediasettings:sensitivemediasettings-scala", - "src/thrift/com/twitter/gizmoduck:user-thrift-scala", - "src/thrift/com/twitter/search/common:constants-scala", - "src/thrift/com/twitter/spam/rtf:safety-level-scala", - "src/thrift/com/twitter/spam/rtf:safety-result-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "stitch/stitch-core/src/main/scala/com/twitter/stitch", - "visibility/common/src/main/scala/com/twitter/visibility/common/actions", - "visibility/common/src/main/scala/com/twitter/visibility/common/actions/converter/scala", - "visibility/common/src/main/thrift/com/twitter/visibility:action-scala", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/configs", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/params", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/models", - "visibility/lib/src/main/scala/com/twitter/visibility/util", - "visibility/lib/src/main/thrift/com/twitter/visibility/logging:vf-logging-scala", - "visibility/lib/src/main/thrift/com/twitter/visibility/strato:vf-strato-scala", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/CardRules.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/CardRules.scala deleted file mode 100644 index 695d40ad4..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/CardRules.scala +++ /dev/null @@ -1,52 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.visibility.configapi.params.FSRuleParams.CardUriRootDomainDenyListParam -import com.twitter.visibility.configapi.params.RuleParam -import com.twitter.visibility.configapi.params.RuleParams.EnableCardUriRootDomainCardDenylistRule -import com.twitter.visibility.configapi.params.RuleParams.EnableCommunityNonMemberPollCardRule -import com.twitter.visibility.configapi.params.RuleParams.EnableCommunityNonMemberPollCardRuleFailClosed -import com.twitter.visibility.rules.Condition.And -import com.twitter.visibility.rules.Condition.CardUriHasRootDomain -import com.twitter.visibility.rules.Condition.CommunityTweetCommunityVisible -import com.twitter.visibility.rules.Condition.IsPollCard -import com.twitter.visibility.rules.Condition.LoggedOutOrViewerNotFollowingAuthor -import com.twitter.visibility.rules.Condition.Not -import com.twitter.visibility.rules.Condition.Or -import com.twitter.visibility.rules.Condition.ProtectedAuthor -import com.twitter.visibility.rules.Condition.TweetIsCommunityTweet -import com.twitter.visibility.rules.Condition.ViewerIsCommunityMember - -object DropProtectedAuthorPollCardRule - extends RuleWithConstantAction( - Drop(Reason.ProtectedAuthor), - And( - IsPollCard, - ProtectedAuthor, - LoggedOutOrViewerNotFollowingAuthor, - ) - ) - -object DropCardUriRootDomainDenylistRule - extends RuleWithConstantAction( - Drop(Reason.Unspecified), - And(CardUriHasRootDomain(CardUriRootDomainDenyListParam)) - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableCardUriRootDomainCardDenylistRule) -} - -object DropCommunityNonMemberPollCardRule - extends RuleWithConstantAction( - Drop(Reason.CommunityNotAMember), - And( - IsPollCard, - TweetIsCommunityTweet, - Or( - Not(ViewerIsCommunityMember), - Not(CommunityTweetCommunityVisible), - ) - ), - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableCommunityNonMemberPollCardRule) - override def enableFailClosed: Seq[RuleParam[Boolean]] = Seq( - EnableCommunityNonMemberPollCardRuleFailClosed) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/ComposableActions.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/ComposableActions.scala deleted file mode 100644 index 36b647618..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/ComposableActions.scala +++ /dev/null @@ -1,45 +0,0 @@ -package com.twitter.visibility.rules - -object ComposableActions { - - object ComposableActionsWithConversationSectionAbusiveQuality { - def unapply( - composableActions: TweetInterstitial - ): Option[ConversationSectionAbusiveQuality.type] = { - composableActions.abusiveQuality - } - } - - object ComposableActionsWithSoftIntervention { - def unapply(composableActions: TweetInterstitial): Option[SoftIntervention] = { - composableActions.softIntervention match { - case Some(si: SoftIntervention) => Some(si) - case _ => None - } - } - } - - object ComposableActionsWithInterstitialLimitedEngagements { - def unapply(composableActions: TweetInterstitial): Option[InterstitialLimitedEngagements] = { - composableActions.interstitial match { - case Some(ile: InterstitialLimitedEngagements) => Some(ile) - case _ => None - } - } - } - - object ComposableActionsWithInterstitial { - def unapply(composableActions: TweetInterstitial): Option[Interstitial] = { - composableActions.interstitial match { - case Some(i: Interstitial) => Some(i) - case _ => None - } - } - } - - object ComposableActionsWithAppealable { - def unapply(composableActions: TweetInterstitial): Option[Appealable] = { - composableActions.appealable - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/Condition.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/Condition.scala deleted file mode 100644 index 7d2dcde3c..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/Condition.scala +++ /dev/null @@ -1,2401 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.contenthealth.sensitivemediasettings.thriftscala.SensitiveMediaSettingsLevel -import com.twitter.contenthealth.toxicreplyfilter.thriftscala.FilterState -import com.twitter.conversions.DurationOps._ -import com.twitter.gizmoduck.thriftscala.Label -import com.twitter.gizmoduck.thriftscala.MuteSurface -import com.twitter.health.platform_manipulation.stcm_tweet_holdback.StcmTweetHoldback -import com.twitter.search.common.constants.thriftscala.ThriftQuerySource -import com.twitter.snowflake.id.SnowflakeId -import com.twitter.takedown.util.TakedownReasons -import com.twitter.takedown.util.{TakedownReasons => TakedownReasonsUtil} -import com.twitter.timelines.configapi.EnumParam -import com.twitter.timelines.configapi.Param -import com.twitter.timelines.configapi.Params -import com.twitter.tseng.withholding.thriftscala.TakedownReason -import com.twitter.util.Duration -import com.twitter.util.Time -import com.twitter.visibility.configapi.params.RuleParam -import com.twitter.visibility.configapi.params.RuleParams -import com.twitter.visibility.features.AuthorIsSuspended -import com.twitter.visibility.features.CardIsPoll -import com.twitter.visibility.features.CardUriHost -import com.twitter.visibility.features.SearchQuerySource -import com.twitter.visibility.features._ -import com.twitter.visibility.features.{AuthorBlocksOuterAuthor => AuthorBlocksOuterAuthorFeature} -import com.twitter.visibility.features.{AuthorBlocksViewer => AuthorBlocksViewerFeature} -import com.twitter.visibility.features.{ - CommunityTweetAuthorIsRemoved => CommunityTweetAuthorIsRemovedFeature -} -import com.twitter.visibility.features.{ - CommunityTweetCommunityNotFound => CommunityTweetCommunityNotFoundFeature -} -import com.twitter.visibility.features.{ - CommunityTweetCommunityDeleted => CommunityTweetCommunityDeletedFeature -} -import com.twitter.visibility.features.{ - CommunityTweetCommunitySuspended => CommunityTweetCommunitySuspendedFeature -} -import com.twitter.visibility.features.{ - CommunityTweetCommunityVisible => CommunityTweetCommunityVisibleFeature -} -import com.twitter.visibility.features.{CommunityTweetIsHidden => CommunityTweetIsHiddenFeature} -import com.twitter.visibility.features.{ - NotificationIsOnCommunityTweet => NotificationIsOnCommunityTweetFeature -} -import com.twitter.visibility.features.{OuterAuthorFollowsAuthor => OuterAuthorFollowsAuthorFeature} -import com.twitter.visibility.features.{OuterAuthorIsInnerAuthor => OuterAuthorIsInnerAuthorFeature} -import com.twitter.visibility.features.{TweetHasCard => TweetHasCardFeature} -import com.twitter.visibility.features.{TweetHasMedia => TweetHasMediaFeature} -import com.twitter.visibility.features.{TweetIsCommunityTweet => TweetIsCommunityTweetFeature} -import com.twitter.visibility.features.{TweetIsEditTweet => TweetIsEditTweetFeature} -import com.twitter.visibility.features.{TweetIsStaleTweet => TweetIsStaleTweetFeature} -import com.twitter.visibility.features.{ViewerBlocksAuthor => ViewerBlocksAuthorFeature} -import com.twitter.visibility.features.{ViewerIsCommunityAdmin => ViewerIsCommunityAdminFeature} -import com.twitter.visibility.features.{ViewerIsCommunityMember => ViewerIsCommunityMemberFeature} -import com.twitter.visibility.features.{ - ViewerIsCommunityModerator => ViewerIsCommunityModeratorFeature -} -import com.twitter.visibility.features.{ - ViewerIsInternalCommunitiesAdmin => ViewerIsInternalCommunitiesAdminFeature -} -import com.twitter.visibility.features.{ViewerMutesAuthor => ViewerMutesAuthorFeature} -import com.twitter.visibility.features.{ - ViewerMutesRetweetsFromAuthor => ViewerMutesRetweetsFromAuthorFeature -} -import com.twitter.visibility.models.ViolationLevel -import com.twitter.visibility.models._ -import com.twitter.visibility.rules.Result.FoundCardUriRootDomain -import com.twitter.visibility.rules.Result.FoundMediaLabel -import com.twitter.visibility.rules.Result.FoundSpaceLabel -import com.twitter.visibility.rules.Result.FoundSpaceLabelWithScoreAboveThreshold -import com.twitter.visibility.rules.Result.FoundTweetLabel -import com.twitter.visibility.rules.Result.FoundTweetLabelForPerspectivalUser -import com.twitter.visibility.rules.Result.FoundTweetLabelWithLanguageIn -import com.twitter.visibility.rules.Result.FoundTweetLabelWithLanguageScoreAboveThreshold -import com.twitter.visibility.rules.Result.FoundTweetLabelWithScoreAboveThreshold -import com.twitter.visibility.rules.Result.FoundTweetViolationOfLevel -import com.twitter.visibility.rules.Result.FoundTweetViolationOfSomeLevel -import com.twitter.visibility.rules.Result.FoundUserLabel -import com.twitter.visibility.rules.Result.FoundUserRole -import com.twitter.visibility.rules.Result.HasQuerySource -import com.twitter.visibility.rules.Result.HasTweetTimestampAfterCutoff -import com.twitter.visibility.rules.Result.HasTweetTimestampAfterOffset -import com.twitter.visibility.rules.Result.HasTweetTimestampBeforeCutoff -import com.twitter.visibility.rules.Result.ParamWasTrue -import com.twitter.visibility.rules.Result.Result -import com.twitter.visibility.rules.Result.Satisfied -import com.twitter.visibility.rules.Result.Unsatisfied -import com.twitter.visibility.util.NamingUtils -import com.twitter.visibility.{features => feats} - -sealed trait PreFilterResult -case object Filtered extends PreFilterResult -case object NeedsFullEvaluation extends PreFilterResult -case object NotFiltered extends PreFilterResult - -sealed trait Condition { - lazy val name: String = NamingUtils.getFriendlyName(this) - def features: Set[Feature[_]] - def optionalFeatures: Set[Feature[_]] - - def preFilter( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): PreFilterResult = { - if (features.forall(featureMap.contains)) { - if (apply(evaluationContext, featureMap).asBoolean) { - NotFiltered - } else { - Filtered - } - } else { - NeedsFullEvaluation - } - } - - def apply(evaluationContext: EvaluationContext, featureMap: Map[Feature[_], _]): Result -} - -trait PreFilterOnOptionalFeatures extends Condition { - override def preFilter( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): PreFilterResult = - if ((features ++ optionalFeatures).forall(featureMap.contains)) { - if (apply(evaluationContext, featureMap).asBoolean) { - NotFiltered - } else { - Filtered - } - } else { - NeedsFullEvaluation - } -} - -trait HasSafetyLabelType { - val labelTypes: Set[SafetyLabelType] - def hasLabelType(labelType: SafetyLabelType): Boolean = labelTypes.contains(labelType) -} - -sealed trait HasNestedConditions extends HasSafetyLabelType { - val conditions: Seq[Condition] - override lazy val labelTypes: Set[SafetyLabelType] = conditions - .collect { - case lt: HasSafetyLabelType => lt.labelTypes - }.flatten.toSet -} - -object Result { - sealed trait ConditionReason - case object FoundInnerQuotedTweet extends ConditionReason - case object FoundTweetViolationOfSomeLevel extends ConditionReason - case class FoundTweetViolationOfLevel(level: ViolationLevel) extends ConditionReason - case class FoundTweetLabel(label: TweetSafetyLabelType) extends ConditionReason - case class FoundSpaceLabel(label: SpaceSafetyLabelType) extends ConditionReason - case class FoundMediaLabel(label: MediaSafetyLabelType) extends ConditionReason - case class FoundTweetLabelForPerspectivalUser(label: TweetSafetyLabelType) extends ConditionReason - case class FoundTweetLabelWithLanguageScoreAboveThreshold( - label: TweetSafetyLabelType, - languagesToScoreThresholds: Map[String, Double]) - extends ConditionReason - case class FoundTweetLabelWithScoreAboveThreshold(label: TweetSafetyLabelType, threshold: Double) - extends ConditionReason - case class FoundTweetLabelWithLanguageIn( - safetyLabelType: TweetSafetyLabelType, - languages: Set[String]) - extends ConditionReason - case class FoundTweetSafetyLabelWithPredicate(safetyLabelType: TweetSafetyLabelType, name: String) - extends ConditionReason - case class FoundUserLabel(label: UserLabelValue) extends ConditionReason - case class FoundMutedKeyword(keyword: String) extends ConditionReason - case object HasTweetTimestampAfterCutoff extends ConditionReason - case object HasTweetTimestampAfterOffset extends ConditionReason - case object HasTweetTimestampBeforeCutoff extends ConditionReason - case class IsTweetReplyToParentTweetBeforeDuration(duration: Duration) extends ConditionReason - case class IsTweetReplyToRootTweetBeforeDuration(duration: Duration) extends ConditionReason - case class HasQuerySource(querySource: ThriftQuerySource) extends ConditionReason - case class FoundUserRole(role: String) extends ConditionReason - case class ViewerInHrcj(jurisdiction: String) extends ConditionReason - case class ViewerOrRequestInCountry(country: String) extends ConditionReason - case class ViewerAgeInYears(ageInYears: Int) extends ConditionReason - case object NoViewerAge extends ConditionReason - case class ParamWasTrue(param: Param[Boolean]) extends ConditionReason - case class FoundCardUriRootDomain(domain: String) extends ConditionReason - case object Unknown extends ConditionReason - - sealed trait Result { - def asBoolean: Boolean - } - - val SatisfiedResult: Result = Satisfied() - - case class Satisfied(reason: ConditionReason = Unknown) extends Result { - override val asBoolean: Boolean = true - } - - case class Unsatisfied(condition: Condition) extends Result { - override val asBoolean: Boolean = false - } - - def fromMutedKeyword(mutedKeyword: MutedKeyword, unsatisfied: Unsatisfied): Result = { - mutedKeyword match { - case MutedKeyword(Some(keyword)) => Satisfied(FoundMutedKeyword(keyword)) - case _ => unsatisfied - } - } - - case class FoundSpaceLabelWithScoreAboveThreshold(label: SpaceSafetyLabelType, threshold: Double) - extends ConditionReason -} - -object Condition { - - abstract class BooleanFeatureCondition(feature: Feature[Boolean]) extends Condition { - override val features: Set[Feature[_]] = Set(feature) - override val optionalFeatures: Set[Feature[_]] = Set.empty - - private val UnsatisfiedResult = Unsatisfied(this) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = - if (featureMap(feature).asInstanceOf[Boolean]) { - Result.SatisfiedResult - } else { - UnsatisfiedResult - } - } - - case class ParamIsTrue(param: Param[Boolean]) extends Condition with HasParams { - override lazy val name: String = s"ParamIsTrue(${NamingUtils.getFriendlyName(param)})" - override val features: Set[Feature[_]] = Set.empty - override val optionalFeatures: Set[Feature[_]] = Set.empty - - private val UnsatisfiedResult = Unsatisfied(this) - private val SatisfiedResult = Satisfied(ParamWasTrue(param)) - - override val params: Set[Param[_]] = Set(param) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = - if (evaluationContext.params(param)) { - SatisfiedResult - } else { - UnsatisfiedResult - } - } - - case object Never extends Condition { - override lazy val name: String = s"""Never""" - override val features: Set[Feature[_]] = Set.empty - override val optionalFeatures: Set[Feature[_]] = Set.empty - private val UnsatisfiedResult = Unsatisfied(this) - - override def preFilter( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): PreFilterResult = { - NeedsFullEvaluation - } - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = - UnsatisfiedResult - } - - class BooleanCondition(value: Boolean) extends Condition { - override lazy val name: String = s"""${if (value) "True" else "False"}""" - override val features: Set[Feature[_]] = Set.empty - override val optionalFeatures: Set[Feature[_]] = Set.empty - private val UnsatisfiedResult = Unsatisfied(this) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = - value match { - case true => Result.SatisfiedResult - case false => UnsatisfiedResult - } - } - - case object True extends BooleanCondition(true) - case object False extends BooleanCondition(false) - - abstract class ContentTakendownInViewerCountry(takedownFeature: Feature[Seq[TakedownReason]]) - extends Condition { - override val features: Set[Feature[_]] = Set(takedownFeature) - override val optionalFeatures: Set[Feature[_]] = Set(RequestCountryCode) - - private val UnsatisfiedResult = Unsatisfied(this) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val requestCountryCode = featureMap.get(RequestCountryCode).asInstanceOf[Option[String]] - val takedownReasons = featureMap(takedownFeature).asInstanceOf[Seq[TakedownReason]] - if (TakedownReasonsUtil.isTakenDownIn(requestCountryCode, takedownReasons)) { - Result.SatisfiedResult - } else { - UnsatisfiedResult - } - } - } - - case object TweetTakendownInViewerCountry - extends ContentTakendownInViewerCountry(TweetTakedownReasons) - - case object AuthorTakendownInViewerCountry - extends ContentTakendownInViewerCountry(AuthorTakedownReasons) - - case object SuspendedAuthor extends BooleanFeatureCondition(AuthorIsSuspended) - - case object SuspendedViewer extends BooleanFeatureCondition(ViewerIsSuspended) - - case object DeactivatedViewer extends BooleanFeatureCondition(ViewerIsDeactivated) - - case object UnavailableAuthor extends BooleanFeatureCondition(AuthorIsUnavailable) - - case object IsVerifiedCrawlerViewer extends BooleanFeatureCondition(RequestIsVerifiedCrawler) - - case object LoggedOutViewer extends Condition { - override val features: Set[Feature[_]] = Set.empty - override val optionalFeatures: Set[Feature[_]] = Set(ViewerId) - - private val UnsatisfiedResult = Unsatisfied(this) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = - if (featureMap.contains(ViewerId)) UnsatisfiedResult else Result.SatisfiedResult - } - - case object IsSelfQuote extends Condition { - override val features: Set[Feature[_]] = Set(AuthorId, OuterAuthorId) - override val optionalFeatures: Set[Feature[_]] = Set.empty - - private val UnsatisfiedResult = Unsatisfied(this) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val authorIds = featureMap(AuthorId).asInstanceOf[Set[Long]] - val outerAuthorId = featureMap(OuterAuthorId).asInstanceOf[Long] - if (authorIds.contains(outerAuthorId)) { - Result.SatisfiedResult - } else { - UnsatisfiedResult - } - } - } - - case object ViewerIsAuthor extends Condition { - override val features: Set[Feature[_]] = Set(AuthorId) - override val optionalFeatures: Set[Feature[_]] = Set(ViewerId) - - private val UnsatisfiedResult = Unsatisfied(this) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = - if (featureMap.contains(ViewerId)) { - val authorIds = featureMap(AuthorId).asInstanceOf[Set[Long]] - val viewerId = featureMap(ViewerId).asInstanceOf[Long] - if (authorIds.contains(viewerId)) { - Result.SatisfiedResult - } else { - UnsatisfiedResult - } - } else { - UnsatisfiedResult - } - } - - case object NonAuthorViewer extends Condition { - override val features: Set[Feature[_]] = Set(AuthorId) - override val optionalFeatures: Set[Feature[_]] = Set(ViewerId) - - private val UnsatisfiedResult = Unsatisfied(this) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = - if (featureMap.contains(ViewerId)) { - val authorIds = featureMap(AuthorId).asInstanceOf[Set[Long]] - val viewerId = featureMap(ViewerId).asInstanceOf[Long] - if (authorIds.contains(viewerId)) { - UnsatisfiedResult - } else { - Result.SatisfiedResult - } - } else { - Result.SatisfiedResult - } - } - - case object ViewerFollowsAuthorOfFosnrViolatingTweet - extends BooleanFeatureCondition(ViewerFollowsAuthorOfViolatingTweet) - - case object ViewerDoesNotFollowAuthorOfFosnrViolatingTweet - extends BooleanFeatureCondition(ViewerDoesNotFollowAuthorOfViolatingTweet) - - case object ViewerDoesFollowAuthor extends BooleanFeatureCondition(ViewerFollowsAuthor) - - case object AuthorDoesFollowViewer extends BooleanFeatureCondition(AuthorFollowsViewer) - - case object AuthorBlocksViewer extends BooleanFeatureCondition(AuthorBlocksViewerFeature) - - case object ViewerBlocksAuthor extends BooleanFeatureCondition(ViewerBlocksAuthorFeature) - - case object ViewerIsUnmentioned extends BooleanFeatureCondition(NotificationIsOnUnmentionedViewer) - - case object AuthorBlocksOuterAuthor - extends BooleanFeatureCondition(AuthorBlocksOuterAuthorFeature) - - case object OuterAuthorFollowsAuthor - extends BooleanFeatureCondition(OuterAuthorFollowsAuthorFeature) - - case object OuterAuthorIsInnerAuthor - extends BooleanFeatureCondition(OuterAuthorIsInnerAuthorFeature) - - case object ViewerMutesAuthor extends BooleanFeatureCondition(ViewerMutesAuthorFeature) - - case object ViewerReportsAuthor extends BooleanFeatureCondition(ViewerReportsAuthorAsSpam) - case object ViewerReportsTweet extends BooleanFeatureCondition(ViewerReportedTweet) - - case object IsQuotedInnerTweet extends BooleanFeatureCondition(TweetIsInnerQuotedTweet) - - case object IsSourceTweet extends BooleanFeatureCondition(TweetIsSourceTweet) - - case object ViewerMutesRetweetsFromAuthor - extends BooleanFeatureCondition(ViewerMutesRetweetsFromAuthorFeature) - - case object ConversationRootAuthorDoesFollowViewer - extends BooleanFeatureCondition(ConversationRootAuthorFollowsViewer) - - case object ViewerDoesFollowConversationRootAuthor - extends BooleanFeatureCondition(ViewerFollowsConversationRootAuthor) - - case object TweetIsCommunityTweet extends BooleanFeatureCondition(TweetIsCommunityTweetFeature) - - case object NotificationIsOnCommunityTweet - extends BooleanFeatureCondition(NotificationIsOnCommunityTweetFeature) - - sealed trait CommunityTweetCommunityUnavailable extends Condition - - case object CommunityTweetCommunityNotFound - extends BooleanFeatureCondition(CommunityTweetCommunityNotFoundFeature) - with CommunityTweetCommunityUnavailable - - case object CommunityTweetCommunityDeleted - extends BooleanFeatureCondition(CommunityTweetCommunityDeletedFeature) - with CommunityTweetCommunityUnavailable - - case object CommunityTweetCommunitySuspended - extends BooleanFeatureCondition(CommunityTweetCommunitySuspendedFeature) - with CommunityTweetCommunityUnavailable - - case object CommunityTweetCommunityVisible - extends BooleanFeatureCondition(CommunityTweetCommunityVisibleFeature) - - case object ViewerIsInternalCommunitiesAdmin - extends BooleanFeatureCondition(ViewerIsInternalCommunitiesAdminFeature) - - case object ViewerIsCommunityAdmin extends BooleanFeatureCondition(ViewerIsCommunityAdminFeature) - - case object ViewerIsCommunityModerator - extends BooleanFeatureCondition(ViewerIsCommunityModeratorFeature) - - case object ViewerIsCommunityMember - extends BooleanFeatureCondition(ViewerIsCommunityMemberFeature) - - sealed trait CommunityTweetIsModerated extends Condition - - case object CommunityTweetIsHidden - extends BooleanFeatureCondition(CommunityTweetIsHiddenFeature) - with CommunityTweetIsModerated - - case object CommunityTweetAuthorIsRemoved - extends BooleanFeatureCondition(CommunityTweetAuthorIsRemovedFeature) - with CommunityTweetIsModerated - - case object DoesHaveInnerCircleOfFriendsRelationship - extends BooleanFeatureCondition(HasInnerCircleOfFriendsRelationship) - - case object TweetIsCommunityConversation - extends BooleanFeatureCondition(TweetHasCommunityConversationControl) - - case object TweetIsByInvitationConversation - extends BooleanFeatureCondition(TweetHasByInvitationConversationControl) - - case object TweetIsFollowersConversation - extends BooleanFeatureCondition(TweetHasFollowersConversationControl) - - case object ViewerIsTweetConversationRootAuthor - extends BooleanFeatureCondition(TweetConversationViewerIsRootAuthor) - - private case object ViewerIsInvitedToTweetConversationByMention - extends BooleanFeatureCondition(TweetConversationViewerIsInvited) - - private case object ViewerIsInvitedToTweetConversationByReplyMention - extends BooleanFeatureCondition(TweetConversationViewerIsInvitedViaReplyMention) - - object ViewerIsInvitedToTweetConversation - extends Or( - ViewerIsInvitedToTweetConversationByMention, - ViewerIsInvitedToTweetConversationByReplyMention) - - object TweetIsExclusiveContent extends BooleanFeatureCondition(TweetIsExclusiveTweet) - object ViewerIsExclusiveTweetAuthor - extends BooleanFeatureCondition(ViewerIsExclusiveTweetRootAuthor) - object ViewerSuperFollowsExclusiveTweetAuthor - extends BooleanFeatureCondition(ViewerSuperFollowsExclusiveTweetRootAuthor) - - object TweetIsTrustedFriendsContent extends BooleanFeatureCondition(TweetIsTrustedFriendTweet) - object ViewerIsTrustedFriendsTweetAuthor - extends BooleanFeatureCondition(ViewerIsTrustedFriendTweetAuthor) - object ViewerIsTrustedFriend extends BooleanFeatureCondition(ViewerIsTrustedFriendOfTweetAuthor) - - object TweetIsCollabInvitationContent - extends BooleanFeatureCondition(TweetIsCollabInvitationTweet) - - case class TweetHasLabelForPerspectivalUser(safetyLabel: TweetSafetyLabelType) - extends Condition - with HasSafetyLabelType { - override lazy val name: String = s"TweetHasLabelForPerspectivalUser(${safetyLabel.name})" - override val features: Set[Feature[_]] = Set(TweetSafetyLabels) - override val optionalFeatures: Set[Feature[_]] = Set(ViewerId) - override val labelTypes: Set[SafetyLabelType] = Set(safetyLabel) - - private val UnsatisfiedResult: Unsatisfied = Unsatisfied(this) - private val SatisfiedResult: Satisfied = Satisfied( - FoundTweetLabelForPerspectivalUser(safetyLabel) - ) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - if (!featureMap.contains(ViewerId)) { - UnsatisfiedResult - } else { - val viewerId = featureMap(ViewerId).asInstanceOf[Long] - val labels = featureMap(TweetSafetyLabels).asInstanceOf[Seq[TweetSafetyLabel]] - labels - .collectFirst { - case label - if label.labelType == safetyLabel && label.applicableUsers.contains(viewerId) - && ExperimentBase.shouldFilterForSource(evaluationContext.params, label.source) => - SatisfiedResult - }.getOrElse(UnsatisfiedResult) - } - } - } - - case class TweetHasLabel( - safetyLabel: TweetSafetyLabelType, - labelSourceExperimentPredicate: Option[(Params, Option[LabelSource]) => Boolean] = None) - extends Condition - with HasSafetyLabelType { - override lazy val name: String = s"TweetHasLabel(${safetyLabel.name})" - override val features: Set[Feature[_]] = Set(TweetSafetyLabels) - override val optionalFeatures: Set[Feature[_]] = Set.empty - override val labelTypes: Set[SafetyLabelType] = Set(safetyLabel) - - private val UnsatisfiedResult: Unsatisfied = Unsatisfied(this) - private val SatisfiedResult: Satisfied = Satisfied(FoundTweetLabel(safetyLabel)) - - private val labelSourcePredicate: (Params, Option[LabelSource]) => Boolean = - labelSourceExperimentPredicate match { - case Some(predicate) => predicate - case _ => ExperimentBase.shouldFilterForSource - } - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val labels = featureMap(TweetSafetyLabels).asInstanceOf[Seq[TweetSafetyLabel]] - labels - .collectFirst { - case label - if label.labelType == safetyLabel - && labelSourcePredicate(evaluationContext.params, label.source) => - SatisfiedResult - }.getOrElse(UnsatisfiedResult) - } - } - - case class SpaceHasLabel( - safetyLabelType: SpaceSafetyLabelType) - extends Condition - with HasSafetyLabelType { - override lazy val name: String = s"SpaceHasLabel(${safetyLabelType.name})" - override val features: Set[Feature[_]] = Set(SpaceSafetyLabels) - override val optionalFeatures: Set[Feature[_]] = Set.empty - override val labelTypes: Set[SafetyLabelType] = Set(safetyLabelType) - - private val UnsatisfiedResult: Unsatisfied = Unsatisfied(this) - private val SatisfiedResult: Satisfied = Satisfied(FoundSpaceLabel(safetyLabelType)) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val labels = featureMap(SpaceSafetyLabels).asInstanceOf[Seq[SpaceSafetyLabel]] - labels - .collectFirst { - case label if label.safetyLabelType == safetyLabelType => - SatisfiedResult - }.getOrElse(UnsatisfiedResult) - } - } - - case class MediaHasLabel( - safetyLabelType: MediaSafetyLabelType) - extends Condition - with HasSafetyLabelType { - override lazy val name: String = s"MediaHasLabel(${safetyLabelType.name})" - override val features: Set[Feature[_]] = Set(MediaSafetyLabels) - override val optionalFeatures: Set[Feature[_]] = Set.empty - override val labelTypes: Set[SafetyLabelType] = Set(safetyLabelType) - - private val UnsatisfiedResult: Unsatisfied = Unsatisfied(this) - private val SatisfiedResult: Satisfied = Satisfied(FoundMediaLabel(safetyLabelType)) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val labels = featureMap(MediaSafetyLabels).asInstanceOf[Seq[MediaSafetyLabel]] - labels - .collectFirst { - case label if label.safetyLabelType == safetyLabelType => - SatisfiedResult - }.getOrElse(UnsatisfiedResult) - } - } - - case class TweetHasLabelWithLanguageScoreAboveThreshold( - safetyLabel: TweetSafetyLabelType, - languagesToScoreThresholds: Map[String, Double]) - extends Condition - with HasSafetyLabelType { - - override lazy val name: String = - s"TweetHasLabelWithLanguageScoreAboveThreshold(${safetyLabel.name}, ${languagesToScoreThresholds.toString})" - override val features: Set[Feature[_]] = Set(TweetSafetyLabels) - override val optionalFeatures: Set[Feature[_]] = Set.empty - override val labelTypes: Set[SafetyLabelType] = Set(safetyLabel) - - private val UnsatisfiedResult: Unsatisfied = Unsatisfied(this) - private val SatisfiedResult: Satisfied = - Satisfied( - FoundTweetLabelWithLanguageScoreAboveThreshold(safetyLabel, languagesToScoreThresholds)) - - private[this] def isAboveThreshold(label: TweetSafetyLabel) = { - val isAboveThresholdOpt = for { - modelMetadata <- label.modelMetadata - calibratedLanguage <- modelMetadata.calibratedLanguage - threshold <- languagesToScoreThresholds.get(calibratedLanguage) - score <- label.score - } yield score >= threshold - - isAboveThresholdOpt.getOrElse(false) - } - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val labels = featureMap(TweetSafetyLabels).asInstanceOf[Seq[TweetSafetyLabel]] - labels - .collectFirst { - case label - if label.labelType == safetyLabel - && isAboveThreshold(label) => - SatisfiedResult - }.getOrElse(UnsatisfiedResult) - } - } - - case class TweetHasLabelWithScoreAboveThreshold( - safetyLabel: TweetSafetyLabelType, - threshold: Double) - extends Condition - with HasSafetyLabelType { - - override lazy val name: String = - s"TweetHasLabelWithScoreAboveThreshold(${safetyLabel.name}, $threshold)" - override val features: Set[Feature[_]] = Set(TweetSafetyLabels) - override val optionalFeatures: Set[Feature[_]] = Set.empty - override val labelTypes: Set[SafetyLabelType] = Set(safetyLabel) - - private val UnsatisfiedResult = Unsatisfied(this) - private val SatisfiedResult = - Satisfied(FoundTweetLabelWithScoreAboveThreshold(safetyLabel, threshold)) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val labels = featureMap(TweetSafetyLabels).asInstanceOf[Seq[TweetSafetyLabel]] - labels - .collectFirst { - case label - if label.labelType == safetyLabel - && label.score.exists(_ >= threshold) => - SatisfiedResult - }.getOrElse(UnsatisfiedResult) - } - } - - case class TweetHasLabelWithScoreAboveThresholdWithParam( - safetyLabel: TweetSafetyLabelType, - thresholdParam: Param[Double]) - extends Condition - with HasSafetyLabelType - with HasParams { - override lazy val name: String = - s"TweetHasLabelWithScoreAboveThreshold(${safetyLabel.name}, ${NamingUtils.getFriendlyName(thresholdParam)})" - override val features: Set[Feature[_]] = Set(TweetSafetyLabels) - override val optionalFeatures: Set[Feature[_]] = Set.empty - override val labelTypes: Set[SafetyLabelType] = Set(safetyLabel) - private val UnsatisfiedResult = Unsatisfied(this) - override val params: Set[Param[_]] = Set(thresholdParam) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val labels = featureMap(TweetSafetyLabels).asInstanceOf[Seq[TweetSafetyLabel]] - val threshold = evaluationContext.params(thresholdParam) - val SatisfiedResult = - Satisfied(FoundTweetLabelWithScoreAboveThreshold(safetyLabel, threshold)) - labels - .collectFirst { - case label - if label.labelType == safetyLabel - && label.score.exists(_ >= threshold) => - SatisfiedResult - }.getOrElse(UnsatisfiedResult) - } - } - - case class TweetHasLabelWithLanguageIn( - safetyLabelType: TweetSafetyLabelType, - languages: Set[String]) - extends Condition - with HasSafetyLabelType { - - override lazy val name: String = - s"TweetHasLabelWithLanguageIn($safetyLabelType, $languages)" - override val features: Set[Feature[_]] = Set(TweetSafetyLabels) - override val optionalFeatures: Set[Feature[_]] = Set.empty - override val labelTypes: Set[SafetyLabelType] = Set(safetyLabelType) - - private val UnsatisfiedResult: Unsatisfied = Unsatisfied(this) - private val SatisfiedResult: Satisfied = - Satisfied(FoundTweetLabelWithLanguageIn(safetyLabelType, languages)) - - private[this] def hasLanguageMatch(label: TweetSafetyLabel): Boolean = { - val isMatchingLanguageOpt = for { - metadata <- label.modelMetadata - language <- metadata.calibratedLanguage - } yield languages.contains(language) - isMatchingLanguageOpt.getOrElse(false) - } - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - featureMap(TweetSafetyLabels) - .asInstanceOf[Seq[TweetSafetyLabel]] - .collectFirst { - case label if label.labelType == safetyLabelType && hasLanguageMatch(label) => - SatisfiedResult - }.getOrElse(UnsatisfiedResult) - } - } - - case class TweetHasLabelWithLanguagesWithParam( - safetyLabelType: TweetSafetyLabelType, - languageParam: Param[Seq[String]]) - extends Condition - with HasSafetyLabelType - with HasParams { - override lazy val name: String = - s"TweetHasLabelWithLanguageIn($safetyLabelType, ${NamingUtils.getFriendlyName(languageParam)})" - override val features: Set[Feature[_]] = Set(TweetSafetyLabels) - override val optionalFeatures: Set[Feature[_]] = Set.empty - override val labelTypes: Set[SafetyLabelType] = Set(safetyLabelType) - override val params: Set[Param[_]] = Set(languageParam) - - private val UnsatisfiedResult: Unsatisfied = Unsatisfied(this) - - private[this] def hasLanguageMatch(label: TweetSafetyLabel, languages: Set[String]): Boolean = { - val isMatchingLanguageOpt = for { - metadata <- label.modelMetadata - language <- metadata.calibratedLanguage - } yield languages.contains(language) - isMatchingLanguageOpt.getOrElse(false) - } - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val languages = evaluationContext.params(languageParam).toSet - val SatisfiedResult: Satisfied = - Satisfied(FoundTweetLabelWithLanguageIn(safetyLabelType, languages)) - featureMap(TweetSafetyLabels) - .asInstanceOf[Seq[TweetSafetyLabel]] - .collectFirst { - case label if label.labelType == safetyLabelType && hasLanguageMatch(label, languages) => - SatisfiedResult - }.getOrElse(UnsatisfiedResult) - } - } - - type TweetSafetyLabelPredicateFn = (TweetSafetyLabel) => Boolean - abstract class NamedTweetSafetyLabelPredicate( - private[rules] val fn: TweetSafetyLabelPredicateFn, - private[rules] val name: String) - - abstract class TweetHasSafetyLabelWithPredicate( - private[rules] val safetyLabelType: TweetSafetyLabelType, - private[rules] val predicate: NamedTweetSafetyLabelPredicate) - extends Condition - with HasSafetyLabelType { - - override lazy val name: String = - s"TweetHasSafetyLabelWithPredicate(${predicate.name}($safetyLabelType))" - override val features: Set[Feature[_]] = Set(TweetSafetyLabels) - override val optionalFeatures: Set[Feature[_]] = Set.empty - override val labelTypes: Set[SafetyLabelType] = Set(safetyLabelType) - - private val UnsatisfiedResult: Unsatisfied = Unsatisfied(this) - private val SatisfiedResult: Satisfied = - Satisfied(Result.FoundTweetSafetyLabelWithPredicate(safetyLabelType, predicate.name)) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - featureMap(TweetSafetyLabels) - .asInstanceOf[Seq[TweetSafetyLabel]] - .collectFirst { - case label if label.labelType == safetyLabelType && predicate.fn(label) => - SatisfiedResult - }.getOrElse(UnsatisfiedResult) - } - } - - object TweetHasSafetyLabelWithPredicate { - def unapply( - condition: TweetHasSafetyLabelWithPredicate - ): Option[(TweetSafetyLabelType, NamedTweetSafetyLabelPredicate)] = - Some((condition.safetyLabelType, condition.predicate)) - } - - case class WithScoreEqInt(score: Int) - extends NamedTweetSafetyLabelPredicate( - fn = tweetSafetyLabel => tweetSafetyLabel.score.exists(s => s.intValue() == score), - name = "WithScoreEqInt" - ) - case class TweetHasSafetyLabelWithScoreEqInt( - override val safetyLabelType: TweetSafetyLabelType, - score: Int) - extends TweetHasSafetyLabelWithPredicate( - safetyLabelType, - predicate = WithScoreEqInt(score) - ) - - case class TweetReplyToParentTweetBeforeDuration(duration: Duration) extends Condition { - override val features: Set[Feature[_]] = Set(TweetParentId, TweetTimestamp) - override val optionalFeatures: Set[Feature[_]] = Set.empty - - private val UnsatisfiedResult: Unsatisfied = Unsatisfied(this) - private val SatisfiedResult: Satisfied = Satisfied( - Result.IsTweetReplyToParentTweetBeforeDuration(duration)) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - featureMap - .get(TweetParentId).collect { - case tweetParentId: Long => - featureMap - .get(TweetTimestamp).collect { - case tweetTimestamp: Time - if tweetTimestamp.diff(SnowflakeId.timeFromId(tweetParentId)) < duration => - SatisfiedResult - }.getOrElse(UnsatisfiedResult) - }.getOrElse(UnsatisfiedResult) - } - } - - case class TweetReplyToRootTweetBeforeDuration(duration: Duration) extends Condition { - override val features: Set[Feature[_]] = Set(TweetConversationId, TweetTimestamp) - override val optionalFeatures: Set[Feature[_]] = Set.empty - - private val UnsatisfiedResult: Unsatisfied = Unsatisfied(this) - private val SatisfiedResult: Satisfied = Satisfied( - Result.IsTweetReplyToRootTweetBeforeDuration(duration)) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - featureMap - .get(TweetConversationId).collect { - case tweetConversationId: Long => - featureMap - .get(TweetTimestamp).collect { - case tweetTimestamp: Time - if tweetTimestamp.diff( - SnowflakeId.timeFromId(tweetConversationId)) < duration => - SatisfiedResult - }.getOrElse(UnsatisfiedResult) - }.getOrElse(UnsatisfiedResult) - } - } - - case class TweetComposedBefore(cutoffTimestamp: Time) extends Condition { - assert(cutoffTimestamp.inMilliseconds > SnowflakeId.FirstSnowflakeIdUnixTime) - - override val features: Set[Feature[_]] = Set(TweetTimestamp) - override val optionalFeatures: Set[Feature[_]] = Set.empty - - private val UnsatisfiedResult: Unsatisfied = Unsatisfied(this) - private val SatisfiedResult: Satisfied = Satisfied(HasTweetTimestampBeforeCutoff) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - featureMap(TweetTimestamp) match { - case timestamp: Time if timestamp > cutoffTimestamp => UnsatisfiedResult - case _ => SatisfiedResult - } - } - } - - case class TweetComposedAfter(cutoffTimestamp: Time) extends Condition { - assert(cutoffTimestamp.inMilliseconds > SnowflakeId.FirstSnowflakeIdUnixTime) - - override val features: Set[Feature[_]] = Set(TweetTimestamp) - override val optionalFeatures: Set[Feature[_]] = Set.empty - - private val UnsatisfiedResult: Unsatisfied = Unsatisfied(this) - private val SatisfiedResult: Satisfied = Satisfied(HasTweetTimestampAfterCutoff) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - featureMap(TweetTimestamp) match { - case timestamp: Time if timestamp > cutoffTimestamp => SatisfiedResult - case _ => UnsatisfiedResult - } - } - } - - case class TweetComposedAfterOffset(offset: Duration) extends Condition { - override val features: Set[Feature[_]] = Set(TweetTimestamp) - override val optionalFeatures: Set[Feature[_]] = Set.empty - - private val UnsatisfiedResult: Unsatisfied = Unsatisfied(this) - private val SatisfiedResult: Satisfied = Satisfied(HasTweetTimestampAfterOffset) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - featureMap(TweetTimestamp) match { - case timestamp: Time if timestamp > Time.now.minus(offset) => SatisfiedResult - case _ => UnsatisfiedResult - } - } - } - - case class TweetComposedAfterWithParam(cutoffTimeParam: Param[Time]) - extends Condition - with HasParams { - override val features: Set[Feature[_]] = Set(TweetTimestamp) - override val optionalFeatures: Set[Feature[_]] = Set.empty - override val params: Set[Param[_]] = Set(cutoffTimeParam) - private val UnsatisfiedResult: Unsatisfied = Unsatisfied(this) - private val SatisfiedResult: Satisfied = Satisfied(HasTweetTimestampAfterCutoff) - - override def preFilter( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): PreFilterResult = { - val cutoffTimestamp = evaluationContext.params(cutoffTimeParam) - if (cutoffTimestamp.inMilliseconds < SnowflakeId.FirstSnowflakeIdUnixTime) { - Filtered - } else { - super.preFilter(evaluationContext, featureMap) - } - } - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val cutoffTimestamp = evaluationContext.params(cutoffTimeParam) - featureMap(TweetTimestamp) match { - case _: Time if cutoffTimestamp.inMilliseconds < SnowflakeId.FirstSnowflakeIdUnixTime => - UnsatisfiedResult - case timestamp: Time if timestamp > cutoffTimestamp => SatisfiedResult - case _ => UnsatisfiedResult - } - } - } - - case class AuthorHasLabel(labelValue: UserLabelValue, shortCircuitable: Boolean = true) - extends Condition - with HasSafetyLabelType { - override lazy val name: String = s"AuthorHasLabel(${labelValue.name})" - override val features: Set[Feature[_]] = Set(AuthorUserLabels) - override val optionalFeatures: Set[Feature[_]] = Set.empty - override val labelTypes: Set[SafetyLabelType] = Set(labelValue) - - private val UnsatisfiedResult: Unsatisfied = Unsatisfied(this) - private val SatisfiedResult: Satisfied = Satisfied(FoundUserLabel(labelValue)) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val labels = featureMap(AuthorUserLabels).asInstanceOf[Seq[Label]].map(UserLabel.fromThrift) - labels - .collectFirst { - case label - if label.labelValue == labelValue - && ExperimentBase.shouldFilterForSource(evaluationContext.params, label.source) => - SatisfiedResult - }.getOrElse(UnsatisfiedResult) - } - } - - abstract class ViewerHasRole(role: String) extends Condition { - override lazy val name: String = s"ViewerHasRole(${role})" - override val features: Set[Feature[_]] = Set(ViewerRoles) - override val optionalFeatures: Set[Feature[_]] = Set.empty - - private val UnsatisfiedResult: Unsatisfied = Unsatisfied(this) - private val SatisfiedResult: Satisfied = Satisfied(FoundUserRole(role)) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val roles = featureMap(ViewerRoles).asInstanceOf[Seq[String]] - if (roles.contains(role)) { - SatisfiedResult - } else { - UnsatisfiedResult - } - } - } - - case object ViewerIsEmployee extends ViewerHasRole(ViewerRoles.EmployeeRole) - - case class ViewerHasLabel(labelValue: UserLabelValue) extends Condition with HasSafetyLabelType { - override lazy val name: String = s"ViewerHasLabel(${labelValue.name})" - override val features: Set[Feature[_]] = Set(ViewerUserLabels) - override val optionalFeatures: Set[Feature[_]] = Set.empty - override val labelTypes: Set[SafetyLabelType] = Set(labelValue) - - private val UnsatisfiedResult: Unsatisfied = Unsatisfied(this) - private val SatisfiedResult: Satisfied = Satisfied(FoundUserLabel(labelValue)) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val labels = featureMap(ViewerUserLabels).asInstanceOf[Seq[Label]].map(UserLabel.fromThrift) - labels - .collectFirst { - case label - if label.labelValue == labelValue - && ExperimentBase.shouldFilterForSource(evaluationContext.params, label.source) => - SatisfiedResult - }.getOrElse(UnsatisfiedResult) - } - } - - case object DeactivatedAuthor extends BooleanFeatureCondition(AuthorIsDeactivated) - case object ErasedAuthor extends BooleanFeatureCondition(AuthorIsErased) - case object OffboardedAuthor extends BooleanFeatureCondition(AuthorIsOffboarded) - case object ProtectedAuthor extends BooleanFeatureCondition(AuthorIsProtected) - case object VerifiedAuthor extends BooleanFeatureCondition(AuthorIsVerified) - case object NsfwUserAuthor extends BooleanFeatureCondition(AuthorIsNsfwUser) - case object NsfwAdminAuthor extends BooleanFeatureCondition(AuthorIsNsfwAdmin) - case object TweetHasNsfwUserAuthor extends BooleanFeatureCondition(TweetHasNsfwUser) - case object TweetHasNsfwAdminAuthor extends BooleanFeatureCondition(TweetHasNsfwAdmin) - case object TweetHasMedia extends BooleanFeatureCondition(TweetHasMediaFeature) - case object TweetHasDmcaMedia extends BooleanFeatureCondition(HasDmcaMediaFeature) - case object TweetHasCard extends BooleanFeatureCondition(TweetHasCardFeature) - case object IsPollCard extends BooleanFeatureCondition(CardIsPoll) - - case object ProtectedViewer extends BooleanFeatureCondition(ViewerIsProtected) - case object SoftViewer extends BooleanFeatureCondition(ViewerIsSoftUser) - - case object ViewerHasUqfEnabled - extends BooleanFeatureCondition(ViewerHasUniversalQualityFilterEnabled) - - abstract class ViewerHasMatchingKeywordFor(muteSurface: MuteSurface) extends Condition { - override def features: Set[Feature[_]] = Set(feature) - override val optionalFeatures: Set[Feature[_]] = Set.empty - - private val UnsatisfiedResult = Unsatisfied(this) - - private val feature: Feature[MutedKeyword] = muteSurface match { - case MuteSurface.HomeTimeline => ViewerMutesKeywordInTweetForHomeTimeline - case MuteSurface.Notifications => ViewerMutesKeywordInTweetForNotifications - case MuteSurface.TweetReplies => ViewerMutesKeywordInTweetForTweetReplies - - case _ => throw new NoSuchElementException(muteSurface.toString) - } - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val mutedKeyword = featureMap(feature) - .asInstanceOf[MutedKeyword] - Result.fromMutedKeyword(mutedKeyword, UnsatisfiedResult) - } - } - - case object ViewerHasMatchingKeywordForHomeTimeline - extends ViewerHasMatchingKeywordFor(MuteSurface.HomeTimeline) - - case object ViewerHasMatchingKeywordForNotifications - extends ViewerHasMatchingKeywordFor(MuteSurface.Notifications) - - case object ViewerHasMatchingKeywordForTweetReplies - extends ViewerHasMatchingKeywordFor(MuteSurface.TweetReplies) - - case object ViewerHasMatchingKeywordForAllSurfaces extends Condition { - override def features: Set[Feature[_]] = Set(ViewerMutesKeywordInTweetForAllSurfaces) - override val optionalFeatures: Set[Feature[_]] = Set.empty - private val UnsatisfiedResult = Unsatisfied(this) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val mutedKeyword = featureMap(ViewerMutesKeywordInTweetForAllSurfaces) - .asInstanceOf[MutedKeyword] - Result.fromMutedKeyword(mutedKeyword, UnsatisfiedResult) - } - } - - abstract class ViewerHasMatchingKeywordInSpaceTitleFor(muteSurface: MuteSurface) - extends Condition { - override def features: Set[Feature[_]] = Set(feature) - override val optionalFeatures: Set[Feature[_]] = Set.empty - - private val UnsatisfiedResult = Unsatisfied(this) - - private val feature: Feature[MutedKeyword] = muteSurface match { - case MuteSurface.Notifications => ViewerMutesKeywordInSpaceTitleForNotifications - case _ => throw new NoSuchElementException(muteSurface.toString) - } - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val mutedKeyword = featureMap(feature) - .asInstanceOf[MutedKeyword] - Result.fromMutedKeyword(mutedKeyword, UnsatisfiedResult) - } - } - - case object ViewerHasMatchingKeywordInSpaceTitleForNotifications - extends ViewerHasMatchingKeywordInSpaceTitleFor(MuteSurface.Notifications) - - case object ViewerFiltersNoConfirmedEmail - extends BooleanFeatureCondition( - com.twitter.visibility.features.ViewerFiltersNoConfirmedEmail - ) - - case object ViewerFiltersNoConfirmedPhone - extends BooleanFeatureCondition( - com.twitter.visibility.features.ViewerFiltersNoConfirmedPhone - ) - - case object ViewerFiltersDefaultProfileImage - extends BooleanFeatureCondition( - com.twitter.visibility.features.ViewerFiltersDefaultProfileImage - ) - - case object ViewerFiltersNewUsers - extends BooleanFeatureCondition( - com.twitter.visibility.features.ViewerFiltersNewUsers - ) - - case object ViewerFiltersNotFollowedBy - extends BooleanFeatureCondition( - com.twitter.visibility.features.ViewerFiltersNotFollowedBy - ) - - case object AuthorHasConfirmedEmail - extends BooleanFeatureCondition( - com.twitter.visibility.features.AuthorHasConfirmedEmail - ) - - case object AuthorHasVerifiedPhone - extends BooleanFeatureCondition( - com.twitter.visibility.features.AuthorHasVerifiedPhone - ) - - case object AuthorHasDefaultProfileImage - extends BooleanFeatureCondition( - com.twitter.visibility.features.AuthorHasDefaultProfileImage - ) - - case object AuthorIsNewAccount extends Condition { - override val features: Set[Feature[_]] = Set(AuthorAccountAge) - override val optionalFeatures: Set[Feature[_]] = Set.empty - - private val UnsatisfiedResult = Unsatisfied(this) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val age = featureMap(AuthorAccountAge).asInstanceOf[Duration] - - if (age < 72.hours) { - Result.SatisfiedResult - } else { - UnsatisfiedResult - } - } - } - - abstract class ViewerInJurisdiction extends Condition { - override def features: Set[Feature[_]] = Set.empty - override val optionalFeatures: Set[Feature[_]] = Set(RequestCountryCode, ViewerCountryCode) - - protected val unsatisfiedResult = Unsatisfied(this) - - protected case class CountryFeatures( - requestCountryCode: Option[String], - viewerCountryCode: Option[String]) - - def getCountryFeatures(featureMap: Map[Feature[_], _]): CountryFeatures = { - val requestCountryCodeOpt = featureMap - .get(RequestCountryCode) - .map(_.asInstanceOf[String]) - val viewerCountryCodeOpt = featureMap - .get(ViewerCountryCode) - .map(_.asInstanceOf[String]) - - CountryFeatures(requestCountryCodeOpt, viewerCountryCodeOpt) - } - } - - case class ViewerInHrcj(jurisdictions: Set[String]) extends ViewerInJurisdiction { - - override def preFilter( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): PreFilterResult = - featureMap - .get(RequestCountryCode) - .map(_.asInstanceOf[String]) - .collectFirst { - case rcc if jurisdictions.contains(rcc) => NeedsFullEvaluation - } - .getOrElse(Filtered) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val countryFeatures = getCountryFeatures(featureMap) - - countryFeatures match { - case CountryFeatures(Some(rcc), Some(vcc)) - if jurisdictions.contains(rcc) && vcc.equals(rcc) => - Satisfied(Result.ViewerInHrcj(rcc)) - case _ => unsatisfiedResult - } - } - } - - case class ViewerOrRequestInJurisdiction(enabledCountriesParam: Param[Seq[String]]) - extends ViewerInJurisdiction - with HasParams - with PreFilterOnOptionalFeatures { - - override val params: Set[Param[_]] = Set(enabledCountriesParam) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val countries: Seq[String] = - evaluationContext.params(enabledCountriesParam).map(c => c.toLowerCase) - val countryFeatures = getCountryFeatures(featureMap) - - val countryCodeOpt = - countryFeatures.viewerCountryCode.orElse(countryFeatures.requestCountryCode) - - countryCodeOpt match { - case Some(countryCode) if countries.contains(countryCode) => - Satisfied(Result.ViewerOrRequestInCountry(countryCode)) - case _ => unsatisfiedResult - } - } - } - - case class ViewerAgeInYearsGte(ageToCompare: Int, ignoreEmptyAge: Boolean = false) - extends Condition - with PreFilterOnOptionalFeatures { - override def features: Set[Feature[_]] = Set.empty - override def optionalFeatures: Set[Feature[_]] = Set(ViewerAge) - - private val unsatisfiedResult = Unsatisfied(this) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = - featureMap - .get(ViewerAge) - .map(_.asInstanceOf[UserAge]) - .collectFirst { - case UserAge(Some(age)) if age >= ageToCompare => - Satisfied(Result.ViewerAgeInYears(age)) - case UserAge(None) if ignoreEmptyAge => - Satisfied(Result.NoViewerAge) - } - .getOrElse(unsatisfiedResult) - } - - case class UnderageViewer(ageToCompare: Int) extends Condition with PreFilterOnOptionalFeatures { - override def features: Set[Feature[_]] = Set.empty - override def optionalFeatures: Set[Feature[_]] = Set(ViewerAge) - - private val unsatisfiedResult = Unsatisfied(this) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = - featureMap - .get(ViewerAge) - .map(_.asInstanceOf[UserAge]) - .collectFirst { - case UserAge(Some(age)) if age < ageToCompare => Satisfied(Result.ViewerAgeInYears(age)) - } - .getOrElse(unsatisfiedResult) - } - - case object ViewerMissingAge extends Condition with PreFilterOnOptionalFeatures { - override def features: Set[Feature[_]] = Set.empty - override def optionalFeatures: Set[Feature[_]] = Set(ViewerAge) - - private val unsatisfiedResult = Unsatisfied(this) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = - featureMap - .get(ViewerAge) - .map(_.asInstanceOf[UserAge]) - .collectFirst { - case UserAge(None) => Satisfied(Result.NoViewerAge) - } - .getOrElse(unsatisfiedResult) - } - - case object ViewerOptInBlockingOnSearch extends BooleanFeatureCondition(ViewerOptInBlocking) - case object ViewerOptInFilteringOnSearch extends BooleanFeatureCondition(ViewerOptInFiltering) - case object SelfReply extends BooleanFeatureCondition(TweetIsSelfReply) - case object Nullcast extends BooleanFeatureCondition(TweetIsNullcast) - case object Moderated extends BooleanFeatureCondition(TweetIsModerated) - case object Retweet extends BooleanFeatureCondition(TweetIsRetweet) - - case object IsFirstPageSearchResult extends Condition { - override val features: Set[Feature[_]] = Set(SearchResultsPageNumber) - override val optionalFeatures: Set[Feature[_]] = Set.empty - private val UnsatisfiedResult = Unsatisfied(this) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val searchResultsPageNumber = featureMap(SearchResultsPageNumber).asInstanceOf[Int] - if (searchResultsPageNumber == 1) { - Result.SatisfiedResult - } else { - UnsatisfiedResult - } - } - } - - case object HasSearchCandidateCountGreaterThan45 extends Condition { - override val features: Set[Feature[_]] = Set(SearchCandidateCount) - override val optionalFeatures: Set[Feature[_]] = Set.empty - private val UnsatisfiedResult = Unsatisfied(this) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val searchCandidateCount = featureMap(SearchCandidateCount).asInstanceOf[Int] - if (searchCandidateCount > 45) { - Result.SatisfiedResult - } else { - UnsatisfiedResult - } - } - } - - abstract class HasSearchQuerySource(querySourceToMatch: ThriftQuerySource) extends Condition { - override lazy val name: String = s"HasSearchQuerySource(${querySourceToMatch})" - override val features: Set[Feature[_]] = Set(SearchQuerySource) - override val optionalFeatures: Set[Feature[_]] = Set.empty - private val UnsatisfiedResult = Unsatisfied(this) - private val SatisfiedResult: Satisfied = Satisfied(HasQuerySource(querySourceToMatch)) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val querySource = featureMap(SearchQuerySource).asInstanceOf[ThriftQuerySource] - if (querySourceToMatch.equals(querySource)) { - SatisfiedResult - } else { - UnsatisfiedResult - } - } - } - - case object IsTrendClickSourceSearchResult extends Condition { - override val features: Set[Feature[_]] = Set(SearchQuerySource) - override val optionalFeatures: Set[Feature[_]] = Set.empty - private val UnsatisfiedResult = Unsatisfied(this) - - private def checkQuerySource[T]( - featureMap: Map[Feature[_], _], - nonTrendSourceResult: T, - trendSourceResult: T - ): T = { - val searchResultsPageNumber = featureMap(SearchQuerySource).asInstanceOf[ThriftQuerySource] - if (searchResultsPageNumber == ThriftQuerySource.TrendClick) { - trendSourceResult - } else { - nonTrendSourceResult - } - } - - override def preFilter( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): PreFilterResult = - checkQuerySource(featureMap, Filtered, NotFiltered) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = - checkQuerySource(featureMap, UnsatisfiedResult, Result.SatisfiedResult) - } - case object IsSearchHashtagClick extends HasSearchQuerySource(ThriftQuerySource.HashtagClick) - case object IsSearchTrendClick extends HasSearchQuerySource(ThriftQuerySource.TrendClick) - - case object SearchQueryHasUser - extends BooleanFeatureCondition(com.twitter.visibility.features.SearchQueryHasUser) - - case class Equals[T](feature: Feature[T], value: T) extends Condition { - - override def features: Set[Feature[_]] = Set(feature) - override val optionalFeatures: Set[Feature[_]] = Set.empty - - private val SatisfiedResult: Result = Satisfied() - private val UnsatisfiedResult: Result = Unsatisfied(this) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val featureValue = featureMap(feature).asInstanceOf[T] - if (featureValue.equals(value)) SatisfiedResult else UnsatisfiedResult - } - } - - case class FeatureEquals[T](left: Feature[T], right: Feature[T]) extends Condition { - - override def features: Set[Feature[_]] = Set.empty - override val optionalFeatures: Set[Feature[_]] = Set(left, right) - - private val SatisfiedResult: Result = Satisfied() - private val UnsatisfiedResult: Result = Unsatisfied(this) - - override def preFilter( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): PreFilterResult = { - if (featureMap.contains(left) && featureMap.contains(right)) { - if (apply(evaluationContext, featureMap).asBoolean) { - NotFiltered - } else { - Filtered - } - } else { - NeedsFullEvaluation - } - } - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - if (featureMap.contains(left) && featureMap.contains(right)) { - val leftValue = featureMap(left).asInstanceOf[T] - val rightValue = featureMap(right).asInstanceOf[T] - if (leftValue.equals(rightValue)) SatisfiedResult else UnsatisfiedResult - } else { - UnsatisfiedResult - } - } - } - - case class And(override val conditions: Condition*) - extends Condition - with HasNestedConditions - with HasParams { - override lazy val name: String = s"(${conditions.map(_.name).mkString(" And ")})" - override val features: Set[Feature[_]] = conditions.flatMap(_.features).toSet - override val optionalFeatures: Set[Feature[_]] = conditions.flatMap(_.optionalFeatures).toSet - override val params: Set[Param[_]] = - conditions.collect { case p: HasParams => p.params }.flatten.toSet - - override def preFilter( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): PreFilterResult = { - conditions.foldLeft(NotFiltered: PreFilterResult) { - case (NotFiltered, condition) => condition.preFilter(evaluationContext, featureMap) - case (Filtered, _) => Filtered - case (NeedsFullEvaluation, condition) => { - condition.preFilter(evaluationContext, featureMap) match { - case Filtered => Filtered - case _ => NeedsFullEvaluation - } - } - } - } - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - conditions.foldLeft(Result.SatisfiedResult) { - case (result @ Unsatisfied(_), _) => result - case (Result.SatisfiedResult, condition) => condition.apply(evaluationContext, featureMap) - case (result @ Satisfied(_), condition) => { - condition.apply(evaluationContext, featureMap) match { - case r @ Unsatisfied(_) => r - case _ => result - } - } - } - } - } - - case class Or(override val conditions: Condition*) - extends Condition - with HasNestedConditions - with HasParams { - override lazy val name: String = s"(${conditions.map(_.name).mkString(" Or ")})" - override val features: Set[Feature[_]] = conditions.flatMap(_.features).toSet - override val optionalFeatures: Set[Feature[_]] = conditions.flatMap(_.optionalFeatures).toSet - override val params: Set[Param[_]] = - conditions.collect { case p: HasParams => p.params }.flatten.toSet - - private val UnsatisfiedResult = Unsatisfied(this) - - override def preFilter( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): PreFilterResult = { - conditions.foldLeft(Filtered: PreFilterResult) { - case (Filtered, c) => c.preFilter(evaluationContext, featureMap) - case (NotFiltered, _) => NotFiltered - case (NeedsFullEvaluation, c) => { - c.preFilter(evaluationContext, featureMap) match { - case NotFiltered => NotFiltered - case _ => NeedsFullEvaluation - } - } - } - } - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val foundSatisfiedCondition = - conditions.find(_.apply(evaluationContext, featureMap).asBoolean) - if (foundSatisfiedCondition.isDefined) { - Result.SatisfiedResult - } else { - UnsatisfiedResult - } - } - } - - case class Not(condition: Condition) extends Condition with HasNestedConditions with HasParams { - override lazy val name: String = s"Not(${condition.name})" - override val features: Set[Feature[_]] = condition.features - override val optionalFeatures: Set[Feature[_]] = condition.optionalFeatures - override val conditions: Seq[Condition] = Seq(condition) - override val params: Set[Param[_]] = - conditions.collect { case p: HasParams => p.params }.flatten.toSet - - private val UnsatisfiedResult = Unsatisfied(this) - - override def preFilter( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): PreFilterResult = - condition.preFilter(evaluationContext, featureMap) match { - case Filtered => NotFiltered - case NotFiltered => Filtered - case _ => NeedsFullEvaluation - } - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = - if (condition(evaluationContext, featureMap).asBoolean) { - UnsatisfiedResult - } else { - Result.SatisfiedResult - } - } - - val LoggedOutOrViewerNotFollowingAuthor: And = - And(NonAuthorViewer, Or(LoggedOutViewer, Not(ViewerDoesFollowAuthor))) - - val LoggedOutOrViewerOptInFiltering: Or = - Or(LoggedOutViewer, ViewerOptInFilteringOnSearch) - - val LoggedInViewer: Not = Not(LoggedOutViewer) - - val OuterAuthorNotFollowingAuthor: And = - And(Not(OuterAuthorIsInnerAuthor), Not(OuterAuthorFollowsAuthor)) - - val IsFocalTweet: FeatureEquals[Long] = FeatureEquals(TweetId, FocalTweetId) - - val NonHydratingConditions: Set[Class[_]] = Set( - LoggedOutViewer, - NonAuthorViewer, - True, - TweetComposedAfter(Time.now), - TweetComposedBefore(Time.now) - ).map(_.getClass) - - trait HasParams { - val params: Set[Param[_]] - } - - def hasLabelCondition(condition: Condition, tweetSafetyLabelType: TweetSafetyLabelType): Boolean = - condition match { - case lt: HasSafetyLabelType => - lt.hasLabelType(tweetSafetyLabelType) - case _ => false - } - - def hasLabelCondition(condition: Condition, userLabelValue: UserLabelValue): Boolean = - condition match { - case lt: HasSafetyLabelType => - lt.hasLabelType(userLabelValue) - case _ => false - } - - def hasLabelCondition(condition: Condition, spaceSafetyLabelType: SpaceSafetyLabelType): Boolean = - condition match { - case lt: HasSafetyLabelType => - lt.hasLabelType(spaceSafetyLabelType) - case _ => false - } - - def hasLabelCondition(condition: Condition, mediaSafetyLabelType: MediaSafetyLabelType): Boolean = - condition match { - case lt: HasSafetyLabelType => - lt.hasLabelType(mediaSafetyLabelType) - case _ => false - } - - case class Choose[T]( - conditionMap: Map[T, Condition], - defaultCondition: Condition, - choiceParam: Param[T]) - extends Condition - with HasNestedConditions - with HasParams { - override lazy val name: String = - s"(Either ${conditionMap.values.map(_.name).mkString(", ")} or ${defaultCondition.name})" - override val features: Set[Feature[_]] = - conditionMap.values.flatMap(_.features).toSet ++ defaultCondition.features - override val optionalFeatures: Set[Feature[_]] = - conditionMap.values.flatMap(_.optionalFeatures).toSet ++ defaultCondition.optionalFeatures - override val conditions: Seq[Condition] = conditionMap.values.toSeq :+ defaultCondition - override val params: Set[Param[_]] = - conditions.collect { case p: HasParams => p.params }.flatten.toSet - - private[this] def getCondition(evaluationContext: EvaluationContext): Condition = - conditionMap.getOrElse(evaluationContext.params(choiceParam), defaultCondition) - - override def preFilter( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): PreFilterResult = - getCondition(evaluationContext).preFilter(evaluationContext, featureMap) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = - getCondition(evaluationContext)(evaluationContext, featureMap) - } - - case class IfElse( - branchingCondition: Condition, - ifTrueCondition: Condition, - ifFalseCondition: Condition) - extends Condition - with HasNestedConditions - with HasParams { - override lazy val name: String = - s"(If ${branchingCondition.name} Then ${ifTrueCondition.name} Else ${ifFalseCondition.name})" - override val features: Set[Feature[_]] = - branchingCondition.features ++ ifTrueCondition.features ++ ifFalseCondition.features - override val optionalFeatures: Set[Feature[_]] = - branchingCondition.optionalFeatures ++ ifTrueCondition.optionalFeatures ++ ifFalseCondition.optionalFeatures - override val conditions: Seq[Condition] = - Seq(branchingCondition, ifTrueCondition, ifFalseCondition) - override val params: Set[Param[_]] = - conditions.collect { case p: HasParams => p.params }.flatten.toSet - - override def preFilter( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): PreFilterResult = - branchingCondition.preFilter(evaluationContext, featureMap) match { - case Filtered => - ifFalseCondition.preFilter(evaluationContext, featureMap) - case NotFiltered => - ifTrueCondition.preFilter(evaluationContext, featureMap) - case _ => - NeedsFullEvaluation - } - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = - if (branchingCondition(evaluationContext, featureMap).asBoolean) { - ifTrueCondition(evaluationContext, featureMap) - } else { - ifFalseCondition(evaluationContext, featureMap) - } - } - - case class GatedAlternate[T]( - defaultCondition: Condition, - alternateConditions: Map[T, Condition], - bucketIdentifierToUseOnDisagreementParam: Param[Option[T]]) - extends Condition - with HasNestedConditions - with HasParams { - - override lazy val name: String = - s"(${defaultCondition.name} or sometimes ${alternateConditions.values.map(_.name).mkString(" or ")})" - - override val features: Set[Feature[_]] = - defaultCondition.features ++ alternateConditions.values.flatMap(_.features) - - override val optionalFeatures: Set[Feature[_]] = - defaultCondition.optionalFeatures ++ alternateConditions.values.flatMap(_.optionalFeatures) - - override val conditions: Seq[Condition] = Seq(defaultCondition) ++ alternateConditions.values - - override val params: Set[Param[_]] = - conditions.collect { case p: HasParams => p.params }.flatten.toSet - - override def preFilter( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): PreFilterResult = - if (defaultCondition.preFilter(evaluationContext, featureMap) == Filtered && - alternateConditions.values.forall(_.preFilter(evaluationContext, featureMap) == Filtered)) { - Filtered - } else if (defaultCondition.preFilter(evaluationContext, featureMap) == NotFiltered && - alternateConditions.values.forall( - _.preFilter(evaluationContext, featureMap) == NotFiltered)) { - NotFiltered - } else { - NeedsFullEvaluation - } - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val defaultConditionResult: Result = defaultCondition(evaluationContext, featureMap) - val alternateConditionResult: Map[T, Result] = - alternateConditions.mapValues(_(evaluationContext, featureMap)) - - if (alternateConditionResult.values.exists(_.asBoolean != defaultConditionResult.asBoolean)) { - evaluationContext.params(bucketIdentifierToUseOnDisagreementParam) match { - case Some(bucket) if alternateConditionResult.contains(bucket) => - alternateConditionResult(bucket) - case _ => - defaultConditionResult - } - } else { - defaultConditionResult - } - } - } - - case class EnumGatedAlternate[E <: Enumeration]( - defaultCondition: Condition, - alternateConditions: Map[E#Value, Condition], - bucketIdentifierToUseOnDisagreementParam: EnumParam[E]) - extends Condition - with HasNestedConditions - with HasParams { - - override lazy val name: String = - s"(${defaultCondition.name} or sometimes ${alternateConditions.values.map(_.name).mkString(" or ")})" - - override val features: Set[Feature[_]] = - defaultCondition.features ++ alternateConditions.values.flatMap(_.features) - - override val optionalFeatures: Set[Feature[_]] = - defaultCondition.optionalFeatures ++ alternateConditions.values.flatMap(_.optionalFeatures) - - override val conditions: Seq[Condition] = Seq(defaultCondition) ++ alternateConditions.values - - override val params: Set[Param[_]] = - conditions - .collect { - case p: HasParams => p.params - }.flatten.toSet + bucketIdentifierToUseOnDisagreementParam - - override def preFilter( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): PreFilterResult = - if (defaultCondition.preFilter(evaluationContext, featureMap) == Filtered && - alternateConditions.values.forall(_.preFilter(evaluationContext, featureMap) == Filtered)) { - Filtered - } else if (defaultCondition.preFilter(evaluationContext, featureMap) == NotFiltered && - alternateConditions.values.forall( - _.preFilter(evaluationContext, featureMap) == NotFiltered)) { - NotFiltered - } else { - NeedsFullEvaluation - } - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val defaultConditionResult: Result = defaultCondition(evaluationContext, featureMap) - val alternateConditionResult: Map[E#Value, Result] = - alternateConditions.mapValues(_(evaluationContext, featureMap)) - - if (alternateConditionResult.values.exists(_.asBoolean != defaultConditionResult.asBoolean)) { - evaluationContext.params(bucketIdentifierToUseOnDisagreementParam) match { - case bucket if alternateConditionResult.contains(bucket) => - alternateConditionResult(bucket) - case _ => - defaultConditionResult - } - } else { - defaultConditionResult - } - } - } - - case object IsTestTweet extends Condition { - override val features: Set[Feature[_]] = Set(TweetId) - override val optionalFeatures: Set[Feature[_]] = Set.empty - - private val UnsatisfiedResult = Unsatisfied(this) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - if (!featureMap.contains(TweetId)) { - UnsatisfiedResult - } else { - Result.SatisfiedResult - } - } - } - - case object IsTweetInTweetLevelStcmHoldback extends Condition { - override val features: Set[Feature[_]] = Set(TweetId) - override val optionalFeatures: Set[Feature[_]] = Set.empty - private val UnsatisfiedResult = Unsatisfied(this) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val tweetId: Long = featureMap(TweetId).asInstanceOf[Long] - if (StcmTweetHoldback.isTweetInHoldback(tweetId)) { - Result.SatisfiedResult - } else { - UnsatisfiedResult - } - } - } - - case object MediaRestrictedInViewerCountry extends Condition { - override val features: Set[Feature[_]] = - Set(MediaGeoRestrictionsAllowList, MediaGeoRestrictionsDenyList) - override val optionalFeatures: Set[Feature[_]] = Set(RequestCountryCode) - - private val UnsatisfiedResult = Unsatisfied(this) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val requestCountryCode = TakedownReasons.normalizeCountryCodeOption( - featureMap.get(RequestCountryCode).asInstanceOf[Option[String]]) - val allowlistCountryCodes = - featureMap(MediaGeoRestrictionsAllowList).asInstanceOf[Seq[String]] - val denylistCountryCodes = - featureMap(MediaGeoRestrictionsDenyList).asInstanceOf[Seq[String]] - if ((allowlistCountryCodes.nonEmpty && !allowlistCountryCodes.contains(requestCountryCode)) - || denylistCountryCodes.contains(requestCountryCode)) { - Result.SatisfiedResult - } else { - UnsatisfiedResult - } - } - } - - case object OneToOneDmConversation - extends BooleanFeatureCondition(DmConversationIsOneToOneConversation) - - case object DmConversationTimelineIsEmpty - extends BooleanFeatureCondition(DmConversationHasEmptyTimeline) - - case object DmConversationLastReadableEventIdIsValid - extends BooleanFeatureCondition(DmConversationHasValidLastReadableEventId) - - case object ViewerIsDmConversationParticipant - extends BooleanFeatureCondition(feats.ViewerIsDmConversationParticipant) - - case object DmConversationInfoExists - extends BooleanFeatureCondition(feats.DmConversationInfoExists) - - case object DmConversationTimelineExists - extends BooleanFeatureCondition(feats.DmConversationTimelineExists) - - case object DmEventIsBeforeLastClearedEvent - extends BooleanFeatureCondition(DmEventOccurredBeforeLastClearedEvent) - - case object DmEventIsBeforeJoinConversationEvent - extends BooleanFeatureCondition(DmEventOccurredBeforeJoinConversationEvent) - - case object DmEventIsDeleted extends BooleanFeatureCondition(feats.DmEventIsDeleted) - - case object DmEventIsHidden extends BooleanFeatureCondition(feats.DmEventIsHidden) - - case object ViewerIsDmEventInitiatingUser - extends BooleanFeatureCondition(feats.ViewerIsDmEventInitiatingUser) - - case object DmEventInOneToOneConversationWithUnavailableUser - extends BooleanFeatureCondition(feats.DmEventInOneToOneConversationWithUnavailableUser) - - case object DmEventInOneToOneConversation - extends BooleanFeatureCondition(feats.DmEventInOneToOneConversation) - - case object MessageCreateDmEvent extends BooleanFeatureCondition(DmEventIsMessageCreateEvent) - - case object WelcomeMessageCreateDmEvent - extends BooleanFeatureCondition(DmEventIsWelcomeMessageCreateEvent) - - case object LastMessageReadUpdateDmEvent - extends BooleanFeatureCondition(DmEventIsLastMessageReadUpdateEvent) - - case object JoinConversationDmEvent - extends BooleanFeatureCondition(DmEventIsJoinConversationEvent) - - case object ConversationCreateDmEvent - extends BooleanFeatureCondition(DmEventIsConversationCreateEvent) - - case object TrustConversationDmEvent - extends BooleanFeatureCondition(DmEventIsTrustConversationEvent) - - case object CsFeedbackSubmittedDmEvent - extends BooleanFeatureCondition(DmEventIsCsFeedbackSubmitted) - - case object CsFeedbackDismissedDmEvent - extends BooleanFeatureCondition(DmEventIsCsFeedbackDismissed) - - case object PerspectivalJoinConversationDmEvent - extends BooleanFeatureCondition(feats.DmEventIsPerspectivalJoinConversationEvent) - - - case class SpaceHasLabelWithScoreAboveThresholdWithParam( - spaceSafetyLabelType: SpaceSafetyLabelType, - thresholdParam: Param[Double]) - extends Condition - with HasParams { - override lazy val name: String = - s"SpaceHasLabelWithScoreAboveThreshold(${spaceSafetyLabelType.name}, ${NamingUtils.getFriendlyName(thresholdParam)})" - override val features: Set[Feature[_]] = Set(SpaceSafetyLabels) - override val optionalFeatures: Set[Feature[_]] = Set.empty - private val UnsatisfiedResult = Unsatisfied(this) - override val params: Set[Param[_]] = Set(thresholdParam) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val labels = featureMap(SpaceSafetyLabels).asInstanceOf[Seq[SpaceSafetyLabel]] - val threshold = evaluationContext.params(thresholdParam) - val SatisfiedResult = - Satisfied(FoundSpaceLabelWithScoreAboveThreshold(spaceSafetyLabelType, threshold)) - labels - .collectFirst { - case label - if label.safetyLabelType == spaceSafetyLabelType - && label.safetyLabel.score.exists(_ >= threshold) => - SatisfiedResult - }.getOrElse(UnsatisfiedResult) - } - } - - case class CardUriHasRootDomain(rootDomainParam: Param[Seq[String]]) - extends Condition - with HasParams { - override lazy val name: String = - s"CardUriHasRootDomain(${NamingUtils.getFriendlyName(rootDomainParam)})" - override val features: Set[Feature[_]] = Set(CardUriHost) - override val optionalFeatures: Set[Feature[_]] = Set.empty - private val UnsatisfiedResult = Unsatisfied(this) - override val params: Set[Param[_]] = Set(rootDomainParam) - - private[this] def isHostDomainOrSubdomain(domain: String, host: String): Boolean = - host == domain || host.endsWith("." + domain) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val cardUriHost = featureMap(CardUriHost).asInstanceOf[String] - val rootDomains = evaluationContext.params(rootDomainParam) - - if (rootDomains.exists(isHostDomainOrSubdomain(_, cardUriHost))) { - Satisfied(FoundCardUriRootDomain(cardUriHost)) - } else { - UnsatisfiedResult - } - } - } - - case class TweetHasViolationOfLevel(level: ViolationLevel) - extends Condition - with HasSafetyLabelType { - - override lazy val name: String = s"tweetHasViolationOfLevel(${level})" - - override val features: Set[Feature[_]] = Set(TweetSafetyLabels) - override def optionalFeatures: Set[Feature[_]] = Set.empty - - private val UnsatisfiedResult: Unsatisfied = Unsatisfied(this) - - private val SatisfiedResult: Satisfied = Satisfied(FoundTweetViolationOfLevel(level)) - - override val labelTypes: Set[SafetyLabelType] = - ViolationLevel.violationLevelToSafetyLabels - .getOrElse(level, Set.empty) - .map(_.asInstanceOf[SafetyLabelType]) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val labels = featureMap(TweetSafetyLabels).asInstanceOf[Seq[TweetSafetyLabel]] - if (labels.map(ViolationLevel.fromTweetSafetyLabel).contains(level)) { - SatisfiedResult - } else { - UnsatisfiedResult - } - } - } - - case object TweetHasViolationOfAnyLevel extends Condition with HasSafetyLabelType { - - override lazy val name: String = s"tweetHasViolationOfAnyLevel" - - override val features: Set[Feature[_]] = Set(TweetSafetyLabels) - - override def optionalFeatures: Set[Feature[_]] = Set.empty - - private val UnsatisfiedResult: Unsatisfied = Unsatisfied(this) - - private val SatisfiedResult: Satisfied = Satisfied(FoundTweetViolationOfSomeLevel) - - override val labelTypes: Set[SafetyLabelType] = - ViolationLevel.violationLevelToSafetyLabels.values - .reduceLeft(_ ++ _) - .map(_.asInstanceOf[SafetyLabelType]) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val labels = featureMap(TweetSafetyLabels).asInstanceOf[Seq[TweetSafetyLabel]] - if (labels - .map(ViolationLevel.fromTweetSafetyLabelOpt).collect { - case Some(level) => level - }.nonEmpty) { - SatisfiedResult - } else { - UnsatisfiedResult - } - } - } - - case object TweetIsEditTweet extends BooleanFeatureCondition(TweetIsEditTweetFeature) - case object TweetIsStaleTweet extends BooleanFeatureCondition(TweetIsStaleTweetFeature) - - - case class ViewerHasAdultMediaSettingLevel(settingLevelToCompare: SensitiveMediaSettingsLevel) - extends Condition { - override def features: Set[Feature[_]] = Set(ViewerSensitiveMediaSettings) - - override def optionalFeatures: Set[Feature[_]] = Set.empty - - private val UnsatisfiedResult = Unsatisfied(this) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - featureMap - .get(ViewerSensitiveMediaSettings) - .map(_.asInstanceOf[UserSensitiveMediaSettings]) - .collectFirst { - case UserSensitiveMediaSettings(Some(setting)) - if (setting.viewAdultContent == settingLevelToCompare) => - Result.SatisfiedResult - case UserSensitiveMediaSettings(None) => UnsatisfiedResult - }.getOrElse(UnsatisfiedResult) - } - } - - case class ViewerHasViolentMediaSettingLevel(settingLevelToCompare: SensitiveMediaSettingsLevel) - extends Condition { - override def features: Set[Feature[_]] = Set(ViewerSensitiveMediaSettings) - - override def optionalFeatures: Set[Feature[_]] = Set.empty - - private val UnsatisfiedResult = Unsatisfied(this) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - - featureMap - .get(ViewerSensitiveMediaSettings) - .map(_.asInstanceOf[UserSensitiveMediaSettings]) - .collectFirst { - case UserSensitiveMediaSettings(Some(setting)) - if (setting.viewViolentContent == settingLevelToCompare) => - Result.SatisfiedResult - case UserSensitiveMediaSettings(None) => UnsatisfiedResult - }.getOrElse(UnsatisfiedResult) - } - } - - case class ViewerHasOtherSensitiveMediaSettingLevel( - settingLevelToCompare: SensitiveMediaSettingsLevel) - extends Condition { - override def features: Set[Feature[_]] = Set(ViewerSensitiveMediaSettings) - - override def optionalFeatures: Set[Feature[_]] = Set.empty - - private val UnsatisfiedResult = Unsatisfied(this) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - - featureMap - .get(ViewerSensitiveMediaSettings) - .map(_.asInstanceOf[UserSensitiveMediaSettings]) - .collectFirst { - case UserSensitiveMediaSettings(Some(setting)) - if (setting.viewOtherContent == settingLevelToCompare) => - Result.SatisfiedResult - case UserSensitiveMediaSettings(None) => UnsatisfiedResult - }.getOrElse(UnsatisfiedResult) - } - } - - private[rules] val ToxrfTweetFilteredForAuthor = - Equals(ToxicReplyFilterState, FilterState.FilteredFromAuthor) - - private[rules] case object ToxrfViewerIsConversationAuthor - extends BooleanFeatureCondition(ToxicReplyFilterConversationAuthorIsViewer) - - val ToxrfFilteredFromAuthorViewer = - And(LoggedInViewer, ToxrfTweetFilteredForAuthor, ToxrfViewerIsConversationAuthor) - - case object SearchQueryMatchesScreenName extends Condition { - override def features: Set[Feature[_]] = Set.empty - - override def optionalFeatures: Set[Feature[_]] = Set(RawQuery, AuthorScreenName) - - private val UnsatisfiedResult = Unsatisfied(this) - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - if (featureMap.contains(RawQuery) && featureMap.contains(AuthorScreenName)) { - val rawQuery = featureMap(RawQuery).asInstanceOf[String] - val authorScreenName = featureMap(AuthorScreenName).asInstanceOf[String] - if (rawQuery.equalsIgnoreCase(authorScreenName)) { - Result.SatisfiedResult - } else { - UnsatisfiedResult - } - } else { - UnsatisfiedResult - } - } - } - - object SearchQueryDoesNotMatchScreenNameConditionBuilder { - def apply(condition: Condition, ruleParam: RuleParam[Boolean]): Choose[Boolean] = { - Choose( - conditionMap = - Map(true -> And(condition, Not(SearchQueryMatchesScreenName)), false -> condition), - defaultCondition = condition, - choiceParam = ruleParam - ) - } - } - - val SearchQueryDoesNotMatchScreenNameDefaultTrueCondition: Choose[Boolean] = - SearchQueryDoesNotMatchScreenNameConditionBuilder(Condition.True, RuleParams.False) - - case object OptionalNonAuthorViewer extends Condition { - override val features: Set[Feature[_]] = Set() - override val optionalFeatures: Set[Feature[_]] = Set(AuthorId, ViewerId) - - private val UnsatisfiedResult = Unsatisfied(this) - - override def preFilter( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): PreFilterResult = { - NeedsFullEvaluation - } - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val authorIdsOpt = featureMap.get(AuthorId).asInstanceOf[Option[Set[Long]]] - val viewerIdOpt = featureMap.get(ViewerId).asInstanceOf[Option[Long]] - - (for { - authorIds <- authorIdsOpt - viewerId <- viewerIdOpt - } yield { - if (authorIds.contains(viewerId)) UnsatisfiedResult - else Result.SatisfiedResult - }) getOrElse { - Result.SatisfiedResult - } - } - } - - case class ViewerLocatedInApplicableCountriesOfMediaWithholdingLabel( - safetyLabelType: MediaSafetyLabelType) - extends ViewerInJurisdiction - with HasSafetyLabelType { - - override lazy val name: String = - s"ViewerLocatedInApplicableCountriesOfMediaLabel(${safetyLabelType.name})" - override val features: Set[Feature[_]] = Set(MediaSafetyLabels) - override val optionalFeatures: Set[Feature[_]] = Set(ViewerCountryCode, RequestCountryCode) - override val labelTypes: Set[SafetyLabelType] = Set(safetyLabelType) - - private val UnsatisfiedResult: Unsatisfied = Unsatisfied(this) - - private[this] def isInApplicableCountries( - countryCodeOpt: Option[String], - label: SafetyLabel - ): Boolean = { - val inApplicableCountry = (for { - applicableCountries <- label.applicableCountries - countryCode <- countryCodeOpt - } yield { - applicableCountries.contains(countryCode) - }) getOrElse (false) - inApplicableCountry - } - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val labels = featureMap(MediaSafetyLabels).asInstanceOf[Seq[MediaSafetyLabel]] - - val countryFeatures = getCountryFeatures(featureMap) - val countryCodeOpt = countryFeatures.requestCountryCode - .orElse(countryFeatures.viewerCountryCode) - - labels - .collectFirst { - case label - if label.safetyLabelType == safetyLabelType - && - isInApplicableCountries(countryCodeOpt, label.safetyLabel) => - Result.SatisfiedResult - }.getOrElse(UnsatisfiedResult) - } - } - - case class MediaHasLabelWithWorldwideWithholding(safetyLabelType: MediaSafetyLabelType) - extends Condition - with HasSafetyLabelType { - - override lazy val name: String = - s"MediaHasLabelWithWorldwideWithholding(${safetyLabelType.name})" - - override val features: Set[Feature[_]] = Set(MediaSafetyLabels) - - override val optionalFeatures: Set[Feature[_]] = Set.empty - - override val labelTypes: Set[SafetyLabelType] = Set(safetyLabelType) - - private val UnsatisfiedResult: Unsatisfied = Unsatisfied(this) - - private[this] def isWithheldWorldwide(label: SafetyLabel): Boolean = { - label.applicableCountries.map(_.contains("xx")).getOrElse(false) - } - - override def apply( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): Result = { - val labels = featureMap(MediaSafetyLabels).asInstanceOf[Seq[MediaSafetyLabel]] - - labels - .collectFirst { - case label - if label.safetyLabelType == safetyLabelType - && isWithheldWorldwide(label.safetyLabel) => - Result.SatisfiedResult - }.getOrElse(UnsatisfiedResult) - } - - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/DmConversationRules.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/DmConversationRules.scala deleted file mode 100644 index b9453cbe0..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/DmConversationRules.scala +++ /dev/null @@ -1,50 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.visibility.configapi.params.RuleParams -import com.twitter.visibility.rules.Condition.And -import com.twitter.visibility.rules.Condition.DmConversationLastReadableEventIdIsValid -import com.twitter.visibility.rules.Condition.DmConversationTimelineIsEmpty -import com.twitter.visibility.rules.Condition.ViewerIsDmConversationParticipant -import com.twitter.visibility.rules.Condition.DmConversationInfoExists -import com.twitter.visibility.rules.Condition.DmConversationTimelineExists -import com.twitter.visibility.rules.Condition.Not -import com.twitter.visibility.rules.Condition.DeactivatedAuthor -import com.twitter.visibility.rules.Condition.ErasedAuthor -import com.twitter.visibility.rules.Condition.OneToOneDmConversation -import com.twitter.visibility.rules.Condition.Or -import com.twitter.visibility.rules.Condition.SuspendedAuthor -import com.twitter.visibility.rules.Reason.Unspecified - -object DmConversationRules { - - object DropEmptyDmConversationRule - extends RuleWithConstantAction( - Drop(Unspecified), - Or( - Not(DmConversationLastReadableEventIdIsValid), - And(OneToOneDmConversation, DmConversationTimelineIsEmpty))) { - override def enableFailClosed = Seq(RuleParams.True) - } - - object DropInaccessibleDmConversationRule - extends RuleWithConstantAction(Drop(Unspecified), Not(ViewerIsDmConversationParticipant)) { - override def enableFailClosed = Seq(RuleParams.True) - } - - object DropDmConversationWithUndefinedConversationInfoRule - extends RuleWithConstantAction(Drop(Unspecified), Not(DmConversationInfoExists)) { - override def enableFailClosed = Seq(RuleParams.True) - } - - object DropDmConversationWithUndefinedConversationTimelineRule - extends RuleWithConstantAction(Drop(Unspecified), Not(DmConversationTimelineExists)) { - override def enableFailClosed = Seq(RuleParams.True) - } - - object DropOneToOneDmConversationWithUnavailableParticipantsRule - extends RuleWithConstantAction( - Drop(Unspecified), - And(OneToOneDmConversation, Or(SuspendedAuthor, DeactivatedAuthor, ErasedAuthor))) { - override def enableFailClosed = Seq(RuleParams.True) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/DmEventRules.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/DmEventRules.scala deleted file mode 100644 index 30bff031c..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/DmEventRules.scala +++ /dev/null @@ -1,90 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.visibility.rules.Reason.Unspecified -import com.twitter.visibility.rules.Condition.DeactivatedAuthor -import com.twitter.visibility.rules.Condition.ErasedAuthor -import com.twitter.visibility.rules.Condition.SuspendedAuthor -import com.twitter.visibility.rules.Condition.DmEventInOneToOneConversationWithUnavailableUser -import com.twitter.visibility.rules.Condition.DmEventIsBeforeLastClearedEvent -import com.twitter.visibility.rules.Condition.DmEventIsBeforeJoinConversationEvent -import com.twitter.visibility.rules.Condition.DmEventIsDeleted -import com.twitter.visibility.rules.Condition.DmEventIsHidden -import com.twitter.visibility.rules.Condition.LastMessageReadUpdateDmEvent -import com.twitter.visibility.rules.Condition.MessageCreateDmEvent -import com.twitter.visibility.rules.Condition.PerspectivalJoinConversationDmEvent -import com.twitter.visibility.rules.Condition.ViewerIsDmEventInitiatingUser -import com.twitter.visibility.rules.Condition.ViewerIsDmConversationParticipant -import com.twitter.visibility.configapi.params.RuleParams -import com.twitter.visibility.rules.Condition.And -import com.twitter.visibility.rules.Condition.CsFeedbackDismissedDmEvent -import com.twitter.visibility.rules.Condition.CsFeedbackSubmittedDmEvent -import com.twitter.visibility.rules.Condition.JoinConversationDmEvent -import com.twitter.visibility.rules.Condition.Not -import com.twitter.visibility.rules.Condition.Or -import com.twitter.visibility.rules.Condition.TrustConversationDmEvent -import com.twitter.visibility.rules.Condition.WelcomeMessageCreateDmEvent -import com.twitter.visibility.rules.Condition.DmEventInOneToOneConversation -import com.twitter.visibility.rules.Condition.ConversationCreateDmEvent - -object DmEventRules { - - object MessageCreateEventWithUnavailableSenderDropRule - extends RuleWithConstantAction( - Drop(Unspecified), - Or(SuspendedAuthor, DeactivatedAuthor, ErasedAuthor)) { - override def enableFailClosed = Seq(RuleParams.True) - } - - object WelcomeMessageCreateEventOnlyVisibleToRecipientDropRule - extends RuleWithConstantAction( - Drop(Unspecified), - And(ViewerIsDmEventInitiatingUser, WelcomeMessageCreateDmEvent)) { - override def enableFailClosed = Seq(RuleParams.True) - } - - object InaccessibleDmEventDropRule - extends RuleWithConstantAction( - Drop(Unspecified), - Or( - Not(ViewerIsDmConversationParticipant), - DmEventIsBeforeLastClearedEvent, - DmEventIsBeforeJoinConversationEvent)) { - override def enableFailClosed = Seq(RuleParams.True) - } - - object HiddenAndDeletedDmEventDropRule - extends RuleWithConstantAction(Drop(Unspecified), Or(DmEventIsDeleted, DmEventIsHidden)) { - override def enableFailClosed = Seq(RuleParams.True) - } - - object NonPerspectivalDmEventDropRule - extends RuleWithConstantAction( - Drop(Unspecified), - Or( - And(Not(PerspectivalJoinConversationDmEvent), JoinConversationDmEvent), - And( - Not(ViewerIsDmEventInitiatingUser), - Or(TrustConversationDmEvent, CsFeedbackSubmittedDmEvent, CsFeedbackDismissedDmEvent)) - ) - ) { - override def enableFailClosed = Seq(RuleParams.True) - } - - object DmEventInOneToOneConversationWithUnavailableUserDropRule - extends RuleWithConstantAction( - Drop(Unspecified), - And( - Or(MessageCreateDmEvent, LastMessageReadUpdateDmEvent), - DmEventInOneToOneConversationWithUnavailableUser)) { - override def enableFailClosed = Seq(RuleParams.True) - } - - object GroupEventInOneToOneConversationDropRule - extends RuleWithConstantAction( - Drop(Unspecified), - And( - Or(JoinConversationDmEvent, ConversationCreateDmEvent), - DmEventInOneToOneConversation)) { - override def enableFailClosed = Seq(RuleParams.True) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/DmVisibilityPolicies.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/DmVisibilityPolicies.scala deleted file mode 100644 index c32ba6d84..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/DmVisibilityPolicies.scala +++ /dev/null @@ -1,130 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.visibility.configapi.params.RuleParams -import com.twitter.visibility.rules.DmConversationRules._ -import com.twitter.visibility.rules.DmEventRules._ -import com.twitter.visibility.rules.PolicyLevelRuleParams.ruleParams - -object SensitiveMediaSettingsDirectMessagesBaseRules { - val policyRuleParams = Map[Rule, PolicyLevelRuleParams]( - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaDirectMessagesRulesParam), - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaDirectMessagesRulesParam), - NsfwReportedHeuristicsAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaDirectMessagesRulesParam), - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaDirectMessagesRulesParam), - NsfwCardImageAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaDirectMessagesRulesParam) - ) -} - -case object DirectMessagesPolicy - extends VisibilityPolicy( - tweetRules = TweetDetailPolicy.tweetRules.diff(LimitedEngagementBaseRules.tweetRules), - dmRules = Seq( - DeactivatedAuthorRule, - ErasedAuthorRule - ), - policyRuleParams = SensitiveMediaSettingsDirectMessagesBaseRules.policyRuleParams - ) - -case object DirectMessagesMutedUsersPolicy - extends VisibilityPolicy( - userRules = Seq(SuspendedAuthorRule) - ) - -case object DirectMessagesSearchPolicy - extends VisibilityPolicy( - dmConversationRules = Seq( - DropDmConversationWithUndefinedConversationInfoRule, - DropDmConversationWithUndefinedConversationTimelineRule, - DropInaccessibleDmConversationRule, - DropEmptyDmConversationRule, - DropOneToOneDmConversationWithUnavailableParticipantsRule - ), - dmEventRules = Seq( - InaccessibleDmEventDropRule, - HiddenAndDeletedDmEventDropRule, - MessageCreateEventWithUnavailableSenderDropRule), - userRules = Seq(ErasedAuthorRule, DeactivatedAuthorRule, SuspendedAuthorRule), - tweetRules = - Seq(ViewerBlocksAuthorRule, ViewerMutesAuthorRule) ++ TweetDetailPolicy.tweetRules.diff( - LimitedEngagementBaseRules.tweetRules), - policyRuleParams = SensitiveMediaSettingsDirectMessagesBaseRules.policyRuleParams - ) - -case object DirectMessagesPinnedPolicy - extends VisibilityPolicy( - dmConversationRules = Seq( - DropDmConversationWithUndefinedConversationInfoRule, - DropDmConversationWithUndefinedConversationTimelineRule, - DropInaccessibleDmConversationRule, - DropEmptyDmConversationRule, - DropOneToOneDmConversationWithUnavailableParticipantsRule - ), - dmEventRules = Seq( - InaccessibleDmEventDropRule, - HiddenAndDeletedDmEventDropRule, - MessageCreateEventWithUnavailableSenderDropRule), - userRules = Seq(ErasedAuthorRule, DeactivatedAuthorRule, SuspendedAuthorRule), - tweetRules = - Seq(ViewerBlocksAuthorRule, ViewerMutesAuthorRule) ++ TweetDetailPolicy.tweetRules.diff( - LimitedEngagementBaseRules.tweetRules), - policyRuleParams = SensitiveMediaSettingsDirectMessagesBaseRules.policyRuleParams - ) - -case object DirectMessagesConversationListPolicy - extends VisibilityPolicy( - dmConversationRules = Seq( - DropDmConversationWithUndefinedConversationInfoRule, - DropDmConversationWithUndefinedConversationTimelineRule, - DropInaccessibleDmConversationRule, - DropEmptyDmConversationRule, - DropOneToOneDmConversationWithUnavailableParticipantsRule - ), - userRules = Seq(ErasedAuthorRule, DeactivatedAuthorRule, SuspendedAuthorRule), - tweetRules = - Seq(ViewerBlocksAuthorRule, ViewerMutesAuthorRule) ++ TweetDetailPolicy.tweetRules.diff( - LimitedEngagementBaseRules.tweetRules), - policyRuleParams = SensitiveMediaSettingsDirectMessagesBaseRules.policyRuleParams - ) - -case object DirectMessagesConversationTimelinePolicy - extends VisibilityPolicy( - dmEventRules = Seq( - InaccessibleDmEventDropRule, - HiddenAndDeletedDmEventDropRule, - MessageCreateEventWithUnavailableSenderDropRule), - userRules = Seq(ErasedAuthorRule, DeactivatedAuthorRule, SuspendedAuthorRule), - tweetRules = - Seq(ViewerBlocksAuthorRule, ViewerMutesAuthorRule) ++ TweetDetailPolicy.tweetRules.diff( - LimitedEngagementBaseRules.tweetRules), - policyRuleParams = SensitiveMediaSettingsDirectMessagesBaseRules.policyRuleParams - ) - -case object DirectMessagesInboxPolicy - extends VisibilityPolicy( - dmConversationRules = Seq( - DropDmConversationWithUndefinedConversationInfoRule, - DropDmConversationWithUndefinedConversationTimelineRule, - DropInaccessibleDmConversationRule, - DropEmptyDmConversationRule, - DropOneToOneDmConversationWithUnavailableParticipantsRule - ), - dmEventRules = Seq( - InaccessibleDmEventDropRule, - HiddenAndDeletedDmEventDropRule, - DmEventInOneToOneConversationWithUnavailableUserDropRule, - MessageCreateEventWithUnavailableSenderDropRule, - NonPerspectivalDmEventDropRule, - WelcomeMessageCreateEventOnlyVisibleToRecipientDropRule, - GroupEventInOneToOneConversationDropRule - ), - userRules = Seq(ErasedAuthorRule, DeactivatedAuthorRule, SuspendedAuthorRule), - tweetRules = - Seq(ViewerBlocksAuthorRule, ViewerMutesAuthorRule) ++ TweetDetailPolicy.tweetRules.diff( - LimitedEngagementBaseRules.tweetRules), - policyRuleParams = SensitiveMediaSettingsDirectMessagesBaseRules.policyRuleParams - ) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/DownrankingRules.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/DownrankingRules.scala deleted file mode 100644 index 7126b8444..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/DownrankingRules.scala +++ /dev/null @@ -1,207 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.timelines.configapi.Params -import com.twitter.visibility.common.ModelScoreThresholds -import com.twitter.visibility.configapi.configs.DeciderKey -import com.twitter.visibility.configapi.params.FSRuleParams.HighSpammyTweetContentScoreConvoDownrankAbusiveQualityThresholdParam -import com.twitter.visibility.configapi.params.RuleParams.EnableDownrankSpamReplySectioningRuleParam -import com.twitter.visibility.configapi.params.RuleParams.EnableNotGraduatedDownrankConvosAbusiveQualityRuleParam -import com.twitter.visibility.configapi.params.RuleParams.NotGraduatedUserLabelRuleHoldbackExperimentParam -import com.twitter.visibility.configapi.params.TimelineConversationsDownrankingSpecificParams._ -import com.twitter.visibility.configapi.params.RuleParam -import com.twitter.visibility.models.TweetSafetyLabelType -import com.twitter.visibility.models.UserLabelValue -import com.twitter.visibility.rules.Condition._ -import com.twitter.visibility.rules.RuleActionSourceBuilder.TweetSafetyLabelSourceBuilder -import com.twitter.visibility.rules.RuleActionSourceBuilder.UserSafetyLabelSourceBuilder - -object DownrankingRules { - - val ToxicityScoreAboveDownrankAbusiveQualitySectionThresholdCondition: TweetHasLabelWithLanguageScoreAboveThreshold = - TweetHasLabelWithLanguageScoreAboveThreshold( - safetyLabel = TweetSafetyLabelType.HighToxicityScore, - languagesToScoreThresholds = ModelScoreThresholds.ToxicityAbusiveQualityLanguagesToThresholds - ) - - val ToxicityScoreAboveDownrankLowQualitySectionThresholdCondition: TweetHasLabelWithLanguageScoreAboveThreshold = - TweetHasLabelWithLanguageScoreAboveThreshold( - safetyLabel = TweetSafetyLabelType.HighToxicityScore, - languagesToScoreThresholds = ModelScoreThresholds.ToxicityLowQualityLanguagesToThresholds - ) - - val ToxicityScoreAboveDownrankHighQualitySectionThresholdCondition: TweetHasLabelWithLanguageScoreAboveThreshold = - TweetHasLabelWithLanguageScoreAboveThreshold( - safetyLabel = TweetSafetyLabelType.HighToxicityScore, - languagesToScoreThresholds = ModelScoreThresholds.ToxicityHighQualityLanguagesToThresholds - ) - - val HighSpammyTweetContentScoreConvoDownrankAbusiveQualityCondition: Condition = - TweetHasLabelWithScoreAboveThresholdWithParam( - TweetSafetyLabelType.HighSpammyTweetContentScore, - HighSpammyTweetContentScoreConvoDownrankAbusiveQualityThresholdParam) - - val HighCryptospamScoreConvoDownrankAbusiveQualityCondition: Condition = - TweetHasLabel(TweetSafetyLabelType.HighCryptospamScore) -} - -object HighToxicityScoreDownrankHighQualitySectionRule - extends ConditionWithNotInnerCircleOfFriendsRule( - Downrank, - DownrankingRules.ToxicityScoreAboveDownrankHighQualitySectionThresholdCondition - ) - with DoesLogVerdictDecidered { - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(TweetSafetyLabelType.HighToxicityScore)) - - override def verdictLogDeciderKey = DeciderKey.EnableDownlevelRuleVerdictLogging -} - -object HighToxicityScoreDownrankLowQualitySectionRule - extends ConditionWithNotInnerCircleOfFriendsRule( - ConversationSectionLowQuality, - DownrankingRules.ToxicityScoreAboveDownrankLowQualitySectionThresholdCondition - ) - with DoesLogVerdict { - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(TweetSafetyLabelType.HighToxicityScore)) -} - -object HighToxicityScoreDownrankAbusiveQualitySectionRule - extends ConditionWithNotInnerCircleOfFriendsRule( - ConversationSectionAbusiveQuality, - DownrankingRules.ToxicityScoreAboveDownrankAbusiveQualitySectionThresholdCondition - ) - with DoesLogVerdict { - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(TweetSafetyLabelType.HighToxicityScore)) -} - -object UntrustedUrlConversationsTweetLabelRule - extends ConditionWithNotInnerCircleOfFriendsRule( - ConversationSectionAbusiveQuality, - TweetHasLabel(TweetSafetyLabelType.UntrustedUrl) - ) - with DoesLogVerdictDecidered { - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(TweetSafetyLabelType.UntrustedUrl)) - override def verdictLogDeciderKey = DeciderKey.EnableDownlevelRuleVerdictLogging -} - -object DownrankSpamReplyConversationsTweetLabelRule - extends ConditionWithNotInnerCircleOfFriendsRule( - ConversationSectionAbusiveQuality, - TweetHasLabel(TweetSafetyLabelType.DownrankSpamReply) - ) - with DoesLogVerdictDecidered { - - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableDownrankSpamReplySectioningRuleParam) - - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(TweetSafetyLabelType.DownrankSpamReply)) - override def verdictLogDeciderKey = DeciderKey.EnableDownlevelRuleVerdictLogging -} - -object DownrankSpamReplyConversationsAuthorLabelRule - extends AuthorLabelWithNotInnerCircleOfFriendsRule( - ConversationSectionAbusiveQuality, - UserLabelValue.DownrankSpamReply - ) - with DoesLogVerdictDecidered { - - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableDownrankSpamReplySectioningRuleParam) - override def verdictLogDeciderKey = DeciderKey.EnableDownlevelRuleVerdictLogging - - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - UserSafetyLabelSourceBuilder(UserLabelValue.DownrankSpamReply)) -} - -object NotGraduatedConversationsAuthorLabelRule - extends AuthorLabelWithNotInnerCircleOfFriendsRule( - ConversationSectionLowQuality, - UserLabelValue.NotGraduated - ) - with DoesLogVerdictDecidered { - - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableNotGraduatedDownrankConvosAbusiveQualityRuleParam) - - override def holdbacks: Seq[RuleParam[Boolean]] = Seq( - NotGraduatedUserLabelRuleHoldbackExperimentParam) - - override def verdictLogDeciderKey = DeciderKey.EnableDownlevelRuleVerdictLogging - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - UserSafetyLabelSourceBuilder(UserLabelValue.NotGraduated)) -} - -object HighProactiveTosScoreTweetLabelDownrankingRule - extends ConditionWithNotInnerCircleOfFriendsRule( - ConversationSectionAbusiveQuality, - TweetHasLabel(TweetSafetyLabelType.HighProactiveTosScore) - ) - with DoesLogVerdictDecidered { - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(TweetSafetyLabelType.HighProactiveTosScore)) - override def verdictLogDeciderKey = DeciderKey.EnableDownlevelRuleVerdictLogging -} - -object HighPSpammyTweetScoreDownrankLowQualitySectionRule - extends ConditionWithNotInnerCircleOfFriendsRule( - action = ConversationSectionLowQuality, - condition = TweetHasLabelWithScoreAboveThreshold( - TweetSafetyLabelType.HighPSpammyTweetScore, - ModelScoreThresholds.HighPSpammyTweetScoreThreshold) - ) - with DoesLogVerdictDecidered { - override def enabled: Seq[RuleParam[Boolean]] = Seq( - EnablePSpammyTweetDownrankConvosLowQualityParam) - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(TweetSafetyLabelType.HighPSpammyTweetScore)) - override def verdictLogDeciderKey: DeciderKey.Value = - DeciderKey.EnableSpammyTweetRuleVerdictLogging -} - -object HighSpammyTweetContentScoreConvoDownrankAbusiveQualityRule - extends ConditionWithNotInnerCircleOfFriendsRule( - action = ConversationSectionAbusiveQuality, - condition = And( - Not(IsTweetInTweetLevelStcmHoldback), - DownrankingRules.HighSpammyTweetContentScoreConvoDownrankAbusiveQualityCondition) - ) - with DoesLogVerdictDecidered { - override def isEnabled(params: Params): Boolean = { - params(EnableHighSpammyTweetContentScoreConvoDownrankAbusiveQualityRuleParam) - } - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(TweetSafetyLabelType.HighSpammyTweetContentScore)) - override def verdictLogDeciderKey = DeciderKey.EnableDownlevelRuleVerdictLogging -} - -object HighCryptospamScoreConvoDownrankAbusiveQualityRule - extends ConditionWithNotInnerCircleOfFriendsRule( - action = ConversationSectionAbusiveQuality, - condition = DownrankingRules.HighCryptospamScoreConvoDownrankAbusiveQualityCondition - ) - with DoesLogVerdictDecidered { - override def isEnabled(params: Params): Boolean = { - params(EnableHighCryptospamScoreConvoDownrankAbusiveQualityRuleParam) - } - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(TweetSafetyLabelType.HighCryptospamScore)) - override def verdictLogDeciderKey = DeciderKey.EnableDownlevelRuleVerdictLogging -} - -object RitoActionedTweetDownrankLowQualitySectionRule - extends ConditionWithNotInnerCircleOfFriendsRule( - action = ConversationSectionLowQuality, - condition = TweetHasLabel(TweetSafetyLabelType.RitoActionedTweet) - ) - with DoesLogVerdictDecidered { - override def enabled: Seq[RuleParam[Boolean]] = Seq( - EnableRitoActionedTweetDownrankConvosLowQualityParam) - - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(TweetSafetyLabelType.RitoActionedTweet)) - override def verdictLogDeciderKey = DeciderKey.EnableDownlevelRuleVerdictLogging -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/EvaluationContext.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/EvaluationContext.scala deleted file mode 100644 index 545bce460..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/EvaluationContext.scala +++ /dev/null @@ -1,68 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.servo.util.Gate -import com.twitter.timelines.configapi.HasParams -import com.twitter.timelines.configapi.Params -import com.twitter.visibility.configapi.VisibilityParams -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.UnitOfDiversion -import com.twitter.visibility.models.ViewerContext - -case class EvaluationContext( - visibilityPolicy: VisibilityPolicy, - params: Params, - statsReceiver: StatsReceiver) - extends HasParams { - - def ruleEnabledInContext(rule: Rule): Boolean = { - visibilityPolicy.policyRuleParams - .get(rule) - .filter(_.ruleParams.nonEmpty) - .map(policyRuleParams => { - (policyRuleParams.force || rule.enabled.forall(params(_))) && - policyRuleParams.ruleParams.forall(params(_)) - }) - .getOrElse(rule.isEnabled(params)) - } -} - -object EvaluationContext { - - def apply( - safetyLevel: SafetyLevel, - params: Params, - statsReceiver: StatsReceiver - ): EvaluationContext = { - val visibilityPolicy = RuleBase.RuleMap(safetyLevel) - new EvaluationContext(visibilityPolicy, params, statsReceiver) - } - - case class Builder( - statsReceiver: StatsReceiver, - visibilityParams: VisibilityParams, - viewerContext: ViewerContext, - unitsOfDiversion: Seq[UnitOfDiversion] = Seq.empty, - memoizeParams: Gate[Unit] = Gate.False, - ) { - - private[this] val emptyContentToUoDCounter = - statsReceiver.counter("empty_content_id_to_unit_of_diversion") - - def build(safetyLevel: SafetyLevel): EvaluationContext = { - val policy = RuleBase.RuleMap(safetyLevel) - val params = if (memoizeParams()) { - visibilityParams.memoized(viewerContext, safetyLevel, unitsOfDiversion) - } else { - visibilityParams(viewerContext, safetyLevel, unitsOfDiversion) - } - new EvaluationContext(policy, params, statsReceiver) - } - - def withUnitOfDiversion(unitOfDiversion: UnitOfDiversion*): Builder = - this.copy(unitsOfDiversion = unitOfDiversion) - - def withMemoizedParams(memoizeParams: Gate[Unit]) = this.copy(memoizeParams = memoizeParams) - } - -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/ExperimentBase.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/ExperimentBase.scala deleted file mode 100644 index 840ca5312..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/ExperimentBase.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.timelines.configapi.Params -import com.twitter.visibility.configapi.params.LabelSourceParam -import com.twitter.visibility.models.LabelSource - -object ExperimentBase { - val sourceToParamMap: Map[LabelSource, LabelSourceParam] = Map.empty - - final def shouldFilterForSource(params: Params, labelSourceOpt: Option[LabelSource]): Boolean = { - labelSourceOpt - .map { source => - val param = ExperimentBase.sourceToParamMap.get(source) - param.map(params.apply).getOrElse(true) - } - .getOrElse(true) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/FailClosedException.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/FailClosedException.scala deleted file mode 100644 index f3f99f4a7..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/FailClosedException.scala +++ /dev/null @@ -1,41 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.visibility.features.Feature -import com.twitter.visibility.rules.State.FeatureFailed -import com.twitter.visibility.rules.State.MissingFeature -import com.twitter.visibility.rules.State.RuleFailed - -abstract class FailClosedException(message: String, state: State, ruleName: String) - extends Exception(message) { - def getState: State = { - state - } - - def getRuleName: String = { - ruleName - } -} - -case class MissingFeaturesException( - ruleName: String, - missingFeatures: Set[Feature[_]]) - extends FailClosedException( - s"A $ruleName rule evaluation has ${missingFeatures.size} missing features: ${missingFeatures - .map(_.name)}", - MissingFeature(missingFeatures), - ruleName) {} - -case class FeaturesFailedException( - ruleName: String, - featureFailures: Map[Feature[_], Throwable]) - extends FailClosedException( - s"A $ruleName rule evaluation has ${featureFailures.size} failed features: ${featureFailures.keys - .map(_.name)}, ${featureFailures.values}", - FeatureFailed(featureFailures), - ruleName) {} - -case class RuleFailedException(ruleName: String, exception: Throwable) - extends FailClosedException( - s"A $ruleName rule evaluation failed to execute", - RuleFailed(exception), - ruleName) {} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/FollowerRelations.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/FollowerRelations.scala deleted file mode 100644 index 1492db7fa..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/FollowerRelations.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.visibility.features.AuthorMutesViewer -import com.twitter.visibility.rules.Condition.BooleanFeatureCondition -import com.twitter.visibility.rules.Condition.ProtectedViewer -import com.twitter.visibility.rules.Reason.Unspecified - -object FollowerRelations { - - case object AuthorMutesViewerFeature extends BooleanFeatureCondition(AuthorMutesViewer) - - object AuthorMutesViewerRule - extends OnlyWhenNotAuthorViewerRule( - action = Drop(Unspecified), - condition = AuthorMutesViewerFeature) - - object ProtectedViewerRule - extends OnlyWhenNotAuthorViewerRule(action = Drop(Unspecified), condition = ProtectedViewer) - -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/ForEmergencyUseOnly.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/ForEmergencyUseOnly.scala deleted file mode 100644 index fabffaae2..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/ForEmergencyUseOnly.scala +++ /dev/null @@ -1,100 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.visibility.common.actions.ComplianceTweetNoticeEventType -import com.twitter.visibility.configapi.params.RuleParam -import com.twitter.visibility.configapi.params.RuleParams.EnableSearchIpiSafeSearchWithoutUserInQueryDropRule -import com.twitter.visibility.features.Feature -import com.twitter.visibility.features.TweetSafetyLabels -import com.twitter.visibility.models.LabelSource.StringSource -import com.twitter.visibility.models.LabelSource.parseStringSource -import com.twitter.visibility.models.TweetSafetyLabel -import com.twitter.visibility.models.TweetSafetyLabelType -import com.twitter.visibility.rules.Condition.And -import com.twitter.visibility.rules.Condition.LoggedOutOrViewerOptInFiltering -import com.twitter.visibility.rules.Condition.Not -import com.twitter.visibility.rules.Condition.SearchQueryHasUser -import com.twitter.visibility.rules.Condition.TweetHasLabel -import com.twitter.visibility.rules.Reason.Unspecified - -object EmergencyDynamicInterstitialActionBuilder - extends ActionBuilder[EmergencyDynamicInterstitial] { - - def actionType: Class[_] = classOf[EmergencyDynamicInterstitial] - - override val actionSeverity = 11 - override def build( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): RuleResult = { - val label = featureMap(TweetSafetyLabels) - .asInstanceOf[Seq[TweetSafetyLabel]] - .find(slv => slv.labelType == TweetSafetyLabelType.ForEmergencyUseOnly) - - label.flatMap(_.source) match { - case Some(StringSource(name)) => - val (copy, linkOpt) = parseStringSource(name) - RuleResult(EmergencyDynamicInterstitial(copy, linkOpt), State.Evaluated) - - case _ => - Rule.EvaluatedRuleResult - } - } -} - -object EmergencyDynamicComplianceTweetNoticeActionBuilder - extends ActionBuilder[ComplianceTweetNoticePreEnrichment] { - - def actionType: Class[_] = classOf[ComplianceTweetNoticePreEnrichment] - - override val actionSeverity = 2 - override def build( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): RuleResult = { - val label = featureMap(TweetSafetyLabels) - .asInstanceOf[Seq[TweetSafetyLabel]] - .find(slv => slv.labelType == TweetSafetyLabelType.ForEmergencyUseOnly) - - label.flatMap(_.source) match { - case Some(StringSource(name)) => - val (copy, linkOpt) = parseStringSource(name) - RuleResult( - ComplianceTweetNoticePreEnrichment( - reason = Unspecified, - complianceTweetNoticeEventType = ComplianceTweetNoticeEventType.PublicInterest, - details = Some(copy), - extendedDetailsUrl = linkOpt - ), - State.Evaluated - ) - - case _ => - Rule.EvaluatedRuleResult - } - } -} - -object EmergencyDynamicInterstitialRule - extends Rule( - EmergencyDynamicInterstitialActionBuilder, - TweetHasLabel(TweetSafetyLabelType.ForEmergencyUseOnly) - ) - -object EmergencyDropRule - extends RuleWithConstantAction( - Drop(Unspecified), - TweetHasLabel(TweetSafetyLabelType.ForEmergencyUseOnly) - ) - -object SearchEdiSafeSearchWithoutUserInQueryDropRule - extends RuleWithConstantAction( - Drop(Unspecified), - And( - TweetHasLabel(TweetSafetyLabelType.ForEmergencyUseOnly), - LoggedOutOrViewerOptInFiltering, - Not(SearchQueryHasUser) - ) - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq( - EnableSearchIpiSafeSearchWithoutUserInQueryDropRule) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/FreedomOfSpeechNotReach.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/FreedomOfSpeechNotReach.scala deleted file mode 100644 index 03e094025..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/FreedomOfSpeechNotReach.scala +++ /dev/null @@ -1,685 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.spam.rtf.thriftscala.SafetyResultReason -import com.twitter.util.Memoize -import com.twitter.visibility.common.actions.AppealableReason -import com.twitter.visibility.common.actions.AvoidReason.MightNotBeSuitableForAds -import com.twitter.visibility.common.actions.LimitedEngagementReason -import com.twitter.visibility.common.actions.SoftInterventionDisplayType -import com.twitter.visibility.common.actions.SoftInterventionReason -import com.twitter.visibility.common.actions.LimitedActionsPolicy -import com.twitter.visibility.common.actions.LimitedAction -import com.twitter.visibility.common.actions.converter.scala.LimitedActionTypeConverter -import com.twitter.visibility.configapi.params.FSRuleParams.FosnrFallbackDropRulesEnabledParam -import com.twitter.visibility.configapi.params.FSRuleParams.FosnrRulesEnabledParam -import com.twitter.visibility.configapi.params.RuleParam -import com.twitter.visibility.configapi.params.RuleParams.EnableFosnrRuleParam -import com.twitter.visibility.features.Feature -import com.twitter.visibility.features.TweetSafetyLabels -import com.twitter.visibility.models.TweetSafetyLabel -import com.twitter.visibility.models.TweetSafetyLabelType -import com.twitter.visibility.models.ViolationLevel -import com.twitter.visibility.rules.ComposableActions.ComposableActionsWithInterstitialLimitedEngagements -import com.twitter.visibility.rules.ComposableActions.ComposableActionsWithSoftIntervention -import com.twitter.visibility.rules.ComposableActions.ComposableActionsWithAppealable -import com.twitter.visibility.rules.ComposableActions.ComposableActionsWithInterstitial -import com.twitter.visibility.rules.Condition.And -import com.twitter.visibility.rules.Condition.NonAuthorViewer -import com.twitter.visibility.rules.Condition.Not -import com.twitter.visibility.rules.Condition.ViewerDoesNotFollowAuthorOfFosnrViolatingTweet -import com.twitter.visibility.rules.Condition.ViewerFollowsAuthorOfFosnrViolatingTweet -import com.twitter.visibility.rules.FreedomOfSpeechNotReach.DefaultViolationLevel -import com.twitter.visibility.rules.Reason._ -import com.twitter.visibility.rules.State.Evaluated - -object FreedomOfSpeechNotReach { - - val DefaultViolationLevel = ViolationLevel.Level1 - - def reasonToSafetyResultReason(reason: Reason): SafetyResultReason = - reason match { - case HatefulConduct => SafetyResultReason.FosnrHatefulConduct - case AbusiveBehavior => SafetyResultReason.FosnrAbusiveBehavior - case _ => SafetyResultReason.FosnrUnspecified - } - - def reasonToSafetyResultReason(reason: AppealableReason): SafetyResultReason = - reason match { - case AppealableReason.HatefulConduct(_) => SafetyResultReason.FosnrHatefulConduct - case AppealableReason.AbusiveBehavior(_) => SafetyResultReason.FosnrAbusiveBehavior - case _ => SafetyResultReason.FosnrUnspecified - } - - val EligibleTweetSafetyLabelTypes: Seq[TweetSafetyLabelType] = - Seq(ViolationLevel.Level4, ViolationLevel.Level3, ViolationLevel.Level2, ViolationLevel.Level1) - .map { - ViolationLevel.violationLevelToSafetyLabels.get(_).getOrElse(Set()).toSeq - }.reduceLeft { - _ ++ _ - } - - private val EligibleTweetSafetyLabelTypesSet = EligibleTweetSafetyLabelTypes.toSet - - def extractTweetSafetyLabel(featureMap: Map[Feature[_], _]): Option[TweetSafetyLabel] = { - val tweetSafetyLabels = featureMap(TweetSafetyLabels) - .asInstanceOf[Seq[TweetSafetyLabel]] - .flatMap { tsl => - if (FreedomOfSpeechNotReach.EligibleTweetSafetyLabelTypesSet.contains(tsl.labelType)) { - Some(tsl.labelType -> tsl) - } else { - None - } - } - .toMap - - FreedomOfSpeechNotReach.EligibleTweetSafetyLabelTypes.flatMap(tweetSafetyLabels.get).headOption - } - - def eligibleTweetSafetyLabelTypesToAppealableReason( - labelType: TweetSafetyLabelType, - violationLevel: ViolationLevel - ): AppealableReason = { - labelType match { - case TweetSafetyLabelType.FosnrHatefulConduct => - AppealableReason.HatefulConduct(violationLevel.level) - case TweetSafetyLabelType.FosnrHatefulConductLowSeveritySlur => - AppealableReason.HatefulConduct(violationLevel.level) - case _ => - AppealableReason.Unspecified(violationLevel.level) - } - } - - def limitedActionConverter( - limitedActionStrings: Option[Seq[String]] - ): Option[LimitedActionsPolicy] = { - val limitedActions = limitedActionStrings.map { limitedActionString => - limitedActionString - .map(action => LimitedActionTypeConverter.fromString(action)).map { action => - action match { - case Some(a) => Some(LimitedAction(a, None)) - case _ => None - } - }.flatten - } - limitedActions.map(actions => LimitedActionsPolicy(actions)) - } -} - -object FreedomOfSpeechNotReachReason { - def unapply(softIntervention: SoftIntervention): Option[AppealableReason] = { - softIntervention.reason match { - case SoftInterventionReason.FosnrReason(appealableReason) => Some(appealableReason) - case _ => None - } - } - - def unapply( - interstitialLimitedEngagements: InterstitialLimitedEngagements - ): Option[AppealableReason] = { - interstitialLimitedEngagements.limitedEngagementReason match { - case Some(LimitedEngagementReason.FosnrReason(appealableReason)) => Some(appealableReason) - case _ => None - } - } - - def unapply( - interstitial: Interstitial - ): Option[AppealableReason] = { - interstitial.reason match { - case Reason.FosnrReason(appealableReason) => Some(appealableReason) - case _ => None - } - } - - def unapply( - appealable: Appealable - ): Option[AppealableReason] = { - Reason.toAppealableReason(appealable.reason, appealable.violationLevel) - } - - def unapply( - action: Action - ): Option[AppealableReason] = { - action match { - case a: SoftIntervention => - a match { - case FreedomOfSpeechNotReachReason(r) => Some(r) - case _ => None - } - case a: InterstitialLimitedEngagements => - a match { - case FreedomOfSpeechNotReachReason(r) => Some(r) - case _ => None - } - case a: Interstitial => - a match { - case FreedomOfSpeechNotReachReason(r) => Some(r) - case _ => None - } - case a: Appealable => - a match { - case FreedomOfSpeechNotReachReason(r) => Some(r) - case _ => None - } - case ComposableActionsWithSoftIntervention(FreedomOfSpeechNotReachReason(appealableReason)) => - Some(appealableReason) - case ComposableActionsWithInterstitialLimitedEngagements( - FreedomOfSpeechNotReachReason(appealableReason)) => - Some(appealableReason) - case ComposableActionsWithInterstitial(FreedomOfSpeechNotReachReason(appealableReason)) => - Some(appealableReason) - case ComposableActionsWithAppealable(FreedomOfSpeechNotReachReason(appealableReason)) => - Some(appealableReason) - case _ => None - } - } -} - -object FreedomOfSpeechNotReachActions { - - trait FreedomOfSpeechNotReachActionBuilder[T <: Action] extends ActionBuilder[T] { - def withViolationLevel(violationLevel: ViolationLevel): FreedomOfSpeechNotReachActionBuilder[T] - } - - case class DropAction(violationLevel: ViolationLevel = DefaultViolationLevel) - extends FreedomOfSpeechNotReachActionBuilder[Drop] { - - override def actionType: Class[_] = classOf[Drop] - - override val actionSeverity = 16 - private def toRuleResult: Reason => RuleResult = Memoize { r => RuleResult(Drop(r), Evaluated) } - - def build(evaluationContext: EvaluationContext, featureMap: Map[Feature[_], _]): RuleResult = { - val appealableReason = - FreedomOfSpeechNotReach.extractTweetSafetyLabel(featureMap).map(_.labelType) match { - case Some(label) => - FreedomOfSpeechNotReach.eligibleTweetSafetyLabelTypesToAppealableReason( - label, - violationLevel) - case _ => - AppealableReason.Unspecified(violationLevel.level) - } - - toRuleResult(Reason.fromAppealableReason(appealableReason)) - } - - override def withViolationLevel(violationLevel: ViolationLevel) = { - copy(violationLevel = violationLevel) - } - } - - case class AppealableAction(violationLevel: ViolationLevel = DefaultViolationLevel) - extends FreedomOfSpeechNotReachActionBuilder[TweetInterstitial] { - - override def actionType: Class[_] = classOf[Appealable] - - override val actionSeverity = 17 - private def toRuleResult: Reason => RuleResult = Memoize { r => - RuleResult( - TweetInterstitial( - interstitial = None, - softIntervention = None, - limitedEngagements = None, - downrank = None, - avoid = Some(Avoid(None)), - mediaInterstitial = None, - tweetVisibilityNudge = None, - abusiveQuality = None, - appealable = Some(Appealable(r, violationLevel = violationLevel)) - ), - Evaluated - ) - } - - def build(evaluationContext: EvaluationContext, featureMap: Map[Feature[_], _]): RuleResult = { - val appealableReason = - FreedomOfSpeechNotReach.extractTweetSafetyLabel(featureMap).map(_.labelType) match { - case Some(label) => - FreedomOfSpeechNotReach.eligibleTweetSafetyLabelTypesToAppealableReason( - label, - violationLevel) - case _ => - AppealableReason.Unspecified(violationLevel.level) - } - - toRuleResult(Reason.fromAppealableReason(appealableReason)) - } - - override def withViolationLevel(violationLevel: ViolationLevel) = { - copy(violationLevel = violationLevel) - } - } - - case class AppealableAvoidLimitedEngagementsAction( - violationLevel: ViolationLevel = DefaultViolationLevel, - limitedActionStrings: Option[Seq[String]]) - extends FreedomOfSpeechNotReachActionBuilder[Appealable] { - - override def actionType: Class[_] = classOf[AppealableAvoidLimitedEngagementsAction] - - override val actionSeverity = 17 - private def toRuleResult: Reason => RuleResult = Memoize { r => - RuleResult( - TweetInterstitial( - interstitial = None, - softIntervention = None, - limitedEngagements = Some( - LimitedEngagements( - toLimitedEngagementReason( - Reason - .toAppealableReason(r, violationLevel) - .getOrElse(AppealableReason.Unspecified(violationLevel.level))), - FreedomOfSpeechNotReach.limitedActionConverter(limitedActionStrings) - )), - downrank = None, - avoid = Some(Avoid(None)), - mediaInterstitial = None, - tweetVisibilityNudge = None, - abusiveQuality = None, - appealable = Some(Appealable(r, violationLevel = violationLevel)) - ), - Evaluated - ) - } - - def build( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): RuleResult = { - val appealableReason = - FreedomOfSpeechNotReach.extractTweetSafetyLabel(featureMap).map(_.labelType) match { - case Some(label) => - FreedomOfSpeechNotReach.eligibleTweetSafetyLabelTypesToAppealableReason( - label, - violationLevel) - case _ => - AppealableReason.Unspecified(violationLevel.level) - } - - toRuleResult(Reason.fromAppealableReason(appealableReason)) - } - - override def withViolationLevel(violationLevel: ViolationLevel) = { - copy(violationLevel = violationLevel) - } - } - - case class AvoidAction(violationLevel: ViolationLevel = DefaultViolationLevel) - extends FreedomOfSpeechNotReachActionBuilder[Avoid] { - - override def actionType: Class[_] = classOf[Avoid] - - override val actionSeverity = 1 - private def toRuleResult: Reason => RuleResult = Memoize { r => - RuleResult(Avoid(None), Evaluated) - } - - def build(evaluationContext: EvaluationContext, featureMap: Map[Feature[_], _]): RuleResult = { - val appealableReason = - FreedomOfSpeechNotReach.extractTweetSafetyLabel(featureMap).map(_.labelType) match { - case Some(label) => - FreedomOfSpeechNotReach.eligibleTweetSafetyLabelTypesToAppealableReason( - label, - violationLevel) - case _ => - AppealableReason.Unspecified(violationLevel.level) - } - - toRuleResult(Reason.fromAppealableReason(appealableReason)) - } - - override def withViolationLevel(violationLevel: ViolationLevel) = { - copy(violationLevel = violationLevel) - } - } - - case class LimitedEngagementsAction(violationLevel: ViolationLevel = DefaultViolationLevel) - extends FreedomOfSpeechNotReachActionBuilder[LimitedEngagements] { - - override def actionType: Class[_] = classOf[LimitedEngagements] - - override val actionSeverity = 6 - private def toRuleResult: Reason => RuleResult = Memoize { r => - RuleResult(LimitedEngagements(LimitedEngagementReason.NonCompliant, None), Evaluated) - } - - def build(evaluationContext: EvaluationContext, featureMap: Map[Feature[_], _]): RuleResult = { - val appealableReason = - FreedomOfSpeechNotReach.extractTweetSafetyLabel(featureMap).map(_.labelType) match { - case Some(label) => - FreedomOfSpeechNotReach.eligibleTweetSafetyLabelTypesToAppealableReason( - label, - violationLevel) - case _ => - AppealableReason.Unspecified(violationLevel.level) - } - - toRuleResult(Reason.fromAppealableReason(appealableReason)) - } - - override def withViolationLevel(violationLevel: ViolationLevel) = { - copy(violationLevel = violationLevel) - } - } - - case class InterstitialLimitedEngagementsAction( - violationLevel: ViolationLevel = DefaultViolationLevel) - extends FreedomOfSpeechNotReachActionBuilder[InterstitialLimitedEngagements] { - - override def actionType: Class[_] = classOf[InterstitialLimitedEngagements] - - override val actionSeverity = 11 - private def toRuleResult: Reason => RuleResult = Memoize { r => - RuleResult(InterstitialLimitedEngagements(r, None), Evaluated) - } - - def build(evaluationContext: EvaluationContext, featureMap: Map[Feature[_], _]): RuleResult = { - val appealableReason = - FreedomOfSpeechNotReach.extractTweetSafetyLabel(featureMap).map(_.labelType) match { - case Some(label) => - FreedomOfSpeechNotReach.eligibleTweetSafetyLabelTypesToAppealableReason( - label, - violationLevel) - case _ => - AppealableReason.Unspecified(violationLevel.level) - } - - toRuleResult(Reason.fromAppealableReason(appealableReason)) - } - - override def withViolationLevel(violationLevel: ViolationLevel) = { - copy(violationLevel = violationLevel) - } - } - - case class InterstitialLimitedEngagementsAvoidAction( - violationLevel: ViolationLevel = DefaultViolationLevel, - limitedActionStrings: Option[Seq[String]]) - extends FreedomOfSpeechNotReachActionBuilder[TweetInterstitial] { - - override def actionType: Class[_] = classOf[InterstitialLimitedEngagementsAvoidAction] - - override val actionSeverity = 14 - private def toRuleResult: AppealableReason => RuleResult = Memoize { r => - RuleResult( - TweetInterstitial( - interstitial = Some( - Interstitial( - reason = FosnrReason(r), - localizedMessage = None, - )), - softIntervention = None, - limitedEngagements = Some( - LimitedEngagements( - reason = toLimitedEngagementReason(r), - policy = FreedomOfSpeechNotReach.limitedActionConverter(limitedActionStrings))), - downrank = None, - avoid = Some(Avoid(None)), - mediaInterstitial = None, - tweetVisibilityNudge = None - ), - Evaluated - ) - } - - def build(evaluationContext: EvaluationContext, featureMap: Map[Feature[_], _]): RuleResult = { - val appealableReason = - FreedomOfSpeechNotReach.extractTweetSafetyLabel(featureMap).map(_.labelType) match { - case Some(label) => - FreedomOfSpeechNotReach.eligibleTweetSafetyLabelTypesToAppealableReason( - labelType = label, - violationLevel = violationLevel) - case _ => - AppealableReason.Unspecified(violationLevel.level) - } - - toRuleResult(appealableReason) - } - - override def withViolationLevel(violationLevel: ViolationLevel) = { - copy(violationLevel = violationLevel) - } - } - - case class SoftInterventionAvoidAction(violationLevel: ViolationLevel = DefaultViolationLevel) - extends FreedomOfSpeechNotReachActionBuilder[TweetInterstitial] { - - override def actionType: Class[_] = classOf[SoftInterventionAvoidAction] - - override val actionSeverity = 8 - private def toRuleResult: AppealableReason => RuleResult = Memoize { r => - RuleResult( - TweetInterstitial( - interstitial = None, - softIntervention = Some( - SoftIntervention( - reason = toSoftInterventionReason(r), - engagementNudge = false, - suppressAutoplay = true, - warning = None, - detailsUrl = None, - displayType = Some(SoftInterventionDisplayType.Fosnr) - )), - limitedEngagements = None, - downrank = None, - avoid = Some(Avoid(None)), - mediaInterstitial = None, - tweetVisibilityNudge = None, - abusiveQuality = None - ), - Evaluated - ) - } - - def build(evaluationContext: EvaluationContext, featureMap: Map[Feature[_], _]): RuleResult = { - val appealableReason = - FreedomOfSpeechNotReach.extractTweetSafetyLabel(featureMap).map(_.labelType) match { - case Some(label) => - FreedomOfSpeechNotReach.eligibleTweetSafetyLabelTypesToAppealableReason( - label, - violationLevel) - case _ => - AppealableReason.Unspecified(violationLevel.level) - } - - toRuleResult(appealableReason) - } - - override def withViolationLevel(violationLevel: ViolationLevel) = { - copy(violationLevel = violationLevel) - } - } - - case class SoftInterventionAvoidLimitedEngagementsAction( - violationLevel: ViolationLevel = DefaultViolationLevel, - limitedActionStrings: Option[Seq[String]]) - extends FreedomOfSpeechNotReachActionBuilder[TweetInterstitial] { - - override def actionType: Class[_] = classOf[SoftInterventionAvoidLimitedEngagementsAction] - - override val actionSeverity = 13 - private def toRuleResult: AppealableReason => RuleResult = Memoize { r => - RuleResult( - TweetInterstitial( - interstitial = None, - softIntervention = Some( - SoftIntervention( - reason = toSoftInterventionReason(r), - engagementNudge = false, - suppressAutoplay = true, - warning = None, - detailsUrl = None, - displayType = Some(SoftInterventionDisplayType.Fosnr) - )), - limitedEngagements = Some( - LimitedEngagements( - toLimitedEngagementReason(r), - FreedomOfSpeechNotReach.limitedActionConverter(limitedActionStrings))), - downrank = None, - avoid = Some(Avoid(None)), - mediaInterstitial = None, - tweetVisibilityNudge = None, - abusiveQuality = None - ), - Evaluated - ) - } - - def build(evaluationContext: EvaluationContext, featureMap: Map[Feature[_], _]): RuleResult = { - val appealableReason = - FreedomOfSpeechNotReach.extractTweetSafetyLabel(featureMap).map(_.labelType) match { - case Some(label) => - FreedomOfSpeechNotReach.eligibleTweetSafetyLabelTypesToAppealableReason( - label, - violationLevel) - case _ => - AppealableReason.Unspecified(violationLevel.level) - } - - toRuleResult(appealableReason) - } - - override def withViolationLevel(violationLevel: ViolationLevel) = { - copy(violationLevel = violationLevel) - } - } - - case class SoftInterventionAvoidAbusiveQualityReplyAction( - violationLevel: ViolationLevel = DefaultViolationLevel) - extends FreedomOfSpeechNotReachActionBuilder[TweetInterstitial] { - - override def actionType: Class[_] = classOf[SoftInterventionAvoidAbusiveQualityReplyAction] - - override val actionSeverity = 13 - private def toRuleResult: AppealableReason => RuleResult = Memoize { r => - RuleResult( - TweetInterstitial( - interstitial = None, - softIntervention = Some( - SoftIntervention( - reason = toSoftInterventionReason(r), - engagementNudge = false, - suppressAutoplay = true, - warning = None, - detailsUrl = None, - displayType = Some(SoftInterventionDisplayType.Fosnr) - )), - limitedEngagements = None, - downrank = None, - avoid = Some(Avoid(None)), - mediaInterstitial = None, - tweetVisibilityNudge = None, - abusiveQuality = Some(ConversationSectionAbusiveQuality) - ), - Evaluated - ) - } - - def build(evaluationContext: EvaluationContext, featureMap: Map[Feature[_], _]): RuleResult = { - val appealableReason = - FreedomOfSpeechNotReach.extractTweetSafetyLabel(featureMap).map(_.labelType) match { - case Some(label) => - FreedomOfSpeechNotReach.eligibleTweetSafetyLabelTypesToAppealableReason( - label, - violationLevel) - case _ => - AppealableReason.Unspecified(violationLevel.level) - } - - toRuleResult(appealableReason) - } - - override def withViolationLevel(violationLevel: ViolationLevel) = { - copy(violationLevel = violationLevel) - } - } -} - -object FreedomOfSpeechNotReachRules { - - abstract class OnlyWhenAuthorViewerRule( - actionBuilder: ActionBuilder[_ <: Action], - condition: Condition) - extends Rule(actionBuilder, And(Not(NonAuthorViewer), condition)) - - abstract class OnlyWhenNonAuthorViewerRule( - actionBuilder: ActionBuilder[_ <: Action], - condition: Condition) - extends Rule(actionBuilder, And(NonAuthorViewer, condition)) - - case class ViewerIsAuthorAndTweetHasViolationOfLevel( - violationLevel: ViolationLevel, - override val actionBuilder: ActionBuilder[_ <: Action]) - extends OnlyWhenAuthorViewerRule( - actionBuilder, - Condition.TweetHasViolationOfLevel(violationLevel) - ) { - override lazy val name: String = s"ViewerIsAuthorAndTweetHasViolationOf$violationLevel" - - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableFosnrRuleParam, FosnrRulesEnabledParam) - } - - case class ViewerIsFollowerAndTweetHasViolationOfLevel( - violationLevel: ViolationLevel, - override val actionBuilder: ActionBuilder[_ <: Action]) - extends OnlyWhenNonAuthorViewerRule( - actionBuilder, - And( - Condition.TweetHasViolationOfLevel(violationLevel), - ViewerFollowsAuthorOfFosnrViolatingTweet) - ) { - override lazy val name: String = s"ViewerIsFollowerAndTweetHasViolationOf$violationLevel" - - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableFosnrRuleParam, FosnrRulesEnabledParam) - - override val fallbackActionBuilder: Option[ActionBuilder[_ <: Action]] = Some( - new ConstantActionBuilder(Avoid(Some(MightNotBeSuitableForAds)))) - } - - case class ViewerIsNonFollowerNonAuthorAndTweetHasViolationOfLevel( - violationLevel: ViolationLevel, - override val actionBuilder: ActionBuilder[_ <: Action]) - extends OnlyWhenNonAuthorViewerRule( - actionBuilder, - And( - Condition.TweetHasViolationOfLevel(violationLevel), - ViewerDoesNotFollowAuthorOfFosnrViolatingTweet) - ) { - override lazy val name: String = - s"ViewerIsNonFollowerNonAuthorAndTweetHasViolationOf$violationLevel" - - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableFosnrRuleParam, FosnrRulesEnabledParam) - - override val fallbackActionBuilder: Option[ActionBuilder[_ <: Action]] = Some( - new ConstantActionBuilder(Avoid(Some(MightNotBeSuitableForAds)))) - } - - case class ViewerIsNonAuthorAndTweetHasViolationOfLevel( - violationLevel: ViolationLevel, - override val actionBuilder: ActionBuilder[_ <: Action]) - extends OnlyWhenNonAuthorViewerRule( - actionBuilder, - Condition.TweetHasViolationOfLevel(violationLevel) - ) { - override lazy val name: String = - s"ViewerIsNonAuthorAndTweetHasViolationOf$violationLevel" - - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableFosnrRuleParam, FosnrRulesEnabledParam) - - override val fallbackActionBuilder: Option[ActionBuilder[_ <: Action]] = Some( - new ConstantActionBuilder(Avoid(Some(MightNotBeSuitableForAds)))) - } - - case object TweetHasViolationOfAnyLevelFallbackDropRule - extends RuleWithConstantAction( - Drop(reason = NotSupportedOnDevice), - Condition.TweetHasViolationOfAnyLevel - ) { - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableFosnrRuleParam, FosnrFallbackDropRulesEnabledParam) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/InterstitialIf.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/InterstitialIf.scala deleted file mode 100644 index 62785b251..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/InterstitialIf.scala +++ /dev/null @@ -1,43 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.visibility.rules.Condition.And -import com.twitter.visibility.rules.Condition.Not - -object InterstitialIf { - - object ViewerMutedKeyword - extends RuleWithConstantAction( - Interstitial(Reason.MutedKeyword), - And( - Not(Condition.IsFocalTweet), - Condition.ViewerHasMatchingKeywordForTweetReplies, - ) - ) - - object ViewerBlockedAuthor - extends RuleWithConstantAction( - Interstitial(Reason.ViewerBlocksAuthor), - And( - Not(Condition.IsFocalTweet), - Condition.ViewerBlocksAuthor - ) - ) - - object ViewerHardMutedAuthor - extends RuleWithConstantAction( - Interstitial(Reason.ViewerHardMutedAuthor), - And( - Not(Condition.IsFocalTweet), - Condition.ViewerMutesAuthor, - Not( - Condition.ViewerDoesFollowAuthor - ) - ) - ) - - object ViewerReportedAuthor - extends RuleWithConstantAction( - Interstitial(Reason.ViewerReportedAuthor), - Condition.ViewerReportsAuthor - ) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/PublicInterestRules.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/PublicInterestRules.scala deleted file mode 100644 index 047e349ae..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/PublicInterestRules.scala +++ /dev/null @@ -1,327 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.guano.commons.thriftscala.PolicyInViolation -import com.twitter.spam.rtf.thriftscala.SafetyResultReason -import com.twitter.util.Memoize -import com.twitter.util.Time -import com.twitter.visibility.common.actions.ComplianceTweetNoticeEventType -import com.twitter.visibility.common.actions.LimitedEngagementReason -import com.twitter.visibility.configapi.params.RuleParam -import com.twitter.visibility.configapi.params.RuleParams.EnableSearchIpiSafeSearchWithoutUserInQueryDropRule -import com.twitter.visibility.features.Feature -import com.twitter.visibility.features.TweetSafetyLabels -import com.twitter.visibility.models.TweetSafetyLabel -import com.twitter.visibility.models.TweetSafetyLabelType -import com.twitter.visibility.rules.Condition.And -import com.twitter.visibility.rules.Condition.LoggedOutOrViewerOptInFiltering -import com.twitter.visibility.rules.Condition.Not -import com.twitter.visibility.rules.Condition.Or -import com.twitter.visibility.rules.Condition.SearchQueryHasUser -import com.twitter.visibility.rules.Condition.TweetComposedAfter -import com.twitter.visibility.rules.Condition.TweetHasLabel -import com.twitter.visibility.rules.Reason._ -import com.twitter.visibility.rules.State.Evaluated - -object PublicInterest { - object PolicyConfig { - val LowQualityProxyLabelStart: Time = Time.fromMilliseconds(1554076800000L) - val DefaultReason: (Reason, Option[LimitedEngagementReason]) = - (OneOff, Some(LimitedEngagementReason.NonCompliant)) - val DefaultPolicyInViolation: PolicyInViolation = PolicyInViolation.OneOff - } - - val policyInViolationToReason: Map[PolicyInViolation, Reason] = Map( - PolicyInViolation.AbusePolicyEpisodic -> AbuseEpisodic, - PolicyInViolation.AbusePolicyEpisodicEncourageSelfharm -> AbuseEpisodicEncourageSelfHarm, - PolicyInViolation.AbusePolicyEpisodicHatefulConduct -> AbuseEpisodicHatefulConduct, - PolicyInViolation.AbusePolicyGratuitousGore -> AbuseGratuitousGore, - PolicyInViolation.AbusePolicyGlorificationofViolence -> AbuseGlorificationOfViolence, - PolicyInViolation.AbusePolicyEncourageMobHarassment -> AbuseMobHarassment, - PolicyInViolation.AbusePolicyMomentofDeathDeceasedUser -> AbuseMomentOfDeathOrDeceasedUser, - PolicyInViolation.AbusePolicyPrivateInformation -> AbusePrivateInformation, - PolicyInViolation.AbusePolicyRighttoPrivacy -> AbuseRightToPrivacy, - PolicyInViolation.AbusePolicyThreattoExpose -> AbuseThreatToExpose, - PolicyInViolation.AbusePolicyViolentSexualConduct -> AbuseViolentSexualConduct, - PolicyInViolation.AbusePolicyViolentThreatsHatefulConduct -> AbuseViolentThreatHatefulConduct, - PolicyInViolation.AbusePolicyViolentThreatorBounty -> AbuseViolentThreatOrBounty, - PolicyInViolation.OneOff -> OneOff, - PolicyInViolation.AbusePolicyElectionInterference -> VotingMisinformation, - PolicyInViolation.MisinformationVoting -> VotingMisinformation, - PolicyInViolation.HackedMaterials -> HackedMaterials, - PolicyInViolation.Scam -> Scams, - PolicyInViolation.PlatformManipulation -> PlatformManipulation, - PolicyInViolation.MisinformationCivic -> MisinfoCivic, - PolicyInViolation.AbusePolicyUkraineCrisisMisinformation -> MisinfoCrisis, - PolicyInViolation.MisinformationGeneric -> MisinfoGeneric, - PolicyInViolation.MisinformationMedical -> MisinfoMedical, - ) - - val reasonToPolicyInViolation: Map[Reason, PolicyInViolation] = Map( - AbuseEpisodic -> PolicyInViolation.AbusePolicyEpisodic, - AbuseEpisodicEncourageSelfHarm -> PolicyInViolation.AbusePolicyEpisodicEncourageSelfharm, - AbuseEpisodicHatefulConduct -> PolicyInViolation.AbusePolicyEpisodicHatefulConduct, - AbuseGratuitousGore -> PolicyInViolation.AbusePolicyGratuitousGore, - AbuseGlorificationOfViolence -> PolicyInViolation.AbusePolicyGlorificationofViolence, - AbuseMobHarassment -> PolicyInViolation.AbusePolicyEncourageMobHarassment, - AbuseMomentOfDeathOrDeceasedUser -> PolicyInViolation.AbusePolicyMomentofDeathDeceasedUser, - AbusePrivateInformation -> PolicyInViolation.AbusePolicyPrivateInformation, - AbuseRightToPrivacy -> PolicyInViolation.AbusePolicyRighttoPrivacy, - AbuseThreatToExpose -> PolicyInViolation.AbusePolicyThreattoExpose, - AbuseViolentSexualConduct -> PolicyInViolation.AbusePolicyViolentSexualConduct, - AbuseViolentThreatHatefulConduct -> PolicyInViolation.AbusePolicyViolentThreatsHatefulConduct, - AbuseViolentThreatOrBounty -> PolicyInViolation.AbusePolicyViolentThreatorBounty, - OneOff -> PolicyInViolation.OneOff, - VotingMisinformation -> PolicyInViolation.MisinformationVoting, - HackedMaterials -> PolicyInViolation.HackedMaterials, - Scams -> PolicyInViolation.Scam, - PlatformManipulation -> PolicyInViolation.PlatformManipulation, - MisinfoCivic -> PolicyInViolation.MisinformationCivic, - MisinfoCrisis -> PolicyInViolation.AbusePolicyUkraineCrisisMisinformation, - MisinfoGeneric -> PolicyInViolation.MisinformationGeneric, - MisinfoMedical -> PolicyInViolation.MisinformationMedical, - ) - - val ReasonToSafetyResultReason: Map[Reason, SafetyResultReason] = Map( - AbuseEpisodic -> SafetyResultReason.Episodic, - AbuseEpisodicEncourageSelfHarm -> SafetyResultReason.AbuseEpisodicEncourageSelfHarm, - AbuseEpisodicHatefulConduct -> SafetyResultReason.AbuseEpisodicHatefulConduct, - AbuseGratuitousGore -> SafetyResultReason.AbuseGratuitousGore, - AbuseGlorificationOfViolence -> SafetyResultReason.AbuseGlorificationOfViolence, - AbuseMobHarassment -> SafetyResultReason.AbuseMobHarassment, - AbuseMomentOfDeathOrDeceasedUser -> SafetyResultReason.AbuseMomentOfDeathOrDeceasedUser, - AbusePrivateInformation -> SafetyResultReason.AbusePrivateInformation, - AbuseRightToPrivacy -> SafetyResultReason.AbuseRightToPrivacy, - AbuseThreatToExpose -> SafetyResultReason.AbuseThreatToExpose, - AbuseViolentSexualConduct -> SafetyResultReason.AbuseViolentSexualConduct, - AbuseViolentThreatHatefulConduct -> SafetyResultReason.AbuseViolentThreatHatefulConduct, - AbuseViolentThreatOrBounty -> SafetyResultReason.AbuseViolentThreatOrBounty, - OneOff -> SafetyResultReason.OneOff, - VotingMisinformation -> SafetyResultReason.VotingMisinformation, - HackedMaterials -> SafetyResultReason.HackedMaterials, - Scams -> SafetyResultReason.Scams, - PlatformManipulation -> SafetyResultReason.PlatformManipulation, - MisinfoCivic -> SafetyResultReason.MisinfoCivic, - MisinfoCrisis -> SafetyResultReason.MisinfoCrisis, - MisinfoGeneric -> SafetyResultReason.MisinfoGeneric, - MisinfoMedical -> SafetyResultReason.MisinfoMedical, - IpiDevelopmentOnly -> SafetyResultReason.DevelopmentOnlyPublicInterest - ) - - val Reasons: Set[Reason] = ReasonToSafetyResultReason.keySet - val SafetyResultReasons: Set[SafetyResultReason] = ReasonToSafetyResultReason.values.toSet - - val SafetyResultReasonToReason: Map[SafetyResultReason, Reason] = - ReasonToSafetyResultReason.map(t => t._2 -> t._1) - - val EligibleTweetSafetyLabelTypes: Seq[TweetSafetyLabelType] = Seq( - TweetSafetyLabelType.LowQuality, - TweetSafetyLabelType.MisinfoCivic, - TweetSafetyLabelType.MisinfoGeneric, - TweetSafetyLabelType.MisinfoMedical, - TweetSafetyLabelType.MisinfoCrisis, - TweetSafetyLabelType.IpiDevelopmentOnly - ) - - private val EligibleTweetSafetyLabelTypesSet = EligibleTweetSafetyLabelTypes.toSet - - def extractTweetSafetyLabel(featureMap: Map[Feature[_], _]): Option[TweetSafetyLabel] = { - val tweetSafetyLabels = featureMap(TweetSafetyLabels) - .asInstanceOf[Seq[TweetSafetyLabel]] - .flatMap { tsl => - if (PublicInterest.EligibleTweetSafetyLabelTypesSet.contains(tsl.labelType)) { - Some(tsl.labelType -> tsl) - } else { - None - } - } - .toMap - - PublicInterest.EligibleTweetSafetyLabelTypes.flatMap(tweetSafetyLabels.get).headOption - } - - def policyToReason(policy: PolicyInViolation): Reason = - policyInViolationToReason.get(policy).getOrElse(PolicyConfig.DefaultReason._1) - - def reasonToPolicy(reason: Reason): PolicyInViolation = - reasonToPolicyInViolation.get(reason).getOrElse(PolicyConfig.DefaultPolicyInViolation) -} - -class PublicInterestActionBuilder[T <: Action]() extends ActionBuilder[T] { - def actionType: Class[_] = classOf[InterstitialLimitedEngagements] - - override val actionSeverity = 11 - def build(evaluationContext: EvaluationContext, featureMap: Map[Feature[_], _]): RuleResult = { - val (reason, limitedEngagementReason) = - PublicInterest.extractTweetSafetyLabel(featureMap).map { tweetSafetyLabel => - (tweetSafetyLabel.labelType, tweetSafetyLabel.source) - } match { - case Some((TweetSafetyLabelType.LowQuality, source)) => - source match { - case Some(source) => - SafetyResultReason.valueOf(source.name) match { - case Some(matchedReason) - if PublicInterest.SafetyResultReasonToReason.contains(matchedReason) => - ( - PublicInterest.SafetyResultReasonToReason(matchedReason), - Some(LimitedEngagementReason.NonCompliant)) - case _ => PublicInterest.PolicyConfig.DefaultReason - } - case _ => PublicInterest.PolicyConfig.DefaultReason - } - - - case Some((TweetSafetyLabelType.MisinfoCivic, source)) => - (Reason.MisinfoCivic, LimitedEngagementReason.fromString(source.map(_.name))) - - case Some((TweetSafetyLabelType.MisinfoCrisis, source)) => - (Reason.MisinfoCrisis, LimitedEngagementReason.fromString(source.map(_.name))) - - case Some((TweetSafetyLabelType.MisinfoGeneric, source)) => - (Reason.MisinfoGeneric, LimitedEngagementReason.fromString(source.map(_.name))) - - case Some((TweetSafetyLabelType.MisinfoMedical, source)) => - (Reason.MisinfoMedical, LimitedEngagementReason.fromString(source.map(_.name))) - - case Some((TweetSafetyLabelType.IpiDevelopmentOnly, _)) => - (Reason.IpiDevelopmentOnly, Some(LimitedEngagementReason.NonCompliant)) - - case _ => - PublicInterest.PolicyConfig.DefaultReason - } - - RuleResult(InterstitialLimitedEngagements(reason, limitedEngagementReason), Evaluated) - } -} - -class PublicInterestComplianceTweetNoticeActionBuilder - extends ActionBuilder[ComplianceTweetNoticePreEnrichment] { - - override def actionType: Class[_] = classOf[ComplianceTweetNoticePreEnrichment] - - override val actionSeverity = 2 - def build(evaluationContext: EvaluationContext, featureMap: Map[Feature[_], _]): RuleResult = { - val reason = - PublicInterest.extractTweetSafetyLabel(featureMap).map { tweetSafetyLabel => - (tweetSafetyLabel.labelType, tweetSafetyLabel.source) - } match { - case Some((TweetSafetyLabelType.LowQuality, source)) => - source match { - case Some(source) => - SafetyResultReason.valueOf(source.name) match { - case Some(matchedReason) - if PublicInterest.SafetyResultReasonToReason.contains(matchedReason) => - PublicInterest.SafetyResultReasonToReason(matchedReason) - case _ => PublicInterest.PolicyConfig.DefaultReason._1 - } - case _ => PublicInterest.PolicyConfig.DefaultReason._1 - } - - - case Some((TweetSafetyLabelType.MisinfoCivic, _)) => - Reason.MisinfoCivic - - case Some((TweetSafetyLabelType.MisinfoCrisis, _)) => - Reason.MisinfoCrisis - - case Some((TweetSafetyLabelType.MisinfoGeneric, _)) => - Reason.MisinfoGeneric - - case Some((TweetSafetyLabelType.MisinfoMedical, _)) => - Reason.MisinfoMedical - - case Some((TweetSafetyLabelType.IpiDevelopmentOnly, _)) => - Reason.IpiDevelopmentOnly - - case _ => - PublicInterest.PolicyConfig.DefaultReason._1 - } - - RuleResult( - ComplianceTweetNoticePreEnrichment(reason, ComplianceTweetNoticeEventType.PublicInterest), - Evaluated) - } -} - -class PublicInterestDropActionBuilder extends ActionBuilder[Drop] { - - override def actionType: Class[_] = classOf[Drop] - - override val actionSeverity = 16 - private def toRuleResult: Reason => RuleResult = Memoize { r => RuleResult(Drop(r), Evaluated) } - - def build(evaluationContext: EvaluationContext, featureMap: Map[Feature[_], _]): RuleResult = { - val reason = PublicInterest.extractTweetSafetyLabel(featureMap).map(_.labelType) match { - case Some(TweetSafetyLabelType.LowQuality) => - Reason.OneOff - - case Some(TweetSafetyLabelType.MisinfoCivic) => - Reason.MisinfoCivic - - case Some(TweetSafetyLabelType.MisinfoCrisis) => - Reason.MisinfoCrisis - - case Some(TweetSafetyLabelType.MisinfoGeneric) => - Reason.MisinfoGeneric - - case Some(TweetSafetyLabelType.MisinfoMedical) => - Reason.MisinfoMedical - - case _ => - Reason.OneOff - } - - toRuleResult(reason) - } -} - -object PublicInterestRules { - - object AbusePolicyEpisodicTweetLabelInterstitialRule - extends Rule( - new PublicInterestActionBuilder(), - And( - TweetComposedAfter(PublicInterest.PolicyConfig.LowQualityProxyLabelStart), - Or( - PublicInterest.EligibleTweetSafetyLabelTypes.map(TweetHasLabel(_)): _* - ) - ) - ) - - object AbusePolicyEpisodicTweetLabelComplianceTweetNoticeRule - extends Rule( - new PublicInterestComplianceTweetNoticeActionBuilder(), - And( - TweetComposedAfter(PublicInterest.PolicyConfig.LowQualityProxyLabelStart), - Or( - PublicInterest.EligibleTweetSafetyLabelTypes.map(TweetHasLabel(_)): _* - ) - ) - ) - - object AbusePolicyEpisodicTweetLabelDropRule - extends Rule( - new PublicInterestDropActionBuilder(), - And( - TweetComposedAfter(PublicInterest.PolicyConfig.LowQualityProxyLabelStart), - Or( - PublicInterest.EligibleTweetSafetyLabelTypes.map(TweetHasLabel(_)): _* - ) - ) - ) - - object SearchIpiSafeSearchWithoutUserInQueryDropRule - extends Rule( - new PublicInterestDropActionBuilder(), - And( - TweetComposedAfter(PublicInterest.PolicyConfig.LowQualityProxyLabelStart), - Or( - PublicInterest.EligibleTweetSafetyLabelTypes.map(TweetHasLabel(_)): _* - ), - LoggedOutOrViewerOptInFiltering, - Not(SearchQueryHasUser) - ) - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq( - EnableSearchIpiSafeSearchWithoutUserInQueryDropRule) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/Rule.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/Rule.scala deleted file mode 100644 index ab1c21e13..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/Rule.scala +++ /dev/null @@ -1,215 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.abdecider.LoggingABDecider -import com.twitter.timelines.configapi.HasParams.DependencyProvider -import com.twitter.timelines.configapi.Params -import com.twitter.visibility.configapi.params.RuleParam -import com.twitter.visibility.configapi.params.RuleParams -import com.twitter.visibility.configapi.params.RuleParams.EnableLikelyIvsUserLabelDropRule -import com.twitter.visibility.features._ -import com.twitter.visibility.models.UserLabelValue -import com.twitter.visibility.models.UserLabelValue.LikelyIvs -import com.twitter.visibility.rules.Condition._ -import com.twitter.visibility.rules.Reason.Unspecified -import com.twitter.visibility.rules.RuleActionSourceBuilder.UserSafetyLabelSourceBuilder -import com.twitter.visibility.rules.State._ -import com.twitter.visibility.util.NamingUtils - -trait WithGate { - def enabled: Seq[RuleParam[Boolean]] = Seq(RuleParams.True) - - def isEnabled(params: Params): Boolean = - enabled.forall(enabledParam => params(enabledParam)) - - def holdbacks: Seq[RuleParam[Boolean]] = Seq(RuleParams.False) - - final def shouldHoldback: DependencyProvider[Boolean] = - holdbacks.foldLeft(DependencyProvider.from(RuleParams.False)) { (dp, holdbackParam) => - dp.or(DependencyProvider.from(holdbackParam)) - } - - protected def enableFailClosed: Seq[RuleParam[Boolean]] = Seq(RuleParams.False) - def shouldFailClosed(params: Params): Boolean = - enableFailClosed.forall(fcParam => params(fcParam)) -} - -abstract class ActionBuilder[T <: Action] { - def actionType: Class[_] - - val actionSeverity: Int - def build(evaluationContext: EvaluationContext, featureMap: Map[Feature[_], _]): RuleResult -} - -object ActionBuilder { - def apply[T <: Action](action: T): ActionBuilder[T] = action match { - case _: InterstitialLimitedEngagements => new PublicInterestActionBuilder() - case _ => new ConstantActionBuilder(action) - } -} - -class ConstantActionBuilder[T <: Action](action: T) extends ActionBuilder[T] { - private val result = RuleResult(action, Evaluated) - - def actionType: Class[_] = action.getClass - - override val actionSeverity = action.severity - def build(evaluationContext: EvaluationContext, featureMap: Map[Feature[_], _]): RuleResult = - result -} - -object ConstantActionBuilder { - def unapply[T <: Action](builder: ConstantActionBuilder[T]): Option[Action] = Some( - builder.result.action) -} - -abstract class Rule(val actionBuilder: ActionBuilder[_ <: Action], val condition: Condition) - extends WithGate { - - import Rule._ - def isExperimental: Boolean = false - - def actionSourceBuilder: Option[RuleActionSourceBuilder] = None - - lazy val name: String = NamingUtils.getFriendlyName(this) - - val featureDependencies: Set[Feature[_]] = condition.features - - val optionalFeatureDependencies: Set[Feature[_]] = condition.optionalFeatures - - def preFilter( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], Any], - abDecider: LoggingABDecider - ): PreFilterResult = - condition.preFilter(evaluationContext, featureMap) - - def actWhen(evaluationContext: EvaluationContext, featureMap: Map[Feature[_], _]): Boolean = - condition(evaluationContext, featureMap).asBoolean - - val fallbackActionBuilder: Option[ActionBuilder[_ <: Action]] = None - - final def evaluate( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], _] - ): RuleResult = { - val missingFeatures = featureDependencies.filterNot(featureMap.contains) - - if (missingFeatures.nonEmpty) { - fallbackActionBuilder match { - case Some(fallbackAction) => - fallbackAction.build(evaluationContext, featureMap) - case None => - RuleResult(NotEvaluated, MissingFeature(missingFeatures)) - } - } else { - try { - val act = actWhen(evaluationContext, featureMap) - if (!act) { - EvaluatedRuleResult - } else if (shouldHoldback(evaluationContext)) { - - HeldbackRuleResult - } else { - actionBuilder.build(evaluationContext, featureMap) - } - } catch { - case t: Throwable => - RuleResult(NotEvaluated, RuleFailed(t)) - } - } - } -} - -trait ExperimentalRule extends Rule { - override def isExperimental: Boolean = true -} - -object Rule { - - val HeldbackRuleResult: RuleResult = RuleResult(Allow, Heldback) - val EvaluatedRuleResult: RuleResult = RuleResult(Allow, Evaluated) - val DisabledRuleResult: RuleResult = RuleResult(NotEvaluated, Disabled) - - def unapply(rule: Rule): Option[(ActionBuilder[_ <: Action], Condition)] = - Some((rule.actionBuilder, rule.condition)) -} - -abstract class RuleWithConstantAction(val action: Action, override val condition: Condition) - extends Rule(ActionBuilder(action), condition) - -abstract class UserHasLabelRule(action: Action, userLabelValue: UserLabelValue) - extends RuleWithConstantAction(action, AuthorHasLabel(userLabelValue)) { - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - UserSafetyLabelSourceBuilder(userLabelValue)) -} - -abstract class ConditionWithUserLabelRule( - action: Action, - condition: Condition, - userLabelValue: UserLabelValue) - extends Rule( - ActionBuilder(action), - And(NonAuthorViewer, AuthorHasLabel(userLabelValue), condition)) { - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - UserSafetyLabelSourceBuilder(userLabelValue)) -} - -abstract class WhenAuthorUserLabelPresentRule(action: Action, userLabelValue: UserLabelValue) - extends ConditionWithUserLabelRule(action, Condition.True, userLabelValue) - -abstract class ConditionWithNotInnerCircleOfFriendsRule( - action: Action, - condition: Condition) - extends RuleWithConstantAction( - action, - And(Not(DoesHaveInnerCircleOfFriendsRelationship), condition)) - -abstract class AuthorLabelWithNotInnerCircleOfFriendsRule( - action: Action, - userLabelValue: UserLabelValue) - extends ConditionWithNotInnerCircleOfFriendsRule( - action, - AuthorHasLabel(userLabelValue) - ) { - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - UserSafetyLabelSourceBuilder(userLabelValue)) -} - -abstract class OnlyWhenNotAuthorViewerRule(action: Action, condition: Condition) - extends RuleWithConstantAction(action, And(NonAuthorViewer, condition)) - -abstract class AuthorLabelAndNonFollowerViewerRule(action: Action, userLabelValue: UserLabelValue) - extends ConditionWithUserLabelRule(action, LoggedOutOrViewerNotFollowingAuthor, userLabelValue) - -abstract class AlwaysActRule(action: Action) extends Rule(ActionBuilder(action), Condition.True) - -abstract class ViewerOptInBlockingOnSearchRule(action: Action, condition: Condition) - extends OnlyWhenNotAuthorViewerRule( - action, - And(condition, ViewerOptInBlockingOnSearch) - ) - -abstract class ViewerOptInFilteringOnSearchRule(action: Action, condition: Condition) - extends OnlyWhenNotAuthorViewerRule( - action, - And(condition, ViewerOptInFilteringOnSearch) - ) - -abstract class ViewerOptInFilteringOnSearchUserLabelRule( - action: Action, - userLabelValue: UserLabelValue, - prerequisiteCondition: Condition = True) - extends ConditionWithUserLabelRule( - action, - And(prerequisiteCondition, LoggedOutOrViewerOptInFiltering), - userLabelValue - ) - -abstract class LikelyIvsLabelNonFollowerDropRule - extends AuthorLabelAndNonFollowerViewerRule( - Drop(Unspecified), - LikelyIvs - ) { - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableLikelyIvsUserLabelDropRule) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/RuleActionSourceBuilder.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/RuleActionSourceBuilder.scala deleted file mode 100644 index 72d54c677..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/RuleActionSourceBuilder.scala +++ /dev/null @@ -1,97 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.escherbird.thriftscala.TweetEntityAnnotation -import com.twitter.gizmoduck.thriftscala.Label -import com.twitter.spam.rtf.thriftscala.BotMakerAction -import com.twitter.spam.rtf.thriftscala.SafetyLabelSource -import com.twitter.spam.rtf.thriftscala.SemanticCoreAction -import com.twitter.visibility.common.actions.EscherbirdAnnotation -import com.twitter.visibility.common.actions.SoftInterventionReason -import com.twitter.visibility.configapi.configs.DeciderKey -import com.twitter.visibility.features.AuthorUserLabels -import com.twitter.visibility.features.Feature -import com.twitter.visibility.features.TweetSafetyLabels -import com.twitter.visibility.logging.thriftscala.ActionSource -import com.twitter.visibility.models.LabelSource._ -import com.twitter.visibility.models.TweetSafetyLabel -import com.twitter.visibility.models.TweetSafetyLabelType -import com.twitter.visibility.models.UserLabel -import com.twitter.visibility.models.UserLabelValue - -sealed trait RuleActionSourceBuilder { - def build(resolvedFeatureMap: Map[Feature[_], Any], verdict: Action): Option[ActionSource] - -} - -object RuleActionSourceBuilder { - - case class TweetSafetyLabelSourceBuilder(tweetSafetyLabelType: TweetSafetyLabelType) - extends RuleActionSourceBuilder { - override def build( - resolvedFeatureMap: Map[Feature[_], Any], - verdict: Action - ): Option[ActionSource] = { - resolvedFeatureMap - .getOrElse(TweetSafetyLabels, Seq.empty[TweetSafetyLabel]) - .asInstanceOf[Seq[TweetSafetyLabel]] - .find(_.labelType == tweetSafetyLabelType) - .flatMap(_.safetyLabelSource) - .map(ActionSource.SafetyLabelSource(_)) - } - } - - case class UserSafetyLabelSourceBuilder(userLabel: UserLabelValue) - extends RuleActionSourceBuilder { - override def build( - resolvedFeatureMap: Map[Feature[_], Any], - verdict: Action - ): Option[ActionSource] = { - resolvedFeatureMap - .getOrElse(AuthorUserLabels, Seq.empty[Label]) - .asInstanceOf[Seq[Label]] - .map(UserLabel.fromThrift) - .find(_.labelValue == userLabel) - .flatMap(_.source) - .collect { - case BotMakerRule(ruleId) => - ActionSource.SafetyLabelSource(SafetyLabelSource.BotMakerAction(BotMakerAction(ruleId))) - } - } - } - - case class SemanticCoreActionSourceBuilder() extends RuleActionSourceBuilder { - override def build( - resolvedFeatureMap: Map[Feature[_], Any], - verdict: Action - ): Option[ActionSource] = { - verdict match { - case softIntervention: SoftIntervention => - getSemanticCoreActionSourceOption(softIntervention) - case tweetInterstitial: TweetInterstitial => - tweetInterstitial.softIntervention.flatMap(getSemanticCoreActionSourceOption) - case _ => None - } - } - - def getSemanticCoreActionSourceOption( - softIntervention: SoftIntervention - ): Option[ActionSource] = { - val siReason = softIntervention.reason - .asInstanceOf[SoftInterventionReason.EscherbirdAnnotations] - val firstAnnotation: Option[EscherbirdAnnotation] = - siReason.escherbirdAnnotations.headOption - - firstAnnotation.map { annotation => - ActionSource.SafetyLabelSource( - SafetyLabelSource.SemanticCoreAction(SemanticCoreAction( - TweetEntityAnnotation(annotation.groupId, annotation.domainId, annotation.entityId)))) - } - } - } -} - -trait DoesLogVerdict {} - -trait DoesLogVerdictDecidered extends DoesLogVerdict { - def verdictLogDeciderKey: DeciderKey.Value -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/RuleBase.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/RuleBase.scala deleted file mode 100644 index e4b99a259..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/RuleBase.scala +++ /dev/null @@ -1,239 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.visibility.features.AuthorScreenName -import com.twitter.visibility.features.Feature -import com.twitter.visibility.features.FeatureMap -import com.twitter.visibility.features.RawQuery -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.SafetyLevel._ - -object RuleBase { - - val DeprecatedFeatures: Seq[Feature[_]] = - Seq(AuthorScreenName, RawQuery) - - val RuleMap: Map[SafetyLevel, VisibilityPolicy] = Map( - AccessInternalPromotedContent -> InternalPromotedContentPolicy, - AllSubscribedLists -> AllSubscribedListsPolicy, - AdsBusinessSettings -> AdsBusinessSettingsPolicy, - AdsCampaign -> AdsCampaignPolicy, - AdsManager -> AdsManagerPolicy, - AdsReportingDashboard -> AdsReportingDashboardPolicy, - Appeals -> AppealsPolicy, - ArticleTweetTimeline -> ArticleTweetTimelinePolicy, - BaseQig -> BaseQigPolicy, - BirdwatchNoteAuthor -> BirdwatchNoteAuthorPolicy, - BirdwatchNoteTweetsTimeline -> BirdwatchNoteTweetsTimelinePolicy, - BirdwatchNeedsYourHelpNotifications -> BirdwatchNeedsYourHelpNotificationsPolicy, - BlockMuteUsersTimeline -> BlockMuteUsersTimelinePolicy, - BrandSafety -> BrandSafetyPolicy, - CardPollVoting -> CardPollVotingPolicy, - CardsService -> CardsServicePolicy, - Communities -> CommunitiesPolicy, - ContentControlToolInstall -> ContentControlToolInstallPolicy, - ConversationFocalPrehydration -> ConversationFocalPrehydrationPolicy, - ConversationFocalTweet -> ConversationFocalTweetPolicy, - ConversationInjectedTweet -> ConversationInjectedTweetPolicy, - ConversationReply -> ConversationReplyPolicy, - CuratedTrendsRepresentativeTweet -> CuratedTrendsRepresentativeTweetPolicy, - CurationPolicyViolations -> CurationPolicyViolationsPolicy, - FollowingAndFollowersUserList -> FollowingAndFollowersUserListPolicy, - DeprecatedSafetyLevel -> FilterNonePolicy, - DevPlatformGetListTweets -> DevPlatformGetListTweetsPolicy, - DesFollowingAndFollowersUserList -> FollowingAndFollowersUserListPolicy, - DesHomeTimeline -> DESHomeTimelinePolicy, - DesQuoteTweetTimeline -> DesQuoteTweetTimelinePolicy, - DesRealtime -> DESRealtimePolicy, - DesRealtimeSpamEnrichment -> DESRealtimeSpamEnrichmentPolicy, - DesRealtimeTweetFilter -> DESRealtimeSpamEnrichmentPolicy, - DesRetweetingUsers -> DESRetweetingUsersPolicy, - DesTweetDetail -> DesTweetDetailPolicy, - DesTweetLikingUsers -> DESTweetLikingUsersPolicy, - DesUserBookmarks -> DESUserBookmarksPolicy, - DesUserLikedTweets -> DESUserLikedTweetsPolicy, - DesUserMentions -> DESUserMentionsPolicy, - DesUserTweets -> DESUserTweetsPolicy, - DevPlatformComplianceStream -> DevPlatformComplianceStreamPolicy, - DirectMessages -> DirectMessagesPolicy, - DirectMessagesConversationList -> DirectMessagesConversationListPolicy, - DirectMessagesConversationTimeline -> DirectMessagesConversationTimelinePolicy, - DirectMessagesInbox -> DirectMessagesInboxPolicy, - DirectMessagesMutedUsers -> DirectMessagesMutedUsersPolicy, - DirectMessagesPinned -> DirectMessagesPinnedPolicy, - DirectMessagesSearch -> DirectMessagesSearchPolicy, - EditHistoryTimeline -> EditHistoryTimelinePolicy, - ElevatedQuoteTweetTimeline -> ElevatedQuoteTweetTimelinePolicy, - EmbeddedTweet -> EmbeddedTweetsPolicy, - EmbedsPublicInterestNotice -> EmbedsPublicInterestNoticePolicy, - EmbedTweetMarkup -> EmbedTweetMarkupPolicy, - WritePathLimitedActionsEnforcement -> WritePathLimitedActionsEnforcementPolicy, - FilterAll -> FilterAllPolicy, - FilterAllPlaceholder -> FilterAllPolicy, - FilterNone -> FilterNonePolicy, - FilterDefault -> FilterDefaultPolicy, - FollowedTopicsTimeline -> FollowedTopicsTimelinePolicy, - FollowerConnections -> FollowerConnectionsPolicy, - ForDevelopmentOnly -> ForDevelopmentOnlyPolicy, - FriendsFollowingList -> FriendsFollowingListPolicy, - GraphqlDefault -> GraphqlDefaultPolicy, - GryphonDecksAndColumns -> GryphonDecksAndColumnsSharingPolicy, - HumanizationNudge -> HumanizationNudgePolicy, - KitchenSinkDevelopment -> KitchenSinkDevelopmentPolicy, - ListHeader -> ListHeaderPolicy, - ListMemberships -> ListMembershipsPolicy, - ListOwnerships -> ListOwnershipsPolicy, - ListRecommendations -> ListRecommendationsPolicy, - ListSearch -> ListSearchPolicy, - ListSubscriptions -> ListSubscriptionsPolicy, - LivePipelineEngagementCounts -> LivePipelineEngagementCountsPolicy, - LiveVideoTimeline -> LiveVideoTimelinePolicy, - MagicRecs -> MagicRecsPolicy, - MagicRecsAggressive -> MagicRecsAggressivePolicy, - MagicRecsAggressiveV2 -> MagicRecsAggressiveV2Policy, - MagicRecsV2 -> MagicRecsV2Policy, - Minimal -> MinimalPolicy, - ModeratedTweetsTimeline -> ModeratedTweetsTimelinePolicy, - Moments -> MomentsPolicy, - NearbyTimeline -> NearbyTimelinePolicy, - NewUserExperience -> NewUserExperiencePolicy, - NotificationsIbis -> NotificationsIbisPolicy, - NotificationsPlatform -> NotificationsPlatformPolicy, - NotificationsPlatformPush -> NotificationsPlatformPushPolicy, - NotificationsQig -> NotificationsQigPolicy, - NotificationsRead -> NotificationsReadPolicy, - NotificationsTimelineDeviceFollow -> NotificationsTimelineDeviceFollowPolicy, - NotificationsWrite -> NotificationsWritePolicy, - NotificationsWriterV2 -> NotificationsWriterV2Policy, - NotificationsWriterTweetHydrator -> NotificationsWriterTweetHydratorPolicy, - ProfileMixerMedia -> ProfileMixerMediaPolicy, - ProfileMixerFavorites -> ProfileMixerFavoritesPolicy, - QuickPromoteTweetEligibility -> QuickPromoteTweetEligibilityPolicy, - QuoteTweetTimeline -> QuoteTweetTimelinePolicy, - QuotedTweetRules -> QuotedTweetRulesPolicy, - Recommendations -> RecommendationsPolicy, - RecosVideo -> RecosVideoPolicy, - RecosWritePath -> RecosWritePathPolicy, - RepliesGrouping -> RepliesGroupingPolicy, - ReportCenter -> ReportCenterPolicy, - ReturningUserExperience -> ReturningUserExperiencePolicy, - ReturningUserExperienceFocalTweet -> ReturningUserExperienceFocalTweetPolicy, - Revenue -> RevenuePolicy, - RitoActionedTweetTimeline -> RitoActionedTweetTimelinePolicy, - SearchHydration -> SearchHydrationPolicy, - SearchMixerSrpMinimal -> SearchMixerSrpMinimalPolicy, - SearchMixerSrpStrict -> SearchMixerSrpStrictPolicy, - SearchLatest -> SearchLatestPolicy, - SearchPeopleSrp -> SearchPeopleSrpPolicy, - SearchPeopleTypeahead -> SearchPeopleTypeaheadPolicy, - SearchPhoto -> SearchPhotoPolicy, - SearchTrendTakeoverPromotedTweet -> SearchTrendTakeoverPromotedTweetPolicy, - SearchTop -> SearchTopPolicy, - SearchTopQig -> SearchTopQigPolicy, - SearchVideo -> SearchVideoPolicy, - SearchBlenderUserRules -> SearchBlenderUserRulesPolicy, - SearchLatestUserRules -> SearchLatestUserRulesPolicy, - ShoppingManagerSpyMode -> ShoppingManagerSpyModePolicy, - SignalsReactions -> SignalsReactionsPolicy, - SignalsTweetReactingUsers -> SignalsTweetReactingUsersPolicy, - SocialProof -> SocialProofPolicy, - SoftInterventionPivot -> SoftInterventionPivotPolicy, - SpaceFleetline -> SpaceFleetlinePolicy, - SpaceHomeTimelineUpranking -> SpaceHomeTimelineUprankingPolicy, - SpaceJoinScreen -> SpaceJoinScreenPolicy, - SpaceNotifications -> SpaceNotificationsPolicy, - Spaces -> SpacesPolicy, - SpacesParticipants -> SpacesParticipantsPolicy, - SpacesSellerApplicationStatus -> SpacesSellerApplicationStatusPolicy, - SpacesSharing -> SpacesSharingPolicy, - SpaceTweetAvatarHomeTimeline -> SpaceTweetAvatarHomeTimelinePolicy, - StickersTimeline -> StickersTimelinePolicy, - StratoExtLimitedEngagements -> StratoExtLimitedEngagementsPolicy, - StreamServices -> StreamServicesPolicy, - SuperFollowerConnections -> SuperFollowerConnectionsPolicy, - SuperLike -> SuperLikePolicy, - Test -> TestPolicy, - TimelineContentControls -> TimelineContentControlsPolicy, - TimelineConversations -> TimelineConversationsPolicy, - TimelineConversationsDownranking -> TimelineConversationsDownrankingPolicy, - TimelineConversationsDownrankingMinimal -> TimelineConversationsDownrankingMinimalPolicy, - TimelineFollowingActivity -> TimelineFollowingActivityPolicy, - TimelineHome -> TimelineHomePolicy, - TimelineHomeCommunities -> TimelineHomeCommunitiesPolicy, - TimelineHomeHydration -> TimelineHomeHydrationPolicy, - TimelineHomePromotedHydration -> TimelineHomePromotedHydrationPolicy, - TimelineHomeRecommendations -> TimelineHomeRecommendationsPolicy, - TimelineHomeTopicFollowRecommendations -> TimelineHomeTopicFollowRecommendationsPolicy, - TimelineScorer -> TimelineScorerPolicy, - TopicsLandingPageTopicRecommendations -> TopicsLandingPageTopicRecommendationsPolicy, - ExploreRecommendations -> ExploreRecommendationsPolicy, - TimelineInjection -> TimelineInjectionPolicy, - TimelineMentions -> TimelineMentionsPolicy, - TimelineModeratedTweetsHydration -> TimelineModeratedTweetsHydrationPolicy, - TimelineHomeLatest -> TimelineHomeLatestPolicy, - TimelineLikedBy -> TimelineLikedByPolicy, - TimelineRetweetedBy -> TimelineRetweetedByPolicy, - TimelineSuperLikedBy -> TimelineSuperLikedByPolicy, - TimelineBookmark -> TimelineBookmarkPolicy, - TimelineMedia -> TimelineMediaPolicy, - TimelineReactiveBlending -> TimelineReactiveBlendingPolicy, - TimelineFavorites -> TimelineFavoritesPolicy, - TimelineFavoritesSelfView -> TimelineFavoritesSelfViewPolicy, - TimelineLists -> TimelineListsPolicy, - TimelineProfile -> TimelineProfilePolicy, - TimelineProfileAll -> TimelineProfileAllPolicy, - TimelineProfileSpaces -> TimelineProfileSpacesPolicy, - TimelineProfileSuperFollows -> TimelineProfileSuperFollowsPolicy, - TimelineFocalTweet -> TimelineFocalTweetPolicy, - Tombstoning -> TombstoningPolicy, - TopicRecommendations -> TopicRecommendationsPolicy, - TrendsRepresentativeTweet -> TrendsRepresentativeTweetPolicy, - TrustedFriendsUserList -> TrustedFriendsUserListPolicy, - TwitterDelegateUserList -> TwitterDelegateUserListPolicy, - TweetDetail -> TweetDetailPolicy, - TweetDetailNonToo -> TweetDetailNonTooPolicy, - TweetDetailWithInjectionsHydration -> TweetDetailWithInjectionsHydrationPolicy, - TweetEngagers -> TweetEngagersPolicy, - TweetReplyNudge -> TweetReplyNudgePolicy, - TweetScopedTimeline -> TweetScopedTimelinePolicy, - TweetWritesApi -> TweetWritesApiPolicy, - TwitterArticleCompose -> TwitterArticleComposePolicy, - TwitterArticleProfileTab -> TwitterArticleProfileTabPolicy, - TwitterArticleRead -> TwitterArticleReadPolicy, - UserMilestoneRecommendation -> UserMilestoneRecommendationPolicy, - UserProfileHeader -> UserProfileHeaderPolicy, - UserScopedTimeline -> UserScopedTimelinePolicy, - UserSearchSrp -> UserSearchSrpPolicy, - UserSearchTypeahead -> UserSearchTypeaheadPolicy, - UserSelfViewOnly -> UserSelfViewOnlyPolicy, - UserSettings -> UserSettingsPolicy, - VideoAds -> VideoAdsPolicy, - ZipbirdConsumerArchives -> ZipbirdConsumerArchivesPolicy, - TweetAward -> TweetAwardPolicy, - ) - - def removeUnusedFeaturesFromFeatureMap( - featureMap: FeatureMap, - rules: Seq[Rule], - ): FeatureMap = { - val featuresInSafetyLevel: Set[Feature[_]] = - RuleBase.getFeaturesForRules(rules) - val filteredMap = featureMap.map.filterKeys(featuresInSafetyLevel.contains(_)) - - new FeatureMap(filteredMap, featureMap.constantMap) - } - - def getFeaturesForRules(rules: Seq[Rule]): Set[Feature[_]] = { - rules.flatMap { r: Rule => - r.featureDependencies ++ r.optionalFeatureDependencies - }.toSet - } - - def hasTweetRules(safetyLevel: SafetyLevel): Boolean = RuleMap(safetyLevel).tweetRules.nonEmpty - def hasUserRules(safetyLevel: SafetyLevel): Boolean = RuleMap(safetyLevel).userRules.nonEmpty - def hasCardRules(safetyLevel: SafetyLevel): Boolean = RuleMap(safetyLevel).cardRules.nonEmpty - def hasDmRules(safetyLevel: SafetyLevel): Boolean = RuleMap(safetyLevel).dmRules.nonEmpty - def hasDmConversationRules(safetyLevel: SafetyLevel): Boolean = RuleMap( - safetyLevel).dmConversationRules.nonEmpty - def hasDmEventRules(safetyLevel: SafetyLevel): Boolean = RuleMap( - safetyLevel).dmEventRules.nonEmpty -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/Rules.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/Rules.scala deleted file mode 100644 index 9e8fa1c38..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/Rules.scala +++ /dev/null @@ -1,315 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.visibility.configapi.params.RuleParam -import com.twitter.visibility.configapi.params.RuleParams -import com.twitter.visibility.configapi.params.RuleParams.EnableAuthorBlocksViewerDropRuleParam -import com.twitter.visibility.configapi.params.RuleParams.EnableInnerQuotedTweetViewerBlocksAuthorInterstitialRuleParam -import com.twitter.visibility.configapi.params.RuleParams.EnableInnerQuotedTweetViewerMutesAuthorInterstitialRuleParam -import com.twitter.visibility.configapi.params.RuleParams.EnableTimelineHomePromotedTweetHealthEnforcementRules -import com.twitter.visibility.configapi.params.RuleParams.EnableViewerIsSoftUserDropRuleParam -import com.twitter.visibility.configapi.params.RuleParams.PromotedTweetHealthEnforcementHoldback -import com.twitter.visibility.rules.Condition.And -import com.twitter.visibility.rules.Condition.IsQuotedInnerTweet -import com.twitter.visibility.rules.Condition.NonAuthorViewer -import com.twitter.visibility.rules.Condition.Not -import com.twitter.visibility.rules.Condition.Retweet -import com.twitter.visibility.rules.Condition.SoftViewer -import com.twitter.visibility.rules.Reason._ - -object DropAllRule - extends AlwaysActRule( - Drop(Unspecified) - ) - -object AllowAllRule - extends AlwaysActRule( - Allow - ) - -object TestRule - extends AlwaysActRule( - Drop(Unspecified) - ) - -object DeactivatedAuthorRule - extends OnlyWhenNotAuthorViewerRule( - Drop(DeactivatedAuthor), - Condition.DeactivatedAuthor - ) - -object ErasedAuthorRule - extends OnlyWhenNotAuthorViewerRule( - Drop(ErasedAuthor), - Condition.ErasedAuthor - ) - -object OffboardedAuthorRule - extends OnlyWhenNotAuthorViewerRule( - Drop(OffboardedAuthor), - Condition.OffboardedAuthor - ) - -object DropNsfwUserAuthorRule - extends OnlyWhenNotAuthorViewerRule( - Drop(Nsfw), - Condition.NsfwUserAuthor - ) - -object DropNsfwUserAuthorViewerOptInFilteringOnSearchRule - extends ViewerOptInFilteringOnSearchRule( - Drop(Nsfw), - Condition.NsfwUserAuthor - ) - -object InterstitialNsfwUserAuthorRule - extends OnlyWhenNotAuthorViewerRule( - Interstitial(Nsfw), - Condition.NsfwUserAuthor - ) - -object DropNsfwAdminAuthorRule - extends OnlyWhenNotAuthorViewerRule( - Drop(Nsfw), - Condition.NsfwAdminAuthor - ) - -object DropNsfwAdminAuthorViewerOptInFilteringOnSearchRule - extends ViewerOptInFilteringOnSearchRule( - Drop(Nsfw), - Condition.NsfwAdminAuthor - ) - -object InterstitialNsfwAdminAuthorRule - extends OnlyWhenNotAuthorViewerRule( - Interstitial(Nsfw), - Condition.NsfwAdminAuthor - ) - -object ProtectedAuthorDropRule - extends RuleWithConstantAction( - Drop(Reason.ProtectedAuthor), - And(Condition.LoggedOutOrViewerNotFollowingAuthor, Condition.ProtectedAuthor) - ) - -object ProtectedAuthorTombstoneRule - extends RuleWithConstantAction( - Tombstone(Epitaph.Protected), - And(Condition.LoggedOutOrViewerNotFollowingAuthor, Condition.ProtectedAuthor) - ) - -object DropAllProtectedAuthorRule - extends RuleWithConstantAction( - Drop(Reason.ProtectedAuthor), - Condition.ProtectedAuthor - ) { - override def enableFailClosed: Seq[RuleParam[Boolean]] = Seq(RuleParams.True) -} - -object ProtectedQuoteTweetAuthorRule - extends RuleWithConstantAction( - Drop(Reason.ProtectedAuthor), - And(Condition.OuterAuthorNotFollowingAuthor, Condition.ProtectedAuthor) - ) - -object DropProtectedViewerIfPresentRule - extends RuleWithConstantAction( - Drop(Reason.Unspecified), - And(Condition.LoggedInViewer, Condition.ProtectedViewer) - ) { - override def enableFailClosed: Seq[RuleParam[Boolean]] = Seq(RuleParams.True) -} - -object SuspendedAuthorRule - extends OnlyWhenNotAuthorViewerRule( - Drop(SuspendedAuthor), - Condition.SuspendedAuthor - ) - -object SuspendedViewerRule - extends OnlyWhenNotAuthorViewerRule( - Drop(Unspecified), - Condition.SuspendedViewer - ) - -object DeactivatedViewerRule - extends OnlyWhenNotAuthorViewerRule( - Drop(Unspecified), - Condition.DeactivatedViewer - ) - -object ViewerIsUnmentionedRule - extends OnlyWhenNotAuthorViewerRule( - Drop(Reason.ViewerIsUnmentioned), - Condition.ViewerIsUnmentioned - ) - -abstract class AuthorBlocksViewerRule(override val action: Action) - extends OnlyWhenNotAuthorViewerRule( - action, - Condition.AuthorBlocksViewer - ) - -object AuthorBlocksViewerDropRule - extends AuthorBlocksViewerRule( - Drop(Reason.AuthorBlocksViewer) - ) - -object DeciderableAuthorBlocksViewerDropRule - extends AuthorBlocksViewerRule( - Drop(Reason.AuthorBlocksViewer) - ) { - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableAuthorBlocksViewerDropRuleParam) -} - -object AuthorBlocksViewerTombstoneRule - extends AuthorBlocksViewerRule( - Tombstone(Epitaph.BlockedBy) - ) - -object ViewerBlocksAuthorRule - extends OnlyWhenNotAuthorViewerRule( - Drop(Reason.ViewerBlocksAuthor), - Condition.ViewerBlocksAuthor - ) - -object ViewerBlocksAuthorViewerOptInBlockingOnSearchRule - extends ViewerOptInBlockingOnSearchRule( - Drop(Reason.ViewerBlocksAuthor), - Condition.ViewerBlocksAuthor - ) - -object ViewerMutesAuthorRule - extends OnlyWhenNotAuthorViewerRule( - Drop(Reason.ViewerMutesAuthor), - Condition.ViewerMutesAuthor - ) - -object ViewerMutesAuthorViewerOptInBlockingOnSearchRule - extends ViewerOptInBlockingOnSearchRule( - Drop(Reason.ViewerMutesAuthor), - Condition.ViewerMutesAuthor - ) - -object AuthorBlocksOuterAuthorRule - extends RuleWithConstantAction( - Drop(Reason.AuthorBlocksViewer), - And(Not(Condition.IsSelfQuote), Condition.AuthorBlocksOuterAuthor) - ) - -object ViewerMutesAndDoesNotFollowAuthorRule - extends OnlyWhenNotAuthorViewerRule( - Drop(Reason.ViewerHardMutedAuthor), - And(Condition.ViewerMutesAuthor, Not(Condition.ViewerDoesFollowAuthor)) - ) - -object AuthorBlocksViewerUnspecifiedRule - extends OnlyWhenNotAuthorViewerRule( - Drop(Reason.Unspecified), - Condition.AuthorBlocksViewer - ) - -object ViewerHasMatchingMutedKeywordForNotificationsRule - extends OnlyWhenNotAuthorViewerRule( - Drop(Reason.MutedKeyword), - Condition.ViewerHasMatchingKeywordForNotifications - ) - -object ViewerHasMatchingMutedKeywordForHomeTimelineRule - extends OnlyWhenNotAuthorViewerRule( - Drop(Reason.MutedKeyword), - Condition.ViewerHasMatchingKeywordForHomeTimeline - ) - -trait HasPromotedTweetHealthEnforcement extends WithGate { - override def holdbacks: Seq[RuleParam[Boolean]] = Seq(PromotedTweetHealthEnforcementHoldback) - override def enabled: Seq[RuleParam[Boolean]] = Seq( - EnableTimelineHomePromotedTweetHealthEnforcementRules) -} - -object ViewerHasMatchingMutedKeywordForHomeTimelinePromotedTweetRule - extends OnlyWhenNotAuthorViewerRule( - Drop(Reason.MutedKeyword), - Condition.ViewerHasMatchingKeywordForHomeTimeline - ) - with HasPromotedTweetHealthEnforcement - -object ViewerHasMatchingMutedKeywordForTweetRepliesRule - extends OnlyWhenNotAuthorViewerRule( - Drop(Reason.MutedKeyword), - Condition.ViewerHasMatchingKeywordForTweetReplies - ) - -object MutedKeywordForTweetRepliesInterstitialRule - extends OnlyWhenNotAuthorViewerRule( - Interstitial(Reason.MutedKeyword), - Condition.ViewerHasMatchingKeywordForTweetReplies - ) - -object MutedKeywordForQuotedTweetTweetDetailInterstitialRule - extends OnlyWhenNotAuthorViewerRule( - Interstitial(Reason.MutedKeyword), - And(Condition.IsQuotedInnerTweet, Condition.ViewerHasMatchingKeywordForTweetReplies) - ) - -object ViewerMutesAuthorInterstitialRule - extends OnlyWhenNotAuthorViewerRule( - Interstitial(Reason.ViewerMutesAuthor), - Condition.ViewerMutesAuthor - ) - -object ViewerMutesAuthorInnerQuotedTweetInterstitialRule - extends OnlyWhenNotAuthorViewerRule( - Interstitial(Reason.ViewerMutesAuthor), - And(Condition.ViewerMutesAuthor, IsQuotedInnerTweet) - ) { - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableInnerQuotedTweetViewerMutesAuthorInterstitialRuleParam) -} - -object ViewerMutesAuthorHomeTimelinePromotedTweetRule - extends OnlyWhenNotAuthorViewerRule( - Drop(Reason.ViewerMutesAuthor), - Condition.ViewerMutesAuthor - ) - with HasPromotedTweetHealthEnforcement - -object ViewerBlocksAuthorInterstitialRule - extends OnlyWhenNotAuthorViewerRule( - Interstitial(Reason.ViewerBlocksAuthor), - Condition.ViewerBlocksAuthor - ) - -object ViewerBlocksAuthorInnerQuotedTweetInterstitialRule - extends OnlyWhenNotAuthorViewerRule( - Interstitial(Reason.ViewerBlocksAuthor), - And(Condition.ViewerBlocksAuthor, IsQuotedInnerTweet) - ) { - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableInnerQuotedTweetViewerBlocksAuthorInterstitialRuleParam) -} - -object ViewerBlocksAuthorHomeTimelinePromotedTweetRule - extends OnlyWhenNotAuthorViewerRule( - Drop(Reason.ViewerBlocksAuthor), - Condition.ViewerBlocksAuthor - ) - with HasPromotedTweetHealthEnforcement - -object ViewerReportsAuthorInterstitialRule - extends OnlyWhenNotAuthorViewerRule( - Interstitial(Reason.ViewerReportedAuthor), - Condition.ViewerReportsAuthor - ) - -object ViewerIsAuthorDropRule - extends RuleWithConstantAction(Drop(Unspecified), Not(NonAuthorViewer)) - -object ViewerIsNotAuthorDropRule extends RuleWithConstantAction(Drop(Unspecified), NonAuthorViewer) - -object RetweetDropRule extends RuleWithConstantAction(Drop(Unspecified), Retweet) - -object ViewerIsSoftUserDropRule extends RuleWithConstantAction(Drop(ViewerIsSoftUser), SoftViewer) { - - override val enabled: Seq[RuleParam[Boolean]] = Seq(EnableViewerIsSoftUserDropRuleParam) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/SafeSearchRules.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/SafeSearchRules.scala deleted file mode 100644 index 838e78a5b..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/SafeSearchRules.scala +++ /dev/null @@ -1,332 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.visibility.configapi.params.RuleParam -import com.twitter.visibility.configapi.params.RuleParams.EnableDownrankSpamReplySectioningRuleParam -import com.twitter.visibility.configapi.params.RuleParams.EnableNotGraduatedSearchDropRuleParam -import com.twitter.visibility.configapi.params.RuleParams.EnableNsfwTextSectioningRuleParam -import com.twitter.visibility.configapi.params.RuleParams.NotGraduatedUserLabelRuleHoldbackExperimentParam -import com.twitter.visibility.models.TweetSafetyLabelType -import com.twitter.visibility.models.UserLabelValue -import com.twitter.visibility.rules.Condition.And -import com.twitter.visibility.rules.Condition.LoggedOutOrViewerNotFollowingAuthor -import com.twitter.visibility.rules.Condition.LoggedOutOrViewerOptInFiltering -import com.twitter.visibility.rules.Condition.NonAuthorViewer -import com.twitter.visibility.rules.Condition.Not -import com.twitter.visibility.rules.Condition.TweetComposedBefore -import com.twitter.visibility.rules.Condition.ViewerDoesFollowAuthor -import com.twitter.visibility.rules.Condition.ViewerOptInFilteringOnSearch -import com.twitter.visibility.rules.Reason.Nsfw -import com.twitter.visibility.rules.Reason.Unspecified -import com.twitter.visibility.rules.RuleActionSourceBuilder.TweetSafetyLabelSourceBuilder - -case object SafeSearchTweetRules { - - object SafeSearchAbusiveTweetLabelRule - extends NonAuthorViewerOptInFilteringWithTweetLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.Abusive - ) - with DoesLogVerdict { - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(TweetSafetyLabelType.Abusive)) - } - - object SafeSearchNsfwHighPrecisionTweetLabelRule - extends NonAuthorViewerOptInFilteringWithTweetLabelRule( - Drop(Nsfw), - TweetSafetyLabelType.NsfwHighPrecision - ) - - object SafeSearchGoreAndViolenceHighPrecisionTweetLabelRule - extends NonAuthorViewerOptInFilteringWithTweetLabelRule( - Drop(Nsfw), - TweetSafetyLabelType.GoreAndViolenceHighPrecision - ) - - object SafeSearchNsfwReportedHeuristicsTweetLabelRule - extends NonAuthorViewerOptInFilteringWithTweetLabelRule( - Drop(Nsfw), - TweetSafetyLabelType.NsfwReportedHeuristics - ) - - object SafeSearchGoreAndViolenceReportedHeuristicsTweetLabelRule - extends NonAuthorViewerOptInFilteringWithTweetLabelRule( - Drop(Nsfw), - TweetSafetyLabelType.GoreAndViolenceReportedHeuristics - ) - - object SafeSearchNsfwCardImageTweetLabelRule - extends NonAuthorViewerOptInFilteringWithTweetLabelRule( - Drop(Nsfw), - TweetSafetyLabelType.NsfwCardImage - ) - - object SafeSearchNsfwHighRecallTweetLabelRule - extends NonAuthorViewerOptInFilteringWithTweetLabelRule( - Drop(Nsfw), - TweetSafetyLabelType.NsfwHighRecall - ) - - object SafeSearchNsfwVideoTweetLabelRule - extends NonAuthorViewerOptInFilteringWithTweetLabelRule( - Drop(Nsfw), - TweetSafetyLabelType.NsfwVideo - ) - - object SafeSearchNsfwTextTweetLabelRule - extends NonAuthorViewerOptInFilteringWithTweetLabelRule( - Drop(Nsfw), - TweetSafetyLabelType.NsfwText - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableNsfwTextSectioningRuleParam) - } - - object SafeSearchNsfwTextAuthorLabelRule - extends ViewerOptInFilteringOnSearchUserLabelRule( - Drop(Nsfw), - UserLabelValue.DownrankSpamReply - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableNsfwTextSectioningRuleParam) - } - - object SafeSearchGoreAndViolenceTweetLabelRule - extends ConditionWithTweetLabelRule( - Drop(Unspecified), - And( - NonAuthorViewer, - TweetComposedBefore(TweetSafetyLabelType.GoreAndViolence.DeprecatedAt), - LoggedOutOrViewerOptInFiltering - ), - TweetSafetyLabelType.GoreAndViolence - ) - - object SafeSearchUntrustedUrlTweetLabelRule - extends NonAuthorViewerOptInFilteringWithTweetLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.UntrustedUrl - ) - - object SafeSearchDownrankSpamReplyTweetLabelRule - extends NonAuthorViewerOptInFilteringWithTweetLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.DownrankSpamReply - ) { - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableDownrankSpamReplySectioningRuleParam) - } - - object SafeSearchDownrankSpamReplyAuthorLabelRule - extends ViewerOptInFilteringOnSearchUserLabelRule( - Drop(Unspecified), - UserLabelValue.DownrankSpamReply - ) { - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableDownrankSpamReplySectioningRuleParam) - } - - object SafeSearchAutomationNonFollowerTweetLabelRule - extends NonFollowerViewerOptInFilteringWithTweetLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.Automation - ) - - object SafeSearchDuplicateMentionNonFollowerTweetLabelRule - extends NonFollowerViewerOptInFilteringWithTweetLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.DuplicateMention - ) - - object SafeSearchBystanderAbusiveTweetLabelRule - extends NonAuthorViewerOptInFilteringWithTweetLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.BystanderAbusive - ) -} - -case object UnsafeSearchTweetRules { - - object UnsafeSearchNsfwHighPrecisionInterstitialAllUsersTweetLabelRule - extends ConditionWithTweetLabelRule( - Interstitial(Nsfw), - Not(ViewerOptInFilteringOnSearch), - TweetSafetyLabelType.NsfwHighPrecision - ) - - object UnsafeSearchGoreAndViolenceHighPrecisionAllUsersTweetLabelRule - extends ConditionWithTweetLabelRule( - Interstitial(Nsfw), - Not(ViewerOptInFilteringOnSearch), - TweetSafetyLabelType.GoreAndViolenceHighPrecision - ) - - object UnsafeSearchGoreAndViolenceHighPrecisionAllUsersTweetLabelDropRule - extends ConditionWithTweetLabelRule( - Drop(Nsfw), - Not(ViewerOptInFilteringOnSearch), - TweetSafetyLabelType.GoreAndViolenceHighPrecision - ) - - object UnsafeSearchNsfwReportedHeuristicsAllUsersTweetLabelRule - extends ConditionWithTweetLabelRule( - Interstitial(Nsfw), - Not(ViewerOptInFilteringOnSearch), - TweetSafetyLabelType.NsfwReportedHeuristics - ) - - object UnsafeSearchNsfwReportedHeuristicsAllUsersTweetLabelDropRule - extends ConditionWithTweetLabelRule( - Drop(Nsfw), - Not(ViewerOptInFilteringOnSearch), - TweetSafetyLabelType.NsfwReportedHeuristics - ) - - object UnsafeSearchNsfwHighPrecisionAllUsersTweetLabelDropRule - extends ConditionWithTweetLabelRule( - Drop(Nsfw), - Not(ViewerOptInFilteringOnSearch), - TweetSafetyLabelType.NsfwHighPrecision - ) - - object UnsafeSearchGoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule - extends ConditionWithTweetLabelRule( - Interstitial(Nsfw), - Not(ViewerOptInFilteringOnSearch), - TweetSafetyLabelType.GoreAndViolenceReportedHeuristics - ) - - object UnsafeSearchGoreAndViolenceReportedHeuristicsAllUsersTweetLabelDropRule - extends ConditionWithTweetLabelRule( - Drop(Nsfw), - Not(ViewerOptInFilteringOnSearch), - TweetSafetyLabelType.GoreAndViolenceReportedHeuristics - ) - - object UnsafeSearchNsfwCardImageAllUsersTweetLabelRule - extends ConditionWithTweetLabelRule( - Interstitial(Nsfw), - Not(ViewerOptInFilteringOnSearch), - TweetSafetyLabelType.NsfwCardImage - ) - - object UnsafeSearchNsfwCardImageAllUsersTweetLabelDropRule - extends ConditionWithTweetLabelRule( - Drop(Nsfw), - Not(ViewerOptInFilteringOnSearch), - TweetSafetyLabelType.NsfwCardImage - ) - -} - -case object SafeSearchUserRules { - - object SafeSearchAbusiveUserLabelRule - extends ViewerOptInFilteringOnSearchUserLabelRule( - Drop(Unspecified), - UserLabelValue.Abusive - ) - - object SafeSearchAbusiveHighRecallUserLabelRule - extends ViewerOptInFilteringOnSearchUserLabelRule( - Drop(Unspecified), - UserLabelValue.AbusiveHighRecall, - LoggedOutOrViewerNotFollowingAuthor - ) - - object SafeSearchHighRecallUserLabelRule - extends ViewerOptInFilteringOnSearchUserLabelRule( - Drop(Nsfw), - UserLabelValue.NsfwHighRecall, - LoggedOutOrViewerNotFollowingAuthor - ) - - object SafeSearchCompromisedUserLabelRule - extends ViewerOptInFilteringOnSearchUserLabelRule( - Drop(Unspecified), - UserLabelValue.Compromised - ) - - object SafeSearchDuplicateContentUserLabelRule - extends ViewerOptInFilteringOnSearchUserLabelRule( - Drop(Unspecified), - UserLabelValue.DuplicateContent - ) - - object SafeSearchLowQualityUserLabelRule - extends ViewerOptInFilteringOnSearchUserLabelRule( - Drop(Unspecified), - UserLabelValue.LowQuality - ) - - object SafeSearchNsfwHighPrecisionUserLabelRule - extends ConditionWithUserLabelRule( - Drop(Nsfw), - LoggedOutOrViewerOptInFiltering, - UserLabelValue.NsfwHighPrecision - ) - - object SafeSearchNsfwAvatarImageUserLabelRule - extends ViewerOptInFilteringOnSearchUserLabelRule( - Drop(Nsfw), - UserLabelValue.NsfwAvatarImage - ) - - object SafeSearchNsfwBannerImageUserLabelRule - extends ViewerOptInFilteringOnSearchUserLabelRule( - Drop(Nsfw), - UserLabelValue.NsfwBannerImage - ) - - object SafeSearchNsfwNearPerfectAuthorRule - extends ViewerOptInFilteringOnSearchUserLabelRule( - Drop(Nsfw), - UserLabelValue.NsfwNearPerfect - ) - - object SafeSearchReadOnlyUserLabelRule - extends ViewerOptInFilteringOnSearchUserLabelRule( - Drop(Unspecified), - UserLabelValue.ReadOnly - ) - - object SafeSearchSpamHighRecallUserLabelRule - extends ViewerOptInFilteringOnSearchUserLabelRule( - Drop(Unspecified), - UserLabelValue.SpamHighRecall - ) - - object SafeSearchSearchBlacklistUserLabelRule - extends ViewerOptInFilteringOnSearchUserLabelRule( - Drop(Unspecified), - UserLabelValue.SearchBlacklist - ) - - object SafeSearchNsfwTextUserLabelRule - extends ViewerOptInFilteringOnSearchUserLabelRule( - Drop(Unspecified), - UserLabelValue.NsfwText - ) { - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableNsfwTextSectioningRuleParam) - } - - object SafeSearchDoNotAmplifyNonFollowersUserLabelRule - extends ViewerOptInFilteringOnSearchUserLabelRule( - Drop(Unspecified), - UserLabelValue.DoNotAmplify, - prerequisiteCondition = Not(ViewerDoesFollowAuthor) - ) - - object SafeSearchNotGraduatedNonFollowersUserLabelRule - extends ViewerOptInFilteringOnSearchUserLabelRule( - Drop(Unspecified), - UserLabelValue.NotGraduated, - prerequisiteCondition = Not(ViewerDoesFollowAuthor) - ) { - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableNotGraduatedSearchDropRuleParam) - - override def holdbacks: Seq[RuleParam[Boolean]] = - Seq(NotGraduatedUserLabelRuleHoldbackExperimentParam) - - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/SearchBlenderRules.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/SearchBlenderRules.scala deleted file mode 100644 index 8e7c54582..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/SearchBlenderRules.scala +++ /dev/null @@ -1,37 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.visibility.models.TweetSafetyLabelType -import com.twitter.visibility.rules.Condition.And -import com.twitter.visibility.rules.Condition.HasSearchCandidateCountGreaterThan45 -import com.twitter.visibility.rules.Condition.IsFirstPageSearchResult -import com.twitter.visibility.rules.Condition.Not -import com.twitter.visibility.rules.Reason.FirstPageSearchResult - -abstract class FirstPageSearchResultWithTweetLabelRule( - action: Action, - tweetSafetyLabelType: TweetSafetyLabelType) - extends ConditionWithTweetLabelRule( - action, - IsFirstPageSearchResult, - tweetSafetyLabelType - ) - -abstract class FirstPageSearchResultSmartOutOfNetworkWithTweetLabelRule( - action: Action, - tweetSafetyLabelType: TweetSafetyLabelType) - extends ConditionWithTweetLabelRule( - action, - And( - IsFirstPageSearchResult, - HasSearchCandidateCountGreaterThan45, - Condition.NonAuthorViewer, - Not(Condition.ViewerDoesFollowAuthor), - Not(Condition.VerifiedAuthor) - ), - tweetSafetyLabelType - ) - -object FirstPageSearchResultAgathaSpamDropRule - extends FirstPageSearchResultWithTweetLabelRule( - Drop(FirstPageSearchResult), - TweetSafetyLabelType.AgathaSpam) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/SensitiveMediaSettingsRules.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/SensitiveMediaSettingsRules.scala deleted file mode 100644 index 2fe315afe..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/SensitiveMediaSettingsRules.scala +++ /dev/null @@ -1,277 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.visibility.rules.Condition.ViewerHasAdultMediaSettingLevel -import com.twitter.visibility.rules.Condition.ViewerHasViolentMediaSettingLevel -import com.twitter.visibility.rules.Condition.ViewerHasOtherSensitiveMediaSettingLevel -import com.twitter.visibility.rules.Condition.LoggedInViewer -import com.twitter.visibility.rules.Condition.LoggedOutViewer -import com.twitter.visibility.rules.Condition.TweetHasNsfwUserAuthor -import com.twitter.visibility.rules.Condition.TweetHasNsfwAdminAuthor -import com.twitter.visibility.rules.Condition.And -import com.twitter.visibility.rules.Condition.Or -import com.twitter.visibility.rules.Condition.Not -import com.twitter.visibility.rules.Condition.NonAuthorViewer -import com.twitter.visibility.rules.Condition.TweetHasMedia -import com.twitter.visibility.rules.Reason.Nsfw -import com.twitter.visibility.models.TweetSafetyLabelType -import com.twitter.contenthealth.sensitivemediasettings.thriftscala.SensitiveMediaSettingsLevel - - -abstract class AdultMediaTweetLabelDropRule(tweetSafetyLabelType: TweetSafetyLabelType) - extends ConditionWithTweetLabelRule( - Drop(Nsfw), - And(LoggedInViewer, ViewerHasAdultMediaSettingLevel(SensitiveMediaSettingsLevel.Drop)), - tweetSafetyLabelType - ) - -abstract class ViolentMediaTweetLabelDropRule(tweetSafetyLabelType: TweetSafetyLabelType) - extends ConditionWithTweetLabelRule( - Drop(Nsfw), - And(LoggedInViewer, ViewerHasViolentMediaSettingLevel(SensitiveMediaSettingsLevel.Drop)), - tweetSafetyLabelType - ) - -abstract class OtherSensitiveMediaTweetLabelDropRule(condition: Condition) - extends RuleWithConstantAction( - Drop(Nsfw), - And( - condition, - And( - TweetHasMedia, - LoggedInViewer, - ViewerHasOtherSensitiveMediaSettingLevel(SensitiveMediaSettingsLevel.Drop))) - ) - -abstract class AdultMediaTweetLabelInterstitialRule(tweetSafetyLabelType: TweetSafetyLabelType) - extends ConditionWithTweetLabelRule( - Interstitial(Nsfw), - Or( - LoggedOutViewer, - ViewerHasAdultMediaSettingLevel(SensitiveMediaSettingsLevel.Warn), - Not(ViewerHasAdultMediaSettingLevel(SensitiveMediaSettingsLevel.Allow)) - ), - tweetSafetyLabelType - ) - -abstract class ViolentMediaTweetLabelInterstitialRule(tweetSafetyLabelType: TweetSafetyLabelType) - extends ConditionWithTweetLabelRule( - Interstitial(Nsfw), - Or( - LoggedOutViewer, - ViewerHasViolentMediaSettingLevel(SensitiveMediaSettingsLevel.Warn), - Not(ViewerHasViolentMediaSettingLevel(SensitiveMediaSettingsLevel.Allow)) - ), - tweetSafetyLabelType - ) - -abstract class OtherSensitiveMediaTweetLabelInterstitialRule(condition: Condition) - extends RuleWithConstantAction( - Interstitial(Nsfw), - And( - condition, - TweetHasMedia, - Or( - LoggedOutViewer, - ViewerHasOtherSensitiveMediaSettingLevel(SensitiveMediaSettingsLevel.Warn) - ) - ) - ) - -abstract class AdultMediaTweetLabelDropSettingLevelTombstoneRule( - tweetSafetyLabelType: TweetSafetyLabelType) - extends ConditionWithTweetLabelRule( - Tombstone(Epitaph.AdultMedia), - And( - LoggedInViewer, - NonAuthorViewer, - ViewerHasAdultMediaSettingLevel(SensitiveMediaSettingsLevel.Drop)), - tweetSafetyLabelType - ) - -abstract class ViolentMediaTweetLabelDropSettingLevelTombstoneRule( - tweetSafetyLabelType: TweetSafetyLabelType) - extends ConditionWithTweetLabelRule( - Tombstone(Epitaph.ViolentMedia), - And( - LoggedInViewer, - NonAuthorViewer, - ViewerHasViolentMediaSettingLevel(SensitiveMediaSettingsLevel.Drop)), - tweetSafetyLabelType - ) - -abstract class OtherSensitiveMediaTweetLabelDropSettingLevelTombstoneRule(condition: Condition) - extends RuleWithConstantAction( - Tombstone(Epitaph.OtherSensitiveMedia), - And( - condition, - And( - TweetHasMedia, - LoggedInViewer, - NonAuthorViewer, - ViewerHasOtherSensitiveMediaSettingLevel(SensitiveMediaSettingsLevel.Drop)) - ) - ) - -case object SensitiveMediaTweetDropRules { - - - object AdultMediaNsfwHighPrecisionTweetLabelDropRule - extends AdultMediaTweetLabelDropRule( - TweetSafetyLabelType.NsfwHighPrecision - ) - - object AdultMediaNsfwCardImageTweetLabelDropRule - extends AdultMediaTweetLabelDropRule( - TweetSafetyLabelType.NsfwCardImage - ) - - object AdultMediaNsfwReportedHeuristicsTweetLabelDropRule - extends AdultMediaTweetLabelDropRule( - TweetSafetyLabelType.NsfwReportedHeuristics - ) - - object AdultMediaNsfwVideoTweetLabelDropRule - extends AdultMediaTweetLabelDropRule( - TweetSafetyLabelType.NsfwVideo - ) - - object AdultMediaNsfwHighRecallTweetLabelDropRule - extends AdultMediaTweetLabelDropRule( - TweetSafetyLabelType.NsfwHighRecall - ) - - object AdultMediaNsfwTextTweetLabelDropRule - extends AdultMediaTweetLabelDropRule( - TweetSafetyLabelType.NsfwText - ) - - object ViolentMediaGoreAndViolenceHighPrecisionDropRule - extends ViolentMediaTweetLabelDropRule( - TweetSafetyLabelType.GoreAndViolenceHighPrecision - ) - - object ViolentMediaGoreAndViolenceReportedHeuristicsDropRule - extends ViolentMediaTweetLabelDropRule( - TweetSafetyLabelType.GoreAndViolenceReportedHeuristics - ) - - object OtherSensitiveMediaNsfwUserTweetFlagDropRule - extends OtherSensitiveMediaTweetLabelDropRule( - TweetHasNsfwUserAuthor - ) - - object OtherSensitiveMediaNsfwAdminTweetFlagDropRule - extends OtherSensitiveMediaTweetLabelDropRule( - TweetHasNsfwAdminAuthor - ) -} - -case object SensitiveMediaTweetInterstitialRules { - - object AdultMediaNsfwHighPrecisionTweetLabelInterstitialRule - extends AdultMediaTweetLabelInterstitialRule( - TweetSafetyLabelType.NsfwHighPrecision - ) - with DoesLogVerdict - - object AdultMediaNsfwCardImageTweetLabelInterstitialRule - extends AdultMediaTweetLabelInterstitialRule( - TweetSafetyLabelType.NsfwCardImage - ) - - object AdultMediaNsfwReportedHeuristicsTweetLabelInterstitialRule - extends AdultMediaTweetLabelInterstitialRule( - TweetSafetyLabelType.NsfwReportedHeuristics - ) - - object AdultMediaNsfwVideoTweetLabelInterstitialRule - extends AdultMediaTweetLabelInterstitialRule( - TweetSafetyLabelType.NsfwVideo - ) - - object AdultMediaNsfwHighRecallTweetLabelInterstitialRule - extends AdultMediaTweetLabelInterstitialRule( - TweetSafetyLabelType.NsfwHighRecall - ) - - object AdultMediaNsfwTextTweetLabelInterstitialRule - extends AdultMediaTweetLabelInterstitialRule( - TweetSafetyLabelType.NsfwText - ) - - object ViolentMediaGoreAndViolenceHighPrecisionInterstitialRule - extends ViolentMediaTweetLabelInterstitialRule( - TweetSafetyLabelType.GoreAndViolenceHighPrecision - ) - with DoesLogVerdict - - object ViolentMediaGoreAndViolenceReportedHeuristicsInterstitialRule - extends ViolentMediaTweetLabelInterstitialRule( - TweetSafetyLabelType.GoreAndViolenceReportedHeuristics - ) - - object OtherSensitiveMediaNsfwUserTweetFlagInterstitialRule - extends OtherSensitiveMediaTweetLabelInterstitialRule( - TweetHasNsfwUserAuthor - ) - - object OtherSensitiveMediaNsfwAdminTweetFlagInterstitialRule - extends OtherSensitiveMediaTweetLabelInterstitialRule( - TweetHasNsfwAdminAuthor - ) - -} - -case object SensitiveMediaTweetDropSettingLevelTombstoneRules { - - - object AdultMediaNsfwHighPrecisionTweetLabelDropSettingLevelTombstoneRule - extends AdultMediaTweetLabelDropSettingLevelTombstoneRule( - TweetSafetyLabelType.NsfwHighPrecision - ) - - object AdultMediaNsfwCardImageTweetLabelDropSettingLevelTombstoneRule - extends AdultMediaTweetLabelDropSettingLevelTombstoneRule( - TweetSafetyLabelType.NsfwCardImage - ) - - object AdultMediaNsfwReportedHeuristicsTweetLabelDropSettingLevelTombstoneRule - extends AdultMediaTweetLabelDropSettingLevelTombstoneRule( - TweetSafetyLabelType.NsfwReportedHeuristics - ) - - object AdultMediaNsfwVideoTweetLabelDropSettingLevelTombstoneRule - extends AdultMediaTweetLabelDropSettingLevelTombstoneRule( - TweetSafetyLabelType.NsfwVideo - ) - - object AdultMediaNsfwHighRecallTweetLabelDropSettingLevelTombstoneRule - extends AdultMediaTweetLabelDropSettingLevelTombstoneRule( - TweetSafetyLabelType.NsfwHighRecall - ) - - object AdultMediaNsfwTextTweetLabelDropSettingLevelTombstoneRule - extends AdultMediaTweetLabelDropSettingLevelTombstoneRule( - TweetSafetyLabelType.NsfwText - ) - - object ViolentMediaGoreAndViolenceHighPrecisionDropSettingLeveTombstoneRule - extends ViolentMediaTweetLabelDropSettingLevelTombstoneRule( - TweetSafetyLabelType.GoreAndViolenceHighPrecision - ) - - object ViolentMediaGoreAndViolenceReportedHeuristicsDropSettingLevelTombstoneRule - extends ViolentMediaTweetLabelDropSettingLevelTombstoneRule( - TweetSafetyLabelType.GoreAndViolenceReportedHeuristics - ) - - object OtherSensitiveMediaNsfwUserTweetFlagDropSettingLevelTombstoneRule - extends OtherSensitiveMediaTweetLabelDropSettingLevelTombstoneRule( - TweetHasNsfwUserAuthor - ) - - object OtherSensitiveMediaNsfwAdminTweetFlagDropSettingLevelTombstoneRule - extends OtherSensitiveMediaTweetLabelDropSettingLevelTombstoneRule( - TweetHasNsfwAdminAuthor - ) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/SpaceRules.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/SpaceRules.scala deleted file mode 100644 index a6d771d27..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/SpaceRules.scala +++ /dev/null @@ -1,219 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.visibility.configapi.params.FSRuleParams.HighToxicityModelScoreSpaceThresholdParam -import com.twitter.visibility.configapi.params.RuleParam -import com.twitter.visibility.configapi.params.RuleParams.EnableMutedKeywordFilteringSpaceTitleNotificationsRuleParam -import com.twitter.visibility.models.SpaceSafetyLabelType.CoordinatedHarmfulActivityHighRecall -import com.twitter.visibility.models.SpaceSafetyLabelType.DoNotAmplify -import com.twitter.visibility.models.SpaceSafetyLabelType.MisleadingHighRecall -import com.twitter.visibility.models.SpaceSafetyLabelType.NsfwHighPrecision -import com.twitter.visibility.models.SpaceSafetyLabelType.NsfwHighRecall -import com.twitter.visibility.models.SpaceSafetyLabelType.UntrustedUrl -import com.twitter.visibility.models.UserLabelValue.Abusive -import com.twitter.visibility.models.UserLabelValue.BlinkWorst -import com.twitter.visibility.models.UserLabelValue.DelayedRemediation -import com.twitter.visibility.models.UserLabelValue.NsfwAvatarImage -import com.twitter.visibility.models.UserLabelValue.NsfwBannerImage -import com.twitter.visibility.models.UserLabelValue.NsfwNearPerfect -import com.twitter.visibility.models.SpaceSafetyLabelType -import com.twitter.visibility.models.SpaceSafetyLabelType.HatefulHighRecall -import com.twitter.visibility.models.SpaceSafetyLabelType.HighToxicityModelScore -import com.twitter.visibility.models.SpaceSafetyLabelType.ViolenceHighRecall -import com.twitter.visibility.models.UserLabelValue -import com.twitter.visibility.rules.Condition._ -import com.twitter.visibility.rules.Reason.Nsfw -import com.twitter.visibility.rules.Reason.Unspecified - -object SpaceRules { - - abstract class SpaceHasLabelRule( - action: Action, - safetyLabelType: SpaceSafetyLabelType) - extends RuleWithConstantAction(action, And(SpaceHasLabel(safetyLabelType), NonAuthorViewer)) - - abstract class SpaceHasLabelAndNonFollowerRule( - action: Action, - safetyLabelType: SpaceSafetyLabelType) - extends RuleWithConstantAction( - action, - And(SpaceHasLabel(safetyLabelType), LoggedOutOrViewerNotFollowingAuthor)) - - abstract class AnySpaceHostOrAdminHasLabelRule( - action: Action, - userLabel: UserLabelValue) - extends WhenAuthorUserLabelPresentRule(action, userLabel) - - abstract class AnySpaceHostOrAdminHasLabelAndNonFollowerRule( - action: Action, - userLabel: UserLabelValue) - extends ConditionWithUserLabelRule(action, LoggedOutOrViewerNotFollowingAuthor, userLabel) - - - object SpaceDoNotAmplifyAllUsersDropRule - extends SpaceHasLabelRule( - Drop(Unspecified), - DoNotAmplify, - ) - - object SpaceDoNotAmplifyNonFollowerDropRule - extends SpaceHasLabelAndNonFollowerRule( - Drop(Unspecified), - DoNotAmplify, - ) - - object SpaceCoordHarmfulActivityHighRecallAllUsersDropRule - extends SpaceHasLabelRule( - Drop(Unspecified), - CoordinatedHarmfulActivityHighRecall, - ) - - object SpaceCoordHarmfulActivityHighRecallNonFollowerDropRule - extends SpaceHasLabelAndNonFollowerRule( - Drop(Unspecified), - CoordinatedHarmfulActivityHighRecall, - ) - - object SpaceUntrustedUrlAllUsersDropRule - extends SpaceHasLabelRule( - Drop(Unspecified), - UntrustedUrl, - ) - - object SpaceUntrustedUrlNonFollowerDropRule - extends SpaceHasLabelAndNonFollowerRule( - Drop(Unspecified), - UntrustedUrl, - ) - - object SpaceMisleadingHighRecallNonFollowerDropRule - extends SpaceHasLabelAndNonFollowerRule( - Drop(Unspecified), - MisleadingHighRecall, - ) - - object SpaceNsfwHighPrecisionAllUsersInterstitialRule - extends SpaceHasLabelRule( - Interstitial(Nsfw), - NsfwHighPrecision, - ) - - object SpaceNsfwHighPrecisionAllUsersDropRule - extends SpaceHasLabelRule( - Drop(Nsfw), - NsfwHighPrecision, - ) - - object SpaceNsfwHighPrecisionNonFollowerDropRule - extends SpaceHasLabelAndNonFollowerRule( - Drop(Nsfw), - NsfwHighPrecision, - ) - - object SpaceNsfwHighPrecisionSafeSearchNonFollowerDropRule - extends RuleWithConstantAction( - Drop(Nsfw), - And( - SpaceHasLabel(NsfwHighPrecision), - NonAuthorViewer, - LoggedOutOrViewerOptInFiltering, - Not(ViewerDoesFollowAuthor), - ), - ) - - object SpaceNsfwHighRecallAllUsersDropRule - extends SpaceHasLabelRule( - Drop(Nsfw), - NsfwHighRecall, - ) - - object SpaceNsfwHighRecallNonFollowerDropRule - extends SpaceHasLabelAndNonFollowerRule( - Drop(Nsfw), - NsfwHighRecall, - ) - - object SpaceNsfwHighRecallSafeSearchNonFollowerDropRule - extends RuleWithConstantAction( - Drop(Nsfw), - And( - SpaceHasLabel(NsfwHighRecall), - NonAuthorViewer, - LoggedOutOrViewerOptInFiltering, - Not(ViewerDoesFollowAuthor), - ), - ) - - object SpaceHatefulHighRecallAllUsersDropRule - extends SpaceHasLabelRule( - Drop(Unspecified), - HatefulHighRecall, - ) - - object SpaceViolenceHighRecallAllUsersDropRule - extends SpaceHasLabelRule( - Drop(Unspecified), - ViolenceHighRecall, - ) - - object SpaceHighToxicityScoreNonFollowerDropRule - extends RuleWithConstantAction( - Drop(Unspecified), - And( - SpaceHasLabelWithScoreAboveThresholdWithParam( - HighToxicityModelScore, - HighToxicityModelScoreSpaceThresholdParam - ), - NonAuthorViewer, - LoggedOutOrViewerNotFollowingAuthor, - ) - ) - with ExperimentalRule - - - object ViewerHasMatchingMutedKeywordInSpaceTitleForNotificationsRule - extends OnlyWhenNotAuthorViewerRule( - Drop(Reason.MutedKeyword), - Condition.ViewerHasMatchingKeywordInSpaceTitleForNotifications - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq( - EnableMutedKeywordFilteringSpaceTitleNotificationsRuleParam) - - } - - - object UserAbusiveNonFollowerDropRule - extends AnySpaceHostOrAdminHasLabelAndNonFollowerRule( - Drop(Unspecified), - Abusive - ) - - object UserBlinkWorstAllUsersDropRule - extends AnySpaceHostOrAdminHasLabelRule( - Drop(Unspecified), - BlinkWorst - ) - - object UserNsfwNearPerfectNonFollowerDropRule - extends AnySpaceHostOrAdminHasLabelAndNonFollowerRule( - Drop(Nsfw), - NsfwNearPerfect - ) - - object UserNsfwHighPrecisionNonFollowerDropRule - extends AnySpaceHostOrAdminHasLabelAndNonFollowerRule( - Drop(Nsfw), - UserLabelValue.NsfwHighPrecision - ) - - object UserNsfwAvatarImageNonFollowerDropRule - extends AnySpaceHostOrAdminHasLabelAndNonFollowerRule( - Drop(Nsfw), - NsfwAvatarImage - ) - - object UserNsfwBannerImageNonFollowerDropRule - extends AnySpaceHostOrAdminHasLabelAndNonFollowerRule( - Drop(Nsfw), - NsfwBannerImage - ) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/TombstoneIf.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/TombstoneIf.scala deleted file mode 100644 index 38f9276ff..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/TombstoneIf.scala +++ /dev/null @@ -1,44 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.visibility.rules.Condition.And -import com.twitter.visibility.rules.Condition.IsFocalTweet -import com.twitter.visibility.rules.Condition.Not - -object TombstoneIf { - - object AuthorIsProtected - extends RuleWithConstantAction( - Tombstone(Epitaph.Protected), - And( - Condition.LoggedOutOrViewerNotFollowingAuthor, - Condition.ProtectedAuthor - ) - ) - - object ReplyIsModeratedByRootAuthor - extends RuleWithConstantAction( - Tombstone(Epitaph.Moderated), - And( - Not(IsFocalTweet), - Condition.Moderated - ) - ) - - object ViewerIsBlockedByAuthor - extends OnlyWhenNotAuthorViewerRule( - Tombstone(Epitaph.BlockedBy), - Condition.AuthorBlocksViewer - ) - - object AuthorIsDeactivated - extends RuleWithConstantAction( - Tombstone(Epitaph.Deactivated), - Condition.DeactivatedAuthor - ) - - object AuthorIsSuspended - extends RuleWithConstantAction( - Tombstone(Epitaph.Suspended), - Condition.SuspendedAuthor - ) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/ToxicityReplyFilterRules.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/ToxicityReplyFilterRules.scala deleted file mode 100644 index 01a1ab393..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/ToxicityReplyFilterRules.scala +++ /dev/null @@ -1,28 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.visibility.configapi.params.RuleParam -import com.twitter.visibility.configapi.params.RuleParams -import com.twitter.visibility.rules.Reason.Toxicity - -object ToxicityReplyFilterRules { - - sealed abstract class ToxicityReplyFilterBaseRule( - action: Action) - extends RuleWithConstantAction( - action = action, - condition = Condition.ToxrfFilteredFromAuthorViewer) - - object ToxicityReplyFilterRule - extends ToxicityReplyFilterBaseRule(action = Tombstone(Epitaph.Unavailable)) { - - override def enabled: Seq[RuleParam[Boolean]] = Seq( - RuleParams.EnableToxicReplyFilteringConversationRulesParam) - } - - object ToxicityReplyFilterDropNotificationRule - extends ToxicityReplyFilterBaseRule(action = Drop(Toxicity)) { - - override def enabled: Seq[RuleParam[Boolean]] = Seq( - RuleParams.EnableToxicReplyFilteringNotificationsRulesParam) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/TweetLabelRules.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/TweetLabelRules.scala deleted file mode 100644 index bcee096f5..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/TweetLabelRules.scala +++ /dev/null @@ -1,883 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.visibility.common.ModelScoreThresholds -import com.twitter.visibility.common.actions.AvoidReason -import com.twitter.visibility.common.actions.AvoidReason.MightNotBeSuitableForAds -import com.twitter.visibility.common.actions.LimitedEngagementReason -import com.twitter.visibility.common.actions.TweetVisibilityNudgeReason -import com.twitter.visibility.configapi.configs.DeciderKey -import com.twitter.visibility.configapi.params.FSRuleParams.HighSpammyTweetContentScoreSearchLatestProdTweetLabelDropRuleThresholdParam -import com.twitter.visibility.configapi.params.FSRuleParams.HighSpammyTweetContentScoreSearchTopProdTweetLabelDropRuleThresholdParam -import com.twitter.visibility.configapi.params.FSRuleParams.HighSpammyTweetContentScoreTrendLatestTweetLabelDropRuleThresholdParam -import com.twitter.visibility.configapi.params.FSRuleParams.HighSpammyTweetContentScoreTrendTopTweetLabelDropRuleThresholdParam -import com.twitter.visibility.configapi.params.FSRuleParams.SkipTweetDetailLimitedEngagementRuleEnabledParam -import com.twitter.visibility.configapi.params.RuleParam -import com.twitter.visibility.configapi.params.RuleParams._ -import com.twitter.visibility.models.TweetSafetyLabelType -import com.twitter.visibility.rules.Condition._ -import com.twitter.visibility.rules.Condition.{True => TrueCondition} -import com.twitter.visibility.rules.Reason._ -import com.twitter.visibility.rules.RuleActionSourceBuilder.TweetSafetyLabelSourceBuilder - -object AbusiveTweetLabelRule - extends NonAuthorWithTweetLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.Abusive - ) - with DoesLogVerdict - -object AbusiveNonFollowerTweetLabelRule - extends NonFollowerWithTweetLabelRule( - Drop(Toxicity), - TweetSafetyLabelType.Abusive - ) - -object AbusiveUqfNonFollowerTweetLabelRule - extends NonFollowerWithUqfTweetLabelRule( - Drop(Toxicity), - TweetSafetyLabelType.Abusive - ) - -object AbusiveHighRecallTweetLabelRule - extends NonAuthorWithTweetLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.AbusiveHighRecall - ) - -object AbusiveHighRecallNonFollowerTweetLabelRule - extends NonFollowerWithTweetLabelRule( - Interstitial(PossiblyUndesirable), - TweetSafetyLabelType.AbusiveHighRecall - ) - -object AutomationTweetLabelRule - extends NonFollowerWithTweetLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.Automation - ) - -object BystanderAbusiveTweetLabelRule - extends NonAuthorWithTweetLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.BystanderAbusive - ) - -object BystanderAbusiveNonFollowerTweetLabelRule - extends NonFollowerWithTweetLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.BystanderAbusive - ) - -abstract class DuplicateContentTweetLabelRule(action: Action) - extends NonAuthorWithTweetLabelRule( - action, - TweetSafetyLabelType.DuplicateContent - ) - -object DuplicateContentTweetLabelDropRule - extends DuplicateContentTweetLabelRule(Drop(TweetLabelDuplicateContent)) - -object DuplicateContentTweetLabelTombstoneRule - extends DuplicateContentTweetLabelRule(Tombstone(Epitaph.Unavailable)) - -object DuplicateMentionTweetLabelRule - extends NonFollowerWithTweetLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.DuplicateMention - ) - -object DuplicateMentionUqfTweetLabelRule - extends NonFollowerWithUqfTweetLabelRule( - Drop(TweetLabelDuplicateMention), - TweetSafetyLabelType.DuplicateMention - ) - -object GoreAndViolenceTweetLabelRule - extends ConditionWithTweetLabelRule( - Drop(Unspecified), - And( - NonAuthorViewer, - TweetComposedBefore(TweetSafetyLabelType.GoreAndViolence.DeprecatedAt) - ), - TweetSafetyLabelType.GoreAndViolence - ) - -object LiveLowQualityTweetLabelRule - extends NonAuthorWithTweetLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.LiveLowQuality - ) - -object LowQualityMentionTweetLabelRule - extends RuleWithConstantAction( - Drop(LowQualityMention), - And( - TweetHasLabelForPerspectivalUser(TweetSafetyLabelType.LowQualityMention), - ViewerHasUqfEnabled - ) - ) - -abstract class NsfwCardImageTweetLabelBaseRule( - override val action: Action, - val additionalCondition: Condition = TrueCondition, -) extends RuleWithConstantAction( - action, - And( - additionalCondition, - TweetHasLabel(TweetSafetyLabelType.NsfwCardImage) - ) - ) - -object NsfwCardImageTweetLabelRule - extends NsfwCardImageTweetLabelBaseRule( - action = Drop(Nsfw), - additionalCondition = NonAuthorViewer, - ) - -object NsfwCardImageAllUsersTweetLabelRule - extends NsfwCardImageTweetLabelBaseRule( - action = Interstitial(Nsfw) - ) - -object NsfwCardImageAvoidAllUsersTweetLabelRule - extends NsfwCardImageTweetLabelBaseRule( - action = Avoid(Some(AvoidReason.ContainsNsfwMedia)), - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableAvoidNsfwRulesParam) - - override val fallbackActionBuilder: Option[ActionBuilder[_ <: Action]] = Some( - new ConstantActionBuilder(Avoid(Some(MightNotBeSuitableForAds)))) -} - -object NsfwCardImageAvoidAdPlacementAllUsersTweetLabelRule - extends NsfwCardImageTweetLabelBaseRule( - action = Avoid(Some(AvoidReason.ContainsNsfwMedia)), - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableAvoidNsfwRulesParam) -} - -object SearchAvoidTweetNsfwAdminRule - extends RuleWithConstantAction( - Avoid(Some(AvoidReason.ContainsNsfwMedia)), - TweetHasNsfwAdminAuthor - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableAvoidNsfwRulesParam) -} - -object SearchAvoidTweetNsfwUserRule - extends RuleWithConstantAction( - Avoid(Some(AvoidReason.ContainsNsfwMedia)), - TweetHasNsfwUserAuthor - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableAvoidNsfwRulesParam) -} - -object NsfwCardImageAllUsersTweetLabelDropRule - extends NsfwCardImageTweetLabelBaseRule( - action = Drop(Nsfw), - ) - -object HighProactiveTosScoreTweetLabelDropRule - extends NonAuthorWithTweetLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.HighProactiveTosScore - ) - -object HighProactiveTosScoreTweetLabelDropSearchRule - extends NonAuthorAndNonFollowerWithTweetLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.HighProactiveTosScore - ) - -object NsfwHighPrecisionTweetLabelRule - extends NonAuthorWithTweetLabelRule( - Drop(Nsfw), - TweetSafetyLabelType.NsfwHighPrecision - ) - -object NsfwHighPrecisionAllUsersTweetLabelDropRule - extends TweetHasLabelRule( - Drop(Nsfw), - TweetSafetyLabelType.NsfwHighPrecision - ) - -object NsfwHighPrecisionInnerQuotedTweetLabelRule - extends ConditionWithTweetLabelRule( - Drop(Nsfw), - And(IsQuotedInnerTweet, NonAuthorViewer), - TweetSafetyLabelType.NsfwHighPrecision - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableNsfwHpQuotedTweetDropRuleParam) -} - -object NsfwHighPrecisionTombstoneInnerQuotedTweetLabelRule - extends ConditionWithTweetLabelRule( - Tombstone(Epitaph.Unavailable), - And(IsQuotedInnerTweet, NonAuthorViewer), - TweetSafetyLabelType.NsfwHighPrecision - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableNsfwHpQuotedTweetTombstoneRuleParam) -} - -object GoreAndViolenceHighPrecisionTweetLabelRule - extends NonAuthorWithTweetLabelRule( - Drop(Nsfw), - TweetSafetyLabelType.GoreAndViolenceHighPrecision - ) - -object NsfwReportedHeuristicsTweetLabelRule - extends NonAuthorWithTweetLabelRule( - Drop(Nsfw), - TweetSafetyLabelType.NsfwReportedHeuristics - ) - -object GoreAndViolenceReportedHeuristicsTweetLabelRule - extends NonAuthorWithTweetLabelRule( - Drop(Nsfw), - TweetSafetyLabelType.GoreAndViolenceReportedHeuristics - ) - -object NsfwHighPrecisionInterstitialAllUsersTweetLabelRule - extends TweetHasLabelRule( - Interstitial(Nsfw), - TweetSafetyLabelType.NsfwHighPrecision - ) - with DoesLogVerdict - -object GoreAndViolenceHighPrecisionAvoidAllUsersTweetLabelRule - extends TweetHasLabelRule( - Avoid(Some(AvoidReason.ContainsNsfwMedia)), - TweetSafetyLabelType.GoreAndViolenceHighPrecision - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableAvoidNsfwRulesParam) - - override val fallbackActionBuilder: Option[ActionBuilder[_ <: Action]] = Some( - new ConstantActionBuilder(Avoid(Some(MightNotBeSuitableForAds)))) -} - -object GoreAndViolenceHighPrecisionAllUsersTweetLabelRule - extends TweetHasLabelRule( - Interstitial(Nsfw), - TweetSafetyLabelType.GoreAndViolenceHighPrecision - ) - with DoesLogVerdict { - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(TweetSafetyLabelType.GoreAndViolenceHighPrecision) - ) -} - -object NsfwReportedHeuristicsAvoidAllUsersTweetLabelRule - extends TweetHasLabelRule( - Avoid(Some(AvoidReason.ContainsNsfwMedia)), - TweetSafetyLabelType.NsfwReportedHeuristics - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableAvoidNsfwRulesParam) - - override val fallbackActionBuilder: Option[ActionBuilder[_ <: Action]] = Some( - new ConstantActionBuilder(Avoid(Some(MightNotBeSuitableForAds)))) -} - -object NsfwReportedHeuristicsAvoidAdPlacementAllUsersTweetLabelRule - extends TweetHasLabelRule( - Avoid(Some(AvoidReason.ContainsNsfwMedia)), - TweetSafetyLabelType.NsfwReportedHeuristics - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableAvoidNsfwRulesParam) - - override val fallbackActionBuilder: Option[ActionBuilder[_ <: Action]] = Some( - new ConstantActionBuilder(Avoid(Some(MightNotBeSuitableForAds)))) -} - -object NsfwReportedHeuristicsAllUsersTweetLabelRule - extends TweetHasLabelRule( - Interstitial(Nsfw), - TweetSafetyLabelType.NsfwReportedHeuristics - ) - -object GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule - extends TweetHasLabelRule( - Interstitial(Nsfw), - TweetSafetyLabelType.GoreAndViolenceReportedHeuristics - ) - -object GoreAndViolenceReportedHeuristicsAvoidAllUsersTweetLabelRule - extends TweetHasLabelRule( - Avoid(Some(AvoidReason.ContainsNsfwMedia)), - TweetSafetyLabelType.GoreAndViolenceReportedHeuristics - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableAvoidNsfwRulesParam) - - override val fallbackActionBuilder: Option[ActionBuilder[_ <: Action]] = Some( - new ConstantActionBuilder(Avoid(Some(MightNotBeSuitableForAds)))) -} - -object GoreAndViolenceReportedHeuristicsAvoidAdPlacementAllUsersTweetLabelRule - extends TweetHasLabelRule( - Avoid(Some(AvoidReason.ContainsNsfwMedia)), - TweetSafetyLabelType.GoreAndViolenceReportedHeuristics - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableAvoidNsfwRulesParam) - - override val fallbackActionBuilder: Option[ActionBuilder[_ <: Action]] = Some( - new ConstantActionBuilder(Avoid(Some(MightNotBeSuitableForAds)))) -} - -object GoreAndViolenceHighPrecisionAllUsersTweetLabelDropRule - extends TweetHasLabelRule( - Drop(Nsfw), - TweetSafetyLabelType.GoreAndViolenceHighPrecision - ) - -object NsfwReportedHeuristicsAllUsersTweetLabelDropRule - extends TweetHasLabelRule( - Drop(Nsfw), - TweetSafetyLabelType.NsfwReportedHeuristics - ) - -object GoreAndViolenceReportedHeuristicsAllUsersTweetLabelDropRule - extends TweetHasLabelRule( - Drop(Nsfw), - TweetSafetyLabelType.GoreAndViolenceReportedHeuristics - ) - -object NsfwHighRecallTweetLabelRule - extends NonAuthorWithTweetLabelRule( - Drop(Nsfw), - TweetSafetyLabelType.NsfwHighRecall - ) - -object NsfwHighRecallAllUsersTweetLabelDropRule - extends TweetHasLabelRule( - Drop(Nsfw), - TweetSafetyLabelType.NsfwHighRecall - ) - -abstract class PdnaTweetLabelRule( - override val action: Action, - val additionalCondition: Condition) - extends ConditionWithTweetLabelRule( - action, - And(NonAuthorViewer, additionalCondition), - TweetSafetyLabelType.Pdna - ) - -object PdnaTweetLabelRule extends PdnaTweetLabelRule(Drop(PdnaTweet), Condition.True) - -object PdnaTweetLabelTombstoneRule - extends PdnaTweetLabelRule(Tombstone(Epitaph.Unavailable), Condition.True) - -object PdnaQuotedTweetLabelTombstoneRule - extends PdnaTweetLabelRule(Tombstone(Epitaph.Unavailable), Condition.IsQuotedInnerTweet) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnablePdnaQuotedTweetTombstoneRuleParam) -} - -object PdnaAllUsersTweetLabelRule - extends TweetHasLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.Pdna - ) - -object SearchBlacklistTweetLabelRule - extends NonAuthorWithTweetLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.SearchBlacklist - ) - -object SearchBlacklistHighRecallTweetLabelDropRule - extends NonAuthorAndNonFollowerWithTweetLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.SearchBlacklistHighRecall - ) - -abstract class SpamTweetLabelRule( - override val action: Action, - val additionalCondition: Condition) - extends ConditionWithTweetLabelRule( - action, - And(NonAuthorViewer, additionalCondition), - TweetSafetyLabelType.Spam - ) - with DoesLogVerdict - -object SpamTweetLabelRule extends SpamTweetLabelRule(Drop(TweetLabeledSpam), Condition.True) - -object SpamTweetLabelTombstoneRule - extends SpamTweetLabelRule(Tombstone(Epitaph.Unavailable), Condition.True) - -object SpamQuotedTweetLabelTombstoneRule - extends SpamTweetLabelRule(Tombstone(Epitaph.Unavailable), Condition.IsQuotedInnerTweet) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableSpamQuotedTweetTombstoneRuleParam) -} - -object SpamAllUsersTweetLabelRule - extends TweetHasLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.Spam - ) - -abstract class BounceTweetLabelRule(override val action: Action) - extends NonAuthorWithTweetLabelRule( - action, - TweetSafetyLabelType.Bounce - ) - -object BounceTweetLabelRule extends BounceTweetLabelRule(Drop(Bounce)) - -object BounceTweetLabelTombstoneRule extends BounceTweetLabelRule(Tombstone(Epitaph.Bounced)) - -abstract class BounceOuterTweetLabelRule(override val action: Action) - extends ConditionWithTweetLabelRule( - action, - And(Not(Condition.IsQuotedInnerTweet), NonAuthorViewer), - TweetSafetyLabelType.Bounce - ) - -object BounceOuterTweetTombstoneRule extends BounceOuterTweetLabelRule(Tombstone(Epitaph.Bounced)) - -object BounceQuotedTweetTombstoneRule - extends ConditionWithTweetLabelRule( - Tombstone(Epitaph.Bounced), - Condition.IsQuotedInnerTweet, - TweetSafetyLabelType.Bounce - ) - -object BounceAllUsersTweetLabelRule - extends TweetHasLabelRule( - Drop(Bounce), - TweetSafetyLabelType.Bounce - ) - - -abstract class SpamHighRecallTweetLabelRule(action: Action) - extends NonAuthorWithTweetLabelRule( - action, - TweetSafetyLabelType.SpamHighRecall - ) - -object SpamHighRecallTweetLabelDropRule - extends SpamHighRecallTweetLabelRule(Drop(SpamHighRecallTweet)) - -object SpamHighRecallTweetLabelTombstoneRule - extends SpamHighRecallTweetLabelRule(Tombstone(Epitaph.Unavailable)) - -object UntrustedUrlAllViewersTweetLabelRule - extends TweetHasLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.UntrustedUrl - ) - -object DownrankSpamReplyAllViewersTweetLabelRule - extends TweetHasLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.DownrankSpamReply - ) { - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableDownrankSpamReplySectioningRuleParam) -} - -object UntrustedUrlTweetLabelRule - extends NonAuthorWithTweetLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.UntrustedUrl - ) - -object DownrankSpamReplyTweetLabelRule - extends NonAuthorWithTweetLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.DownrankSpamReply - ) { - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableDownrankSpamReplySectioningRuleParam) -} - -object UntrustedUrlUqfNonFollowerTweetLabelRule - extends NonFollowerWithUqfTweetLabelRule( - Drop(UntrustedUrl), - TweetSafetyLabelType.UntrustedUrl - ) - -object DownrankSpamReplyUqfNonFollowerTweetLabelRule - extends NonFollowerWithUqfTweetLabelRule( - Drop(SpamReplyDownRank), - TweetSafetyLabelType.DownrankSpamReply - ) { - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableDownrankSpamReplySectioningRuleParam) -} - -object NsfaHighRecallTweetLabelRule - extends RuleWithConstantAction( - Drop(Unspecified), - And( - NonAuthorViewer, - TweetHasLabel(TweetSafetyLabelType.NsfaHighRecall) - ) - ) - -object NsfaHighRecallTweetLabelInterstitialRule - extends RuleWithConstantAction( - Interstitial(Unspecified), - And( - NonAuthorViewer, - TweetHasLabel(TweetSafetyLabelType.NsfaHighRecall) - ) - ) - -object NsfwVideoTweetLabelDropRule - extends NonAuthorWithTweetLabelRule( - Drop(Nsfw), - TweetSafetyLabelType.NsfwVideo - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableNsfwTextSectioningRuleParam) -} - -object NsfwTextTweetLabelDropRule - extends NonAuthorWithTweetLabelRule( - Drop(Nsfw), - TweetSafetyLabelType.NsfwText - ) - -object NsfwVideoAllUsersTweetLabelDropRule - extends TweetHasLabelRule( - Drop(Nsfw), - TweetSafetyLabelType.NsfwVideo - ) - -object NsfwTextAllUsersTweetLabelDropRule - extends TweetHasLabelRule( - Drop(Nsfw), - TweetSafetyLabelType.NsfwText - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableNsfwTextSectioningRuleParam) -} - -abstract class BaseLowQualityTweetLabelRule(action: Action) - extends RuleWithConstantAction( - action, - And( - TweetHasLabel(TweetSafetyLabelType.LowQuality), - TweetComposedBefore(PublicInterest.PolicyConfig.LowQualityProxyLabelStart), - NonAuthorViewer - ) - ) - with DoesLogVerdict { - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(TweetSafetyLabelType.LowQuality)) -} - -object LowQualityTweetLabelDropRule extends BaseLowQualityTweetLabelRule(Drop(LowQualityTweet)) - -object LowQualityTweetLabelTombstoneRule - extends BaseLowQualityTweetLabelRule(Tombstone(Epitaph.Unavailable)) - -abstract class SafetyCrisisLevelDropRule(level: Int, condition: Condition = TrueCondition) - extends ConditionWithTweetLabelRule( - Drop(Unspecified), - And( - NonAuthorViewer, - condition, - TweetHasSafetyLabelWithScoreEqInt(TweetSafetyLabelType.SafetyCrisis, level) - ), - TweetSafetyLabelType.SafetyCrisis - ) - -object SafetyCrisisAnyLevelDropRule - extends NonAuthorWithTweetLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.SafetyCrisis - ) - -object SafetyCrisisLevel2DropRule extends SafetyCrisisLevelDropRule(2, Not(ViewerDoesFollowAuthor)) - -object SafetyCrisisLevel3DropRule extends SafetyCrisisLevelDropRule(3, Not(ViewerDoesFollowAuthor)) - -object SafetyCrisisLevel4DropRule extends SafetyCrisisLevelDropRule(4) - -abstract class SafetyCrisisLevelSectionRule(level: Int) - extends ConditionWithNotInnerCircleOfFriendsRule( - ConversationSectionAbusiveQuality, - And( - TweetHasLabel(TweetSafetyLabelType.SafetyCrisis), - TweetHasSafetyLabelWithScoreEqInt(TweetSafetyLabelType.SafetyCrisis, level)) - ) { - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(TweetSafetyLabelType.SafetyCrisis)) -} - -object SafetyCrisisLevel3SectionRule - extends SafetyCrisisLevelSectionRule(3) - with DoesLogVerdictDecidered { - override def verdictLogDeciderKey = DeciderKey.EnableDownlevelRuleVerdictLogging -} - -object SafetyCrisisLevel4SectionRule - extends SafetyCrisisLevelSectionRule(4) - with DoesLogVerdictDecidered { - override def verdictLogDeciderKey = DeciderKey.EnableDownlevelRuleVerdictLogging -} - -object DoNotAmplifyDropRule - extends NonFollowerWithTweetLabelRule(Drop(Unspecified), TweetSafetyLabelType.DoNotAmplify) - -object DoNotAmplifyAllViewersDropRule - extends TweetHasLabelRule(Drop(Unspecified), TweetSafetyLabelType.DoNotAmplify) - -object DoNotAmplifySectionRule - extends ConditionWithNotInnerCircleOfFriendsRule( - ConversationSectionAbusiveQuality, - TweetHasLabel(TweetSafetyLabelType.DoNotAmplify)) - -object HighPSpammyScoreAllViewerDropRule - extends TweetHasLabelRule(Drop(Unspecified), TweetSafetyLabelType.HighPSpammyTweetScore) - -object HighPSpammyTweetScoreSearchTweetLabelDropRule - extends RuleWithConstantAction( - action = Drop(Unspecified), - condition = And( - LoggedOutOrViewerNotFollowingAuthor, - TweetHasLabelWithScoreAboveThreshold( - TweetSafetyLabelType.HighPSpammyTweetScore, - ModelScoreThresholds.HighPSpammyTweetScoreThreshold) - ) - ) - with DoesLogVerdictDecidered { - override def enabled: Seq[RuleParam[Boolean]] = Seq( - EnableHighPSpammyTweetScoreSearchTweetLabelDropRuleParam) - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(TweetSafetyLabelType.HighPSpammyTweetScore)) - override def verdictLogDeciderKey: DeciderKey.Value = - DeciderKey.EnableSpammyTweetRuleVerdictLogging -} - -object AdsManagerDenyListAllUsersTweetLabelRule - extends TweetHasLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.AdsManagerDenyList - ) - -abstract class SmyteSpamTweetLabelRule(action: Action) - extends NonAuthorWithTweetLabelRule( - action, - TweetSafetyLabelType.SmyteSpamTweet - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableSmyteSpamTweetRuleParam) -} - -object SmyteSpamTweetLabelDropRule extends SmyteSpamTweetLabelRule(Drop(TweetLabeledSpam)) - -object SmyteSpamTweetLabelTombstoneRule - extends SmyteSpamTweetLabelRule(Tombstone(Epitaph.Unavailable)) - -object SmyteSpamTweetLabelDropSearchRule extends SmyteSpamTweetLabelRule(Drop(Unspecified)) - -object HighSpammyTweetContentScoreSearchLatestTweetLabelDropRule - extends RuleWithConstantAction( - action = Drop(Unspecified), - condition = And( - Not(IsTweetInTweetLevelStcmHoldback), - LoggedOutOrViewerNotFollowingAuthor, - TweetHasLabelWithScoreAboveThresholdWithParam( - TweetSafetyLabelType.HighSpammyTweetContentScore, - HighSpammyTweetContentScoreSearchLatestProdTweetLabelDropRuleThresholdParam) - ) - ) - with DoesLogVerdictDecidered { - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(TweetSafetyLabelType.HighSpammyTweetContentScore)) - override def verdictLogDeciderKey: DeciderKey.Value = - DeciderKey.EnableSpammyTweetRuleVerdictLogging -} - -object HighSpammyTweetContentScoreSearchTopTweetLabelDropRule - extends RuleWithConstantAction( - action = Drop(Unspecified), - condition = And( - Not(IsTweetInTweetLevelStcmHoldback), - LoggedOutOrViewerNotFollowingAuthor, - TweetHasLabelWithScoreAboveThresholdWithParam( - TweetSafetyLabelType.HighSpammyTweetContentScore, - HighSpammyTweetContentScoreSearchTopProdTweetLabelDropRuleThresholdParam) - ) - ) - with DoesLogVerdictDecidered { - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(TweetSafetyLabelType.HighSpammyTweetContentScore)) - override def verdictLogDeciderKey: DeciderKey.Value = - DeciderKey.EnableSpammyTweetRuleVerdictLogging - -} - -object HighSpammyTweetContentScoreTrendsTopTweetLabelDropRule - extends RuleWithConstantAction( - action = Drop(Unspecified), - condition = And( - Not(IsTweetInTweetLevelStcmHoldback), - LoggedOutOrViewerNotFollowingAuthor, - IsTrendClickSourceSearchResult, - TweetHasLabelWithScoreAboveThresholdWithParam( - TweetSafetyLabelType.HighSpammyTweetContentScore, - HighSpammyTweetContentScoreTrendTopTweetLabelDropRuleThresholdParam) - ) - ) - with DoesLogVerdictDecidered { - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(TweetSafetyLabelType.HighSpammyTweetContentScore)) - override def verdictLogDeciderKey: DeciderKey.Value = - DeciderKey.EnableSpammyTweetRuleVerdictLogging - -} - -object HighSpammyTweetContentScoreTrendsLatestTweetLabelDropRule - extends RuleWithConstantAction( - action = Drop(Unspecified), - condition = And( - Not(IsTweetInTweetLevelStcmHoldback), - LoggedOutOrViewerNotFollowingAuthor, - IsTrendClickSourceSearchResult, - TweetHasLabelWithScoreAboveThresholdWithParam( - TweetSafetyLabelType.HighSpammyTweetContentScore, - HighSpammyTweetContentScoreTrendLatestTweetLabelDropRuleThresholdParam) - ) - ) - with DoesLogVerdictDecidered { - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(TweetSafetyLabelType.HighSpammyTweetContentScore)) - override def verdictLogDeciderKey: DeciderKey.Value = - DeciderKey.EnableSpammyTweetRuleVerdictLogging -} - -object GoreAndViolenceTopicHighRecallTweetLabelRule - extends NonAuthorWithTweetLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.GoreAndViolenceTopicHighRecall - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq( - EnableGoreAndViolenceTopicHighRecallTweetLabelRule) -} - -object CopypastaSpamAllViewersTweetLabelRule - extends TweetHasLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.CopypastaSpam - ) { - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableCopypastaSpamSearchDropRule) -} - -object CopypastaSpamAllViewersSearchTweetLabelRule - extends TweetHasLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.CopypastaSpam - ) { - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableCopypastaSpamSearchDropRule) -} - -object CopypastaSpamNonFollowerSearchTweetLabelRule - extends NonFollowerWithTweetLabelRule( - Drop(Unspecified), - TweetSafetyLabelType.CopypastaSpam - ) { - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableCopypastaSpamSearchDropRule) -} - -object CopypastaSpamAbusiveQualityTweetLabelRule - extends ConditionWithNotInnerCircleOfFriendsRule( - ConversationSectionAbusiveQuality, - TweetHasLabel(TweetSafetyLabelType.CopypastaSpam) - ) - with DoesLogVerdictDecidered { - override def enabled: Seq[RuleParam[Boolean]] = Seq( - EnableCopypastaSpamDownrankConvosAbusiveQualityRule) - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(TweetSafetyLabelType.CopypastaSpam)) - override def verdictLogDeciderKey = DeciderKey.EnableDownlevelRuleVerdictLogging -} - -object DynamicProductAdLimitedEngagementTweetLabelRule - extends TweetHasLabelRule( - LimitedEngagements(LimitedEngagementReason.DynamicProductAd), - TweetSafetyLabelType.DynamicProductAd) - -object SkipTweetDetailLimitedEngagementTweetLabelRule - extends AlwaysActRule(LimitedEngagements(LimitedEngagementReason.SkipTweetDetail)) { - override def enabled: Seq[RuleParam[Boolean]] = Seq( - SkipTweetDetailLimitedEngagementRuleEnabledParam) -} - -object DynamicProductAdDropTweetLabelRule - extends TweetHasLabelRule(Drop(Unspecified), TweetSafetyLabelType.DynamicProductAd) - -object NsfwTextHighPrecisionTweetLabelDropRule - extends RuleWithConstantAction( - Drop(Reason.Nsfw), - And( - NonAuthorViewer, - Or( - TweetHasLabel(TweetSafetyLabelType.ExperimentalSensitiveIllegal2), - TweetHasLabel(TweetSafetyLabelType.NsfwTextHighPrecision) - ) - ) - ) - with DoesLogVerdict { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableNsfwTextHighPrecisionDropRuleParam) - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(TweetSafetyLabelType.NsfwTextHighPrecision)) -} - - -object ExperimentalNudgeLabelRule - extends TweetHasLabelRule( - TweetVisibilityNudge(TweetVisibilityNudgeReason.ExperimentalNudgeSafetyLabelReason), - TweetSafetyLabelType.ExperimentalNudge) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableExperimentalNudgeEnabledParam) -} - -object NsfwTextTweetLabelAvoidRule - extends RuleWithConstantAction( - Avoid(), - Or( - TweetHasLabel(TweetSafetyLabelType.ExperimentalSensitiveIllegal2), - TweetHasLabel(TweetSafetyLabelType.NsfwTextHighPrecision) - ) - ) { - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(TweetSafetyLabelType.NsfwTextHighPrecision)) -} - -object DoNotAmplifyTweetLabelAvoidRule - extends TweetHasLabelRule( - Avoid(), - TweetSafetyLabelType.DoNotAmplify - ) { - override val fallbackActionBuilder: Option[ActionBuilder[_ <: Action]] = Some( - new ConstantActionBuilder(Avoid(Some(MightNotBeSuitableForAds)))) -} - -object NsfaHighPrecisionTweetLabelAvoidRule - extends TweetHasLabelRule( - Avoid(), - TweetSafetyLabelType.NsfaHighPrecision - ) { - override val fallbackActionBuilder: Option[ActionBuilder[_ <: Action]] = Some( - new ConstantActionBuilder(Avoid(Some(MightNotBeSuitableForAds)))) -} - -object NsfwHighPrecisionTweetLabelAvoidRule - extends TweetHasLabelRule( - Avoid(Some(AvoidReason.ContainsNsfwMedia)), - TweetSafetyLabelType.NsfwHighPrecision - ) { - override val fallbackActionBuilder: Option[ActionBuilder[_ <: Action]] = Some( - new ConstantActionBuilder(Avoid(Some(MightNotBeSuitableForAds)))) -} - -object NsfwHighRecallTweetLabelAvoidRule - extends TweetHasLabelRule( - Avoid(Some(AvoidReason.ContainsNsfwMedia)), - TweetSafetyLabelType.NsfwHighRecall - ) { - override val fallbackActionBuilder: Option[ActionBuilder[_ <: Action]] = Some( - new ConstantActionBuilder(Avoid(Some(MightNotBeSuitableForAds)))) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/TweetRules.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/TweetRules.scala deleted file mode 100644 index 666b2debf..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/TweetRules.scala +++ /dev/null @@ -1,594 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.visibility.common.actions.LimitedEngagementReason -import com.twitter.visibility.configapi.params.FSRuleParams.AdAvoidanceHighToxicityModelScoreThresholdParam -import com.twitter.visibility.configapi.params.FSRuleParams.AdAvoidanceReportedTweetModelScoreThresholdParam -import com.twitter.visibility.configapi.params.FSRuleParams.CommunityTweetCommunityUnavailableLimitedActionsRulesEnabledParam -import com.twitter.visibility.configapi.params.FSRuleParams.CommunityTweetDropProtectedRuleEnabledParam -import com.twitter.visibility.configapi.params.FSRuleParams.CommunityTweetDropRuleEnabledParam -import com.twitter.visibility.configapi.params.FSRuleParams.CommunityTweetLimitedActionsRulesEnabledParam -import com.twitter.visibility.configapi.params.FSRuleParams.CommunityTweetMemberRemovedLimitedActionsRulesEnabledParam -import com.twitter.visibility.configapi.params.FSRuleParams.CommunityTweetNonMemberLimitedActionsRuleEnabledParam -import com.twitter.visibility.configapi.params.FSRuleParams.StaleTweetLimitedActionsRulesEnabledParam -import com.twitter.visibility.configapi.params.FSRuleParams.TrustedFriendsTweetLimitedEngagementsRuleEnabledParam -import com.twitter.visibility.configapi.params.RuleParam -import com.twitter.visibility.configapi.params.RuleParams -import com.twitter.visibility.configapi.params.RuleParams._ -import com.twitter.visibility.features.{TweetDeleteReason => FeatureTweetDeleteReason} -import com.twitter.visibility.models.TweetDeleteReason -import com.twitter.visibility.models.TweetSafetyLabelType -import com.twitter.visibility.rules.Condition.ViewerIsExclusiveTweetAuthor -import com.twitter.visibility.rules.Condition._ -import com.twitter.visibility.rules.Reason.CommunityTweetAuthorRemoved -import com.twitter.visibility.rules.Reason.CommunityTweetHidden -import com.twitter.visibility.rules.Reason.Nsfw -import com.twitter.visibility.rules.Reason.StaleTweet -import com.twitter.visibility.rules.Reason.Unspecified -import com.twitter.visibility.rules.RuleActionSourceBuilder.TweetSafetyLabelSourceBuilder - -abstract class TweetHasLabelRule(action: Action, tweetSafetyLabelType: TweetSafetyLabelType) - extends RuleWithConstantAction(action, TweetHasLabel(tweetSafetyLabelType)) { - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(tweetSafetyLabelType)) -} - -abstract class ConditionWithTweetLabelRule( - action: Action, - condition: Condition, - tweetSafetyLabelType: TweetSafetyLabelType) - extends RuleWithConstantAction(action, And(TweetHasLabel(tweetSafetyLabelType), condition)) { - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(tweetSafetyLabelType)) -} - -abstract class NonAuthorWithTweetLabelRule( - action: Action, - tweetSafetyLabelType: TweetSafetyLabelType) - extends ConditionWithTweetLabelRule(action, NonAuthorViewer, tweetSafetyLabelType) { - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - TweetSafetyLabelSourceBuilder(tweetSafetyLabelType)) -} - -abstract class NonFollowerWithTweetLabelRule( - action: Action, - tweetSafetyLabelType: TweetSafetyLabelType) - extends ConditionWithTweetLabelRule( - action, - LoggedOutOrViewerNotFollowingAuthor, - tweetSafetyLabelType - ) - -abstract class NonAuthorAndNonFollowerWithTweetLabelRule( - action: Action, - tweetSafetyLabelType: TweetSafetyLabelType) - extends ConditionWithTweetLabelRule( - action, - And(NonAuthorViewer, LoggedOutOrViewerNotFollowingAuthor), - tweetSafetyLabelType - ) - -abstract class NonFollowerWithUqfTweetLabelRule( - action: Action, - tweetSafetyLabelType: TweetSafetyLabelType) - extends ConditionWithTweetLabelRule( - action, - Or( - LoggedOutViewer, - And( - NonAuthorViewer, - Not(ViewerDoesFollowAuthor), - ViewerHasUqfEnabled - ) - ), - tweetSafetyLabelType - ) - -abstract class ViewerWithUqfTweetLabelRule(action: Action, labelValue: TweetSafetyLabelType) - extends ConditionWithTweetLabelRule(action, ViewerHasUqfEnabled, labelValue) - -case object ConversationControlRules { - - abstract class ConversationControlBaseRule(condition: Condition) - extends RuleWithConstantAction( - LimitedEngagements(LimitedEngagementReason.ConversationControl), - condition) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(TweetConversationControlEnabledParam) - } - - object LimitRepliesCommunityConversationRule - extends ConversationControlBaseRule( - And( - TweetIsCommunityConversation, - Not( - Or( - LoggedOutViewer, - Retweet, - ViewerIsTweetConversationRootAuthor, - ViewerIsInvitedToTweetConversation, - ConversationRootAuthorDoesFollowViewer - )) - ) - ) - - object LimitRepliesFollowersConversationRule - extends ConversationControlBaseRule( - And( - TweetIsFollowersConversation, - Not( - Or( - LoggedOutViewer, - Retweet, - ViewerIsTweetConversationRootAuthor, - ViewerIsInvitedToTweetConversation, - ViewerDoesFollowConversationRootAuthor - )) - ) - ) - - object LimitRepliesByInvitationConversationRule - extends ConversationControlBaseRule( - And( - TweetIsByInvitationConversation, - Not( - Or( - LoggedOutViewer, - Retweet, - ViewerIsTweetConversationRootAuthor, - ViewerIsInvitedToTweetConversation - )) - ) - ) - -} - -abstract class NonAuthorViewerOptInFilteringWithTweetLabelRule( - action: Action, - tweetSafetyLabelType: TweetSafetyLabelType) - extends ConditionWithTweetLabelRule( - action, - And(NonAuthorViewer, LoggedOutOrViewerOptInFiltering), - tweetSafetyLabelType) - -abstract class NonFollowerViewerOptInFilteringWithTweetLabelRule( - action: Action, - tweetSafetyLabelType: TweetSafetyLabelType) - extends ConditionWithTweetLabelRule( - action, - And(LoggedOutOrViewerNotFollowingAuthor, LoggedOutOrViewerOptInFiltering), - tweetSafetyLabelType - ) - -object TweetNsfwUserDropRule extends RuleWithConstantAction(Drop(Nsfw), TweetHasNsfwUserAuthor) -object TweetNsfwAdminDropRule extends RuleWithConstantAction(Drop(Nsfw), TweetHasNsfwAdminAuthor) - -object NullcastedTweetRule - extends RuleWithConstantAction( - Drop(Unspecified), - And(Nullcast, Not(Retweet), Not(IsQuotedInnerTweet), Not(TweetIsCommunityTweet))) - -object MutedRetweetsRule - extends RuleWithConstantAction(Drop(Unspecified), And(Retweet, ViewerMutesRetweetsFromAuthor)) - -abstract class FilterCommunityTweetsRule(override val action: Action) - extends RuleWithConstantAction(action, TweetIsCommunityTweet) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(CommunityTweetDropRuleEnabledParam) -} - -object DropCommunityTweetsRule extends FilterCommunityTweetsRule(Drop(CommunityTweetHidden)) - -object TombstoneCommunityTweetsRule - extends FilterCommunityTweetsRule(Tombstone(Epitaph.Unavailable)) - -abstract class FilterCommunityTweetCommunityNotVisibleRule(override val action: Action) - extends RuleWithConstantAction( - action, - And( - NonAuthorViewer, - TweetIsCommunityTweet, - Not(CommunityTweetCommunityVisible), - )) { - override def enabled: Seq[RuleParam[Boolean]] = - Seq(DropCommunityTweetWithUndefinedCommunityRuleEnabledParam) -} - -object DropCommunityTweetCommunityNotVisibleRule - extends FilterCommunityTweetCommunityNotVisibleRule(Drop(CommunityTweetHidden)) - -object TombstoneCommunityTweetCommunityNotVisibleRule - extends FilterCommunityTweetCommunityNotVisibleRule(Tombstone(Epitaph.Unavailable)) - -abstract class FilterAllCommunityTweetsRule(override val action: Action) - extends RuleWithConstantAction(action, TweetIsCommunityTweet) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(CommunityTweetsEnabledParam) -} - -object DropAllCommunityTweetsRule extends FilterAllCommunityTweetsRule(Drop(Unspecified)) - -object TombstoneAllCommunityTweetsRule - extends FilterAllCommunityTweetsRule(Tombstone(Epitaph.Unavailable)) - -object DropOuterCommunityTweetsRule - extends RuleWithConstantAction( - Drop(Unspecified), - And(TweetIsCommunityTweet, Not(IsQuotedInnerTweet))) - -object DropAllHiddenCommunityTweetsRule - extends RuleWithConstantAction( - Drop(Unspecified), - And(TweetIsCommunityTweet, CommunityTweetIsHidden)) - -abstract class FilterHiddenCommunityTweetsRule(override val action: Action) - extends RuleWithConstantAction( - action, - And( - NonAuthorViewer, - TweetIsCommunityTweet, - CommunityTweetIsHidden, - Not(ViewerIsCommunityModerator) - )) - -object DropHiddenCommunityTweetsRule - extends FilterHiddenCommunityTweetsRule(Drop(CommunityTweetHidden)) - -object TombstoneHiddenCommunityTweetsRule - extends FilterHiddenCommunityTweetsRule(Tombstone(Epitaph.CommunityTweetHidden)) - -object DropAllAuthorRemovedCommunityTweetsRule - extends RuleWithConstantAction( - Drop(Unspecified), - And(TweetIsCommunityTweet, CommunityTweetAuthorIsRemoved)) - -abstract class FilterAuthorRemovedCommunityTweetsRule(override val action: Action) - extends RuleWithConstantAction( - action, - And( - NonAuthorViewer, - TweetIsCommunityTweet, - CommunityTweetAuthorIsRemoved, - Not(ViewerIsCommunityModerator) - )) - -object DropAuthorRemovedCommunityTweetsRule - extends FilterAuthorRemovedCommunityTweetsRule(Drop(CommunityTweetAuthorRemoved)) - -object TombstoneAuthorRemovedCommunityTweetsRule - extends FilterAuthorRemovedCommunityTweetsRule(Tombstone(Epitaph.Unavailable)) - -abstract class FilterProtectedCommunityTweetsRule(override val action: Action) - extends RuleWithConstantAction( - action, - And(TweetIsCommunityTweet, ProtectedAuthor, NonAuthorViewer)) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(CommunityTweetDropProtectedRuleEnabledParam) -} - -object DropProtectedCommunityTweetsRule - extends FilterProtectedCommunityTweetsRule(Drop(CommunityTweetHidden)) - -object TombstoneProtectedCommunityTweetsRule - extends FilterProtectedCommunityTweetsRule(Tombstone(Epitaph.Unavailable)) - -abstract class CommunityTweetCommunityUnavailableLimitedActionsRule( - reason: LimitedEngagementReason, - condition: CommunityTweetCommunityUnavailable, -) extends RuleWithConstantAction( - LimitedEngagements(reason), - And( - Not(NonAuthorViewer), - TweetIsCommunityTweet, - condition, - ) - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq( - CommunityTweetCommunityUnavailableLimitedActionsRulesEnabledParam) -} - -object CommunityTweetCommunityNotFoundLimitedActionsRule - extends CommunityTweetCommunityUnavailableLimitedActionsRule( - LimitedEngagementReason.CommunityTweetCommunityNotFound, - CommunityTweetCommunityNotFound, - ) - -object CommunityTweetCommunityDeletedLimitedActionsRule - extends CommunityTweetCommunityUnavailableLimitedActionsRule( - LimitedEngagementReason.CommunityTweetCommunityDeleted, - CommunityTweetCommunityDeleted, - ) - -object CommunityTweetCommunitySuspendedLimitedActionsRule - extends CommunityTweetCommunityUnavailableLimitedActionsRule( - LimitedEngagementReason.CommunityTweetCommunitySuspended, - CommunityTweetCommunitySuspended, - ) - -abstract class CommunityTweetModeratedLimitedActionsRule( - reason: LimitedEngagementReason, - condition: CommunityTweetIsModerated, - enabledParam: RuleParam[Boolean], -) extends RuleWithConstantAction( - LimitedEngagements(reason), - And( - TweetIsCommunityTweet, - condition, - Or( - Not(NonAuthorViewer), - ViewerIsCommunityModerator, - ) - )) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(enabledParam) -} - -object CommunityTweetMemberRemovedLimitedActionsRule - extends CommunityTweetModeratedLimitedActionsRule( - LimitedEngagementReason.CommunityTweetMemberRemoved, - CommunityTweetAuthorIsRemoved, - CommunityTweetMemberRemovedLimitedActionsRulesEnabledParam, - ) - -object CommunityTweetHiddenLimitedActionsRule - extends CommunityTweetModeratedLimitedActionsRule( - LimitedEngagementReason.CommunityTweetHidden, - CommunityTweetIsHidden, - CommunityTweetLimitedActionsRulesEnabledParam, - ) - -abstract class CommunityTweetLimitedActionsRule( - reason: LimitedEngagementReason, - condition: Condition, -) extends RuleWithConstantAction( - LimitedEngagements(reason), - And( - TweetIsCommunityTweet, - condition - )) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(CommunityTweetLimitedActionsRulesEnabledParam) -} - -object CommunityTweetMemberLimitedActionsRule - extends CommunityTweetLimitedActionsRule( - LimitedEngagementReason.CommunityTweetMember, - ViewerIsCommunityMember, - ) - -object CommunityTweetNonMemberLimitedActionsRule - extends CommunityTweetLimitedActionsRule( - LimitedEngagementReason.CommunityTweetNonMember, - Not(ViewerIsCommunityMember), - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq( - CommunityTweetNonMemberLimitedActionsRuleEnabledParam) -} - -object ReportedTweetInterstitialRule - extends RuleWithConstantAction( - Interstitial(Reason.ViewerReportedTweet), - And( - NonAuthorViewer, - Not(Retweet), - ViewerReportsTweet - )) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableReportedTweetInterstitialRule) -} - -object ReportedTweetInterstitialSearchRule - extends RuleWithConstantAction( - Interstitial(Reason.ViewerReportedTweet), - And( - NonAuthorViewer, - Not(Retweet), - ViewerReportsTweet - )) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableReportedTweetInterstitialSearchRule) -} - -abstract class FilterExclusiveTweetContentRule( - action: Action, - additionalCondition: Condition = Condition.True) - extends RuleWithConstantAction( - action, - And( - additionalCondition, - TweetIsExclusiveContent, - Or( - LoggedOutViewer, - Not( - Or( - ViewerIsExclusiveTweetAuthor, - ViewerSuperFollowsExclusiveTweetAuthor, - And( - Not(NonAuthorViewer), - Not(Retweet) - ) - ) - ), - ), - ) - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableDropExclusiveTweetContentRule) - override def enableFailClosed: Seq[RuleParam[Boolean]] = Seq( - EnableDropExclusiveTweetContentRuleFailClosed) -} - -object DropExclusiveTweetContentRule - extends FilterExclusiveTweetContentRule(Drop(Reason.ExclusiveTweet)) - -object TombstoneExclusiveTweetContentRule - extends FilterExclusiveTweetContentRule(Tombstone(Epitaph.SuperFollowsContent)) - -object TombstoneExclusiveQuotedTweetContentRule - extends FilterExclusiveTweetContentRule( - Tombstone(Epitaph.SuperFollowsContent), - IsQuotedInnerTweet - ) - -object DropAllExclusiveTweetsRule - extends RuleWithConstantAction( - Drop(Reason.ExclusiveTweet), - TweetIsExclusiveContent - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableDropAllExclusiveTweetsRuleParam) - override def enableFailClosed: Seq[RuleParam[Boolean]] = Seq( - EnableDropAllExclusiveTweetsRuleFailClosedParam) -} - -object DropTweetsWithGeoRestrictedMediaRule - extends RuleWithConstantAction(Drop(Unspecified), MediaRestrictedInViewerCountry) { - override def enabled: Seq[RuleParam[Boolean]] = Seq( - EnableDropTweetsWithGeoRestrictedMediaRuleParam) -} - -object TrustedFriendsTweetLimitedEngagementsRule - extends RuleWithConstantAction( - LimitedEngagements(LimitedEngagementReason.TrustedFriendsTweet), - TweetIsTrustedFriendsContent - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq( - TrustedFriendsTweetLimitedEngagementsRuleEnabledParam - ) -} - -object DropAllTrustedFriendsTweetsRule - extends RuleWithConstantAction( - Drop(Reason.TrustedFriendsTweet), - TweetIsTrustedFriendsContent - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableDropAllTrustedFriendsTweetsRuleParam) - override def enableFailClosed: Seq[RuleParam[Boolean]] = Seq(RuleParams.True) -} - -object DropAllCollabInvitationTweetsRule - extends RuleWithConstantAction( - Drop(Unspecified), - TweetIsCollabInvitationContent - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableDropAllCollabInvitationTweetsRuleParam) - override def enableFailClosed: Seq[RuleParam[Boolean]] = Seq(RuleParams.True) -} - -abstract class FilterTrustedFriendsTweetContentRule(action: Action) - extends OnlyWhenNotAuthorViewerRule( - action, - And( - TweetIsTrustedFriendsContent, - Not( - Or( - ViewerIsTrustedFriendsTweetAuthor, - ViewerIsTrustedFriend - ) - ) - ) - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableDropTrustedFriendsTweetContentRuleParam) - override def enableFailClosed: Seq[RuleParam[Boolean]] = Seq(RuleParams.True) -} - -object DropTrustedFriendsTweetContentRule - extends FilterTrustedFriendsTweetContentRule(Drop(Reason.TrustedFriendsTweet)) - -object TombstoneTrustedFriendsTweetContentRule - extends FilterTrustedFriendsTweetContentRule(Tombstone(Epitaph.Unavailable)) - -object TweetNsfwUserAdminAvoidRule - extends RuleWithConstantAction( - Avoid(), - Or( - TweetHasNsfwUserAuthor, - TweetHasNsfwAdminAuthor, - NsfwUserAuthor, - NsfwAdminAuthor - ) - ) - -object AvoidHighToxicityModelScoreRule - extends RuleWithConstantAction( - Avoid(), - TweetHasLabelWithScoreAboveThresholdWithParam( - TweetSafetyLabelType.HighToxicityScore, - AdAvoidanceHighToxicityModelScoreThresholdParam) - ) - -object AvoidReportedTweetModelScoreRule - extends RuleWithConstantAction( - Avoid(), - TweetHasLabelWithScoreAboveThresholdWithParam( - TweetSafetyLabelType.HighPReportedTweetScore, - AdAvoidanceReportedTweetModelScoreThresholdParam) - ) - -object TombstoneDeletedOuterTweetRule - extends RuleWithConstantAction( - Tombstone(Epitaph.Deleted), - And( - Equals(FeatureTweetDeleteReason, TweetDeleteReason.Deleted), - Not(IsQuotedInnerTweet) - ) - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableDeleteStateTweetRulesParam) -} - -object TombstoneDeletedTweetRule - extends RuleWithConstantAction( - Tombstone(Epitaph.Deleted), - And( - Equals(FeatureTweetDeleteReason, TweetDeleteReason.Deleted), - ) - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableDeleteStateTweetRulesParam) -} - -object TombstoneDeletedQuotedTweetRule - extends RuleWithConstantAction( - Tombstone(Epitaph.Deleted), - And( - Equals(FeatureTweetDeleteReason, TweetDeleteReason.Deleted), - IsQuotedInnerTweet - ) - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableDeleteStateTweetRulesParam) -} - -object TombstoneBounceDeletedTweetRule - extends RuleWithConstantAction( - Tombstone(Epitaph.BounceDeleted), - Equals(FeatureTweetDeleteReason, TweetDeleteReason.BounceDeleted), - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableDeleteStateTweetRulesParam) -} - -object TombstoneBounceDeletedOuterTweetRule - extends RuleWithConstantAction( - Tombstone(Epitaph.BounceDeleted), - And( - Equals(FeatureTweetDeleteReason, TweetDeleteReason.BounceDeleted), - Not(IsQuotedInnerTweet) - ) - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableDeleteStateTweetRulesParam) -} - -object TombstoneBounceDeletedQuotedTweetRule - extends RuleWithConstantAction( - Tombstone(Epitaph.BounceDeleted), - And( - Equals(FeatureTweetDeleteReason, TweetDeleteReason.BounceDeleted), - IsQuotedInnerTweet - ) - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableDeleteStateTweetRulesParam) -} - - -object DropStaleTweetsRule - extends RuleWithConstantAction( - Drop(StaleTweet), - And(TweetIsStaleTweet, Not(IsQuotedInnerTweet), Not(Retweet), Not(IsSourceTweet))) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableStaleTweetDropRuleParam) - override def enableFailClosed: Seq[RuleParam[Boolean]] = Seq( - EnableStaleTweetDropRuleFailClosedParam) -} - -object StaleTweetLimitedActionsRule - extends RuleWithConstantAction( - LimitedEngagements(LimitedEngagementReason.StaleTweet), - TweetIsStaleTweet) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(StaleTweetLimitedActionsRulesEnabledParam) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/UserLabelRules.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/UserLabelRules.scala deleted file mode 100644 index 668b28538..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/UserLabelRules.scala +++ /dev/null @@ -1,361 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.abdecider.LoggingABDecider -import com.twitter.timelines.configapi.Params -import com.twitter.visibility.configapi.configs.DeciderKey -import com.twitter.visibility.configapi.params.RuleParam -import com.twitter.visibility.configapi.params.RuleParams -import com.twitter.visibility.configapi.params.RuleParams._ -import com.twitter.visibility.features.Feature -import com.twitter.visibility.models.UserLabelValue -import com.twitter.visibility.models.UserLabelValue._ -import com.twitter.visibility.rules.Condition._ -import com.twitter.visibility.rules.Reason._ -import com.twitter.visibility.rules.RuleActionSourceBuilder.UserSafetyLabelSourceBuilder - -object AbusiveRule - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - Abusive - ) - -object DoNotAmplifyUserRule - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - DoNotAmplify - ) - -object AbusiveHighRecallRule - extends AuthorLabelAndNonFollowerViewerRule( - Drop(Unspecified), - AbusiveHighRecall - ) - -object CompromisedRule - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - Compromised - ) - -object DuplicateContentRule - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - DuplicateContent - ) - -object EngagementSpammerRule - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - EngagementSpammer - ) - -object EngagementSpammerHighRecallRule - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - EngagementSpammerHighRecall - ) - -object LiveLowQualityRule - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - LiveLowQuality - ) - -object LowQualityRule - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - LowQuality - ) - -object LowQualityHighRecallRule - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - LowQualityHighRecall - ) - -object NotGraduatedRule - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - NotGraduated - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableNotGraduatedDropRuleParam) - override def holdbacks: Seq[RuleParam[Boolean]] = Seq( - NotGraduatedUserLabelRuleHoldbackExperimentParam) - -} - -abstract class BaseNsfwHighPrecisionRule() - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - UserLabelValue.NsfwHighPrecision - ) -object NsfwHighPrecisionRule - extends BaseNsfwHighPrecisionRule() - -object NsfwHighRecallRule - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - NsfwHighRecall - ) - -abstract class BaseNsfwNearPerfectAuthorRule() - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - NsfwNearPerfect - ) -object NsfwNearPerfectAuthorRule extends BaseNsfwNearPerfectAuthorRule() - -object NsfwAvatarImageRule - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - NsfwAvatarImage - ) - -object NsfwBannerImageRule - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - NsfwBannerImage - ) - -object NsfwSensitiveRule - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - NsfwSensitive - ) - -object ReadOnlyRule - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - ReadOnly - ) - -object RecommendationsBlacklistRule - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - RecommendationsBlacklist - ) - -sealed abstract class BaseSpamHighRecallRule(val holdback: RuleParam[Boolean]) - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - SpamHighRecall - ) { - override val holdbacks: Seq[RuleParam[Boolean]] = Seq(holdback) -} - -object SpamHighRecallRule extends BaseSpamHighRecallRule(RuleParams.False) - -object DeciderableSpamHighRecallRule extends BaseSpamHighRecallRule(RuleParams.False) - -object SearchBlacklistRule - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - SearchBlacklist - ) - -object SearchNsfwTextRule - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - NsfwText - ) { - - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableNsfwTextSectioningRuleParam) -} - -object SpammyFollowerRule - extends OnlyWhenNotAuthorViewerRule( - Drop(Unspecified), - And( - Or( - AuthorHasLabel(Compromised), - AuthorHasLabel(EngagementSpammer), - AuthorHasLabel(EngagementSpammerHighRecall), - AuthorHasLabel(LowQuality), - AuthorHasLabel(ReadOnly), - AuthorHasLabel(SpamHighRecall) - ), - Or( - LoggedOutViewer, - And( - NonAuthorViewer, - ViewerHasUqfEnabled, - Or( - And( - ProtectedViewer, - LoggedOutOrViewerNotFollowingAuthor, - Not(AuthorDoesFollowViewer) - ), - And(Not(ProtectedViewer), LoggedOutOrViewerNotFollowingAuthor) - ) - ) - ) - ) - ) - -abstract class NonFollowerWithUqfUserLabelDropRule(labelValue: UserLabelValue) - extends ConditionWithUserLabelRule( - Drop(Unspecified), - And( - Or( - LoggedOutViewer, - And(Not(ViewerDoesFollowAuthor), ViewerHasUqfEnabled) - ) - ), - labelValue - ) - -object EngagementSpammerNonFollowerWithUqfRule - extends NonFollowerWithUqfUserLabelDropRule( - EngagementSpammer - ) - -object EngagementSpammerHighRecallNonFollowerWithUqfRule - extends NonFollowerWithUqfUserLabelDropRule( - EngagementSpammerHighRecall - ) - -object SpamHighRecallNonFollowerWithUqfRule - extends NonFollowerWithUqfUserLabelDropRule( - SpamHighRecall - ) - -object CompromisedNonFollowerWithUqfRule - extends NonFollowerWithUqfUserLabelDropRule( - Compromised - ) - -object ReadOnlyNonFollowerWithUqfRule - extends NonFollowerWithUqfUserLabelDropRule( - ReadOnly - ) - -object LowQualityNonFollowerWithUqfRule - extends NonFollowerWithUqfUserLabelDropRule( - LowQuality - ) - -object TsViolationRule - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - TsViolation - ) - -object DownrankSpamReplyAllViewersRule - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - DownrankSpamReply - ) { - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableDownrankSpamReplySectioningRuleParam) -} - -object DownrankSpamReplyNonAuthorRule - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - DownrankSpamReply - ) { - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableDownrankSpamReplySectioningRuleParam) -} - -object DownrankSpamReplyNonFollowerWithUqfRule - extends NonFollowerWithUqfUserLabelDropRule(DownrankSpamReply) { - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableDownrankSpamReplySectioningRuleParam) -} - -object NsfwTextAllUsersDropRule - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - NsfwText - ) { - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableNsfwTextSectioningRuleParam) -} - -object NsfwTextNonAuthorDropRule - extends WhenAuthorUserLabelPresentRule( - Drop(Unspecified), - DownrankSpamReply - ) { - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableNsfwTextSectioningRuleParam) -} - -abstract class DeciderableSpamHighRecallAuthorLabelRule(action: Action) - extends RuleWithConstantAction( - action, - And( - NonAuthorViewer, - SelfReply, - AuthorHasLabel(SpamHighRecall, shortCircuitable = false) - ) - ) { - override def preFilter( - evaluationContext: EvaluationContext, - featureMap: Map[Feature[_], Any], - abDecider: LoggingABDecider - ): PreFilterResult = { - Filtered - } -} - -object DeciderableSpamHighRecallAuthorLabelDropRule - extends DeciderableSpamHighRecallAuthorLabelRule(Drop(Unspecified)) - -object DeciderableSpamHighRecallAuthorLabelTombstoneRule - extends DeciderableSpamHighRecallAuthorLabelRule(Tombstone(Epitaph.Unavailable)) - -object DoNotAmplifyNonFollowerRule - extends AuthorLabelAndNonFollowerViewerRule( - Drop(Unspecified), - DoNotAmplify - ) - -object NotGraduatedNonFollowerRule - extends AuthorLabelAndNonFollowerViewerRule( - Drop(Unspecified), - NotGraduated - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq(EnableNotGraduatedDropRuleParam) - override def holdbacks: Seq[RuleParam[Boolean]] = Seq( - NotGraduatedUserLabelRuleHoldbackExperimentParam) - -} - -object DoNotAmplifySectionUserRule - extends AuthorLabelWithNotInnerCircleOfFriendsRule( - ConversationSectionAbusiveQuality, - DoNotAmplify) - with DoesLogVerdictDecidered { - override def actionSourceBuilder: Option[RuleActionSourceBuilder] = Some( - UserSafetyLabelSourceBuilder(DoNotAmplify)) - override def verdictLogDeciderKey = DeciderKey.EnableDownlevelRuleVerdictLogging -} - - -object SpammyUserModelHighPrecisionDropTweetRule - extends AuthorLabelAndNonFollowerViewerRule( - Drop(Unspecified), - SpammyUserModelHighPrecision, - ) - with DoesLogVerdictDecidered { - override def isEnabled(params: Params): Boolean = - params(EnableSpammyUserModelTweetDropRuleParam) - override def verdictLogDeciderKey: DeciderKey.Value = - DeciderKey.EnableSpammyTweetRuleVerdictLogging -} - -object LikelyIvsLabelNonFollowerDropUserRule extends LikelyIvsLabelNonFollowerDropRule - -object SearchLikelyIvsLabelNonFollowerDropUserRule extends LikelyIvsLabelNonFollowerDropRule - -object NsfwHighPrecisionUserLabelAvoidTweetRule - extends UserHasLabelRule( - Avoid(), - UserLabelValue.NsfwHighPrecision - ) { - override def enabled: Seq[RuleParam[Boolean]] = Seq( - NsfwHighPrecisionUserLabelAvoidTweetRuleEnabledParam) -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/UserUnavailableStateTombstoneRules.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/UserUnavailableStateTombstoneRules.scala deleted file mode 100644 index 716ea6ab8..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/UserUnavailableStateTombstoneRules.scala +++ /dev/null @@ -1,120 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.visibility.configapi.params.RuleParam -import com.twitter.visibility.configapi.params.RuleParams.EnableInnerQuotedTweetViewerBlocksAuthorInterstitialRuleParam -import com.twitter.visibility.configapi.params.RuleParams.EnableInnerQuotedTweetViewerMutesAuthorInterstitialRuleParam -import com.twitter.visibility.rules.Condition.And -import com.twitter.visibility.rules.Condition.AuthorBlocksViewer -import com.twitter.visibility.rules.Condition.DeactivatedAuthor -import com.twitter.visibility.rules.Condition.ErasedAuthor -import com.twitter.visibility.rules.Condition.IsQuotedInnerTweet -import com.twitter.visibility.rules.Condition.OffboardedAuthor -import com.twitter.visibility.rules.Condition.ProtectedAuthor -import com.twitter.visibility.rules.Condition.Retweet -import com.twitter.visibility.rules.Condition.SuspendedAuthor -import com.twitter.visibility.rules.Condition.UnavailableAuthor -import com.twitter.visibility.rules.Condition.ViewerBlocksAuthor -import com.twitter.visibility.rules.Condition.ViewerMutesAuthor - -object UserUnavailableStateTombstoneRules { - abstract class UserUnavailableStateTweetTombstoneRule(epitaph: Epitaph, condition: Condition) - extends RuleWithConstantAction(Tombstone(epitaph), condition) {} - - abstract class UserUnavailableStateRetweetTombstoneRule(epitaph: Epitaph, condition: Condition) - extends RuleWithConstantAction(Tombstone(epitaph), And(Retweet, condition)) {} - - abstract class UserUnavailableStateInnerQuotedTweetTombstoneRule( - epitaph: Epitaph, - condition: Condition) - extends RuleWithConstantAction(Tombstone(epitaph), And(IsQuotedInnerTweet, condition)) - - abstract class UserUnavailableStateInnerQuotedTweetInterstitialRule( - reason: Reason, - condition: Condition) - extends RuleWithConstantAction(Interstitial(reason), And(IsQuotedInnerTweet, condition)) - - object SuspendedUserUnavailableTweetTombstoneRule - extends UserUnavailableStateTweetTombstoneRule(Epitaph.Suspended, SuspendedAuthor) - - object DeactivatedUserUnavailableTweetTombstoneRule - extends UserUnavailableStateTweetTombstoneRule(Epitaph.Deactivated, DeactivatedAuthor) - - object OffBoardedUserUnavailableTweetTombstoneRule - extends UserUnavailableStateTweetTombstoneRule(Epitaph.Offboarded, OffboardedAuthor) - - object ErasedUserUnavailableTweetTombstoneRule - extends UserUnavailableStateTweetTombstoneRule(Epitaph.Deactivated, ErasedAuthor) - - object ProtectedUserUnavailableTweetTombstoneRule - extends UserUnavailableStateTweetTombstoneRule(Epitaph.Protected, ProtectedAuthor) - - object AuthorBlocksViewerUserUnavailableTweetTombstoneRule - extends UserUnavailableStateTweetTombstoneRule(Epitaph.BlockedBy, AuthorBlocksViewer) - - object UserUnavailableTweetTombstoneRule - extends UserUnavailableStateTweetTombstoneRule(Epitaph.Unavailable, UnavailableAuthor) - - object SuspendedUserUnavailableRetweetTombstoneRule - extends UserUnavailableStateRetweetTombstoneRule(Epitaph.Suspended, SuspendedAuthor) - - object DeactivatedUserUnavailableRetweetTombstoneRule - extends UserUnavailableStateRetweetTombstoneRule(Epitaph.Deactivated, DeactivatedAuthor) - - object OffBoardedUserUnavailableRetweetTombstoneRule - extends UserUnavailableStateRetweetTombstoneRule(Epitaph.Offboarded, OffboardedAuthor) - - object ErasedUserUnavailableRetweetTombstoneRule - extends UserUnavailableStateRetweetTombstoneRule(Epitaph.Deactivated, ErasedAuthor) - - object ProtectedUserUnavailableRetweetTombstoneRule - extends UserUnavailableStateRetweetTombstoneRule(Epitaph.Protected, ProtectedAuthor) - - object AuthorBlocksViewerUserUnavailableRetweetTombstoneRule - extends UserUnavailableStateRetweetTombstoneRule(Epitaph.BlockedBy, AuthorBlocksViewer) - - object ViewerBlocksAuthorUserUnavailableRetweetTombstoneRule - extends UserUnavailableStateRetweetTombstoneRule(Epitaph.Unavailable, ViewerBlocksAuthor) - - object ViewerMutesAuthorUserUnavailableRetweetTombstoneRule - extends UserUnavailableStateRetweetTombstoneRule(Epitaph.Unavailable, ViewerMutesAuthor) - - object SuspendedUserUnavailableInnerQuotedTweetTombstoneRule - extends UserUnavailableStateInnerQuotedTweetTombstoneRule(Epitaph.Suspended, SuspendedAuthor) - - object DeactivatedUserUnavailableInnerQuotedTweetTombstoneRule - extends UserUnavailableStateInnerQuotedTweetTombstoneRule( - Epitaph.Deactivated, - DeactivatedAuthor) - - object OffBoardedUserUnavailableInnerQuotedTweetTombstoneRule - extends UserUnavailableStateInnerQuotedTweetTombstoneRule( - Epitaph.Offboarded, - OffboardedAuthor) - - object ErasedUserUnavailableInnerQuotedTweetTombstoneRule - extends UserUnavailableStateInnerQuotedTweetTombstoneRule(Epitaph.Deactivated, ErasedAuthor) - - object ProtectedUserUnavailableInnerQuotedTweetTombstoneRule - extends UserUnavailableStateInnerQuotedTweetTombstoneRule(Epitaph.Protected, ProtectedAuthor) - - object AuthorBlocksViewerUserUnavailableInnerQuotedTweetTombstoneRule - extends UserUnavailableStateInnerQuotedTweetTombstoneRule( - Epitaph.BlockedBy, - AuthorBlocksViewer) - - object ViewerBlocksAuthorUserUnavailableInnerQuotedTweetInterstitialRule - extends UserUnavailableStateInnerQuotedTweetInterstitialRule( - Reason.ViewerBlocksAuthor, - ViewerBlocksAuthor) { - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableInnerQuotedTweetViewerBlocksAuthorInterstitialRuleParam) - } - - object ViewerMutesAuthorUserUnavailableInnerQuotedTweetInterstitialRule - extends UserUnavailableStateInnerQuotedTweetInterstitialRule( - Reason.ViewerMutesAuthor, - ViewerMutesAuthor) { - override def enabled: Seq[RuleParam[Boolean]] = - Seq(EnableInnerQuotedTweetViewerMutesAuthorInterstitialRuleParam) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/VisibilityPolicy.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/VisibilityPolicy.scala deleted file mode 100644 index e1dcbf88a..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/VisibilityPolicy.scala +++ /dev/null @@ -1,3818 +0,0 @@ -package com.twitter.visibility.rules - -import com.twitter.visibility.configapi.params.RuleParam -import com.twitter.visibility.configapi.params.RuleParams -import com.twitter.visibility.models.ContentId -import com.twitter.visibility.rules.ConversationControlRules._ -import com.twitter.visibility.rules.FollowerRelations.AuthorMutesViewerRule -import com.twitter.visibility.rules.FollowerRelations.ProtectedViewerRule -import com.twitter.visibility.rules.PolicyLevelRuleParams.ruleParams -import com.twitter.visibility.rules.PublicInterestRules._ -import com.twitter.visibility.rules.SafeSearchTweetRules._ -import com.twitter.visibility.rules.SafeSearchUserRules.SafeSearchNsfwAvatarImageUserLabelRule -import com.twitter.visibility.rules.SafeSearchUserRules._ -import com.twitter.visibility.rules.SpaceRules._ -import com.twitter.visibility.rules.ToxicityReplyFilterRules.ToxicityReplyFilterDropNotificationRule -import com.twitter.visibility.rules.ToxicityReplyFilterRules.ToxicityReplyFilterRule -import com.twitter.visibility.rules.UnsafeSearchTweetRules._ -import com.twitter.visibility.rules.UserUnavailableStateTombstoneRules._ - -abstract class VisibilityPolicy( - val tweetRules: Seq[Rule] = Nil, - val userRules: Seq[Rule] = Nil, - val cardRules: Seq[Rule] = Nil, - val quotedTweetRules: Seq[Rule] = Nil, - val dmRules: Seq[Rule] = Nil, - val dmConversationRules: Seq[Rule] = Nil, - val dmEventRules: Seq[Rule] = Nil, - val spaceRules: Seq[Rule] = Nil, - val userUnavailableStateRules: Seq[Rule] = Nil, - val twitterArticleRules: Seq[Rule] = Nil, - val deletedTweetRules: Seq[Rule] = Nil, - val mediaRules: Seq[Rule] = Nil, - val communityRules: Seq[Rule] = Nil, - val policyRuleParams: Map[Rule, PolicyLevelRuleParams] = Map.empty) { - - def forContentId(contentId: ContentId): Seq[Rule] = - contentId match { - case ContentId.TweetId(_) => tweetRules - case ContentId.UserId(_) => userRules - case ContentId.CardId(_) => cardRules - case ContentId.QuotedTweetRelationship(_, _) => quotedTweetRules - case ContentId.NotificationId(_) => userRules - case ContentId.DmId(_) => dmRules - case ContentId.BlenderTweetId(_) => userRules ++ tweetRules - case ContentId.SpaceId(_) => spaceRules - case ContentId.SpacePlusUserId(_) => spaceRules ++ userRules - case ContentId.DmConversationId(_) => dmConversationRules - case ContentId.DmEventId(_) => dmEventRules - case ContentId.UserUnavailableState(_) => userUnavailableStateRules - case ContentId.TwitterArticleId(_) => twitterArticleRules - case ContentId.DeleteTweetId(_) => deletedTweetRules - case ContentId.MediaId(_) => mediaRules - case ContentId.CommunityId(_) => communityRules - } - - private[visibility] def allRules: Seq[Rule] = - (tweetRules ++ userRules ++ cardRules ++ quotedTweetRules ++ dmRules ++ spaceRules ++ dmConversationRules ++ dmEventRules ++ twitterArticleRules ++ deletedTweetRules ++ mediaRules ++ communityRules) -} - -object VisibilityPolicy { - val baseTweetRules = Seq( - DropCommunityTweetsRule, - DropCommunityTweetCommunityNotVisibleRule, - DropProtectedCommunityTweetsRule, - DropHiddenCommunityTweetsRule, - DropAuthorRemovedCommunityTweetsRule, - SpamTweetLabelRule, - PdnaTweetLabelRule, - BounceTweetLabelRule, - DropExclusiveTweetContentRule, - DropTrustedFriendsTweetContentRule - ) - - val baseTweetTombstoneRules = Seq( - TombstoneCommunityTweetsRule, - TombstoneCommunityTweetCommunityNotVisibleRule, - TombstoneProtectedCommunityTweetsRule, - TombstoneHiddenCommunityTweetsRule, - TombstoneAuthorRemovedCommunityTweetsRule, - SpamTweetLabelTombstoneRule, - PdnaTweetLabelTombstoneRule, - BounceTweetLabelTombstoneRule, - TombstoneExclusiveTweetContentRule, - TombstoneTrustedFriendsTweetContentRule, - ) - - val baseMediaRules = Seq( - ) - - val baseQuotedTweetTombstoneRules = Seq( - BounceQuotedTweetTombstoneRule - ) - - def union[T](rules: Seq[Rule]*): Seq[Rule] = { - if (rules.isEmpty) { - Seq.empty[Rule] - } else { - rules.reduce((a, b) => a ++ b.filterNot(a.contains)) - } - } -} - -case class PolicyLevelRuleParams( - ruleParams: Seq[RuleParam[Boolean]], - force: Boolean = false) {} - -object PolicyLevelRuleParams { - def ruleParams(ruleParams: RuleParam[Boolean]*): PolicyLevelRuleParams = { - PolicyLevelRuleParams(ruleParams) - } - - def ruleParams(force: Boolean, ruleParams: RuleParam[Boolean]*): PolicyLevelRuleParams = { - PolicyLevelRuleParams(ruleParams, force) - } -} - -case object FilterAllPolicy - extends VisibilityPolicy( - tweetRules = Seq(DropAllRule), - userRules = Seq(DropAllRule), - cardRules = Seq(DropAllRule), - quotedTweetRules = Seq(DropAllRule), - dmRules = Seq(DropAllRule), - dmConversationRules = Seq(DropAllRule), - dmEventRules = Seq(DropAllRule), - spaceRules = Seq(DropAllRule), - userUnavailableStateRules = Seq(DropAllRule), - twitterArticleRules = Seq(DropAllRule), - deletedTweetRules = Seq(DropAllRule), - mediaRules = Seq(DropAllRule), - communityRules = Seq(DropAllRule), - ) - -case object FilterNonePolicy extends VisibilityPolicy() - -object ConversationsAdAvoidanceRules { - val tweetRules = Seq( - NsfwHighRecallTweetLabelAvoidRule, - NsfwHighPrecisionTweetLabelAvoidRule, - NsfwTextTweetLabelAvoidRule, - AvoidHighToxicityModelScoreRule, - AvoidReportedTweetModelScoreRule, - NsfwHighPrecisionUserLabelAvoidTweetRule, - TweetNsfwUserAdminAvoidRule, - DoNotAmplifyTweetLabelAvoidRule, - NsfaHighPrecisionTweetLabelAvoidRule, - ) - - val policyRuleParams = Map[Rule, PolicyLevelRuleParams]( - NsfwHighRecallTweetLabelAvoidRule -> ruleParams( - RuleParams.EnableNewAdAvoidanceRulesParam - ), - NsfwHighPrecisionTweetLabelAvoidRule -> ruleParams( - RuleParams.EnableNewAdAvoidanceRulesParam - ), - NsfwTextTweetLabelAvoidRule -> ruleParams(RuleParams.EnableNewAdAvoidanceRulesParam), - AvoidHighToxicityModelScoreRule -> ruleParams(RuleParams.EnableNewAdAvoidanceRulesParam), - AvoidReportedTweetModelScoreRule -> ruleParams(RuleParams.EnableNewAdAvoidanceRulesParam), - NsfwHighPrecisionUserLabelAvoidTweetRule -> ruleParams( - RuleParams.EnableNewAdAvoidanceRulesParam), - TweetNsfwUserAdminAvoidRule -> ruleParams(RuleParams.EnableNewAdAvoidanceRulesParam), - DoNotAmplifyTweetLabelAvoidRule -> ruleParams(RuleParams.EnableNewAdAvoidanceRulesParam), - NsfaHighPrecisionTweetLabelAvoidRule -> ruleParams(RuleParams.EnableNewAdAvoidanceRulesParam), - ) -} - -case object FilterDefaultPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ - Seq( - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule - ) - ) - -case object LimitedEngagementBaseRules - extends VisibilityPolicy( - tweetRules = Seq( - StaleTweetLimitedActionsRule, - LimitRepliesByInvitationConversationRule, - LimitRepliesCommunityConversationRule, - LimitRepliesFollowersConversationRule, - CommunityTweetCommunityNotFoundLimitedActionsRule, - CommunityTweetCommunityDeletedLimitedActionsRule, - CommunityTweetCommunitySuspendedLimitedActionsRule, - CommunityTweetMemberRemovedLimitedActionsRule, - CommunityTweetHiddenLimitedActionsRule, - CommunityTweetMemberLimitedActionsRule, - CommunityTweetNonMemberLimitedActionsRule, - DynamicProductAdLimitedEngagementTweetLabelRule, - TrustedFriendsTweetLimitedEngagementsRule - ) - ) - -case object WritePathLimitedActionsEnforcementPolicy - extends VisibilityPolicy( - tweetRules = Seq( - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule - ) ++ - LimitedEngagementBaseRules.tweetRules - ) - -case object TestPolicy - extends VisibilityPolicy( - tweetRules = Seq( - TestRule - ) - ) - -case object CardsServicePolicy - extends VisibilityPolicy( - cardRules = Seq( - DropProtectedAuthorPollCardRule, - DropCardUriRootDomainDenylistRule - ), - spaceRules = Seq( - SpaceHighToxicityScoreNonFollowerDropRule, - SpaceHatefulHighRecallAllUsersDropRule, - SpaceViolenceHighRecallAllUsersDropRule, - ViewerIsSoftUserDropRule - ), - ) - -case object CardPollVotingPolicy - extends VisibilityPolicy( - cardRules = Seq( - DropProtectedAuthorPollCardRule, - DropCommunityNonMemberPollCardRule - ) - ) - -case object UserTimelineRules { - val UserRules = Seq( - AuthorBlocksViewerDropRule, - ProtectedAuthorDropRule, - SuspendedAuthorRule - ) -} - -case object TimelineLikedByRules { - val UserRules = Seq( - CompromisedNonFollowerWithUqfRule, - EngagementSpammerNonFollowerWithUqfRule, - LowQualityNonFollowerWithUqfRule, - ReadOnlyNonFollowerWithUqfRule, - SpamHighRecallNonFollowerWithUqfRule - ) -} - -case object FollowingAndFollowersUserListPolicy - extends VisibilityPolicy( - userRules = UserTimelineRules.UserRules - ) - -case object FriendsFollowingListPolicy - extends VisibilityPolicy( - userRules = UserTimelineRules.UserRules - ) - -case object ListOwnershipsPolicy - extends VisibilityPolicy( - userRules = UserTimelineRules.UserRules - ) - -case object ListRecommendationsPolicy - extends VisibilityPolicy( - userRules = RecommendationsPolicy.userRules ++ Seq( - DropNsfwUserAuthorRule, - NsfwHighRecallRule, - SearchBlacklistRule, - SearchNsfwTextRule, - ViewerBlocksAuthorRule, - ViewerMutesAuthorRule - ) - ) - -case object ListSearchBaseRules { - - val NonExperimentalSafeSearchMinimalPolicyUserRules: Seq[Rule] = - SafeSearchMinimalPolicy.userRules.filterNot(_.isExperimental) - - val MinimalPolicyUserRules: Seq[Rule] = NonExperimentalSafeSearchMinimalPolicyUserRules - - val BlockMutePolicyUserRules = Seq( - ViewerBlocksAuthorViewerOptInBlockingOnSearchRule, - ViewerMutesAuthorViewerOptInBlockingOnSearchRule - ) - - val StrictPolicyUserRules = Seq( - SafeSearchAbusiveUserLabelRule, - SafeSearchAbusiveHighRecallUserLabelRule, - SafeSearchCompromisedUserLabelRule, - SafeSearchDoNotAmplifyNonFollowersUserLabelRule, - SafeSearchDuplicateContentUserLabelRule, - SafeSearchLowQualityUserLabelRule, - SafeSearchNotGraduatedNonFollowersUserLabelRule, - SafeSearchNsfwHighPrecisionUserLabelRule, - SafeSearchNsfwAvatarImageUserLabelRule, - SafeSearchNsfwBannerImageUserLabelRule, - SafeSearchReadOnlyUserLabelRule, - SafeSearchSearchBlacklistUserLabelRule, - SafeSearchNsfwTextUserLabelRule, - SafeSearchSpamHighRecallUserLabelRule, - SafeSearchDownrankSpamReplyAuthorLabelRule, - SafeSearchNsfwTextAuthorLabelRule, - DropNsfwAdminAuthorViewerOptInFilteringOnSearchRule, - DropNsfwUserAuthorViewerOptInFilteringOnSearchRule, - ) -} - -object SensitiveMediaSettingsTimelineHomeBaseRules { - val policyRuleParams = Map[Rule, PolicyLevelRuleParams]( - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaHomeTimelineRulesParam), - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaHomeTimelineRulesParam), - NsfwReportedHeuristicsAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaHomeTimelineRulesParam), - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaHomeTimelineRulesParam), - NsfwCardImageAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaHomeTimelineRulesParam), - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwHighPrecisionTweetLabelInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsHomeTimelineRulesParam), - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceHighPrecisionInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsHomeTimelineRulesParam), - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwReportedHeuristicsTweetLabelInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsHomeTimelineRulesParam), - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceReportedHeuristicsInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsHomeTimelineRulesParam), - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwCardImageTweetLabelInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsHomeTimelineRulesParam), - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwUserTweetFlagInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsHomeTimelineRulesParam), - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwAdminTweetFlagInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsHomeTimelineRulesParam) - ) -} - -object SensitiveMediaSettingsConversationBaseRules { - val policyRuleParams = Map[Rule, PolicyLevelRuleParams]( - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaConversationRulesParam), - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaConversationRulesParam), - NsfwReportedHeuristicsAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaConversationRulesParam), - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaConversationRulesParam), - NsfwCardImageAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaConversationRulesParam), - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwHighPrecisionTweetLabelInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsConversationRulesParam), - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceHighPrecisionInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsConversationRulesParam), - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwReportedHeuristicsTweetLabelInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsConversationRulesParam), - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceReportedHeuristicsInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsConversationRulesParam), - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwCardImageTweetLabelInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsConversationRulesParam), - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwUserTweetFlagInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsConversationRulesParam), - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwAdminTweetFlagInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsConversationRulesParam) - ) -} - -object SensitiveMediaSettingsProfileTimelineBaseRules { - val policyRuleParams = Map[Rule, PolicyLevelRuleParams]( - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaProfileTimelineRulesParam), - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaProfileTimelineRulesParam), - NsfwReportedHeuristicsAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaProfileTimelineRulesParam), - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaProfileTimelineRulesParam), - NsfwCardImageAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaProfileTimelineRulesParam), - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwHighPrecisionTweetLabelInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsProfileTimelineRulesParam), - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceHighPrecisionInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsProfileTimelineRulesParam), - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwReportedHeuristicsTweetLabelInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsProfileTimelineRulesParam), - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceReportedHeuristicsInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsProfileTimelineRulesParam), - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwCardImageTweetLabelInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsProfileTimelineRulesParam), - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwUserTweetFlagInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsProfileTimelineRulesParam), - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwAdminTweetFlagInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsProfileTimelineRulesParam) - ) -} - -object SensitiveMediaSettingsTweetDetailBaseRules { - val policyRuleParams = Map[Rule, PolicyLevelRuleParams]( - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaTweetDetailRulesParam), - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaTweetDetailRulesParam), - NsfwReportedHeuristicsAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaTweetDetailRulesParam), - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaTweetDetailRulesParam), - NsfwCardImageAllUsersTweetLabelRule -> ruleParams( - RuleParams.EnableLegacySensitiveMediaTweetDetailRulesParam), - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwHighPrecisionTweetLabelInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsTweetDetailRulesParam), - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceHighPrecisionInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsTweetDetailRulesParam), - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwReportedHeuristicsTweetLabelInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsTweetDetailRulesParam), - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceReportedHeuristicsInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsTweetDetailRulesParam), - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwCardImageTweetLabelInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsTweetDetailRulesParam), - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwUserTweetFlagInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsTweetDetailRulesParam), - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwAdminTweetFlagInterstitialRule -> ruleParams( - RuleParams.EnableNewSensitiveMediaSettingsInterstitialsTweetDetailRulesParam) - ) -} - -case object ListSearchPolicy - extends VisibilityPolicy( - userRules = ListSearchBaseRules.MinimalPolicyUserRules ++ - ListSearchBaseRules.BlockMutePolicyUserRules ++ - ListSearchBaseRules.StrictPolicyUserRules - ) - -case object ListSubscriptionsPolicy - extends VisibilityPolicy( - userRules = UserTimelineRules.UserRules - ) - -case object ListMembershipsPolicy - extends VisibilityPolicy( - userRules = UserTimelineRules.UserRules - ) - -case object AllSubscribedListsPolicy - extends VisibilityPolicy( - userRules = UserTimelineRules.UserRules - ) - -case object ListHeaderPolicy - extends VisibilityPolicy( - userRules = Seq( - AuthorBlocksViewerDropRule, - ProtectedAuthorDropRule, - SuspendedAuthorRule - ) - ) - -case object NewUserExperiencePolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ Seq( - AbusiveTweetLabelRule, - LowQualityTweetLabelDropRule, - NsfaHighRecallTweetLabelRule, - NsfwHighPrecisionTweetLabelRule, - GoreAndViolenceHighPrecisionTweetLabelRule, - NsfwReportedHeuristicsTweetLabelRule, - GoreAndViolenceReportedHeuristicsTweetLabelRule, - NsfwCardImageTweetLabelRule, - NsfwHighRecallTweetLabelRule, - NsfwVideoTweetLabelDropRule, - NsfwTextTweetLabelDropRule, - SpamHighRecallTweetLabelDropRule, - DuplicateContentTweetLabelDropRule, - GoreAndViolenceTweetLabelRule, - UntrustedUrlTweetLabelRule, - DownrankSpamReplyTweetLabelRule, - SearchBlacklistTweetLabelRule, - AutomationTweetLabelRule, - DuplicateMentionTweetLabelRule, - BystanderAbusiveTweetLabelRule, - SafetyCrisisLevel3DropRule, - SafetyCrisisLevel4DropRule, - DoNotAmplifyDropRule, - SmyteSpamTweetLabelDropRule, - ), - userRules = Seq( - AbusiveRule, - LowQualityRule, - ReadOnlyRule, - SearchBlacklistRule, - SearchNsfwTextRule, - CompromisedRule, - SpamHighRecallRule, - DuplicateContentRule, - NsfwHighPrecisionRule, - NsfwAvatarImageRule, - NsfwBannerImageRule, - AbusiveHighRecallRule, - DoNotAmplifyNonFollowerRule, - NotGraduatedNonFollowerRule, - LikelyIvsLabelNonFollowerDropUserRule, - DownrankSpamReplyNonAuthorRule, - NsfwTextNonAuthorDropRule - ) - ) - -case object DESHomeTimelinePolicy - extends VisibilityPolicy( - tweetRules = Seq( - DropStaleTweetsRule, - DropAllExclusiveTweetsRule, - DropAllTrustedFriendsTweetsRule, - DropAllCommunityTweetsRule - ) ++ - VisibilityPolicy.baseTweetRules, - userRules = UserTimelineRules.UserRules - ) - -case object DesQuoteTweetTimelinePolicy - extends VisibilityPolicy( - tweetRules = Seq( - DropStaleTweetsRule, - DropAllExclusiveTweetsRule, - DropAllTrustedFriendsTweetsRule - ) ++ ElevatedQuoteTweetTimelinePolicy.tweetRules.diff(Seq(DropStaleTweetsRule)), - userRules = Seq( - ProtectedAuthorDropRule - ), - policyRuleParams = ElevatedQuoteTweetTimelinePolicy.policyRuleParams - ) - -case object DESRealtimeSpamEnrichmentPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ Seq( - LowQualityTweetLabelDropRule, - SpamHighRecallTweetLabelDropRule, - DuplicateContentTweetLabelDropRule, - SearchBlacklistTweetLabelRule, - SmyteSpamTweetLabelDropRule, - DropAllCommunityTweetsRule, - DropAllExclusiveTweetsRule, - DropAllTrustedFriendsTweetsRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule - ) - ) - -case object DESRealtimePolicy - extends VisibilityPolicy( - tweetRules = Seq( - DropAllCommunityTweetsRule, - DropAllExclusiveTweetsRule, - DropAllTrustedFriendsTweetsRule, - DropAllCollabInvitationTweetsRule - ), - userRules = Seq( - DropAllProtectedAuthorRule, - DropProtectedViewerIfPresentRule - ) - ) - -case object DESRetweetingUsersPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ Seq( - DropAllExclusiveTweetsRule, - DropAllTrustedFriendsTweetsRule, - ), - userRules = Seq( - AuthorBlocksViewerDropRule, - ViewerBlocksAuthorRule, - ProtectedAuthorDropRule, - SuspendedAuthorRule - ) - ) - -case object DESTweetLikingUsersPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ Seq( - DropAllExclusiveTweetsRule, - DropAllTrustedFriendsTweetsRule, - ), - userRules = TimelineLikedByRules.UserRules - ) - -case object DESUserBookmarksPolicy - extends VisibilityPolicy( - tweetRules = Seq( - DropAllExclusiveTweetsRule, - DropAllTrustedFriendsTweetsRule, - ) ++ - (VisibilityPolicy.baseTweetRules - ++ Seq(DropAllCommunityTweetsRule) - ++ TimelineProfileRules.tweetRules), - userRules = UserTimelineRules.UserRules - ) - -case object DESUserLikedTweetsPolicy - extends VisibilityPolicy( - tweetRules = Seq( - DropStaleTweetsRule, - DropAllExclusiveTweetsRule, - DropAllTrustedFriendsTweetsRule, - ) ++ - ( - VisibilityPolicy.baseTweetRules ++ - Seq( - DropAllCommunityTweetsRule, - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - ReportedTweetInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - NsfwHighPrecisionTweetLabelAvoidRule, - NsfwHighRecallTweetLabelAvoidRule, - GoreAndViolenceHighPrecisionAvoidAllUsersTweetLabelRule, - NsfwReportedHeuristicsAvoidAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAvoidAllUsersTweetLabelRule, - NsfwCardImageAvoidAllUsersTweetLabelRule, - DoNotAmplifyTweetLabelAvoidRule, - NsfaHighPrecisionTweetLabelAvoidRule, - ) ++ LimitedEngagementBaseRules.tweetRules - ), - userRules = UserTimelineRules.UserRules - ) - -case object DESUserMentionsPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ Seq( - DropAllCommunityTweetsRule, - AuthorBlocksViewerDropRule, - ProtectedAuthorDropRule, - DropAllExclusiveTweetsRule, - DropAllTrustedFriendsTweetsRule, - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - ) ++ LimitedEngagementBaseRules.tweetRules, - userRules = Seq( - SuspendedAuthorRule - ) - ) - -case object DESUserTweetsPolicy - extends VisibilityPolicy( - tweetRules = Seq( - DropStaleTweetsRule, - DropAllExclusiveTweetsRule, - DropAllTrustedFriendsTweetsRule, - ) ++ - (VisibilityPolicy.baseTweetRules - ++ Seq(DropAllCommunityTweetsRule) - ++ TimelineProfileRules.tweetRules), - userRules = UserTimelineRules.UserRules - ) - -case object DevPlatformComplianceStreamPolicy - extends VisibilityPolicy( - tweetRules = Seq( - SpamAllUsersTweetLabelRule, - PdnaAllUsersTweetLabelRule, - BounceAllUsersTweetLabelRule, - AbusePolicyEpisodicTweetLabelComplianceTweetNoticeRule, - ) - ) - -case object DesTweetDetailPolicy - extends VisibilityPolicy( - tweetRules = Seq( - DropAllExclusiveTweetsRule, - DropAllTrustedFriendsTweetsRule, - ) ++ BaseTweetDetailPolicy.tweetRules - ) - -case object DevPlatformGetListTweetsPolicy - extends VisibilityPolicy( - tweetRules = Seq(DropStaleTweetsRule) ++ DesTweetDetailPolicy.tweetRules - ) - -case object FollowerConnectionsPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules, - userRules = Seq( - SpammyFollowerRule - ) - ) - -case object SuperFollowerConnectionsPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules, - userRules = Seq( - SpammyFollowerRule - ) - ) - -case object LivePipelineEngagementCountsPolicy - extends VisibilityPolicy( - tweetRules = Seq( - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - ) ++ LimitedEngagementBaseRules.tweetRules - ) - -case object LiveVideoTimelinePolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ Seq( - AbusiveTweetLabelRule, - AbusiveHighRecallTweetLabelRule, - LowQualityTweetLabelDropRule, - NsfwHighPrecisionTweetLabelRule, - GoreAndViolenceHighPrecisionTweetLabelRule, - NsfwReportedHeuristicsTweetLabelRule, - GoreAndViolenceReportedHeuristicsTweetLabelRule, - NsfwCardImageTweetLabelRule, - NsfwHighRecallTweetLabelRule, - NsfwVideoTweetLabelDropRule, - NsfwTextTweetLabelDropRule, - LiveLowQualityTweetLabelRule, - SpamHighRecallTweetLabelDropRule, - DuplicateContentTweetLabelDropRule, - SearchBlacklistTweetLabelRule, - BystanderAbusiveTweetLabelRule, - SafetyCrisisLevel3DropRule, - SafetyCrisisLevel4DropRule, - DoNotAmplifyDropRule, - SmyteSpamTweetLabelDropRule, - AbusePolicyEpisodicTweetLabelDropRule, - EmergencyDropRule, - ), - userRules = Seq( - AbusiveRule, - LowQualityRule, - ReadOnlyRule, - SearchBlacklistRule, - SearchNsfwTextRule, - CompromisedRule, - NsfwHighPrecisionRule, - NsfwHighRecallRule, - NsfwAvatarImageRule, - NsfwBannerImageRule, - SpamHighRecallRule, - DuplicateContentRule, - LiveLowQualityRule, - EngagementSpammerRule, - EngagementSpammerHighRecallRule, - AbusiveHighRecallRule, - DoNotAmplifyNonFollowerRule, - NotGraduatedNonFollowerRule, - LikelyIvsLabelNonFollowerDropUserRule, - NsfwTextNonAuthorDropRule - ) - ) - -case object MagicRecsPolicyOverrides { - val replacements: Map[Rule, Rule] = Map() - def union(rules: Seq[Rule]*): Seq[Rule] = rules - .map(ar => ar.map(x => replacements.getOrElse(x, x))) - .reduce((a, b) => a ++ b.filterNot(a.contains)) -} - -case object MagicRecsPolicy - extends VisibilityPolicy( - tweetRules = MagicRecsPolicyOverrides.union( - RecommendationsPolicy.tweetRules.filterNot(_ == SafetyCrisisLevel3DropRule), - NotificationsIbisPolicy.tweetRules, - Seq( - NsfaHighRecallTweetLabelRule, - NsfwHighRecallTweetLabelRule, - NsfwTextHighPrecisionTweetLabelDropRule), - Seq( - AuthorBlocksViewerDropRule, - ViewerBlocksAuthorRule, - ViewerMutesAuthorRule - ), - Seq( - DeactivatedAuthorRule, - SuspendedAuthorRule, - TweetNsfwUserDropRule, - TweetNsfwAdminDropRule - ) - ), - userRules = MagicRecsPolicyOverrides.union( - RecommendationsPolicy.userRules, - NotificationsRules.userRules - ) - ) - -case object MagicRecsV2Policy - extends VisibilityPolicy( - tweetRules = MagicRecsPolicyOverrides.union( - MagicRecsPolicy.tweetRules, - NotificationsWriterTweetHydratorPolicy.tweetRules - ), - userRules = MagicRecsPolicyOverrides.union( - MagicRecsPolicy.userRules, - NotificationsWriterV2Policy.userRules - ) - ) - -case object MagicRecsAggressivePolicy - extends VisibilityPolicy( - tweetRules = MagicRecsPolicy.tweetRules, - userRules = MagicRecsPolicy.userRules - ) - -case object MagicRecsAggressiveV2Policy - extends VisibilityPolicy( - tweetRules = MagicRecsV2Policy.tweetRules, - userRules = MagicRecsV2Policy.userRules - ) - -case object MinimalPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules, - userRules = Seq( - TsViolationRule - ) - ) - -case object ModeratedTweetsTimelinePolicy - extends VisibilityPolicy( - tweetRules = TweetDetailPolicy.tweetRules.diff( - Seq( - AuthorBlocksViewerDropRule, - MutedKeywordForTweetRepliesInterstitialRule, - ReportedTweetInterstitialRule)), - policyRuleParams = TweetDetailPolicy.policyRuleParams - ) - -case object MomentsPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ - Seq( - AuthorBlocksViewerUnspecifiedRule, - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - ) ++ LimitedEngagementBaseRules.tweetRules - ) - -case object NearbyTimelinePolicy - extends VisibilityPolicy( - tweetRules = SearchBlenderRules.tweetRelevanceRules, - userRules = SearchBlenderRules.userBaseRules - ) - -private object NotificationsRules { - val tweetRules: Seq[Rule] = - DropStaleTweetsRule +: VisibilityPolicy.baseTweetRules - - val userRules: Seq[Rule] = Seq( - AbusiveRule, - LowQualityRule, - ReadOnlyRule, - CompromisedRule, - SpamHighRecallRule, - DuplicateContentRule, - AbusiveHighRecallRule, - EngagementSpammerNonFollowerWithUqfRule, - EngagementSpammerHighRecallNonFollowerWithUqfRule, - DownrankSpamReplyNonFollowerWithUqfRule - ) -} - -case object NotificationsIbisPolicy - extends VisibilityPolicy( - tweetRules = - VisibilityPolicy.baseTweetRules ++ Seq( - AbusiveUqfNonFollowerTweetLabelRule, - LowQualityTweetLabelDropRule, - ToxicityReplyFilterDropNotificationRule, - NsfwHighPrecisionTweetLabelRule, - GoreAndViolenceHighPrecisionTweetLabelRule, - NsfwReportedHeuristicsTweetLabelRule, - GoreAndViolenceReportedHeuristicsTweetLabelRule, - NsfwCardImageTweetLabelRule, - NsfwVideoTweetLabelDropRule, - NsfwTextTweetLabelDropRule, - SpamHighRecallTweetLabelDropRule, - DuplicateContentTweetLabelDropRule, - DuplicateMentionTweetLabelRule, - LowQualityMentionTweetLabelRule, - UntrustedUrlUqfNonFollowerTweetLabelRule, - DownrankSpamReplyUqfNonFollowerTweetLabelRule, - SafetyCrisisAnyLevelDropRule, - DoNotAmplifyDropRule, - SmyteSpamTweetLabelDropRule, - AbusePolicyEpisodicTweetLabelDropRule, - EmergencyDropRule, - ), - userRules = NotificationsRules.userRules ++ Seq( - DoNotAmplifyNonFollowerRule, - LikelyIvsLabelNonFollowerDropUserRule, - NsfwTextNonAuthorDropRule - ) - ) - -case object NotificationsReadPolicy - extends VisibilityPolicy( - tweetRules = NotificationsRules.tweetRules, - userRules = NotificationsRules.userRules - ) - -case object NotificationsTimelineDeviceFollowPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules, - userRules = Seq( - AuthorBlocksViewerDropRule, - ViewerBlocksAuthorRule, - CompromisedRule - ) - ) - -case object NotificationsWritePolicy - extends VisibilityPolicy( - tweetRules = NotificationsRules.tweetRules, - userRules = NotificationsRules.userRules - ) - -case object NotificationsWriterV2Policy - extends VisibilityPolicy( - userRules = - Seq( - AuthorBlocksViewerDropRule, - DeactivatedAuthorRule, - ErasedAuthorRule, - ProtectedAuthorDropRule, - SuspendedAuthorRule, - DeactivatedViewerRule, - SuspendedViewerRule, - ViewerBlocksAuthorRule, - ViewerMutesAndDoesNotFollowAuthorRule, - ViewerIsUnmentionedRule, - NoConfirmedEmailRule, - NoConfirmedPhoneRule, - NoDefaultProfileImageRule, - NoNewUsersRule, - NoNotFollowedByRule, - OnlyPeopleIFollowRule - ) ++ - NotificationsRules.userRules - ) - -case object NotificationsWriterTweetHydratorPolicy - extends VisibilityPolicy( - tweetRules = NotificationsRules.tweetRules ++ - Seq( - LowQualityTweetLabelDropRule, - SpamHighRecallTweetLabelDropRule, - DuplicateContentTweetLabelDropRule, - DuplicateMentionUqfTweetLabelRule, - LowQualityMentionTweetLabelRule, - SmyteSpamTweetLabelDropRule, - ToxicityReplyFilterDropNotificationRule, - AbusiveUqfNonFollowerTweetLabelRule, - UntrustedUrlUqfNonFollowerTweetLabelRule, - DownrankSpamReplyUqfNonFollowerTweetLabelRule, - ViewerHasMatchingMutedKeywordForNotificationsRule, - NsfwCardImageAllUsersTweetLabelRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - ) ++ LimitedEngagementBaseRules.tweetRules - ) - -case object NotificationsPlatformPolicy - extends VisibilityPolicy( - tweetRules = NotificationsWriterTweetHydratorPolicy.tweetRules, - userRules = NotificationsWriterV2Policy.userRules - ) - -case object NotificationsPlatformPushPolicy - extends VisibilityPolicy( - tweetRules = NotificationsIbisPolicy.tweetRules, - userRules = Seq(ViewerMutesAuthorRule) - ++ NotificationsIbisPolicy.userRules - ) - -case object QuoteTweetTimelinePolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ Seq( - DropStaleTweetsRule, - AbusiveTweetLabelRule, - LowQualityTweetLabelDropRule, - NsfwHighPrecisionTweetLabelRule, - GoreAndViolenceHighPrecisionTweetLabelRule, - NsfwReportedHeuristicsTweetLabelRule, - GoreAndViolenceReportedHeuristicsTweetLabelRule, - NsfwCardImageTweetLabelRule, - NsfwHighRecallTweetLabelRule, - NsfwVideoTweetLabelDropRule, - NsfwTextTweetLabelDropRule, - SpamHighRecallTweetLabelDropRule, - DuplicateContentTweetLabelDropRule, - GoreAndViolenceTweetLabelRule, - UntrustedUrlTweetLabelRule, - DownrankSpamReplyTweetLabelRule, - SearchBlacklistTweetLabelRule, - AutomationTweetLabelRule, - DuplicateMentionTweetLabelRule, - BystanderAbusiveTweetLabelRule, - SmyteSpamTweetLabelDropRule, - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - ) ++ LimitedEngagementBaseRules.tweetRules, - userRules = Seq( - AbusiveRule, - LowQualityRule, - ReadOnlyRule, - SearchBlacklistRule, - SearchNsfwTextRule, - CompromisedRule, - SpamHighRecallRule, - DuplicateContentRule, - NsfwHighPrecisionRule, - NsfwAvatarImageRule, - NsfwBannerImageRule, - AbusiveHighRecallRule, - DownrankSpamReplyNonAuthorRule, - NsfwTextNonAuthorDropRule - ) - ) - -case object ElevatedQuoteTweetTimelinePolicy - extends VisibilityPolicy( - tweetRules = - TweetDetailPolicy.tweetRules.diff( - Seq( - MutedKeywordForQuotedTweetTweetDetailInterstitialRule, - ReportedTweetInterstitialRule)), - policyRuleParams = TweetDetailPolicy.policyRuleParams - ) - -case object EmbedsPublicInterestNoticePolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ Seq( - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - ) - ) - -case object RecommendationsPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ - Seq( - AbusiveTweetLabelRule, - LowQualityTweetLabelDropRule, - NsfwHighPrecisionTweetLabelRule, - GoreAndViolenceHighPrecisionTweetLabelRule, - NsfwReportedHeuristicsTweetLabelRule, - GoreAndViolenceReportedHeuristicsTweetLabelRule, - NsfwCardImageTweetLabelRule, - NsfwVideoTweetLabelDropRule, - NsfwTextTweetLabelDropRule, - SpamHighRecallTweetLabelDropRule, - DuplicateContentTweetLabelDropRule, - GoreAndViolenceTweetLabelRule, - BystanderAbusiveTweetLabelRule, - DoNotAmplifyDropRule, - SafetyCrisisLevel3DropRule, - SmyteSpamTweetLabelDropRule, - AbusePolicyEpisodicTweetLabelDropRule, - EmergencyDropRule, - ), - userRules = Seq( - DropNsfwAdminAuthorRule, - AbusiveRule, - LowQualityRule, - ReadOnlyRule, - CompromisedRule, - RecommendationsBlacklistRule, - SpamHighRecallRule, - DuplicateContentRule, - NsfwHighPrecisionRule, - NsfwNearPerfectAuthorRule, - NsfwBannerImageRule, - NsfwAvatarImageRule, - EngagementSpammerRule, - EngagementSpammerHighRecallRule, - AbusiveHighRecallRule, - DoNotAmplifyNonFollowerRule, - NotGraduatedNonFollowerRule, - LikelyIvsLabelNonFollowerDropUserRule, - NsfwTextNonAuthorDropRule - ) - ) - -case object RecosVideoPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ Seq( - AbusiveTweetLabelRule, - LowQualityTweetLabelDropRule, - NsfwHighPrecisionTweetLabelRule, - GoreAndViolenceHighPrecisionTweetLabelRule, - NsfwReportedHeuristicsTweetLabelRule, - GoreAndViolenceReportedHeuristicsTweetLabelRule, - NsfwCardImageTweetLabelRule, - NsfwHighRecallTweetLabelRule, - NsfwVideoTweetLabelDropRule, - NsfwTextTweetLabelDropRule, - SpamHighRecallTweetLabelDropRule, - DuplicateContentTweetLabelDropRule, - BystanderAbusiveTweetLabelRule, - SmyteSpamTweetLabelDropRule, - ), - userRules = Seq(NsfwTextNonAuthorDropRule) - ) - -case object RepliesGroupingPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ - Seq( - LowQualityTweetLabelDropRule, - SpamHighRecallTweetLabelDropRule, - DuplicateContentTweetLabelDropRule, - DeciderableSpamHighRecallAuthorLabelDropRule, - SmyteSpamTweetLabelDropRule, - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - MutedKeywordForTweetRepliesInterstitialRule, - ReportedTweetInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - NsfwHighPrecisionTweetLabelAvoidRule, - NsfwHighRecallTweetLabelAvoidRule, - GoreAndViolenceHighPrecisionAvoidAllUsersTweetLabelRule, - NsfwReportedHeuristicsAvoidAdPlacementAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAvoidAdPlacementAllUsersTweetLabelRule, - NsfwCardImageAvoidAdPlacementAllUsersTweetLabelRule, - DoNotAmplifyTweetLabelAvoidRule, - NsfaHighPrecisionTweetLabelAvoidRule, - ) ++ LimitedEngagementBaseRules.tweetRules, - userRules = Seq( - LowQualityRule, - ReadOnlyRule, - LowQualityHighRecallRule, - CompromisedRule, - DeciderableSpamHighRecallRule - ) - ) - -case object ReturningUserExperiencePolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ Seq( - AbusiveTweetLabelRule, - LowQualityTweetLabelDropRule, - NsfaHighRecallTweetLabelRule, - NsfwHighPrecisionTweetLabelRule, - GoreAndViolenceHighPrecisionTweetLabelRule, - NsfwReportedHeuristicsTweetLabelRule, - GoreAndViolenceReportedHeuristicsTweetLabelRule, - NsfwCardImageTweetLabelRule, - NsfwHighRecallTweetLabelRule, - NsfwVideoTweetLabelDropRule, - NsfwTextTweetLabelDropRule, - NsfwTextHighPrecisionTweetLabelDropRule, - SpamHighRecallTweetLabelDropRule, - DuplicateContentTweetLabelDropRule, - GoreAndViolenceTweetLabelRule, - UntrustedUrlTweetLabelRule, - DownrankSpamReplyTweetLabelRule, - SearchBlacklistTweetLabelRule, - AutomationTweetLabelRule, - DuplicateMentionTweetLabelRule, - BystanderAbusiveTweetLabelRule, - SmyteSpamTweetLabelDropRule, - SafetyCrisisLevel3DropRule, - SafetyCrisisLevel4DropRule, - DoNotAmplifyDropRule, - AbusePolicyEpisodicTweetLabelDropRule, - EmergencyDropRule, - ) ++ LimitedEngagementBaseRules.tweetRules, - userRules = Seq( - AbusiveRule, - LowQualityRule, - ReadOnlyRule, - SearchBlacklistRule, - SearchNsfwTextRule, - CompromisedRule, - SpamHighRecallRule, - DuplicateContentRule, - NsfwHighPrecisionRule, - NsfwAvatarImageRule, - NsfwBannerImageRule, - AbusiveHighRecallRule, - DoNotAmplifyNonFollowerRule, - NotGraduatedNonFollowerRule, - LikelyIvsLabelNonFollowerDropUserRule, - DownrankSpamReplyNonAuthorRule, - NsfwTextNonAuthorDropRule, - DropNsfwUserAuthorRule, - NsfwHighRecallRule - ) - ) - -case object ReturningUserExperienceFocalTweetPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ - Seq( - AuthorBlocksViewerDropRule, - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - MutedKeywordForTweetRepliesInterstitialRule, - ViewerMutesAuthorInterstitialRule, - ReportedTweetInterstitialRule, - ) ++ LimitedEngagementBaseRules.tweetRules - ) - -case object RevenuePolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ - Seq( - AbusiveTweetLabelRule, - BystanderAbusiveTweetLabelRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule - ) - ) - -case object SafeSearchMinimalPolicy - extends VisibilityPolicy( - tweetRules = Seq( - DropOuterCommunityTweetsRule, - ) ++ VisibilityPolicy.baseTweetRules ++ Seq( - LowQualityTweetLabelDropRule, - HighProactiveTosScoreTweetLabelDropSearchRule, - SpamHighRecallTweetLabelDropRule, - DuplicateContentTweetLabelDropRule, - SearchBlacklistTweetLabelRule, - SearchBlacklistHighRecallTweetLabelDropRule, - SafetyCrisisLevel3DropRule, - SafetyCrisisLevel4DropRule, - DoNotAmplifyDropRule, - SmyteSpamTweetLabelDropRule, - ) ++ - Seq( - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - ) ++ LimitedEngagementBaseRules.tweetRules - ++ SearchBlenderRules.tweetAvoidRules, - userRules = Seq( - LowQualityRule, - ReadOnlyRule, - CompromisedRule, - SpamHighRecallRule, - SearchBlacklistRule, - SearchNsfwTextRule, - DuplicateContentRule, - DoNotAmplifyNonFollowerRule, - SearchLikelyIvsLabelNonFollowerDropUserRule - ) - ) - -case object SearchHydrationPolicy - extends VisibilityPolicy( - tweetRules = Seq( - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - ReportedTweetInterstitialSearchRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - ) ++ LimitedEngagementBaseRules.tweetRules - ) - -case object SearchBlenderRules { - val limitedEngagementBaseRules: Seq[Rule] = LimitedEngagementBaseRules.tweetRules - - val tweetAvoidRules: Seq[Rule] = - Seq( - NsfwHighPrecisionTweetLabelAvoidRule, - NsfwHighRecallTweetLabelAvoidRule, - GoreAndViolenceHighPrecisionAvoidAllUsersTweetLabelRule, - NsfwReportedHeuristicsAvoidAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAvoidAllUsersTweetLabelRule, - NsfwCardImageAvoidAllUsersTweetLabelRule, - SearchAvoidTweetNsfwAdminRule, - SearchAvoidTweetNsfwUserRule, - DoNotAmplifyTweetLabelAvoidRule, - NsfaHighPrecisionTweetLabelAvoidRule, - ) - - val basicBlockMuteRules: Seq[Rule] = Seq( - AuthorBlocksViewerDropRule, - ViewerBlocksAuthorViewerOptInBlockingOnSearchRule, - ViewerMutesAuthorViewerOptInBlockingOnSearchRule - ) - - val tweetRelevanceRules: Seq[Rule] = - Seq( - DropOuterCommunityTweetsRule, - DropStaleTweetsRule, - ) ++ VisibilityPolicy.baseTweetRules ++ Seq( - SafeSearchAbusiveTweetLabelRule, - LowQualityTweetLabelDropRule, - HighProactiveTosScoreTweetLabelDropSearchRule, - HighPSpammyTweetScoreSearchTweetLabelDropRule, - HighSpammyTweetContentScoreSearchTopTweetLabelDropRule, - HighSpammyTweetContentScoreTrendsTopTweetLabelDropRule, - SafeSearchNsfwHighPrecisionTweetLabelRule, - SafeSearchGoreAndViolenceHighPrecisionTweetLabelRule, - SafeSearchNsfwReportedHeuristicsTweetLabelRule, - SafeSearchGoreAndViolenceReportedHeuristicsTweetLabelRule, - SafeSearchNsfwCardImageTweetLabelRule, - SafeSearchNsfwHighRecallTweetLabelRule, - SafeSearchNsfwVideoTweetLabelRule, - SafeSearchNsfwTextTweetLabelRule, - SpamHighRecallTweetLabelDropRule, - DuplicateContentTweetLabelDropRule, - SafeSearchGoreAndViolenceTweetLabelRule, - SafeSearchUntrustedUrlTweetLabelRule, - SafeSearchDownrankSpamReplyTweetLabelRule, - SearchBlacklistTweetLabelRule, - SearchBlacklistHighRecallTweetLabelDropRule, - SmyteSpamTweetLabelDropSearchRule, - CopypastaSpamAllViewersSearchTweetLabelRule, - ) ++ basicBlockMuteRules ++ - Seq( - SafeSearchAutomationNonFollowerTweetLabelRule, - SafeSearchDuplicateMentionNonFollowerTweetLabelRule, - SafeSearchBystanderAbusiveTweetLabelRule, - SafetyCrisisLevel3DropRule, - SafetyCrisisLevel4DropRule, - DoNotAmplifyDropRule, - SearchIpiSafeSearchWithoutUserInQueryDropRule, - SearchEdiSafeSearchWithoutUserInQueryDropRule, - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - UnsafeSearchNsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - UnsafeSearchGoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - UnsafeSearchNsfwReportedHeuristicsAllUsersTweetLabelRule, - UnsafeSearchGoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - UnsafeSearchNsfwCardImageAllUsersTweetLabelRule, - ) ++ - limitedEngagementBaseRules ++ - tweetAvoidRules - - VisibilityPolicy.baseTweetRules ++ Seq( - SafeSearchAbusiveTweetLabelRule, - LowQualityTweetLabelDropRule, - HighProactiveTosScoreTweetLabelDropSearchRule, - HighSpammyTweetContentScoreSearchLatestTweetLabelDropRule, - HighSpammyTweetContentScoreTrendsLatestTweetLabelDropRule, - SafeSearchNsfwHighPrecisionTweetLabelRule, - SafeSearchGoreAndViolenceHighPrecisionTweetLabelRule, - SafeSearchNsfwReportedHeuristicsTweetLabelRule, - SafeSearchGoreAndViolenceReportedHeuristicsTweetLabelRule, - SafeSearchNsfwCardImageTweetLabelRule, - SafeSearchNsfwHighRecallTweetLabelRule, - SafeSearchNsfwVideoTweetLabelRule, - SafeSearchNsfwTextTweetLabelRule, - SpamHighRecallTweetLabelDropRule, - DuplicateContentTweetLabelDropRule, - SafeSearchGoreAndViolenceTweetLabelRule, - SafeSearchUntrustedUrlTweetLabelRule, - SafeSearchDownrankSpamReplyTweetLabelRule, - SearchBlacklistTweetLabelRule, - SearchBlacklistHighRecallTweetLabelDropRule, - SmyteSpamTweetLabelDropSearchRule, - CopypastaSpamNonFollowerSearchTweetLabelRule, - ) ++ - basicBlockMuteRules ++ - Seq( - SafeSearchAutomationNonFollowerTweetLabelRule, - SafeSearchDuplicateMentionNonFollowerTweetLabelRule, - SafeSearchBystanderAbusiveTweetLabelRule, - SafetyCrisisLevel3DropRule, - SafetyCrisisLevel4DropRule, - SearchIpiSafeSearchWithoutUserInQueryDropRule, - SearchEdiSafeSearchWithoutUserInQueryDropRule, - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - UnsafeSearchNsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - UnsafeSearchGoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - UnsafeSearchNsfwReportedHeuristicsAllUsersTweetLabelRule, - UnsafeSearchGoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - UnsafeSearchNsfwCardImageAllUsersTweetLabelRule, - ) ++ limitedEngagementBaseRules ++ tweetAvoidRules - - val userBaseRules: Seq[ConditionWithUserLabelRule] = Seq( - SafeSearchAbusiveUserLabelRule, - LowQualityRule, - ReadOnlyRule, - SearchBlacklistRule, - CompromisedRule, - SpamHighRecallRule, - DuplicateContentRule, - DoNotAmplifyNonFollowerRule, - SearchLikelyIvsLabelNonFollowerDropUserRule, - SafeSearchNsfwHighPrecisionUserLabelRule, - SafeSearchNsfwAvatarImageUserLabelRule, - SafeSearchNsfwBannerImageUserLabelRule, - SafeSearchAbusiveHighRecallUserLabelRule, - SafeSearchDownrankSpamReplyAuthorLabelRule, - SafeSearchNotGraduatedNonFollowersUserLabelRule, - SafeSearchNsfwTextAuthorLabelRule - ) - - val userRules: Seq[ConditionWithUserLabelRule] = userBaseRules - - val userRelevanceBaseRules = userBaseRules ++ basicBlockMuteRules - - val userRelevanceRules = userRelevanceBaseRules - - val userRecencyBaseRules = userBaseRules.filterNot( - Seq(DoNotAmplifyNonFollowerRule, SearchLikelyIvsLabelNonFollowerDropUserRule).contains - ) ++ basicBlockMuteRules - - val searchQueryMatchesTweetAuthorRules: Seq[ConditionWithUserLabelRule] = - userBaseRules - - val basicBlockMutePolicyRuleParam: Map[Rule, PolicyLevelRuleParams] = - SearchBlenderRules.basicBlockMuteRules - .map(rule => rule -> ruleParams(RuleParams.EnableSearchBasicBlockMuteRulesParam)).toMap -} - -case object SearchBlenderUserRulesPolicy - extends VisibilityPolicy( - userRules = SearchBlenderRules.userRules - ) - -case object SearchLatestUserRulesPolicy - extends VisibilityPolicy( - userRules = SearchLatestPolicy.userRules - ) - -case object UserSearchSrpPolicy - extends VisibilityPolicy( - userRules = Seq( - AuthorBlocksViewerDropRule, - ViewerBlocksAuthorViewerOptInBlockingOnSearchRule, - ViewerMutesAuthorViewerOptInBlockingOnSearchRule, - DropNsfwAdminAuthorViewerOptInFilteringOnSearchRule, - SafeSearchAbusiveUserLabelRule, - SafeSearchHighRecallUserLabelRule, - SafeSearchNsfwNearPerfectAuthorRule, - SafeSearchNsfwHighPrecisionUserLabelRule, - SafeSearchNsfwAvatarImageUserLabelRule, - SafeSearchNsfwBannerImageUserLabelRule, - SafeSearchAbusiveHighRecallUserLabelRule, - SafeSearchNsfwTextAuthorLabelRule - ) - ) - -case object UserSearchTypeaheadPolicy - extends VisibilityPolicy( - userRules = Seq( - SafeSearchAbusiveUserLabelRule, - SafeSearchHighRecallUserLabelRule, - SafeSearchNsfwNearPerfectAuthorRule, - SafeSearchNsfwHighPrecisionUserLabelRule, - SafeSearchNsfwAvatarImageUserLabelRule, - SafeSearchNsfwBannerImageUserLabelRule, - SafeSearchAbusiveHighRecallUserLabelRule, - SafeSearchNsfwTextAuthorLabelRule - ), - tweetRules = Seq(DropAllRule) - ) - -case object SearchMixerSrpMinimalPolicy - extends VisibilityPolicy( - userRules = Seq( - AuthorBlocksViewerDropRule, - ViewerBlocksAuthorViewerOptInBlockingOnSearchRule, - ViewerMutesAuthorViewerOptInBlockingOnSearchRule - ) - ) - -case object SearchMixerSrpStrictPolicy - extends VisibilityPolicy( - userRules = Seq( - AuthorBlocksViewerDropRule, - ViewerBlocksAuthorViewerOptInBlockingOnSearchRule, - ViewerMutesAuthorViewerOptInBlockingOnSearchRule, - DropNsfwAdminAuthorViewerOptInFilteringOnSearchRule, - NsfwNearPerfectAuthorRule, - NsfwHighPrecisionRule, - NsfwHighRecallRule, - NsfwSensitiveRule, - NsfwAvatarImageRule, - NsfwBannerImageRule - ) ++ SearchBlenderRules.searchQueryMatchesTweetAuthorRules - .diff(Seq(SafeSearchNotGraduatedNonFollowersUserLabelRule)) - ) - -case object SearchPeopleSrpPolicy - extends VisibilityPolicy( - userRules = SearchBlenderRules.searchQueryMatchesTweetAuthorRules - ) - -case object SearchPeopleTypeaheadPolicy - extends VisibilityPolicy( - userRules = SearchBlenderRules.searchQueryMatchesTweetAuthorRules - .diff( - Seq( - SafeSearchNotGraduatedNonFollowersUserLabelRule - )), - tweetRules = Seq(DropAllRule) - ) - -case object SearchPhotoPolicy - extends VisibilityPolicy( - tweetRules = SearchBlenderRules.tweetRelevanceRules, - userRules = SearchBlenderRules.userRelevanceRules, - policyRuleParams = SearchBlenderRules.basicBlockMutePolicyRuleParam - ) - -case object SearchTrendTakeoverPromotedTweetPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules - ) - -case object SearchVideoPolicy - extends VisibilityPolicy( - tweetRules = SearchBlenderRules.tweetRelevanceRules, - userRules = SearchBlenderRules.userRelevanceRules, - policyRuleParams = SearchBlenderRules.basicBlockMutePolicyRuleParam - ) - -case object SearchLatestPolicy - extends VisibilityPolicy( - tweetRules = SearchBlenderRules.tweetRecencyRules, - userRules = SearchBlenderRules.userRecencyBaseRules, - policyRuleParams = SearchBlenderRules.basicBlockMutePolicyRuleParam - ) - -case object SearchTopPolicy - extends VisibilityPolicy( - tweetRules = SearchBlenderRules.tweetRelevanceRules, - userRules = Seq(SpammyUserModelHighPrecisionDropTweetRule) ++ - SearchBlenderRules.basicBlockMuteRules ++ - SearchBlenderRules.searchQueryMatchesTweetAuthorRules, - policyRuleParams = SearchBlenderRules.basicBlockMutePolicyRuleParam - ) - -case object SearchTopQigPolicy - extends VisibilityPolicy( - tweetRules = BaseQigPolicy.tweetRules ++ - Seq( - UnsafeSearchGoreAndViolenceHighPrecisionAllUsersTweetLabelDropRule, - UnsafeSearchGoreAndViolenceReportedHeuristicsAllUsersTweetLabelDropRule, - UnsafeSearchNsfwCardImageAllUsersTweetLabelDropRule, - UnsafeSearchNsfwReportedHeuristicsAllUsersTweetLabelDropRule, - UnsafeSearchNsfwHighPrecisionAllUsersTweetLabelDropRule - ) ++ - SearchTopPolicy.tweetRules.diff( - Seq( - SearchIpiSafeSearchWithoutUserInQueryDropRule, - SearchEdiSafeSearchWithoutUserInQueryDropRule, - HighSpammyTweetContentScoreTrendsTopTweetLabelDropRule, - UnsafeSearchNsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - UnsafeSearchGoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - UnsafeSearchGoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - UnsafeSearchNsfwCardImageAllUsersTweetLabelRule, - UnsafeSearchNsfwReportedHeuristicsAllUsersTweetLabelRule - ) ++ - SearchTopPolicy.tweetRules.intersect(BaseQigPolicy.tweetRules)), - userRules = BaseQigPolicy.userRules ++ Seq( - DropNsfwAdminAuthorViewerOptInFilteringOnSearchRule, - NsfwNearPerfectAuthorRule, - ) ++ SearchTopPolicy.userRules.diff( - SearchTopPolicy.userRules.intersect(BaseQigPolicy.userRules)), - policyRuleParams = SearchBlenderRules.basicBlockMutePolicyRuleParam - ) - -case object SafeSearchStrictPolicy - extends VisibilityPolicy( - tweetRules = Seq( - DropOuterCommunityTweetsRule, - ) ++ VisibilityPolicy.baseTweetRules ++ Seq( - AbusiveTweetLabelRule, - LowQualityTweetLabelDropRule, - HighProactiveTosScoreTweetLabelDropSearchRule, - NsfwHighPrecisionTweetLabelRule, - GoreAndViolenceHighPrecisionTweetLabelRule, - NsfwReportedHeuristicsTweetLabelRule, - GoreAndViolenceReportedHeuristicsTweetLabelRule, - NsfwCardImageTweetLabelRule, - NsfwHighRecallTweetLabelRule, - NsfwVideoTweetLabelDropRule, - NsfwTextTweetLabelDropRule, - SpamHighRecallTweetLabelDropRule, - DuplicateContentTweetLabelDropRule, - GoreAndViolenceTweetLabelRule, - UntrustedUrlTweetLabelRule, - DownrankSpamReplyTweetLabelRule, - SearchBlacklistTweetLabelRule, - SearchBlacklistHighRecallTweetLabelDropRule, - AutomationTweetLabelRule, - DuplicateMentionTweetLabelRule, - BystanderAbusiveTweetLabelRule, - SafetyCrisisLevel3DropRule, - SafetyCrisisLevel4DropRule, - DoNotAmplifyDropRule, - SmyteSpamTweetLabelDropRule, - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - ) ++ LimitedEngagementBaseRules.tweetRules - ++ SearchBlenderRules.tweetAvoidRules, - userRules = Seq( - AbusiveRule, - LowQualityRule, - ReadOnlyRule, - SearchBlacklistRule, - SearchNsfwTextRule, - CompromisedRule, - SpamHighRecallRule, - DuplicateContentRule, - NsfwHighPrecisionRule, - NsfwAvatarImageRule, - NsfwBannerImageRule, - AbusiveHighRecallRule, - DoNotAmplifyNonFollowerRule, - NotGraduatedNonFollowerRule, - SearchLikelyIvsLabelNonFollowerDropUserRule, - DownrankSpamReplyNonAuthorRule, - NsfwTextNonAuthorDropRule, - ) - ) - -case object StickersTimelinePolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules, - userRules = Seq( - AbusiveRule, - LowQualityRule, - ReadOnlyRule, - CompromisedRule, - SearchBlacklistRule, - SearchNsfwTextRule, - DuplicateContentRule, - EngagementSpammerRule, - EngagementSpammerHighRecallRule, - NsfwSensitiveRule, - SpamHighRecallRule, - AbusiveHighRecallRule - ) - ) - -case object StratoExtLimitedEngagementsPolicy - extends VisibilityPolicy( - tweetRules = - VisibilityPolicy.baseTweetRules ++ LimitedEngagementBaseRules.tweetRules - ) - -case object InternalPromotedContentPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules - ) - -case object StreamServicesPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ Seq( - AbusiveTweetLabelRule, - LowQualityTweetLabelDropRule, - NsfwHighPrecisionTweetLabelRule, - GoreAndViolenceHighPrecisionTweetLabelRule, - NsfwReportedHeuristicsTweetLabelRule, - GoreAndViolenceReportedHeuristicsTweetLabelRule, - NsfwCardImageTweetLabelRule, - NsfwVideoTweetLabelDropRule, - NsfwTextTweetLabelDropRule, - SpamHighRecallTweetLabelDropRule, - DuplicateContentTweetLabelDropRule, - BystanderAbusiveTweetLabelRule, - SmyteSpamTweetLabelDropRule - ), - userRules = Seq(NsfwTextNonAuthorDropRule) - ) - -case object SuperLikePolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ Seq( - AbusePolicyEpisodicTweetLabelDropRule, - EmergencyDropRule, - NsfwHighPrecisionTweetLabelRule, - GoreAndViolenceHighPrecisionTweetLabelRule, - NsfwReportedHeuristicsTweetLabelRule, - GoreAndViolenceReportedHeuristicsTweetLabelRule, - NsfwCardImageTweetLabelRule, - NsfwVideoTweetLabelDropRule, - NsfwTextTweetLabelDropRule - ), - userRules = Seq(NsfwTextNonAuthorDropRule) - ) - -case object TimelineFocalTweetPolicy - extends VisibilityPolicy( - tweetRules = Seq( - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - ) ++ LimitedEngagementBaseRules.tweetRules - ) - -case object TimelineBookmarkPolicy - extends VisibilityPolicy( - tweetRules = - Seq( - DropCommunityTweetsRule, - DropCommunityTweetCommunityNotVisibleRule, - DropProtectedCommunityTweetsRule, - DropHiddenCommunityTweetsRule, - DropAuthorRemovedCommunityTweetsRule, - SpamTweetLabelRule, - PdnaTweetLabelRule, - BounceOuterTweetTombstoneRule, - BounceQuotedTweetTombstoneRule, - DropExclusiveTweetContentRule, - DropTrustedFriendsTweetContentRule, - ) ++ - Seq( - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - ViewerBlocksAuthorInnerQuotedTweetInterstitialRule, - ViewerMutesAuthorInnerQuotedTweetInterstitialRule, - NsfwCardImageAllUsersTweetLabelRule, - ) ++ LimitedEngagementBaseRules.tweetRules, - deletedTweetRules = Seq( - TombstoneBounceDeletedTweetRule, - TombstoneDeletedQuotedTweetRule - ), - userUnavailableStateRules = Seq( - SuspendedUserUnavailableTweetTombstoneRule, - DeactivatedUserUnavailableTweetTombstoneRule, - OffBoardedUserUnavailableTweetTombstoneRule, - ErasedUserUnavailableTweetTombstoneRule, - ProtectedUserUnavailableTweetTombstoneRule, - AuthorBlocksViewerUserUnavailableInnerQuotedTweetTombstoneRule, - UserUnavailableTweetTombstoneRule, - ViewerBlocksAuthorUserUnavailableInnerQuotedTweetInterstitialRule, - ViewerMutesAuthorUserUnavailableInnerQuotedTweetInterstitialRule - ), - ) - -case object TimelineListsPolicy - extends VisibilityPolicy( - tweetRules = - Seq( - DropOuterCommunityTweetsRule, - DropStaleTweetsRule, - ) ++ - VisibilityPolicy.baseTweetRules ++ - Seq( - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - NsfwHighPrecisionTweetLabelAvoidRule, - NsfwHighRecallTweetLabelAvoidRule, - GoreAndViolenceHighPrecisionAvoidAllUsersTweetLabelRule, - NsfwReportedHeuristicsAvoidAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAvoidAllUsersTweetLabelRule, - NsfwCardImageAvoidAllUsersTweetLabelRule, - DoNotAmplifyTweetLabelAvoidRule, - NsfaHighPrecisionTweetLabelAvoidRule, - ) ++ LimitedEngagementBaseRules.tweetRules - ) - -case object TimelineFavoritesPolicy - extends VisibilityPolicy( - tweetRules = - Seq( - DropOuterCommunityTweetsRule, - DropStaleTweetsRule, - ) - ++ TimelineProfileRules.baseTweetRules - ++ Seq( - DynamicProductAdDropTweetLabelRule, - NsfwHighPrecisionTombstoneInnerQuotedTweetLabelRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.AdultMediaNsfwHighPrecisionTweetLabelDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.ViolentMediaGoreAndViolenceHighPrecisionDropSettingLeveTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.AdultMediaNsfwReportedHeuristicsTweetLabelDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.ViolentMediaGoreAndViolenceReportedHeuristicsDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.AdultMediaNsfwCardImageTweetLabelDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.OtherSensitiveMediaNsfwUserTweetFlagDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.OtherSensitiveMediaNsfwAdminTweetFlagDropSettingLevelTombstoneRule, - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - ReportedTweetInterstitialRule, - ViewerMutesAuthorInterstitialRule, - ViewerBlocksAuthorInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwHighPrecisionTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceHighPrecisionInterstitialRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwReportedHeuristicsTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceReportedHeuristicsInterstitialRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwCardImageTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwUserTweetFlagInterstitialRule, - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwAdminTweetFlagInterstitialRule, - NsfwHighPrecisionTweetLabelAvoidRule, - NsfwHighRecallTweetLabelAvoidRule, - GoreAndViolenceHighPrecisionAvoidAllUsersTweetLabelRule, - NsfwReportedHeuristicsAvoidAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAvoidAllUsersTweetLabelRule, - NsfwCardImageAvoidAllUsersTweetLabelRule, - DoNotAmplifyTweetLabelAvoidRule, - NsfaHighPrecisionTweetLabelAvoidRule, - ) ++ LimitedEngagementBaseRules.tweetRules, - deletedTweetRules = Seq( - TombstoneDeletedQuotedTweetRule, - TombstoneBounceDeletedQuotedTweetRule - ), - userUnavailableStateRules = Seq( - SuspendedUserUnavailableInnerQuotedTweetTombstoneRule, - DeactivatedUserUnavailableInnerQuotedTweetTombstoneRule, - OffBoardedUserUnavailableInnerQuotedTweetTombstoneRule, - ErasedUserUnavailableInnerQuotedTweetTombstoneRule, - ProtectedUserUnavailableInnerQuotedTweetTombstoneRule, - AuthorBlocksViewerUserUnavailableInnerQuotedTweetTombstoneRule, - ViewerBlocksAuthorUserUnavailableInnerQuotedTweetInterstitialRule, - ViewerMutesAuthorUserUnavailableInnerQuotedTweetInterstitialRule - ), - policyRuleParams = SensitiveMediaSettingsProfileTimelineBaseRules.policyRuleParams - ) - -case object ProfileMixerFavoritesPolicy - extends VisibilityPolicy( - tweetRules = Seq( - DropStaleTweetsRule, - DropExclusiveTweetContentRule, - DropOuterCommunityTweetsRule, - ), - deletedTweetRules = Seq( - TombstoneDeletedQuotedTweetRule, - TombstoneBounceDeletedQuotedTweetRule - ) - ) - -case object TimelineMediaPolicy - extends VisibilityPolicy( - TimelineProfileRules.baseTweetRules - ++ Seq( - NsfwHighPrecisionTombstoneInnerQuotedTweetLabelRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.AdultMediaNsfwHighPrecisionTweetLabelDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.ViolentMediaGoreAndViolenceHighPrecisionDropSettingLeveTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.AdultMediaNsfwReportedHeuristicsTweetLabelDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.ViolentMediaGoreAndViolenceReportedHeuristicsDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.AdultMediaNsfwCardImageTweetLabelDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.OtherSensitiveMediaNsfwUserTweetFlagDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.OtherSensitiveMediaNsfwAdminTweetFlagDropSettingLevelTombstoneRule, - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - ReportedTweetInterstitialRule, - ViewerMutesAuthorInnerQuotedTweetInterstitialRule, - ViewerBlocksAuthorInnerQuotedTweetInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwHighPrecisionTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceHighPrecisionInterstitialRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwReportedHeuristicsTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceReportedHeuristicsInterstitialRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwCardImageTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwUserTweetFlagInterstitialRule, - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwAdminTweetFlagInterstitialRule, - NsfwHighPrecisionTweetLabelAvoidRule, - NsfwHighRecallTweetLabelAvoidRule, - GoreAndViolenceHighPrecisionAvoidAllUsersTweetLabelRule, - NsfwReportedHeuristicsAvoidAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAvoidAllUsersTweetLabelRule, - NsfwCardImageAvoidAllUsersTweetLabelRule, - DoNotAmplifyTweetLabelAvoidRule, - NsfaHighPrecisionTweetLabelAvoidRule, - ) ++ LimitedEngagementBaseRules.tweetRules, - deletedTweetRules = Seq( - TombstoneBounceDeletedOuterTweetRule, - TombstoneDeletedQuotedTweetRule, - TombstoneBounceDeletedQuotedTweetRule - ), - userUnavailableStateRules = Seq( - SuspendedUserUnavailableInnerQuotedTweetTombstoneRule, - DeactivatedUserUnavailableInnerQuotedTweetTombstoneRule, - OffBoardedUserUnavailableInnerQuotedTweetTombstoneRule, - ErasedUserUnavailableInnerQuotedTweetTombstoneRule, - ProtectedUserUnavailableInnerQuotedTweetTombstoneRule, - AuthorBlocksViewerUserUnavailableInnerQuotedTweetTombstoneRule, - ViewerBlocksAuthorUserUnavailableInnerQuotedTweetInterstitialRule, - ViewerMutesAuthorUserUnavailableInnerQuotedTweetInterstitialRule - ), - policyRuleParams = SensitiveMediaSettingsProfileTimelineBaseRules.policyRuleParams - ) - -case object ProfileMixerMediaPolicy - extends VisibilityPolicy( - tweetRules = Seq( - DropStaleTweetsRule, - DropExclusiveTweetContentRule - ), - deletedTweetRules = Seq( - TombstoneBounceDeletedOuterTweetRule, - TombstoneDeletedQuotedTweetRule, - TombstoneBounceDeletedQuotedTweetRule - ) - ) - -object TimelineProfileRules { - - val baseTweetRules: Seq[Rule] = Seq( - TombstoneCommunityTweetsRule, - TombstoneCommunityTweetCommunityNotVisibleRule, - TombstoneProtectedCommunityTweetsRule, - TombstoneHiddenCommunityTweetsRule, - TombstoneAuthorRemovedCommunityTweetsRule, - SpamQuotedTweetLabelTombstoneRule, - SpamTweetLabelRule, - PdnaQuotedTweetLabelTombstoneRule, - PdnaTweetLabelRule, - BounceTweetLabelTombstoneRule, - TombstoneExclusiveQuotedTweetContentRule, - DropExclusiveTweetContentRule, - DropTrustedFriendsTweetContentRule - ) - - val tweetRules: Seq[Rule] = - Seq( - DynamicProductAdDropTweetLabelRule, - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - ReportedTweetInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - NsfwHighPrecisionTweetLabelAvoidRule, - NsfwHighRecallTweetLabelAvoidRule, - GoreAndViolenceHighPrecisionAvoidAllUsersTweetLabelRule, - NsfwReportedHeuristicsAvoidAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAvoidAllUsersTweetLabelRule, - NsfwCardImageAvoidAllUsersTweetLabelRule, - NsfwTextTweetLabelAvoidRule, - DoNotAmplifyTweetLabelAvoidRule, - NsfaHighPrecisionTweetLabelAvoidRule, - ) ++ LimitedEngagementBaseRules.tweetRules - - val tweetTombstoneRules: Seq[Rule] = - Seq( - DynamicProductAdDropTweetLabelRule, - NsfwHighPrecisionInnerQuotedTweetLabelRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.AdultMediaNsfwHighPrecisionTweetLabelDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.ViolentMediaGoreAndViolenceHighPrecisionDropSettingLeveTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.AdultMediaNsfwReportedHeuristicsTweetLabelDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.ViolentMediaGoreAndViolenceReportedHeuristicsDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.AdultMediaNsfwCardImageTweetLabelDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.OtherSensitiveMediaNsfwUserTweetFlagDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.OtherSensitiveMediaNsfwAdminTweetFlagDropSettingLevelTombstoneRule, - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - ReportedTweetInterstitialRule, - ViewerMutesAuthorInnerQuotedTweetInterstitialRule, - ViewerBlocksAuthorInnerQuotedTweetInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwHighPrecisionTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceHighPrecisionInterstitialRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwReportedHeuristicsTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceReportedHeuristicsInterstitialRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwCardImageTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwUserTweetFlagInterstitialRule, - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwAdminTweetFlagInterstitialRule, - NsfwHighPrecisionTweetLabelAvoidRule, - NsfwHighRecallTweetLabelAvoidRule, - GoreAndViolenceHighPrecisionAvoidAllUsersTweetLabelRule, - NsfwReportedHeuristicsAvoidAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAvoidAllUsersTweetLabelRule, - NsfwCardImageAvoidAllUsersTweetLabelRule, - DoNotAmplifyTweetLabelAvoidRule, - NsfaHighPrecisionTweetLabelAvoidRule, - ) ++ LimitedEngagementBaseRules.tweetRules -} - -case object TimelineProfilePolicy - extends VisibilityPolicy( - tweetRules = - Seq( - DropOuterCommunityTweetsRule, - DropStaleTweetsRule, - ) - ++ TimelineProfileRules.baseTweetRules - ++ TimelineProfileRules.tweetTombstoneRules, - deletedTweetRules = Seq( - TombstoneBounceDeletedOuterTweetRule, - TombstoneDeletedQuotedTweetRule, - TombstoneBounceDeletedQuotedTweetRule, - ), - userUnavailableStateRules = Seq( - SuspendedUserUnavailableInnerQuotedTweetTombstoneRule, - DeactivatedUserUnavailableInnerQuotedTweetTombstoneRule, - OffBoardedUserUnavailableInnerQuotedTweetTombstoneRule, - ErasedUserUnavailableInnerQuotedTweetTombstoneRule, - ProtectedUserUnavailableInnerQuotedTweetTombstoneRule, - AuthorBlocksViewerUserUnavailableInnerQuotedTweetTombstoneRule, - ViewerBlocksAuthorUserUnavailableInnerQuotedTweetInterstitialRule, - ViewerMutesAuthorUserUnavailableInnerQuotedTweetInterstitialRule - ), - policyRuleParams = SensitiveMediaSettingsProfileTimelineBaseRules.policyRuleParams - ) - -case object TimelineProfileAllPolicy - extends VisibilityPolicy( - TimelineProfileRules.baseTweetRules - ++ TimelineProfileRules.tweetTombstoneRules, - deletedTweetRules = Seq( - TombstoneBounceDeletedOuterTweetRule, - TombstoneDeletedQuotedTweetRule, - TombstoneBounceDeletedQuotedTweetRule, - ), - userUnavailableStateRules = Seq( - SuspendedUserUnavailableInnerQuotedTweetTombstoneRule, - DeactivatedUserUnavailableInnerQuotedTweetTombstoneRule, - OffBoardedUserUnavailableInnerQuotedTweetTombstoneRule, - ErasedUserUnavailableInnerQuotedTweetTombstoneRule, - ProtectedUserUnavailableInnerQuotedTweetTombstoneRule, - AuthorBlocksViewerUserUnavailableInnerQuotedTweetTombstoneRule, - ViewerBlocksAuthorUserUnavailableInnerQuotedTweetInterstitialRule, - ViewerMutesAuthorUserUnavailableInnerQuotedTweetInterstitialRule - ), - policyRuleParams = SensitiveMediaSettingsProfileTimelineBaseRules.policyRuleParams - ) - -case object TimelineProfileSuperFollowsPolicy - extends VisibilityPolicy( - tweetRules = - Seq( - DropOuterCommunityTweetsRule - ) ++ - VisibilityPolicy.baseTweetRules ++ - TimelineProfileRules.tweetRules - ) - -case object TimelineReactiveBlendingPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ - Seq( - ViewerHasMatchingMutedKeywordForHomeTimelineRule, - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - ) ++ LimitedEngagementBaseRules.tweetRules - ) - -case object TimelineHomePolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseQuotedTweetTombstoneRules ++ - VisibilityPolicy.baseTweetRules ++ - Seq( - NullcastedTweetRule, - DropOuterCommunityTweetsRule, - DynamicProductAdDropTweetLabelRule, - MutedRetweetsRule, - DropAllAuthorRemovedCommunityTweetsRule, - DropAllHiddenCommunityTweetsRule, - AbusePolicyEpisodicTweetLabelDropRule, - EmergencyDropRule, - SafetyCrisisLevel4DropRule, - ViewerHasMatchingMutedKeywordForHomeTimelineRule, - SensitiveMediaTweetDropRules.AdultMediaNsfwHighPrecisionTweetLabelDropRule, - SensitiveMediaTweetDropRules.ViolentMediaGoreAndViolenceHighPrecisionDropRule, - SensitiveMediaTweetDropRules.AdultMediaNsfwReportedHeuristicsTweetLabelDropRule, - SensitiveMediaTweetDropRules.ViolentMediaGoreAndViolenceReportedHeuristicsDropRule, - SensitiveMediaTweetDropRules.AdultMediaNsfwCardImageTweetLabelDropRule, - SensitiveMediaTweetDropRules.OtherSensitiveMediaNsfwUserTweetFlagDropRule, - SensitiveMediaTweetDropRules.OtherSensitiveMediaNsfwAdminTweetFlagDropRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwHighPrecisionTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceHighPrecisionInterstitialRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwReportedHeuristicsTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceReportedHeuristicsInterstitialRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwCardImageTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwUserTweetFlagInterstitialRule, - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwAdminTweetFlagInterstitialRule, - NsfwHighPrecisionTweetLabelAvoidRule, - NsfwHighRecallTweetLabelAvoidRule, - GoreAndViolenceHighPrecisionAvoidAllUsersTweetLabelRule, - NsfwReportedHeuristicsAvoidAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAvoidAllUsersTweetLabelRule, - NsfwCardImageAvoidAllUsersTweetLabelRule, - DoNotAmplifyTweetLabelAvoidRule, - NsfaHighPrecisionTweetLabelAvoidRule, - ) - ++ - LimitedEngagementBaseRules.tweetRules, - userRules = Seq( - ViewerMutesAuthorRule, - ViewerBlocksAuthorRule, - DeciderableAuthorBlocksViewerDropRule, - ProtectedAuthorDropRule, - SuspendedAuthorRule, - DeactivatedAuthorRule, - ErasedAuthorRule, - OffboardedAuthorRule, - DropTakendownUserRule - ), - policyRuleParams = SensitiveMediaSettingsTimelineHomeBaseRules.policyRuleParams - ) - -case object BaseTimelineHomePolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseQuotedTweetTombstoneRules ++ - VisibilityPolicy.baseTweetRules ++ - Seq( - NullcastedTweetRule, - DropOuterCommunityTweetsRule, - DynamicProductAdDropTweetLabelRule, - MutedRetweetsRule, - DropAllAuthorRemovedCommunityTweetsRule, - DropAllHiddenCommunityTweetsRule, - AbusePolicyEpisodicTweetLabelDropRule, - EmergencyDropRule, - SafetyCrisisLevel4DropRule, - ViewerHasMatchingMutedKeywordForHomeTimelineRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - NsfwHighPrecisionTweetLabelAvoidRule, - NsfwHighRecallTweetLabelAvoidRule, - GoreAndViolenceHighPrecisionAvoidAllUsersTweetLabelRule, - NsfwReportedHeuristicsAvoidAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAvoidAllUsersTweetLabelRule, - NsfwCardImageAvoidAllUsersTweetLabelRule, - DoNotAmplifyTweetLabelAvoidRule, - NsfaHighPrecisionTweetLabelAvoidRule, - ) - ++ - LimitedEngagementBaseRules.tweetRules, - userRules = Seq( - ViewerMutesAuthorRule, - ViewerBlocksAuthorRule, - DeciderableAuthorBlocksViewerDropRule, - ProtectedAuthorDropRule, - SuspendedAuthorRule, - DeactivatedAuthorRule, - ErasedAuthorRule, - OffboardedAuthorRule, - DropTakendownUserRule - ) - ) - -case object TimelineHomeHydrationPolicy - extends VisibilityPolicy( - tweetRules = - VisibilityPolicy.baseQuotedTweetTombstoneRules ++ - VisibilityPolicy.baseTweetRules ++ - Seq( - SensitiveMediaTweetDropRules.AdultMediaNsfwHighPrecisionTweetLabelDropRule, - SensitiveMediaTweetDropRules.ViolentMediaGoreAndViolenceHighPrecisionDropRule, - SensitiveMediaTweetDropRules.AdultMediaNsfwReportedHeuristicsTweetLabelDropRule, - SensitiveMediaTweetDropRules.ViolentMediaGoreAndViolenceReportedHeuristicsDropRule, - SensitiveMediaTweetDropRules.AdultMediaNsfwCardImageTweetLabelDropRule, - SensitiveMediaTweetDropRules.OtherSensitiveMediaNsfwUserTweetFlagDropRule, - SensitiveMediaTweetDropRules.OtherSensitiveMediaNsfwAdminTweetFlagDropRule, - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwHighPrecisionTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceHighPrecisionInterstitialRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwReportedHeuristicsTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceReportedHeuristicsInterstitialRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwCardImageTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwUserTweetFlagInterstitialRule, - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwAdminTweetFlagInterstitialRule, - NsfaHighPrecisionTweetLabelAvoidRule, - NsfwHighPrecisionTweetLabelAvoidRule, - NsfwHighRecallTweetLabelAvoidRule, - ) ++ LimitedEngagementBaseRules.tweetRules, - policyRuleParams = SensitiveMediaSettingsTimelineHomeBaseRules.policyRuleParams - ) - -case object TimelineHomeLatestPolicy - extends VisibilityPolicy( - tweetRules = - VisibilityPolicy.baseQuotedTweetTombstoneRules ++ - VisibilityPolicy.baseTweetRules ++ - Seq( - NullcastedTweetRule, - DropOuterCommunityTweetsRule, - DynamicProductAdDropTweetLabelRule, - MutedRetweetsRule, - ViewerHasMatchingMutedKeywordForHomeTimelineRule, - SensitiveMediaTweetDropRules.AdultMediaNsfwHighPrecisionTweetLabelDropRule, - SensitiveMediaTweetDropRules.ViolentMediaGoreAndViolenceHighPrecisionDropRule, - SensitiveMediaTweetDropRules.AdultMediaNsfwReportedHeuristicsTweetLabelDropRule, - SensitiveMediaTweetDropRules.ViolentMediaGoreAndViolenceReportedHeuristicsDropRule, - SensitiveMediaTweetDropRules.AdultMediaNsfwCardImageTweetLabelDropRule, - SensitiveMediaTweetDropRules.OtherSensitiveMediaNsfwUserTweetFlagDropRule, - SensitiveMediaTweetDropRules.OtherSensitiveMediaNsfwAdminTweetFlagDropRule, - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwHighPrecisionTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceHighPrecisionInterstitialRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwReportedHeuristicsTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceReportedHeuristicsInterstitialRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwCardImageTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwUserTweetFlagInterstitialRule, - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwAdminTweetFlagInterstitialRule, - NsfwHighPrecisionTweetLabelAvoidRule, - NsfwHighRecallTweetLabelAvoidRule, - GoreAndViolenceHighPrecisionAvoidAllUsersTweetLabelRule, - NsfwReportedHeuristicsAvoidAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAvoidAllUsersTweetLabelRule, - NsfwCardImageAvoidAllUsersTweetLabelRule, - DoNotAmplifyTweetLabelAvoidRule, - NsfaHighPrecisionTweetLabelAvoidRule, - ) - ++ - LimitedEngagementBaseRules.tweetRules, - userRules = Seq( - ViewerMutesAuthorRule, - ViewerBlocksAuthorRule, - DeciderableAuthorBlocksViewerDropRule, - ProtectedAuthorDropRule, - SuspendedAuthorRule, - DeactivatedAuthorRule, - ErasedAuthorRule, - OffboardedAuthorRule, - DropTakendownUserRule - ), - policyRuleParams = SensitiveMediaSettingsTimelineHomeBaseRules.policyRuleParams - ) - -case object TimelineModeratedTweetsHydrationPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ - Seq( - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - ) ++ LimitedEngagementBaseRules.tweetRules - ) - -case object SignalsReactionsPolicy - extends VisibilityPolicy( - tweetRules = Seq( - AuthorBlocksViewerDropRule - ) ++ LimitedEngagementBaseRules.tweetRules - ) - -case object SignalsTweetReactingUsersPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules :+ - NsfwVideoTweetLabelDropRule :+ - NsfwTextAllUsersTweetLabelDropRule, - userRules = Seq( - CompromisedNonFollowerWithUqfRule, - EngagementSpammerNonFollowerWithUqfRule, - LowQualityNonFollowerWithUqfRule, - ReadOnlyNonFollowerWithUqfRule, - SpamHighRecallNonFollowerWithUqfRule, - AuthorBlocksViewerDropRule, - ProtectedAuthorDropRule, - SuspendedAuthorRule, - NsfwTextNonAuthorDropRule - ) - ) - -case object SocialProofPolicy - extends VisibilityPolicy( - tweetRules = FilterDefaultPolicy.tweetRules, - userRules = Seq( - ProtectedAuthorDropRule, - SuspendedAuthorRule, - AuthorBlocksViewerDropRule, - ViewerBlocksAuthorRule - ) - ) - -case object TimelineLikedByPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules :+ - NsfwVideoTweetLabelDropRule :+ - NsfwTextAllUsersTweetLabelDropRule, - userRules = TimelineLikedByRules.UserRules :+ NsfwTextNonAuthorDropRule - ) - -case object TimelineRetweetedByPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules :+ - NsfwVideoTweetLabelDropRule :+ - NsfwTextAllUsersTweetLabelDropRule, - userRules = Seq( - CompromisedNonFollowerWithUqfRule, - EngagementSpammerNonFollowerWithUqfRule, - LowQualityNonFollowerWithUqfRule, - ReadOnlyNonFollowerWithUqfRule, - SpamHighRecallNonFollowerWithUqfRule, - NsfwTextNonAuthorDropRule - ) - ) - -case object TimelineSuperLikedByPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules :+ - NsfwVideoTweetLabelDropRule :+ - NsfwTextAllUsersTweetLabelDropRule, - userRules = Seq( - CompromisedNonFollowerWithUqfRule, - EngagementSpammerNonFollowerWithUqfRule, - LowQualityNonFollowerWithUqfRule, - ReadOnlyNonFollowerWithUqfRule, - SpamHighRecallNonFollowerWithUqfRule, - NsfwTextNonAuthorDropRule - ) - ) - -case object TimelineContentControlsPolicy - extends VisibilityPolicy( - tweetRules = TopicsLandingPageTopicRecommendationsPolicy.tweetRules, - userRules = TopicsLandingPageTopicRecommendationsPolicy.userRules - ) - -case object TimelineConversationsPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ - Seq( - AbusiveNonFollowerTweetLabelRule, - LowQualityTweetLabelDropRule, - SpamHighRecallTweetLabelDropRule, - DuplicateContentTweetLabelDropRule, - BystanderAbusiveNonFollowerTweetLabelRule, - UntrustedUrlAllViewersTweetLabelRule, - DownrankSpamReplyAllViewersTweetLabelRule, - SmyteSpamTweetLabelDropRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.AdultMediaNsfwHighPrecisionTweetLabelDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.ViolentMediaGoreAndViolenceHighPrecisionDropSettingLeveTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.AdultMediaNsfwReportedHeuristicsTweetLabelDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.ViolentMediaGoreAndViolenceReportedHeuristicsDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.AdultMediaNsfwCardImageTweetLabelDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.OtherSensitiveMediaNsfwUserTweetFlagDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.OtherSensitiveMediaNsfwAdminTweetFlagDropSettingLevelTombstoneRule, - MutedKeywordForTweetRepliesInterstitialRule, - ReportedTweetInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwHighPrecisionTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceHighPrecisionInterstitialRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwReportedHeuristicsTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceReportedHeuristicsInterstitialRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwCardImageTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwUserTweetFlagInterstitialRule, - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwAdminTweetFlagInterstitialRule, - AbusiveHighRecallNonFollowerTweetLabelRule, - ) ++ LimitedEngagementBaseRules.tweetRules, - userRules = Seq( - AbusiveRule, - LowQualityRule, - ReadOnlyRule, - LowQualityHighRecallRule, - CompromisedRule, - SpamHighRecallRule, - AbusiveHighRecallRule, - DownrankSpamReplyAllViewersRule, - ), - policyRuleParams = SensitiveMediaSettingsConversationBaseRules.policyRuleParams - ) - -case object TimelineFollowingActivityPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ - Seq( - AbusiveTweetLabelRule, - BystanderAbusiveTweetLabelRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - ) ++ LimitedEngagementBaseRules.tweetRules - ) - -case object TimelineInjectionPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ Seq( - NsfwHighPrecisionTweetLabelRule, - GoreAndViolenceHighPrecisionTweetLabelRule, - NsfwReportedHeuristicsTweetLabelRule, - GoreAndViolenceReportedHeuristicsTweetLabelRule, - NsfwCardImageTweetLabelRule, - NsfwHighRecallTweetLabelRule, - NsfwVideoTweetLabelDropRule, - NsfwTextTweetLabelDropRule, - SafetyCrisisLevel2DropRule, - SafetyCrisisLevel3DropRule, - SafetyCrisisLevel4DropRule, - DoNotAmplifyDropRule, - HighProactiveTosScoreTweetLabelDropRule - ), - userRules = Seq( - DoNotAmplifyNonFollowerRule, - NotGraduatedNonFollowerRule, - LikelyIvsLabelNonFollowerDropUserRule, - NsfwTextNonAuthorDropRule - ) - ) - -case object TimelineMentionsPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ - Seq( - LowQualityTweetLabelDropRule, - SpamHighRecallTweetLabelDropRule, - DuplicateContentTweetLabelDropRule, - DuplicateMentionUqfTweetLabelRule, - LowQualityMentionTweetLabelRule, - SmyteSpamTweetLabelDropRule, - ToxicityReplyFilterDropNotificationRule, - AbusiveUqfNonFollowerTweetLabelRule, - UntrustedUrlUqfNonFollowerTweetLabelRule, - DownrankSpamReplyUqfNonFollowerTweetLabelRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - ) ++ LimitedEngagementBaseRules.tweetRules, - userRules = Seq( - AbusiveRule, - LowQualityRule, - ReadOnlyRule, - CompromisedRule, - SpamHighRecallRule, - DuplicateContentRule, - AbusiveHighRecallRule, - EngagementSpammerNonFollowerWithUqfRule, - EngagementSpammerHighRecallNonFollowerWithUqfRule, - DownrankSpamReplyNonFollowerWithUqfRule - ) - ) - -case object TweetEngagersPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules, - userRules = Seq( - CompromisedNonFollowerWithUqfRule, - EngagementSpammerNonFollowerWithUqfRule, - LowQualityNonFollowerWithUqfRule, - ReadOnlyNonFollowerWithUqfRule, - SpamHighRecallNonFollowerWithUqfRule - ) - ) - -case object TweetWritesApiPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ Seq( - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - ) ++ LimitedEngagementBaseRules.tweetRules - ) - -case object QuotedTweetRulesPolicy - extends VisibilityPolicy( - quotedTweetRules = Seq( - DeactivatedAuthorRule, - ErasedAuthorRule, - OffboardedAuthorRule, - SuspendedAuthorRule, - AuthorBlocksOuterAuthorRule, - ViewerBlocksAuthorRule, - AuthorBlocksViewerDropRule, - ViewerMutesAndDoesNotFollowAuthorRule, - ProtectedQuoteTweetAuthorRule - ) - ) - -case object TweetDetailPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ - Seq( - AuthorBlocksViewerDropRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.AdultMediaNsfwHighPrecisionTweetLabelDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.ViolentMediaGoreAndViolenceHighPrecisionDropSettingLeveTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.AdultMediaNsfwReportedHeuristicsTweetLabelDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.ViolentMediaGoreAndViolenceReportedHeuristicsDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.AdultMediaNsfwCardImageTweetLabelDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.OtherSensitiveMediaNsfwUserTweetFlagDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.OtherSensitiveMediaNsfwAdminTweetFlagDropSettingLevelTombstoneRule, - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwHighPrecisionTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceHighPrecisionInterstitialRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwReportedHeuristicsTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceReportedHeuristicsInterstitialRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwCardImageTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwUserTweetFlagInterstitialRule, - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwAdminTweetFlagInterstitialRule, - NsfwHighPrecisionTweetLabelAvoidRule, - NsfwHighRecallTweetLabelAvoidRule, - GoreAndViolenceHighPrecisionAvoidAllUsersTweetLabelRule, - NsfwReportedHeuristicsAvoidAdPlacementAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAvoidAdPlacementAllUsersTweetLabelRule, - NsfwCardImageAvoidAdPlacementAllUsersTweetLabelRule, - DoNotAmplifyTweetLabelAvoidRule, - NsfaHighPrecisionTweetLabelAvoidRule, - MutedKeywordForQuotedTweetTweetDetailInterstitialRule, - ) - ++ LimitedEngagementBaseRules.tweetRules, - policyRuleParams = SensitiveMediaSettingsTweetDetailBaseRules.policyRuleParams - ) - -case object BaseTweetDetailPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ - Seq( - AuthorBlocksViewerDropRule, - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - NsfwHighPrecisionTweetLabelAvoidRule, - NsfwHighRecallTweetLabelAvoidRule, - GoreAndViolenceHighPrecisionAvoidAllUsersTweetLabelRule, - NsfwReportedHeuristicsAvoidAdPlacementAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAvoidAdPlacementAllUsersTweetLabelRule, - NsfwCardImageAvoidAdPlacementAllUsersTweetLabelRule, - DoNotAmplifyTweetLabelAvoidRule, - NsfaHighPrecisionTweetLabelAvoidRule, - MutedKeywordForQuotedTweetTweetDetailInterstitialRule, - ) - ++ LimitedEngagementBaseRules.tweetRules - ) - -case object TweetDetailWithInjectionsHydrationPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ - Seq( - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - MutedKeywordForQuotedTweetTweetDetailInterstitialRule, - ReportedTweetInterstitialRule, - ) ++ LimitedEngagementBaseRules.tweetRules, - userRules = UserTimelineRules.UserRules - ) - -case object TweetDetailNonTooPolicy - extends VisibilityPolicy( - tweetRules = Seq( - DropAllExclusiveTweetsRule, - DropAllTrustedFriendsTweetsRule, - ) ++ BaseTweetDetailPolicy.tweetRules - ) - -case object RecosWritePathPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ Seq( - AbusiveTweetLabelRule, - LowQualityTweetLabelDropRule, - NsfwHighPrecisionTweetLabelRule, - GoreAndViolenceHighPrecisionTweetLabelRule, - NsfwReportedHeuristicsTweetLabelRule, - GoreAndViolenceReportedHeuristicsTweetLabelRule, - NsfwCardImageTweetLabelRule, - NsfwVideoTweetLabelDropRule, - NsfwTextTweetLabelDropRule, - SpamHighRecallTweetLabelDropRule, - DuplicateContentTweetLabelDropRule, - BystanderAbusiveTweetLabelRule, - SmyteSpamTweetLabelDropRule - ), - userRules = Seq(NsfwTextNonAuthorDropRule) - ) - -case object BrandSafetyPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ Seq( - NsfwVideoTweetLabelDropRule, - NsfwTextTweetLabelDropRule, - NsfaHighRecallTweetLabelInterstitialRule - ), - userRules = Seq(NsfwTextNonAuthorDropRule) - ) - -case object VideoAdsPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules - ) - -case object AppealsPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ - Seq( - NsfwCardImageAllUsersTweetLabelRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - ) - ) - -case object TimelineConversationsDownrankingPolicy - extends VisibilityPolicy( - tweetRules = Seq( - HighToxicityScoreDownrankAbusiveQualitySectionRule, - UntrustedUrlConversationsTweetLabelRule, - DownrankSpamReplyConversationsTweetLabelRule, - DownrankSpamReplyConversationsAuthorLabelRule, - HighProactiveTosScoreTweetLabelDownrankingRule, - SafetyCrisisLevel3SectionRule, - SafetyCrisisLevel4SectionRule, - DoNotAmplifySectionRule, - DoNotAmplifySectionUserRule, - NotGraduatedConversationsAuthorLabelRule, - HighSpammyTweetContentScoreConvoDownrankAbusiveQualityRule, - HighCryptospamScoreConvoDownrankAbusiveQualityRule, - CopypastaSpamAbusiveQualityTweetLabelRule, - HighToxicityScoreDownrankLowQualitySectionRule, - HighPSpammyTweetScoreDownrankLowQualitySectionRule, - RitoActionedTweetDownrankLowQualitySectionRule, - HighToxicityScoreDownrankHighQualitySectionRule, - ) - ) - -case object TimelineConversationsDownrankingMinimalPolicy - extends VisibilityPolicy( - tweetRules = Seq( - HighProactiveTosScoreTweetLabelDownrankingRule - ) - ) - -case object TimelineHomeRecommendationsPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.union( - RecommendationsPolicy.tweetRules.filter( - _ != NsfwHighPrecisionTweetLabelRule - ), - Seq( - SafetyCrisisLevel2DropRule, - SafetyCrisisLevel3DropRule, - SafetyCrisisLevel4DropRule, - HighProactiveTosScoreTweetLabelDropRule, - NsfwHighRecallTweetLabelRule, - ), - BaseTimelineHomePolicy.tweetRules, - ), - userRules = VisibilityPolicy.union( - RecommendationsPolicy.userRules, - BaseTimelineHomePolicy.userRules - ) - ) - -case object TimelineHomeTopicFollowRecommendationsPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.union( - Seq( - SearchBlacklistTweetLabelRule, - GoreAndViolenceTopicHighRecallTweetLabelRule, - NsfwHighRecallTweetLabelRule, - ), - RecommendationsPolicy.tweetRules - .filterNot( - Seq( - NsfwHighPrecisionTweetLabelRule, - ).contains), - BaseTimelineHomePolicy.tweetRules - ), - userRules = VisibilityPolicy.union( - RecommendationsPolicy.userRules, - BaseTimelineHomePolicy.userRules - ) - ) - -case object TimelineScorerPolicy - extends VisibilityPolicy( - tweetRules = Seq( - AllowAllRule - ) - ) - -case object FollowedTopicsTimelinePolicy - extends VisibilityPolicy( - userRules = Seq( - AuthorBlocksViewerDropRule, - ProtectedAuthorDropRule, - SuspendedAuthorRule - ) - ) - -case object TopicsLandingPageTopicRecommendationsPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.union( - Seq( - SearchBlacklistTweetLabelRule, - GoreAndViolenceTopicHighRecallTweetLabelRule, - NsfwHighRecallTweetLabelRule - ), - RecommendationsPolicy.tweetRules, - BaseTimelineHomePolicy.tweetRules, - ), - userRules = VisibilityPolicy.union( - RecommendationsPolicy.userRules, - BaseTimelineHomePolicy.userRules - ) ++ Seq( - AuthorBlocksViewerDropRule - ) - ) - -case object ExploreRecommendationsPolicy - extends VisibilityPolicy( - tweetRules = Seq( - DropOuterCommunityTweetsRule, - SearchBlacklistTweetLabelRule, - GoreAndViolenceTopicHighRecallTweetLabelRule, - NsfwHighRecallTweetLabelRule, - DropTweetsWithGeoRestrictedMediaRule, - TweetNsfwUserDropRule, - TweetNsfwAdminDropRule, - ViewerHasMatchingMutedKeywordForHomeTimelineRule, - ViewerHasMatchingMutedKeywordForNotificationsRule, - ) ++ VisibilityPolicy.union( - RecommendationsPolicy.tweetRules - ), - userRules = VisibilityPolicy.union( - RecommendationsPolicy.userRules - ) ++ Seq( - AuthorBlocksViewerDropRule, - ViewerMutesAuthorRule, - ViewerBlocksAuthorRule - ) - ) - -case object TombstoningPolicy - extends VisibilityPolicy( - tweetRules = Seq( - TombstoneIf.ViewerIsBlockedByAuthor, - TombstoneIf.AuthorIsProtected, - TombstoneIf.ReplyIsModeratedByRootAuthor, - TombstoneIf.AuthorIsSuspended, - TombstoneIf.AuthorIsDeactivated, - InterstitialIf.ViewerHardMutedAuthor - ) - ) - -case object TweetReplyNudgePolicy - extends VisibilityPolicy( - tweetRules = Seq( - SpamAllUsersTweetLabelRule, - PdnaAllUsersTweetLabelRule, - BounceAllUsersTweetLabelRule, - TweetNsfwAdminDropRule, - TweetNsfwUserDropRule, - NsfwHighRecallAllUsersTweetLabelDropRule, - NsfwHighPrecisionAllUsersTweetLabelDropRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelDropRule, - NsfwReportedHeuristicsAllUsersTweetLabelDropRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelDropRule, - NsfwCardImageAllUsersTweetLabelDropRule, - NsfwVideoAllUsersTweetLabelDropRule, - NsfwTextAllUsersTweetLabelDropRule, - ), - userRules = Seq( - DropNsfwUserAuthorRule, - DropNsfwAdminAuthorRule, - NsfwTextAllUsersDropRule - ) - ) - -case object HumanizationNudgePolicy - extends VisibilityPolicy( - userRules = UserTimelineRules.UserRules - ) - -case object TrendsRepresentativeTweetPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.union( - RecommendationsPolicy.tweetRules, - Seq( - AbusiveHighRecallTweetLabelRule, - BystanderAbusiveTweetLabelRule, - DuplicateContentTweetLabelDropRule, - LowQualityTweetLabelDropRule, - HighProactiveTosScoreTweetLabelDropRule, - NsfaHighRecallTweetLabelRule, - NsfwCardImageAllUsersTweetLabelDropRule, - NsfwHighPrecisionTweetLabelRule, - NsfwHighRecallAllUsersTweetLabelDropRule, - NsfwVideoTweetLabelDropRule, - NsfwTextTweetLabelDropRule, - PdnaAllUsersTweetLabelRule, - SearchBlacklistTweetLabelRule, - SpamHighRecallTweetLabelDropRule, - UntrustedUrlAllViewersTweetLabelRule, - DownrankSpamReplyAllViewersTweetLabelRule, - HighPSpammyScoreAllViewerDropRule, - DoNotAmplifyAllViewersDropRule, - SmyteSpamTweetLabelDropRule, - AuthorBlocksViewerDropRule, - ViewerBlocksAuthorRule, - ViewerMutesAuthorRule, - CopypastaSpamAllViewersTweetLabelRule, - ) - ), - userRules = VisibilityPolicy.union( - RecommendationsPolicy.userRules, - Seq( - AbusiveRule, - LowQualityRule, - ReadOnlyRule, - CompromisedRule, - RecommendationsBlacklistRule, - SpamHighRecallRule, - DuplicateContentRule, - NsfwHighPrecisionRule, - NsfwNearPerfectAuthorRule, - NsfwBannerImageRule, - NsfwAvatarImageRule, - EngagementSpammerRule, - EngagementSpammerHighRecallRule, - AbusiveHighRecallRule, - SearchBlacklistRule, - SearchNsfwTextRule, - NsfwHighRecallRule, - TsViolationRule, - DownrankSpamReplyAllViewersRule, - NsfwTextNonAuthorDropRule - ) - ) - ) - -case object AdsCampaignPolicy - extends VisibilityPolicy( - userRules = Seq(SuspendedAuthorRule), - tweetRules = VisibilityPolicy.baseTweetRules - ) - -case object AdsManagerPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ Seq( - AdsManagerDenyListAllUsersTweetLabelRule, - ) - ) - -case object AdsReportingDashboardPolicy - extends VisibilityPolicy( - tweetRules = AdsManagerPolicy.tweetRules, - userRules = AdsCampaignPolicy.userRules - ) - -case object BirdwatchNoteAuthorPolicy - extends VisibilityPolicy( - userRules = Seq( - SuspendedAuthorRule, - AuthorBlocksViewerDropRule, - ViewerBlocksAuthorRule, - ViewerMutesAuthorRule - ) - ) - -case object BirdwatchNoteTweetsTimelinePolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ - Seq( - MutedRetweetsRule, - AuthorBlocksViewerDropRule, - ViewerMutesAuthorRule, - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - ) ++ LimitedEngagementBaseRules.tweetRules - ) - -case object BirdwatchNeedsYourHelpNotificationsPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ - Seq( - AuthorBlocksViewerDropRule, - ViewerBlocksAuthorRule, - ViewerMutesAuthorRule, - ViewerHasMatchingMutedKeywordForHomeTimelineRule, - ViewerHasMatchingMutedKeywordForNotificationsRule, - ) - ) - -case object ForDevelopmentOnlyPolicy - extends VisibilityPolicy( - userRules = Seq.empty, - tweetRules = VisibilityPolicy.baseTweetRules - ) - -case object UserProfileHeaderPolicy - extends VisibilityPolicy( - userRules = Seq.empty, - tweetRules = Seq(DropAllRule) - ) - -case object UserScopedTimelinePolicy - extends VisibilityPolicy( - userRules = UserTimelineRules.UserRules, - tweetRules = Seq(DropAllRule) - ) - -case object TweetScopedTimelinePolicy - extends VisibilityPolicy( - userRules = UserTimelineRules.UserRules, - tweetRules = Seq.empty - ) - -case object SoftInterventionPivotPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules - ) - -case object CuratedTrendsRepresentativeTweetPolicy - extends VisibilityPolicy( - userRules = Seq( - SuspendedAuthorRule, - AuthorBlocksViewerDropRule, - ViewerBlocksAuthorRule, - ViewerMutesAndDoesNotFollowAuthorRule - ) - ) - -case object CommunitiesPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ - Seq( - RetweetDropRule, - AbusePolicyEpisodicTweetLabelDropRule, - EmergencyDropRule, - SafetyCrisisLevel4DropRule, - ReportedTweetInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - ) ++ LimitedEngagementBaseRules.tweetRules - ) - -case object TimelineHomeCommunitiesPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.union( - Seq( - DropAllAuthorRemovedCommunityTweetsRule, - DropAllHiddenCommunityTweetsRule, - ViewerHasMatchingMutedKeywordForHomeTimelineRule, - ), - VisibilityPolicy.baseQuotedTweetTombstoneRules, - CommunitiesPolicy.tweetRules, - ), - userRules = Seq( - ViewerMutesAuthorRule, - ViewerBlocksAuthorRule, - ) - ) - -case object TimelineHomePromotedHydrationPolicy - extends VisibilityPolicy( - tweetRules = Seq( - ViewerHasMatchingMutedKeywordForHomeTimelinePromotedTweetRule, - ViewerMutesAuthorHomeTimelinePromotedTweetRule, - ViewerBlocksAuthorHomeTimelinePromotedTweetRule - ) ++ TimelineHomeHydrationPolicy.tweetRules, - policyRuleParams = TimelineHomeHydrationPolicy.policyRuleParams - ) - -case object SpacesPolicy - extends VisibilityPolicy( - SpaceDoNotAmplifyAllUsersDropRule, - SpaceNsfwHighPrecisionNonFollowerDropRule), - userRules = Seq( - AuthorBlocksViewerDropRule - ) - ) - -case object SpacesSellerApplicationStatusPolicy - extends VisibilityPolicy( - userRules = Seq( - ViewerIsNotAuthorDropRule - ) - ) - -case object SpacesParticipantsPolicy - extends VisibilityPolicy( - tweetRules = Seq(DropAllRule), - userRules = Seq( - AuthorBlocksViewerDropRule, - SuspendedAuthorRule - ) - ) - -case object SpacesSharingPolicy - extends VisibilityPolicy( - tweetRules = TweetDetailPolicy.tweetRules, - userRules = Seq( - AuthorBlocksViewerDropRule, - ProtectedAuthorDropRule, - SuspendedAuthorRule - ), - policyRuleParams = TweetDetailPolicy.policyRuleParams - ) - -case object SpaceFleetlinePolicy - extends VisibilityPolicy( - spaceRules = Seq( - SpaceDoNotAmplifyNonFollowerDropRule, - SpaceCoordHarmfulActivityHighRecallNonFollowerDropRule, - SpaceUntrustedUrlNonFollowerDropRule, - SpaceMisleadingHighRecallNonFollowerDropRule, - SpaceNsfwHighPrecisionAllUsersInterstitialRule - ), - userRules = Seq( - TsViolationRule, - DoNotAmplifyNonFollowerRule, - NotGraduatedNonFollowerRule, - LikelyIvsLabelNonFollowerDropUserRule, - UserAbusiveNonFollowerDropRule - ) - ) - -case object SpaceNotificationsPolicy - extends VisibilityPolicy( - spaceRules = Seq( - SpaceHatefulHighRecallAllUsersDropRule, - SpaceViolenceHighRecallAllUsersDropRule, - SpaceDoNotAmplifyAllUsersDropRule, - SpaceCoordHarmfulActivityHighRecallAllUsersDropRule, - SpaceUntrustedUrlNonFollowerDropRule, - SpaceMisleadingHighRecallNonFollowerDropRule, - SpaceNsfwHighPrecisionAllUsersDropRule, - SpaceNsfwHighRecallAllUsersDropRule, - ViewerHasMatchingMutedKeywordInSpaceTitleForNotificationsRule - ), - userRules = Seq( - ViewerMutesAuthorRule, - ViewerBlocksAuthorRule, - AuthorBlocksViewerDropRule, - TsViolationRule, - DoNotAmplifyUserRule, - AbusiveRule, - SearchBlacklistRule, - SearchNsfwTextRule, - RecommendationsBlacklistRule, - NotGraduatedRule, - SpamHighRecallRule, - AbusiveHighRecallRule, - UserBlinkWorstAllUsersDropRule, - UserNsfwNearPerfectNonFollowerDropRule, - SpaceNsfwHighPrecisionNonFollowerDropRule, - UserNsfwAvatarImageNonFollowerDropRule, - UserNsfwBannerImageNonFollowerDropRule - ) - ) - -case object SpaceTweetAvatarHomeTimelinePolicy - extends VisibilityPolicy( - spaceRules = Seq( - SpaceDoNotAmplifyNonFollowerDropRule, - SpaceCoordHarmfulActivityHighRecallNonFollowerDropRule, - SpaceUntrustedUrlNonFollowerDropRule, - SpaceMisleadingHighRecallNonFollowerDropRule, - SpaceNsfwHighPrecisionAllUsersDropRule, - SpaceNsfwHighPrecisionAllUsersInterstitialRule - ), - userRules = Seq( - TsViolationRule, - DoNotAmplifyUserRule, - NotGraduatedNonFollowerRule, - AbusiveRule, - SearchBlacklistRule, - SearchNsfwTextRule, - RecommendationsBlacklistRule, - SpamHighRecallRule, - AbusiveHighRecallRule, - UserBlinkWorstAllUsersDropRule, - UserNsfwNearPerfectNonFollowerDropRule, - SpaceNsfwHighPrecisionNonFollowerDropRule, - UserNsfwAvatarImageNonFollowerDropRule, - UserNsfwBannerImageNonFollowerDropRule - ) - ) - -case object SpaceHomeTimelineUprankingPolicy - extends VisibilityPolicy( - spaceRules = Seq( - SpaceDoNotAmplifyNonFollowerDropRule, - SpaceCoordHarmfulActivityHighRecallNonFollowerDropRule, - SpaceUntrustedUrlNonFollowerDropRule, - SpaceMisleadingHighRecallNonFollowerDropRule, - SpaceNsfwHighPrecisionNonFollowerDropRule, - SpaceNsfwHighPrecisionSafeSearchNonFollowerDropRule, - SpaceNsfwHighRecallSafeSearchNonFollowerDropRule - ), - userRules = Seq( - TsViolationRule, - DoNotAmplifyUserRule, - NotGraduatedRule, - AbusiveRule, - SearchBlacklistRule, - SearchNsfwTextRule, - RecommendationsBlacklistRule, - SpamHighRecallRule, - AbusiveHighRecallRule, - UserBlinkWorstAllUsersDropRule, - UserNsfwNearPerfectNonFollowerDropRule, - UserNsfwAvatarImageNonFollowerDropRule, - UserNsfwBannerImageNonFollowerDropRule - ) - ) - -case object SpaceJoinScreenPolicy - extends VisibilityPolicy( - spaceRules = Seq( - SpaceNsfwHighPrecisionAllUsersInterstitialRule - ) - ) - -case object KitchenSinkDevelopmentPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules.diff( - Seq( - BounceTweetLabelRule, - DropExclusiveTweetContentRule, - DropTrustedFriendsTweetContentRule - ) - ) ++ Seq( - BounceTweetLabelTombstoneRule, - TombstoneExclusiveTweetContentRule, - TombstoneTrustedFriendsTweetContentRule) - ++ Seq( - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - ViewerReportsAuthorInterstitialRule, - ViewerMutesAuthorInterstitialRule, - ViewerBlocksAuthorInterstitialRule, - MutedKeywordForTweetRepliesInterstitialRule, - ReportedTweetInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - ExperimentalNudgeLabelRule, - ) ++ LimitedEngagementBaseRules.tweetRules, - userRules = Seq( - AuthorBlocksViewerDropRule, - ProtectedAuthorTombstoneRule, - SuspendedAuthorRule - ), - userUnavailableStateRules = Seq( - SuspendedUserUnavailableRetweetTombstoneRule, - DeactivatedUserUnavailableRetweetTombstoneRule, - OffBoardedUserUnavailableRetweetTombstoneRule, - ErasedUserUnavailableRetweetTombstoneRule, - ProtectedUserUnavailableRetweetTombstoneRule, - AuthorBlocksViewerUserUnavailableRetweetTombstoneRule, - ViewerBlocksAuthorUserUnavailableRetweetTombstoneRule, - ViewerMutesAuthorUserUnavailableRetweetTombstoneRule, - SuspendedUserUnavailableInnerQuotedTweetTombstoneRule, - DeactivatedUserUnavailableInnerQuotedTweetTombstoneRule, - OffBoardedUserUnavailableInnerQuotedTweetTombstoneRule, - ErasedUserUnavailableInnerQuotedTweetTombstoneRule, - ProtectedUserUnavailableInnerQuotedTweetTombstoneRule, - AuthorBlocksViewerUserUnavailableInnerQuotedTweetTombstoneRule, - SuspendedUserUnavailableTweetTombstoneRule, - DeactivatedUserUnavailableTweetTombstoneRule, - OffBoardedUserUnavailableTweetTombstoneRule, - ErasedUserUnavailableTweetTombstoneRule, - ProtectedUserUnavailableTweetTombstoneRule, - AuthorBlocksViewerUserUnavailableTweetTombstoneRule, - ViewerBlocksAuthorUserUnavailableInnerQuotedTweetInterstitialRule, - ViewerMutesAuthorUserUnavailableInnerQuotedTweetInterstitialRule - ), - deletedTweetRules = Seq( - TombstoneDeletedOuterTweetRule, - TombstoneBounceDeletedOuterTweetRule, - TombstoneDeletedQuotedTweetRule, - TombstoneBounceDeletedQuotedTweetRule - ), - mediaRules = VisibilityPolicy.baseMediaRules - ) - -case object CurationPolicyViolationsPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ Seq( - DoNotAmplifyAllViewersDropRule, - ), - userRules = Seq( - DoNotAmplifyUserRule, - TsViolationRule - ) - ) - -case object GraphqlDefaultPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ - Seq( - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - ) ++ LimitedEngagementBaseRules.tweetRules - ) - -case object GryphonDecksAndColumnsSharingPolicy - extends VisibilityPolicy( - userRules = Seq( - AuthorBlocksViewerDropRule, - ProtectedAuthorDropRule, - SuspendedAuthorRule - ), - tweetRules = Seq(DropAllRule) - ) - -case object UserSettingsPolicy - extends VisibilityPolicy( - userRules = Seq(ViewerIsNotAuthorDropRule), - tweetRules = Seq(DropAllRule) - ) - -case object BlockMuteUsersTimelinePolicy - extends VisibilityPolicy( - userRules = Seq(SuspendedAuthorRule), - tweetRules = Seq(DropAllRule) - ) - -case object TopicRecommendationsPolicy - extends VisibilityPolicy( - tweetRules = - Seq( - NsfwHighRecallTweetLabelRule, - NsfwTextHighPrecisionTweetLabelDropRule - ) - ++ RecommendationsPolicy.tweetRules, - userRules = RecommendationsPolicy.userRules - ) - -case object RitoActionedTweetTimelinePolicy - extends VisibilityPolicy( - tweetRules = - VisibilityPolicy.baseTweetTombstoneRules - ++ Seq( - AuthorBlocksViewerTombstoneRule, - ProtectedAuthorTombstoneRule - ), - deletedTweetRules = Seq( - TombstoneDeletedOuterTweetRule, - TombstoneBounceDeletedOuterTweetRule, - TombstoneDeletedQuotedTweetRule, - TombstoneBounceDeletedQuotedTweetRule, - ), - ) - -case object EmbeddedTweetsPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetTombstoneRules - ++ Seq( - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - ) - ++ LimitedEngagementBaseRules.tweetRules, - deletedTweetRules = Seq( - TombstoneDeletedOuterTweetRule, - TombstoneBounceDeletedOuterTweetRule, - TombstoneDeletedQuotedTweetRule, - TombstoneBounceDeletedQuotedTweetRule, - ), - userUnavailableStateRules = Seq( - SuspendedUserUnavailableTweetTombstoneRule, - DeactivatedUserUnavailableTweetTombstoneRule, - OffBoardedUserUnavailableTweetTombstoneRule, - ErasedUserUnavailableTweetTombstoneRule, - ProtectedUserUnavailableTweetTombstoneRule, - AuthorBlocksViewerUserUnavailableInnerQuotedTweetTombstoneRule, - ) - ) - -case object EmbedTweetMarkupPolicy - extends VisibilityPolicy( - tweetRules = Seq(DropStaleTweetsRule) ++ - VisibilityPolicy.baseTweetTombstoneRules - ++ Seq( - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - ) - ++ LimitedEngagementBaseRules.tweetRules, - deletedTweetRules = Seq( - TombstoneDeletedOuterTweetRule, - TombstoneBounceDeletedOuterTweetRule, - TombstoneDeletedQuotedTweetRule, - TombstoneBounceDeletedQuotedTweetRule, - ), - ) - -case object ArticleTweetTimelinePolicy - extends VisibilityPolicy( - tweetRules = - VisibilityPolicy.baseTweetRules ++ - Seq( - ViewerHasMatchingMutedKeywordForHomeTimelineRule, - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - ) ++ LimitedEngagementBaseRules.tweetRules, - userRules = Seq( - AuthorBlocksViewerDropRule, - ViewerBlocksAuthorRule, - ViewerMutesAuthorRule, - ProtectedAuthorDropRule, - SuspendedAuthorRule - ) - ) - -case object ConversationFocalPrehydrationPolicy - extends VisibilityPolicy( - deletedTweetRules = Seq( - TombstoneBounceDeletedOuterTweetRule, - TombstoneBounceDeletedQuotedTweetRule, - ) - ) - -case object ConversationFocalTweetPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetTombstoneRules - ++ Seq( - DynamicProductAdDropTweetLabelRule, - AuthorBlocksViewerTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.AdultMediaNsfwHighPrecisionTweetLabelDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.ViolentMediaGoreAndViolenceHighPrecisionDropSettingLeveTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.AdultMediaNsfwReportedHeuristicsTweetLabelDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.ViolentMediaGoreAndViolenceReportedHeuristicsDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.AdultMediaNsfwCardImageTweetLabelDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.OtherSensitiveMediaNsfwUserTweetFlagDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.OtherSensitiveMediaNsfwAdminTweetFlagDropSettingLevelTombstoneRule, - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - ReportedTweetInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwHighPrecisionTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceHighPrecisionInterstitialRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwReportedHeuristicsTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceReportedHeuristicsInterstitialRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwCardImageTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwUserTweetFlagInterstitialRule, - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwAdminTweetFlagInterstitialRule, - GoreAndViolenceHighPrecisionAvoidAllUsersTweetLabelRule, - NsfwReportedHeuristicsAvoidAdPlacementAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAvoidAdPlacementAllUsersTweetLabelRule, - NsfwCardImageAvoidAdPlacementAllUsersTweetLabelRule, - MutedKeywordForQuotedTweetTweetDetailInterstitialRule, - ViewerMutesAuthorInnerQuotedTweetInterstitialRule, - ViewerBlocksAuthorInnerQuotedTweetInterstitialRule, - ) - ++ LimitedEngagementBaseRules.tweetRules - ++ ConversationsAdAvoidanceRules.tweetRules, - deletedTweetRules = Seq( - TombstoneBounceDeletedOuterTweetRule, - TombstoneDeletedQuotedTweetRule, - TombstoneBounceDeletedQuotedTweetRule, - ), - userUnavailableStateRules = Seq( - SuspendedUserUnavailableTweetTombstoneRule, - DeactivatedUserUnavailableTweetTombstoneRule, - OffBoardedUserUnavailableTweetTombstoneRule, - ErasedUserUnavailableTweetTombstoneRule, - ProtectedUserUnavailableTweetTombstoneRule, - AuthorBlocksViewerUserUnavailableInnerQuotedTweetTombstoneRule, - UserUnavailableTweetTombstoneRule, - ViewerBlocksAuthorUserUnavailableInnerQuotedTweetInterstitialRule, - ViewerMutesAuthorUserUnavailableInnerQuotedTweetInterstitialRule - ), - policyRuleParams = ConversationsAdAvoidanceRules.policyRuleParams - ++ SensitiveMediaSettingsConversationBaseRules.policyRuleParams - ) - -case object ConversationReplyPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetTombstoneRules - ++ Seq( - LowQualityTweetLabelTombstoneRule, - SpamHighRecallTweetLabelTombstoneRule, - DuplicateContentTweetLabelTombstoneRule, - DeciderableSpamHighRecallAuthorLabelTombstoneRule, - SmyteSpamTweetLabelTombstoneRule, - AuthorBlocksViewerTombstoneRule, - ToxicityReplyFilterRule, - DynamicProductAdDropTweetLabelRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.AdultMediaNsfwHighPrecisionTweetLabelDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.ViolentMediaGoreAndViolenceHighPrecisionDropSettingLeveTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.AdultMediaNsfwReportedHeuristicsTweetLabelDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.ViolentMediaGoreAndViolenceReportedHeuristicsDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.AdultMediaNsfwCardImageTweetLabelDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.OtherSensitiveMediaNsfwUserTweetFlagDropSettingLevelTombstoneRule, - SensitiveMediaTweetDropSettingLevelTombstoneRules.OtherSensitiveMediaNsfwAdminTweetFlagDropSettingLevelTombstoneRule, - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - MutedKeywordForTweetRepliesInterstitialRule, - ReportedTweetInterstitialRule, - ViewerBlocksAuthorInterstitialRule, - ViewerMutesAuthorInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwHighPrecisionTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceHighPrecisionInterstitialRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwReportedHeuristicsTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.ViolentMediaGoreAndViolenceReportedHeuristicsInterstitialRule, - SensitiveMediaTweetInterstitialRules.AdultMediaNsfwCardImageTweetLabelInterstitialRule, - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwUserTweetFlagInterstitialRule, - SensitiveMediaTweetInterstitialRules.OtherSensitiveMediaNsfwAdminTweetFlagInterstitialRule, - GoreAndViolenceHighPrecisionAvoidAllUsersTweetLabelRule, - NsfwReportedHeuristicsAvoidAdPlacementAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAvoidAdPlacementAllUsersTweetLabelRule, - NsfwCardImageAvoidAdPlacementAllUsersTweetLabelRule, - ) - ++ LimitedEngagementBaseRules.tweetRules - ++ ConversationsAdAvoidanceRules.tweetRules, - userRules = Seq( - LowQualityRule, - ReadOnlyRule, - LowQualityHighRecallRule, - CompromisedRule, - DeciderableSpamHighRecallRule - ), - deletedTweetRules = Seq( - TombstoneDeletedOuterTweetRule, - TombstoneBounceDeletedOuterTweetRule, - TombstoneDeletedQuotedTweetRule, - TombstoneBounceDeletedQuotedTweetRule, - ), - userUnavailableStateRules = Seq( - SuspendedUserUnavailableTweetTombstoneRule, - DeactivatedUserUnavailableTweetTombstoneRule, - OffBoardedUserUnavailableTweetTombstoneRule, - ErasedUserUnavailableTweetTombstoneRule, - ProtectedUserUnavailableTweetTombstoneRule, - AuthorBlocksViewerUserUnavailableInnerQuotedTweetTombstoneRule, - UserUnavailableTweetTombstoneRule, - ViewerBlocksAuthorUserUnavailableInnerQuotedTweetInterstitialRule, - ViewerMutesAuthorUserUnavailableInnerQuotedTweetInterstitialRule - ), - policyRuleParams = ConversationsAdAvoidanceRules.policyRuleParams - ++ SensitiveMediaSettingsConversationBaseRules.policyRuleParams - ) - -case object AdsBusinessSettingsPolicy - extends VisibilityPolicy( - tweetRules = Seq(DropAllRule) - ) - -case object UserMilestoneRecommendationPolicy - extends VisibilityPolicy( - userRules = RecommendationsPolicy.userRules ++ Seq( - ) - ) - -case object TrustedFriendsUserListPolicy - extends VisibilityPolicy( - tweetRules = Seq(DropAllRule), - userRules = Seq( - ViewerBlocksAuthorRule - ) - ) - -case object TwitterDelegateUserListPolicy - extends VisibilityPolicy( - userRules = Seq( - ViewerBlocksAuthorRule, - ViewerIsAuthorDropRule, - DeactivatedAuthorRule, - AuthorBlocksViewerDropRule - ), - tweetRules = Seq(DropAllRule) - ) - -case object QuickPromoteTweetEligibilityPolicy - extends VisibilityPolicy( - tweetRules = TweetDetailPolicy.tweetRules, - userRules = UserTimelineRules.UserRules, - policyRuleParams = TweetDetailPolicy.policyRuleParams - ) - -case object ReportCenterPolicy - extends VisibilityPolicy( - tweetRules = ConversationFocalTweetPolicy.tweetRules.diff( - ConversationsAdAvoidanceRules.tweetRules - ), - deletedTweetRules = Seq( - TombstoneBounceDeletedOuterTweetRule, - TombstoneDeletedQuotedTweetRule, - TombstoneBounceDeletedQuotedTweetRule, - TombstoneDeletedOuterTweetRule, - ), - userUnavailableStateRules = Seq( - SuspendedUserUnavailableTweetTombstoneRule, - DeactivatedUserUnavailableTweetTombstoneRule, - OffBoardedUserUnavailableTweetTombstoneRule, - ErasedUserUnavailableTweetTombstoneRule, - ProtectedUserUnavailableTweetTombstoneRule, - AuthorBlocksViewerUserUnavailableInnerQuotedTweetTombstoneRule, - UserUnavailableTweetTombstoneRule, - ViewerBlocksAuthorUserUnavailableInnerQuotedTweetInterstitialRule, - ViewerMutesAuthorUserUnavailableInnerQuotedTweetInterstitialRule - ), - policyRuleParams = ConversationFocalTweetPolicy.policyRuleParams - ) - -case object ConversationInjectedTweetPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetRules ++ - Seq( - AbusePolicyEpisodicTweetLabelInterstitialRule, - EmergencyDynamicInterstitialRule, - NsfwHighPrecisionInterstitialAllUsersTweetLabelRule, - GoreAndViolenceHighPrecisionAllUsersTweetLabelRule, - NsfwReportedHeuristicsAllUsersTweetLabelRule, - GoreAndViolenceReportedHeuristicsAllUsersTweetLabelRule, - NsfwCardImageAllUsersTweetLabelRule, - ) ++ - LimitedEngagementBaseRules.tweetRules ++ Seq( - SkipTweetDetailLimitedEngagementTweetLabelRule - ) - ) - -case object EditHistoryTimelinePolicy - extends VisibilityPolicy( - tweetRules = ConversationReplyPolicy.tweetRules, - policyRuleParams = ConversationReplyPolicy.policyRuleParams, - deletedTweetRules = ConversationReplyPolicy.deletedTweetRules, - userUnavailableStateRules = ConversationReplyPolicy.userUnavailableStateRules) - -case object UserSelfViewOnlyPolicy - extends VisibilityPolicy( - userRules = Seq(ViewerIsNotAuthorDropRule), - tweetRules = Seq(DropAllRule) - ) - -case object TwitterArticleComposePolicy - extends VisibilityPolicy( - twitterArticleRules = Seq( - ViewerIsNotAuthorDropRule - ) - ) - -case object TwitterArticleProfileTabPolicy - extends VisibilityPolicy( - twitterArticleRules = Seq( - AuthorBlocksViewerDropRule - ) - ) - -case object TwitterArticleReadPolicy - extends VisibilityPolicy( - twitterArticleRules = Seq( - AuthorBlocksViewerDropRule, - ) - ) - -case object ContentControlToolInstallPolicy - extends VisibilityPolicy( - userRules = UserProfileHeaderPolicy.userRules, - tweetRules = UserProfileHeaderPolicy.tweetRules - ) - -case object TimelineProfileSpacesPolicy - extends VisibilityPolicy( - userRules = UserProfileHeaderPolicy.userRules, - tweetRules = UserProfileHeaderPolicy.tweetRules - ) - -case object TimelineFavoritesSelfViewPolicy - extends VisibilityPolicy( - tweetRules = TimelineFavoritesPolicy.tweetRules.diff(Seq(DropStaleTweetsRule)), - policyRuleParams = TimelineFavoritesPolicy.policyRuleParams, - deletedTweetRules = TimelineFavoritesPolicy.deletedTweetRules, - userUnavailableStateRules = TimelineFavoritesPolicy.userUnavailableStateRules - ) - -case object BaseQigPolicy - extends VisibilityPolicy( - tweetRules = Seq( - AbusePolicyEpisodicTweetLabelDropRule, - AutomationTweetLabelRule, - DoNotAmplifyDropRule, - DownrankSpamReplyTweetLabelRule, - DuplicateContentTweetLabelDropRule, - DuplicateMentionTweetLabelRule, - NsfwHighPrecisionTweetLabelRule, - GoreAndViolenceHighPrecisionTweetLabelRule, - GoreAndViolenceReportedHeuristicsTweetLabelRule, - LikelyIvsLabelNonFollowerDropUserRule, - NsfwCardImageTweetLabelRule, - NsfwHighRecallTweetLabelRule, - NsfwReportedHeuristicsTweetLabelRule, - NsfwTextTweetLabelDropRule, - NsfwVideoTweetLabelDropRule, - PdnaTweetLabelRule, - SafetyCrisisLevel3DropRule, - SafetyCrisisLevel4DropRule, - SearchBlacklistHighRecallTweetLabelDropRule, - SearchBlacklistTweetLabelRule, - SmyteSpamTweetLabelDropRule, - SpamHighRecallTweetLabelDropRule, - ), - userRules = Seq( - DuplicateContentRule, - EngagementSpammerHighRecallRule, - EngagementSpammerRule, - NsfwAvatarImageRule, - NsfwBannerImageRule, - NsfwHighPrecisionRule, - NsfwHighRecallRule, - NsfwSensitiveRule, - ReadOnlyRule, - RecommendationsBlacklistRule, - SearchBlacklistRule, - SpamHighRecallRule - )) - -case object NotificationsQigPolicy - extends VisibilityPolicy( - tweetRules = BaseQigPolicy.tweetRules ++ Seq( - DropAllCommunityTweetsRule, - DropNsfwAdminAuthorViewerOptInFilteringOnSearchRule, - HighProactiveTosScoreTweetLabelDropSearchRule, - LowQualityTweetLabelDropRule, - NsfwHighPrecisionRule, - NsfwHighRecallRule, - NsfwNearPerfectAuthorRule, - NsfwSensitiveRule, - ), - userRules = BaseQigPolicy.userRules ++ Seq( - AbusiveRule, - LowQualityRule, - CompromisedRule, - ViewerBlocksAuthorViewerOptInBlockingOnSearchRule, - ViewerMutesAuthorViewerOptInBlockingOnSearchRule, - DropNsfwAdminAuthorViewerOptInFilteringOnSearchRule, - NsfwNearPerfectAuthorRule - ) - ) - -case object ShoppingManagerSpyModePolicy - extends VisibilityPolicy( - tweetRules = Seq( - DropAllRule - ), - userRules = Seq( - SuspendedAuthorRule, - DeactivatedAuthorRule, - ErasedAuthorRule, - OffboardedAuthorRule - ) - ) - -case object ZipbirdConsumerArchivesPolicy - extends VisibilityPolicy( - tweetRules = VisibilityPolicy.baseTweetTombstoneRules, - userRules = Seq( - AuthorBlocksViewerDropRule, - ProtectedAuthorDropRule, - SuspendedAuthorRule, - ), - userUnavailableStateRules = Seq( - AuthorBlocksViewerUserUnavailableTweetTombstoneRule, - ProtectedUserUnavailableTweetTombstoneRule, - SuspendedUserUnavailableTweetTombstoneRule, - ), - deletedTweetRules = Seq( - TombstoneDeletedTweetRule, - TombstoneBounceDeletedTweetRule, - ) - ) - -case class MixedVisibilityPolicy( - originalPolicy: VisibilityPolicy, - additionalTweetRules: Seq[Rule]) - extends VisibilityPolicy( - tweetRules = (additionalTweetRules ++ originalPolicy.tweetRules) - .sortWith(_.actionBuilder.actionSeverity > _.actionBuilder.actionSeverity), - userRules = originalPolicy.userRules, - cardRules = originalPolicy.cardRules, - quotedTweetRules = originalPolicy.quotedTweetRules, - dmRules = originalPolicy.dmRules, - dmConversationRules = originalPolicy.dmConversationRules, - dmEventRules = originalPolicy.dmEventRules, - spaceRules = originalPolicy.spaceRules, - userUnavailableStateRules = originalPolicy.userUnavailableStateRules, - twitterArticleRules = originalPolicy.twitterArticleRules, - deletedTweetRules = originalPolicy.deletedTweetRules, - mediaRules = originalPolicy.mediaRules, - communityRules = originalPolicy.communityRules, - policyRuleParams = originalPolicy.policyRuleParams - ) - -case object TweetAwardPolicy - extends VisibilityPolicy( - userRules = Seq.empty, - tweetRules = - VisibilityPolicy.baseTweetRules ++ Seq( - EmergencyDropRule, - NsfwHighPrecisionTweetLabelRule, - NsfwHighRecallTweetLabelRule, - NsfwReportedHeuristicsTweetLabelRule, - NsfwCardImageTweetLabelRule, - NsfwVideoTweetLabelDropRule, - NsfwTextTweetLabelDropRule, - GoreAndViolenceHighPrecisionTweetLabelRule, - GoreAndViolenceReportedHeuristicsTweetLabelRule, - GoreAndViolenceTweetLabelRule, - AbusePolicyEpisodicTweetLabelDropRule, - AbusiveTweetLabelRule, - BystanderAbusiveTweetLabelRule - ) - ) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/generators/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/rules/generators/BUILD deleted file mode 100644 index 424c99ac4..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/generators/BUILD +++ /dev/null @@ -1,37 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/google/guava", - "3rdparty/jvm/com/squareup/okhttp:okhttp3", - "abdecider/src/main/scala", - "configapi/configapi-core", - "decider/src/main/scala", - "scribelib/marshallers/src/main/scala/com/twitter/scribelib/marshallers", - "servo/decider/src/main/scala", - "snowflake/src/main/scala/com/twitter/snowflake/id", - "src/scala/com/twitter/takedown/util", - "src/thrift/com/twitter/content-health/sensitivemediasettings:sensitivemediasettings-scala", - "src/thrift/com/twitter/gizmoduck:user-thrift-scala", - "src/thrift/com/twitter/search/common:constants-scala", - "src/thrift/com/twitter/spam/rtf:safety-level-scala", - "src/thrift/com/twitter/spam/rtf:safety-result-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "stitch/stitch-core/src/main/scala/com/twitter/stitch", - "visibility/common/src/main/scala/com/twitter/visibility/common/actions", - "visibility/common/src/main/scala/com/twitter/visibility/common/actions/converter/scala", - "visibility/common/src/main/thrift/com/twitter/visibility:action-scala", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/configs", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/params", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/models", - "visibility/lib/src/main/scala/com/twitter/visibility/rules", - "visibility/lib/src/main/scala/com/twitter/visibility/util", - "visibility/lib/src/main/thrift/com/twitter/visibility/logging:vf-logging-scala", - "visibility/lib/src/main/thrift/com/twitter/visibility/strato:vf-strato-scala", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/generators/RuleGenerator.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/generators/RuleGenerator.scala deleted file mode 100644 index 262134636..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/generators/RuleGenerator.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.visibility.rules.generators - -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.rules.Rule - -trait RuleGenerator { - def rulesForSurface(safetyLevel: SafetyLevel): Seq[Rule] -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/generators/TweetRuleGenerator.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/generators/TweetRuleGenerator.scala deleted file mode 100644 index 90db70006..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/generators/TweetRuleGenerator.scala +++ /dev/null @@ -1,273 +0,0 @@ -package com.twitter.visibility.rules.generators - -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.SafetyLevelGroup -import com.twitter.visibility.models.ViolationLevel -import com.twitter.visibility.rules.FreedomOfSpeechNotReachActions -import com.twitter.visibility.rules.FreedomOfSpeechNotReachRules -import com.twitter.visibility.rules.Rule -import com.twitter.visibility.rules.generators.TweetRuleGenerator.violationLevelPolicies - -object TweetRuleGenerator { - private val level3LimitedActions: Seq[String] = Seq( - "like", - "reply", - "retweet", - "quote_tweet", - "share_tweet_via", - "add_to_bookmarks", - "pin_to_profile", - "copy_link", - "send_via_dm") - private val violationLevelPolicies: Map[ - ViolationLevel, - Map[UserType, TweetVisibilityPolicy] - ] = Map( - ViolationLevel.Level1 -> Map( - UserType.Follower -> TweetVisibilityPolicy - .builder() - .addGlobalRule(FreedomOfSpeechNotReachActions.SoftInterventionAvoidAction()) - .addSafetyLevelGroupRule( - SafetyLevelGroup.Notifications, - FreedomOfSpeechNotReachActions.DropAction()) - .addSafetyLevelGroupRule( - SafetyLevelGroup.Recommendations, - FreedomOfSpeechNotReachActions.DropAction()) - .addSafetyLevelGroupRule( - SafetyLevelGroup.Search, - FreedomOfSpeechNotReachActions.DropAction()) - .addSafetyLevelGroupRule( - SafetyLevelGroup.TopicRecommendations, - FreedomOfSpeechNotReachActions.DropAction()) - .addSafetyLevelRule( - SafetyLevel.TimelineHomeRecommendations, - FreedomOfSpeechNotReachActions.DropAction()) - .addSafetyLevelRule( - SafetyLevel.TrendsRepresentativeTweet, - FreedomOfSpeechNotReachActions.DropAction()) - .build, - UserType.Author -> TweetVisibilityPolicy - .builder() - .addGlobalRule(FreedomOfSpeechNotReachActions.AppealableAction()) - .build, - UserType.Other -> TweetVisibilityPolicy - .builder() - .addGlobalRule(FreedomOfSpeechNotReachActions.SoftInterventionAvoidAction()) - .addSafetyLevelGroupRule( - SafetyLevelGroup.Notifications, - FreedomOfSpeechNotReachActions.DropAction()) - .addSafetyLevelGroupRule( - SafetyLevelGroup.Recommendations, - FreedomOfSpeechNotReachActions.DropAction()) - .addSafetyLevelGroupRule( - SafetyLevelGroup.TimelineHome, - FreedomOfSpeechNotReachActions.DropAction()) - .addSafetyLevelGroupRule( - SafetyLevelGroup.Search, - FreedomOfSpeechNotReachActions.DropAction()) - .addSafetyLevelGroupRule( - SafetyLevelGroup.TopicRecommendations, - FreedomOfSpeechNotReachActions.DropAction()) - .addSafetyLevelRule( - SafetyLevel.TrendsRepresentativeTweet, - FreedomOfSpeechNotReachActions.DropAction()) - .addSafetyLevelRule( - SafetyLevel.ConversationReply, - FreedomOfSpeechNotReachActions.SoftInterventionAvoidAbusiveQualityReplyAction()) - .build, - ), - ViolationLevel.Level3 -> Map( - UserType.Follower -> TweetVisibilityPolicy - .builder() - .addGlobalRule(FreedomOfSpeechNotReachActions.DropAction()) - .addSafetyLevelGroupRule( - SafetyLevelGroup.TimelineProfile, - FreedomOfSpeechNotReachActions.SoftInterventionAvoidLimitedEngagementsAction( - limitedActionStrings = Some(level3LimitedActions)) - ) - .addSafetyLevelGroupRule( - SafetyLevelGroup.TweetDetails, - FreedomOfSpeechNotReachActions.SoftInterventionAvoidLimitedEngagementsAction( - limitedActionStrings = Some(level3LimitedActions)) - ) - .addSafetyLevelRule( - SafetyLevel.ConversationReply, - FreedomOfSpeechNotReachActions.SoftInterventionAvoidLimitedEngagementsAction( - limitedActionStrings = Some(level3LimitedActions)) - ) - .addSafetyLevelRule( - SafetyLevel.ConversationFocalTweet, - FreedomOfSpeechNotReachActions.SoftInterventionAvoidLimitedEngagementsAction( - limitedActionStrings = Some(level3LimitedActions)) - ) - .build, - UserType.Author -> TweetVisibilityPolicy - .builder() - .addGlobalRule( - FreedomOfSpeechNotReachActions.AppealableAvoidLimitedEngagementsAction( - limitedActionStrings = Some(level3LimitedActions)) - ) - .build, - UserType.Other -> TweetVisibilityPolicy - .builder() - .addGlobalRule(FreedomOfSpeechNotReachActions.DropAction()) - .addSafetyLevelGroupRule( - SafetyLevelGroup.TimelineProfile, - FreedomOfSpeechNotReachActions - .InterstitialLimitedEngagementsAvoidAction(limitedActionStrings = - Some(level3LimitedActions)) - ) - .addSafetyLevelGroupRule( - SafetyLevelGroup.TweetDetails, - FreedomOfSpeechNotReachActions - .InterstitialLimitedEngagementsAvoidAction(limitedActionStrings = - Some(level3LimitedActions)) - ) - .addSafetyLevelRule( - SafetyLevel.ConversationReply, - FreedomOfSpeechNotReachActions - .InterstitialLimitedEngagementsAvoidAction(limitedActionStrings = - Some(level3LimitedActions)) - ) - .addSafetyLevelRule( - SafetyLevel.ConversationFocalTweet, - FreedomOfSpeechNotReachActions - .InterstitialLimitedEngagementsAvoidAction(limitedActionStrings = - Some(level3LimitedActions)) - ) - .build, - ), - ) -} -sealed trait UserType -object UserType { - case object Author extends UserType - - case object Follower extends UserType - - case object Other extends UserType -} -class TweetRuleGenerator extends RuleGenerator { - - private[rules] val tweetRulesForSurface: Map[SafetyLevel, Seq[Rule]] = generateTweetPolicies() - - private[rules] def getViolationLevelPolicies = violationLevelPolicies - - override def rulesForSurface(safetyLevel: SafetyLevel): Seq[Rule] = - tweetRulesForSurface.getOrElse(safetyLevel, Seq()) - - private def generateRulesForPolicy( - violationLevel: ViolationLevel, - userType: UserType, - tweetVisibilityPolicy: TweetVisibilityPolicy - ): Seq[(SafetyLevel, Rule)] = { - tweetVisibilityPolicy - .getRules() - .map { - case (safetyLevel, actionBuilder) => - safetyLevel -> (userType match { - case UserType.Author => - FreedomOfSpeechNotReachRules.ViewerIsAuthorAndTweetHasViolationOfLevel( - violationLevel = violationLevel, - actionBuilder = actionBuilder.withViolationLevel(violationLevel = violationLevel)) - case UserType.Follower => - FreedomOfSpeechNotReachRules.ViewerIsFollowerAndTweetHasViolationOfLevel( - violationLevel = violationLevel, - actionBuilder = actionBuilder.withViolationLevel(violationLevel = violationLevel)) - case UserType.Other => - FreedomOfSpeechNotReachRules.ViewerIsNonFollowerNonAuthorAndTweetHasViolationOfLevel( - violationLevel = violationLevel, - actionBuilder = actionBuilder.withViolationLevel(violationLevel = violationLevel)) - }) - }.toSeq - } - - private def generatePoliciesForViolationLevel( - violationLevel: ViolationLevel - ): Seq[(SafetyLevel, Rule)] = { - getViolationLevelPolicies - .get(violationLevel).map { policiesPerUserType => - Seq(UserType.Author, UserType.Follower, UserType.Other).foldLeft( - List.empty[(UserType, SafetyLevel, Rule)]) { - case (rulesForAllUserTypes, userType) => - rulesForAllUserTypes ++ generateRulesForPolicy( - violationLevel = violationLevel, - userType = userType, - tweetVisibilityPolicy = policiesPerUserType(userType)).map { - case (safetyLevel, rule) => (userType, safetyLevel, rule) - } - } - } - .map(policy => optimizePolicy(policy = policy, violationLevel = violationLevel)) - .getOrElse(List()) - } - - private def injectFallbackRule(rules: Seq[Rule]): Seq[Rule] = { - rules :+ FreedomOfSpeechNotReachRules.TweetHasViolationOfAnyLevelFallbackDropRule - } - - private def optimizePolicy( - policy: Seq[(UserType, SafetyLevel, Rule)], - violationLevel: ViolationLevel - ): Seq[(SafetyLevel, Rule)] = { - val policiesByUserType = policy.groupBy { case (userType, _, _) => userType }.map { - case (userType, aggregated) => - (userType, aggregated.map { case (_, safetyLevel, rules) => (safetyLevel, rules) }) - } - val followerPolicies = aggregateRulesBySafetyLevel( - policiesByUserType.getOrElse(UserType.Follower, Seq())) - val otherPolicies = aggregateRulesBySafetyLevel( - policiesByUserType.getOrElse(UserType.Other, Seq())) - policiesByUserType(UserType.Author) ++ - followerPolicies.collect { - case (safetyLevel, rule) if !otherPolicies.contains(safetyLevel) => - (safetyLevel, rule) - } ++ - otherPolicies.collect { - case (safetyLevel, rule) if !followerPolicies.contains(safetyLevel) => - (safetyLevel, rule) - } ++ - followerPolicies.keySet - .intersect(otherPolicies.keySet).foldLeft(List.empty[(SafetyLevel, Rule)]) { - case (aggr, safetyLevel) - if followerPolicies(safetyLevel).actionBuilder == otherPolicies( - safetyLevel).actionBuilder => - ( - safetyLevel, - FreedomOfSpeechNotReachRules.ViewerIsNonAuthorAndTweetHasViolationOfLevel( - violationLevel = violationLevel, - actionBuilder = followerPolicies(safetyLevel).actionBuilder - )) :: aggr - case (aggr, safetyLevel) => - (safetyLevel, followerPolicies(safetyLevel)) :: - (safetyLevel, otherPolicies(safetyLevel)) :: aggr - } - } - - private def aggregateRulesBySafetyLevel( - policy: Seq[(SafetyLevel, Rule)] - ): Map[SafetyLevel, Rule] = { - policy - .groupBy { - case (safetyLevel, _) => safetyLevel - }.map { - case (safetyLevel, Seq((_, rule))) => - (safetyLevel, rule) - case _ => throw new Exception("Policy optimization failure") - } - } - - private def generateTweetPolicies(): Map[SafetyLevel, Seq[Rule]] = { - Seq(ViolationLevel.Level4, ViolationLevel.Level3, ViolationLevel.Level2, ViolationLevel.Level1) - .foldLeft(List.empty[(SafetyLevel, Rule)]) { - case (rulesForAllViolationLevels, violationLevel) => - rulesForAllViolationLevels ++ - generatePoliciesForViolationLevel(violationLevel) - } - .groupBy { case (safetyLevel, _) => safetyLevel } - .map { - case (safetyLevel, list) => - (safetyLevel, injectFallbackRule(list.map { case (_, rule) => rule })) - } - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/generators/TweetVisibilityPolicy.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/generators/TweetVisibilityPolicy.scala deleted file mode 100644 index 1b9de7a1c..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/generators/TweetVisibilityPolicy.scala +++ /dev/null @@ -1,74 +0,0 @@ -package com.twitter.visibility.rules.generators - -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.models.SafetyLevelGroup -import com.twitter.visibility.rules.Action -import com.twitter.visibility.rules.FreedomOfSpeechNotReachActions.FreedomOfSpeechNotReachActionBuilder - -class TweetVisibilityPolicy( - rules: Map[SafetyLevel, FreedomOfSpeechNotReachActionBuilder[_ <: Action]] = Map()) { - def getRules(): Map[SafetyLevel, FreedomOfSpeechNotReachActionBuilder[_ <: Action]] = rules -} - -object TweetVisibilityPolicy { - private[generators] val allApplicableSurfaces = - SafetyLevel.List.toSet -- - SafetyLevelGroup.Special.levels -- - Set( - SafetyLevel.SearchPeopleTypeahead, - SafetyLevel.UserProfileHeader, - SafetyLevel.UserScopedTimeline, - SafetyLevel.SpacesParticipants, - SafetyLevel.GryphonDecksAndColumns, - SafetyLevel.UserSettings, - SafetyLevel.BlockMuteUsersTimeline, - SafetyLevel.AdsBusinessSettings, - SafetyLevel.TrustedFriendsUserList, - SafetyLevel.UserSelfViewOnly, - SafetyLevel.ShoppingManagerSpyMode, - ) - - def builder(): TweetVisibilityPolicyBuilder = TweetVisibilityPolicyBuilder() -} - -case class TweetVisibilityPolicyBuilder( - rules: Map[SafetyLevel, FreedomOfSpeechNotReachActionBuilder[_ <: Action]] = Map()) { - - def addGlobalRule[T <: Action]( - actionBuilder: FreedomOfSpeechNotReachActionBuilder[T] - ): TweetVisibilityPolicyBuilder = - copy(rules = - rules ++ TweetVisibilityPolicy.allApplicableSurfaces.map(_ -> actionBuilder)) - - def addSafetyLevelRule[T <: Action]( - safetyLevel: SafetyLevel, - actionBuilder: FreedomOfSpeechNotReachActionBuilder[T] - ): TweetVisibilityPolicyBuilder = { - if (TweetVisibilityPolicy.allApplicableSurfaces.contains(safetyLevel)) { - copy(rules = rules ++ Map(safetyLevel -> actionBuilder)) - } else { - this - } - } - - def addSafetyLevelGroupRule[T <: Action]( - group: SafetyLevelGroup, - actionBuilder: FreedomOfSpeechNotReachActionBuilder[T] - ): TweetVisibilityPolicyBuilder = - copy(rules = - rules ++ group.levels.collect { - case safetyLevel if TweetVisibilityPolicy.allApplicableSurfaces.contains(safetyLevel) => - safetyLevel -> actionBuilder - }) - - def addRuleForAllRemainingSafetyLevels[T <: Action]( - actionBuilder: FreedomOfSpeechNotReachActionBuilder[T] - ): TweetVisibilityPolicyBuilder = - copy(rules = - rules ++ (TweetVisibilityPolicy.allApplicableSurfaces -- rules.keySet) - .map(_ -> actionBuilder).toMap) - - def build: TweetVisibilityPolicy = { - new TweetVisibilityPolicy(rules) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/package.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/package.scala deleted file mode 100644 index 2b4019f46..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/package.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.visibility - -package object rules { - type LabelTypeId = Short -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/providers/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/rules/providers/BUILD deleted file mode 100644 index a65d83f10..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/providers/BUILD +++ /dev/null @@ -1,38 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/google/guava", - "3rdparty/jvm/com/squareup/okhttp:okhttp3", - "abdecider/src/main/scala", - "configapi/configapi-core", - "decider/src/main/scala", - "scribelib/marshallers/src/main/scala/com/twitter/scribelib/marshallers", - "servo/decider/src/main/scala", - "snowflake/src/main/scala/com/twitter/snowflake/id", - "src/scala/com/twitter/takedown/util", - "src/thrift/com/twitter/content-health/sensitivemediasettings:sensitivemediasettings-scala", - "src/thrift/com/twitter/gizmoduck:user-thrift-scala", - "src/thrift/com/twitter/search/common:constants-scala", - "src/thrift/com/twitter/spam/rtf:safety-level-scala", - "src/thrift/com/twitter/spam/rtf:safety-result-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "stitch/stitch-core/src/main/scala/com/twitter/stitch", - "visibility/common/src/main/scala/com/twitter/visibility/common/actions", - "visibility/common/src/main/scala/com/twitter/visibility/common/actions/converter/scala", - "visibility/common/src/main/thrift/com/twitter/visibility:action-scala", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/configs", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/params", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/models", - "visibility/lib/src/main/scala/com/twitter/visibility/rules", - "visibility/lib/src/main/scala/com/twitter/visibility/rules/generators", - "visibility/lib/src/main/scala/com/twitter/visibility/util", - "visibility/lib/src/main/thrift/com/twitter/visibility/logging:vf-logging-scala", - "visibility/lib/src/main/thrift/com/twitter/visibility/strato:vf-strato-scala", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/providers/InjectedPolicyProvider.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/providers/InjectedPolicyProvider.scala deleted file mode 100644 index b9eafbbd6..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/providers/InjectedPolicyProvider.scala +++ /dev/null @@ -1,27 +0,0 @@ -package com.twitter.visibility.rules.providers - -import com.twitter.visibility.configapi.configs.VisibilityDeciderGates -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.rules.MixedVisibilityPolicy -import com.twitter.visibility.rules.RuleBase -import com.twitter.visibility.rules.generators.TweetRuleGenerator - -class InjectedPolicyProvider( - visibilityDeciderGates: VisibilityDeciderGates, - tweetRuleGenerator: TweetRuleGenerator) - extends PolicyProvider { - - private[rules] val policiesForSurface: Map[SafetyLevel, MixedVisibilityPolicy] = - RuleBase.RuleMap.map { - case (safetyLevel, policy) => - ( - safetyLevel, - MixedVisibilityPolicy( - originalPolicy = policy, - additionalTweetRules = tweetRuleGenerator.rulesForSurface(safetyLevel))) - } - - override def policyForSurface(safetyLevel: SafetyLevel): MixedVisibilityPolicy = { - policiesForSurface(safetyLevel) - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/providers/PolicyProvider.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/providers/PolicyProvider.scala deleted file mode 100644 index a39c0a083..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/providers/PolicyProvider.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.visibility.rules.providers - -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.rules.VisibilityPolicy - -trait PolicyProvider { - def policyForSurface(safetyLevel: SafetyLevel): VisibilityPolicy -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/providers/ProvidedEvaluationContext.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/providers/ProvidedEvaluationContext.scala deleted file mode 100644 index 76f6899da..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/providers/ProvidedEvaluationContext.scala +++ /dev/null @@ -1,50 +0,0 @@ -package com.twitter.visibility.rules.providers - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.timelines.configapi.Params -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.rules.EvaluationContext -import com.twitter.visibility.rules.VisibilityPolicy - -sealed abstract class ProvidedEvaluationContext( - visibilityPolicy: VisibilityPolicy, - params: Params, - statsReceiver: StatsReceiver) - extends EvaluationContext( - visibilityPolicy = visibilityPolicy, - params = params, - statsReceiver = statsReceiver) - -object ProvidedEvaluationContext { - - def injectRuntimeRulesIntoEvaluationContext( - evaluationContext: EvaluationContext, - safetyLevel: Option[SafetyLevel] = None, - policyProviderOpt: Option[PolicyProvider] = None - ): ProvidedEvaluationContext = { - (policyProviderOpt, safetyLevel) match { - case (Some(policyProvider), Some(safetyLevel)) => - new InjectedEvaluationContext( - evaluationContext = evaluationContext, - safetyLevel = safetyLevel, - policyProvider = policyProvider) - case (_, _) => new StaticEvaluationContext(evaluationContext) - } - } -} - -private class StaticEvaluationContext( - evaluationContext: EvaluationContext) - extends ProvidedEvaluationContext( - visibilityPolicy = evaluationContext.visibilityPolicy, - params = evaluationContext.params, - statsReceiver = evaluationContext.statsReceiver) - -private class InjectedEvaluationContext( - evaluationContext: EvaluationContext, - safetyLevel: SafetyLevel, - policyProvider: PolicyProvider) - extends ProvidedEvaluationContext( - visibilityPolicy = policyProvider.policyForSurface(safetyLevel), - params = evaluationContext.params, - statsReceiver = evaluationContext.statsReceiver) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/utils/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/rules/utils/BUILD deleted file mode 100644 index 75953e740..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/utils/BUILD +++ /dev/null @@ -1,38 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/google/guava", - "3rdparty/jvm/com/squareup/okhttp:okhttp3", - "abdecider/src/main/scala", - "configapi/configapi-core", - "decider/src/main/scala", - "scribelib/marshallers/src/main/scala/com/twitter/scribelib/marshallers", - "servo/decider/src/main/scala", - "snowflake/src/main/scala/com/twitter/snowflake/id", - "src/scala/com/twitter/takedown/util", - "src/thrift/com/twitter/content-health/sensitivemediasettings:sensitivemediasettings-scala", - "src/thrift/com/twitter/gizmoduck:user-thrift-scala", - "src/thrift/com/twitter/search/common:constants-scala", - "src/thrift/com/twitter/spam/rtf:safety-level-scala", - "src/thrift/com/twitter/spam/rtf:safety-result-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "stitch/stitch-core/src/main/scala/com/twitter/stitch", - "visibility/common/src/main/scala/com/twitter/visibility/common/actions", - "visibility/common/src/main/scala/com/twitter/visibility/common/actions/converter/scala", - "visibility/common/src/main/thrift/com/twitter/visibility:action-scala", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/configs", - "visibility/lib/src/main/scala/com/twitter/visibility/configapi/params", - "visibility/lib/src/main/scala/com/twitter/visibility/features", - "visibility/lib/src/main/scala/com/twitter/visibility/models", - "visibility/lib/src/main/scala/com/twitter/visibility/rules", - "visibility/lib/src/main/scala/com/twitter/visibility/rules/providers", - "visibility/lib/src/main/scala/com/twitter/visibility/util", - "visibility/lib/src/main/thrift/com/twitter/visibility/logging:vf-logging-scala", - "visibility/lib/src/main/thrift/com/twitter/visibility/strato:vf-strato-scala", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/utils/ShimUtils.scala b/visibilitylib/src/main/scala/com/twitter/visibility/rules/utils/ShimUtils.scala deleted file mode 100644 index 7501d7273..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/rules/utils/ShimUtils.scala +++ /dev/null @@ -1,60 +0,0 @@ -package com.twitter.visibility.rules.utils - -import com.twitter.visibility.features.Feature -import com.twitter.visibility.features.FeatureMap -import com.twitter.visibility.models.ContentId -import com.twitter.visibility.models.SafetyLevel -import com.twitter.visibility.rules.Filtered -import com.twitter.visibility.rules.Rule -import com.twitter.visibility.rules.RuleBase -import com.twitter.visibility.rules.RuleBase.RuleMap -import com.twitter.visibility.rules.providers.ProvidedEvaluationContext -import com.twitter.visibility.rules.providers.PolicyProvider - -object ShimUtils { - - def preFilterFeatureMap( - featureMap: FeatureMap, - safetyLevel: SafetyLevel, - contentId: ContentId, - evaluationContext: ProvidedEvaluationContext, - policyProviderOpt: Option[PolicyProvider] = None, - ): FeatureMap = { - val safetyLevelRules: Seq[Rule] = policyProviderOpt match { - case Some(policyProvider) => - policyProvider - .policyForSurface(safetyLevel) - .forContentId(contentId) - case _ => RuleMap(safetyLevel).forContentId(contentId) - } - - val afterDisabledRules = - safetyLevelRules.filter(evaluationContext.ruleEnabledInContext) - - val afterMissingFeatureRules = - afterDisabledRules.filter(rule => { - val missingFeatures: Set[Feature[_]] = rule.featureDependencies.collect { - case feature: Feature[_] if !featureMap.contains(feature) => feature - } - if (missingFeatures.isEmpty) { - true - } else { - false - } - }) - - val afterPreFilterRules = afterMissingFeatureRules.filter(rule => { - rule.preFilter(evaluationContext, featureMap.constantMap, null) match { - case Filtered => - false - case _ => - true - } - }) - - val filteredFeatureMap = - RuleBase.removeUnusedFeaturesFromFeatureMap(featureMap, afterPreFilterRules) - - filteredFeatureMap - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/util/BUILD b/visibilitylib/src/main/scala/com/twitter/visibility/util/BUILD deleted file mode 100644 index 3bfead4c2..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/util/BUILD +++ /dev/null @@ -1,18 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "abdecider/src/main/scala", - "decider", - "featureswitches/featureswitches-core/src/main/scala", - "featureswitches/featureswitches-core/src/main/scala/com/twitter/featureswitches/v2/builder", - "stitch/stitch-core", - "twitter-config/yaml", - "util-internal/scribe", - "util/util-logging/src/main/scala", - "util/util-stats/src/main/scala", - ], -) diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/util/DeciderUtil.scala b/visibilitylib/src/main/scala/com/twitter/visibility/util/DeciderUtil.scala deleted file mode 100644 index 751066c15..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/util/DeciderUtil.scala +++ /dev/null @@ -1,45 +0,0 @@ -package com.twitter.visibility.util - -import com.twitter.abdecider.ABDeciderFactory -import com.twitter.abdecider.LoggingABDecider -import com.twitter.decider.Decider -import com.twitter.decider.DeciderFactory -import com.twitter.decider.LocalOverrides -import com.twitter.logging._ - -object DeciderUtil { - val DefaultDeciderPath = "/config/com/twitter/visibility/decider.yml" - - private val zone = Option(System.getProperty("dc")).getOrElse("atla") - val DefaultDeciderOverlayPath: Some[String] = Some( - s"/usr/local/config/overlays/visibility-library/visibility-library/prod/$zone/decider_overlay.yml" - ) - - val DefaultABDeciderPath = "/usr/local/config/abdecider/abdecider.yml" - - def mkDecider( - deciderBasePath: String = DefaultDeciderPath, - deciderOverlayPath: Option[String] = DefaultDeciderOverlayPath, - useLocalDeciderOverrides: Boolean = false, - ): Decider = { - val fileBased = new DeciderFactory(Some(deciderBasePath), deciderOverlayPath)() - if (useLocalDeciderOverrides) { - LocalOverrides.decider("visibility-library").orElse(fileBased) - } else { - fileBased - } - } - - def mkLocalDecider: Decider = mkDecider(deciderOverlayPath = None) - - def mkABDecider( - scribeLogger: Option[Logger], - abDeciderPath: String = DefaultABDeciderPath - ): LoggingABDecider = { - ABDeciderFactory( - abDeciderPath, - Some("production"), - scribeLogger = scribeLogger - ).buildWithLogging() - } -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/util/FeatureSwitchUtil.scala b/visibilitylib/src/main/scala/com/twitter/visibility/util/FeatureSwitchUtil.scala deleted file mode 100644 index f6c0d6953..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/util/FeatureSwitchUtil.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.visibility.util - -import com.twitter.abdecider.ABDecider -import com.twitter.featureswitches.v2.FeatureSwitches -import com.twitter.featureswitches.v2.builder.FeatureSwitchesBuilder -import com.twitter.finagle.stats.StatsReceiver - -object FeatureSwitchUtil { - private val LibraryFeaturesConfigPath = "/features/visibility/main" - private val LimitedActionsFeaturesConfigPath = "/features/visibility-limited-actions/main" - - def mkVisibilityLibraryFeatureSwitches( - abDecider: ABDecider, - statsReceiver: StatsReceiver - ): FeatureSwitches = - FeatureSwitchesBuilder - .createDefault(LibraryFeaturesConfigPath, abDecider, Some(statsReceiver)).build() - - def mkLimitedActionsFeatureSwitches(statsReceiver: StatsReceiver): FeatureSwitches = - FeatureSwitchesBuilder - .createWithNoExperiments(LimitedActionsFeaturesConfigPath, Some(statsReceiver)).build() -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/util/LoggingUtil.scala b/visibilitylib/src/main/scala/com/twitter/visibility/util/LoggingUtil.scala deleted file mode 100644 index aecd21971..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/util/LoggingUtil.scala +++ /dev/null @@ -1,35 +0,0 @@ -package com.twitter.visibility.util - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.logging._ - -object LoggingUtil { - - val ExperimentationLog: String = "vf_abdecider" - - def mkDefaultHandlerFactory(statsReceiver: StatsReceiver): () => Handler = { - QueueingHandler( - maxQueueSize = 10000, - handler = ScribeHandler( - category = "client_event", - formatter = BareFormatter, - statsReceiver = statsReceiver.scope("client_event_scribe"), - level = Some(Level.INFO) - ) - ) - } - - def mkDefaultLoggerFactory(statsReceiver: StatsReceiver): LoggerFactory = { - LoggerFactory( - node = ExperimentationLog, - level = Some(Level.INFO), - useParents = false, - handlers = List(mkDefaultHandlerFactory(statsReceiver)) - ) - } - - def mkDefaultLogger(statsReceiver: StatsReceiver): Logger = { - mkDefaultLoggerFactory(statsReceiver)() - } - -} diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/util/NamingUtils.scala b/visibilitylib/src/main/scala/com/twitter/visibility/util/NamingUtils.scala deleted file mode 100644 index 0238b6544..000000000 --- a/visibilitylib/src/main/scala/com/twitter/visibility/util/NamingUtils.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.visibility.util - -object NamingUtils { - def getFriendlyName(a: Any): String = getFriendlyNameFromClass(a.getClass) - def getFriendlyNameFromClass(a: Class[_]): String = a.getSimpleName.stripSuffix("$") -}