diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/notifications/NotificationsVisibilityLibrary.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/notifications/NotificationsVisibilityLibrary.docx new file mode 100644 index 000000000..a6ce0c6a5 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/notifications/NotificationsVisibilityLibrary.docx differ 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/BUILD.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/BUILD.docx new file mode 100644 index 000000000..366dfb244 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/BUILD.docx differ diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceSafetyLabelMapFetcher.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceSafetyLabelMapFetcher.docx new file mode 100644 index 000000000..63c2b8bfe Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceSafetyLabelMapFetcher.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityLibrary.docx new file mode 100644 index 000000000..895786f74 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityLibrary.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityLibraryParity.docx new file mode 100644 index 000000000..cd58a23ba Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityLibraryParity.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityLibraryUtil.docx new file mode 100644 index 000000000..7c6aec6d2 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityLibraryUtil.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityRequest.docx new file mode 100644 index 000000000..d1a9e4374 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityRequest.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityResponse.docx new file mode 100644 index 000000000..7d33670e9 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/push_service/PushServiceVisibilityResponse.docx differ 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/BUILD.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/BUILD.docx new file mode 100644 index 000000000..8c6e3b793 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/BUILD.docx differ diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/BatchSearchVisibilityRequest.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/BatchSearchVisibilityRequest.docx new file mode 100644 index 000000000..4d2c21028 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/BatchSearchVisibilityRequest.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/BatchSearchVisibilityResponse.docx new file mode 100644 index 000000000..e2a6d1d7d Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/BatchSearchVisibilityResponse.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/CombinedVisibilityResult.docx new file mode 100644 index 000000000..fe08ecedb Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/CombinedVisibilityResult.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/SearchVisibilityLibrary.docx new file mode 100644 index 000000000..01f59e09a Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/SearchVisibilityLibrary.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/TweetContext.docx new file mode 100644 index 000000000..539a37b12 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/search/TweetContext.docx differ 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/BUILD.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/spaces/BUILD.docx new file mode 100644 index 000000000..a8c27aaaa Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/spaces/BUILD.docx differ diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/spaces/SpaceVisibilityLibrary.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/spaces/SpaceVisibilityLibrary.docx new file mode 100644 index 000000000..431974e33 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/spaces/SpaceVisibilityLibrary.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/spaces/SpaceVisibilityRequest.docx new file mode 100644 index 000000000..2ef9dca1d Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/spaces/SpaceVisibilityRequest.docx differ 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/BUILD.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/BUILD.docx new file mode 100644 index 000000000..4253ece2f Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/BUILD.docx differ diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/DeletedTweetVisibilityLibrary.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/DeletedTweetVisibilityLibrary.docx new file mode 100644 index 000000000..8e7f25389 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/DeletedTweetVisibilityLibrary.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/QuotedTweetVisibilityLibrary.docx new file mode 100644 index 000000000..9b2ee8a38 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/QuotedTweetVisibilityLibrary.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/TweetVisibilityLibrary.docx new file mode 100644 index 000000000..e04de6d89 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/TweetVisibilityLibrary.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/TweetVisibilityLibraryParityTest.docx new file mode 100644 index 000000000..3ac53d0fa Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/TweetVisibilityLibraryParityTest.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/TweetVisibilityRequest.docx new file mode 100644 index 000000000..120807a6a Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/TweetVisibilityRequest.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/TweetypieContext.docx new file mode 100644 index 000000000..5de8b12d4 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/TweetypieContext.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/UserUnavailableStateVisibilityLibrary.docx new file mode 100644 index 000000000..f0d45ba3f Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/UserUnavailableStateVisibilityLibrary.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/UserUnavailableStateVisibilityRequest.docx new file mode 100644 index 000000000..c621177db Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/UserUnavailableStateVisibilityRequest.docx differ 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/BUILD.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/enrichments/BUILD.docx new file mode 100644 index 000000000..88d20faa9 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/enrichments/BUILD.docx differ diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/enrichments/ComplianceTweetNoticeEnrichment.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/enrichments/ComplianceTweetNoticeEnrichment.docx new file mode 100644 index 000000000..8b3308112 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/enrichments/ComplianceTweetNoticeEnrichment.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/enrichments/LimitedActionsPolicyEnrichment.docx new file mode 100644 index 000000000..2f0ab5ccd Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/enrichments/LimitedActionsPolicyEnrichment.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/enrichments/TweetVisibilityNudgeEnrichment.docx new file mode 100644 index 000000000..1d7009677 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/enrichments/TweetVisibilityNudgeEnrichment.docx differ 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/BUILD.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/users/BUILD.docx new file mode 100644 index 000000000..3e7f2df41 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/users/BUILD.docx differ diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/users/UserVisibilityLibrary.docx b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/users/UserVisibilityLibrary.docx new file mode 100644 index 000000000..60492ad4a Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/interfaces/users/UserVisibilityLibrary.docx differ 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/BUILD.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/BUILD.docx new file mode 100644 index 000000000..2fe99ad13 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/BUILD.docx differ diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/models/CommunityTweet.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/CommunityTweet.docx new file mode 100644 index 000000000..c3132fe5b Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/CommunityTweet.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/ContentId.docx new file mode 100644 index 000000000..a1c1a1943 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/ContentId.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/LabelSource.docx new file mode 100644 index 000000000..d114b927c Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/LabelSource.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/MediaSafetyLabelType.docx new file mode 100644 index 000000000..e27fcde7e Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/MediaSafetyLabelType.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/MisinformationPolicy.docx new file mode 100644 index 000000000..e5db9baeb Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/MisinformationPolicy.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/MutedKeyword.docx new file mode 100644 index 000000000..a79c97bad Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/MutedKeyword.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLabel.docx new file mode 100644 index 000000000..f2963eb3e Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLabel.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLabelMetadata.docx new file mode 100644 index 000000000..adeb7e8a2 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLabelMetadata.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLabelType.docx new file mode 100644 index 000000000..5df2243d4 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLabelType.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLevel.docx new file mode 100644 index 000000000..14dc9998c Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLevel.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLevelGroup.docx new file mode 100644 index 000000000..23b4334ff Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/SafetyLevelGroup.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/SemanticCoreAnnotation.docx new file mode 100644 index 000000000..85bc060ca Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/SemanticCoreAnnotation.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/SpaceSafetyLabelType.docx new file mode 100644 index 000000000..1fe264632 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/SpaceSafetyLabelType.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/TweetDeleteReason.docx new file mode 100644 index 000000000..6496e13ec Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/TweetDeleteReason.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/TweetModelMetadata.docx new file mode 100644 index 000000000..f9da2277c Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/TweetModelMetadata.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/TweetSafetyLabel.docx new file mode 100644 index 000000000..08c05441e Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/TweetSafetyLabel.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/UnitOfDiversion.docx new file mode 100644 index 000000000..cb9d309a9 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/UnitOfDiversion.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/UserAge.docx new file mode 100644 index 000000000..218867008 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/UserAge.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/UserLabel.docx new file mode 100644 index 000000000..ef0f7fbcd Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/UserLabel.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/UserSensitiveMediaSettings.docx new file mode 100644 index 000000000..e02b8bdb1 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/UserSensitiveMediaSettings.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/UserUnavailableStateEnum.docx new file mode 100644 index 000000000..94d356e39 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/UserUnavailableStateEnum.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/ViewerContext.docx new file mode 100644 index 000000000..381193bcf Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/ViewerContext.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/ViolationLevel.docx new file mode 100644 index 000000000..084e9ebd9 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/ViolationLevel.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/models/package.docx new file mode 100644 index 000000000..73984a4c9 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/models/package.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/Action.docx new file mode 100644 index 000000000..45a6ca458 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/Action.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/AdvancedFilteringRules.docx new file mode 100644 index 000000000..a4b13133f Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/AdvancedFilteringRules.docx differ 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/BUILD.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/BUILD.docx new file mode 100644 index 000000000..895920fcc Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/BUILD.docx differ diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/CardRules.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/CardRules.docx new file mode 100644 index 000000000..e87ba2d79 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/CardRules.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/ComposableActions.docx new file mode 100644 index 000000000..ad4277217 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/ComposableActions.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/Condition.docx new file mode 100644 index 000000000..b25bbeea7 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/Condition.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/DmConversationRules.docx new file mode 100644 index 000000000..ff17f3a1e Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/DmConversationRules.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/DmEventRules.docx new file mode 100644 index 000000000..2a8299d1c Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/DmEventRules.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/DmVisibilityPolicies.docx new file mode 100644 index 000000000..802a2e2ae Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/DmVisibilityPolicies.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/DownrankingRules.docx new file mode 100644 index 000000000..6ed0ff58e Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/DownrankingRules.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/EvaluationContext.docx new file mode 100644 index 000000000..8b157203d Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/EvaluationContext.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/ExperimentBase.docx new file mode 100644 index 000000000..97037d7b4 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/ExperimentBase.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/FailClosedException.docx new file mode 100644 index 000000000..f5a4505c9 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/FailClosedException.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/FollowerRelations.docx new file mode 100644 index 000000000..fefa2a45e Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/FollowerRelations.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/ForEmergencyUseOnly.docx new file mode 100644 index 000000000..de23aa81b Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/ForEmergencyUseOnly.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/FreedomOfSpeechNotReach.docx new file mode 100644 index 000000000..ce0261f14 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/FreedomOfSpeechNotReach.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/InterstitialIf.docx new file mode 100644 index 000000000..70b603b08 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/InterstitialIf.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/PublicInterestRules.docx new file mode 100644 index 000000000..d3da33204 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/PublicInterestRules.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/Rule.docx new file mode 100644 index 000000000..0742b714c Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/Rule.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/RuleActionSourceBuilder.docx new file mode 100644 index 000000000..39dbfbc07 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/RuleActionSourceBuilder.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/RuleBase.docx new file mode 100644 index 000000000..55b814910 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/RuleBase.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/Rules.docx new file mode 100644 index 000000000..d57176ef1 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/Rules.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/SafeSearchRules.docx new file mode 100644 index 000000000..ec1ddecee Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/SafeSearchRules.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/SearchBlenderRules.docx new file mode 100644 index 000000000..a15cb782d Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/SearchBlenderRules.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/SensitiveMediaSettingsRules.docx new file mode 100644 index 000000000..219b2cc79 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/SensitiveMediaSettingsRules.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/SpaceRules.docx new file mode 100644 index 000000000..8a4b5f750 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/SpaceRules.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/TombstoneIf.docx new file mode 100644 index 000000000..d8dce31ad Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/TombstoneIf.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/ToxicityReplyFilterRules.docx new file mode 100644 index 000000000..17502c2f2 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/ToxicityReplyFilterRules.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/TweetLabelRules.docx new file mode 100644 index 000000000..d07eaa745 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/TweetLabelRules.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/TweetRules.docx new file mode 100644 index 000000000..549c6daf2 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/TweetRules.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/UserLabelRules.docx new file mode 100644 index 000000000..2b7abc78b Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/UserLabelRules.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/UserUnavailableStateTombstoneRules.docx new file mode 100644 index 000000000..e1e7fc3e2 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/UserUnavailableStateTombstoneRules.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/VisibilityPolicy.docx new file mode 100644 index 000000000..64d0b305b Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/VisibilityPolicy.docx differ 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/BUILD.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/generators/BUILD.docx new file mode 100644 index 000000000..c840fc2eb Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/generators/BUILD.docx differ diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/generators/RuleGenerator.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/generators/RuleGenerator.docx new file mode 100644 index 000000000..4c5bbf97d Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/generators/RuleGenerator.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/generators/TweetRuleGenerator.docx new file mode 100644 index 000000000..57ab211bb Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/generators/TweetRuleGenerator.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/generators/TweetVisibilityPolicy.docx new file mode 100644 index 000000000..1db2e2e3a Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/generators/TweetVisibilityPolicy.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/package.docx new file mode 100644 index 000000000..4b988ae8a Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/package.docx differ 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/BUILD.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/providers/BUILD.docx new file mode 100644 index 000000000..97230510d Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/providers/BUILD.docx differ diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/providers/InjectedPolicyProvider.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/providers/InjectedPolicyProvider.docx new file mode 100644 index 000000000..00c86cf83 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/providers/InjectedPolicyProvider.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/providers/PolicyProvider.docx new file mode 100644 index 000000000..1eb875f00 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/providers/PolicyProvider.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/providers/ProvidedEvaluationContext.docx new file mode 100644 index 000000000..204e2a6c0 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/providers/ProvidedEvaluationContext.docx differ 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/BUILD.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/utils/BUILD.docx new file mode 100644 index 000000000..41a404521 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/utils/BUILD.docx differ diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/rules/utils/ShimUtils.docx b/visibilitylib/src/main/scala/com/twitter/visibility/rules/utils/ShimUtils.docx new file mode 100644 index 000000000..9bf0b1da4 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/rules/utils/ShimUtils.docx differ 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/BUILD.docx b/visibilitylib/src/main/scala/com/twitter/visibility/util/BUILD.docx new file mode 100644 index 000000000..7a8b7a243 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/util/BUILD.docx differ diff --git a/visibilitylib/src/main/scala/com/twitter/visibility/util/DeciderUtil.docx b/visibilitylib/src/main/scala/com/twitter/visibility/util/DeciderUtil.docx new file mode 100644 index 000000000..02ae1f07c Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/util/DeciderUtil.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/util/FeatureSwitchUtil.docx new file mode 100644 index 000000000..3873cd9be Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/util/FeatureSwitchUtil.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/util/LoggingUtil.docx new file mode 100644 index 000000000..4b75b3906 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/util/LoggingUtil.docx differ 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.docx b/visibilitylib/src/main/scala/com/twitter/visibility/util/NamingUtils.docx new file mode 100644 index 000000000..4bce8a8f7 Binary files /dev/null and b/visibilitylib/src/main/scala/com/twitter/visibility/util/NamingUtils.docx differ 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("$") -}