@atproto/bsky 0.0.28 → 0.0.30
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.
- package/CHANGELOG.md +15 -0
- package/LICENSE.txt +1 -1
- package/dist/api/app/bsky/feed/getAuthorFeed.d.ts +1 -0
- package/dist/auto-moderator/index.d.ts +1 -14
- package/dist/context.d.ts +0 -3
- package/dist/db/index.js +43762 -12377
- package/dist/db/index.js.map +3 -3
- package/dist/db/pagination.d.ts +1 -0
- package/dist/index.d.ts +0 -4
- package/dist/index.js +2422 -2135
- package/dist/index.js.map +3 -3
- package/dist/indexer/config.d.ts +0 -8
- package/dist/lexicon/index.d.ts +0 -2
- package/dist/lexicon/lexicons.d.ts +134 -52
- package/dist/lexicon/types/app/bsky/actor/defs.d.ts +1 -0
- package/dist/lexicon/types/app/bsky/actor/getPreferences.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/actor/getProfile.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/actor/getProfiles.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/actor/getSuggestions.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/actor/searchActors.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/actor/searchActorsTypeahead.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/feed/describeFeedGenerator.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/feed/getActorFeeds.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/feed/getActorLikes.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/feed/getAuthorFeed.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/feed/getFeed.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/feed/getFeedGenerator.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/feed/getFeedGenerators.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/feed/getFeedSkeleton.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/feed/getLikes.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/feed/getListFeed.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/feed/getPostThread.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/feed/getPosts.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/feed/getRepostedBy.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/feed/getSuggestedFeeds.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/feed/getTimeline.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/feed/searchPosts.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/graph/getBlocks.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/graph/getFollowers.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/graph/getFollows.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/graph/getList.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/graph/getListBlocks.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/graph/getListMutes.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/graph/getLists.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/graph/getMutes.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/graph/getRelationships.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/graph/getSuggestedFollowsByActor.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/notification/getUnreadCount.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/notification/listNotifications.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/unspecced/getPopularFeedGenerators.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/unspecced/getTaggedSuggestions.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/unspecced/searchActorsSkeleton.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/unspecced/searchPostsSkeleton.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/admin/createCommunicationTemplate.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/admin/defs.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/admin/emitModerationEvent.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/admin/getAccountInfo.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/admin/getAccountInfos.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/admin/getInviteCodes.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/admin/getModerationEvent.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/admin/getRecord.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/admin/getRepo.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/admin/getSubjectStatus.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/admin/listCommunicationTemplates.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/admin/queryModerationEvents.d.ts +9 -2
- package/dist/lexicon/types/com/atproto/admin/queryModerationStatuses.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/admin/searchRepos.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/admin/sendEmail.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/admin/updateCommunicationTemplate.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/admin/updateSubjectStatus.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/identity/resolveHandle.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/label/queryLabels.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/moderation/createReport.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/repo/createRecord.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/repo/describeRepo.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/repo/getRecord.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/repo/listRecords.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/repo/putRecord.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/repo/uploadBlob.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/server/createAccount.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/server/createAppPassword.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/server/createInviteCode.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/server/createInviteCodes.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/server/createSession.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/server/describeServer.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/server/getAccountInviteCodes.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/server/getSession.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/server/listAppPasswords.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/server/refreshSession.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/server/requestEmailUpdate.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/server/reserveSigningKey.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/sync/getBlob.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/sync/getBlocks.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/sync/getCheckout.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/sync/getHead.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/sync/getLatestCommit.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/sync/getRecord.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/sync/getRepo.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/sync/listBlobs.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/sync/listRepos.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/temp/checkSignupQueue.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/temp/fetchLabels.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/temp/importRepo.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/temp/transferAccount.d.ts +2 -2
- package/dist/services/feed/index.d.ts +2 -1
- package/package.json +8 -7
- package/src/api/app/bsky/actor/getSuggestions.ts +1 -1
- package/src/api/app/bsky/actor/searchActors.ts +1 -0
- package/src/api/app/bsky/feed/getActorFeeds.ts +6 -0
- package/src/api/app/bsky/feed/getActorLikes.ts +4 -0
- package/src/api/app/bsky/feed/getAuthorFeed.ts +16 -4
- package/src/api/app/bsky/feed/getFeed.ts +8 -5
- package/src/api/app/bsky/feed/getLikes.ts +4 -0
- package/src/api/app/bsky/feed/getListFeed.ts +4 -0
- package/src/api/app/bsky/feed/getRepostedBy.ts +4 -0
- package/src/api/app/bsky/feed/getSuggestedFeeds.ts +1 -1
- package/src/api/app/bsky/feed/getTimeline.ts +4 -0
- package/src/api/app/bsky/feed/searchPosts.ts +1 -0
- package/src/api/app/bsky/graph/getBlocks.ts +7 -0
- package/src/api/app/bsky/graph/getFollowers.ts +4 -0
- package/src/api/app/bsky/graph/getFollows.ts +4 -0
- package/src/api/app/bsky/graph/getList.ts +4 -0
- package/src/api/app/bsky/graph/getListBlocks.ts +4 -0
- package/src/api/app/bsky/graph/getListMutes.ts +7 -0
- package/src/api/app/bsky/graph/getLists.ts +7 -0
- package/src/api/app/bsky/graph/getMutes.ts +7 -0
- package/src/api/app/bsky/notification/listNotifications.ts +3 -0
- package/src/api/app/bsky/unspecced/getPopularFeedGenerators.ts +7 -1
- package/src/api/index.ts +0 -6
- package/src/auto-moderator/index.ts +9 -176
- package/src/context.ts +0 -6
- package/src/db/pagination.ts +3 -0
- package/src/index.ts +1 -6
- package/src/indexer/config.ts +0 -29
- package/src/lexicon/index.ts +0 -12
- package/src/lexicon/lexicons.ts +382 -173
- package/src/lexicon/types/app/bsky/actor/defs.ts +2 -0
- package/src/lexicon/types/app/bsky/actor/getPreferences.ts +2 -2
- package/src/lexicon/types/app/bsky/actor/getProfile.ts +3 -2
- package/src/lexicon/types/app/bsky/actor/getProfiles.ts +2 -2
- package/src/lexicon/types/app/bsky/actor/getSuggestions.ts +2 -2
- package/src/lexicon/types/app/bsky/actor/profile.ts +3 -0
- package/src/lexicon/types/app/bsky/actor/putPreferences.ts +1 -1
- package/src/lexicon/types/app/bsky/actor/searchActors.ts +2 -2
- package/src/lexicon/types/app/bsky/actor/searchActorsTypeahead.ts +2 -2
- package/src/lexicon/types/app/bsky/embed/external.ts +1 -0
- package/src/lexicon/types/app/bsky/embed/images.ts +4 -0
- package/src/lexicon/types/app/bsky/embed/record.ts +1 -0
- package/src/lexicon/types/app/bsky/feed/defs.ts +1 -0
- package/src/lexicon/types/app/bsky/feed/describeFeedGenerator.ts +2 -2
- package/src/lexicon/types/app/bsky/feed/getActorFeeds.ts +2 -2
- package/src/lexicon/types/app/bsky/feed/getActorLikes.ts +2 -2
- package/src/lexicon/types/app/bsky/feed/getAuthorFeed.ts +3 -2
- package/src/lexicon/types/app/bsky/feed/getFeed.ts +2 -2
- package/src/lexicon/types/app/bsky/feed/getFeedGenerator.ts +5 -2
- package/src/lexicon/types/app/bsky/feed/getFeedGenerators.ts +2 -2
- package/src/lexicon/types/app/bsky/feed/getFeedSkeleton.ts +3 -2
- package/src/lexicon/types/app/bsky/feed/getLikes.ts +4 -2
- package/src/lexicon/types/app/bsky/feed/getListFeed.ts +3 -2
- package/src/lexicon/types/app/bsky/feed/getPostThread.ts +5 -2
- package/src/lexicon/types/app/bsky/feed/getPosts.ts +3 -2
- package/src/lexicon/types/app/bsky/feed/getRepostedBy.ts +4 -2
- package/src/lexicon/types/app/bsky/feed/getSuggestedFeeds.ts +2 -2
- package/src/lexicon/types/app/bsky/feed/getTimeline.ts +3 -2
- package/src/lexicon/types/app/bsky/feed/post.ts +5 -1
- package/src/lexicon/types/app/bsky/feed/searchPosts.ts +2 -2
- package/src/lexicon/types/app/bsky/feed/threadgate.ts +1 -0
- package/src/lexicon/types/app/bsky/graph/block.ts +1 -0
- package/src/lexicon/types/app/bsky/graph/getBlocks.ts +2 -2
- package/src/lexicon/types/app/bsky/graph/getFollowers.ts +2 -2
- package/src/lexicon/types/app/bsky/graph/getFollows.ts +2 -2
- package/src/lexicon/types/app/bsky/graph/getList.ts +3 -2
- package/src/lexicon/types/app/bsky/graph/getListBlocks.ts +2 -2
- package/src/lexicon/types/app/bsky/graph/getListMutes.ts +2 -2
- package/src/lexicon/types/app/bsky/graph/getLists.ts +3 -2
- package/src/lexicon/types/app/bsky/graph/getMutes.ts +2 -2
- package/src/lexicon/types/app/bsky/graph/getRelationships.ts +4 -2
- package/src/lexicon/types/app/bsky/graph/getSuggestedFollowsByActor.ts +2 -2
- package/src/lexicon/types/app/bsky/graph/list.ts +1 -0
- package/src/lexicon/types/app/bsky/graph/listblock.ts +1 -0
- package/src/lexicon/types/app/bsky/graph/listitem.ts +2 -0
- package/src/lexicon/types/app/bsky/graph/muteActor.ts +1 -1
- package/src/lexicon/types/app/bsky/graph/muteActorList.ts +1 -1
- package/src/lexicon/types/app/bsky/graph/unmuteActor.ts +1 -1
- package/src/lexicon/types/app/bsky/graph/unmuteActorList.ts +1 -1
- package/src/lexicon/types/app/bsky/notification/getUnreadCount.ts +2 -2
- package/src/lexicon/types/app/bsky/notification/listNotifications.ts +2 -2
- package/src/lexicon/types/app/bsky/notification/registerPush.ts +1 -1
- package/src/lexicon/types/app/bsky/notification/updateSeen.ts +1 -1
- package/src/lexicon/types/app/bsky/richtext/facet.ts +5 -4
- package/src/lexicon/types/app/bsky/unspecced/getPopularFeedGenerators.ts +2 -2
- package/src/lexicon/types/app/bsky/unspecced/getTaggedSuggestions.ts +2 -2
- package/src/lexicon/types/app/bsky/unspecced/searchActorsSkeleton.ts +2 -2
- package/src/lexicon/types/app/bsky/unspecced/searchPostsSkeleton.ts +2 -2
- package/src/lexicon/types/com/atproto/admin/createCommunicationTemplate.ts +2 -2
- package/src/lexicon/types/com/atproto/admin/defs.ts +2 -0
- package/src/lexicon/types/com/atproto/admin/deleteAccount.ts +1 -1
- package/src/lexicon/types/com/atproto/admin/deleteCommunicationTemplate.ts +1 -1
- package/src/lexicon/types/com/atproto/admin/disableAccountInvites.ts +1 -1
- package/src/lexicon/types/com/atproto/admin/disableInviteCodes.ts +1 -1
- package/src/lexicon/types/com/atproto/admin/emitModerationEvent.ts +2 -2
- package/src/lexicon/types/com/atproto/admin/enableAccountInvites.ts +1 -1
- package/src/lexicon/types/com/atproto/admin/getAccountInfo.ts +2 -2
- package/src/lexicon/types/com/atproto/admin/getAccountInfos.ts +2 -2
- package/src/lexicon/types/com/atproto/admin/getInviteCodes.ts +2 -2
- package/src/lexicon/types/com/atproto/admin/getModerationEvent.ts +2 -2
- package/src/lexicon/types/com/atproto/admin/getRecord.ts +2 -2
- package/src/lexicon/types/com/atproto/admin/getRepo.ts +2 -2
- package/src/lexicon/types/com/atproto/admin/getSubjectStatus.ts +2 -2
- package/src/lexicon/types/com/atproto/admin/listCommunicationTemplates.ts +2 -2
- package/src/lexicon/types/com/atproto/admin/queryModerationEvents.ts +15 -2
- package/src/lexicon/types/com/atproto/admin/queryModerationStatuses.ts +2 -2
- package/src/lexicon/types/com/atproto/admin/searchRepos.ts +2 -2
- package/src/lexicon/types/com/atproto/admin/sendEmail.ts +2 -2
- package/src/lexicon/types/com/atproto/admin/updateAccountEmail.ts +1 -1
- package/src/lexicon/types/com/atproto/admin/updateAccountHandle.ts +1 -1
- package/src/lexicon/types/com/atproto/admin/updateCommunicationTemplate.ts +2 -2
- package/src/lexicon/types/com/atproto/admin/updateSubjectStatus.ts +2 -2
- package/src/lexicon/types/com/atproto/identity/resolveHandle.ts +2 -2
- package/src/lexicon/types/com/atproto/identity/updateHandle.ts +2 -1
- package/src/lexicon/types/com/atproto/label/queryLabels.ts +2 -2
- package/src/lexicon/types/com/atproto/label/subscribeLabels.ts +1 -1
- package/src/lexicon/types/com/atproto/moderation/createReport.ts +3 -2
- package/src/lexicon/types/com/atproto/repo/applyWrites.ts +7 -6
- package/src/lexicon/types/com/atproto/repo/createRecord.ts +6 -6
- package/src/lexicon/types/com/atproto/repo/deleteRecord.ts +3 -3
- package/src/lexicon/types/com/atproto/repo/describeRepo.ts +5 -2
- package/src/lexicon/types/com/atproto/repo/getRecord.ts +3 -3
- package/src/lexicon/types/com/atproto/repo/listRecords.ts +2 -2
- package/src/lexicon/types/com/atproto/repo/putRecord.ts +6 -6
- package/src/lexicon/types/com/atproto/repo/uploadBlob.ts +2 -2
- package/src/lexicon/types/com/atproto/server/confirmEmail.ts +1 -1
- package/src/lexicon/types/com/atproto/server/createAccount.ts +10 -2
- package/src/lexicon/types/com/atproto/server/createAppPassword.ts +3 -2
- package/src/lexicon/types/com/atproto/server/createInviteCode.ts +2 -2
- package/src/lexicon/types/com/atproto/server/createInviteCodes.ts +2 -2
- package/src/lexicon/types/com/atproto/server/createSession.ts +2 -2
- package/src/lexicon/types/com/atproto/server/deleteAccount.ts +1 -1
- package/src/lexicon/types/com/atproto/server/deleteSession.ts +1 -1
- package/src/lexicon/types/com/atproto/server/describeServer.ts +5 -2
- package/src/lexicon/types/com/atproto/server/getAccountInviteCodes.ts +3 -2
- package/src/lexicon/types/com/atproto/server/getSession.ts +2 -2
- package/src/lexicon/types/com/atproto/server/listAppPasswords.ts +2 -2
- package/src/lexicon/types/com/atproto/server/refreshSession.ts +2 -2
- package/src/lexicon/types/com/atproto/server/requestAccountDelete.ts +1 -1
- package/src/lexicon/types/com/atproto/server/requestEmailConfirmation.ts +1 -1
- package/src/lexicon/types/com/atproto/server/requestEmailUpdate.ts +2 -2
- package/src/lexicon/types/com/atproto/server/requestPasswordReset.ts +1 -1
- package/src/lexicon/types/com/atproto/server/reserveSigningKey.ts +4 -4
- package/src/lexicon/types/com/atproto/server/resetPassword.ts +1 -1
- package/src/lexicon/types/com/atproto/server/revokeAppPassword.ts +1 -1
- package/src/lexicon/types/com/atproto/server/updateEmail.ts +1 -1
- package/src/lexicon/types/com/atproto/sync/getBlob.ts +3 -3
- package/src/lexicon/types/com/atproto/sync/getBlocks.ts +2 -2
- package/src/lexicon/types/com/atproto/sync/getCheckout.ts +2 -2
- package/src/lexicon/types/com/atproto/sync/getHead.ts +2 -2
- package/src/lexicon/types/com/atproto/sync/getLatestCommit.ts +2 -2
- package/src/lexicon/types/com/atproto/sync/getRecord.ts +3 -2
- package/src/lexicon/types/com/atproto/sync/getRepo.ts +3 -3
- package/src/lexicon/types/com/atproto/sync/listBlobs.ts +2 -2
- package/src/lexicon/types/com/atproto/sync/listRepos.ts +3 -2
- package/src/lexicon/types/com/atproto/sync/notifyOfUpdate.ts +2 -2
- package/src/lexicon/types/com/atproto/sync/requestCrawl.ts +2 -2
- package/src/lexicon/types/com/atproto/sync/subscribeRepos.ts +17 -5
- package/src/lexicon/types/com/atproto/temp/checkSignupQueue.ts +2 -2
- package/src/lexicon/types/com/atproto/temp/fetchLabels.ts +2 -2
- package/src/lexicon/types/com/atproto/temp/importRepo.ts +2 -2
- package/src/lexicon/types/com/atproto/temp/pushBlob.ts +1 -1
- package/src/lexicon/types/com/atproto/temp/requestPhoneVerification.ts +1 -1
- package/src/lexicon/types/com/atproto/temp/transferAccount.ts +2 -2
- package/src/logger.ts +32 -0
- package/src/services/feed/index.ts +10 -4
- package/src/services/feed/views.ts +3 -1
- package/tests/auto-moderator/labeler.test.ts +2 -0
- package/tests/feed-generation.test.ts +0 -6
- package/tests/views/author-feed.test.ts +29 -9
- package/tests/views/notifications.test.ts +9 -0
- package/tests/views/timeline.test.ts +8 -0
- package/dist/api/app/bsky/feed/describeFeedGenerator.d.ts +0 -3
- package/dist/api/app/bsky/feed/getFeedSkeleton.d.ts +0 -3
- package/dist/api/app/bsky/unspecced/getTimelineSkeleton.d.ts +0 -3
- package/dist/auto-moderator/abyss.d.ts +0 -48
- package/dist/auto-moderator/fuzzy-matcher.d.ts +0 -14
- package/dist/feed-gen/bsky-team.d.ts +0 -3
- package/dist/feed-gen/hot-classic.d.ts +0 -3
- package/dist/feed-gen/index.d.ts +0 -2
- package/dist/feed-gen/mutuals.d.ts +0 -3
- package/dist/feed-gen/types.d.ts +0 -15
- package/dist/lexicon/types/app/bsky/unspecced/getTimelineSkeleton.d.ts +0 -35
- package/src/api/app/bsky/feed/describeFeedGenerator.ts +0 -21
- package/src/api/app/bsky/feed/getFeedSkeleton.ts +0 -30
- package/src/api/app/bsky/unspecced/getTimelineSkeleton.ts +0 -26
- package/src/auto-moderator/abyss.ts +0 -114
- package/src/auto-moderator/fuzzy-matcher.ts +0 -126
- package/src/feed-gen/bsky-team.ts +0 -42
- package/src/feed-gen/hot-classic.ts +0 -55
- package/src/feed-gen/index.ts +0 -17
- package/src/feed-gen/mutuals.ts +0 -57
- package/src/feed-gen/types.ts +0 -32
- package/src/lexicon/types/app/bsky/unspecced/getTimelineSkeleton.ts +0 -49
- package/tests/algos/hot-classic.test.ts +0 -87
- package/tests/auto-moderator/fuzzy-matcher.test.ts +0 -163
- package/tests/auto-moderator/takedowns.test.ts +0 -202
|
@@ -6,7 +6,7 @@ import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
|
|
6
6
|
import { lexicons } from '../../../../lexicons'
|
|
7
7
|
import { isObj, hasProp } from '../../../../util'
|
|
8
8
|
import { CID } from 'multiformats/cid'
|
|
9
|
-
import { HandlerAuth } from '@atproto/xrpc-server'
|
|
9
|
+
import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
|
|
10
10
|
|
|
11
11
|
export interface QueryParams {}
|
|
12
12
|
|
|
@@ -49,7 +49,7 @@ export interface HandlerError {
|
|
|
49
49
|
| 'IncompatibleDidDoc'
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
export type HandlerOutput = HandlerError | HandlerSuccess
|
|
52
|
+
export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough
|
|
53
53
|
export type HandlerReqCtx<HA extends HandlerAuth = never> = {
|
|
54
54
|
auth: HA
|
|
55
55
|
params: QueryParams
|
package/src/logger.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import pino from 'pino'
|
|
1
2
|
import pinoHttp from 'pino-http'
|
|
3
|
+
import * as jose from 'jose'
|
|
2
4
|
import { subsystemLogger } from '@atproto/common'
|
|
5
|
+
import { parseBasicAuth } from './auth-verifier'
|
|
3
6
|
|
|
4
7
|
export const dbLogger: ReturnType<typeof subsystemLogger> =
|
|
5
8
|
subsystemLogger('bsky:db')
|
|
@@ -21,5 +24,34 @@ export const loggerMiddleware = pinoHttp({
|
|
|
21
24
|
message: err?.message,
|
|
22
25
|
}
|
|
23
26
|
},
|
|
27
|
+
req: (req) => {
|
|
28
|
+
const serialized = pino.stdSerializers.req(req)
|
|
29
|
+
const authHeader = serialized.headers.authorization || ''
|
|
30
|
+
let auth: string | undefined = undefined
|
|
31
|
+
if (authHeader.startsWith('Bearer ')) {
|
|
32
|
+
const token = authHeader.slice('Bearer '.length)
|
|
33
|
+
const { iss } = jose.decodeJwt(token)
|
|
34
|
+
if (iss) {
|
|
35
|
+
auth = 'Bearer ' + iss
|
|
36
|
+
} else {
|
|
37
|
+
auth = 'Bearer Invalid'
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (authHeader.startsWith('Basic ')) {
|
|
41
|
+
const parsed = parseBasicAuth(authHeader)
|
|
42
|
+
if (!parsed) {
|
|
43
|
+
auth = 'Basic Invalid'
|
|
44
|
+
} else {
|
|
45
|
+
auth = 'Basic ' + parsed.username
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
...serialized,
|
|
50
|
+
headers: {
|
|
51
|
+
...serialized.headers,
|
|
52
|
+
authorization: auth,
|
|
53
|
+
},
|
|
54
|
+
}
|
|
55
|
+
},
|
|
24
56
|
},
|
|
25
57
|
})
|
|
@@ -139,6 +139,7 @@ export class FeedService {
|
|
|
139
139
|
async getPostInfos(
|
|
140
140
|
postUris: string[],
|
|
141
141
|
viewer: string | null,
|
|
142
|
+
includeSoftDeleted?: boolean,
|
|
142
143
|
): Promise<PostInfoMap> {
|
|
143
144
|
if (postUris.length < 1) return {}
|
|
144
145
|
const db = this.db.db
|
|
@@ -149,8 +150,12 @@ export class FeedService {
|
|
|
149
150
|
.innerJoin('actor', 'actor.did', 'post.creator')
|
|
150
151
|
.innerJoin('record', 'record.uri', 'post.uri')
|
|
151
152
|
.leftJoin('post_agg', 'post_agg.uri', 'post.uri')
|
|
152
|
-
.
|
|
153
|
-
|
|
153
|
+
.if(!includeSoftDeleted, (qb) =>
|
|
154
|
+
qb.where(notSoftDeletedClause(ref('actor'))),
|
|
155
|
+
) // Ensures post reply parent/roots get omitted from views when taken down
|
|
156
|
+
.if(!includeSoftDeleted, (qb) =>
|
|
157
|
+
qb.where(notSoftDeletedClause(ref('record'))),
|
|
158
|
+
)
|
|
154
159
|
.select([
|
|
155
160
|
'post.uri as uri',
|
|
156
161
|
'post.cid as cid',
|
|
@@ -249,12 +254,13 @@ export class FeedService {
|
|
|
249
254
|
dids: Set<string>
|
|
250
255
|
uris: Set<string>
|
|
251
256
|
viewer: string | null
|
|
257
|
+
includeSoftDeleted?: boolean
|
|
252
258
|
},
|
|
253
259
|
depth = 0,
|
|
254
260
|
): Promise<FeedHydrationState> {
|
|
255
261
|
const { viewer, dids, uris } = refs
|
|
256
262
|
const [posts, threadgates, labels, bam] = await Promise.all([
|
|
257
|
-
this.getPostInfos(Array.from(uris), viewer),
|
|
263
|
+
this.getPostInfos(Array.from(uris), viewer, refs.includeSoftDeleted),
|
|
258
264
|
this.threadgatesByPostUri(Array.from(uris)),
|
|
259
265
|
this.services.label.getLabelsForSubjects([...uris, ...dids]),
|
|
260
266
|
this.services.graph.getBlockAndMuteState(
|
|
@@ -266,7 +272,7 @@ export class FeedService {
|
|
|
266
272
|
const [profileState, blocks, lists] = await Promise.all([
|
|
267
273
|
this.services.actor.views.profileHydration(
|
|
268
274
|
Array.from(dids),
|
|
269
|
-
{ viewer },
|
|
275
|
+
{ viewer, includeSoftDeleted: refs.includeSoftDeleted },
|
|
270
276
|
{ bam, labels },
|
|
271
277
|
),
|
|
272
278
|
this.blocksForPosts(posts, bam),
|
|
@@ -208,7 +208,9 @@ export class FeedViews {
|
|
|
208
208
|
const post = posts[uri]
|
|
209
209
|
const gate = threadgates[uri]
|
|
210
210
|
const author = actors[post?.creator]
|
|
211
|
-
if (!post || !author)
|
|
211
|
+
if (!post || !author) {
|
|
212
|
+
return undefined
|
|
213
|
+
}
|
|
212
214
|
const postLabels = labels[uri] ?? []
|
|
213
215
|
const postSelfLabels = getSelfLabels({
|
|
214
216
|
uri: post.uri,
|
|
@@ -86,12 +86,6 @@ describe('feed generation', () => {
|
|
|
86
86
|
await network.close()
|
|
87
87
|
})
|
|
88
88
|
|
|
89
|
-
// @TODO enable once getFeed is implemented
|
|
90
|
-
it('describes the feed generator', async () => {
|
|
91
|
-
const res = await agent.api.app.bsky.feed.describeFeedGenerator()
|
|
92
|
-
expect(res.data.did).toBe(network.bsky.ctx.cfg.feedGenDid)
|
|
93
|
-
})
|
|
94
|
-
|
|
95
89
|
it('feed gen records can be created.', async () => {
|
|
96
90
|
const all = await pdsAgent.api.app.bsky.feed.generator.create(
|
|
97
91
|
{ repo: alice, rkey: 'all' },
|
|
@@ -138,7 +138,7 @@ describe('pds author feed views', () => {
|
|
|
138
138
|
)
|
|
139
139
|
})
|
|
140
140
|
|
|
141
|
-
it('blocked by actor takedown.', async () => {
|
|
141
|
+
it('non-admins blocked by actor takedown.', async () => {
|
|
142
142
|
const { data: preBlock } = await agent.api.app.bsky.feed.getAuthorFeed(
|
|
143
143
|
{ actor: alice },
|
|
144
144
|
{ headers: await network.serviceHeaders(carol) },
|
|
@@ -163,11 +163,18 @@ describe('pds author feed views', () => {
|
|
|
163
163
|
},
|
|
164
164
|
)
|
|
165
165
|
|
|
166
|
-
const
|
|
166
|
+
const attemptAsUser = agent.api.app.bsky.feed.getAuthorFeed(
|
|
167
167
|
{ actor: alice },
|
|
168
168
|
{ headers: await network.serviceHeaders(carol) },
|
|
169
169
|
)
|
|
170
|
-
await expect(
|
|
170
|
+
await expect(attemptAsUser).rejects.toThrow('Profile not found')
|
|
171
|
+
|
|
172
|
+
const attemptAsAdmin = await agent.api.app.bsky.feed.getAuthorFeed(
|
|
173
|
+
{ actor: alice },
|
|
174
|
+
{ headers: network.bsky.adminAuthHeaders() },
|
|
175
|
+
)
|
|
176
|
+
expect(attemptAsAdmin.data.feed.length).toBeGreaterThan(0)
|
|
177
|
+
expect(attemptAsAdmin.data.feed.length).toEqual(preBlock.feed.length)
|
|
171
178
|
|
|
172
179
|
// Cleanup
|
|
173
180
|
await agent.api.com.atproto.admin.updateSubjectStatus(
|
|
@@ -215,13 +222,26 @@ describe('pds author feed views', () => {
|
|
|
215
222
|
},
|
|
216
223
|
)
|
|
217
224
|
|
|
218
|
-
const { data:
|
|
219
|
-
|
|
220
|
-
|
|
225
|
+
const [{ data: postBlockAsUser }, { data: postBlockAsAdmin }] =
|
|
226
|
+
await Promise.all([
|
|
227
|
+
agent.api.app.bsky.feed.getAuthorFeed(
|
|
228
|
+
{ actor: alice },
|
|
229
|
+
{ headers: await network.serviceHeaders(carol) },
|
|
230
|
+
),
|
|
231
|
+
agent.api.app.bsky.feed.getAuthorFeed(
|
|
232
|
+
{ actor: alice },
|
|
233
|
+
{ headers: network.bsky.adminAuthHeaders() },
|
|
234
|
+
),
|
|
235
|
+
])
|
|
236
|
+
|
|
237
|
+
expect(postBlockAsUser.feed.length).toEqual(preBlock.feed.length - 1)
|
|
238
|
+
expect(postBlockAsUser.feed.map((item) => item.post.uri)).not.toContain(
|
|
239
|
+
post.uri,
|
|
240
|
+
)
|
|
241
|
+
expect(postBlockAsAdmin.feed.length).toEqual(preBlock.feed.length)
|
|
242
|
+
expect(postBlockAsAdmin.feed.map((item) => item.post.uri)).toContain(
|
|
243
|
+
post.uri,
|
|
221
244
|
)
|
|
222
|
-
|
|
223
|
-
expect(postBlock.feed.length).toEqual(preBlock.feed.length - 1)
|
|
224
|
-
expect(postBlock.feed.map((item) => item.post.uri)).not.toContain(post.uri)
|
|
225
245
|
|
|
226
246
|
// Cleanup
|
|
227
247
|
await agent.api.com.atproto.admin.updateSubjectStatus(
|
|
@@ -296,4 +296,13 @@ describe('notification views', () => {
|
|
|
296
296
|
),
|
|
297
297
|
)
|
|
298
298
|
})
|
|
299
|
+
|
|
300
|
+
it('fails open on clearly bad cursor.', async () => {
|
|
301
|
+
const { data: notifs } =
|
|
302
|
+
await agent.api.app.bsky.notification.listNotifications(
|
|
303
|
+
{ cursor: 'bad' },
|
|
304
|
+
{ headers: await network.serviceHeaders(alice) },
|
|
305
|
+
)
|
|
306
|
+
expect(notifs).toEqual({ notifications: [] })
|
|
307
|
+
})
|
|
299
308
|
})
|
|
@@ -298,4 +298,12 @@ describe('timeline views', () => {
|
|
|
298
298
|
),
|
|
299
299
|
)
|
|
300
300
|
})
|
|
301
|
+
|
|
302
|
+
it('fails open on clearly bad cursor.', async () => {
|
|
303
|
+
const { data: timeline } = await agent.api.app.bsky.feed.getTimeline(
|
|
304
|
+
{ cursor: 'bad' },
|
|
305
|
+
{ headers: await network.serviceHeaders(alice) },
|
|
306
|
+
)
|
|
307
|
+
expect(timeline).toEqual({ feed: [] })
|
|
308
|
+
})
|
|
301
309
|
})
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { CID } from 'multiformats/cid';
|
|
2
|
-
import { AtUri } from '@atproto/syntax';
|
|
3
|
-
import { PrimaryDatabase } from '../db';
|
|
4
|
-
import { IdResolver } from '@atproto/identity';
|
|
5
|
-
export interface ImageFlagger {
|
|
6
|
-
scanImage(did: string, cid: CID, uri: AtUri): Promise<string[]>;
|
|
7
|
-
}
|
|
8
|
-
export declare class Abyss implements ImageFlagger {
|
|
9
|
-
endpoint: string;
|
|
10
|
-
protected password: string;
|
|
11
|
-
ctx: {
|
|
12
|
-
db: PrimaryDatabase;
|
|
13
|
-
idResolver: IdResolver;
|
|
14
|
-
};
|
|
15
|
-
protected auth: string;
|
|
16
|
-
constructor(endpoint: string, password: string, ctx: {
|
|
17
|
-
db: PrimaryDatabase;
|
|
18
|
-
idResolver: IdResolver;
|
|
19
|
-
});
|
|
20
|
-
scanImage(did: string, cid: CID, uri: AtUri): Promise<string[]>;
|
|
21
|
-
makeReq(did: string, cid: CID, uri: AtUri): Promise<ScannerResp>;
|
|
22
|
-
parseRes(res: ScannerResp): string[];
|
|
23
|
-
getReqUrl(params: {
|
|
24
|
-
did: string;
|
|
25
|
-
uri: string;
|
|
26
|
-
}): string;
|
|
27
|
-
}
|
|
28
|
-
type ScannerResp = {
|
|
29
|
-
blob: unknown;
|
|
30
|
-
match?: {
|
|
31
|
-
status: string;
|
|
32
|
-
hits: ScannerHit[];
|
|
33
|
-
};
|
|
34
|
-
classify?: {
|
|
35
|
-
hits?: unknown[];
|
|
36
|
-
};
|
|
37
|
-
review?: {
|
|
38
|
-
state?: string;
|
|
39
|
-
ticketId?: string;
|
|
40
|
-
};
|
|
41
|
-
};
|
|
42
|
-
type ScannerHit = {
|
|
43
|
-
hashType: string;
|
|
44
|
-
hashValue: string;
|
|
45
|
-
label: string;
|
|
46
|
-
corpus: string;
|
|
47
|
-
};
|
|
48
|
-
export {};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export interface TextFlagger {
|
|
2
|
-
getMatches(string: string): string[];
|
|
3
|
-
}
|
|
4
|
-
export declare class FuzzyMatcher implements TextFlagger {
|
|
5
|
-
private bannedWords;
|
|
6
|
-
private falsePositives;
|
|
7
|
-
constructor(bannedWords: string[], falsePositives?: string[]);
|
|
8
|
-
static fromB64(bannedB64: string, falsePositivesB64?: string): FuzzyMatcher;
|
|
9
|
-
private normalize;
|
|
10
|
-
private generatePermutations;
|
|
11
|
-
getMatches(domain: string): string[];
|
|
12
|
-
}
|
|
13
|
-
export declare const decode: (encoded: string) => string[];
|
|
14
|
-
export declare const encode: (words: string[]) => string;
|
package/dist/feed-gen/index.d.ts
DELETED
package/dist/feed-gen/types.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import AppContext from '../context';
|
|
2
|
-
import { SkeletonFeedPost } from '../lexicon/types/app/bsky/feed/defs';
|
|
3
|
-
import { QueryParams as SkeletonParams } from '../lexicon/types/app/bsky/feed/getFeedSkeleton';
|
|
4
|
-
import { FeedRow } from '../services/feed';
|
|
5
|
-
export type AlgoResponse = {
|
|
6
|
-
feedItems: FeedRow[];
|
|
7
|
-
resHeaders?: Record<string, string>;
|
|
8
|
-
cursor?: string;
|
|
9
|
-
};
|
|
10
|
-
export type AlgoHandler = (ctx: AppContext, params: SkeletonParams, viewer: string | null) => Promise<AlgoResponse>;
|
|
11
|
-
export type MountedAlgos = Record<string, AlgoHandler>;
|
|
12
|
-
export declare const toSkeletonItem: (feedItem: {
|
|
13
|
-
uri: string;
|
|
14
|
-
postUri: string;
|
|
15
|
-
}) => SkeletonFeedPost;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import express from 'express';
|
|
2
|
-
import { HandlerAuth } from '@atproto/xrpc-server';
|
|
3
|
-
import * as AppBskyFeedDefs from '../feed/defs';
|
|
4
|
-
export interface QueryParams {
|
|
5
|
-
limit: number;
|
|
6
|
-
cursor?: string;
|
|
7
|
-
}
|
|
8
|
-
export type InputSchema = undefined;
|
|
9
|
-
export interface OutputSchema {
|
|
10
|
-
cursor?: string;
|
|
11
|
-
feed: AppBskyFeedDefs.SkeletonFeedPost[];
|
|
12
|
-
[k: string]: unknown;
|
|
13
|
-
}
|
|
14
|
-
export type HandlerInput = undefined;
|
|
15
|
-
export interface HandlerSuccess {
|
|
16
|
-
encoding: 'application/json';
|
|
17
|
-
body: OutputSchema;
|
|
18
|
-
headers?: {
|
|
19
|
-
[key: string]: string;
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
export interface HandlerError {
|
|
23
|
-
status: number;
|
|
24
|
-
message?: string;
|
|
25
|
-
error?: 'UnknownFeed';
|
|
26
|
-
}
|
|
27
|
-
export type HandlerOutput = HandlerError | HandlerSuccess;
|
|
28
|
-
export type HandlerReqCtx<HA extends HandlerAuth = never> = {
|
|
29
|
-
auth: HA;
|
|
30
|
-
params: QueryParams;
|
|
31
|
-
input: HandlerInput;
|
|
32
|
-
req: express.Request;
|
|
33
|
-
res: express.Response;
|
|
34
|
-
};
|
|
35
|
-
export type Handler<HA extends HandlerAuth = never> = (ctx: HandlerReqCtx<HA>) => Promise<HandlerOutput> | HandlerOutput;
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { MethodNotImplementedError } from '@atproto/xrpc-server'
|
|
2
|
-
import { Server } from '../../../../lexicon'
|
|
3
|
-
import AppContext from '../../../../context'
|
|
4
|
-
|
|
5
|
-
export default function (server: Server, ctx: AppContext) {
|
|
6
|
-
server.app.bsky.feed.describeFeedGenerator(async () => {
|
|
7
|
-
if (!ctx.cfg.feedGenDid) {
|
|
8
|
-
throw new MethodNotImplementedError()
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const feeds = Object.keys(ctx.algos).map((uri) => ({ uri }))
|
|
12
|
-
|
|
13
|
-
return {
|
|
14
|
-
encoding: 'application/json',
|
|
15
|
-
body: {
|
|
16
|
-
did: ctx.cfg.feedGenDid,
|
|
17
|
-
feeds,
|
|
18
|
-
},
|
|
19
|
-
}
|
|
20
|
-
})
|
|
21
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { InvalidRequestError } from '@atproto/xrpc-server'
|
|
2
|
-
import { Server } from '../../../../lexicon'
|
|
3
|
-
import AppContext from '../../../../context'
|
|
4
|
-
import { toSkeletonItem } from '../../../../feed-gen/types'
|
|
5
|
-
|
|
6
|
-
export default function (server: Server, ctx: AppContext) {
|
|
7
|
-
server.app.bsky.feed.getFeedSkeleton({
|
|
8
|
-
auth: ctx.authVerifier.standardOptional,
|
|
9
|
-
handler: async ({ params, auth }) => {
|
|
10
|
-
const { feed } = params
|
|
11
|
-
const viewer = auth.credentials.iss
|
|
12
|
-
const localAlgo = ctx.algos[feed]
|
|
13
|
-
|
|
14
|
-
if (!localAlgo) {
|
|
15
|
-
throw new InvalidRequestError('Unknown feed', 'UnknownFeed')
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const result = await localAlgo(ctx, params, viewer)
|
|
19
|
-
|
|
20
|
-
return {
|
|
21
|
-
encoding: 'application/json',
|
|
22
|
-
body: {
|
|
23
|
-
// @TODO should we proactively filter blocks/mutes from the skeleton, or treat this similar to other custom feeds?
|
|
24
|
-
feed: result.feedItems.map(toSkeletonItem),
|
|
25
|
-
cursor: result.cursor,
|
|
26
|
-
},
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
})
|
|
30
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { Server } from '../../../../lexicon'
|
|
2
|
-
import AppContext from '../../../../context'
|
|
3
|
-
import { skeleton } from '../feed/getTimeline'
|
|
4
|
-
import { toSkeletonItem } from '../../../../feed-gen/types'
|
|
5
|
-
|
|
6
|
-
// THIS IS A TEMPORARY UNSPECCED ROUTE
|
|
7
|
-
export default function (server: Server, ctx: AppContext) {
|
|
8
|
-
server.app.bsky.unspecced.getTimelineSkeleton({
|
|
9
|
-
auth: ctx.authVerifier.standard,
|
|
10
|
-
handler: async ({ auth, params }) => {
|
|
11
|
-
const db = ctx.db.getReplica('timeline')
|
|
12
|
-
const feedService = ctx.services.feed(db)
|
|
13
|
-
const viewer = auth.credentials.iss
|
|
14
|
-
|
|
15
|
-
const result = await skeleton({ ...params, viewer }, { db, feedService })
|
|
16
|
-
|
|
17
|
-
return {
|
|
18
|
-
encoding: 'application/json',
|
|
19
|
-
body: {
|
|
20
|
-
feed: result.feedItems.map(toSkeletonItem),
|
|
21
|
-
cursor: result.cursor,
|
|
22
|
-
},
|
|
23
|
-
}
|
|
24
|
-
},
|
|
25
|
-
})
|
|
26
|
-
}
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import axios from 'axios'
|
|
2
|
-
import { CID } from 'multiformats/cid'
|
|
3
|
-
import { AtUri } from '@atproto/syntax'
|
|
4
|
-
import * as ui8 from 'uint8arrays'
|
|
5
|
-
import { resolveBlob } from '../api/blob-resolver'
|
|
6
|
-
import { retryHttp } from '../util/retry'
|
|
7
|
-
import { PrimaryDatabase } from '../db'
|
|
8
|
-
import { IdResolver } from '@atproto/identity'
|
|
9
|
-
import { labelerLogger as log } from '../logger'
|
|
10
|
-
|
|
11
|
-
export interface ImageFlagger {
|
|
12
|
-
scanImage(did: string, cid: CID, uri: AtUri): Promise<string[]>
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export class Abyss implements ImageFlagger {
|
|
16
|
-
protected auth: string
|
|
17
|
-
|
|
18
|
-
constructor(
|
|
19
|
-
public endpoint: string,
|
|
20
|
-
protected password: string,
|
|
21
|
-
public ctx: { db: PrimaryDatabase; idResolver: IdResolver },
|
|
22
|
-
) {
|
|
23
|
-
this.auth = basicAuth(this.password)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
async scanImage(did: string, cid: CID, uri: AtUri): Promise<string[]> {
|
|
27
|
-
const start = Date.now()
|
|
28
|
-
const res = await retryHttp(async () => {
|
|
29
|
-
try {
|
|
30
|
-
return await this.makeReq(did, cid, uri)
|
|
31
|
-
} catch (err) {
|
|
32
|
-
log.warn({ err, did, cid: cid.toString() }, 'abyss request failed')
|
|
33
|
-
throw err
|
|
34
|
-
}
|
|
35
|
-
})
|
|
36
|
-
log.info(
|
|
37
|
-
{ res, did, cid: cid.toString(), duration: Date.now() - start },
|
|
38
|
-
'abyss response',
|
|
39
|
-
)
|
|
40
|
-
return this.parseRes(res)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async makeReq(did: string, cid: CID, uri: AtUri): Promise<ScannerResp> {
|
|
44
|
-
const { stream, contentType } = await resolveBlob(
|
|
45
|
-
did,
|
|
46
|
-
cid,
|
|
47
|
-
this.ctx.db,
|
|
48
|
-
this.ctx.idResolver,
|
|
49
|
-
)
|
|
50
|
-
const { data } = await axios.post(
|
|
51
|
-
this.getReqUrl({ did, uri: uri.toString() }),
|
|
52
|
-
stream,
|
|
53
|
-
{
|
|
54
|
-
headers: {
|
|
55
|
-
'Content-Type': contentType,
|
|
56
|
-
authorization: this.auth,
|
|
57
|
-
},
|
|
58
|
-
timeout: 10000,
|
|
59
|
-
},
|
|
60
|
-
)
|
|
61
|
-
return data
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
parseRes(res: ScannerResp): string[] {
|
|
65
|
-
if (!res.match || res.match.status !== 'success') {
|
|
66
|
-
return []
|
|
67
|
-
}
|
|
68
|
-
const labels: string[] = []
|
|
69
|
-
for (const hit of res.match.hits) {
|
|
70
|
-
if (TAKEDOWN_LABELS.includes(hit.label)) {
|
|
71
|
-
labels.push(hit.label)
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
return labels
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
getReqUrl(params: { did: string; uri: string }) {
|
|
78
|
-
const search = new URLSearchParams(params)
|
|
79
|
-
return `${
|
|
80
|
-
this.endpoint
|
|
81
|
-
}/xrpc/com.atproto.unspecced.scanBlob?${search.toString()}`
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const TAKEDOWN_LABELS = ['csam', 'csem']
|
|
86
|
-
|
|
87
|
-
type ScannerResp = {
|
|
88
|
-
blob: unknown
|
|
89
|
-
match?: {
|
|
90
|
-
status: string
|
|
91
|
-
hits: ScannerHit[]
|
|
92
|
-
}
|
|
93
|
-
classify?: {
|
|
94
|
-
hits?: unknown[]
|
|
95
|
-
}
|
|
96
|
-
review?: {
|
|
97
|
-
state?: string
|
|
98
|
-
ticketId?: string
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
type ScannerHit = {
|
|
103
|
-
hashType: string
|
|
104
|
-
hashValue: string
|
|
105
|
-
label: string
|
|
106
|
-
corpus: string
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const basicAuth = (password: string) => {
|
|
110
|
-
return (
|
|
111
|
-
'Basic ' +
|
|
112
|
-
ui8.toString(ui8.fromString(`admin:${password}`, 'utf8'), 'base64pad')
|
|
113
|
-
)
|
|
114
|
-
}
|