Bluesky feed server - NSFW Likes
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: Return posts in order

Closes #1

+15 -24
+15 -24
app/src/main/kotlin/DarkFeedApi.kt
··· 11 11 import io.ktor.server.plugins.contentnegotiation.* 12 12 import io.ktor.server.response.* 13 13 import io.ktor.server.routing.* 14 - import kotlinx.coroutines.Job 15 - import kotlinx.coroutines.joinAll 16 - import kotlinx.coroutines.launch 17 - import kotlinx.coroutines.runBlocking 14 + import kotlinx.coroutines.* 18 15 import kotlinx.serialization.Serializable 19 16 import kotlinx.serialization.json.Json 20 17 18 + val DESIRED_LABELS: List<String> = listOf("porn", "sexual", "nudity", "sexual-figurative") 21 19 22 20 class DarkFeedApi( 23 21 private val hostname: String, ··· 83 81 84 82 println("handleGetFeedSkeleton: requestor: $requestor, limit: $limit, cursor: $cursor") 85 83 86 - call.respond(buildFeedSkeleton(requestor, limit, cursor)) 84 + call.respond(buildFeedSkeleton(requestor, limit ?: 25, cursor)) 87 85 } 88 86 89 - private suspend fun buildFeedSkeleton(requestor: String, limit: Int? = null, cursor: String? = null): FeedSkeleton { 87 + private suspend fun buildFeedSkeleton(requestor: String, limit: Int = 25, cursor: String? = null): FeedSkeleton { 90 88 val labeledPosts: MutableSet<PostView> = mutableSetOf() 91 89 var apiCallsCount = 0 92 90 var getLikesByActorCursor: String? = cursor?.split(':')?.last() 93 91 var isFeedFinished: Boolean = false 94 92 95 - while (labeledPosts.count() < (limit ?: 10) && apiCallsCount < 10 && !isFeedFinished) { 93 + while (labeledPosts.count() < limit && apiCallsCount < 10 && !isFeedFinished) { 96 94 val likes = bskyApi.getLikesByActor(requestor, getLikesByActorCursor) 97 95 .also { 98 96 if (it.second == null) { ··· 106 104 107 105 println("buildFeedSkeleton: $requestor: got ${likes.count()} likes, new cursor: $getLikesByActorCursor") 108 106 109 - val handles: MutableList<Job> = mutableListOf() 107 + runBlocking { 108 + val jobs: MutableList<Deferred<List<PostView>>> = mutableListOf() 110 109 111 - runBlocking { 112 - likes 113 - .chunked(25) 110 + likes.chunked(25) 114 111 .forEach { likeUris -> 115 - launch { 112 + async { 116 113 bskyApi.getPostLabels(likeUris) 117 114 .filter { post -> 118 - post.labels?.any { label -> 119 - listOf( 120 - "porn", 121 - "sexual", 122 - "nudity", 123 - "sexual-figurative" 124 - ).contains(label.value) 125 - } ?: false 126 - }.also { labeledPosts.addAll(it) } 127 - }.also { handles.add(it) } 115 + post.labels?.any { label -> DESIRED_LABELS.contains(label.value) } ?: false 116 + } 117 + }.also { deferred -> jobs.add(deferred) } 128 118 } 129 - } 130 119 131 - handles.joinAll() 120 + jobs.map { it.await() } 121 + .forEach { labeledPosts.addAll(it) } 122 + } 132 123 133 124 println("buildFeedSkeleton: $requestor: found ${labeledPosts.count()} labeled likes") 134 125