@atproto/ozone 0.0.2

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 (444) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/LICENSE.txt +7 -0
  3. package/README.md +15 -0
  4. package/babel.config.js +3 -0
  5. package/bin/migration-create.ts +38 -0
  6. package/build.js +18 -0
  7. package/dist/api/admin/emitModerationEvent.d.ts +3 -0
  8. package/dist/api/admin/getModerationEvent.d.ts +3 -0
  9. package/dist/api/admin/getRecord.d.ts +3 -0
  10. package/dist/api/admin/getRepo.d.ts +3 -0
  11. package/dist/api/admin/queryModerationEvents.d.ts +3 -0
  12. package/dist/api/admin/queryModerationStatuses.d.ts +3 -0
  13. package/dist/api/admin/searchRepos.d.ts +3 -0
  14. package/dist/api/admin/util.d.ts +5 -0
  15. package/dist/api/com/atproto/admin/emitModerationEvent.d.ts +3 -0
  16. package/dist/api/com/atproto/admin/getModerationEvent.d.ts +3 -0
  17. package/dist/api/com/atproto/admin/getRecord.d.ts +3 -0
  18. package/dist/api/com/atproto/admin/getRepo.d.ts +3 -0
  19. package/dist/api/com/atproto/admin/queryModerationEvents.d.ts +3 -0
  20. package/dist/api/com/atproto/admin/queryModerationStatuses.d.ts +3 -0
  21. package/dist/api/com/atproto/admin/searchRepos.d.ts +3 -0
  22. package/dist/api/com/atproto/admin/util.d.ts +5 -0
  23. package/dist/api/com/atproto/moderation/createReport.d.ts +3 -0
  24. package/dist/api/com/atproto/moderation/util.d.ts +4 -0
  25. package/dist/api/com/atproto/temp/fetchLabels.d.ts +3 -0
  26. package/dist/api/health.d.ts +3 -0
  27. package/dist/api/index.d.ts +5 -0
  28. package/dist/api/label/queryLabels.d.ts +3 -0
  29. package/dist/api/label/subscribeLabels.d.ts +3 -0
  30. package/dist/api/moderation/createReport.d.ts +3 -0
  31. package/dist/api/moderation/util.d.ts +4 -0
  32. package/dist/api/temp/fetchLabels.d.ts +3 -0
  33. package/dist/api/util.d.ts +2 -0
  34. package/dist/api/well-known.d.ts +3 -0
  35. package/dist/auth-verifier.d.ts +47 -0
  36. package/dist/auth.d.ts +81 -0
  37. package/dist/background.d.ts +13 -0
  38. package/dist/config/config.d.ts +30 -0
  39. package/dist/config/env.d.ts +19 -0
  40. package/dist/config/index.d.ts +3 -0
  41. package/dist/config/secrets.d.ts +8 -0
  42. package/dist/config.d.ts +42 -0
  43. package/dist/context.d.ts +140 -0
  44. package/dist/daemon/config.d.ts +23 -0
  45. package/dist/daemon/context.d.ts +25 -0
  46. package/dist/daemon/event-pusher.d.ts +48 -0
  47. package/dist/daemon/event-reverser.d.ts +16 -0
  48. package/dist/daemon/index.d.ts +13 -0
  49. package/dist/db/index.d.ts +32 -0
  50. package/dist/db/index.js +33707 -0
  51. package/dist/db/index.js.map +7 -0
  52. package/dist/db/migrations/20231219T205730722Z-init.d.ts +3 -0
  53. package/dist/db/migrations/index.d.ts +1 -0
  54. package/dist/db/migrations/provider.d.ts +11 -0
  55. package/dist/db/pagination.d.ts +66 -0
  56. package/dist/db/schema/blob_push_event.d.ts +17 -0
  57. package/dist/db/schema/index.d.ts +10 -0
  58. package/dist/db/schema/label.d.ts +12 -0
  59. package/dist/db/schema/moderation_event.d.ts +22 -0
  60. package/dist/db/schema/moderation_subject_status.d.ts +25 -0
  61. package/dist/db/schema/record_push_event.d.ts +17 -0
  62. package/dist/db/schema/repo_push_event.d.ts +15 -0
  63. package/dist/db/types.d.ts +12 -0
  64. package/dist/error.d.ts +2 -0
  65. package/dist/index.d.ts +27 -0
  66. package/dist/index.js +131818 -0
  67. package/dist/index.js.map +7 -0
  68. package/dist/lexicon/index.d.ts +372 -0
  69. package/dist/lexicon/lexicons.d.ts +7553 -0
  70. package/dist/lexicon/types/app/bsky/actor/defs.d.ts +104 -0
  71. package/dist/lexicon/types/app/bsky/actor/getPreferences.d.ts +31 -0
  72. package/dist/lexicon/types/app/bsky/actor/getProfile.d.ts +29 -0
  73. package/dist/lexicon/types/app/bsky/actor/getProfiles.d.ts +32 -0
  74. package/dist/lexicon/types/app/bsky/actor/getSuggestions.d.ts +34 -0
  75. package/dist/lexicon/types/app/bsky/actor/profile.d.ts +15 -0
  76. package/dist/lexicon/types/app/bsky/actor/putPreferences.d.ts +26 -0
  77. package/dist/lexicon/types/app/bsky/actor/searchActors.d.ts +36 -0
  78. package/dist/lexicon/types/app/bsky/actor/searchActorsTypeahead.d.ts +34 -0
  79. package/dist/lexicon/types/app/bsky/embed/external.d.ts +31 -0
  80. package/dist/lexicon/types/app/bsky/embed/images.d.ts +37 -0
  81. package/dist/lexicon/types/app/bsky/embed/record.d.ts +54 -0
  82. package/dist/lexicon/types/app/bsky/embed/recordWithMedia.d.ts +24 -0
  83. package/dist/lexicon/types/app/bsky/feed/defs.d.ts +151 -0
  84. package/dist/lexicon/types/app/bsky/feed/describeFeedGenerator.d.ts +46 -0
  85. package/dist/lexicon/types/app/bsky/feed/generator.d.ts +18 -0
  86. package/dist/lexicon/types/app/bsky/feed/getActorFeeds.d.ts +35 -0
  87. package/dist/lexicon/types/app/bsky/feed/getActorLikes.d.ts +36 -0
  88. package/dist/lexicon/types/app/bsky/feed/getAuthorFeed.d.ts +37 -0
  89. package/dist/lexicon/types/app/bsky/feed/getFeed.d.ts +36 -0
  90. package/dist/lexicon/types/app/bsky/feed/getFeedGenerator.d.ts +34 -0
  91. package/dist/lexicon/types/app/bsky/feed/getFeedGenerators.d.ts +32 -0
  92. package/dist/lexicon/types/app/bsky/feed/getFeedSkeleton.d.ts +36 -0
  93. package/dist/lexicon/types/app/bsky/feed/getLikes.d.ts +47 -0
  94. package/dist/lexicon/types/app/bsky/feed/getListFeed.d.ts +36 -0
  95. package/dist/lexicon/types/app/bsky/feed/getPostThread.d.ts +38 -0
  96. package/dist/lexicon/types/app/bsky/feed/getPosts.d.ts +32 -0
  97. package/dist/lexicon/types/app/bsky/feed/getRepostedBy.d.ts +38 -0
  98. package/dist/lexicon/types/app/bsky/feed/getSuggestedFeeds.d.ts +34 -0
  99. package/dist/lexicon/types/app/bsky/feed/getTimeline.d.ts +35 -0
  100. package/dist/lexicon/types/app/bsky/feed/like.d.ts +9 -0
  101. package/dist/lexicon/types/app/bsky/feed/post.d.ts +50 -0
  102. package/dist/lexicon/types/app/bsky/feed/repost.d.ts +9 -0
  103. package/dist/lexicon/types/app/bsky/feed/searchPosts.d.ts +37 -0
  104. package/dist/lexicon/types/app/bsky/feed/threadgate.d.ts +28 -0
  105. package/dist/lexicon/types/app/bsky/graph/block.d.ts +8 -0
  106. package/dist/lexicon/types/app/bsky/graph/defs.d.ts +47 -0
  107. package/dist/lexicon/types/app/bsky/graph/follow.d.ts +8 -0
  108. package/dist/lexicon/types/app/bsky/graph/getBlocks.d.ts +34 -0
  109. package/dist/lexicon/types/app/bsky/graph/getFollowers.d.ts +36 -0
  110. package/dist/lexicon/types/app/bsky/graph/getFollows.d.ts +36 -0
  111. package/dist/lexicon/types/app/bsky/graph/getList.d.ts +36 -0
  112. package/dist/lexicon/types/app/bsky/graph/getListBlocks.d.ts +34 -0
  113. package/dist/lexicon/types/app/bsky/graph/getListMutes.d.ts +34 -0
  114. package/dist/lexicon/types/app/bsky/graph/getLists.d.ts +35 -0
  115. package/dist/lexicon/types/app/bsky/graph/getMutes.d.ts +34 -0
  116. package/dist/lexicon/types/app/bsky/graph/getSuggestedFollowsByActor.d.ts +32 -0
  117. package/dist/lexicon/types/app/bsky/graph/list.d.ts +19 -0
  118. package/dist/lexicon/types/app/bsky/graph/listblock.d.ts +8 -0
  119. package/dist/lexicon/types/app/bsky/graph/listitem.d.ts +9 -0
  120. package/dist/lexicon/types/app/bsky/graph/muteActor.d.ts +25 -0
  121. package/dist/lexicon/types/app/bsky/graph/muteActorList.d.ts +25 -0
  122. package/dist/lexicon/types/app/bsky/graph/unmuteActor.d.ts +25 -0
  123. package/dist/lexicon/types/app/bsky/graph/unmuteActorList.d.ts +25 -0
  124. package/dist/lexicon/types/app/bsky/moderation/defs.d.ts +49 -0
  125. package/dist/lexicon/types/app/bsky/moderation/getService.d.ts +29 -0
  126. package/dist/lexicon/types/app/bsky/moderation/getServices.d.ts +32 -0
  127. package/dist/lexicon/types/app/bsky/moderation/service.d.ts +17 -0
  128. package/dist/lexicon/types/app/bsky/notification/getUnreadCount.d.ts +31 -0
  129. package/dist/lexicon/types/app/bsky/notification/listNotifications.d.ts +52 -0
  130. package/dist/lexicon/types/app/bsky/notification/registerPush.d.ts +28 -0
  131. package/dist/lexicon/types/app/bsky/notification/updateSeen.d.ts +25 -0
  132. package/dist/lexicon/types/app/bsky/richtext/facet.d.ts +36 -0
  133. package/dist/lexicon/types/app/bsky/unspecced/defs.d.ts +13 -0
  134. package/dist/lexicon/types/app/bsky/unspecced/getPopular.d.ts +35 -0
  135. package/dist/lexicon/types/app/bsky/unspecced/getPopularFeedGenerators.d.ts +35 -0
  136. package/dist/lexicon/types/app/bsky/unspecced/getTimelineSkeleton.d.ts +35 -0
  137. package/dist/lexicon/types/app/bsky/unspecced/searchActorsSkeleton.d.ts +38 -0
  138. package/dist/lexicon/types/app/bsky/unspecced/searchPostsSkeleton.d.ts +37 -0
  139. package/dist/lexicon/types/com/atproto/admin/defs.d.ts +319 -0
  140. package/dist/lexicon/types/com/atproto/admin/deleteAccount.d.ts +25 -0
  141. package/dist/lexicon/types/com/atproto/admin/disableAccountInvites.d.ts +26 -0
  142. package/dist/lexicon/types/com/atproto/admin/disableInviteCodes.d.ts +26 -0
  143. package/dist/lexicon/types/com/atproto/admin/emitModerationEvent.d.ts +45 -0
  144. package/dist/lexicon/types/com/atproto/admin/enableAccountInvites.d.ts +26 -0
  145. package/dist/lexicon/types/com/atproto/admin/getAccountInfo.d.ts +29 -0
  146. package/dist/lexicon/types/com/atproto/admin/getAccountInfos.d.ts +32 -0
  147. package/dist/lexicon/types/com/atproto/admin/getInviteCodes.d.ts +35 -0
  148. package/dist/lexicon/types/com/atproto/admin/getModerationEvent.d.ts +29 -0
  149. package/dist/lexicon/types/com/atproto/admin/getRecord.d.ts +31 -0
  150. package/dist/lexicon/types/com/atproto/admin/getRepo.d.ts +30 -0
  151. package/dist/lexicon/types/com/atproto/admin/getSubjectStatus.d.ts +39 -0
  152. package/dist/lexicon/types/com/atproto/admin/queryModerationEvents.d.ts +39 -0
  153. package/dist/lexicon/types/com/atproto/admin/queryModerationStatuses.d.ts +48 -0
  154. package/dist/lexicon/types/com/atproto/admin/searchRepos.d.ts +36 -0
  155. package/dist/lexicon/types/com/atproto/admin/sendEmail.d.ts +40 -0
  156. package/dist/lexicon/types/com/atproto/admin/updateAccountEmail.d.ts +26 -0
  157. package/dist/lexicon/types/com/atproto/admin/updateAccountHandle.d.ts +26 -0
  158. package/dist/lexicon/types/com/atproto/admin/updateSubjectStatus.d.ts +46 -0
  159. package/dist/lexicon/types/com/atproto/identity/resolveHandle.d.ts +31 -0
  160. package/dist/lexicon/types/com/atproto/identity/updateHandle.d.ts +25 -0
  161. package/dist/lexicon/types/com/atproto/label/defs.d.ts +24 -0
  162. package/dist/lexicon/types/com/atproto/label/queryLabels.d.ts +36 -0
  163. package/dist/lexicon/types/com/atproto/label/subscribeLabels.d.ts +36 -0
  164. package/dist/lexicon/types/com/atproto/moderation/createReport.d.ts +52 -0
  165. package/dist/lexicon/types/com/atproto/moderation/defs.d.ts +8 -0
  166. package/dist/lexicon/types/com/atproto/repo/applyWrites.d.ts +53 -0
  167. package/dist/lexicon/types/com/atproto/repo/createRecord.d.ts +43 -0
  168. package/dist/lexicon/types/com/atproto/repo/deleteRecord.d.ts +30 -0
  169. package/dist/lexicon/types/com/atproto/repo/describeRepo.d.ts +35 -0
  170. package/dist/lexicon/types/com/atproto/repo/getRecord.d.ts +36 -0
  171. package/dist/lexicon/types/com/atproto/repo/listRecords.d.ts +47 -0
  172. package/dist/lexicon/types/com/atproto/repo/putRecord.d.ts +44 -0
  173. package/dist/lexicon/types/com/atproto/repo/strongRef.d.ts +8 -0
  174. package/dist/lexicon/types/com/atproto/repo/uploadBlob.d.ts +36 -0
  175. package/dist/lexicon/types/com/atproto/server/confirmEmail.d.ts +27 -0
  176. package/dist/lexicon/types/com/atproto/server/createAccount.d.ts +49 -0
  177. package/dist/lexicon/types/com/atproto/server/createAppPassword.d.ts +43 -0
  178. package/dist/lexicon/types/com/atproto/server/createInviteCode.d.ts +37 -0
  179. package/dist/lexicon/types/com/atproto/server/createInviteCodes.d.ts +46 -0
  180. package/dist/lexicon/types/com/atproto/server/createSession.d.ts +44 -0
  181. package/dist/lexicon/types/com/atproto/server/defs.d.ts +20 -0
  182. package/dist/lexicon/types/com/atproto/server/deleteAccount.d.ts +28 -0
  183. package/dist/lexicon/types/com/atproto/server/deleteSession.d.ts +19 -0
  184. package/dist/lexicon/types/com/atproto/server/describeServer.d.ts +41 -0
  185. package/dist/lexicon/types/com/atproto/server/getAccountInviteCodes.d.ts +34 -0
  186. package/dist/lexicon/types/com/atproto/server/getSession.d.ts +34 -0
  187. package/dist/lexicon/types/com/atproto/server/listAppPasswords.d.ts +39 -0
  188. package/dist/lexicon/types/com/atproto/server/refreshSession.d.ts +35 -0
  189. package/dist/lexicon/types/com/atproto/server/requestAccountDelete.d.ts +19 -0
  190. package/dist/lexicon/types/com/atproto/server/requestEmailConfirmation.d.ts +19 -0
  191. package/dist/lexicon/types/com/atproto/server/requestEmailUpdate.d.ts +30 -0
  192. package/dist/lexicon/types/com/atproto/server/requestPasswordReset.d.ts +25 -0
  193. package/dist/lexicon/types/com/atproto/server/reserveSigningKey.d.ts +36 -0
  194. package/dist/lexicon/types/com/atproto/server/resetPassword.d.ts +27 -0
  195. package/dist/lexicon/types/com/atproto/server/revokeAppPassword.d.ts +25 -0
  196. package/dist/lexicon/types/com/atproto/server/updateEmail.d.ts +27 -0
  197. package/dist/lexicon/types/com/atproto/sync/getBlob.d.ts +30 -0
  198. package/dist/lexicon/types/com/atproto/sync/getBlocks.d.ts +30 -0
  199. package/dist/lexicon/types/com/atproto/sync/getCheckout.d.ts +29 -0
  200. package/dist/lexicon/types/com/atproto/sync/getHead.d.ts +32 -0
  201. package/dist/lexicon/types/com/atproto/sync/getLatestCommit.d.ts +33 -0
  202. package/dist/lexicon/types/com/atproto/sync/getRecord.d.ts +32 -0
  203. package/dist/lexicon/types/com/atproto/sync/getRepo.d.ts +30 -0
  204. package/dist/lexicon/types/com/atproto/sync/listBlobs.d.ts +35 -0
  205. package/dist/lexicon/types/com/atproto/sync/listRepos.d.ts +42 -0
  206. package/dist/lexicon/types/com/atproto/sync/notifyOfUpdate.d.ts +25 -0
  207. package/dist/lexicon/types/com/atproto/sync/requestCrawl.d.ts +25 -0
  208. package/dist/lexicon/types/com/atproto/sync/subscribeRepos.d.ts +80 -0
  209. package/dist/lexicon/types/com/atproto/temp/fetchLabels.d.ts +33 -0
  210. package/dist/lexicon/types/com/atproto/temp/importRepo.d.ts +32 -0
  211. package/dist/lexicon/types/com/atproto/temp/pushBlob.d.ts +25 -0
  212. package/dist/lexicon/types/com/atproto/temp/requestPhoneVerification.d.ts +25 -0
  213. package/dist/lexicon/types/com/atproto/temp/transferAccount.d.ts +42 -0
  214. package/dist/lexicon/util.d.ts +2 -0
  215. package/dist/logger.d.ts +4 -0
  216. package/dist/mod-service/index.d.ts +155 -0
  217. package/dist/mod-service/status.d.ts +12 -0
  218. package/dist/mod-service/subject.d.ts +59 -0
  219. package/dist/mod-service/types.d.ts +19 -0
  220. package/dist/mod-service/views.d.ts +49 -0
  221. package/dist/sequencer/index.d.ts +2 -0
  222. package/dist/sequencer/outbox.d.ts +16 -0
  223. package/dist/sequencer/sequencer.d.ts +35 -0
  224. package/dist/services/index.d.ts +7 -0
  225. package/dist/services/moderation/index.d.ts +144 -0
  226. package/dist/services/moderation/status.d.ts +12 -0
  227. package/dist/services/moderation/subject.d.ts +60 -0
  228. package/dist/services/moderation/types.d.ts +19 -0
  229. package/dist/services/moderation/views.d.ts +42 -0
  230. package/dist/services/types.d.ts +2 -0
  231. package/dist/util/date.d.ts +1 -0
  232. package/dist/util/debug.d.ts +1 -0
  233. package/dist/util/retry.d.ts +3 -0
  234. package/dist/util.d.ts +3 -0
  235. package/jest.config.js +6 -0
  236. package/package.json +67 -0
  237. package/src/api/admin/emitModerationEvent.ts +130 -0
  238. package/src/api/admin/getModerationEvent.ts +19 -0
  239. package/src/api/admin/getRecord.ts +34 -0
  240. package/src/api/admin/getRepo.ts +31 -0
  241. package/src/api/admin/queryModerationEvents.ts +40 -0
  242. package/src/api/admin/queryModerationStatuses.ts +57 -0
  243. package/src/api/admin/searchRepos.ts +42 -0
  244. package/src/api/admin/util.ts +54 -0
  245. package/src/api/health.ts +20 -0
  246. package/src/api/index.ts +28 -0
  247. package/src/api/moderation/createReport.ts +41 -0
  248. package/src/api/moderation/util.ts +65 -0
  249. package/src/api/temp/fetchLabels.ts +29 -0
  250. package/src/api/well-known.ts +35 -0
  251. package/src/auth.ts +147 -0
  252. package/src/background.ts +35 -0
  253. package/src/config/config.ts +84 -0
  254. package/src/config/env.ts +41 -0
  255. package/src/config/index.ts +3 -0
  256. package/src/config/secrets.ts +23 -0
  257. package/src/context.ts +180 -0
  258. package/src/daemon/context.ts +90 -0
  259. package/src/daemon/event-pusher.ts +296 -0
  260. package/src/daemon/event-reverser.ts +74 -0
  261. package/src/daemon/index.ts +33 -0
  262. package/src/db/index.ts +197 -0
  263. package/src/db/migrations/20231219T205730722Z-init.ts +164 -0
  264. package/src/db/migrations/index.ts +5 -0
  265. package/src/db/migrations/provider.ts +25 -0
  266. package/src/db/pagination.ts +216 -0
  267. package/src/db/schema/blob_push_event.ts +21 -0
  268. package/src/db/schema/index.ts +18 -0
  269. package/src/db/schema/label.ts +12 -0
  270. package/src/db/schema/moderation_event.ts +35 -0
  271. package/src/db/schema/moderation_subject_status.ts +32 -0
  272. package/src/db/schema/record_push_event.ts +21 -0
  273. package/src/db/schema/repo_push_event.ts +19 -0
  274. package/src/db/types.ts +15 -0
  275. package/src/error.ts +12 -0
  276. package/src/index.ts +102 -0
  277. package/src/lexicon/index.ts +1626 -0
  278. package/src/lexicon/lexicons.ts +8050 -0
  279. package/src/lexicon/types/app/bsky/actor/defs.ts +235 -0
  280. package/src/lexicon/types/app/bsky/actor/getPreferences.ts +44 -0
  281. package/src/lexicon/types/app/bsky/actor/getProfile.ts +41 -0
  282. package/src/lexicon/types/app/bsky/actor/getProfiles.ts +46 -0
  283. package/src/lexicon/types/app/bsky/actor/getSuggestions.ts +48 -0
  284. package/src/lexicon/types/app/bsky/actor/profile.ts +32 -0
  285. package/src/lexicon/types/app/bsky/actor/putPreferences.ts +39 -0
  286. package/src/lexicon/types/app/bsky/actor/searchActors.ts +52 -0
  287. package/src/lexicon/types/app/bsky/actor/searchActorsTypeahead.ts +50 -0
  288. package/src/lexicon/types/app/bsky/embed/external.ts +82 -0
  289. package/src/lexicon/types/app/bsky/embed/images.ts +96 -0
  290. package/src/lexicon/types/app/bsky/embed/record.ts +120 -0
  291. package/src/lexicon/types/app/bsky/embed/recordWithMedia.ts +53 -0
  292. package/src/lexicon/types/app/bsky/feed/defs.ts +308 -0
  293. package/src/lexicon/types/app/bsky/feed/describeFeedGenerator.ts +80 -0
  294. package/src/lexicon/types/app/bsky/feed/generator.ts +35 -0
  295. package/src/lexicon/types/app/bsky/feed/getActorFeeds.ts +49 -0
  296. package/src/lexicon/types/app/bsky/feed/getActorLikes.ts +50 -0
  297. package/src/lexicon/types/app/bsky/feed/getAuthorFeed.ts +56 -0
  298. package/src/lexicon/types/app/bsky/feed/getFeed.ts +50 -0
  299. package/src/lexicon/types/app/bsky/feed/getFeedGenerator.ts +48 -0
  300. package/src/lexicon/types/app/bsky/feed/getFeedGenerators.ts +46 -0
  301. package/src/lexicon/types/app/bsky/feed/getFeedSkeleton.ts +50 -0
  302. package/src/lexicon/types/app/bsky/feed/getLikes.ts +69 -0
  303. package/src/lexicon/types/app/bsky/feed/getListFeed.ts +50 -0
  304. package/src/lexicon/types/app/bsky/feed/getPostThread.ts +53 -0
  305. package/src/lexicon/types/app/bsky/feed/getPosts.ts +46 -0
  306. package/src/lexicon/types/app/bsky/feed/getRepostedBy.ts +52 -0
  307. package/src/lexicon/types/app/bsky/feed/getSuggestedFeeds.ts +48 -0
  308. package/src/lexicon/types/app/bsky/feed/getTimeline.ts +49 -0
  309. package/src/lexicon/types/app/bsky/feed/like.ts +26 -0
  310. package/src/lexicon/types/app/bsky/feed/post.ts +102 -0
  311. package/src/lexicon/types/app/bsky/feed/repost.ts +27 -0
  312. package/src/lexicon/types/app/bsky/feed/searchPosts.ts +54 -0
  313. package/src/lexicon/types/app/bsky/feed/threadgate.ts +84 -0
  314. package/src/lexicon/types/app/bsky/graph/block.ts +26 -0
  315. package/src/lexicon/types/app/bsky/graph/defs.ts +104 -0
  316. package/src/lexicon/types/app/bsky/graph/follow.ts +26 -0
  317. package/src/lexicon/types/app/bsky/graph/getBlocks.ts +48 -0
  318. package/src/lexicon/types/app/bsky/graph/getFollowers.ts +50 -0
  319. package/src/lexicon/types/app/bsky/graph/getFollows.ts +50 -0
  320. package/src/lexicon/types/app/bsky/graph/getList.ts +50 -0
  321. package/src/lexicon/types/app/bsky/graph/getListBlocks.ts +48 -0
  322. package/src/lexicon/types/app/bsky/graph/getListMutes.ts +48 -0
  323. package/src/lexicon/types/app/bsky/graph/getLists.ts +49 -0
  324. package/src/lexicon/types/app/bsky/graph/getMutes.ts +48 -0
  325. package/src/lexicon/types/app/bsky/graph/getSuggestedFollowsByActor.ts +46 -0
  326. package/src/lexicon/types/app/bsky/graph/list.ts +36 -0
  327. package/src/lexicon/types/app/bsky/graph/listblock.ts +26 -0
  328. package/src/lexicon/types/app/bsky/graph/listitem.ts +27 -0
  329. package/src/lexicon/types/app/bsky/graph/muteActor.ts +38 -0
  330. package/src/lexicon/types/app/bsky/graph/muteActorList.ts +38 -0
  331. package/src/lexicon/types/app/bsky/graph/unmuteActor.ts +38 -0
  332. package/src/lexicon/types/app/bsky/graph/unmuteActorList.ts +38 -0
  333. package/src/lexicon/types/app/bsky/notification/getUnreadCount.ts +45 -0
  334. package/src/lexicon/types/app/bsky/notification/listNotifications.ts +87 -0
  335. package/src/lexicon/types/app/bsky/notification/registerPush.ts +41 -0
  336. package/src/lexicon/types/app/bsky/notification/updateSeen.ts +38 -0
  337. package/src/lexicon/types/app/bsky/richtext/facet.ts +97 -0
  338. package/src/lexicon/types/app/bsky/unspecced/defs.ts +41 -0
  339. package/src/lexicon/types/app/bsky/unspecced/getPopularFeedGenerators.ts +49 -0
  340. package/src/lexicon/types/app/bsky/unspecced/getTimelineSkeleton.ts +49 -0
  341. package/src/lexicon/types/app/bsky/unspecced/searchActorsSkeleton.ts +56 -0
  342. package/src/lexicon/types/app/bsky/unspecced/searchPostsSkeleton.ts +54 -0
  343. package/src/lexicon/types/com/atproto/admin/defs.ts +719 -0
  344. package/src/lexicon/types/com/atproto/admin/deleteAccount.ts +38 -0
  345. package/src/lexicon/types/com/atproto/admin/disableAccountInvites.ts +40 -0
  346. package/src/lexicon/types/com/atproto/admin/disableInviteCodes.ts +39 -0
  347. package/src/lexicon/types/com/atproto/admin/emitModerationEvent.ts +66 -0
  348. package/src/lexicon/types/com/atproto/admin/enableAccountInvites.ts +40 -0
  349. package/src/lexicon/types/com/atproto/admin/getAccountInfo.ts +41 -0
  350. package/src/lexicon/types/com/atproto/admin/getAccountInfos.ts +46 -0
  351. package/src/lexicon/types/com/atproto/admin/getInviteCodes.ts +49 -0
  352. package/src/lexicon/types/com/atproto/admin/getModerationEvent.ts +41 -0
  353. package/src/lexicon/types/com/atproto/admin/getRecord.ts +43 -0
  354. package/src/lexicon/types/com/atproto/admin/getRepo.ts +42 -0
  355. package/src/lexicon/types/com/atproto/admin/getSubjectStatus.ts +54 -0
  356. package/src/lexicon/types/com/atproto/admin/queryModerationEvents.ts +56 -0
  357. package/src/lexicon/types/com/atproto/admin/queryModerationStatuses.ts +72 -0
  358. package/src/lexicon/types/com/atproto/admin/searchRepos.ts +51 -0
  359. package/src/lexicon/types/com/atproto/admin/sendEmail.ts +54 -0
  360. package/src/lexicon/types/com/atproto/admin/updateAccountEmail.ts +40 -0
  361. package/src/lexicon/types/com/atproto/admin/updateAccountHandle.ts +39 -0
  362. package/src/lexicon/types/com/atproto/admin/updateSubjectStatus.ts +61 -0
  363. package/src/lexicon/types/com/atproto/identity/resolveHandle.ts +46 -0
  364. package/src/lexicon/types/com/atproto/identity/updateHandle.ts +38 -0
  365. package/src/lexicon/types/com/atproto/label/defs.ts +73 -0
  366. package/src/lexicon/types/com/atproto/label/queryLabels.ts +52 -0
  367. package/src/lexicon/types/com/atproto/label/subscribeLabels.ts +67 -0
  368. package/src/lexicon/types/com/atproto/moderation/createReport.ts +65 -0
  369. package/src/lexicon/types/com/atproto/moderation/defs.ts +32 -0
  370. package/src/lexicon/types/com/atproto/repo/applyWrites.ts +103 -0
  371. package/src/lexicon/types/com/atproto/repo/createRecord.ts +62 -0
  372. package/src/lexicon/types/com/atproto/repo/deleteRecord.ts +48 -0
  373. package/src/lexicon/types/com/atproto/repo/describeRepo.ts +50 -0
  374. package/src/lexicon/types/com/atproto/repo/getRecord.ts +54 -0
  375. package/src/lexicon/types/com/atproto/repo/listRecords.ts +77 -0
  376. package/src/lexicon/types/com/atproto/repo/putRecord.ts +64 -0
  377. package/src/lexicon/types/com/atproto/repo/strongRef.ts +26 -0
  378. package/src/lexicon/types/com/atproto/repo/uploadBlob.ts +47 -0
  379. package/src/lexicon/types/com/atproto/server/confirmEmail.ts +40 -0
  380. package/src/lexicon/types/com/atproto/server/createAccount.ts +69 -0
  381. package/src/lexicon/types/com/atproto/server/createAppPassword.ts +69 -0
  382. package/src/lexicon/types/com/atproto/server/createInviteCode.ts +50 -0
  383. package/src/lexicon/types/com/atproto/server/createInviteCodes.ts +72 -0
  384. package/src/lexicon/types/com/atproto/server/createSession.ts +58 -0
  385. package/src/lexicon/types/com/atproto/server/defs.ts +48 -0
  386. package/src/lexicon/types/com/atproto/server/deleteAccount.ts +41 -0
  387. package/src/lexicon/types/com/atproto/server/deleteSession.ts +31 -0
  388. package/src/lexicon/types/com/atproto/server/describeServer.ts +64 -0
  389. package/src/lexicon/types/com/atproto/server/getAccountInviteCodes.ts +48 -0
  390. package/src/lexicon/types/com/atproto/server/getSession.ts +47 -0
  391. package/src/lexicon/types/com/atproto/server/listAppPasswords.ts +62 -0
  392. package/src/lexicon/types/com/atproto/server/refreshSession.ts +48 -0
  393. package/src/lexicon/types/com/atproto/server/requestAccountDelete.ts +31 -0
  394. package/src/lexicon/types/com/atproto/server/requestEmailConfirmation.ts +31 -0
  395. package/src/lexicon/types/com/atproto/server/requestEmailUpdate.ts +43 -0
  396. package/src/lexicon/types/com/atproto/server/requestPasswordReset.ts +38 -0
  397. package/src/lexicon/types/com/atproto/server/reserveSigningKey.ts +51 -0
  398. package/src/lexicon/types/com/atproto/server/resetPassword.ts +40 -0
  399. package/src/lexicon/types/com/atproto/server/revokeAppPassword.ts +38 -0
  400. package/src/lexicon/types/com/atproto/server/updateEmail.ts +41 -0
  401. package/src/lexicon/types/com/atproto/sync/getBlob.ts +43 -0
  402. package/src/lexicon/types/com/atproto/sync/getBlocks.ts +42 -0
  403. package/src/lexicon/types/com/atproto/sync/getCheckout.ts +41 -0
  404. package/src/lexicon/types/com/atproto/sync/getHead.ts +47 -0
  405. package/src/lexicon/types/com/atproto/sync/getLatestCommit.ts +48 -0
  406. package/src/lexicon/types/com/atproto/sync/getRecord.ts +45 -0
  407. package/src/lexicon/types/com/atproto/sync/getRepo.ts +43 -0
  408. package/src/lexicon/types/com/atproto/sync/listBlobs.ts +51 -0
  409. package/src/lexicon/types/com/atproto/sync/listRepos.ts +66 -0
  410. package/src/lexicon/types/com/atproto/sync/notifyOfUpdate.ts +39 -0
  411. package/src/lexicon/types/com/atproto/sync/requestCrawl.ts +39 -0
  412. package/src/lexicon/types/com/atproto/sync/subscribeRepos.ts +161 -0
  413. package/src/lexicon/types/com/atproto/temp/fetchLabels.ts +47 -0
  414. package/src/lexicon/types/com/atproto/temp/importRepo.ts +45 -0
  415. package/src/lexicon/types/com/atproto/temp/pushBlob.ts +39 -0
  416. package/src/lexicon/types/com/atproto/temp/requestPhoneVerification.ts +38 -0
  417. package/src/lexicon/types/com/atproto/temp/transferAccount.ts +62 -0
  418. package/src/lexicon/util.ts +13 -0
  419. package/src/logger.ts +19 -0
  420. package/src/mod-service/index.ts +758 -0
  421. package/src/mod-service/status.ts +264 -0
  422. package/src/mod-service/subject.ts +136 -0
  423. package/src/mod-service/types.ts +32 -0
  424. package/src/mod-service/views.ts +531 -0
  425. package/src/util.ts +26 -0
  426. package/test.env +2 -0
  427. package/test.log +0 -0
  428. package/tests/__snapshots__/get-record.test.ts.snap +173 -0
  429. package/tests/__snapshots__/get-repo.test.ts.snap +57 -0
  430. package/tests/__snapshots__/moderation-events.test.ts.snap +168 -0
  431. package/tests/__snapshots__/moderation-statuses.test.ts.snap +64 -0
  432. package/tests/__snapshots__/moderation.test.ts.snap +55 -0
  433. package/tests/_util.ts +192 -0
  434. package/tests/db.test.ts +184 -0
  435. package/tests/get-record.test.ts +110 -0
  436. package/tests/get-repo.test.ts +131 -0
  437. package/tests/moderation-appeals.test.ts +269 -0
  438. package/tests/moderation-events.test.ts +220 -0
  439. package/tests/moderation-statuses.test.ts +144 -0
  440. package/tests/moderation.test.ts +961 -0
  441. package/tests/repo-search.test.ts +123 -0
  442. package/tests/server.test.ts +76 -0
  443. package/tsconfig.build.json +4 -0
  444. package/tsconfig.json +21 -0
