in visibilitylib/src/main/scala/com/twitter/visibility/interfaces/tweets/TweetVisibilityLibrary.scala [46:267]
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
}
}
}