@atproto/bsky 0.0.251 → 0.0.254

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/dist/api/age-assurance/const.js +19 -19
  3. package/dist/api/age-assurance/const.js.map +1 -1
  4. package/dist/kws.d.ts +8 -0
  5. package/dist/kws.d.ts.map +1 -1
  6. package/dist/kws.js +53 -4
  7. package/dist/kws.js.map +1 -1
  8. package/dist/lexicons/app/bsky/actor/defs.defs.d.ts +6 -0
  9. package/dist/lexicons/app/bsky/actor/defs.defs.d.ts.map +1 -1
  10. package/dist/lexicons/app/bsky/actor/defs.defs.js +1 -0
  11. package/dist/lexicons/app/bsky/actor/defs.defs.js.map +1 -1
  12. package/package.json +28 -23
  13. package/bin/migration-create.ts +0 -46
  14. package/buf.gen.yaml +0 -12
  15. package/proto/bsky.proto +0 -1907
  16. package/proto/courier.proto +0 -84
  17. package/proto/rolodex.proto +0 -116
  18. package/src/api/age-assurance/const.ts +0 -203
  19. package/src/api/age-assurance/index.ts +0 -34
  20. package/src/api/age-assurance/kws/age-verified.test.ts +0 -98
  21. package/src/api/age-assurance/kws/age-verified.ts +0 -81
  22. package/src/api/age-assurance/kws/const.ts +0 -33
  23. package/src/api/age-assurance/kws/external-payload.test.ts +0 -72
  24. package/src/api/age-assurance/kws/external-payload.ts +0 -149
  25. package/src/api/age-assurance/redirects/kws-age-verified.ts +0 -107
  26. package/src/api/age-assurance/stash.ts +0 -23
  27. package/src/api/age-assurance/types.ts +0 -10
  28. package/src/api/age-assurance/util.ts +0 -68
  29. package/src/api/age-assurance/webhooks/kws-age-verified.ts +0 -75
  30. package/src/api/app/bsky/actor/getProfile.ts +0 -106
  31. package/src/api/app/bsky/actor/getProfiles.ts +0 -99
  32. package/src/api/app/bsky/actor/getSuggestions.ts +0 -163
  33. package/src/api/app/bsky/actor/searchActors.ts +0 -171
  34. package/src/api/app/bsky/actor/searchActorsTypeahead.ts +0 -164
  35. package/src/api/app/bsky/ageassurance/begin.ts +0 -175
  36. package/src/api/app/bsky/ageassurance/getConfig.ts +0 -16
  37. package/src/api/app/bsky/ageassurance/getState.ts +0 -58
  38. package/src/api/app/bsky/bookmark/createBookmark.ts +0 -39
  39. package/src/api/app/bsky/bookmark/deleteBookmark.ts +0 -32
  40. package/src/api/app/bsky/bookmark/getBookmarks.ts +0 -97
  41. package/src/api/app/bsky/bookmark/util.ts +0 -13
  42. package/src/api/app/bsky/contact/dismissMatch.ts +0 -26
  43. package/src/api/app/bsky/contact/getMatches.ts +0 -111
  44. package/src/api/app/bsky/contact/getSyncStatus.ts +0 -38
  45. package/src/api/app/bsky/contact/importContacts.ts +0 -119
  46. package/src/api/app/bsky/contact/removeData.ts +0 -25
  47. package/src/api/app/bsky/contact/sendNotification.ts +0 -33
  48. package/src/api/app/bsky/contact/startPhoneVerification.ts +0 -26
  49. package/src/api/app/bsky/contact/util.ts +0 -92
  50. package/src/api/app/bsky/contact/verifyPhone.ts +0 -29
  51. package/src/api/app/bsky/draft/createDraft.ts +0 -45
  52. package/src/api/app/bsky/draft/deleteDraft.ts +0 -20
  53. package/src/api/app/bsky/draft/getDrafts.ts +0 -44
  54. package/src/api/app/bsky/draft/updateDraft.ts +0 -26
  55. package/src/api/app/bsky/embed/getEmbedExternalView.ts +0 -154
  56. package/src/api/app/bsky/feed/getActorFeeds.ts +0 -101
  57. package/src/api/app/bsky/feed/getActorLikes.ts +0 -128
  58. package/src/api/app/bsky/feed/getAuthorFeed.ts +0 -279
  59. package/src/api/app/bsky/feed/getFeed.ts +0 -282
  60. package/src/api/app/bsky/feed/getFeedGenerator.ts +0 -68
  61. package/src/api/app/bsky/feed/getFeedGenerators.ts +0 -86
  62. package/src/api/app/bsky/feed/getLikes.ts +0 -151
  63. package/src/api/app/bsky/feed/getListFeed.ts +0 -147
  64. package/src/api/app/bsky/feed/getPostThread.ts +0 -156
  65. package/src/api/app/bsky/feed/getPosts.ts +0 -100
  66. package/src/api/app/bsky/feed/getQuotes.ts +0 -122
  67. package/src/api/app/bsky/feed/getRepostedBy.ts +0 -121
  68. package/src/api/app/bsky/feed/getSuggestedFeeds.ts +0 -39
  69. package/src/api/app/bsky/feed/getTimeline.ts +0 -127
  70. package/src/api/app/bsky/feed/searchPosts.ts +0 -274
  71. package/src/api/app/bsky/feed/searchPostsV2.ts +0 -243
  72. package/src/api/app/bsky/graph/getActorStarterPacks.ts +0 -103
  73. package/src/api/app/bsky/graph/getBlocks.ts +0 -94
  74. package/src/api/app/bsky/graph/getFollowers.ts +0 -153
  75. package/src/api/app/bsky/graph/getFollows.ts +0 -151
  76. package/src/api/app/bsky/graph/getKnownFollowers.ts +0 -123
  77. package/src/api/app/bsky/graph/getList.ts +0 -152
  78. package/src/api/app/bsky/graph/getListBlocks.ts +0 -87
  79. package/src/api/app/bsky/graph/getListMutes.ts +0 -87
  80. package/src/api/app/bsky/graph/getLists.ts +0 -125
  81. package/src/api/app/bsky/graph/getListsWithMembership.ts +0 -146
  82. package/src/api/app/bsky/graph/getMutes.ts +0 -87
  83. package/src/api/app/bsky/graph/getRelationships.ts +0 -58
  84. package/src/api/app/bsky/graph/getStarterPack.ts +0 -82
  85. package/src/api/app/bsky/graph/getStarterPacks.ts +0 -86
  86. package/src/api/app/bsky/graph/getStarterPacksWithMembership.ts +0 -136
  87. package/src/api/app/bsky/graph/getSuggestedFollowsByActor.ts +0 -171
  88. package/src/api/app/bsky/graph/muteActor.ts +0 -24
  89. package/src/api/app/bsky/graph/muteActorList.ts +0 -19
  90. package/src/api/app/bsky/graph/muteThread.ts +0 -19
  91. package/src/api/app/bsky/graph/searchStarterPacks.ts +0 -169
  92. package/src/api/app/bsky/graph/unmuteActor.ts +0 -21
  93. package/src/api/app/bsky/graph/unmuteActorList.ts +0 -19
  94. package/src/api/app/bsky/graph/unmuteThread.ts +0 -19
  95. package/src/api/app/bsky/labeler/getServices.ts +0 -41
  96. package/src/api/app/bsky/notification/getPreferences.ts +0 -49
  97. package/src/api/app/bsky/notification/getUnreadCount.ts +0 -83
  98. package/src/api/app/bsky/notification/listActivitySubscriptions.ts +0 -116
  99. package/src/api/app/bsky/notification/listNotifications.ts +0 -272
  100. package/src/api/app/bsky/notification/putActivitySubscription.ts +0 -69
  101. package/src/api/app/bsky/notification/putPreferences.ts +0 -17
  102. package/src/api/app/bsky/notification/putPreferencesV2.ts +0 -64
  103. package/src/api/app/bsky/notification/registerPush.ts +0 -40
  104. package/src/api/app/bsky/notification/unregisterPush.ts +0 -39
  105. package/src/api/app/bsky/notification/updateSeen.ts +0 -52
  106. package/src/api/app/bsky/notification/util.ts +0 -134
  107. package/src/api/app/bsky/unspecced/getAgeAssuranceState.ts +0 -48
  108. package/src/api/app/bsky/unspecced/getConfig.ts +0 -20
  109. package/src/api/app/bsky/unspecced/getOnboardingSuggestedStarterPacks.ts +0 -162
  110. package/src/api/app/bsky/unspecced/getPopularFeedGenerators.ts +0 -91
  111. package/src/api/app/bsky/unspecced/getPostThreadOtherV2.ts +0 -126
  112. package/src/api/app/bsky/unspecced/getPostThreadV2.ts +0 -148
  113. package/src/api/app/bsky/unspecced/getSuggestedFeeds.ts +0 -100
  114. package/src/api/app/bsky/unspecced/getSuggestedOnboardingUsers.ts +0 -143
  115. package/src/api/app/bsky/unspecced/getSuggestedStarterPacks.ts +0 -165
  116. package/src/api/app/bsky/unspecced/getSuggestedUsers.ts +0 -183
  117. package/src/api/app/bsky/unspecced/getSuggestedUsersForDiscover.ts +0 -175
  118. package/src/api/app/bsky/unspecced/getSuggestedUsersForExplore.ts +0 -178
  119. package/src/api/app/bsky/unspecced/getSuggestedUsersForSeeMore.ts +0 -178
  120. package/src/api/app/bsky/unspecced/getTaggedSuggestions.ts +0 -27
  121. package/src/api/app/bsky/unspecced/getTrendingTopics.ts +0 -96
  122. package/src/api/app/bsky/unspecced/getTrends.ts +0 -162
  123. package/src/api/app/bsky/unspecced/initAgeAssurance.ts +0 -150
  124. package/src/api/blob-dispatcher.ts +0 -41
  125. package/src/api/blob-resolver.ts +0 -401
  126. package/src/api/com/atproto/admin/getAccountInfos.ts +0 -49
  127. package/src/api/com/atproto/admin/getSubjectStatus.ts +0 -79
  128. package/src/api/com/atproto/admin/updateSubjectStatus.ts +0 -80
  129. package/src/api/com/atproto/identity/resolveHandle.ts +0 -19
  130. package/src/api/com/atproto/label/queryLabels.ts +0 -42
  131. package/src/api/com/atproto/repo/getRecord.ts +0 -44
  132. package/src/api/com/atproto/temp/fetchLabels.ts +0 -9
  133. package/src/api/external.ts +0 -15
  134. package/src/api/health.ts +0 -47
  135. package/src/api/index.ts +0 -216
  136. package/src/api/internal/bsky/actor/getProfiles.ts +0 -87
  137. package/src/api/kws/api.ts +0 -113
  138. package/src/api/kws/index.ts +0 -29
  139. package/src/api/kws/types.ts +0 -78
  140. package/src/api/kws/util.test.ts +0 -50
  141. package/src/api/kws/util.ts +0 -109
  142. package/src/api/kws/webhook.ts +0 -134
  143. package/src/api/sitemap.ts +0 -76
  144. package/src/api/util.ts +0 -45
  145. package/src/api/well-known.ts +0 -44
  146. package/src/auth-verifier.ts +0 -522
  147. package/src/bsync.ts +0 -41
  148. package/src/cache/read-through.ts +0 -157
  149. package/src/config.ts +0 -719
  150. package/src/context.ts +0 -143
  151. package/src/courier.ts +0 -41
  152. package/src/data-plane/client/hosts.ts +0 -103
  153. package/src/data-plane/client/index.ts +0 -125
  154. package/src/data-plane/client/util.test.ts +0 -29
  155. package/src/data-plane/client/util.ts +0 -74
  156. package/src/data-plane/index.ts +0 -2
  157. package/src/data-plane/server/background.ts +0 -66
  158. package/src/data-plane/server/bsync-subscription.ts +0 -590
  159. package/src/data-plane/server/db/database-schema.ts +0 -90
  160. package/src/data-plane/server/db/db.ts +0 -204
  161. package/src/data-plane/server/db/index.ts +0 -2
  162. package/src/data-plane/server/db/migrations/20230309T045948368Z-init.ts +0 -305
  163. package/src/data-plane/server/db/migrations/20230408T152211201Z-notification-init.ts +0 -25
  164. package/src/data-plane/server/db/migrations/20230417T210628672Z-moderation-init.ts +0 -127
  165. package/src/data-plane/server/db/migrations/20230420T211446071Z-did-cache.ts +0 -14
  166. package/src/data-plane/server/db/migrations/20230427T194702079Z-notif-record-index.ts +0 -14
  167. package/src/data-plane/server/db/migrations/20230605T144730094Z-post-profile-aggs.ts +0 -23
  168. package/src/data-plane/server/db/migrations/20230607T211442112Z-feed-generator-init.ts +0 -34
  169. package/src/data-plane/server/db/migrations/20230608T155101190Z-algo-whats-hot-view.ts +0 -85
  170. package/src/data-plane/server/db/migrations/20230608T201813132Z-mute-lists.ts +0 -78
  171. package/src/data-plane/server/db/migrations/20230608T205147239Z-mutes.ts +0 -15
  172. package/src/data-plane/server/db/migrations/20230609T153623961Z-blocks.ts +0 -33
  173. package/src/data-plane/server/db/migrations/20230609T232122649Z-actor-deletion-indexes.ts +0 -27
  174. package/src/data-plane/server/db/migrations/20230610T203555962Z-suggested-follows.ts +0 -13
  175. package/src/data-plane/server/db/migrations/20230611T215300060Z-actor-state.ts +0 -13
  176. package/src/data-plane/server/db/migrations/20230620T161134972Z-post-langs.ts +0 -9
  177. package/src/data-plane/server/db/migrations/20230627T212437895Z-optional-handle.ts +0 -15
  178. package/src/data-plane/server/db/migrations/20230629T220835893Z-remove-post-hierarchy.ts +0 -32
  179. package/src/data-plane/server/db/migrations/20230703T045536691Z-feed-and-label-indices.ts +0 -31
  180. package/src/data-plane/server/db/migrations/20230720T164800037Z-posts-cursor-idx.ts +0 -19
  181. package/src/data-plane/server/db/migrations/20230807T035309811Z-feed-item-delete-invite-for-user-idx.ts +0 -14
  182. package/src/data-plane/server/db/migrations/20230808T172902639Z-repo-rev.ts +0 -12
  183. package/src/data-plane/server/db/migrations/20230810T203349843Z-action-duration.ts +0 -23
  184. package/src/data-plane/server/db/migrations/20230817T195936007Z-native-notifications.ts +0 -16
  185. package/src/data-plane/server/db/migrations/20230830T205507322Z-suggested-feeds.ts +0 -13
  186. package/src/data-plane/server/db/migrations/20230904T211011773Z-block-lists.ts +0 -24
  187. package/src/data-plane/server/db/migrations/20230906T222220386Z-thread-gating.ts +0 -27
  188. package/src/data-plane/server/db/migrations/20230920T213858047Z-add-tags-to-post.ts +0 -9
  189. package/src/data-plane/server/db/migrations/20230929T192920807Z-record-cursor-indexes.ts +0 -40
  190. package/src/data-plane/server/db/migrations/20231003T202833377Z-create-moderation-subject-status.ts +0 -123
  191. package/src/data-plane/server/db/migrations/20231220T225126090Z-blob-takedowns.ts +0 -66
  192. package/src/data-plane/server/db/migrations/20240124T023719200Z-tagged-suggestions.ts +0 -15
  193. package/src/data-plane/server/db/migrations/20240226T225725627Z-labelers.ts +0 -27
  194. package/src/data-plane/server/db/migrations/20240530T170337073Z-account-deactivation.ts +0 -12
  195. package/src/data-plane/server/db/migrations/20240606T171229898Z-thread-mutes.ts +0 -15
  196. package/src/data-plane/server/db/migrations/20240606T222548219Z-starter-packs.ts +0 -45
  197. package/src/data-plane/server/db/migrations/20240719T203853939Z-priority-notifs.ts +0 -25
  198. package/src/data-plane/server/db/migrations/20240723T220700077Z-quotes-post-aggs.ts +0 -12
  199. package/src/data-plane/server/db/migrations/20240723T220703655Z-quotes.ts +0 -28
  200. package/src/data-plane/server/db/migrations/20240801T193939827Z-post-gate.ts +0 -17
  201. package/src/data-plane/server/db/migrations/20240808T224251220Z-post-gate-flags.ts +0 -25
  202. package/src/data-plane/server/db/migrations/20240829T211238293Z-simplify-actor-sync.ts +0 -23
  203. package/src/data-plane/server/db/migrations/20240831T134810923Z-pinned-posts.ts +0 -17
  204. package/src/data-plane/server/db/migrations/20241114T153108102Z-add-starter-packs-name.ts +0 -19
  205. package/src/data-plane/server/db/migrations/20250116T222618297Z-post-embed-video.ts +0 -17
  206. package/src/data-plane/server/db/migrations/20250207T174822012Z-add-label-exp.ts +0 -9
  207. package/src/data-plane/server/db/migrations/20250404T163421487Z-verifications.ts +0 -39
  208. package/src/data-plane/server/db/migrations/20250526T023712742Z-like-repost-via.ts +0 -17
  209. package/src/data-plane/server/db/migrations/20250528T221913281Z-add-record-tags.ts +0 -9
  210. package/src/data-plane/server/db/migrations/20250602T190357447Z-add-private-data.ts +0 -22
  211. package/src/data-plane/server/db/migrations/20250611T140649895Z-add-activity-subscription.ts +0 -22
  212. package/src/data-plane/server/db/migrations/20250627T025331240Z-add-actor-age-assurance-columns.ts +0 -22
  213. package/src/data-plane/server/db/migrations/20250812T183735692Z-add-bookmarks.ts +0 -23
  214. package/src/data-plane/server/db/migrations/20250813T174955711Z-add-post-agg-bookmarks.ts +0 -12
  215. package/src/data-plane/server/db/migrations/20251120T004738098Z-update-actor-age-assurance-v2.ts +0 -28
  216. package/src/data-plane/server/db/migrations/20260112T133951271Z-add-drafts.ts +0 -24
  217. package/src/data-plane/server/db/migrations/20260604T224952774Z-post-embed-gallery-image.ts +0 -19
  218. package/src/data-plane/server/db/migrations/index.ts +0 -60
  219. package/src/data-plane/server/db/migrations/provider.ts +0 -26
  220. package/src/data-plane/server/db/pagination.ts +0 -341
  221. package/src/data-plane/server/db/tables/activity-subscription.ts +0 -12
  222. package/src/data-plane/server/db/tables/actor-block.ts +0 -14
  223. package/src/data-plane/server/db/tables/actor-state.ts +0 -10
  224. package/src/data-plane/server/db/tables/actor-sync.ts +0 -9
  225. package/src/data-plane/server/db/tables/actor.ts +0 -19
  226. package/src/data-plane/server/db/tables/algo.ts +0 -11
  227. package/src/data-plane/server/db/tables/blob-takedown.ts +0 -9
  228. package/src/data-plane/server/db/tables/bookmark.ts +0 -11
  229. package/src/data-plane/server/db/tables/did-cache.ts +0 -13
  230. package/src/data-plane/server/db/tables/draft.ts +0 -11
  231. package/src/data-plane/server/db/tables/duplicate-record.ts +0 -12
  232. package/src/data-plane/server/db/tables/feed-generator.ts +0 -21
  233. package/src/data-plane/server/db/tables/feed-item.ts +0 -12
  234. package/src/data-plane/server/db/tables/follow.ts +0 -15
  235. package/src/data-plane/server/db/tables/label.ts +0 -13
  236. package/src/data-plane/server/db/tables/labeler.ts +0 -16
  237. package/src/data-plane/server/db/tables/like.ts +0 -18
  238. package/src/data-plane/server/db/tables/list-block.ts +0 -15
  239. package/src/data-plane/server/db/tables/list-item.ts +0 -16
  240. package/src/data-plane/server/db/tables/list-mute.ts +0 -9
  241. package/src/data-plane/server/db/tables/list.ts +0 -19
  242. package/src/data-plane/server/db/tables/mute.ts +0 -9
  243. package/src/data-plane/server/db/tables/notification-push-token.ts +0 -10
  244. package/src/data-plane/server/db/tables/notification.ts +0 -16
  245. package/src/data-plane/server/db/tables/post-agg.ts +0 -16
  246. package/src/data-plane/server/db/tables/post-embed.ts +0 -47
  247. package/src/data-plane/server/db/tables/post-gate.ts +0 -12
  248. package/src/data-plane/server/db/tables/post.ts +0 -28
  249. package/src/data-plane/server/db/tables/private-data.ts +0 -13
  250. package/src/data-plane/server/db/tables/profile-agg.ts +0 -14
  251. package/src/data-plane/server/db/tables/profile.ts +0 -17
  252. package/src/data-plane/server/db/tables/quote.ts +0 -15
  253. package/src/data-plane/server/db/tables/record.ts +0 -15
  254. package/src/data-plane/server/db/tables/repost.ts +0 -18
  255. package/src/data-plane/server/db/tables/starter-pack.ts +0 -17
  256. package/src/data-plane/server/db/tables/subscription.ts +0 -9
  257. package/src/data-plane/server/db/tables/suggested-feed.ts +0 -10
  258. package/src/data-plane/server/db/tables/suggested-follow.ts +0 -10
  259. package/src/data-plane/server/db/tables/tagged-suggestion.ts +0 -11
  260. package/src/data-plane/server/db/tables/thread-gate.ts +0 -12
  261. package/src/data-plane/server/db/tables/thread-mute.ts +0 -9
  262. package/src/data-plane/server/db/tables/verification.ts +0 -20
  263. package/src/data-plane/server/db/tables/view-param.ts +0 -12
  264. package/src/data-plane/server/db/types.ts +0 -12
  265. package/src/data-plane/server/db/util.ts +0 -67
  266. package/src/data-plane/server/index.ts +0 -44
  267. package/src/data-plane/server/indexing/index.ts +0 -458
  268. package/src/data-plane/server/indexing/plugins/block.ts +0 -84
  269. package/src/data-plane/server/indexing/plugins/chat-declaration.ts +0 -60
  270. package/src/data-plane/server/indexing/plugins/feed-generator.ts +0 -80
  271. package/src/data-plane/server/indexing/plugins/follow.ts +0 -132
  272. package/src/data-plane/server/indexing/plugins/germ-declaration.ts +0 -57
  273. package/src/data-plane/server/indexing/plugins/labeler.ts +0 -74
  274. package/src/data-plane/server/indexing/plugins/like.ts +0 -151
  275. package/src/data-plane/server/indexing/plugins/list-block.ts +0 -84
  276. package/src/data-plane/server/indexing/plugins/list-item.ts +0 -92
  277. package/src/data-plane/server/indexing/plugins/list.ts +0 -80
  278. package/src/data-plane/server/indexing/plugins/notif-declaration.ts +0 -57
  279. package/src/data-plane/server/indexing/plugins/post-gate.ts +0 -101
  280. package/src/data-plane/server/indexing/plugins/post.ts +0 -675
  281. package/src/data-plane/server/indexing/plugins/profile.ts +0 -90
  282. package/src/data-plane/server/indexing/plugins/repost.ts +0 -176
  283. package/src/data-plane/server/indexing/plugins/starter-pack.ts +0 -74
  284. package/src/data-plane/server/indexing/plugins/status.ts +0 -57
  285. package/src/data-plane/server/indexing/plugins/thread-gate.ts +0 -101
  286. package/src/data-plane/server/indexing/plugins/verification.ts +0 -113
  287. package/src/data-plane/server/indexing/processor.ts +0 -292
  288. package/src/data-plane/server/routes/activity-subscription.ts +0 -84
  289. package/src/data-plane/server/routes/blocks.ts +0 -127
  290. package/src/data-plane/server/routes/bookmarks.ts +0 -83
  291. package/src/data-plane/server/routes/drafts.ts +0 -37
  292. package/src/data-plane/server/routes/feed-gens.ts +0 -89
  293. package/src/data-plane/server/routes/feeds.ts +0 -176
  294. package/src/data-plane/server/routes/follows.ts +0 -141
  295. package/src/data-plane/server/routes/identity.ts +0 -59
  296. package/src/data-plane/server/routes/index.ts +0 -67
  297. package/src/data-plane/server/routes/interactions.ts +0 -120
  298. package/src/data-plane/server/routes/labels.ts +0 -55
  299. package/src/data-plane/server/routes/likes.ts +0 -92
  300. package/src/data-plane/server/routes/lists.ts +0 -88
  301. package/src/data-plane/server/routes/moderation.ts +0 -102
  302. package/src/data-plane/server/routes/mutes.ts +0 -195
  303. package/src/data-plane/server/routes/notifs.ts +0 -239
  304. package/src/data-plane/server/routes/profile.ts +0 -220
  305. package/src/data-plane/server/routes/quotes.ts +0 -32
  306. package/src/data-plane/server/routes/records.ts +0 -119
  307. package/src/data-plane/server/routes/relationships.ts +0 -174
  308. package/src/data-plane/server/routes/reposts.ts +0 -76
  309. package/src/data-plane/server/routes/search.ts +0 -181
  310. package/src/data-plane/server/routes/site-standard.ts +0 -12
  311. package/src/data-plane/server/routes/sitemap.ts +0 -43
  312. package/src/data-plane/server/routes/starter-packs.ts +0 -32
  313. package/src/data-plane/server/routes/suggestions.ts +0 -175
  314. package/src/data-plane/server/routes/sync.ts +0 -16
  315. package/src/data-plane/server/routes/threads.ts +0 -33
  316. package/src/data-plane/server/subscription.ts +0 -152
  317. package/src/data-plane/server/util.ts +0 -202
  318. package/src/error.ts +0 -12
  319. package/src/etcd.ts +0 -90
  320. package/src/feature-gates/README.md +0 -83
  321. package/src/feature-gates/gates.ts +0 -25
  322. package/src/feature-gates/index.ts +0 -235
  323. package/src/feature-gates/metrics.test.ts +0 -196
  324. package/src/feature-gates/metrics.ts +0 -107
  325. package/src/feature-gates/types.ts +0 -62
  326. package/src/feature-gates/utils.test.ts +0 -66
  327. package/src/feature-gates/utils.ts +0 -135
  328. package/src/hydration/actor.ts +0 -578
  329. package/src/hydration/external.test.ts +0 -281
  330. package/src/hydration/external.ts +0 -268
  331. package/src/hydration/feed.ts +0 -455
  332. package/src/hydration/graph.ts +0 -354
  333. package/src/hydration/hydrator.ts +0 -1835
  334. package/src/hydration/label.ts +0 -207
  335. package/src/hydration/util.ts +0 -199
  336. package/src/image/index.ts +0 -2
  337. package/src/image/invalidator.ts +0 -33
  338. package/src/image/logger.ts +0 -6
  339. package/src/image/server.ts +0 -228
  340. package/src/image/sharp.ts +0 -89
  341. package/src/image/uri.ts +0 -114
  342. package/src/image/util.ts +0 -41
  343. package/src/index.ts +0 -312
  344. package/src/kws.ts +0 -197
  345. package/src/logger.ts +0 -40
  346. package/src/pipeline.ts +0 -60
  347. package/src/redis.ts +0 -205
  348. package/src/rolodex.ts +0 -42
  349. package/src/stash.ts +0 -76
  350. package/src/util/debug.ts +0 -10
  351. package/src/util/http.ts +0 -42
  352. package/src/util/retry.ts +0 -10
  353. package/src/util/standard-site.test.ts +0 -423
  354. package/src/util/standard-site.ts +0 -196
  355. package/src/util/uris.ts +0 -38
  356. package/src/util.ts +0 -48
  357. package/src/views/index.ts +0 -2783
  358. package/src/views/threads-v2.ts +0 -510
  359. package/src/views/types.ts +0 -193
  360. package/src/views/util.ts +0 -114
  361. package/test.env +0 -2
  362. package/tests/__snapshots__/feed-generation.test.ts.snap +0 -2510
  363. package/tests/_util.ts +0 -292
  364. package/tests/admin/admin-auth.test.ts +0 -190
  365. package/tests/admin/moderation.test.ts +0 -222
  366. package/tests/auth.test.ts +0 -90
  367. package/tests/blob-resolver.test.ts +0 -125
  368. package/tests/data-plane/__snapshots__/indexing.test.ts.snap +0 -887
  369. package/tests/data-plane/db.test.ts +0 -189
  370. package/tests/data-plane/duplicate-records.test.ts +0 -156
  371. package/tests/data-plane/handle-invalidation.test.ts +0 -153
  372. package/tests/data-plane/indexing.test.ts +0 -827
  373. package/tests/data-plane/subscription.test.ts +0 -128
  374. package/tests/data-plane/thread-mutes.test.ts +0 -175
  375. package/tests/entryway-auth.test.ts +0 -177
  376. package/tests/etcd.test.ts +0 -302
  377. package/tests/feed-generation.test.ts +0 -965
  378. package/tests/hydration/util.test.ts +0 -119
  379. package/tests/image/server.test.ts +0 -97
  380. package/tests/image/sharp.test.ts +0 -199
  381. package/tests/image/uri.test.ts +0 -106
  382. package/tests/label-hydration.test.ts +0 -245
  383. package/tests/postgates.test.ts +0 -182
  384. package/tests/query-labels.test.ts +0 -85
  385. package/tests/redis-cache.test.ts +0 -230
  386. package/tests/seed/feed-hidden-replies.ts +0 -63
  387. package/tests/seed/get-suggested-starter-packs.ts +0 -64
  388. package/tests/seed/get-trends.ts +0 -71
  389. package/tests/seed/known-followers.ts +0 -111
  390. package/tests/seed/postgates.ts +0 -57
  391. package/tests/server.test.ts +0 -115
  392. package/tests/sitemap.test.ts +0 -75
  393. package/tests/stash.test.ts +0 -180
  394. package/tests/utils.test.ts +0 -36
  395. package/tests/views/__snapshots__/actor-search.test.ts.snap +0 -155
  396. package/tests/views/__snapshots__/author-feed.test.ts.snap +0 -6301
  397. package/tests/views/__snapshots__/block-lists.test.ts.snap +0 -690
  398. package/tests/views/__snapshots__/blocks.test.ts.snap +0 -462
  399. package/tests/views/__snapshots__/bookmarks.test.ts.snap +0 -379
  400. package/tests/views/__snapshots__/follows.test.ts.snap +0 -798
  401. package/tests/views/__snapshots__/labeler-service.test.ts.snap +0 -233
  402. package/tests/views/__snapshots__/likes.test.ts.snap +0 -124
  403. package/tests/views/__snapshots__/list-feed.test.ts.snap +0 -883
  404. package/tests/views/__snapshots__/lists.test.ts.snap +0 -650
  405. package/tests/views/__snapshots__/mute-lists.test.ts.snap +0 -705
  406. package/tests/views/__snapshots__/mutes.test.ts.snap +0 -353
  407. package/tests/views/__snapshots__/notifications.test.ts.snap +0 -3074
  408. package/tests/views/__snapshots__/posts.test.ts.snap +0 -1019
  409. package/tests/views/__snapshots__/profile.test.ts.snap +0 -811
  410. package/tests/views/__snapshots__/quotes.test.ts.snap +0 -445
  411. package/tests/views/__snapshots__/reposts.test.ts.snap +0 -112
  412. package/tests/views/__snapshots__/starter-packs.test.ts.snap +0 -836
  413. package/tests/views/__snapshots__/thread-v2.test.ts.snap +0 -1298
  414. package/tests/views/__snapshots__/thread.test.ts.snap +0 -2051
  415. package/tests/views/__snapshots__/threadgating.test.ts.snap +0 -189
  416. package/tests/views/__snapshots__/timeline.test.ts.snap +0 -7252
  417. package/tests/views/account-deactivation.test.ts +0 -81
  418. package/tests/views/actor-likes.test.ts +0 -138
  419. package/tests/views/actor-search.test.ts +0 -261
  420. package/tests/views/age-assurance-v2.test.ts +0 -823
  421. package/tests/views/age-assurance.test.ts +0 -479
  422. package/tests/views/author-feed.test.ts +0 -694
  423. package/tests/views/block-lists.test.ts +0 -661
  424. package/tests/views/blocks.test.ts +0 -889
  425. package/tests/views/bookmarks.test.ts +0 -345
  426. package/tests/views/drafts.test.ts +0 -430
  427. package/tests/views/feed-hidden-replies.test.ts +0 -243
  428. package/tests/views/feed-view-post.test.ts +0 -501
  429. package/tests/views/follows.test.ts +0 -372
  430. package/tests/views/get-config.test.ts +0 -64
  431. package/tests/views/get-suggested-onboarding-users.test.ts +0 -193
  432. package/tests/views/get-suggested-starter-packs.test.ts +0 -137
  433. package/tests/views/get-trends.test.ts +0 -141
  434. package/tests/views/internal-actor.test.ts +0 -127
  435. package/tests/views/known-followers.test.ts +0 -193
  436. package/tests/views/labeler-service.test.ts +0 -242
  437. package/tests/views/labels-needs-review.test.ts +0 -316
  438. package/tests/views/labels-takedown.test.ts +0 -247
  439. package/tests/views/likes.test.ts +0 -192
  440. package/tests/views/list-feed.test.ts +0 -195
  441. package/tests/views/lists.test.ts +0 -412
  442. package/tests/views/mute-lists.test.ts +0 -509
  443. package/tests/views/mutes.test.ts +0 -308
  444. package/tests/views/notifications.test.ts +0 -1581
  445. package/tests/views/post-search.test.ts +0 -281
  446. package/tests/views/posts-debug.test.ts +0 -79
  447. package/tests/views/posts.test.ts +0 -427
  448. package/tests/views/profile-debug.test.ts +0 -75
  449. package/tests/views/profile.test.ts +0 -795
  450. package/tests/views/quotes.test.ts +0 -133
  451. package/tests/views/reposts.test.ts +0 -112
  452. package/tests/views/starter-packs.test.ts +0 -395
  453. package/tests/views/suggestions.test.ts +0 -145
  454. package/tests/views/thread-v2.test.ts +0 -2005
  455. package/tests/views/thread.test.ts +0 -637
  456. package/tests/views/threadgating.test.ts +0 -843
  457. package/tests/views/timeline.test.ts +0 -328
  458. package/tests/views/verification.test.ts +0 -296
  459. package/tsconfig.build.json +0 -10
  460. package/tsconfig.build.tsbuildinfo +0 -1
  461. package/tsconfig.json +0 -7
  462. package/tsconfig.tests.json +0 -8
  463. package/vitest.config.ts +0 -10