@@ -0,0 +1,531 @@
1
+ import { sql } from 'kysely'
2
+ import { AtUri, INVALID_HANDLE, normalizeDatetimeAlways } from '@atproto/syntax'
3
+ import AtpAgent from '@atproto/api'
4
+ import { dedupeStrs } from '@atproto/common'
5
+ import { BlobRef } from '@atproto/lexicon'
6
+ import { Database } from '../db'
7
+ import {
8
+ ModEventView,
9
+ RepoView,
10
+ RepoViewDetail,
11
+ RecordView,
12
+ RecordViewDetail,
13
+ ReportViewDetail,
14
+ BlobView,
15
+ SubjectStatusView,
16
+ ModEventViewDetail,
17
+ AccountView,
18
+ } from '../lexicon/types/com/atproto/admin/defs'
19
+ import { OutputSchema as ReportOutput } from '../lexicon/types/com/atproto/moderation/createReport'
20
+ import { Label, isSelfLabels } from '../lexicon/types/com/atproto/label/defs'
21
+ import {
22
+ ModerationEventRowWithHandle,
23
+ ModerationSubjectStatusRowWithHandle,
24
+ } from './types'
25
+ import { REASONOTHER } from '../lexicon/types/com/atproto/moderation/defs'
26
+ import { subjectFromEventRow, subjectFromStatusRow } from './subject'
27
+
28
+ export type AppviewAuth = () => Promise<
29
+ | {
30
+ headers: {
31
+ authorization: string
32
+ }
33
+ }
34
+ | undefined
35
+ >
36
+
37
+ export class ModerationViews {
38
+ constructor(
39
+ private db: Database,
40
+ private appviewAgent: AtpAgent,
41
+ private appviewAuth: AppviewAuth,
42
+ ) {}
43
+
44
+ async getAccoutInfosByDid(dids: string[]): Promise<Map<string, AccountView>> {
45
+ if (dids.length === 0) return new Map()
46
+ const auth = await this.appviewAuth()
47
+ if (!auth) return new Map()
48
+ const res = await this.appviewAgent.api.com.atproto.admin.getAccountInfos(
49
+ {
50
+ dids: dedupeStrs(dids),
51
+ },
52
+ auth,
53
+ )
54
+ return res.data.infos.reduce((acc, cur) => {
55
+ return acc.set(cur.did, cur)
56
+ }, new Map<string, AccountView>())
57
+ }
58
+
59
+ async repos(dids: string[]): Promise<Map<string, RepoView>> {
60
+ if (dids.length === 0) return new Map()
61
+ const [infos, subjectStatuses] = await Promise.all([
62
+ this.getAccoutInfosByDid(dids),
63
+ this.getSubjectStatus(dids),
64
+ ])
65
+
66
+ return dids.reduce((acc, did) => {
67
+ const info = infos.get(did)
68
+ if (!info) return acc
69
+ const status = subjectStatuses.get(did)
70
+ return acc.set(did, {
71
+ // No email or invite info on appview
72
+ did,
73
+ handle: info.handle,
74
+ relatedRecords: info.relatedRecords ?? [],
75
+ indexedAt: info.indexedAt,
76
+ moderation: {
77
+ subjectStatus: status ? this.formatSubjectStatus(status) : undefined,
78
+ },
79
+ })
80
+ }, new Map<string, RepoView>())
81
+ }
82
+
83
+ formatEvent(event: ModerationEventRowWithHandle): ModEventView {
84
+ const eventView: ModEventView = {
85
+ id: event.id,
86
+ event: {
87
+ $type: event.action,
88
+ comment: event.comment ?? undefined,
89
+ },
90
+ subject: subjectFromEventRow(event).lex(),
91
+ subjectBlobCids: [],
92
+ createdBy: event.createdBy,
93
+ createdAt: event.createdAt,
94
+ subjectHandle: event.subjectHandle ?? undefined,
95
+ creatorHandle: event.creatorHandle ?? undefined,
96
+ }
97
+
98
+ if (
99
+ [
100
+ 'com.atproto.admin.defs#modEventTakedown',
101
+ 'com.atproto.admin.defs#modEventMute',
102
+ ].includes(event.action)
103
+ ) {
104
+ eventView.event = {
105
+ ...eventView.event,
106
+ durationInHours: event.durationInHours ?? undefined,
107
+ }
108
+ }
109
+
110
+ if (event.action === 'com.atproto.admin.defs#modEventLabel') {
111
+ eventView.event = {
112
+ ...eventView.event,
113
+ createLabelVals: event.createLabelVals?.length
114
+ ? event.createLabelVals.split(' ')
115
+ : [],
116
+ negateLabelVals: event.negateLabelVals?.length
117
+ ? event.negateLabelVals.split(' ')
118
+ : [],
119
+ }
120
+ }
121
+
122
+ // This is for legacy data only, for new events, these types of events won't have labels attached
123
+ if (
124
+ [
125
+ 'com.atproto.admin.defs#modEventAcknowledge',
126
+ 'com.atproto.admin.defs#modEventTakedown',
127
+ 'com.atproto.admin.defs#modEventEscalate',
128
+ ].includes(event.action)
129
+ ) {
130
+ if (event.createLabelVals?.length) {
131
+ eventView.event = {
132
+ ...eventView.event,
133
+ createLabelVals: event.createLabelVals.split(' '),
134
+ }
135
+ }
136
+
137
+ if (event.negateLabelVals?.length) {
138
+ eventView.event = {
139
+ ...eventView.event,
140
+ negateLabelVals: event.negateLabelVals.split(' '),
141
+ }
142
+ }
143
+ }
144
+
145
+ if (event.action === 'com.atproto.admin.defs#modEventReport') {
146
+ eventView.event = {
147
+ ...eventView.event,
148
+ reportType: event.meta?.reportType ?? undefined,
149
+ }
150
+ }
151
+
152
+ if (event.action === 'com.atproto.admin.defs#modEventEmail') {
153
+ eventView.event = {
154
+ ...eventView.event,
155
+ subjectLine: event.meta?.subjectLine ?? '',
156
+ }
157
+ }
158
+
159
+ if (
160
+ event.action === 'com.atproto.admin.defs#modEventComment' &&
161
+ event.meta?.sticky
162
+ ) {
163
+ eventView.event.sticky = true
164
+ }
165
+
166
+ return eventView
167
+ }
168
+
169
+ async eventDetail(
170
+ result: ModerationEventRowWithHandle,
171
+ ): Promise<ModEventViewDetail> {
172
+ const subjectId =
173
+ result.subjectType === 'com.atproto.admin.defs#repoRef'
174
+ ? result.subjectDid
175
+ : result.subjectUri
176
+ if (!subjectId) {
177
+ throw new Error(`Bad subject: ${result.id}`)
178
+ }
179
+ const subject = await this.subject(subjectId)
180
+ const eventView = this.formatEvent(result)
181
+ const allBlobs = findBlobRefs(subject.value)
182
+ const subjectBlobs = await this.blob(
183
+ allBlobs.filter((blob) =>
184
+ eventView.subjectBlobCids.includes(blob.ref.toString()),
185
+ ),
186
+ )
187
+ return {
188
+ ...eventView,
189
+ subject,
190
+ subjectBlobs,
191
+ }
192
+ }
193
+
194
+ async repoDetail(did: string): Promise<RepoViewDetail | undefined> {
195
+ const [repos, labels] = await Promise.all([
196
+ this.repos([did]),
197
+ this.labels(did),
198
+ ])
199
+ const repo = repos.get(did)
200
+ if (!repo) return
201
+
202
+ return {
203
+ ...repo,
204
+ moderation: {
205
+ ...repo.moderation,
206
+ },
207
+ labels,
208
+ }
209
+ }
210
+
211
+ async fetchRecords(
212
+ subjects: RecordSubject[],
213
+ ): Promise<Map<string, RecordInfo>> {
214
+ const auth = await this.appviewAuth()
215
+ if (!auth) return new Map()
216
+ const fetched = await Promise.all(
217
+ subjects.map(async (subject) => {
218
+ const uri = new AtUri(subject.uri)
219
+ try {
220
+ return await this.appviewAgent.api.com.atproto.repo.getRecord(
221
+ {
222
+ repo: uri.hostname,
223
+ collection: uri.collection,
224
+ rkey: uri.rkey,
225
+ cid: subject.cid,
226
+ },
227
+ auth,
228
+ )
229
+ } catch {
230
+ return null
231
+ }
232
+ }),
233
+ )
234
+ return fetched.reduce((acc, cur) => {
235
+ if (!cur) return acc
236
+ const data = cur.data
237
+ const indexedAt = new Date().toISOString()
238
+ return acc.set(data.uri, { ...data, cid: data.cid ?? '', indexedAt })
239
+ }, new Map<string, RecordInfo>())
240
+ }
241
+
242
+ async records(subjects: RecordSubject[]): Promise<Map<string, RecordView>> {
243
+ const uris = subjects.map((record) => new AtUri(record.uri))
244
+ const dids = uris.map((u) => u.hostname)
245
+
246
+ const [repos, subjectStatuses, records] = await Promise.all([
247
+ this.repos(dids),
248
+ this.getSubjectStatus(subjects.map((s) => s.uri)),
249
+ this.fetchRecords(subjects),
250
+ ])
251
+
252
+ return uris.reduce((acc, uri) => {
253
+ const repo = repos.get(uri.hostname)
254
+ if (!repo) return acc
255
+ const record = records.get(uri.toString())
256
+ if (!record) return acc
257
+ const subjectStatus = subjectStatuses.get(uri.toString())
258
+ return acc.set(uri.toString(), {
259
+ uri: uri.toString(),
260
+ cid: record.cid,
261
+ value: record.value,
262
+ blobCids: findBlobRefs(record.value).map((blob) => blob.ref.toString()),
263
+ indexedAt: record.indexedAt,
264
+ repo,
265
+ moderation: {
266
+ subjectStatus: subjectStatus
267
+ ? this.formatSubjectStatus(subjectStatus)
268
+ : undefined,
269
+ },
270
+ })
271
+ }, new Map<string, RecordView>())
272
+ }
273
+
274
+ async recordDetail(
275
+ subject: RecordSubject,
276
+ ): Promise<RecordViewDetail | undefined> {
277
+ const [records, subjectStatusesResult] = await Promise.all([
278
+ this.records([subject]),
279
+ this.getSubjectStatus([subject.uri]),
280
+ ])
281
+ const record = records.get(subject.uri)
282
+ if (!record) return undefined
283
+
284
+ const status = subjectStatusesResult.get(subject.uri)
285
+
286
+ const [blobs, labels, subjectStatus] = await Promise.all([
287
+ this.blob(findBlobRefs(record.value)),
288
+ this.labels(record.uri),
289
+ status ? this.formatSubjectStatus(status) : Promise.resolve(undefined),
290
+ ])
291
+ const selfLabels = getSelfLabels({
292
+ uri: record.uri,
293
+ cid: record.cid,
294
+ record: record.value,
295
+ })
296
+ return {
297
+ ...record,
298
+ blobs,
299
+ moderation: {
300
+ ...record.moderation,
301
+ subjectStatus,
302
+ },
303
+ labels: [...labels, ...selfLabels],
304
+ }
305
+ }
306
+
307
+ formatReport(report: ModerationEventRowWithHandle): ReportOutput {
308
+ return {
309
+ id: report.id,
310
+ createdAt: report.createdAt,
311
+ // Ideally, we would never have a report entry that does not have a reasonType but at the schema level
312
+ // we are not guarantying that so in whatever case, if we end up with such entries, default to 'other'
313
+ reasonType: report.meta?.reportType
314
+ ? (report.meta?.reportType as string)
315
+ : REASONOTHER,
316
+ reason: report.comment ?? undefined,
317
+ reportedBy: report.createdBy,
318
+ subject: subjectFromEventRow(report).lex(),
319
+ }
320
+ }
321
+ // Partial view for subjects
322
+
323
+ async subject(subject: string): Promise<SubjectView> {
324
+ if (subject.startsWith('did:')) {
325
+ const repos = await this.repos([subject])
326
+ const repo = repos.get(subject)
327
+ if (repo) {
328
+ return {
329
+ $type: 'com.atproto.admin.defs#repoView',
330
+ ...repo,
331
+ }
332
+ } else {
333
+ return {
334
+ $type: 'com.atproto.admin.defs#repoViewNotFound',
335
+ did: subject,
336
+ }
337
+ }
338
+ } else {
339
+ const records = await this.records([{ uri: subject }])
340
+ const record = records.get(subject)
341
+ if (record) {
342
+ return {
343
+ $type: 'com.atproto.admin.defs#recordView',
344
+ ...record,
345
+ }
346
+ } else {
347
+ return {
348
+ $type: 'com.atproto.admin.defs#recordViewNotFound',
349
+ uri: subject,
350
+ }
351
+ }
352
+ }
353
+ }
354
+
355
+ // Partial view for blobs
356
+
357
+ async blob(blobs: BlobRef[]): Promise<BlobView[]> {
358
+ if (!blobs.length) return []
359
+ const { ref } = this.db.db.dynamic
360
+ const modStatusResults = await this.db.db
361
+ .selectFrom('moderation_subject_status')
362
+ .where(
363
+ sql<string>`${ref(
364
+ 'moderation_subject_status.blobCids',
365
+ )} @> ${JSON.stringify(blobs.map((blob) => blob.ref.toString()))}`,
366
+ )
367
+ .selectAll()
368
+ .executeTakeFirst()
369
+ const statusByCid = (modStatusResults?.blobCids || [])?.reduce(
370
+ (acc, cur) => Object.assign(acc, { [cur]: modStatusResults }),
371
+ {},
372
+ )
373
+ // Intentionally missing details field, since we don't have any on appview.
374
+ // We also don't know when the blob was created, so we use a canned creation time.
375
+ const unknownTime = new Date(0).toISOString()
376
+ return blobs.map((blob) => {
377
+ const cid = blob.ref.toString()
378
+ const subjectStatus = statusByCid[cid]
379
+ ? this.formatSubjectStatus(statusByCid[cid])
380
+ : undefined
381
+ return {
382
+ cid,
383
+ mimeType: blob.mimeType,
384
+ size: blob.size,
385
+ createdAt: unknownTime,
386
+ moderation: {
387
+ subjectStatus,
388
+ },
389
+ }
390
+ })
391
+ }
392
+
393
+ async labels(subject: string, includeNeg?: boolean): Promise<Label[]> {
394
+ const res = await this.db.db
395
+ .selectFrom('label')
396
+ .where('label.uri', '=', subject)
397
+ .if(!includeNeg, (qb) => qb.where('neg', '=', false))
398
+ .selectAll()
399
+ .execute()
400
+ return res.map((l) => ({
401
+ ...l,
402
+ cid: l.cid === '' ? undefined : l.cid,
403
+ neg: l.neg,
404
+ }))
405
+ }
406
+
407
+ async getSubjectStatus(
408
+ subjects: string[],
409
+ ): Promise<Map<string, ModerationSubjectStatusRowWithHandle>> {
410
+ const parsedSubjects = subjects.map((subject) => parseSubjectId(subject))
411
+ const filterForSubject = (did: string, recordPath?: string) => {
412
+ return (clause: any) => {
413
+ clause = clause
414
+ .where('moderation_subject_status.did', '=', did)
415
+ .where('moderation_subject_status.recordPath', '=', recordPath || '')
416
+ return clause
417
+ }
418
+ // TODO: Fix the typing here?
419
+ }
420
+
421
+ const builder = this.db.db
422
+ .selectFrom('moderation_subject_status')
423
+ .where((clause) => {
424
+ parsedSubjects.forEach((subject, i) => {
425
+ const applySubjectFilter = filterForSubject(
426
+ subject.did,
427
+ subject.recordPath,
428
+ )
429
+ if (i === 0) {
430
+ clause = clause.where(applySubjectFilter)
431
+ } else {
432
+ clause = clause.orWhere(applySubjectFilter)
433
+ }
434
+ })
435
+
436
+ return clause
437
+ })
438
+ .selectAll()
439
+
440
+ const [statusRes, accountsByDid] = await Promise.all([
441
+ builder.execute(),
442
+ this.getAccoutInfosByDid(parsedSubjects.map((s) => s.did)),
443
+ ])
444
+
445
+ return statusRes.reduce((acc, cur) => {
446
+ const subject = cur.recordPath
447
+ ? formatSubjectId(cur.did, cur.recordPath)
448
+ : cur.did
449
+ const handle = accountsByDid.get(cur.did)?.handle
450
+ return acc.set(subject, {
451
+ ...cur,
452
+ handle: handle ?? INVALID_HANDLE,
453
+ })
454
+ }, new Map<string, ModerationSubjectStatusRowWithHandle>())
455
+ }
456
+
457
+ formatSubjectStatus(
458
+ status: ModerationSubjectStatusRowWithHandle,
459
+ ): SubjectStatusView {
460
+ return {
461
+ id: status.id,
462
+ reviewState: status.reviewState,
463
+ createdAt: status.createdAt,
464
+ updatedAt: status.updatedAt,
465
+ comment: status.comment ?? undefined,
466
+ lastReviewedBy: status.lastReviewedBy ?? undefined,
467
+ lastReviewedAt: status.lastReviewedAt ?? undefined,
468
+ lastReportedAt: status.lastReportedAt ?? undefined,
469
+ lastAppealedAt: status.lastAppealedAt ?? undefined,
470
+ muteUntil: status.muteUntil ?? undefined,
471
+ suspendUntil: status.suspendUntil ?? undefined,
472
+ takendown: status.takendown ?? undefined,
473
+ appealed: status.appealed ?? undefined,
474
+ subjectRepoHandle: status.handle ?? undefined,
475
+ subjectBlobCids: status.blobCids || [],
476
+ subject: subjectFromStatusRow(status).lex(),
477
+ }
478
+ }
479
+ }
480
+
481
+ type RecordSubject = { uri: string; cid?: string }
482
+
483
+ type SubjectView = ModEventViewDetail['subject'] & ReportViewDetail['subject']
484
+
485
+ type RecordInfo = {
486
+ uri: string
487
+ cid: string
488
+ value: Record<string, unknown>
489
+ indexedAt: string
490
+ }
491
+
492
+ function parseSubjectId(subject: string) {
493
+ if (subject.startsWith('did:')) {
494
+ return { did: subject }
495
+ }
496
+ const uri = new AtUri(subject)
497
+ return { did: uri.hostname, recordPath: `${uri.collection}/${uri.rkey}` }
498
+ }
499
+
500
+ function formatSubjectId(did: string, recordPath?: string) {
501
+ return recordPath ? `at://${did}/${recordPath}` : did
502
+ }
503
+
504
+ function findBlobRefs(value: unknown, refs: BlobRef[] = []) {
505
+ if (value instanceof BlobRef) {
506
+ refs.push(value)
507
+ } else if (Array.isArray(value)) {
508
+ value.forEach((val) => findBlobRefs(val, refs))
509
+ } else if (value && typeof value === 'object') {
510
+ Object.values(value).forEach((val) => findBlobRefs(val, refs))
511
+ }
512
+ return refs
513
+ }
514
+
515
+ export function getSelfLabels(details: {
516
+ uri: string | null
517
+ cid: string | null
518
+ record: Record<string, unknown> | null
519
+ }): Label[] {
520
+ const { uri, cid, record } = details
521
+ if (!uri || !cid || !record) return []
522
+ if (!isSelfLabels(record.labels)) return []
523
+ const src = new AtUri(uri).host // record creator
524
+ const cts =
525
+ typeof record.createdAt === 'string'
526
+ ? normalizeDatetimeAlways(record.createdAt)
527
+ : new Date(0).toISOString()
528
+ return record.labels.values.map(({ val }) => {
529
+ return { src, uri, cid, val, cts, neg: false }
530
+ })
531
+ }
package/src/util.ts ADDED
@@ -0,0 +1,26 @@
1
+ import { AxiosError } from 'axios'
2
+ import { XRPCError, ResponseType } from '@atproto/xrpc'
3
+ import { RetryOptions, retry } from '@atproto/common'
4
+
5
+ export async function retryHttp<T>(
6
+ fn: () => Promise<T>,
7
+ opts: RetryOptions = {},
8
+ ): Promise<T> {
9
+ return retry(fn, { retryable: retryableHttp, ...opts })
10
+ }
11
+
12
+ export function retryableHttp(err: unknown) {
13
+ if (err instanceof XRPCError) {
14
+ if (err.status === ResponseType.Unknown) return true
15
+ return retryableHttpStatusCodes.has(err.status)
16
+ }
17
+ if (err instanceof AxiosError) {
18
+ if (!err.response) return true
19
+ return retryableHttpStatusCodes.has(err.response.status)
20
+ }
21
+ return false
22
+ }
23
+
24
+ const retryableHttpStatusCodes = new Set([
25
+ 408, 425, 429, 500, 502, 503, 504, 522, 524,
26
+ ])
package/test.env ADDED
@@ -0,0 +1,2 @@
1
+ LOG_ENABLED=true
2
+ LOG_DESTINATION=test.log
package/test.log ADDED
Binary file