@atproto/bsky 0.0.25 → 0.0.26
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 +7 -0
- package/buf.gen.yaml +12 -0
- package/dist/api/app/bsky/unspecced/getTaggedSuggestions.d.ts +3 -0
- package/dist/bsync.d.ts +8 -0
- package/dist/config.d.ts +20 -0
- package/dist/context.d.ts +6 -3
- package/dist/courier.d.ts +8 -0
- package/dist/db/database-schema.d.ts +2 -1
- package/dist/db/index.js +15 -1
- package/dist/db/index.js.map +3 -3
- package/dist/db/migrations/20240124T023719200Z-tagged-suggestions.d.ts +3 -0
- package/dist/db/migrations/index.d.ts +1 -0
- package/dist/db/tables/tagged-suggestion.d.ts +9 -0
- package/dist/index.js +47930 -16807
- package/dist/index.js.map +3 -3
- package/dist/indexer/config.d.ts +8 -0
- package/dist/indexer/context.d.ts +3 -0
- package/dist/ingester/config.d.ts +8 -0
- package/dist/ingester/context.d.ts +3 -0
- package/dist/ingester/mute-subscription.d.ts +22 -0
- package/dist/lexicon/index.d.ts +2 -0
- package/dist/lexicon/lexicons.d.ts +48 -0
- package/dist/lexicon/types/app/bsky/unspecced/getTaggedSuggestions.d.ts +39 -0
- package/dist/notifications.d.ts +27 -16
- package/dist/proto/bsync_connect.d.ts +25 -0
- package/dist/proto/bsync_pb.d.ts +90 -0
- package/dist/proto/courier_connect.d.ts +25 -0
- package/dist/proto/courier_pb.d.ts +91 -0
- package/dist/services/actor/index.d.ts +2 -2
- package/dist/services/indexing/index.d.ts +2 -2
- package/dist/services/util/post.d.ts +6 -6
- package/dist/util/retry.d.ts +2 -0
- package/package.json +15 -7
- package/proto/courier.proto +56 -0
- package/src/api/app/bsky/graph/muteActor.ts +32 -5
- package/src/api/app/bsky/graph/muteActorList.ts +32 -5
- package/src/api/app/bsky/graph/unmuteActor.ts +32 -5
- package/src/api/app/bsky/graph/unmuteActorList.ts +32 -5
- package/src/api/app/bsky/notification/registerPush.ts +42 -8
- package/src/api/app/bsky/unspecced/getTaggedSuggestions.ts +21 -0
- package/src/api/index.ts +2 -0
- package/src/bsync.ts +41 -0
- package/src/config.ts +79 -0
- package/src/context.ts +12 -6
- package/src/courier.ts +41 -0
- package/src/db/database-schema.ts +2 -0
- package/src/db/migrations/20240124T023719200Z-tagged-suggestions.ts +15 -0
- package/src/db/migrations/index.ts +1 -0
- package/src/db/tables/tagged-suggestion.ts +11 -0
- package/src/index.ts +26 -3
- package/src/indexer/config.ts +36 -0
- package/src/indexer/context.ts +6 -0
- package/src/indexer/index.ts +27 -3
- package/src/ingester/config.ts +34 -0
- package/src/ingester/context.ts +6 -0
- package/src/ingester/index.ts +18 -0
- package/src/ingester/mute-subscription.ts +213 -0
- package/src/lexicon/index.ts +12 -0
- package/src/lexicon/lexicons.ts +50 -0
- package/src/lexicon/types/app/bsky/unspecced/getTaggedSuggestions.ts +65 -0
- package/src/notifications.ts +165 -149
- package/src/proto/bsync_connect.ts +54 -0
- package/src/proto/bsync_pb.ts +459 -0
- package/src/proto/courier_connect.ts +50 -0
- package/src/proto/courier_pb.ts +473 -0
- package/src/services/actor/index.ts +17 -2
- package/src/services/indexing/processor.ts +1 -1
- package/src/util/retry.ts +12 -0
- package/tests/notification-server.test.ts +59 -19
- package/tests/subscription/mutes.test.ts +170 -0
- package/tests/views/suggestions.test.ts +22 -0
|
@@ -2,28 +2,28 @@ import DatabaseSchema from '../../db/database-schema';
|
|
|
2
2
|
export declare const getDescendentsQb: (db: DatabaseSchema, opts: {
|
|
3
3
|
uri: string;
|
|
4
4
|
depth: number;
|
|
5
|
-
}) => import("kysely/dist/cjs/parser/with-parser").QueryCreatorWithCommonTableExpression<import("../../db/database-schema").DatabaseSchemaType, "descendent(uri, depth)", (cte: import("kysely").QueryCreator<import("../../db/tables/duplicate-record").PartialDB & import("../../db/tables/profile").PartialDB & import("../../db/tables/profile-agg").PartialDB & import("../../db/tables/post").PartialDB & import("../../db/tables/post-embed").PartialDB & import("../../db/tables/post-agg").PartialDB & import("../../db/tables/repost").PartialDB & import("../../db/tables/thread-gate").PartialDB & import("../../db/tables/feed-item").PartialDB & import("../../db/tables/follow").PartialDB & import("../../db/tables/like").PartialDB & import("../../db/tables/list").PartialDB & import("../../db/tables/list-item").PartialDB & import("../../db/tables/list-mute").PartialDB & import("../../db/tables/list-block").PartialDB & import("../../db/tables/mute").PartialDB & import("../../db/tables/actor-block").PartialDB & import("../../db/tables/feed-generator").PartialDB & import("../../db/tables/subscription").PartialDB & import("../../db/tables/actor").PartialDB & import("../../db/tables/actor-state").PartialDB & import("../../db/tables/actor-sync").PartialDB & import("../../db/tables/record").PartialDB & import("../../db/tables/notification").PartialDB & import("../../db/tables/notification-push-token").PartialDB & import("../../db/tables/moderation").PartialDB & import("../../db/tables/label").PartialDB & import("../../db/tables/algo").PartialDB & import("../../db/tables/view-param").PartialDB & import("../../db/tables/suggested-follow").PartialDB & import("../../db/tables/suggested-feed").PartialDB & import("../../db/tables/blob-takedown").PartialDB & Record<"descendent", {
|
|
5
|
+
}) => import("kysely/dist/cjs/parser/with-parser").QueryCreatorWithCommonTableExpression<import("../../db/database-schema").DatabaseSchemaType, "descendent(uri, depth)", (cte: import("kysely").QueryCreator<import("../../db/tables/duplicate-record").PartialDB & import("../../db/tables/profile").PartialDB & import("../../db/tables/profile-agg").PartialDB & import("../../db/tables/post").PartialDB & import("../../db/tables/post-embed").PartialDB & import("../../db/tables/post-agg").PartialDB & import("../../db/tables/repost").PartialDB & import("../../db/tables/thread-gate").PartialDB & import("../../db/tables/feed-item").PartialDB & import("../../db/tables/follow").PartialDB & import("../../db/tables/like").PartialDB & import("../../db/tables/list").PartialDB & import("../../db/tables/list-item").PartialDB & import("../../db/tables/list-mute").PartialDB & import("../../db/tables/list-block").PartialDB & import("../../db/tables/mute").PartialDB & import("../../db/tables/actor-block").PartialDB & import("../../db/tables/feed-generator").PartialDB & import("../../db/tables/subscription").PartialDB & import("../../db/tables/actor").PartialDB & import("../../db/tables/actor-state").PartialDB & import("../../db/tables/actor-sync").PartialDB & import("../../db/tables/record").PartialDB & import("../../db/tables/notification").PartialDB & import("../../db/tables/notification-push-token").PartialDB & import("../../db/tables/moderation").PartialDB & import("../../db/tables/label").PartialDB & import("../../db/tables/algo").PartialDB & import("../../db/tables/view-param").PartialDB & import("../../db/tables/suggested-follow").PartialDB & import("../../db/tables/suggested-feed").PartialDB & import("../../db/tables/tagged-suggestion").PartialDB & import("../../db/tables/blob-takedown").PartialDB & Record<"descendent", {
|
|
6
6
|
uri: any;
|
|
7
7
|
depth: any;
|
|
8
|
-
}>>) => import("kysely").SelectQueryBuilder<import("kysely/dist/cjs/parser/table-parser").From<import("../../db/tables/duplicate-record").PartialDB & import("../../db/tables/profile").PartialDB & import("../../db/tables/profile-agg").PartialDB & import("../../db/tables/post").PartialDB & import("../../db/tables/post-embed").PartialDB & import("../../db/tables/post-agg").PartialDB & import("../../db/tables/repost").PartialDB & import("../../db/tables/thread-gate").PartialDB & import("../../db/tables/feed-item").PartialDB & import("../../db/tables/follow").PartialDB & import("../../db/tables/like").PartialDB & import("../../db/tables/list").PartialDB & import("../../db/tables/list-item").PartialDB & import("../../db/tables/list-mute").PartialDB & import("../../db/tables/list-block").PartialDB & import("../../db/tables/mute").PartialDB & import("../../db/tables/actor-block").PartialDB & import("../../db/tables/feed-generator").PartialDB & import("../../db/tables/subscription").PartialDB & import("../../db/tables/actor").PartialDB & import("../../db/tables/actor-state").PartialDB & import("../../db/tables/actor-sync").PartialDB & import("../../db/tables/record").PartialDB & import("../../db/tables/notification").PartialDB & import("../../db/tables/notification-push-token").PartialDB & import("../../db/tables/moderation").PartialDB & import("../../db/tables/label").PartialDB & import("../../db/tables/algo").PartialDB & import("../../db/tables/view-param").PartialDB & import("../../db/tables/suggested-follow").PartialDB & import("../../db/tables/suggested-feed").PartialDB & import("../../db/tables/blob-takedown").PartialDB & Record<"descendent", {
|
|
8
|
+
}>>) => import("kysely").SelectQueryBuilder<import("kysely/dist/cjs/parser/table-parser").From<import("../../db/tables/duplicate-record").PartialDB & import("../../db/tables/profile").PartialDB & import("../../db/tables/profile-agg").PartialDB & import("../../db/tables/post").PartialDB & import("../../db/tables/post-embed").PartialDB & import("../../db/tables/post-agg").PartialDB & import("../../db/tables/repost").PartialDB & import("../../db/tables/thread-gate").PartialDB & import("../../db/tables/feed-item").PartialDB & import("../../db/tables/follow").PartialDB & import("../../db/tables/like").PartialDB & import("../../db/tables/list").PartialDB & import("../../db/tables/list-item").PartialDB & import("../../db/tables/list-mute").PartialDB & import("../../db/tables/list-block").PartialDB & import("../../db/tables/mute").PartialDB & import("../../db/tables/actor-block").PartialDB & import("../../db/tables/feed-generator").PartialDB & import("../../db/tables/subscription").PartialDB & import("../../db/tables/actor").PartialDB & import("../../db/tables/actor-state").PartialDB & import("../../db/tables/actor-sync").PartialDB & import("../../db/tables/record").PartialDB & import("../../db/tables/notification").PartialDB & import("../../db/tables/notification-push-token").PartialDB & import("../../db/tables/moderation").PartialDB & import("../../db/tables/label").PartialDB & import("../../db/tables/algo").PartialDB & import("../../db/tables/view-param").PartialDB & import("../../db/tables/suggested-follow").PartialDB & import("../../db/tables/suggested-feed").PartialDB & import("../../db/tables/tagged-suggestion").PartialDB & import("../../db/tables/blob-takedown").PartialDB & Record<"descendent", {
|
|
9
9
|
uri: any;
|
|
10
10
|
depth: any;
|
|
11
|
-
}>, "post">, "post", import("kysely").Selection<import("kysely/dist/cjs/parser/table-parser").From<import("../../db/tables/duplicate-record").PartialDB & import("../../db/tables/profile").PartialDB & import("../../db/tables/profile-agg").PartialDB & import("../../db/tables/post").PartialDB & import("../../db/tables/post-embed").PartialDB & import("../../db/tables/post-agg").PartialDB & import("../../db/tables/repost").PartialDB & import("../../db/tables/thread-gate").PartialDB & import("../../db/tables/feed-item").PartialDB & import("../../db/tables/follow").PartialDB & import("../../db/tables/like").PartialDB & import("../../db/tables/list").PartialDB & import("../../db/tables/list-item").PartialDB & import("../../db/tables/list-mute").PartialDB & import("../../db/tables/list-block").PartialDB & import("../../db/tables/mute").PartialDB & import("../../db/tables/actor-block").PartialDB & import("../../db/tables/feed-generator").PartialDB & import("../../db/tables/subscription").PartialDB & import("../../db/tables/actor").PartialDB & import("../../db/tables/actor-state").PartialDB & import("../../db/tables/actor-sync").PartialDB & import("../../db/tables/record").PartialDB & import("../../db/tables/notification").PartialDB & import("../../db/tables/notification-push-token").PartialDB & import("../../db/tables/moderation").PartialDB & import("../../db/tables/label").PartialDB & import("../../db/tables/algo").PartialDB & import("../../db/tables/view-param").PartialDB & import("../../db/tables/suggested-follow").PartialDB & import("../../db/tables/suggested-feed").PartialDB & import("../../db/tables/blob-takedown").PartialDB & Record<"descendent", {
|
|
11
|
+
}>, "post">, "post", import("kysely").Selection<import("kysely/dist/cjs/parser/table-parser").From<import("../../db/tables/duplicate-record").PartialDB & import("../../db/tables/profile").PartialDB & import("../../db/tables/profile-agg").PartialDB & import("../../db/tables/post").PartialDB & import("../../db/tables/post-embed").PartialDB & import("../../db/tables/post-agg").PartialDB & import("../../db/tables/repost").PartialDB & import("../../db/tables/thread-gate").PartialDB & import("../../db/tables/feed-item").PartialDB & import("../../db/tables/follow").PartialDB & import("../../db/tables/like").PartialDB & import("../../db/tables/list").PartialDB & import("../../db/tables/list-item").PartialDB & import("../../db/tables/list-mute").PartialDB & import("../../db/tables/list-block").PartialDB & import("../../db/tables/mute").PartialDB & import("../../db/tables/actor-block").PartialDB & import("../../db/tables/feed-generator").PartialDB & import("../../db/tables/subscription").PartialDB & import("../../db/tables/actor").PartialDB & import("../../db/tables/actor-state").PartialDB & import("../../db/tables/actor-sync").PartialDB & import("../../db/tables/record").PartialDB & import("../../db/tables/notification").PartialDB & import("../../db/tables/notification-push-token").PartialDB & import("../../db/tables/moderation").PartialDB & import("../../db/tables/label").PartialDB & import("../../db/tables/algo").PartialDB & import("../../db/tables/view-param").PartialDB & import("../../db/tables/suggested-follow").PartialDB & import("../../db/tables/suggested-feed").PartialDB & import("../../db/tables/tagged-suggestion").PartialDB & import("../../db/tables/blob-takedown").PartialDB & Record<"descendent", {
|
|
12
12
|
uri: any;
|
|
13
13
|
depth: any;
|
|
14
14
|
}>, "post">, "post", "post.uri as uri" | import("kysely").AliasedRawBuilder<number, "depth">>>>;
|
|
15
15
|
export declare const getAncestorsAndSelfQb: (db: DatabaseSchema, opts: {
|
|
16
16
|
uri: string;
|
|
17
17
|
parentHeight: number;
|
|
18
|
-
}) => import("kysely/dist/cjs/parser/with-parser").QueryCreatorWithCommonTableExpression<import("../../db/database-schema").DatabaseSchemaType, "ancestor(uri, ancestorUri, height)", (cte: import("kysely").QueryCreator<import("../../db/tables/duplicate-record").PartialDB & import("../../db/tables/profile").PartialDB & import("../../db/tables/profile-agg").PartialDB & import("../../db/tables/post").PartialDB & import("../../db/tables/post-embed").PartialDB & import("../../db/tables/post-agg").PartialDB & import("../../db/tables/repost").PartialDB & import("../../db/tables/thread-gate").PartialDB & import("../../db/tables/feed-item").PartialDB & import("../../db/tables/follow").PartialDB & import("../../db/tables/like").PartialDB & import("../../db/tables/list").PartialDB & import("../../db/tables/list-item").PartialDB & import("../../db/tables/list-mute").PartialDB & import("../../db/tables/list-block").PartialDB & import("../../db/tables/mute").PartialDB & import("../../db/tables/actor-block").PartialDB & import("../../db/tables/feed-generator").PartialDB & import("../../db/tables/subscription").PartialDB & import("../../db/tables/actor").PartialDB & import("../../db/tables/actor-state").PartialDB & import("../../db/tables/actor-sync").PartialDB & import("../../db/tables/record").PartialDB & import("../../db/tables/notification").PartialDB & import("../../db/tables/notification-push-token").PartialDB & import("../../db/tables/moderation").PartialDB & import("../../db/tables/label").PartialDB & import("../../db/tables/algo").PartialDB & import("../../db/tables/view-param").PartialDB & import("../../db/tables/suggested-follow").PartialDB & import("../../db/tables/suggested-feed").PartialDB & import("../../db/tables/blob-takedown").PartialDB & Record<"ancestor", {
|
|
18
|
+
}) => import("kysely/dist/cjs/parser/with-parser").QueryCreatorWithCommonTableExpression<import("../../db/database-schema").DatabaseSchemaType, "ancestor(uri, ancestorUri, height)", (cte: import("kysely").QueryCreator<import("../../db/tables/duplicate-record").PartialDB & import("../../db/tables/profile").PartialDB & import("../../db/tables/profile-agg").PartialDB & import("../../db/tables/post").PartialDB & import("../../db/tables/post-embed").PartialDB & import("../../db/tables/post-agg").PartialDB & import("../../db/tables/repost").PartialDB & import("../../db/tables/thread-gate").PartialDB & import("../../db/tables/feed-item").PartialDB & import("../../db/tables/follow").PartialDB & import("../../db/tables/like").PartialDB & import("../../db/tables/list").PartialDB & import("../../db/tables/list-item").PartialDB & import("../../db/tables/list-mute").PartialDB & import("../../db/tables/list-block").PartialDB & import("../../db/tables/mute").PartialDB & import("../../db/tables/actor-block").PartialDB & import("../../db/tables/feed-generator").PartialDB & import("../../db/tables/subscription").PartialDB & import("../../db/tables/actor").PartialDB & import("../../db/tables/actor-state").PartialDB & import("../../db/tables/actor-sync").PartialDB & import("../../db/tables/record").PartialDB & import("../../db/tables/notification").PartialDB & import("../../db/tables/notification-push-token").PartialDB & import("../../db/tables/moderation").PartialDB & import("../../db/tables/label").PartialDB & import("../../db/tables/algo").PartialDB & import("../../db/tables/view-param").PartialDB & import("../../db/tables/suggested-follow").PartialDB & import("../../db/tables/suggested-feed").PartialDB & import("../../db/tables/tagged-suggestion").PartialDB & import("../../db/tables/blob-takedown").PartialDB & Record<"ancestor", {
|
|
19
19
|
uri: any;
|
|
20
20
|
height: any;
|
|
21
21
|
ancestorUri: any;
|
|
22
|
-
}>>) => import("kysely").SelectQueryBuilder<import("kysely/dist/cjs/parser/table-parser").From<import("../../db/tables/duplicate-record").PartialDB & import("../../db/tables/profile").PartialDB & import("../../db/tables/profile-agg").PartialDB & import("../../db/tables/post").PartialDB & import("../../db/tables/post-embed").PartialDB & import("../../db/tables/post-agg").PartialDB & import("../../db/tables/repost").PartialDB & import("../../db/tables/thread-gate").PartialDB & import("../../db/tables/feed-item").PartialDB & import("../../db/tables/follow").PartialDB & import("../../db/tables/like").PartialDB & import("../../db/tables/list").PartialDB & import("../../db/tables/list-item").PartialDB & import("../../db/tables/list-mute").PartialDB & import("../../db/tables/list-block").PartialDB & import("../../db/tables/mute").PartialDB & import("../../db/tables/actor-block").PartialDB & import("../../db/tables/feed-generator").PartialDB & import("../../db/tables/subscription").PartialDB & import("../../db/tables/actor").PartialDB & import("../../db/tables/actor-state").PartialDB & import("../../db/tables/actor-sync").PartialDB & import("../../db/tables/record").PartialDB & import("../../db/tables/notification").PartialDB & import("../../db/tables/notification-push-token").PartialDB & import("../../db/tables/moderation").PartialDB & import("../../db/tables/label").PartialDB & import("../../db/tables/algo").PartialDB & import("../../db/tables/view-param").PartialDB & import("../../db/tables/suggested-follow").PartialDB & import("../../db/tables/suggested-feed").PartialDB & import("../../db/tables/blob-takedown").PartialDB & Record<"ancestor", {
|
|
22
|
+
}>>) => import("kysely").SelectQueryBuilder<import("kysely/dist/cjs/parser/table-parser").From<import("../../db/tables/duplicate-record").PartialDB & import("../../db/tables/profile").PartialDB & import("../../db/tables/profile-agg").PartialDB & import("../../db/tables/post").PartialDB & import("../../db/tables/post-embed").PartialDB & import("../../db/tables/post-agg").PartialDB & import("../../db/tables/repost").PartialDB & import("../../db/tables/thread-gate").PartialDB & import("../../db/tables/feed-item").PartialDB & import("../../db/tables/follow").PartialDB & import("../../db/tables/like").PartialDB & import("../../db/tables/list").PartialDB & import("../../db/tables/list-item").PartialDB & import("../../db/tables/list-mute").PartialDB & import("../../db/tables/list-block").PartialDB & import("../../db/tables/mute").PartialDB & import("../../db/tables/actor-block").PartialDB & import("../../db/tables/feed-generator").PartialDB & import("../../db/tables/subscription").PartialDB & import("../../db/tables/actor").PartialDB & import("../../db/tables/actor-state").PartialDB & import("../../db/tables/actor-sync").PartialDB & import("../../db/tables/record").PartialDB & import("../../db/tables/notification").PartialDB & import("../../db/tables/notification-push-token").PartialDB & import("../../db/tables/moderation").PartialDB & import("../../db/tables/label").PartialDB & import("../../db/tables/algo").PartialDB & import("../../db/tables/view-param").PartialDB & import("../../db/tables/suggested-follow").PartialDB & import("../../db/tables/suggested-feed").PartialDB & import("../../db/tables/tagged-suggestion").PartialDB & import("../../db/tables/blob-takedown").PartialDB & Record<"ancestor", {
|
|
23
23
|
uri: any;
|
|
24
24
|
height: any;
|
|
25
25
|
ancestorUri: any;
|
|
26
|
-
}>, "post">, "post", import("kysely").Selection<import("kysely/dist/cjs/parser/table-parser").From<import("../../db/tables/duplicate-record").PartialDB & import("../../db/tables/profile").PartialDB & import("../../db/tables/profile-agg").PartialDB & import("../../db/tables/post").PartialDB & import("../../db/tables/post-embed").PartialDB & import("../../db/tables/post-agg").PartialDB & import("../../db/tables/repost").PartialDB & import("../../db/tables/thread-gate").PartialDB & import("../../db/tables/feed-item").PartialDB & import("../../db/tables/follow").PartialDB & import("../../db/tables/like").PartialDB & import("../../db/tables/list").PartialDB & import("../../db/tables/list-item").PartialDB & import("../../db/tables/list-mute").PartialDB & import("../../db/tables/list-block").PartialDB & import("../../db/tables/mute").PartialDB & import("../../db/tables/actor-block").PartialDB & import("../../db/tables/feed-generator").PartialDB & import("../../db/tables/subscription").PartialDB & import("../../db/tables/actor").PartialDB & import("../../db/tables/actor-state").PartialDB & import("../../db/tables/actor-sync").PartialDB & import("../../db/tables/record").PartialDB & import("../../db/tables/notification").PartialDB & import("../../db/tables/notification-push-token").PartialDB & import("../../db/tables/moderation").PartialDB & import("../../db/tables/label").PartialDB & import("../../db/tables/algo").PartialDB & import("../../db/tables/view-param").PartialDB & import("../../db/tables/suggested-follow").PartialDB & import("../../db/tables/suggested-feed").PartialDB & import("../../db/tables/blob-takedown").PartialDB & Record<"ancestor", {
|
|
26
|
+
}>, "post">, "post", import("kysely").Selection<import("kysely/dist/cjs/parser/table-parser").From<import("../../db/tables/duplicate-record").PartialDB & import("../../db/tables/profile").PartialDB & import("../../db/tables/profile-agg").PartialDB & import("../../db/tables/post").PartialDB & import("../../db/tables/post-embed").PartialDB & import("../../db/tables/post-agg").PartialDB & import("../../db/tables/repost").PartialDB & import("../../db/tables/thread-gate").PartialDB & import("../../db/tables/feed-item").PartialDB & import("../../db/tables/follow").PartialDB & import("../../db/tables/like").PartialDB & import("../../db/tables/list").PartialDB & import("../../db/tables/list-item").PartialDB & import("../../db/tables/list-mute").PartialDB & import("../../db/tables/list-block").PartialDB & import("../../db/tables/mute").PartialDB & import("../../db/tables/actor-block").PartialDB & import("../../db/tables/feed-generator").PartialDB & import("../../db/tables/subscription").PartialDB & import("../../db/tables/actor").PartialDB & import("../../db/tables/actor-state").PartialDB & import("../../db/tables/actor-sync").PartialDB & import("../../db/tables/record").PartialDB & import("../../db/tables/notification").PartialDB & import("../../db/tables/notification-push-token").PartialDB & import("../../db/tables/moderation").PartialDB & import("../../db/tables/label").PartialDB & import("../../db/tables/algo").PartialDB & import("../../db/tables/view-param").PartialDB & import("../../db/tables/suggested-follow").PartialDB & import("../../db/tables/suggested-feed").PartialDB & import("../../db/tables/tagged-suggestion").PartialDB & import("../../db/tables/blob-takedown").PartialDB & Record<"ancestor", {
|
|
27
27
|
uri: any;
|
|
28
28
|
height: any;
|
|
29
29
|
ancestorUri: any;
|
package/dist/util/retry.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import { RetryOptions } from '@atproto/common';
|
|
2
2
|
export declare function retryHttp<T>(fn: () => Promise<T>, opts?: RetryOptions): Promise<T>;
|
|
3
3
|
export declare function retryableHttp(err: unknown): boolean;
|
|
4
|
+
export declare function retryConnect<T>(fn: () => Promise<T>, opts?: RetryOptions): Promise<T>;
|
|
5
|
+
export declare function retryableConnect(err: unknown): boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto/bsky",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.26",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Reference implementation of app.bsky App View (Bluesky API)",
|
|
6
6
|
"keywords": [
|
|
@@ -16,6 +16,9 @@
|
|
|
16
16
|
"main": "dist/index.js",
|
|
17
17
|
"bin": "dist/bin.js",
|
|
18
18
|
"dependencies": {
|
|
19
|
+
"@bufbuild/protobuf": "^1.5.0",
|
|
20
|
+
"@connectrpc/connect": "^1.1.4",
|
|
21
|
+
"@connectrpc/connect-node": "^1.1.4",
|
|
19
22
|
"@did-plc/lib": "^0.0.1",
|
|
20
23
|
"@isaacs/ttlcache": "^1.4.1",
|
|
21
24
|
"compression": "^1.7.4",
|
|
@@ -28,6 +31,7 @@
|
|
|
28
31
|
"ioredis": "^5.3.2",
|
|
29
32
|
"kysely": "^0.22.0",
|
|
30
33
|
"multiformats": "^9.9.0",
|
|
34
|
+
"murmurhash": "^2.0.1",
|
|
31
35
|
"p-queue": "^6.6.2",
|
|
32
36
|
"pg": "^8.10.0",
|
|
33
37
|
"pino": "^8.15.0",
|
|
@@ -35,16 +39,19 @@
|
|
|
35
39
|
"sharp": "^0.32.6",
|
|
36
40
|
"typed-emitter": "^2.1.0",
|
|
37
41
|
"uint8arrays": "3.0.0",
|
|
38
|
-
"@atproto/api": "^0.9.
|
|
42
|
+
"@atproto/api": "^0.9.3",
|
|
39
43
|
"@atproto/common": "^0.3.3",
|
|
40
44
|
"@atproto/crypto": "^0.3.0",
|
|
41
|
-
"@atproto/syntax": "^0.1.5",
|
|
42
45
|
"@atproto/identity": "^0.3.2",
|
|
43
46
|
"@atproto/lexicon": "^0.3.1",
|
|
44
47
|
"@atproto/repo": "^0.3.6",
|
|
48
|
+
"@atproto/syntax": "^0.1.5",
|
|
45
49
|
"@atproto/xrpc-server": "^0.4.2"
|
|
46
50
|
},
|
|
47
51
|
"devDependencies": {
|
|
52
|
+
"@bufbuild/buf": "^1.28.1",
|
|
53
|
+
"@bufbuild/protoc-gen-es": "^1.5.0",
|
|
54
|
+
"@connectrpc/protoc-gen-connect-es": "^1.1.4",
|
|
48
55
|
"@did-plc/server": "^0.0.1",
|
|
49
56
|
"@types/cors": "^2.8.12",
|
|
50
57
|
"@types/express": "^4.17.13",
|
|
@@ -52,10 +59,10 @@
|
|
|
52
59
|
"@types/pg": "^8.6.6",
|
|
53
60
|
"@types/qs": "^6.9.7",
|
|
54
61
|
"axios": "^0.27.2",
|
|
55
|
-
"@atproto/api": "^0.9.
|
|
56
|
-
"@atproto/dev-env": "^0.2.
|
|
62
|
+
"@atproto/api": "^0.9.3",
|
|
63
|
+
"@atproto/dev-env": "^0.2.26",
|
|
57
64
|
"@atproto/lex-cli": "^0.3.0",
|
|
58
|
-
"@atproto/pds": "^0.3.
|
|
65
|
+
"@atproto/pds": "^0.3.14",
|
|
59
66
|
"@atproto/xrpc": "^0.4.1"
|
|
60
67
|
},
|
|
61
68
|
"scripts": {
|
|
@@ -67,7 +74,8 @@
|
|
|
67
74
|
"test": "../dev-infra/with-test-redis-and-db.sh jest",
|
|
68
75
|
"test:log": "tail -50 test.log | pino-pretty",
|
|
69
76
|
"test:updateSnapshot": "jest --updateSnapshot",
|
|
70
|
-
"migration:create": "ts-node ./bin/migration-create.ts"
|
|
77
|
+
"migration:create": "ts-node ./bin/migration-create.ts",
|
|
78
|
+
"buf:gen": "buf generate ../bsync/proto && buf generate ./proto"
|
|
71
79
|
},
|
|
72
80
|
"types": "dist/index.d.ts"
|
|
73
81
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
syntax = "proto3";
|
|
2
|
+
|
|
3
|
+
package courier;
|
|
4
|
+
option go_package = "./;courier";
|
|
5
|
+
|
|
6
|
+
import "google/protobuf/struct.proto";
|
|
7
|
+
import "google/protobuf/timestamp.proto";
|
|
8
|
+
|
|
9
|
+
//
|
|
10
|
+
// Messages
|
|
11
|
+
//
|
|
12
|
+
|
|
13
|
+
// Ping
|
|
14
|
+
message PingRequest {}
|
|
15
|
+
message PingResponse {}
|
|
16
|
+
|
|
17
|
+
// Notifications
|
|
18
|
+
|
|
19
|
+
enum AppPlatform {
|
|
20
|
+
APP_PLATFORM_UNSPECIFIED = 0;
|
|
21
|
+
APP_PLATFORM_IOS = 1;
|
|
22
|
+
APP_PLATFORM_ANDROID = 2;
|
|
23
|
+
APP_PLATFORM_WEB = 3;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
message Notification {
|
|
27
|
+
string id = 1;
|
|
28
|
+
string recipient_did = 2;
|
|
29
|
+
string title = 3;
|
|
30
|
+
string message = 4;
|
|
31
|
+
string collapse_key = 5;
|
|
32
|
+
bool always_deliver = 6;
|
|
33
|
+
google.protobuf.Timestamp timestamp = 7;
|
|
34
|
+
google.protobuf.Struct additional = 8;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
message PushNotificationsRequest {
|
|
38
|
+
repeated Notification notifications = 1;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
message PushNotificationsResponse {}
|
|
42
|
+
|
|
43
|
+
message RegisterDeviceTokenRequest {
|
|
44
|
+
string did = 1;
|
|
45
|
+
string token = 2;
|
|
46
|
+
string app_id = 3;
|
|
47
|
+
AppPlatform platform = 4;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
message RegisterDeviceTokenResponse {}
|
|
51
|
+
|
|
52
|
+
service Service {
|
|
53
|
+
rpc Ping(PingRequest) returns (PingResponse);
|
|
54
|
+
rpc PushNotifications(PushNotificationsRequest) returns (PushNotificationsResponse);
|
|
55
|
+
rpc RegisterDeviceToken(RegisterDeviceTokenRequest) returns (RegisterDeviceTokenResponse);
|
|
56
|
+
}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import assert from 'node:assert'
|
|
1
2
|
import { InvalidRequestError } from '@atproto/xrpc-server'
|
|
2
3
|
import { Server } from '../../../../lexicon'
|
|
3
4
|
import AppContext from '../../../../context'
|
|
5
|
+
import { MuteOperation_Type } from '../../../../proto/bsync_pb'
|
|
6
|
+
import { BsyncClient } from '../../../../bsync'
|
|
4
7
|
|
|
5
8
|
export default function (server: Server, ctx: AppContext) {
|
|
6
9
|
server.app.bsky.graph.muteActor({
|
|
7
10
|
auth: ctx.authVerifier.standard,
|
|
8
|
-
handler: async ({ auth, input }) => {
|
|
11
|
+
handler: async ({ req, auth, input }) => {
|
|
9
12
|
const { actor } = input.body
|
|
10
13
|
const requester = auth.credentials.iss
|
|
11
14
|
const db = ctx.db.getPrimary()
|
|
@@ -18,10 +21,34 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
18
21
|
throw new InvalidRequestError('Cannot mute oneself')
|
|
19
22
|
}
|
|
20
23
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
const muteActor = async () => {
|
|
25
|
+
await ctx.services.graph(db).muteActor({
|
|
26
|
+
subjectDid,
|
|
27
|
+
mutedByDid: requester,
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const addBsyncMuteOp = async (bsyncClient: BsyncClient) => {
|
|
32
|
+
await bsyncClient.addMuteOperation({
|
|
33
|
+
type: MuteOperation_Type.ADD,
|
|
34
|
+
actorDid: requester,
|
|
35
|
+
subject: subjectDid,
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (ctx.cfg.bsyncOnlyMutes) {
|
|
40
|
+
assert(ctx.bsyncClient)
|
|
41
|
+
await addBsyncMuteOp(ctx.bsyncClient)
|
|
42
|
+
} else {
|
|
43
|
+
await muteActor()
|
|
44
|
+
if (ctx.bsyncClient) {
|
|
45
|
+
try {
|
|
46
|
+
await addBsyncMuteOp(ctx.bsyncClient)
|
|
47
|
+
} catch (err) {
|
|
48
|
+
req.log.warn(err, 'failed to sync mute op to bsync')
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
25
52
|
},
|
|
26
53
|
})
|
|
27
54
|
}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
import assert from 'node:assert'
|
|
1
2
|
import { InvalidRequestError } from '@atproto/xrpc-server'
|
|
2
3
|
import { Server } from '../../../../lexicon'
|
|
3
4
|
import * as lex from '../../../../lexicon/lexicons'
|
|
4
5
|
import AppContext from '../../../../context'
|
|
5
6
|
import { AtUri } from '@atproto/syntax'
|
|
7
|
+
import { MuteOperation_Type } from '../../../../proto/bsync_pb'
|
|
8
|
+
import { BsyncClient } from '../../../../bsync'
|
|
6
9
|
|
|
7
10
|
export default function (server: Server, ctx: AppContext) {
|
|
8
11
|
server.app.bsky.graph.muteActorList({
|
|
9
12
|
auth: ctx.authVerifier.standard,
|
|
10
|
-
handler: async ({ auth, input }) => {
|
|
13
|
+
handler: async ({ req, auth, input }) => {
|
|
11
14
|
const { list } = input.body
|
|
12
15
|
const requester = auth.credentials.iss
|
|
13
16
|
|
|
@@ -19,10 +22,34 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
19
22
|
throw new InvalidRequestError(`Invalid collection: expected: ${collId}`)
|
|
20
23
|
}
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
const muteActorList = async () => {
|
|
26
|
+
await ctx.services.graph(db).muteActorList({
|
|
27
|
+
list,
|
|
28
|
+
mutedByDid: requester,
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const addBsyncMuteOp = async (bsyncClient: BsyncClient) => {
|
|
33
|
+
await bsyncClient.addMuteOperation({
|
|
34
|
+
type: MuteOperation_Type.ADD,
|
|
35
|
+
actorDid: requester,
|
|
36
|
+
subject: list,
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (ctx.cfg.bsyncOnlyMutes) {
|
|
41
|
+
assert(ctx.bsyncClient)
|
|
42
|
+
await addBsyncMuteOp(ctx.bsyncClient)
|
|
43
|
+
} else {
|
|
44
|
+
await muteActorList()
|
|
45
|
+
if (ctx.bsyncClient) {
|
|
46
|
+
try {
|
|
47
|
+
await addBsyncMuteOp(ctx.bsyncClient)
|
|
48
|
+
} catch (err) {
|
|
49
|
+
req.log.warn(err, 'failed to sync mute op to bsync')
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
26
53
|
},
|
|
27
54
|
})
|
|
28
55
|
}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import assert from 'node:assert'
|
|
1
2
|
import { InvalidRequestError } from '@atproto/xrpc-server'
|
|
2
3
|
import { Server } from '../../../../lexicon'
|
|
3
4
|
import AppContext from '../../../../context'
|
|
5
|
+
import { MuteOperation_Type } from '../../../../proto/bsync_pb'
|
|
6
|
+
import { BsyncClient } from '../../../../bsync'
|
|
4
7
|
|
|
5
8
|
export default function (server: Server, ctx: AppContext) {
|
|
6
9
|
server.app.bsky.graph.unmuteActor({
|
|
7
10
|
auth: ctx.authVerifier.standard,
|
|
8
|
-
handler: async ({ auth, input }) => {
|
|
11
|
+
handler: async ({ req, auth, input }) => {
|
|
9
12
|
const { actor } = input.body
|
|
10
13
|
const requester = auth.credentials.iss
|
|
11
14
|
const db = ctx.db.getPrimary()
|
|
@@ -18,10 +21,34 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
18
21
|
throw new InvalidRequestError('Cannot mute oneself')
|
|
19
22
|
}
|
|
20
23
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
const unmuteActor = async () => {
|
|
25
|
+
await ctx.services.graph(db).unmuteActor({
|
|
26
|
+
subjectDid,
|
|
27
|
+
mutedByDid: requester,
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const addBsyncMuteOp = async (bsyncClient: BsyncClient) => {
|
|
32
|
+
await bsyncClient.addMuteOperation({
|
|
33
|
+
type: MuteOperation_Type.REMOVE,
|
|
34
|
+
actorDid: requester,
|
|
35
|
+
subject: subjectDid,
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (ctx.cfg.bsyncOnlyMutes) {
|
|
40
|
+
assert(ctx.bsyncClient)
|
|
41
|
+
await addBsyncMuteOp(ctx.bsyncClient)
|
|
42
|
+
} else {
|
|
43
|
+
await unmuteActor()
|
|
44
|
+
if (ctx.bsyncClient) {
|
|
45
|
+
try {
|
|
46
|
+
await addBsyncMuteOp(ctx.bsyncClient)
|
|
47
|
+
} catch (err) {
|
|
48
|
+
req.log.warn(err, 'failed to sync mute op to bsync')
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
25
52
|
},
|
|
26
53
|
})
|
|
27
54
|
}
|
|
@@ -1,18 +1,45 @@
|
|
|
1
|
+
import assert from 'node:assert'
|
|
1
2
|
import { Server } from '../../../../lexicon'
|
|
2
3
|
import AppContext from '../../../../context'
|
|
4
|
+
import { MuteOperation_Type } from '../../../../proto/bsync_pb'
|
|
5
|
+
import { BsyncClient } from '../../../../bsync'
|
|
3
6
|
|
|
4
7
|
export default function (server: Server, ctx: AppContext) {
|
|
5
8
|
server.app.bsky.graph.unmuteActorList({
|
|
6
9
|
auth: ctx.authVerifier.standard,
|
|
7
|
-
handler: async ({ auth, input }) => {
|
|
10
|
+
handler: async ({ req, auth, input }) => {
|
|
8
11
|
const { list } = input.body
|
|
9
12
|
const requester = auth.credentials.iss
|
|
10
13
|
const db = ctx.db.getPrimary()
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
const unmuteActorList = async () => {
|
|
16
|
+
await ctx.services.graph(db).unmuteActorList({
|
|
17
|
+
list,
|
|
18
|
+
mutedByDid: requester,
|
|
19
|
+
})
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const addBsyncMuteOp = async (bsyncClient: BsyncClient) => {
|
|
23
|
+
await bsyncClient.addMuteOperation({
|
|
24
|
+
type: MuteOperation_Type.REMOVE,
|
|
25
|
+
actorDid: requester,
|
|
26
|
+
subject: list,
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (ctx.cfg.bsyncOnlyMutes) {
|
|
31
|
+
assert(ctx.bsyncClient)
|
|
32
|
+
await addBsyncMuteOp(ctx.bsyncClient)
|
|
33
|
+
} else {
|
|
34
|
+
await unmuteActorList()
|
|
35
|
+
if (ctx.bsyncClient) {
|
|
36
|
+
try {
|
|
37
|
+
await addBsyncMuteOp(ctx.bsyncClient)
|
|
38
|
+
} catch (err) {
|
|
39
|
+
req.log.warn(err, 'failed to sync mute op to bsync')
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
16
43
|
},
|
|
17
44
|
})
|
|
18
45
|
}
|
|
@@ -1,29 +1,63 @@
|
|
|
1
|
+
import assert from 'node:assert'
|
|
1
2
|
import { InvalidRequestError } from '@atproto/xrpc-server'
|
|
2
3
|
import { Server } from '../../../../lexicon'
|
|
3
4
|
import AppContext from '../../../../context'
|
|
4
5
|
import { Platform } from '../../../../notifications'
|
|
6
|
+
import { CourierClient } from '../../../../courier'
|
|
7
|
+
import { AppPlatform } from '../../../../proto/courier_pb'
|
|
5
8
|
|
|
6
9
|
export default function (server: Server, ctx: AppContext) {
|
|
7
10
|
server.app.bsky.notification.registerPush({
|
|
8
11
|
auth: ctx.authVerifier.standard,
|
|
9
|
-
handler: async ({ auth, input }) => {
|
|
12
|
+
handler: async ({ req, auth, input }) => {
|
|
10
13
|
const { token, platform, serviceDid, appId } = input.body
|
|
11
14
|
const did = auth.credentials.iss
|
|
12
15
|
if (serviceDid !== auth.credentials.aud) {
|
|
13
16
|
throw new InvalidRequestError('Invalid serviceDid.')
|
|
14
17
|
}
|
|
15
|
-
const { notifServer } = ctx
|
|
16
18
|
if (platform !== 'ios' && platform !== 'android' && platform !== 'web') {
|
|
17
19
|
throw new InvalidRequestError(
|
|
18
20
|
'Unsupported platform: must be "ios", "android", or "web".',
|
|
19
21
|
)
|
|
20
22
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
|
|
24
|
+
const db = ctx.db.getPrimary()
|
|
25
|
+
|
|
26
|
+
const registerDeviceWithAppview = async () => {
|
|
27
|
+
await ctx.services
|
|
28
|
+
.actor(db)
|
|
29
|
+
.registerPushDeviceToken(did, token, platform as Platform, appId)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const registerDeviceWithCourier = async (
|
|
33
|
+
courierClient: CourierClient,
|
|
34
|
+
) => {
|
|
35
|
+
await courierClient.registerDeviceToken({
|
|
36
|
+
did,
|
|
37
|
+
token,
|
|
38
|
+
platform:
|
|
39
|
+
platform === 'ios'
|
|
40
|
+
? AppPlatform.IOS
|
|
41
|
+
: platform === 'android'
|
|
42
|
+
? AppPlatform.ANDROID
|
|
43
|
+
: AppPlatform.WEB,
|
|
44
|
+
appId,
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (ctx.cfg.courierOnlyRegistration) {
|
|
49
|
+
assert(ctx.courierClient)
|
|
50
|
+
await registerDeviceWithCourier(ctx.courierClient)
|
|
51
|
+
} else {
|
|
52
|
+
await registerDeviceWithAppview()
|
|
53
|
+
if (ctx.courierClient) {
|
|
54
|
+
try {
|
|
55
|
+
await registerDeviceWithCourier(ctx.courierClient)
|
|
56
|
+
} catch (err) {
|
|
57
|
+
req.log.warn(err, 'failed to register device token with courier')
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
27
61
|
},
|
|
28
62
|
})
|
|
29
63
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Server } from '../../../../lexicon'
|
|
2
|
+
import AppContext from '../../../../context'
|
|
3
|
+
|
|
4
|
+
// THIS IS A TEMPORARY UNSPECCED ROUTE
|
|
5
|
+
export default function (server: Server, ctx: AppContext) {
|
|
6
|
+
server.app.bsky.unspecced.getTaggedSuggestions({
|
|
7
|
+
handler: async () => {
|
|
8
|
+
const suggestions = await ctx.db
|
|
9
|
+
.getReplica()
|
|
10
|
+
.db.selectFrom('tagged_suggestion')
|
|
11
|
+
.selectAll()
|
|
12
|
+
.execute()
|
|
13
|
+
return {
|
|
14
|
+
encoding: 'application/json',
|
|
15
|
+
body: {
|
|
16
|
+
suggestions,
|
|
17
|
+
},
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
})
|
|
21
|
+
}
|
package/src/api/index.ts
CHANGED
|
@@ -40,6 +40,7 @@ import updateSeen from './app/bsky/notification/updateSeen'
|
|
|
40
40
|
import registerPush from './app/bsky/notification/registerPush'
|
|
41
41
|
import getPopularFeedGenerators from './app/bsky/unspecced/getPopularFeedGenerators'
|
|
42
42
|
import getTimelineSkeleton from './app/bsky/unspecced/getTimelineSkeleton'
|
|
43
|
+
import getTaggedSuggestions from './app/bsky/unspecced/getTaggedSuggestions'
|
|
43
44
|
import getSubjectStatus from './com/atproto/admin/getSubjectStatus'
|
|
44
45
|
import updateSubjectStatus from './com/atproto/admin/updateSubjectStatus'
|
|
45
46
|
import getAccountInfos from './com/atproto/admin/getAccountInfos'
|
|
@@ -95,6 +96,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
95
96
|
registerPush(server, ctx)
|
|
96
97
|
getPopularFeedGenerators(server, ctx)
|
|
97
98
|
getTimelineSkeleton(server, ctx)
|
|
99
|
+
getTaggedSuggestions(server, ctx)
|
|
98
100
|
// com.atproto
|
|
99
101
|
getSubjectStatus(server, ctx)
|
|
100
102
|
updateSubjectStatus(server, ctx)
|
package/src/bsync.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Service } from './proto/bsync_connect'
|
|
2
|
+
import {
|
|
3
|
+
Code,
|
|
4
|
+
ConnectError,
|
|
5
|
+
PromiseClient,
|
|
6
|
+
createPromiseClient,
|
|
7
|
+
Interceptor,
|
|
8
|
+
} from '@connectrpc/connect'
|
|
9
|
+
import {
|
|
10
|
+
createConnectTransport,
|
|
11
|
+
ConnectTransportOptions,
|
|
12
|
+
} from '@connectrpc/connect-node'
|
|
13
|
+
|
|
14
|
+
export type BsyncClient = PromiseClient<typeof Service>
|
|
15
|
+
|
|
16
|
+
export const createBsyncClient = (
|
|
17
|
+
opts: ConnectTransportOptions,
|
|
18
|
+
): BsyncClient => {
|
|
19
|
+
const transport = createConnectTransport(opts)
|
|
20
|
+
return createPromiseClient(Service, transport)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { Code }
|
|
24
|
+
|
|
25
|
+
export const isBsyncError = (
|
|
26
|
+
err: unknown,
|
|
27
|
+
code?: Code,
|
|
28
|
+
): err is ConnectError => {
|
|
29
|
+
if (err instanceof ConnectError) {
|
|
30
|
+
return !code || err.code === code
|
|
31
|
+
}
|
|
32
|
+
return false
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const authWithApiKey =
|
|
36
|
+
(apiKey: string): Interceptor =>
|
|
37
|
+
(next) =>
|
|
38
|
+
(req) => {
|
|
39
|
+
req.header.set('authorization', `Bearer ${apiKey}`)
|
|
40
|
+
return next(req)
|
|
41
|
+
}
|