@@ -1,2005 +0,0 @@
1
- import assert from 'node:assert'
2
- import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'vitest'
3
- import {
4
- AppBskyUnspeccedDefs,
5
- AppBskyUnspeccedGetPostThreadOtherV2,
6
- AppBskyUnspeccedGetPostThreadV2,
7
- AtpAgent,
8
- ids,
9
- } from '@atproto/api'
10
- import { SeedClient, TestNetwork, seedThreadV2 } from '@atproto/dev-env'
11
- import {
12
- ThreadItemValuePost,
13
- ThreadOtherItemValuePost,
14
- } from '../../src/views/threads-v2.js'
15
- import { forSnapshot } from '../_util.js'
16
-
17
- type PostProps = Pick<
18
- AppBskyUnspeccedDefs.ThreadItemPost,
19
- 'moreReplies' | 'opThread'
20
- >
21
- const props = (overrides: Partial<PostProps> = {}): PostProps => ({
22
- moreReplies: 0,
23
- opThread: false,
24
- ...overrides,
25
- })
26
-
27
- type PostPropsHidden = Pick<
28
- AppBskyUnspeccedDefs.ThreadItemPost,
29
- 'hiddenByThreadgate' | 'mutedByViewer'
30
- >
31
- const propsHidden = (
32
- overrides: Partial<PostPropsHidden> = {},
33
- ): PostPropsHidden => ({
34
- hiddenByThreadgate: false,
35
- mutedByViewer: false,
36
- ...overrides,
37
- })
38
-
39
- describe('appview thread views v2', () => {
40
- let network: TestNetwork
41
- let agent: AtpAgent
42
- let labelerDid: string
43
- let sc: SeedClient<TestNetwork>
44
-
45
- beforeAll(async () => {
46
- network = await TestNetwork.create({
47
- bsky: {
48
- maxThreadParents: 15,
49
- threadTagsBumpDown: new Set([seedThreadV2.TAG_BUMP_DOWN]),
50
- threadTagsHide: new Set([seedThreadV2.TAG_HIDE]),
51
- },
52
- dbPostgresSchema: 'bsky_views_thread_v_two',
53
- })
54
- agent = network.bsky.getAgent()
55
- sc = network.getSeedClient()
56
- labelerDid = network.bsky.ctx.cfg.modServiceDid
57
- })
58
-
59
- beforeEach(async () => network.processAll())
60
- afterAll(async () => network?.close())
61
-
62
- describe('not found anchor', () => {
63
- it('returns not found error', async () => {
64
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2({
65
- anchor: 'at://did:plc:123/app.bsky.feed.post/456',
66
- })
67
- const { thread: t } = data
68
-
69
- expect(t).toEqual([
70
- expect.objectContaining({
71
- depth: 0,
72
- value: {
73
- $type: 'app.bsky.unspecced.defs#threadItemNotFound',
74
- },
75
- }),
76
- ])
77
- })
78
- })
79
-
80
- describe('simple thread', () => {
81
- let seed: Awaited<ReturnType<typeof seedThreadV2.simple>>
82
-
83
- beforeAll(async () => {
84
- seed = await seedThreadV2.simple(sc)
85
- await network.processAll()
86
- })
87
-
88
- it('returns thread anchored on root', async () => {
89
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
90
- { anchor: seed.root.ref.uriStr },
91
- {
92
- headers: await network.serviceHeaders(
93
- seed.users.op.did,
94
- ids.AppBskyUnspeccedGetPostThreadV2,
95
- ),
96
- },
97
- )
98
- const { thread: t, hasOtherReplies } = data
99
-
100
- assertPosts(t)
101
- expect(hasOtherReplies).toBe(false)
102
- expect(t).toEqual([
103
- expect.objectContaining({ depth: 0, uri: seed.root.ref.uriStr }),
104
- expect.objectContaining({ depth: 1, uri: seed.r['0'].ref.uriStr }),
105
- expect.objectContaining({ depth: 2, uri: seed.r['0.0'].ref.uriStr }),
106
- expect.objectContaining({ depth: 1, uri: seed.r['1'].ref.uriStr }),
107
- expect.objectContaining({ depth: 1, uri: seed.r['2'].ref.uriStr }),
108
- expect.objectContaining({ depth: 2, uri: seed.r['2.0'].ref.uriStr }),
109
- expect.objectContaining({ depth: 1, uri: seed.r['3'].ref.uriStr }),
110
- ])
111
- expect(forSnapshot(data)).toMatchSnapshot()
112
- })
113
-
114
- it('returns thread anchored on r 0', async () => {
115
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
116
- { anchor: seed.r['0'].ref.uriStr },
117
- {
118
- headers: await network.serviceHeaders(
119
- seed.users.op.did,
120
- ids.AppBskyUnspeccedGetPostThreadV2,
121
- ),
122
- },
123
- )
124
- const { thread: t, hasOtherReplies } = data
125
-
126
- assertPosts(t)
127
- expect(hasOtherReplies).toBe(false)
128
- expect(t).toEqual([
129
- expect.objectContaining({ depth: -1, uri: seed.root.ref.uriStr }),
130
- expect.objectContaining({ depth: 0, uri: seed.r['0'].ref.uriStr }),
131
- expect.objectContaining({ depth: 1, uri: seed.r['0.0'].ref.uriStr }),
132
- ])
133
- expect(forSnapshot(data)).toMatchSnapshot()
134
- })
135
-
136
- it('returns thread anchored on r 0.0', async () => {
137
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
138
- { anchor: seed.r['0.0'].ref.uriStr },
139
- {
140
- headers: await network.serviceHeaders(
141
- seed.users.op.did,
142
- ids.AppBskyUnspeccedGetPostThreadV2,
143
- ),
144
- },
145
- )
146
- const { thread: t, hasOtherReplies } = data
147
-
148
- assertPosts(t)
149
- expect(hasOtherReplies).toBe(false)
150
- expect(t).toEqual([
151
- expect.objectContaining({ depth: -2, uri: seed.root.ref.uriStr }),
152
- expect.objectContaining({ depth: -1, uri: seed.r['0'].ref.uriStr }),
153
- expect.objectContaining({ depth: 0, uri: seed.r['0.0'].ref.uriStr }),
154
- ])
155
- expect(forSnapshot(data)).toMatchSnapshot()
156
- })
157
-
158
- it('returns thread anchored on 1', async () => {
159
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
160
- { anchor: seed.r['1'].ref.uriStr },
161
- {
162
- headers: await network.serviceHeaders(
163
- seed.users.op.did,
164
- ids.AppBskyUnspeccedGetPostThreadV2,
165
- ),
166
- },
167
- )
168
- const { thread: t, hasOtherReplies } = data
169
-
170
- assertPosts(t)
171
- expect(hasOtherReplies).toBe(false)
172
- expect(t).toEqual([
173
- expect.objectContaining({ depth: -1, uri: seed.root.ref.uriStr }),
174
- expect.objectContaining({ depth: 0, uri: seed.r['1'].ref.uriStr }),
175
- ])
176
- expect(forSnapshot(data)).toMatchSnapshot()
177
- })
178
-
179
- it('returns thread anchored on 2', async () => {
180
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
181
- { anchor: seed.r['2'].ref.uriStr },
182
- {
183
- headers: await network.serviceHeaders(
184
- seed.users.op.did,
185
- ids.AppBskyUnspeccedGetPostThreadV2,
186
- ),
187
- },
188
- )
189
- const { thread: t, hasOtherReplies } = data
190
-
191
- assertPosts(t)
192
- expect(hasOtherReplies).toBe(false)
193
- expect(t).toEqual([
194
- expect.objectContaining({ depth: -1, uri: seed.root.ref.uriStr }),
195
- expect.objectContaining({ depth: 0, uri: seed.r['2'].ref.uriStr }),
196
- expect.objectContaining({ depth: 1, uri: seed.r['2.0'].ref.uriStr }),
197
- ])
198
- expect(forSnapshot(data)).toMatchSnapshot()
199
- })
200
-
201
- it('returns thread anchored on 2.0', async () => {
202
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
203
- { anchor: seed.r['2.0'].ref.uriStr },
204
- {
205
- headers: await network.serviceHeaders(
206
- seed.users.op.did,
207
- ids.AppBskyUnspeccedGetPostThreadV2,
208
- ),
209
- },
210
- )
211
- const { thread: t, hasOtherReplies } = data
212
-
213
- assertPosts(t)
214
- expect(hasOtherReplies).toBe(false)
215
- expect(t).toEqual([
216
- expect.objectContaining({ depth: -2, uri: seed.root.ref.uriStr }),
217
- expect.objectContaining({ depth: -1, uri: seed.r['2'].ref.uriStr }),
218
- expect.objectContaining({ depth: 0, uri: seed.r['2.0'].ref.uriStr }),
219
- ])
220
- expect(forSnapshot(data)).toMatchSnapshot()
221
- })
222
-
223
- it('returns thread anchored on 3', async () => {
224
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
225
- { anchor: seed.r['3'].ref.uriStr },
226
- {
227
- headers: await network.serviceHeaders(
228
- seed.users.op.did,
229
- ids.AppBskyUnspeccedGetPostThreadV2,
230
- ),
231
- },
232
- )
233
- const { thread: t, hasOtherReplies } = data
234
-
235
- assertPosts(t)
236
- expect(hasOtherReplies).toBe(false)
237
- expect(t).toEqual([
238
- expect.objectContaining({ depth: -1, uri: seed.root.ref.uriStr }),
239
- expect.objectContaining({ depth: 0, uri: seed.r['3'].ref.uriStr }),
240
- ])
241
- expect(forSnapshot(data)).toMatchSnapshot()
242
- })
243
- })
244
-
245
- describe('long thread', () => {
246
- let seed: Awaited<ReturnType<typeof seedThreadV2.long>>
247
-
248
- beforeAll(async () => {
249
- seed = await seedThreadV2.long(sc)
250
- await network.processAll()
251
- })
252
-
253
- describe('calculating depth', () => {
254
- type Case = {
255
- postKey: string
256
- }
257
-
258
- const cases: Case[] = [
259
- { postKey: 'root' },
260
- { postKey: '0' },
261
- { postKey: '0.0' },
262
- { postKey: '0.0.0' },
263
- { postKey: '0.0.0.0' },
264
- { postKey: '0.0.0.0.0' },
265
- { postKey: '0.0.1' },
266
- { postKey: '1' },
267
- { postKey: '2' },
268
- { postKey: '3' },
269
- { postKey: '4' },
270
- { postKey: '4.0' },
271
- { postKey: '4.0.0' },
272
- { postKey: '4.0.0.0' },
273
- { postKey: '4.0.0.0.0' },
274
- { postKey: '5' },
275
- { postKey: '6' },
276
- { postKey: '7' },
277
- ]
278
-
279
- it.each(cases)(
280
- 'calculates the depths anchored at $postKey',
281
- async ({ postKey }) => {
282
- const post = postKey === 'root' ? seed.root : seed.r[postKey]
283
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
284
- { anchor: post.ref.uriStr },
285
- {
286
- headers: await network.serviceHeaders(
287
- seed.users.op.did,
288
- ids.AppBskyUnspeccedGetPostThreadV2,
289
- ),
290
- },
291
- )
292
- const { thread: t, hasOtherReplies } = data
293
-
294
- assertPosts(t)
295
- expect(hasOtherReplies).toBe(false)
296
- const anchorIndex = t.findIndex((i) => i.uri === post.ref.uriStr)
297
- const anchorPost = t[anchorIndex]
298
-
299
- const parents = t.slice(0, anchorIndex)
300
- const children = t.slice(anchorIndex + 1, t.length)
301
-
302
- parents.forEach((parent) => {
303
- expect(parent.depth).toBeLessThan(0)
304
- })
305
- expect(anchorPost.depth).toEqual(0)
306
- children.forEach((child) => {
307
- expect(child.depth).toBeGreaterThan(0)
308
- })
309
- },
310
- )
311
- })
312
- })
313
-
314
- describe('deep thread', () => {
315
- let seed: Awaited<ReturnType<typeof seedThreadV2.deep>>
316
-
317
- beforeAll(async () => {
318
- seed = await seedThreadV2.deep(sc)
319
- await network.processAll()
320
- })
321
-
322
- describe('above', () => {
323
- it('returns the ancestors above if true (default)', async () => {
324
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
325
- {
326
- anchor: seed.r['0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0'].ref.uriStr,
327
- },
328
- {
329
- headers: await network.serviceHeaders(
330
- seed.users.op.did,
331
- ids.AppBskyUnspeccedGetPostThreadV2,
332
- ),
333
- },
334
- )
335
- const { thread: t, hasOtherReplies } = data
336
-
337
- assertPosts(t)
338
- expect(hasOtherReplies).toBe(false)
339
- expect(t).toHaveLength(16) // anchor + 15 ancestors, as limited by `maxThreadParents`.
340
-
341
- const first = t.at(0)
342
- expect(first!.uri).toBe(seed.r['0.0.0'].ref.uriStr)
343
- expect(first!.value.moreParents).toBe(true)
344
-
345
- const second = t.at(1)
346
- expect(second!.uri).toBe(seed.r['0.0.0.0'].ref.uriStr)
347
- expect(second!.value.moreParents).toBe(false)
348
-
349
- const last = t.at(-1)
350
- expect(last!.uri).toBe(
351
- seed.r['0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0'].ref.uriStr,
352
- )
353
- expect(last!.value.moreParents).toBe(false)
354
- })
355
-
356
- it(`does not return ancestors if false`, async () => {
357
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
358
- {
359
- anchor: seed.r['0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0'].ref.uriStr,
360
- above: false,
361
- },
362
- {
363
- headers: await network.serviceHeaders(
364
- seed.users.op.did,
365
- ids.AppBskyUnspeccedGetPostThreadV2,
366
- ),
367
- },
368
- )
369
- const { thread: t, hasOtherReplies } = data
370
-
371
- assertPosts(t)
372
- expect(hasOtherReplies).toBe(false)
373
- expect(t).toHaveLength(1)
374
-
375
- const first = t.at(0)
376
- expect(first!.uri).toBe(
377
- seed.r['0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0'].ref.uriStr,
378
- )
379
- })
380
- })
381
-
382
- describe('below', () => {
383
- it('limits to the below count', async () => {
384
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
385
- {
386
- anchor: seed.root.ref.uriStr,
387
- below: 10,
388
- },
389
- {
390
- headers: await network.serviceHeaders(
391
- seed.users.op.did,
392
- ids.AppBskyUnspeccedGetPostThreadV2,
393
- ),
394
- },
395
- )
396
- const { thread: t, hasOtherReplies } = data
397
-
398
- assertPosts(t)
399
- expect(hasOtherReplies).toBe(false)
400
- expect(t).toHaveLength(11)
401
- const first = t.at(0)
402
- expect(first!.uri).toBe(seed.root.ref.uriStr)
403
- })
404
-
405
- it(`does not fulfill the below count if there are not enough items in the thread`, async () => {
406
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
407
- {
408
- anchor: seed.r['0.0.0.0.0.0.0.0.0.0.0.0.0.0.0'].ref.uriStr,
409
- above: false,
410
- below: 10,
411
- },
412
- {
413
- headers: await network.serviceHeaders(
414
- seed.users.op.did,
415
- ids.AppBskyUnspeccedGetPostThreadV2,
416
- ),
417
- },
418
- )
419
- const { thread: t, hasOtherReplies } = data
420
-
421
- assertPosts(t)
422
- expect(hasOtherReplies).toBe(false)
423
- expect(t).toHaveLength(4)
424
-
425
- const first = t.at(0)
426
- expect(first!.uri).toBe(
427
- seed.r['0.0.0.0.0.0.0.0.0.0.0.0.0.0.0'].ref.uriStr,
428
- )
429
- })
430
- })
431
- })
432
-
433
- describe('branching factor', () => {
434
- let seed: Awaited<ReturnType<typeof seedThreadV2.branchingFactor>>
435
-
436
- beforeAll(async () => {
437
- seed = await seedThreadV2.branchingFactor(sc)
438
- await network.processAll()
439
- })
440
-
441
- type Case =
442
- | {
443
- branchingFactor: number
444
- sort: AppBskyUnspeccedGetPostThreadV2.QueryParams['sort']
445
- postKeys: string[]
446
- }
447
- | {
448
- branchingFactor: number
449
- sort: AppBskyUnspeccedGetPostThreadV2.QueryParams['sort']
450
- // For higher branching factors it gets too verbose to write all posts.
451
- length: number
452
- }
453
- const cases: Case[] = [
454
- {
455
- branchingFactor: 1,
456
- sort: 'oldest',
457
- postKeys: [
458
- 'root',
459
- '0',
460
- '0.0',
461
- '0.0.0',
462
- '1',
463
- '1.0',
464
- '1.0.0',
465
- '2',
466
- '2.0',
467
- '2.0.0',
468
- '3',
469
- '3.0',
470
- '3.0.0',
471
- ],
472
- },
473
- {
474
- branchingFactor: 1,
475
- sort: 'newest',
476
- postKeys: [
477
- 'root',
478
- '3',
479
- '3.3',
480
- '3.3.3',
481
- '2',
482
- '2.3',
483
- '2.3.3',
484
- '1',
485
- '1.3',
486
- '1.3.3',
487
- '0',
488
- '0.3',
489
- '0.3.3',
490
- ],
491
- },
492
- {
493
- branchingFactor: 2,
494
- sort: 'oldest',
495
- postKeys: [
496
- 'root',
497
- '0',
498
- '0.0',
499
- '0.0.0',
500
- '0.0.1',
501
- '0.1',
502
- '0.1.0',
503
- '0.1.1',
504
- '1',
505
- '1.0',
506
- '1.0.0',
507
- '1.1',
508
- '1.1.0',
509
- '1.1.1',
510
- '2',
511
- '2.0',
512
- '2.0.0',
513
- '2.0.1',
514
- '2.1',
515
- '2.1.0',
516
- '2.1.1',
517
- '3',
518
- '3.0',
519
- '3.0.0',
520
- '3.0.1',
521
- '3.1',
522
- '3.1.0',
523
- '3.1.1',
524
- ],
525
- },
526
- {
527
- branchingFactor: 2,
528
- sort: 'newest',
529
- postKeys: [
530
- 'root',
531
- '3',
532
- '3.3',
533
- '3.3.3',
534
- '3.3.2',
535
- '3.2',
536
- '3.2.3',
537
- '3.2.2',
538
- '2',
539
- '2.3',
540
- '2.3.3',
541
- '2.3.2',
542
- '2.2',
543
- '2.2.3',
544
- '2.2.2',
545
- '1',
546
- '1.3',
547
- '1.3.3',
548
- '1.3.2',
549
- '1.2',
550
- '1.2.3',
551
- '1.2.2',
552
- '0',
553
- '0.3',
554
- '0.3.3',
555
- '0.3.2',
556
- '0.2',
557
- '0.2.3',
558
- '0.2.2',
559
- ],
560
- },
561
- {
562
- branchingFactor: 3,
563
- sort: 'newest',
564
- length: 53,
565
- },
566
- {
567
- branchingFactor: 4,
568
- sort: 'newest',
569
- length: 82,
570
- },
571
- {
572
- branchingFactor: 5,
573
- sort: 'newest',
574
- // The seeds have 1 post with 5 replies, so it is +1 compared to branchingFactor 4.
575
- length: 83,
576
- },
577
- ]
578
-
579
- it.each(cases)(
580
- 'returns all top-level replies and limits nested to branching factor of $branchingFactor when sorting by $sort',
581
- async (args) => {
582
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
583
- {
584
- anchor: seed.root.ref.uriStr,
585
- sort: 'sort' in args ? args.sort : undefined,
586
- branchingFactor: args.branchingFactor,
587
- },
588
- {
589
- headers: await network.serviceHeaders(
590
- seed.users.op.did,
591
- ids.AppBskyUnspeccedGetPostThreadV2,
592
- ),
593
- },
594
- )
595
- const { thread: t, hasOtherReplies } = data
596
-
597
- assertPosts(t)
598
- expect(hasOtherReplies).toBe(false)
599
- if ('length' in args) {
600
- expect(data.thread).toHaveLength(args.length)
601
- } else {
602
- const tUris = t.map((i) => i.uri)
603
- const postUris = args.postKeys.map((k) =>
604
- k === 'root' ? seed.root.ref.uriStr : seed.r[k].ref.uriStr,
605
- )
606
- expect(tUris).toEqual(postUris)
607
- }
608
- },
609
- )
610
- })
611
-
612
- describe('annotate more replies', () => {
613
- let seed: Awaited<ReturnType<typeof seedThreadV2.annotateMoreReplies>>
614
-
615
- beforeAll(async () => {
616
- seed = await seedThreadV2.annotateMoreReplies(sc)
617
- await network.processAll()
618
- })
619
-
620
- it('annotates correctly both in cases of trimmed replies by depth and by branching factor reached', async () => {
621
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
622
- {
623
- anchor: seed.root.ref.uriStr,
624
- below: 4,
625
- branchingFactor: 2,
626
- },
627
- {
628
- headers: await network.serviceHeaders(
629
- seed.users.op.did,
630
- ids.AppBskyUnspeccedGetPostThreadV2,
631
- ),
632
- },
633
- )
634
- const { thread: t, hasOtherReplies } = data
635
-
636
- assertPosts(t)
637
- expect(hasOtherReplies).toBe(false)
638
- expect(t).toEqual([
639
- expect.objectContaining({
640
- uri: seed.root.ref.uriStr,
641
- value: expect.objectContaining(props({ opThread: true })),
642
- }),
643
- expect.objectContaining({
644
- uri: seed.r['0'].ref.uriStr,
645
- value: expect.objectContaining(props()),
646
- }),
647
- expect.objectContaining({
648
- uri: seed.r['0.0'].ref.uriStr,
649
- value: expect.objectContaining(props()),
650
- }),
651
- expect.objectContaining({
652
- uri: seed.r['0.0.0'].ref.uriStr,
653
- value: expect.objectContaining(props()),
654
- }),
655
- expect.objectContaining({
656
- uri: seed.r['0.0.0.0'].ref.uriStr,
657
- value: expect.objectContaining(props({ moreReplies: 5 })),
658
- }),
659
- expect.objectContaining({
660
- uri: seed.r['0.1'].ref.uriStr,
661
- value: expect.objectContaining(props()),
662
- }),
663
- expect.objectContaining({
664
- uri: seed.r['0.1.0'].ref.uriStr,
665
- value: expect.objectContaining(props()),
666
- }),
667
- expect.objectContaining({
668
- uri: seed.r['0.1.0.0'].ref.uriStr,
669
- value: expect.objectContaining(props()),
670
- }),
671
- expect.objectContaining({
672
- uri: seed.r['1'].ref.uriStr,
673
- value: expect.objectContaining(props({ moreReplies: 1 })),
674
- }),
675
- expect.objectContaining({
676
- uri: seed.r['1.0'].ref.uriStr,
677
- value: expect.objectContaining(props({ moreReplies: 3 })),
678
- }),
679
- expect.objectContaining({
680
- uri: seed.r['1.0.0'].ref.uriStr,
681
- value: expect.objectContaining(props()),
682
- }),
683
- expect.objectContaining({
684
- uri: seed.r['1.0.1'].ref.uriStr,
685
- value: expect.objectContaining(props()),
686
- }),
687
- expect.objectContaining({
688
- uri: seed.r['1.1'].ref.uriStr,
689
- value: expect.objectContaining(props()),
690
- }),
691
- expect.objectContaining({
692
- uri: seed.r['1.1.0'].ref.uriStr,
693
- value: expect.objectContaining(props()),
694
- }),
695
- expect.objectContaining({
696
- uri: seed.r['1.1.1'].ref.uriStr,
697
- value: expect.objectContaining(props()),
698
- }),
699
- expect.objectContaining({
700
- uri: seed.r['2'].ref.uriStr,
701
- value: expect.objectContaining(props()),
702
- }),
703
- ])
704
- })
705
- })
706
-
707
- describe(`annotate OP thread`, () => {
708
- let seed: Awaited<ReturnType<typeof seedThreadV2.annotateOP>>
709
-
710
- beforeAll(async () => {
711
- seed = await seedThreadV2.annotateOP(sc)
712
- await network.processAll()
713
- })
714
-
715
- type Case = {
716
- postKey: string
717
- length: number
718
- opThreadPostKeys: string[]
719
- }
720
-
721
- const cases: Case[] = [
722
- {
723
- postKey: 'root',
724
- length: 9,
725
- opThreadPostKeys: ['root', '0', '0.0', '0.0.0', '2'],
726
- },
727
- {
728
- postKey: '0',
729
- length: 4,
730
- opThreadPostKeys: ['root', '0', '0.0', '0.0.0'],
731
- },
732
- {
733
- postKey: '0.0',
734
- length: 4,
735
- opThreadPostKeys: ['root', '0', '0.0', '0.0.0'],
736
- },
737
- {
738
- postKey: '0.0.0',
739
- length: 4,
740
- opThreadPostKeys: ['root', '0', '0.0', '0.0.0'],
741
- },
742
- {
743
- postKey: '1',
744
- length: 3,
745
- opThreadPostKeys: ['root'],
746
- },
747
- {
748
- postKey: '1.0',
749
- length: 3,
750
- opThreadPostKeys: ['root'],
751
- },
752
- {
753
- postKey: '2',
754
- length: 4,
755
- opThreadPostKeys: ['root', '2'],
756
- },
757
- {
758
- postKey: '2.0',
759
- length: 4,
760
- opThreadPostKeys: ['root', '2'],
761
- },
762
- {
763
- postKey: '2.0.0',
764
- length: 4,
765
- opThreadPostKeys: ['root', '2'],
766
- },
767
- ]
768
-
769
- it.each(cases)(
770
- `annotates OP threads correctly anchored at $postKey`,
771
- async ({ postKey, length, opThreadPostKeys: opThreadPosts }) => {
772
- const post = postKey === 'root' ? seed.root : seed.r[postKey]
773
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
774
- { anchor: post.ref.uriStr },
775
- {
776
- headers: await network.serviceHeaders(
777
- seed.users.op.did,
778
- ids.AppBskyUnspeccedGetPostThreadV2,
779
- ),
780
- },
781
- )
782
- const { thread: t, hasOtherReplies } = data
783
-
784
- assertPosts(t)
785
- expect(hasOtherReplies).toBe(false)
786
- const opThreadPostsUris = new Set<string>(
787
- opThreadPosts.map((k) =>
788
- k === 'root' ? seed.root.ref.uriStr : seed.r[k].ref.uriStr,
789
- ),
790
- )
791
-
792
- expect(t).toHaveLength(length)
793
- t.forEach((i) => {
794
- expect(i.value.opThread).toBe(opThreadPostsUris.has(i.uri))
795
- })
796
- },
797
- )
798
- })
799
-
800
- describe('bumping and sorting', () => {
801
- describe('sorting', () => {
802
- let seed: Awaited<ReturnType<typeof seedThreadV2.sort>>
803
-
804
- beforeAll(async () => {
805
- seed = await seedThreadV2.sort(sc)
806
- await network.processAll()
807
- })
808
-
809
- type Case = {
810
- sort: AppBskyUnspeccedGetPostThreadV2.QueryParams['sort']
811
- postKeys: string[]
812
- }
813
-
814
- const cases: Case[] = [
815
- {
816
- sort: 'newest',
817
- postKeys: [
818
- 'root',
819
- '2',
820
- '2.2',
821
- '2.1',
822
- '2.0',
823
- '1',
824
- '1.2',
825
- '1.1',
826
- '1.0',
827
- '0',
828
- '0.2',
829
- '0.1',
830
- '0.0',
831
- ],
832
- },
833
- {
834
- sort: 'oldest',
835
- postKeys: [
836
- 'root',
837
- '0',
838
- '0.0',
839
- '0.1',
840
- '0.2',
841
- '1',
842
- '1.0',
843
- '1.1',
844
- '1.2',
845
- '2',
846
- '2.0',
847
- '2.1',
848
- '2.2',
849
- ],
850
- },
851
- {
852
- sort: 'top',
853
- postKeys: [
854
- 'root',
855
- '1',
856
- '1.1',
857
- '1.0',
858
- '1.2',
859
- '2',
860
- '2.0',
861
- '2.1',
862
- '2.2',
863
- '0',
864
- '0.2',
865
- '0.1',
866
- '0.0',
867
- ],
868
- },
869
- ]
870
-
871
- it.each(cases)(
872
- 'sorts by $sort in all levels',
873
- async ({ sort: sort, postKeys }) => {
874
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
875
- {
876
- anchor: seed.root.ref.uriStr,
877
- sort,
878
- },
879
- {
880
- headers: await network.serviceHeaders(
881
- seed.users.op.did,
882
- ids.AppBskyUnspeccedGetPostThreadV2,
883
- ),
884
- },
885
- )
886
- const { thread: t, hasOtherReplies } = data
887
-
888
- assertPosts(t)
889
- expect(hasOtherReplies).toBe(false)
890
- const tUris = t.map((i) => i.uri)
891
- const postUris = postKeys.map((k) =>
892
- k === 'root' ? seed.root.ref.uriStr : seed.r[k].ref.uriStr,
893
- )
894
- expect(tUris).toEqual(postUris)
895
- },
896
- )
897
- })
898
-
899
- describe('bumping', () => {
900
- describe('sorting within bumped post groups', () => {
901
- let seed: Awaited<ReturnType<typeof seedThreadV2.bumpGroupSorting>>
902
-
903
- beforeAll(async () => {
904
- seed = await seedThreadV2.bumpGroupSorting(sc)
905
- await network.processAll()
906
- })
907
-
908
- type Case = {
909
- sort: AppBskyUnspeccedGetPostThreadV2.QueryParams['sort']
910
- postKeys: string[]
911
- }
912
-
913
- const cases: Case[] = [
914
- {
915
- sort: 'newest',
916
- postKeys: ['root', '5', '3', '1', '7', '4', '0', '6', '2'],
917
- },
918
- {
919
- sort: 'oldest',
920
- postKeys: ['root', '1', '3', '5', '0', '4', '7', '2', '6'],
921
- },
922
- ]
923
-
924
- it.each(cases)(
925
- 'sorts by $sort inside each bumped group',
926
- async ({ sort: sort, postKeys }) => {
927
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
928
- {
929
- anchor: seed.root.ref.uriStr,
930
- sort,
931
- },
932
- {
933
- headers: await network.serviceHeaders(
934
- seed.users.viewer.did,
935
- ids.AppBskyUnspeccedGetPostThreadV2,
936
- ),
937
- },
938
- )
939
- const { thread: t, hasOtherReplies } = data
940
-
941
- assertPosts(t)
942
- expect(hasOtherReplies).toBe(false)
943
- const tUris = t.map((i) => i.uri)
944
- const postUris = postKeys.map((k) =>
945
- k === 'root' ? seed.root.ref.uriStr : seed.r[k].ref.uriStr,
946
- )
947
- expect(tUris).toEqual(postUris)
948
- },
949
- )
950
- })
951
-
952
- describe('OP and viewer', () => {
953
- let seed: Awaited<ReturnType<typeof seedThreadV2.bumpOpAndViewer>>
954
-
955
- beforeAll(async () => {
956
- seed = await seedThreadV2.bumpOpAndViewer(sc)
957
- await network.processAll()
958
- })
959
-
960
- type Case = {
961
- sort: AppBskyUnspeccedGetPostThreadV2.QueryParams['sort']
962
- postKeys: string[]
963
- }
964
-
965
- const cases: Case[] = [
966
- {
967
- sort: 'newest',
968
- postKeys: [
969
- 'root',
970
- '3', // op
971
- '3.2', // op
972
- '3.0', // viewer
973
- '3.4',
974
- '3.3',
975
- '3.1',
976
- '4', // viewer
977
- '4.2', // op
978
- '4.3', // viewer
979
- '4.4',
980
- '4.1',
981
- '4.0',
982
- '2',
983
- '2.2', // op
984
- '2.0', // viewer
985
- '2.4',
986
- '2.3',
987
- '2.1',
988
- '1',
989
- '1.2', // op
990
- '1.3', // viewer
991
- '1.4',
992
- '1.1',
993
- '1.0',
994
- '0',
995
- '0.4', // op
996
- '0.3', // viewer
997
- '0.2',
998
- '0.1',
999
- '0.0',
1000
- ],
1001
- },
1002
- {
1003
- sort: 'oldest',
1004
- postKeys: [
1005
- 'root',
1006
- '3', // op
1007
- '3.2', // op
1008
- '3.0', // viewer
1009
- '3.1',
1010
- '3.3',
1011
- '3.4',
1012
- '4', // viewer
1013
- '4.2', // op
1014
- '4.3', // viewer
1015
- '4.0',
1016
- '4.1',
1017
- '4.4',
1018
- '0',
1019
- '0.4', // op
1020
- '0.3', // viewer
1021
- '0.0',
1022
- '0.1',
1023
- '0.2',
1024
- '1',
1025
- '1.2', // op
1026
- '1.3', // viewer
1027
- '1.0',
1028
- '1.1',
1029
- '1.4',
1030
- '2',
1031
- '2.2', // op
1032
- '2.0', // viewer
1033
- '2.1',
1034
- '2.3',
1035
- '2.4',
1036
- ],
1037
- },
1038
- {
1039
- sort: 'top',
1040
- postKeys: [
1041
- 'root',
1042
- '3', // op
1043
- '3.2', // op
1044
- '3.0', // viewer
1045
- '3.4',
1046
- '3.3',
1047
- '3.1',
1048
- '4', // viewer
1049
- '4.2', // op
1050
- '4.3', // viewer
1051
- '4.1',
1052
- '4.0',
1053
- '4.4',
1054
- '1',
1055
- '1.2', // op
1056
- '1.3', // viewer
1057
- '1.1',
1058
- '1.0',
1059
- '1.4',
1060
- '2',
1061
- '2.2', // op
1062
- '2.0', // viewer
1063
- '2.1',
1064
- '2.4',
1065
- '2.3',
1066
- '0',
1067
- '0.4', // op
1068
- '0.3', // viewer
1069
- '0.2',
1070
- '0.1',
1071
- '0.0',
1072
- ],
1073
- },
1074
- ]
1075
-
1076
- it.each(cases)(
1077
- 'bumps up OP and viewer and sorts by $sort in all levels',
1078
- async ({ sort: sort, postKeys }) => {
1079
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
1080
- {
1081
- anchor: seed.root.ref.uriStr,
1082
- sort,
1083
- },
1084
- {
1085
- headers: await network.serviceHeaders(
1086
- seed.users.viewer.did,
1087
- ids.AppBskyUnspeccedGetPostThreadV2,
1088
- ),
1089
- },
1090
- )
1091
- const { thread: t, hasOtherReplies } = data
1092
-
1093
- assertPosts(t)
1094
- expect(hasOtherReplies).toBe(false)
1095
- const tUris = t.map((i) => i.uri)
1096
- const postUris = postKeys.map((k) =>
1097
- k === 'root' ? seed.root.ref.uriStr : seed.r[k].ref.uriStr,
1098
- )
1099
- expect(tUris).toEqual(postUris)
1100
- },
1101
- )
1102
- })
1103
-
1104
- describe('followers', () => {
1105
- let seed: Awaited<ReturnType<typeof seedThreadV2.bumpFollows>>
1106
-
1107
- beforeAll(async () => {
1108
- seed = await seedThreadV2.bumpFollows(sc)
1109
- await network.processAll()
1110
- })
1111
-
1112
- const threadForPostAndViewer = async (post: string, viewer: string) => {
1113
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
1114
- {
1115
- anchor: post,
1116
- sort: 'newest',
1117
- },
1118
- {
1119
- headers: await network.serviceHeaders(
1120
- viewer,
1121
- ids.AppBskyUnspeccedGetPostThreadV2,
1122
- ),
1123
- },
1124
- )
1125
- const { thread: t, hasOtherReplies } = data
1126
-
1127
- assertPosts(t)
1128
- expect(hasOtherReplies).toBe(false)
1129
- return t
1130
- }
1131
-
1132
- it('bumps up followed users', async () => {
1133
- const t1 = await threadForPostAndViewer(
1134
- seed.root.ref.uriStr,
1135
- seed.users.viewerF.did,
1136
- )
1137
- expect(t1).toEqual([
1138
- expect.objectContaining({ uri: seed.root.ref.uriStr }), // root
1139
- expect.objectContaining({ uri: seed.r['3'].ref.uriStr }), // op reply
1140
- expect.objectContaining({ uri: seed.r['4'].ref.uriStr }), // viewer reply
1141
- expect.objectContaining({ uri: seed.r['1'].ref.uriStr }), // newest followed reply
1142
- expect.objectContaining({ uri: seed.r['0'].ref.uriStr }), // oldest followed reply
1143
- expect.objectContaining({ uri: seed.r['5'].ref.uriStr }), // newest non-followed reply
1144
- expect.objectContaining({ uri: seed.r['2'].ref.uriStr }), // oldest non-followed reply
1145
- ])
1146
-
1147
- const t2 = await threadForPostAndViewer(
1148
- seed.root.ref.uriStr,
1149
- seed.users.viewerNoF.did,
1150
- )
1151
- expect(t2).toEqual([
1152
- expect.objectContaining({ uri: seed.root.ref.uriStr }), // root
1153
- expect.objectContaining({ uri: seed.r['3'].ref.uriStr }), // op reply
1154
- expect.objectContaining({ uri: seed.r['5'].ref.uriStr }), // viewer reply
1155
- // newest to oldest
1156
- expect.objectContaining({ uri: seed.r['4'].ref.uriStr }),
1157
- expect.objectContaining({ uri: seed.r['2'].ref.uriStr }),
1158
- expect.objectContaining({ uri: seed.r['1'].ref.uriStr }),
1159
- expect.objectContaining({ uri: seed.r['0'].ref.uriStr }),
1160
- ])
1161
- })
1162
- })
1163
- })
1164
- })
1165
-
1166
- describe(`blocks, deletions, no-unauthenticated`, () => {
1167
- let seed: Awaited<ReturnType<typeof seedThreadV2.blockDeletionAuth>>
1168
-
1169
- beforeAll(async () => {
1170
- seed = await seedThreadV2.blockDeletionAuth(sc, labelerDid)
1171
- await network.processAll()
1172
- })
1173
-
1174
- describe(`1p blocks`, () => {
1175
- it(`blocked reply is omitted from replies`, async () => {
1176
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
1177
- { anchor: seed.root.ref.uriStr },
1178
- {
1179
- headers: await network.serviceHeaders(
1180
- // Use `blocked`, who was blocked by `blocker`, author of '0'.
1181
- seed.users.blocked.did,
1182
- ids.AppBskyUnspeccedGetPostThreadV2,
1183
- ),
1184
- },
1185
- )
1186
- const { thread: t, hasOtherReplies } = data
1187
-
1188
- assertPosts(t)
1189
- expect(hasOtherReplies).toBe(false)
1190
- expect(t).toEqual([
1191
- expect.objectContaining({ uri: seed.root.ref.uriStr }),
1192
- expect.objectContaining({ uri: seed.r['3'].ref.uriStr }),
1193
- expect.objectContaining({ uri: seed.r['3.0'].ref.uriStr }),
1194
- expect.objectContaining({ uri: seed.r['3.0.0'].ref.uriStr }),
1195
- ])
1196
- })
1197
-
1198
- it(`blocked anchor returns lone blocked view`, async () => {
1199
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
1200
- { anchor: seed.r['0'].ref.uriStr },
1201
- {
1202
- headers: await network.serviceHeaders(
1203
- // Use `blocked`, who was blocked by `blocker`, author of '0'.
1204
- seed.users.blocked.did,
1205
- ids.AppBskyUnspeccedGetPostThreadV2,
1206
- ),
1207
- },
1208
- )
1209
- const { thread: t, hasOtherReplies } = data
1210
-
1211
- expect(hasOtherReplies).toBe(false)
1212
- expect(t).toEqual([
1213
- expect.objectContaining({
1214
- uri: seed.r['0'].ref.uriStr,
1215
- depth: 0,
1216
- value: expect.objectContaining({
1217
- $type: 'app.bsky.unspecced.defs#threadItemBlocked',
1218
- }),
1219
- }),
1220
- ])
1221
- })
1222
-
1223
- it(`blocked parent is replaced by blocked view`, async () => {
1224
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
1225
- { anchor: seed.r['0.0'].ref.uriStr },
1226
- {
1227
- headers: await network.serviceHeaders(
1228
- // Use `blocked`, who was blocked by `blocker`, author of '0'.
1229
- seed.users.blocked.did,
1230
- ids.AppBskyUnspeccedGetPostThreadV2,
1231
- ),
1232
- },
1233
- )
1234
- const { thread: t, hasOtherReplies } = data
1235
-
1236
- expect(hasOtherReplies).toBe(false)
1237
- expect(t).toEqual([
1238
- expect.objectContaining({
1239
- uri: seed.r['0'].ref.uriStr,
1240
- depth: -1,
1241
- value: expect.objectContaining({
1242
- $type: 'app.bsky.unspecced.defs#threadItemBlocked',
1243
- }),
1244
- }),
1245
- expect.objectContaining({
1246
- uri: seed.r['0.0'].ref.uriStr,
1247
- depth: 0,
1248
- value: expect.objectContaining({
1249
- $type: 'app.bsky.unspecced.defs#threadItemPost',
1250
- }),
1251
- }),
1252
- ])
1253
- })
1254
- })
1255
-
1256
- describe(`3p blocks`, () => {
1257
- it(`blocked reply is omitted from replies`, async () => {
1258
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
1259
- { anchor: seed.root.ref.uriStr },
1260
- {
1261
- headers: await network.serviceHeaders(
1262
- // Use `alice` who is a 3rd party between `op` and `opBlocked`.
1263
- seed.users.alice.did,
1264
- ids.AppBskyUnspeccedGetPostThreadV2,
1265
- ),
1266
- },
1267
- )
1268
- const { thread: t, hasOtherReplies } = data
1269
-
1270
- expect(hasOtherReplies).toBe(false)
1271
- assertPosts(t)
1272
- expect(t).toEqual([
1273
- expect.objectContaining({ uri: seed.root.ref.uriStr }),
1274
- expect.objectContaining({ uri: seed.r['0'].ref.uriStr }),
1275
- expect.objectContaining({ uri: seed.r['0.0'].ref.uriStr }),
1276
- expect.objectContaining({ uri: seed.r['3'].ref.uriStr }),
1277
- expect.objectContaining({ uri: seed.r['3.0'].ref.uriStr }),
1278
- expect.objectContaining({ uri: seed.r['3.0.0'].ref.uriStr }),
1279
- ])
1280
- })
1281
-
1282
- it(`blocked anchor returns post with blocked parent and non-blocked descendants`, async () => {
1283
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
1284
- { anchor: seed.r['1'].ref.uriStr },
1285
- {
1286
- headers: await network.serviceHeaders(
1287
- // Use `alice` who is a 3rd party between `op` and `opBlocked`.
1288
- seed.users.alice.did,
1289
- ids.AppBskyUnspeccedGetPostThreadV2,
1290
- ),
1291
- },
1292
- )
1293
- const { thread: t, hasOtherReplies } = data
1294
-
1295
- expect(hasOtherReplies).toBe(false)
1296
- expect(t).toEqual([
1297
- expect.objectContaining({
1298
- uri: seed.root.ref.uriStr,
1299
- depth: -1,
1300
- value: expect.objectContaining({
1301
- $type: 'app.bsky.unspecced.defs#threadItemBlocked',
1302
- }),
1303
- }),
1304
- expect.objectContaining({
1305
- uri: seed.r['1'].ref.uriStr,
1306
- depth: 0,
1307
- value: expect.objectContaining({
1308
- $type: 'app.bsky.unspecced.defs#threadItemPost',
1309
- }),
1310
- }),
1311
- // 1.0 is blocked, but 1.1 is not
1312
- expect.objectContaining({
1313
- uri: seed.r['1.1'].ref.uriStr,
1314
- depth: 1,
1315
- value: expect.objectContaining({
1316
- $type: 'app.bsky.unspecced.defs#threadItemPost',
1317
- }),
1318
- }),
1319
- ])
1320
- })
1321
-
1322
- it(`blocked parent is replaced by blocked view`, async () => {
1323
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
1324
- { anchor: seed.r['1.0'].ref.uriStr },
1325
- {
1326
- headers: await network.serviceHeaders(
1327
- // Use `alice` who is a 3rd party between `op` and `opBlocked`.
1328
- seed.users.alice.did,
1329
- ids.AppBskyUnspeccedGetPostThreadV2,
1330
- ),
1331
- },
1332
- )
1333
- const { thread: t, hasOtherReplies } = data
1334
-
1335
- expect(hasOtherReplies).toBe(false)
1336
- expect(t).toEqual([
1337
- expect.objectContaining({
1338
- uri: seed.r['1'].ref.uriStr,
1339
- depth: -1,
1340
- value: expect.objectContaining({
1341
- $type: 'app.bsky.unspecced.defs#threadItemBlocked',
1342
- }),
1343
- }),
1344
- expect.objectContaining({
1345
- uri: seed.r['1.0'].ref.uriStr,
1346
- depth: 0,
1347
- value: expect.objectContaining({
1348
- $type: 'app.bsky.unspecced.defs#threadItemPost',
1349
- }),
1350
- }),
1351
- ])
1352
- })
1353
-
1354
- it(`blocked root is replaced by blocked view`, async () => {
1355
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
1356
- { anchor: seed.r['1.1'].ref.uriStr },
1357
- {
1358
- headers: await network.serviceHeaders(
1359
- // Use `alice` who is a 3rd party between `op` and `opBlocked`.
1360
- seed.users.alice.did,
1361
- ids.AppBskyUnspeccedGetPostThreadV2,
1362
- ),
1363
- },
1364
- )
1365
- const { thread: t, hasOtherReplies } = data
1366
-
1367
- expect(hasOtherReplies).toBe(false)
1368
- expect(t).toEqual([
1369
- expect.objectContaining({
1370
- uri: seed.root.ref.uriStr,
1371
- depth: -2,
1372
- value: expect.objectContaining({
1373
- $type: 'app.bsky.unspecced.defs#threadItemBlocked',
1374
- }),
1375
- }),
1376
- expect.objectContaining({
1377
- uri: seed.r['1'].ref.uriStr,
1378
- depth: -1,
1379
- value: expect.objectContaining({
1380
- $type: 'app.bsky.unspecced.defs#threadItemPost',
1381
- }),
1382
- }),
1383
- expect.objectContaining({
1384
- uri: seed.r['1.1'].ref.uriStr,
1385
- depth: 0,
1386
- value: expect.objectContaining({
1387
- $type: 'app.bsky.unspecced.defs#threadItemPost',
1388
- }),
1389
- }),
1390
- ])
1391
- })
1392
- })
1393
-
1394
- describe(`deleted posts`, () => {
1395
- it(`deleted reply is omitted from replies`, async () => {
1396
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
1397
- { anchor: seed.root.ref.uriStr },
1398
- {
1399
- headers: await network.serviceHeaders(
1400
- seed.users.op.did,
1401
- ids.AppBskyUnspeccedGetPostThreadV2,
1402
- ),
1403
- },
1404
- )
1405
- const { thread: t, hasOtherReplies } = data
1406
-
1407
- expect(hasOtherReplies).toBe(false)
1408
- assertPosts(t)
1409
- expect(t).toEqual([
1410
- expect.objectContaining({ uri: seed.root.ref.uriStr }),
1411
- expect.objectContaining({ uri: seed.r['0'].ref.uriStr }),
1412
- expect.objectContaining({ uri: seed.r['0.0'].ref.uriStr }),
1413
- expect.objectContaining({ uri: seed.r['3'].ref.uriStr }),
1414
- expect.objectContaining({ uri: seed.r['3.0'].ref.uriStr }),
1415
- expect.objectContaining({ uri: seed.r['3.0.0'].ref.uriStr }),
1416
- ])
1417
- })
1418
-
1419
- it(`deleted parent is replaced by not found view`, async () => {
1420
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
1421
- { anchor: seed.r['2.0'].ref.uriStr },
1422
- {
1423
- headers: await network.serviceHeaders(
1424
- seed.users.op.did,
1425
- ids.AppBskyUnspeccedGetPostThreadV2,
1426
- ),
1427
- },
1428
- )
1429
- const { thread: t, hasOtherReplies } = data
1430
-
1431
- expect(hasOtherReplies).toBe(false)
1432
- expect(t).toEqual([
1433
- expect.objectContaining({
1434
- uri: seed.r['2'].ref.uriStr,
1435
- depth: -1,
1436
- value: expect.objectContaining({
1437
- $type: 'app.bsky.unspecced.defs#threadItemNotFound',
1438
- }),
1439
- }),
1440
- expect.objectContaining({
1441
- uri: seed.r['2.0'].ref.uriStr,
1442
- depth: 0,
1443
- value: expect.objectContaining({
1444
- $type: 'app.bsky.unspecced.defs#threadItemPost',
1445
- }),
1446
- }),
1447
- ])
1448
- })
1449
- })
1450
-
1451
- describe('no-unauthenticated', () => {
1452
- it(`no-unauthenticated reply is omitted from replies`, async () => {
1453
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
1454
- { anchor: seed.root.ref.uriStr },
1455
- {
1456
- headers: {
1457
- 'atproto-accept-labelers': `${labelerDid}`,
1458
- },
1459
- },
1460
- )
1461
- const { thread: t, hasOtherReplies } = data
1462
-
1463
- expect(hasOtherReplies).toBe(false)
1464
- expect(t).toEqual([
1465
- expect.objectContaining({
1466
- uri: seed.root.ref.uriStr,
1467
- depth: 0,
1468
- value: expect.objectContaining({
1469
- $type: 'app.bsky.unspecced.defs#threadItemPost',
1470
- }),
1471
- }),
1472
- expect.objectContaining({
1473
- uri: seed.r['0'].ref.uriStr,
1474
- depth: 1,
1475
- value: expect.objectContaining({
1476
- $type: 'app.bsky.unspecced.defs#threadItemPost',
1477
- }),
1478
- }),
1479
- expect.objectContaining({
1480
- uri: seed.r['0.0'].ref.uriStr,
1481
- depth: 2,
1482
- value: expect.objectContaining({
1483
- $type: 'app.bsky.unspecced.defs#threadItemPost',
1484
- }),
1485
- }),
1486
- ])
1487
- })
1488
-
1489
- it(`no-unauthenticated anchor returns no-unauthenticated view without breaking the parent chain`, async () => {
1490
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
1491
- { anchor: seed.r['3'].ref.uriStr },
1492
- {
1493
- headers: {
1494
- 'atproto-accept-labelers': `${labelerDid}`,
1495
- },
1496
- },
1497
- )
1498
- const { thread: t, hasOtherReplies } = data
1499
-
1500
- expect(hasOtherReplies).toBe(false)
1501
- expect(t).toEqual([
1502
- expect.objectContaining({
1503
- uri: seed.root.ref.uriStr,
1504
- depth: -1,
1505
- value: expect.objectContaining({
1506
- $type: 'app.bsky.unspecced.defs#threadItemPost',
1507
- }),
1508
- }),
1509
- expect.objectContaining({
1510
- uri: seed.r['3'].ref.uriStr,
1511
- depth: 0,
1512
- value: expect.objectContaining({
1513
- $type: 'app.bsky.unspecced.defs#threadItemNoUnauthenticated',
1514
- }),
1515
- }),
1516
- ])
1517
- })
1518
-
1519
- it(`no-unauthenticated parent is replaced by no-unauthenticated view without breaking the parent chain`, async () => {
1520
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
1521
- { anchor: seed.r['3.0.0'].ref.uriStr },
1522
- {
1523
- headers: {
1524
- 'atproto-accept-labelers': `${labelerDid}`,
1525
- },
1526
- },
1527
- )
1528
- const { thread: t, hasOtherReplies } = data
1529
-
1530
- expect(hasOtherReplies).toBe(false)
1531
- expect(t).toEqual([
1532
- expect.objectContaining({
1533
- uri: seed.root.ref.uriStr,
1534
- depth: -3,
1535
- value: expect.objectContaining({
1536
- $type: 'app.bsky.unspecced.defs#threadItemPost',
1537
- }),
1538
- }),
1539
- expect.objectContaining({
1540
- uri: seed.r['3'].ref.uriStr,
1541
- depth: -2,
1542
- value: expect.objectContaining({
1543
- $type: 'app.bsky.unspecced.defs#threadItemNoUnauthenticated',
1544
- }),
1545
- }),
1546
- expect.objectContaining({
1547
- uri: seed.r['3.0'].ref.uriStr,
1548
- depth: -1,
1549
- value: expect.objectContaining({
1550
- $type: 'app.bsky.unspecced.defs#threadItemNoUnauthenticated',
1551
- }),
1552
- }),
1553
- expect.objectContaining({
1554
- uri: seed.r['3.0.0'].ref.uriStr,
1555
- depth: 0,
1556
- value: expect.objectContaining({
1557
- $type: 'app.bsky.unspecced.defs#threadItemPost',
1558
- }),
1559
- }),
1560
- ])
1561
- })
1562
- })
1563
- })
1564
-
1565
- describe(`mutes`, () => {
1566
- let seed: Awaited<ReturnType<typeof seedThreadV2.mutes>>
1567
-
1568
- beforeAll(async () => {
1569
- seed = await seedThreadV2.mutes(sc)
1570
- await network.processAll()
1571
- })
1572
-
1573
- describe('omitting muted replies', () => {
1574
- it(`muted reply is omitted in top-level replies and in nested replies`, async () => {
1575
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
1576
- { anchor: seed.root.ref.uriStr },
1577
- {
1578
- headers: await network.serviceHeaders(
1579
- // Fetching as `op` mutes `opMuted`.
1580
- seed.users.op.did,
1581
- ids.AppBskyUnspeccedGetPostThreadV2,
1582
- ),
1583
- },
1584
- )
1585
- const { thread: t, hasOtherReplies } = data
1586
-
1587
- expect(hasOtherReplies).toBe(true)
1588
- assertPosts(t)
1589
- expect(t).toEqual([
1590
- expect.objectContaining({
1591
- uri: seed.root.ref.uriStr,
1592
- value: expect.objectContaining(props({ opThread: true })),
1593
- }),
1594
- expect.objectContaining({
1595
- uri: seed.r['1'].ref.uriStr,
1596
- value: expect.objectContaining(props()),
1597
- }),
1598
- // 1.0 is a nested muted reply, so it is omitted.
1599
- expect.objectContaining({
1600
- uri: seed.r['1.1'].ref.uriStr,
1601
- value: expect.objectContaining(props()),
1602
- }),
1603
- ])
1604
- })
1605
-
1606
- it(`top-level muted replies are returned when fetching hidden, sorted by newest`, async () => {
1607
- const { data } = await agent.app.bsky.unspecced.getPostThreadOtherV2(
1608
- { anchor: seed.root.ref.uriStr },
1609
- {
1610
- headers: await network.serviceHeaders(
1611
- // Fetching as `op` mutes `opMuted`.
1612
- seed.users.op.did,
1613
- ids.AppBskyUnspeccedGetPostThreadOtherV2,
1614
- ),
1615
- },
1616
- )
1617
- const { thread: t } = data
1618
-
1619
- assertHiddenPosts(t)
1620
- expect(t).toEqual([
1621
- expect.objectContaining({
1622
- uri: seed.r['0'].ref.uriStr,
1623
- value: expect.objectContaining(
1624
- propsHidden({ mutedByViewer: true }),
1625
- ),
1626
- }),
1627
- // No nested replies for hidden.
1628
- ])
1629
- })
1630
- })
1631
-
1632
- describe('OP mutes', () => {
1633
- it(`mutes by OP don't mute for 3p`, async () => {
1634
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
1635
- { anchor: seed.root.ref.uriStr },
1636
- {
1637
- headers: await network.serviceHeaders(
1638
- // Fetching as `muter` mutes `muted`.
1639
- seed.users.muter.did,
1640
- ids.AppBskyUnspeccedGetPostThreadV2,
1641
- ),
1642
- },
1643
- )
1644
- const { thread: t, hasOtherReplies } = data
1645
-
1646
- expect(hasOtherReplies).toBe(true)
1647
- assertPosts(t)
1648
- expect(t).toEqual([
1649
- expect.objectContaining({
1650
- uri: seed.root.ref.uriStr,
1651
- value: expect.objectContaining(props({ opThread: true })),
1652
- }),
1653
- expect.objectContaining({
1654
- uri: seed.r['0'].ref.uriStr,
1655
- value: expect.objectContaining(props()),
1656
- }),
1657
- expect.objectContaining({
1658
- uri: seed.r['0.0'].ref.uriStr,
1659
- value: expect.objectContaining(props()),
1660
- }),
1661
- // 0.1 is a nested muted reply, so it is omitted.
1662
- ])
1663
- })
1664
-
1665
- it(`fetches hidden replies includes own mutes, not OP mutes, sorted by newest`, async () => {
1666
- const { data } = await agent.app.bsky.unspecced.getPostThreadOtherV2(
1667
- { anchor: seed.root.ref.uriStr },
1668
- {
1669
- headers: await network.serviceHeaders(
1670
- // Fetching as `muter` mutes `muted`.
1671
- seed.users.muter.did,
1672
- ids.AppBskyUnspeccedGetPostThreadOtherV2,
1673
- ),
1674
- },
1675
- )
1676
- const { thread: t } = data
1677
-
1678
- assertHiddenPosts(t)
1679
- expect(t).toEqual([
1680
- expect.objectContaining({
1681
- uri: seed.r['1'].ref.uriStr,
1682
- value: expect.objectContaining(
1683
- propsHidden({ mutedByViewer: true }),
1684
- ),
1685
- }),
1686
- // No nested replies for hidden.
1687
- ])
1688
- })
1689
-
1690
- it(`mutes by OP don't affect the muted user`, async () => {
1691
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
1692
- { anchor: seed.root.ref.uriStr },
1693
- {
1694
- headers: await network.serviceHeaders(
1695
- seed.users.opMuted.did,
1696
- ids.AppBskyUnspeccedGetPostThreadV2,
1697
- ),
1698
- },
1699
- )
1700
- const { thread: t, hasOtherReplies } = data
1701
-
1702
- expect(hasOtherReplies).toBe(false)
1703
- assertPosts(t)
1704
- // No muted posts by `opMuted`, gets the full thread.
1705
- expect(t.length).toBe(1 + Object.keys(seed.r).length) // root + replies
1706
- })
1707
- })
1708
- })
1709
-
1710
- describe(`threadgated`, () => {
1711
- let seed: Awaited<ReturnType<typeof seedThreadV2.threadgated>>
1712
-
1713
- beforeAll(async () => {
1714
- seed = await seedThreadV2.threadgated(sc)
1715
- await network.processAll()
1716
- })
1717
-
1718
- it(`threadgated reply is omitted in top-level replies and in nested replies`, async () => {
1719
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
1720
- { anchor: seed.root.ref.uriStr },
1721
- {
1722
- headers: await network.serviceHeaders(
1723
- seed.users.op.did,
1724
- ids.AppBskyUnspeccedGetPostThreadV2,
1725
- ),
1726
- },
1727
- )
1728
- const { thread: t, hasOtherReplies } = data
1729
-
1730
- expect(hasOtherReplies).toBe(true)
1731
- assertPosts(t)
1732
- expect(t).toEqual([
1733
- expect.objectContaining({
1734
- uri: seed.root.ref.uriStr,
1735
- value: expect.objectContaining(props({ opThread: true })),
1736
- }),
1737
- expect.objectContaining({
1738
- uri: seed.r['2'].ref.uriStr,
1739
- value: expect.objectContaining(props()),
1740
- }),
1741
- // OP reply bumped up.
1742
- expect.objectContaining({
1743
- uri: seed.r['2.2'].ref.uriStr,
1744
- value: expect.objectContaining(props()),
1745
- }),
1746
- expect.objectContaining({
1747
- uri: seed.r['2.0'].ref.uriStr,
1748
- value: expect.objectContaining(props()),
1749
- }),
1750
- // 2.1 is a nested hidden reply, so it is omitted.
1751
- ])
1752
- })
1753
-
1754
- it(`top-level threadgated replies are returned to OP when fetching hidden, sorted by newest`, async () => {
1755
- const { data } = await agent.app.bsky.unspecced.getPostThreadOtherV2(
1756
- { anchor: seed.root.ref.uriStr },
1757
- {
1758
- headers: await network.serviceHeaders(
1759
- seed.users.op.did,
1760
- ids.AppBskyUnspeccedGetPostThreadOtherV2,
1761
- ),
1762
- },
1763
- )
1764
- const { thread: t } = data
1765
-
1766
- assertHiddenPosts(t)
1767
- expect(t).toEqual([
1768
- expect.objectContaining({
1769
- uri: seed.r['1'].ref.uriStr,
1770
- value: expect.objectContaining(
1771
- propsHidden({ hiddenByThreadgate: true }),
1772
- ),
1773
- }),
1774
- // No nested replies for hidden.
1775
-
1776
- // Mutes come after hidden.
1777
- expect.objectContaining({
1778
- uri: seed.r['0'].ref.uriStr,
1779
- value: expect.objectContaining(propsHidden({ mutedByViewer: true })),
1780
- }),
1781
- ])
1782
- })
1783
-
1784
- it(`author of hidden reply does not see it as hidden`, async () => {
1785
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
1786
- { anchor: seed.root.ref.uriStr },
1787
- {
1788
- headers: await network.serviceHeaders(
1789
- // `alice` does not get its own reply as hidden.
1790
- seed.users.alice.did,
1791
- ids.AppBskyUnspeccedGetPostThreadV2,
1792
- ),
1793
- },
1794
- )
1795
- const { thread: t, hasOtherReplies } = data
1796
-
1797
- expect(hasOtherReplies).toBe(false)
1798
- assertPosts(t)
1799
- expect(t).toEqual([
1800
- expect.objectContaining({
1801
- uri: seed.root.ref.uriStr,
1802
- value: expect.objectContaining(props({ opThread: true })),
1803
- }),
1804
-
1805
- // alice does not see its own reply as hidden.
1806
- expect.objectContaining({
1807
- uri: seed.r['1'].ref.uriStr,
1808
- value: expect.objectContaining(props()),
1809
- }),
1810
- // OP reply bumped up.
1811
- expect.objectContaining({
1812
- uri: seed.r['1.2'].ref.uriStr,
1813
- value: expect.objectContaining(props()),
1814
- }),
1815
- expect.objectContaining({
1816
- uri: seed.r['1.0'].ref.uriStr,
1817
- value: expect.objectContaining(props()),
1818
- }),
1819
- expect.objectContaining({
1820
- uri: seed.r['1.1'].ref.uriStr,
1821
- value: expect.objectContaining(props()),
1822
- }),
1823
-
1824
- // `opMuted` is not muted by `alice`.
1825
- expect.objectContaining({
1826
- uri: seed.r['0'].ref.uriStr,
1827
- value: expect.objectContaining(props()),
1828
- }),
1829
-
1830
- expect.objectContaining({
1831
- uri: seed.r['2'].ref.uriStr,
1832
- value: expect.objectContaining(props()),
1833
- }),
1834
- // OP reply bumped up.
1835
- expect.objectContaining({
1836
- uri: seed.r['2.2'].ref.uriStr,
1837
- value: expect.objectContaining(props()),
1838
- }),
1839
- expect.objectContaining({
1840
- uri: seed.r['2.0'].ref.uriStr,
1841
- value: expect.objectContaining(props()),
1842
- }),
1843
- // 2.1 is a nested hidden reply, so it is omitted.
1844
- ])
1845
- })
1846
-
1847
- it(`other viewers are affected by threadgate-hidden replies by OP`, async () => {
1848
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
1849
- { anchor: seed.root.ref.uriStr },
1850
- {
1851
- headers: await network.serviceHeaders(
1852
- // `viewer` also gets the replies as hidden.
1853
- seed.users.viewer.did,
1854
- ids.AppBskyUnspeccedGetPostThreadV2,
1855
- ),
1856
- },
1857
- )
1858
- const { thread: t, hasOtherReplies } = data
1859
-
1860
- expect(hasOtherReplies).toBe(true)
1861
- assertPosts(t)
1862
- expect(t).toEqual([
1863
- expect.objectContaining({
1864
- uri: seed.root.ref.uriStr,
1865
- value: expect.objectContaining(props({ opThread: true })),
1866
- }),
1867
- // `opMuted` doesn't see itself as muted, just `op` does.
1868
- expect.objectContaining({
1869
- uri: seed.r['0'].ref.uriStr,
1870
- value: expect.objectContaining(props()),
1871
- }),
1872
-
1873
- expect.objectContaining({
1874
- uri: seed.r['2'].ref.uriStr,
1875
- value: expect.objectContaining(props()),
1876
- }),
1877
- // OP reply bumped up.
1878
- expect.objectContaining({
1879
- uri: seed.r['2.2'].ref.uriStr,
1880
- value: expect.objectContaining(props()),
1881
- }),
1882
- expect.objectContaining({
1883
- uri: seed.r['2.0'].ref.uriStr,
1884
- value: expect.objectContaining(props()),
1885
- }),
1886
- // 2.1 is a nested hidden reply, so it is omitted.
1887
- ])
1888
- })
1889
-
1890
- it(`top-level threadgated replies are returned to other viewers when fetching hidden, sorted by newest`, async () => {
1891
- const { data } = await agent.app.bsky.unspecced.getPostThreadOtherV2(
1892
- { anchor: seed.root.ref.uriStr },
1893
- {
1894
- headers: await network.serviceHeaders(
1895
- // `viewer` also gets the replies as hidden.
1896
- seed.users.viewer.did,
1897
- ids.AppBskyUnspeccedGetPostThreadOtherV2,
1898
- ),
1899
- },
1900
- )
1901
- const { thread: t } = data
1902
-
1903
- assertHiddenPosts(t)
1904
- expect(t).toEqual([
1905
- expect.objectContaining({
1906
- uri: seed.r['1'].ref.uriStr,
1907
- value: expect.objectContaining(
1908
- propsHidden({ hiddenByThreadgate: true }),
1909
- ),
1910
- }),
1911
- // No nested replies for hidden.
1912
- ])
1913
- })
1914
- })
1915
-
1916
- describe('tags', () => {
1917
- let seed: Awaited<ReturnType<typeof seedThreadV2.tags>>
1918
-
1919
- beforeAll(async () => {
1920
- seed = await seedThreadV2.tags(sc)
1921
- await network.processAll()
1922
- })
1923
-
1924
- describe('when prioritizing followed users', () => {
1925
- it('considers tags for bumping down and hiding', async () => {
1926
- const { data } = await agent.app.bsky.unspecced.getPostThreadV2(
1927
- {
1928
- anchor: seed.root.ref.uriStr,
1929
- sort: 'newest',
1930
- },
1931
- {
1932
- headers: await network.serviceHeaders(
1933
- seed.users.viewer.did,
1934
- ids.AppBskyUnspeccedGetPostThreadV2,
1935
- ),
1936
- },
1937
- )
1938
- const { thread: t, hasOtherReplies } = data
1939
-
1940
- expect(hasOtherReplies).toBe(true)
1941
- assertPosts(t)
1942
- expect(t).toEqual([
1943
- expect.objectContaining({ uri: seed.root.ref.uriStr }),
1944
- // OP (down overridden).
1945
- expect.objectContaining({ uri: seed.r['3'].ref.uriStr }),
1946
- // Viewer (hide overridden).
1947
- expect.objectContaining({ uri: seed.r['4'].ref.uriStr }),
1948
- // Following (hide overridden).
1949
- expect.objectContaining({ uri: seed.r['5'].ref.uriStr }),
1950
- // Fot following.
1951
- expect.objectContaining({ uri: seed.r['0'].ref.uriStr }),
1952
- expect.objectContaining({ uri: seed.r['0.0'].ref.uriStr }),
1953
- expect.objectContaining({ uri: seed.r['0.1'].ref.uriStr }),
1954
- // Down.
1955
- expect.objectContaining({ uri: seed.r['1'].ref.uriStr }),
1956
- expect.objectContaining({ uri: seed.r['1.0'].ref.uriStr }),
1957
- expect.objectContaining({ uri: seed.r['1.1'].ref.uriStr }),
1958
- ])
1959
- })
1960
-
1961
- it('finds the hidden by tag', async () => {
1962
- const { data } = await agent.app.bsky.unspecced.getPostThreadOtherV2(
1963
- {
1964
- anchor: seed.root.ref.uriStr,
1965
- },
1966
- {
1967
- headers: await network.serviceHeaders(
1968
- seed.users.viewer.did,
1969
- ids.AppBskyUnspeccedGetPostThreadOtherV2,
1970
- ),
1971
- },
1972
- )
1973
- const { thread: t } = data
1974
-
1975
- assertHiddenPosts(t)
1976
- expect(t).toEqual([
1977
- // Hide.
1978
- expect.objectContaining({ uri: seed.r['2'].ref.uriStr }),
1979
- ])
1980
- })
1981
- })
1982
- })
1983
- })
1984
-
1985
- function assertPosts(
1986
- t: AppBskyUnspeccedGetPostThreadV2.OutputSchema['thread'],
1987
- ): asserts t is ThreadItemValuePost[] {
1988
- t.forEach((i) => {
1989
- assert(
1990
- AppBskyUnspeccedDefs.isThreadItemPost(i.value),
1991
- `Expected thread item to have a post as value`,
1992
- )
1993
- })
1994
- }
1995
-
1996
- function assertHiddenPosts(
1997
- t: AppBskyUnspeccedGetPostThreadOtherV2.OutputSchema['thread'],
1998
- ): asserts t is ThreadOtherItemValuePost[] {
1999
- t.forEach((i) => {
2000
- assert(
2001
- AppBskyUnspeccedDefs.isThreadItemPost(i.value),
2002
- `Expected thread item to have a hidden post as value`,
2003
- )
2004
- })
2005
- }