@atproto/bsky 0.0.37 → 0.0.38
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 +14 -0
- package/dist/api/app/bsky/feed/getAuthorFeed.d.ts +2 -3
- package/dist/api/app/bsky/feed/getListFeed.d.ts +2 -2
- package/dist/api/app/bsky/feed/getTimeline.d.ts +4 -2
- package/dist/api/app/bsky/labeler/getServices.d.ts +3 -0
- package/dist/api/util.d.ts +9 -2
- package/dist/auth-verifier.d.ts +1 -1
- package/dist/context.d.ts +3 -0
- package/dist/data-plane/server/db/database-schema.d.ts +2 -2
- package/dist/data-plane/server/db/migrations/20240226T225725627Z-labelers.d.ts +3 -0
- package/dist/data-plane/server/db/migrations/index.d.ts +1 -0
- package/dist/data-plane/server/db/tables/labeler.d.ts +13 -0
- package/dist/data-plane/server/indexing/index.d.ts +2 -0
- package/dist/data-plane/server/indexing/plugins/labeler.d.ts +10 -0
- package/dist/data-plane/server/util.d.ts +6 -6
- package/dist/hydration/actor.d.ts +3 -0
- package/dist/hydration/hydrator.d.ts +27 -22
- package/dist/hydration/label.d.ts +23 -9
- package/dist/index.js +4068 -4641
- package/dist/index.js.map +3 -3
- package/dist/lexicon/index.d.ts +7 -27
- package/dist/lexicon/lexicons.d.ts +507 -1467
- package/dist/lexicon/types/app/bsky/actor/defs.d.ts +23 -1
- package/dist/lexicon/types/app/bsky/embed/record.d.ts +2 -1
- package/dist/lexicon/types/app/bsky/feed/defs.d.ts +1 -0
- package/dist/lexicon/types/app/bsky/graph/defs.d.ts +3 -0
- package/dist/lexicon/types/app/bsky/labeler/defs.d.ts +41 -0
- package/dist/lexicon/types/{com/atproto/admin/searchRepos.d.ts → app/bsky/labeler/getServices.d.ts} +7 -7
- package/dist/lexicon/types/app/bsky/labeler/service.d.ts +14 -0
- package/dist/lexicon/types/com/atproto/admin/defs.d.ts +0 -304
- package/dist/lexicon/types/com/atproto/label/defs.d.ts +23 -0
- package/dist/proto/bsky_connect.d.ts +7 -1
- package/dist/proto/bsky_pb.d.ts +25 -0
- package/dist/util.d.ts +7 -0
- package/dist/views/index.d.ts +3 -0
- package/dist/views/types.d.ts +2 -1
- package/package.json +14 -13
- package/proto/bsky.proto +12 -0
- package/src/api/app/bsky/actor/getProfile.ts +21 -17
- package/src/api/app/bsky/actor/getProfiles.ts +16 -7
- package/src/api/app/bsky/actor/getSuggestions.ts +18 -13
- package/src/api/app/bsky/actor/searchActors.ts +9 -5
- package/src/api/app/bsky/actor/searchActorsTypeahead.ts +12 -5
- package/src/api/app/bsky/feed/getActorFeeds.ts +16 -6
- package/src/api/app/bsky/feed/getActorLikes.ts +18 -8
- package/src/api/app/bsky/feed/getAuthorFeed.ts +18 -19
- package/src/api/app/bsky/feed/getFeed.ts +14 -7
- package/src/api/app/bsky/feed/getFeedGenerator.ts +8 -2
- package/src/api/app/bsky/feed/getFeedGenerators.ts +16 -5
- package/src/api/app/bsky/feed/getLikes.ts +13 -6
- package/src/api/app/bsky/feed/getListFeed.ts +13 -7
- package/src/api/app/bsky/feed/getPostThread.ts +15 -8
- package/src/api/app/bsky/feed/getPosts.ts +14 -5
- package/src/api/app/bsky/feed/getRepostedBy.ts +13 -6
- package/src/api/app/bsky/feed/getSuggestedFeeds.ts +8 -2
- package/src/api/app/bsky/feed/getTimeline.ts +14 -8
- package/src/api/app/bsky/feed/searchPosts.ts +9 -5
- package/src/api/app/bsky/graph/getBlocks.ts +10 -9
- package/src/api/app/bsky/graph/getFollowers.ts +23 -15
- package/src/api/app/bsky/graph/getFollows.ts +23 -15
- package/src/api/app/bsky/graph/getList.ts +14 -8
- package/src/api/app/bsky/graph/getListBlocks.ts +10 -7
- package/src/api/app/bsky/graph/getListMutes.ts +10 -7
- package/src/api/app/bsky/graph/getLists.ts +9 -7
- package/src/api/app/bsky/graph/getMutes.ts +10 -8
- package/src/api/app/bsky/graph/getSuggestedFollowsByActor.ts +10 -7
- package/src/api/app/bsky/graph/muteActor.ts +1 -1
- package/src/api/app/bsky/labeler/getServices.ts +46 -0
- package/src/api/app/bsky/notification/listNotifications.ts +12 -8
- package/src/api/app/bsky/unspecced/getPopularFeedGenerators.ts +6 -3
- package/src/api/com/atproto/admin/getAccountInfos.ts +10 -3
- package/src/api/index.ts +2 -0
- package/src/api/util.ts +19 -4
- package/src/auth-verifier.ts +2 -2
- package/src/context.ts +20 -0
- package/src/data-plane/server/db/database-schema.ts +4 -4
- package/src/data-plane/server/db/migrations/20240226T225725627Z-labelers.ts +27 -0
- package/src/data-plane/server/db/migrations/index.ts +1 -0
- package/src/data-plane/server/db/tables/labeler.ts +16 -0
- package/src/data-plane/server/indexing/index.ts +4 -0
- package/src/data-plane/server/indexing/plugins/labeler.ts +77 -0
- package/src/data-plane/server/routes/interactions.ts +17 -1
- package/src/data-plane/server/routes/profile.ts +15 -1
- package/src/data-plane/server/routes/records.ts +1 -0
- package/src/hydration/actor.ts +6 -0
- package/src/hydration/hydrator.ts +171 -97
- package/src/hydration/label.ts +106 -20
- package/src/index.ts +1 -3
- package/src/lexicon/index.ts +22 -137
- package/src/lexicon/lexicons.ts +502 -1598
- package/src/lexicon/types/app/bsky/actor/defs.ts +57 -1
- package/src/lexicon/types/app/bsky/embed/record.ts +2 -0
- package/src/lexicon/types/app/bsky/feed/defs.ts +1 -0
- package/src/lexicon/types/app/bsky/graph/defs.ts +3 -0
- package/src/lexicon/types/app/bsky/labeler/defs.ts +93 -0
- package/src/lexicon/types/{com/atproto/admin/searchRepos.ts → app/bsky/labeler/getServices.ts} +8 -8
- package/src/lexicon/types/app/bsky/labeler/service.ts +31 -0
- package/src/lexicon/types/com/atproto/admin/defs.ts +0 -694
- package/src/lexicon/types/com/atproto/label/defs.ts +78 -0
- package/src/proto/bsky_connect.ts +11 -0
- package/src/proto/bsky_pb.ts +146 -0
- package/src/util.ts +44 -0
- package/src/views/index.ts +76 -7
- package/src/views/types.ts +6 -3
- package/tests/__snapshots__/feed-generation.test.ts.snap +12 -0
- package/tests/_util.ts +21 -0
- package/tests/data-plane/__snapshots__/indexing.test.ts.snap +20 -0
- package/tests/label-hydration.test.ts +162 -0
- package/tests/views/__snapshots__/block-lists.test.ts.snap +7 -0
- package/tests/views/__snapshots__/labeler-service.test.ts.snap +160 -0
- package/tests/views/__snapshots__/mute-lists.test.ts.snap +10 -0
- package/tests/views/__snapshots__/profile.test.ts.snap +40 -0
- package/tests/views/__snapshots__/threadgating.test.ts.snap +2 -0
- package/tests/views/labeler-service.test.ts +156 -0
- package/tests/views/takedown-labels.test.ts +133 -0
- package/tests/views/timeline.test.ts +7 -2
- package/dist/data-plane/server/db/tables/moderation.d.ts +0 -42
- package/dist/lexicon/types/com/atproto/admin/createCommunicationTemplate.d.ts +0 -37
- package/dist/lexicon/types/com/atproto/admin/deleteCommunicationTemplate.d.ts +0 -25
- package/dist/lexicon/types/com/atproto/admin/emitModerationEvent.d.ts +0 -45
- package/dist/lexicon/types/com/atproto/admin/getModerationEvent.d.ts +0 -29
- package/dist/lexicon/types/com/atproto/admin/getRecord.d.ts +0 -31
- package/dist/lexicon/types/com/atproto/admin/getRepo.d.ts +0 -30
- package/dist/lexicon/types/com/atproto/admin/listCommunicationTemplates.d.ts +0 -31
- package/dist/lexicon/types/com/atproto/admin/queryModerationEvents.d.ts +0 -48
- package/dist/lexicon/types/com/atproto/admin/queryModerationStatuses.d.ts +0 -50
- package/dist/lexicon/types/com/atproto/admin/updateCommunicationTemplate.d.ts +0 -39
- package/src/data-plane/server/db/tables/moderation.ts +0 -59
- package/src/lexicon/types/com/atproto/admin/createCommunicationTemplate.ts +0 -54
- package/src/lexicon/types/com/atproto/admin/deleteCommunicationTemplate.ts +0 -38
- package/src/lexicon/types/com/atproto/admin/emitModerationEvent.ts +0 -67
- package/src/lexicon/types/com/atproto/admin/getModerationEvent.ts +0 -41
- package/src/lexicon/types/com/atproto/admin/getRecord.ts +0 -43
- package/src/lexicon/types/com/atproto/admin/getRepo.ts +0 -42
- package/src/lexicon/types/com/atproto/admin/listCommunicationTemplates.ts +0 -44
- package/src/lexicon/types/com/atproto/admin/queryModerationEvents.ts +0 -73
- package/src/lexicon/types/com/atproto/admin/queryModerationStatuses.ts +0 -74
- package/src/lexicon/types/com/atproto/admin/updateCommunicationTemplate.ts +0 -57
|
@@ -11,9 +11,13 @@ import {
|
|
|
11
11
|
createPipeline,
|
|
12
12
|
} from '../../../../pipeline'
|
|
13
13
|
import { didFromUri } from '../../../../hydration/util'
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
HydrateCtx,
|
|
16
|
+
Hydrator,
|
|
17
|
+
mergeStates,
|
|
18
|
+
} from '../../../../hydration/hydrator'
|
|
15
19
|
import { Views } from '../../../../views'
|
|
16
|
-
import { clearlyBadCursor } from '../../../util'
|
|
20
|
+
import { clearlyBadCursor, resHeaders } from '../../../util'
|
|
17
21
|
|
|
18
22
|
export default function (server: Server, ctx: AppContext) {
|
|
19
23
|
const getFollowers = createPipeline(
|
|
@@ -24,17 +28,17 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
24
28
|
)
|
|
25
29
|
server.app.bsky.graph.getFollowers({
|
|
26
30
|
auth: ctx.authVerifier.optionalStandardOrRole,
|
|
27
|
-
handler: async ({ params, auth }) => {
|
|
28
|
-
const { viewer,
|
|
31
|
+
handler: async ({ params, auth, req }) => {
|
|
32
|
+
const { viewer, includeTakedowns } = ctx.authVerifier.parseCreds(auth)
|
|
33
|
+
const labelers = ctx.reqLabelers(req)
|
|
34
|
+
const hydrateCtx = { labelers, viewer, includeTakedowns }
|
|
29
35
|
|
|
30
|
-
const result = await getFollowers(
|
|
31
|
-
{ ...params, viewer, canViewTakedowns },
|
|
32
|
-
ctx,
|
|
33
|
-
)
|
|
36
|
+
const result = await getFollowers({ ...params, hydrateCtx }, ctx)
|
|
34
37
|
|
|
35
38
|
return {
|
|
36
39
|
encoding: 'application/json',
|
|
37
40
|
body: result,
|
|
41
|
+
headers: resHeaders({ labelers }),
|
|
38
42
|
}
|
|
39
43
|
},
|
|
40
44
|
})
|
|
@@ -65,7 +69,6 @@ const hydration = async (
|
|
|
65
69
|
input: HydrationFnInput<Context, Params, SkeletonState>,
|
|
66
70
|
) => {
|
|
67
71
|
const { ctx, params, skeleton } = input
|
|
68
|
-
const { viewer } = params
|
|
69
72
|
const { followUris, subjectDid } = skeleton
|
|
70
73
|
const followState = await ctx.hydrator.hydrateFollows(followUris)
|
|
71
74
|
const dids = [subjectDid]
|
|
@@ -76,13 +79,16 @@ const hydration = async (
|
|
|
76
79
|
}
|
|
77
80
|
}
|
|
78
81
|
}
|
|
79
|
-
const profileState = await ctx.hydrator.hydrateProfiles(
|
|
82
|
+
const profileState = await ctx.hydrator.hydrateProfiles(
|
|
83
|
+
dids,
|
|
84
|
+
params.hydrateCtx,
|
|
85
|
+
)
|
|
80
86
|
return mergeStates(followState, profileState)
|
|
81
87
|
}
|
|
82
88
|
|
|
83
89
|
const noBlocks = (input: RulesFnInput<Context, Params, SkeletonState>) => {
|
|
84
90
|
const { skeleton, params, hydration, ctx } = input
|
|
85
|
-
const
|
|
91
|
+
const viewer = params.hydrateCtx.viewer
|
|
86
92
|
skeleton.followUris = skeleton.followUris.filter((followUri) => {
|
|
87
93
|
const followerDid = didFromUri(followUri)
|
|
88
94
|
return (
|
|
@@ -102,13 +108,16 @@ const presentation = (
|
|
|
102
108
|
ctx.views.actorIsTakendown(did, hydration)
|
|
103
109
|
|
|
104
110
|
const subject = ctx.views.profile(subjectDid, hydration)
|
|
105
|
-
if (
|
|
111
|
+
if (
|
|
112
|
+
!subject ||
|
|
113
|
+
(!params.hydrateCtx.includeTakedowns && isTakendown(subjectDid))
|
|
114
|
+
) {
|
|
106
115
|
throw new InvalidRequestError(`Actor not found: ${params.actor}`)
|
|
107
116
|
}
|
|
108
117
|
|
|
109
118
|
const followers = mapDefined(followUris, (followUri) => {
|
|
110
119
|
const followerDid = didFromUri(followUri)
|
|
111
|
-
if (!params.
|
|
120
|
+
if (!params.hydrateCtx.includeTakedowns && isTakendown(followerDid)) {
|
|
112
121
|
return
|
|
113
122
|
}
|
|
114
123
|
return ctx.views.profile(didFromUri(followUri), hydration)
|
|
@@ -123,8 +132,7 @@ type Context = {
|
|
|
123
132
|
}
|
|
124
133
|
|
|
125
134
|
type Params = QueryParams & {
|
|
126
|
-
|
|
127
|
-
canViewTakedowns: boolean
|
|
135
|
+
hydrateCtx: HydrateCtx
|
|
128
136
|
}
|
|
129
137
|
|
|
130
138
|
type SkeletonState = {
|
|
@@ -10,26 +10,30 @@ import {
|
|
|
10
10
|
SkeletonFnInput,
|
|
11
11
|
createPipeline,
|
|
12
12
|
} from '../../../../pipeline'
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
HydrateCtx,
|
|
15
|
+
Hydrator,
|
|
16
|
+
mergeStates,
|
|
17
|
+
} from '../../../../hydration/hydrator'
|
|
14
18
|
import { Views } from '../../../../views'
|
|
15
|
-
import { clearlyBadCursor } from '../../../util'
|
|
19
|
+
import { clearlyBadCursor, resHeaders } from '../../../util'
|
|
16
20
|
|
|
17
21
|
export default function (server: Server, ctx: AppContext) {
|
|
18
22
|
const getFollows = createPipeline(skeleton, hydration, noBlocks, presentation)
|
|
19
23
|
server.app.bsky.graph.getFollows({
|
|
20
24
|
auth: ctx.authVerifier.optionalStandardOrRole,
|
|
21
|
-
handler: async ({ params, auth }) => {
|
|
22
|
-
const { viewer,
|
|
25
|
+
handler: async ({ params, auth, req }) => {
|
|
26
|
+
const { viewer, includeTakedowns } = ctx.authVerifier.parseCreds(auth)
|
|
27
|
+
const labelers = ctx.reqLabelers(req)
|
|
28
|
+
const hydrateCtx = { labelers, viewer, includeTakedowns }
|
|
23
29
|
|
|
24
30
|
// @TODO ensure canViewTakedowns gets threaded through and applied properly
|
|
25
|
-
const result = await getFollows(
|
|
26
|
-
{ ...params, viewer, canViewTakedowns },
|
|
27
|
-
ctx,
|
|
28
|
-
)
|
|
31
|
+
const result = await getFollows({ ...params, hydrateCtx }, ctx)
|
|
29
32
|
|
|
30
33
|
return {
|
|
31
34
|
encoding: 'application/json',
|
|
32
35
|
body: result,
|
|
36
|
+
headers: resHeaders({ labelers }),
|
|
33
37
|
}
|
|
34
38
|
},
|
|
35
39
|
})
|
|
@@ -60,7 +64,6 @@ const hydration = async (
|
|
|
60
64
|
input: HydrationFnInput<Context, Params, SkeletonState>,
|
|
61
65
|
) => {
|
|
62
66
|
const { ctx, params, skeleton } = input
|
|
63
|
-
const { viewer } = params
|
|
64
67
|
const { followUris, subjectDid } = skeleton
|
|
65
68
|
const followState = await ctx.hydrator.hydrateFollows(followUris)
|
|
66
69
|
const dids = [subjectDid]
|
|
@@ -71,13 +74,16 @@ const hydration = async (
|
|
|
71
74
|
}
|
|
72
75
|
}
|
|
73
76
|
}
|
|
74
|
-
const profileState = await ctx.hydrator.hydrateProfiles(
|
|
77
|
+
const profileState = await ctx.hydrator.hydrateProfiles(
|
|
78
|
+
dids,
|
|
79
|
+
params.hydrateCtx,
|
|
80
|
+
)
|
|
75
81
|
return mergeStates(followState, profileState)
|
|
76
82
|
}
|
|
77
83
|
|
|
78
84
|
const noBlocks = (input: RulesFnInput<Context, Params, SkeletonState>) => {
|
|
79
85
|
const { skeleton, params, hydration, ctx } = input
|
|
80
|
-
const
|
|
86
|
+
const viewer = params.hydrateCtx.viewer
|
|
81
87
|
skeleton.followUris = skeleton.followUris.filter((followUri) => {
|
|
82
88
|
const follow = hydration.follows?.get(followUri)
|
|
83
89
|
if (!follow) return false
|
|
@@ -99,14 +105,17 @@ const presentation = (
|
|
|
99
105
|
ctx.views.actorIsTakendown(did, hydration)
|
|
100
106
|
|
|
101
107
|
const subject = ctx.views.profile(subjectDid, hydration)
|
|
102
|
-
if (
|
|
108
|
+
if (
|
|
109
|
+
!subject ||
|
|
110
|
+
(!params.hydrateCtx.includeTakedowns && isTakendown(subjectDid))
|
|
111
|
+
) {
|
|
103
112
|
throw new InvalidRequestError(`Actor not found: ${params.actor}`)
|
|
104
113
|
}
|
|
105
114
|
|
|
106
115
|
const follows = mapDefined(followUris, (followUri) => {
|
|
107
116
|
const followDid = hydration.follows?.get(followUri)?.record.subject
|
|
108
117
|
if (!followDid) return
|
|
109
|
-
if (!params.
|
|
118
|
+
if (!params.hydrateCtx.includeTakedowns && isTakendown(followDid)) {
|
|
110
119
|
return
|
|
111
120
|
}
|
|
112
121
|
return ctx.views.profile(followDid, hydration)
|
|
@@ -121,8 +130,7 @@ type Context = {
|
|
|
121
130
|
}
|
|
122
131
|
|
|
123
132
|
type Params = QueryParams & {
|
|
124
|
-
|
|
125
|
-
canViewTakedowns: boolean
|
|
133
|
+
hydrateCtx: HydrateCtx
|
|
126
134
|
}
|
|
127
135
|
|
|
128
136
|
type SkeletonState = {
|
|
@@ -10,21 +10,28 @@ import {
|
|
|
10
10
|
PresentationFnInput,
|
|
11
11
|
SkeletonFnInput,
|
|
12
12
|
} from '../../../../pipeline'
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
HydrateCtx,
|
|
15
|
+
Hydrator,
|
|
16
|
+
mergeStates,
|
|
17
|
+
} from '../../../../hydration/hydrator'
|
|
14
18
|
import { Views } from '../../../../views'
|
|
15
|
-
import { clearlyBadCursor } from '../../../util'
|
|
19
|
+
import { clearlyBadCursor, resHeaders } from '../../../util'
|
|
16
20
|
import { ListItemInfo } from '../../../../proto/bsky_pb'
|
|
17
21
|
|
|
18
22
|
export default function (server: Server, ctx: AppContext) {
|
|
19
23
|
const getList = createPipeline(skeleton, hydration, noRules, presentation)
|
|
20
24
|
server.app.bsky.graph.getList({
|
|
21
25
|
auth: ctx.authVerifier.standardOptional,
|
|
22
|
-
handler: async ({ params, auth }) => {
|
|
26
|
+
handler: async ({ params, auth, req }) => {
|
|
23
27
|
const viewer = auth.credentials.iss
|
|
24
|
-
const
|
|
28
|
+
const labelers = ctx.reqLabelers(req)
|
|
29
|
+
const hydrateCtx = { labelers, viewer }
|
|
30
|
+
const result = await getList({ ...params, hydrateCtx }, ctx)
|
|
25
31
|
return {
|
|
26
32
|
encoding: 'application/json',
|
|
27
33
|
body: result,
|
|
34
|
+
headers: resHeaders({ labelers }),
|
|
28
35
|
}
|
|
29
36
|
},
|
|
30
37
|
})
|
|
@@ -53,13 +60,12 @@ const hydration = async (
|
|
|
53
60
|
input: HydrationFnInput<Context, Params, SkeletonState>,
|
|
54
61
|
) => {
|
|
55
62
|
const { ctx, params, skeleton } = input
|
|
56
|
-
const { viewer } = params
|
|
57
63
|
const { listUri, listitems } = skeleton
|
|
58
64
|
const [listState, profileState] = await Promise.all([
|
|
59
|
-
ctx.hydrator.hydrateLists([listUri],
|
|
65
|
+
ctx.hydrator.hydrateLists([listUri], params.hydrateCtx),
|
|
60
66
|
ctx.hydrator.hydrateProfiles(
|
|
61
67
|
listitems.map(({ did }) => did),
|
|
62
|
-
|
|
68
|
+
params.hydrateCtx,
|
|
63
69
|
),
|
|
64
70
|
])
|
|
65
71
|
return mergeStates(listState, profileState)
|
|
@@ -88,7 +94,7 @@ type Context = {
|
|
|
88
94
|
}
|
|
89
95
|
|
|
90
96
|
type Params = QueryParams & {
|
|
91
|
-
|
|
97
|
+
hydrateCtx: HydrateCtx
|
|
92
98
|
}
|
|
93
99
|
|
|
94
100
|
type SkeletonState = {
|
|
@@ -9,9 +9,9 @@ import {
|
|
|
9
9
|
PresentationFnInput,
|
|
10
10
|
SkeletonFnInput,
|
|
11
11
|
} from '../../../../pipeline'
|
|
12
|
-
import { Hydrator } from '../../../../hydration/hydrator'
|
|
12
|
+
import { HydrateCtx, Hydrator } from '../../../../hydration/hydrator'
|
|
13
13
|
import { Views } from '../../../../views'
|
|
14
|
-
import { clearlyBadCursor } from '../../../util'
|
|
14
|
+
import { clearlyBadCursor, resHeaders } from '../../../util'
|
|
15
15
|
|
|
16
16
|
export default function (server: Server, ctx: AppContext) {
|
|
17
17
|
const getListBlocks = createPipeline(
|
|
@@ -22,12 +22,15 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
22
22
|
)
|
|
23
23
|
server.app.bsky.graph.getListBlocks({
|
|
24
24
|
auth: ctx.authVerifier.standard,
|
|
25
|
-
handler: async ({ params, auth }) => {
|
|
25
|
+
handler: async ({ params, auth, req }) => {
|
|
26
26
|
const viewer = auth.credentials.iss
|
|
27
|
-
const
|
|
27
|
+
const labelers = ctx.reqLabelers(req)
|
|
28
|
+
const hydrateCtx = { labelers, viewer }
|
|
29
|
+
const result = await getListBlocks({ ...params, hydrateCtx }, ctx)
|
|
28
30
|
return {
|
|
29
31
|
encoding: 'application/json',
|
|
30
32
|
body: result,
|
|
33
|
+
headers: resHeaders({ labelers }),
|
|
31
34
|
}
|
|
32
35
|
},
|
|
33
36
|
})
|
|
@@ -42,7 +45,7 @@ const skeleton = async (
|
|
|
42
45
|
}
|
|
43
46
|
const { listUris, cursor } =
|
|
44
47
|
await ctx.hydrator.dataplane.getBlocklistSubscriptions({
|
|
45
|
-
actorDid: params.viewer,
|
|
48
|
+
actorDid: params.hydrateCtx.viewer,
|
|
46
49
|
cursor: params.cursor,
|
|
47
50
|
limit: params.limit,
|
|
48
51
|
})
|
|
@@ -53,7 +56,7 @@ const hydration = async (
|
|
|
53
56
|
input: HydrationFnInput<Context, Params, SkeletonState>,
|
|
54
57
|
) => {
|
|
55
58
|
const { ctx, params, skeleton } = input
|
|
56
|
-
return await ctx.hydrator.hydrateLists(skeleton.listUris, params.
|
|
59
|
+
return await ctx.hydrator.hydrateLists(skeleton.listUris, params.hydrateCtx)
|
|
57
60
|
}
|
|
58
61
|
|
|
59
62
|
const presentation = (
|
|
@@ -71,7 +74,7 @@ type Context = {
|
|
|
71
74
|
}
|
|
72
75
|
|
|
73
76
|
type Params = QueryParams & {
|
|
74
|
-
viewer: string
|
|
77
|
+
hydrateCtx: HydrateCtx & { viewer: string }
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
type SkeletonState = {
|
|
@@ -9,9 +9,9 @@ import {
|
|
|
9
9
|
PresentationFnInput,
|
|
10
10
|
SkeletonFnInput,
|
|
11
11
|
} from '../../../../pipeline'
|
|
12
|
-
import { Hydrator } from '../../../../hydration/hydrator'
|
|
12
|
+
import { HydrateCtx, Hydrator } from '../../../../hydration/hydrator'
|
|
13
13
|
import { Views } from '../../../../views'
|
|
14
|
-
import { clearlyBadCursor } from '../../../util'
|
|
14
|
+
import { clearlyBadCursor, resHeaders } from '../../../util'
|
|
15
15
|
|
|
16
16
|
export default function (server: Server, ctx: AppContext) {
|
|
17
17
|
const getListMutes = createPipeline(
|
|
@@ -22,12 +22,15 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
22
22
|
)
|
|
23
23
|
server.app.bsky.graph.getListMutes({
|
|
24
24
|
auth: ctx.authVerifier.standard,
|
|
25
|
-
handler: async ({ params, auth }) => {
|
|
25
|
+
handler: async ({ params, auth, req }) => {
|
|
26
26
|
const viewer = auth.credentials.iss
|
|
27
|
-
const
|
|
27
|
+
const labelers = ctx.reqLabelers(req)
|
|
28
|
+
const hydrateCtx = { labelers, viewer }
|
|
29
|
+
const result = await getListMutes({ ...params, hydrateCtx }, ctx)
|
|
28
30
|
return {
|
|
29
31
|
encoding: 'application/json',
|
|
30
32
|
body: result,
|
|
33
|
+
headers: resHeaders({ labelers }),
|
|
31
34
|
}
|
|
32
35
|
},
|
|
33
36
|
})
|
|
@@ -42,7 +45,7 @@ const skeleton = async (
|
|
|
42
45
|
}
|
|
43
46
|
const { listUris, cursor } =
|
|
44
47
|
await ctx.hydrator.dataplane.getMutelistSubscriptions({
|
|
45
|
-
actorDid: params.viewer,
|
|
48
|
+
actorDid: params.hydrateCtx.viewer,
|
|
46
49
|
cursor: params.cursor,
|
|
47
50
|
limit: params.limit,
|
|
48
51
|
})
|
|
@@ -53,7 +56,7 @@ const hydration = async (
|
|
|
53
56
|
input: HydrationFnInput<Context, Params, SkeletonState>,
|
|
54
57
|
) => {
|
|
55
58
|
const { ctx, params, skeleton } = input
|
|
56
|
-
return await ctx.hydrator.hydrateLists(skeleton.listUris, params.
|
|
59
|
+
return await ctx.hydrator.hydrateLists(skeleton.listUris, params.hydrateCtx)
|
|
57
60
|
}
|
|
58
61
|
|
|
59
62
|
const presentation = (
|
|
@@ -71,7 +74,7 @@ type Context = {
|
|
|
71
74
|
}
|
|
72
75
|
|
|
73
76
|
type Params = QueryParams & {
|
|
74
|
-
viewer: string
|
|
77
|
+
hydrateCtx: HydrateCtx & { viewer: string }
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
type SkeletonState = {
|
|
@@ -9,21 +9,24 @@ import {
|
|
|
9
9
|
PresentationFnInput,
|
|
10
10
|
SkeletonFnInput,
|
|
11
11
|
} from '../../../../pipeline'
|
|
12
|
-
import { Hydrator } from '../../../../hydration/hydrator'
|
|
12
|
+
import { HydrateCtx, Hydrator } from '../../../../hydration/hydrator'
|
|
13
13
|
import { Views } from '../../../../views'
|
|
14
|
-
import { clearlyBadCursor } from '../../../util'
|
|
14
|
+
import { clearlyBadCursor, resHeaders } from '../../../util'
|
|
15
15
|
|
|
16
16
|
export default function (server: Server, ctx: AppContext) {
|
|
17
17
|
const getLists = createPipeline(skeleton, hydration, noRules, presentation)
|
|
18
18
|
server.app.bsky.graph.getLists({
|
|
19
19
|
auth: ctx.authVerifier.standardOptional,
|
|
20
|
-
handler: async ({ params, auth }) => {
|
|
20
|
+
handler: async ({ params, auth, req }) => {
|
|
21
21
|
const viewer = auth.credentials.iss
|
|
22
|
-
const
|
|
22
|
+
const labelers = ctx.reqLabelers(req)
|
|
23
|
+
const hydrateCtx = { labelers, viewer }
|
|
24
|
+
const result = await getLists({ ...params, hydrateCtx }, ctx)
|
|
23
25
|
|
|
24
26
|
return {
|
|
25
27
|
encoding: 'application/json',
|
|
26
28
|
body: result,
|
|
29
|
+
headers: resHeaders({ labelers }),
|
|
27
30
|
}
|
|
28
31
|
},
|
|
29
32
|
})
|
|
@@ -48,9 +51,8 @@ const hydration = async (
|
|
|
48
51
|
input: HydrationFnInput<Context, Params, SkeletonState>,
|
|
49
52
|
) => {
|
|
50
53
|
const { ctx, params, skeleton } = input
|
|
51
|
-
const { viewer } = params
|
|
52
54
|
const { listUris } = skeleton
|
|
53
|
-
return ctx.hydrator.hydrateLists(listUris,
|
|
55
|
+
return ctx.hydrator.hydrateLists(listUris, params.hydrateCtx)
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
const presentation = (
|
|
@@ -70,7 +72,7 @@ type Context = {
|
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
type Params = QueryParams & {
|
|
73
|
-
|
|
75
|
+
hydrateCtx: HydrateCtx
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
type SkeletonState = {
|
|
@@ -2,7 +2,7 @@ import { mapDefined } from '@atproto/common'
|
|
|
2
2
|
import { Server } from '../../../../lexicon'
|
|
3
3
|
import { QueryParams } from '../../../../lexicon/types/app/bsky/graph/getMutes'
|
|
4
4
|
import AppContext from '../../../../context'
|
|
5
|
-
import { Hydrator } from '../../../../hydration/hydrator'
|
|
5
|
+
import { HydrateCtx, Hydrator } from '../../../../hydration/hydrator'
|
|
6
6
|
import { Views } from '../../../../views'
|
|
7
7
|
import {
|
|
8
8
|
HydrationFnInput,
|
|
@@ -11,18 +11,21 @@ import {
|
|
|
11
11
|
createPipeline,
|
|
12
12
|
noRules,
|
|
13
13
|
} from '../../../../pipeline'
|
|
14
|
-
import { clearlyBadCursor } from '../../../util'
|
|
14
|
+
import { clearlyBadCursor, resHeaders } from '../../../util'
|
|
15
15
|
|
|
16
16
|
export default function (server: Server, ctx: AppContext) {
|
|
17
17
|
const getMutes = createPipeline(skeleton, hydration, noRules, presentation)
|
|
18
18
|
server.app.bsky.graph.getMutes({
|
|
19
19
|
auth: ctx.authVerifier.standard,
|
|
20
|
-
handler: async ({ params, auth }) => {
|
|
20
|
+
handler: async ({ params, auth, req }) => {
|
|
21
21
|
const viewer = auth.credentials.iss
|
|
22
|
-
const
|
|
22
|
+
const labelers = ctx.reqLabelers(req)
|
|
23
|
+
const hydrateCtx = { labelers, viewer }
|
|
24
|
+
const result = await getMutes({ ...params, hydrateCtx }, ctx)
|
|
23
25
|
return {
|
|
24
26
|
encoding: 'application/json',
|
|
25
27
|
body: result,
|
|
28
|
+
headers: resHeaders({ labelers }),
|
|
26
29
|
}
|
|
27
30
|
},
|
|
28
31
|
})
|
|
@@ -34,7 +37,7 @@ const skeleton = async (input: SkeletonFnInput<Context, Params>) => {
|
|
|
34
37
|
return { mutedDids: [] }
|
|
35
38
|
}
|
|
36
39
|
const { dids, cursor } = await ctx.hydrator.dataplane.getMutes({
|
|
37
|
-
actorDid: params.viewer,
|
|
40
|
+
actorDid: params.hydrateCtx.viewer,
|
|
38
41
|
cursor: params.cursor,
|
|
39
42
|
limit: params.limit,
|
|
40
43
|
})
|
|
@@ -48,9 +51,8 @@ const hydration = async (
|
|
|
48
51
|
input: HydrationFnInput<Context, Params, SkeletonState>,
|
|
49
52
|
) => {
|
|
50
53
|
const { ctx, params, skeleton } = input
|
|
51
|
-
const { viewer } = params
|
|
52
54
|
const { mutedDids } = skeleton
|
|
53
|
-
return ctx.hydrator.hydrateProfiles(mutedDids,
|
|
55
|
+
return ctx.hydrator.hydrateProfiles(mutedDids, params.hydrateCtx)
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
const presentation = (
|
|
@@ -70,7 +72,7 @@ type Context = {
|
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
type Params = QueryParams & {
|
|
73
|
-
viewer: string
|
|
75
|
+
hydrateCtx: HydrateCtx & { viewer: string }
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
type SkeletonState = {
|
|
@@ -10,8 +10,9 @@ import {
|
|
|
10
10
|
SkeletonFnInput,
|
|
11
11
|
createPipeline,
|
|
12
12
|
} from '../../../../pipeline'
|
|
13
|
-
import { Hydrator } from '../../../../hydration/hydrator'
|
|
13
|
+
import { HydrateCtx, Hydrator } from '../../../../hydration/hydrator'
|
|
14
14
|
import { Views } from '../../../../views'
|
|
15
|
+
import { resHeaders } from '../../../util'
|
|
15
16
|
|
|
16
17
|
export default function (server: Server, ctx: AppContext) {
|
|
17
18
|
const getSuggestedFollowsByActor = createPipeline(
|
|
@@ -22,15 +23,18 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
22
23
|
)
|
|
23
24
|
server.app.bsky.graph.getSuggestedFollowsByActor({
|
|
24
25
|
auth: ctx.authVerifier.standard,
|
|
25
|
-
handler: async ({ auth, params }) => {
|
|
26
|
+
handler: async ({ auth, params, req }) => {
|
|
26
27
|
const viewer = auth.credentials.iss
|
|
28
|
+
const labelers = ctx.reqLabelers(req)
|
|
29
|
+
const hydrateCtx = { labelers, viewer }
|
|
27
30
|
const result = await getSuggestedFollowsByActor(
|
|
28
|
-
{ ...params,
|
|
31
|
+
{ ...params, hydrateCtx },
|
|
29
32
|
ctx,
|
|
30
33
|
)
|
|
31
34
|
return {
|
|
32
35
|
encoding: 'application/json',
|
|
33
36
|
body: result,
|
|
37
|
+
headers: resHeaders({ labelers }),
|
|
34
38
|
}
|
|
35
39
|
},
|
|
36
40
|
})
|
|
@@ -43,7 +47,7 @@ const skeleton = async (input: SkeletonFnInput<Context, Params>) => {
|
|
|
43
47
|
throw new InvalidRequestError('Actor not found')
|
|
44
48
|
}
|
|
45
49
|
const { dids, cursor } = await ctx.hydrator.dataplane.getFollowSuggestions({
|
|
46
|
-
actorDid: params.viewer,
|
|
50
|
+
actorDid: params.hydrateCtx.viewer,
|
|
47
51
|
relativeToDid,
|
|
48
52
|
})
|
|
49
53
|
return {
|
|
@@ -56,9 +60,8 @@ const hydration = async (
|
|
|
56
60
|
input: HydrationFnInput<Context, Params, SkeletonState>,
|
|
57
61
|
) => {
|
|
58
62
|
const { ctx, params, skeleton } = input
|
|
59
|
-
const { viewer } = params
|
|
60
63
|
const { suggestedDids } = skeleton
|
|
61
|
-
return ctx.hydrator.hydrateProfilesDetailed(suggestedDids,
|
|
64
|
+
return ctx.hydrator.hydrateProfilesDetailed(suggestedDids, params.hydrateCtx)
|
|
62
65
|
}
|
|
63
66
|
|
|
64
67
|
const noBlocksOrMutes = (
|
|
@@ -90,7 +93,7 @@ type Context = {
|
|
|
90
93
|
}
|
|
91
94
|
|
|
92
95
|
type Params = QueryParams & {
|
|
93
|
-
viewer: string
|
|
96
|
+
hydrateCtx: HydrateCtx & { viewer: string }
|
|
94
97
|
}
|
|
95
98
|
|
|
96
99
|
type SkeletonState = {
|
|
@@ -6,7 +6,7 @@ import { MuteOperation_Type } from '../../../../proto/bsync_pb'
|
|
|
6
6
|
export default function (server: Server, ctx: AppContext) {
|
|
7
7
|
server.app.bsky.graph.muteActor({
|
|
8
8
|
auth: ctx.authVerifier.standard,
|
|
9
|
-
handler: async ({
|
|
9
|
+
handler: async ({ auth, input }) => {
|
|
10
10
|
const { actor } = input.body
|
|
11
11
|
const requester = auth.credentials.iss
|
|
12
12
|
const [did] = await ctx.hydrator.actor.getDids([actor])
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Server } from '../../../../lexicon'
|
|
2
|
+
import AppContext from '../../../../context'
|
|
3
|
+
import { mapDefined } from '@atproto/common'
|
|
4
|
+
import { resHeaders } from '../../../util'
|
|
5
|
+
|
|
6
|
+
export default function (server: Server, ctx: AppContext) {
|
|
7
|
+
server.app.bsky.labeler.getServices({
|
|
8
|
+
auth: ctx.authVerifier.standardOptional,
|
|
9
|
+
handler: async ({ params, auth, req }) => {
|
|
10
|
+
const { dids, detailed } = params
|
|
11
|
+
const viewer = auth.credentials.iss
|
|
12
|
+
const labelers = ctx.reqLabelers(req)
|
|
13
|
+
|
|
14
|
+
const hydration = await ctx.hydrator.hydrateLabelers(dids, {
|
|
15
|
+
viewer,
|
|
16
|
+
labelers,
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
const views = mapDefined(dids, (did) => {
|
|
20
|
+
if (detailed) {
|
|
21
|
+
const view = ctx.views.labelerDetailed(did, hydration)
|
|
22
|
+
if (!view) return
|
|
23
|
+
return {
|
|
24
|
+
$type: 'app.bsky.labeler.defs#labelerViewDetailed',
|
|
25
|
+
...view,
|
|
26
|
+
}
|
|
27
|
+
} else {
|
|
28
|
+
const view = ctx.views.labeler(did, hydration)
|
|
29
|
+
if (!view) return
|
|
30
|
+
return {
|
|
31
|
+
$type: 'app.bsky.labeler.defs#labelerView',
|
|
32
|
+
...view,
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
encoding: 'application/json',
|
|
39
|
+
body: {
|
|
40
|
+
views,
|
|
41
|
+
},
|
|
42
|
+
headers: resHeaders({ labelers }),
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
})
|
|
46
|
+
}
|
|
@@ -10,11 +10,11 @@ import {
|
|
|
10
10
|
RulesFnInput,
|
|
11
11
|
SkeletonFnInput,
|
|
12
12
|
} from '../../../../pipeline'
|
|
13
|
-
import { Hydrator } from '../../../../hydration/hydrator'
|
|
13
|
+
import { HydrateCtx, Hydrator } from '../../../../hydration/hydrator'
|
|
14
14
|
import { Views } from '../../../../views'
|
|
15
15
|
import { Notification } from '../../../../proto/bsky_pb'
|
|
16
16
|
import { didFromUri } from '../../../../hydration/util'
|
|
17
|
-
import { clearlyBadCursor } from '../../../util'
|
|
17
|
+
import { clearlyBadCursor, resHeaders } from '../../../util'
|
|
18
18
|
|
|
19
19
|
export default function (server: Server, ctx: AppContext) {
|
|
20
20
|
const listNotifications = createPipeline(
|
|
@@ -25,12 +25,15 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
25
25
|
)
|
|
26
26
|
server.app.bsky.notification.listNotifications({
|
|
27
27
|
auth: ctx.authVerifier.standard,
|
|
28
|
-
handler: async ({ params, auth }) => {
|
|
28
|
+
handler: async ({ params, auth, req }) => {
|
|
29
29
|
const viewer = auth.credentials.iss
|
|
30
|
-
const
|
|
30
|
+
const labelers = ctx.reqLabelers(req)
|
|
31
|
+
const hydrateCtx = { labelers, viewer }
|
|
32
|
+
const result = await listNotifications({ ...params, hydrateCtx }, ctx)
|
|
31
33
|
return {
|
|
32
34
|
encoding: 'application/json',
|
|
33
35
|
body: result,
|
|
36
|
+
headers: resHeaders({ labelers }),
|
|
34
37
|
}
|
|
35
38
|
},
|
|
36
39
|
})
|
|
@@ -43,17 +46,18 @@ const skeleton = async (
|
|
|
43
46
|
if (params.seenAt) {
|
|
44
47
|
throw new InvalidRequestError('The seenAt parameter is unsupported')
|
|
45
48
|
}
|
|
49
|
+
const viewer = params.hydrateCtx.viewer
|
|
46
50
|
if (clearlyBadCursor(params.cursor)) {
|
|
47
51
|
return { notifs: [] }
|
|
48
52
|
}
|
|
49
53
|
const [res, lastSeenRes] = await Promise.all([
|
|
50
54
|
ctx.hydrator.dataplane.getNotifications({
|
|
51
|
-
actorDid:
|
|
55
|
+
actorDid: viewer,
|
|
52
56
|
cursor: params.cursor,
|
|
53
57
|
limit: params.limit,
|
|
54
58
|
}),
|
|
55
59
|
ctx.hydrator.dataplane.getNotificationSeen({
|
|
56
|
-
actorDid:
|
|
60
|
+
actorDid: viewer,
|
|
57
61
|
}),
|
|
58
62
|
])
|
|
59
63
|
// @NOTE for the first page of results if there's no last-seen time, consider top notification unread
|
|
@@ -73,7 +77,7 @@ const hydration = async (
|
|
|
73
77
|
input: HydrationFnInput<Context, Params, SkeletonState>,
|
|
74
78
|
) => {
|
|
75
79
|
const { skeleton, params, ctx } = input
|
|
76
|
-
return ctx.hydrator.hydrateNotifications(skeleton.notifs, params.
|
|
80
|
+
return ctx.hydrator.hydrateNotifications(skeleton.notifs, params.hydrateCtx)
|
|
77
81
|
}
|
|
78
82
|
|
|
79
83
|
const noBlockOrMutes = (
|
|
@@ -107,7 +111,7 @@ type Context = {
|
|
|
107
111
|
}
|
|
108
112
|
|
|
109
113
|
type Params = QueryParams & {
|
|
110
|
-
viewer: string
|
|
114
|
+
hydrateCtx: HydrateCtx & { viewer: string }
|
|
111
115
|
}
|
|
112
116
|
|
|
113
117
|
type SkeletonState = {
|