@atproto/bsky 0.0.224 → 0.0.226
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 +34 -0
- package/dist/api/app/bsky/actor/getProfile.d.ts.map +1 -1
- package/dist/api/app/bsky/actor/getProfile.js +2 -1
- package/dist/api/app/bsky/actor/getProfile.js.map +1 -1
- package/dist/api/app/bsky/actor/getProfiles.d.ts.map +1 -1
- package/dist/api/app/bsky/actor/getProfiles.js +2 -1
- package/dist/api/app/bsky/actor/getProfiles.js.map +1 -1
- package/dist/api/app/bsky/actor/searchActors.d.ts.map +1 -1
- package/dist/api/app/bsky/actor/searchActors.js +2 -1
- package/dist/api/app/bsky/actor/searchActors.js.map +1 -1
- package/dist/api/app/bsky/bookmark/getBookmarks.d.ts.map +1 -1
- package/dist/api/app/bsky/bookmark/getBookmarks.js +1 -1
- package/dist/api/app/bsky/bookmark/getBookmarks.js.map +1 -1
- package/dist/api/app/bsky/contact/getMatches.d.ts.map +1 -1
- package/dist/api/app/bsky/contact/getMatches.js +1 -1
- package/dist/api/app/bsky/contact/getMatches.js.map +1 -1
- package/dist/api/app/bsky/feed/getAuthorFeed.d.ts.map +1 -1
- package/dist/api/app/bsky/feed/getAuthorFeed.js +2 -1
- package/dist/api/app/bsky/feed/getAuthorFeed.js.map +1 -1
- package/dist/api/app/bsky/feed/getLikes.d.ts.map +1 -1
- package/dist/api/app/bsky/feed/getLikes.js +2 -1
- package/dist/api/app/bsky/feed/getLikes.js.map +1 -1
- package/dist/api/app/bsky/feed/getPostThread.d.ts.map +1 -1
- package/dist/api/app/bsky/feed/getPostThread.js +2 -1
- package/dist/api/app/bsky/feed/getPostThread.js.map +1 -1
- package/dist/api/app/bsky/feed/getQuotes.d.ts.map +1 -1
- package/dist/api/app/bsky/feed/getQuotes.js +2 -1
- package/dist/api/app/bsky/feed/getQuotes.js.map +1 -1
- package/dist/api/app/bsky/feed/getRepostedBy.d.ts.map +1 -1
- package/dist/api/app/bsky/feed/getRepostedBy.js +2 -1
- package/dist/api/app/bsky/feed/getRepostedBy.js.map +1 -1
- package/dist/api/app/bsky/feed/getTimeline.d.ts +2 -4
- package/dist/api/app/bsky/feed/getTimeline.d.ts.map +1 -1
- package/dist/api/app/bsky/feed/getTimeline.js +1 -1
- package/dist/api/app/bsky/feed/getTimeline.js.map +1 -1
- package/dist/api/app/bsky/feed/searchPosts.d.ts.map +1 -1
- package/dist/api/app/bsky/feed/searchPosts.js +2 -1
- package/dist/api/app/bsky/feed/searchPosts.js.map +1 -1
- package/dist/api/app/bsky/graph/getActorStarterPacks.d.ts.map +1 -1
- package/dist/api/app/bsky/graph/getActorStarterPacks.js +2 -1
- package/dist/api/app/bsky/graph/getActorStarterPacks.js.map +1 -1
- package/dist/api/app/bsky/graph/getBlocks.d.ts.map +1 -1
- package/dist/api/app/bsky/graph/getBlocks.js +1 -1
- package/dist/api/app/bsky/graph/getBlocks.js.map +1 -1
- package/dist/api/app/bsky/graph/getFollowers.d.ts.map +1 -1
- package/dist/api/app/bsky/graph/getFollowers.js +2 -1
- package/dist/api/app/bsky/graph/getFollowers.js.map +1 -1
- package/dist/api/app/bsky/graph/getFollows.d.ts.map +1 -1
- package/dist/api/app/bsky/graph/getFollows.js +2 -1
- package/dist/api/app/bsky/graph/getFollows.js.map +1 -1
- package/dist/api/app/bsky/graph/getKnownFollowers.d.ts.map +1 -1
- package/dist/api/app/bsky/graph/getKnownFollowers.js +1 -1
- package/dist/api/app/bsky/graph/getKnownFollowers.js.map +1 -1
- package/dist/api/app/bsky/graph/getList.d.ts.map +1 -1
- package/dist/api/app/bsky/graph/getList.js +2 -1
- package/dist/api/app/bsky/graph/getList.js.map +1 -1
- package/dist/api/app/bsky/graph/getListBlocks.d.ts.map +1 -1
- package/dist/api/app/bsky/graph/getListBlocks.js +1 -1
- package/dist/api/app/bsky/graph/getListBlocks.js.map +1 -1
- package/dist/api/app/bsky/graph/getListMutes.d.ts.map +1 -1
- package/dist/api/app/bsky/graph/getListMutes.js +1 -1
- package/dist/api/app/bsky/graph/getListMutes.js.map +1 -1
- package/dist/api/app/bsky/graph/getLists.d.ts.map +1 -1
- package/dist/api/app/bsky/graph/getLists.js +2 -1
- package/dist/api/app/bsky/graph/getLists.js.map +1 -1
- package/dist/api/app/bsky/graph/getListsWithMembership.js +1 -1
- package/dist/api/app/bsky/graph/getListsWithMembership.js.map +1 -1
- package/dist/api/app/bsky/graph/getMutes.d.ts.map +1 -1
- package/dist/api/app/bsky/graph/getMutes.js +1 -1
- package/dist/api/app/bsky/graph/getMutes.js.map +1 -1
- package/dist/api/app/bsky/graph/getStarterPack.d.ts.map +1 -1
- package/dist/api/app/bsky/graph/getStarterPack.js +2 -1
- package/dist/api/app/bsky/graph/getStarterPack.js.map +1 -1
- package/dist/api/app/bsky/graph/getStarterPacks.d.ts.map +1 -1
- package/dist/api/app/bsky/graph/getStarterPacks.js +2 -1
- package/dist/api/app/bsky/graph/getStarterPacks.js.map +1 -1
- package/dist/api/app/bsky/graph/getStarterPacksWithMembership.js +1 -1
- package/dist/api/app/bsky/graph/getStarterPacksWithMembership.js.map +1 -1
- package/dist/api/app/bsky/graph/searchStarterPacks.d.ts.map +1 -1
- package/dist/api/app/bsky/graph/searchStarterPacks.js +2 -1
- package/dist/api/app/bsky/graph/searchStarterPacks.js.map +1 -1
- package/dist/api/app/bsky/notification/listActivitySubscriptions.js +1 -1
- package/dist/api/app/bsky/notification/listActivitySubscriptions.js.map +1 -1
- package/dist/api/app/bsky/notification/listNotifications.d.ts.map +1 -1
- package/dist/api/app/bsky/notification/listNotifications.js +1 -1
- package/dist/api/app/bsky/notification/listNotifications.js.map +1 -1
- package/dist/api/app/bsky/unspecced/getPostThreadOtherV2.d.ts.map +1 -1
- package/dist/api/app/bsky/unspecced/getPostThreadOtherV2.js +2 -1
- package/dist/api/app/bsky/unspecced/getPostThreadOtherV2.js.map +1 -1
- package/dist/api/app/bsky/unspecced/getPostThreadV2.d.ts.map +1 -1
- package/dist/api/app/bsky/unspecced/getPostThreadV2.js +2 -1
- package/dist/api/app/bsky/unspecced/getPostThreadV2.js.map +1 -1
- package/dist/auth-verifier.d.ts +1 -0
- package/dist/auth-verifier.d.ts.map +1 -1
- package/dist/auth-verifier.js +1 -0
- package/dist/auth-verifier.js.map +1 -1
- package/dist/data-plane/client/index.d.ts.map +1 -1
- package/dist/data-plane/client/index.js +2 -0
- package/dist/data-plane/client/index.js.map +1 -1
- package/dist/data-plane/client/util.d.ts +2 -1
- package/dist/data-plane/client/util.d.ts.map +1 -1
- package/dist/data-plane/client/util.js +6 -1
- package/dist/data-plane/client/util.js.map +1 -1
- package/dist/data-plane/client/util.test.d.ts +2 -0
- package/dist/data-plane/client/util.test.d.ts.map +1 -0
- package/dist/data-plane/client/util.test.js +33 -0
- package/dist/data-plane/client/util.test.js.map +1 -0
- package/dist/data-plane/server/indexing/plugins/feed-generator.js +2 -1
- package/dist/data-plane/server/indexing/plugins/feed-generator.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/list.js +2 -1
- package/dist/data-plane/server/indexing/plugins/list.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/post.js +3 -3
- package/dist/data-plane/server/indexing/plugins/post.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/profile.js +3 -2
- package/dist/data-plane/server/indexing/plugins/profile.js.map +1 -1
- package/dist/hydration/hydrator.d.ts +5 -0
- package/dist/hydration/hydrator.d.ts.map +1 -1
- package/dist/hydration/hydrator.js +8 -0
- package/dist/hydration/hydrator.js.map +1 -1
- package/dist/hydration/util.d.ts +13 -7
- package/dist/hydration/util.d.ts.map +1 -1
- package/dist/hydration/util.js +30 -10
- package/dist/hydration/util.js.map +1 -1
- package/dist/lexicons/app/bsky/actor/defs.defs.d.ts +1 -0
- package/dist/lexicons/app/bsky/actor/defs.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/actor/defs.defs.js +1 -0
- package/dist/lexicons/app/bsky/actor/defs.defs.js.map +1 -1
- package/dist/lexicons/app/bsky/actor/profile.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/actor/profile.defs.js +2 -10
- package/dist/lexicons/app/bsky/actor/profile.defs.js.map +1 -1
- package/dist/lexicons/app/bsky/embed/external.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/embed/external.defs.js +1 -1
- package/dist/lexicons/app/bsky/embed/external.defs.js.map +1 -1
- package/dist/lexicons/app/bsky/embed/images.defs.d.ts +3 -0
- package/dist/lexicons/app/bsky/embed/images.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/embed/images.defs.js +1 -5
- package/dist/lexicons/app/bsky/embed/images.defs.js.map +1 -1
- package/dist/lexicons/app/bsky/embed/video.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/embed/video.defs.js +2 -6
- package/dist/lexicons/app/bsky/embed/video.defs.js.map +1 -1
- package/dist/lexicons/app/bsky/feed/generator.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/feed/generator.defs.js +1 -5
- package/dist/lexicons/app/bsky/feed/generator.defs.js.map +1 -1
- package/dist/lexicons/app/bsky/graph/list.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/graph/list.defs.js +1 -5
- package/dist/lexicons/app/bsky/graph/list.defs.js.map +1 -1
- package/dist/lexicons/app/bsky/video/defs.defs.js +1 -1
- package/dist/lexicons/app/bsky/video/defs.defs.js.map +1 -1
- package/dist/lexicons/com/atproto/repo/uploadBlob.defs.d.ts +2 -6
- package/dist/lexicons/com/atproto/repo/uploadBlob.defs.d.ts.map +1 -1
- package/dist/lexicons/com/atproto/repo/uploadBlob.defs.js +1 -1
- package/dist/lexicons/com/atproto/repo/uploadBlob.defs.js.map +1 -1
- package/dist/views/index.d.ts.map +1 -1
- package/dist/views/index.js +13 -8
- package/dist/views/index.js.map +1 -1
- package/dist/views/util.d.ts +1 -2
- package/dist/views/util.d.ts.map +1 -1
- package/dist/views/util.js +1 -5
- package/dist/views/util.js.map +1 -1
- package/package.json +10 -10
- package/src/api/app/bsky/actor/getProfile.ts +3 -1
- package/src/api/app/bsky/actor/getProfiles.ts +3 -1
- package/src/api/app/bsky/actor/searchActors.ts +3 -1
- package/src/api/app/bsky/bookmark/getBookmarks.ts +3 -6
- package/src/api/app/bsky/contact/getMatches.ts +3 -6
- package/src/api/app/bsky/feed/getAuthorFeed.ts +3 -1
- package/src/api/app/bsky/feed/getLikes.ts +3 -1
- package/src/api/app/bsky/feed/getPostThread.ts +2 -1
- package/src/api/app/bsky/feed/getQuotes.ts +3 -1
- package/src/api/app/bsky/feed/getRepostedBy.ts +3 -1
- package/src/api/app/bsky/feed/getTimeline.ts +3 -6
- package/src/api/app/bsky/feed/searchPosts.ts +3 -1
- package/src/api/app/bsky/graph/getActorStarterPacks.ts +3 -1
- package/src/api/app/bsky/graph/getBlocks.ts +3 -6
- package/src/api/app/bsky/graph/getFollowers.ts +3 -1
- package/src/api/app/bsky/graph/getFollows.ts +3 -1
- package/src/api/app/bsky/graph/getKnownFollowers.ts +3 -6
- package/src/api/app/bsky/graph/getList.ts +3 -1
- package/src/api/app/bsky/graph/getListBlocks.ts +3 -6
- package/src/api/app/bsky/graph/getListMutes.ts +3 -6
- package/src/api/app/bsky/graph/getLists.ts +3 -1
- package/src/api/app/bsky/graph/getListsWithMembership.ts +3 -3
- package/src/api/app/bsky/graph/getMutes.ts +3 -6
- package/src/api/app/bsky/graph/getStarterPack.ts +3 -1
- package/src/api/app/bsky/graph/getStarterPacks.ts +3 -1
- package/src/api/app/bsky/graph/getStarterPacksWithMembership.ts +3 -3
- package/src/api/app/bsky/graph/searchStarterPacks.ts +3 -1
- package/src/api/app/bsky/notification/listActivitySubscriptions.ts +3 -3
- package/src/api/app/bsky/notification/listNotifications.ts +3 -6
- package/src/api/app/bsky/unspecced/getPostThreadOtherV2.ts +2 -1
- package/src/api/app/bsky/unspecced/getPostThreadV2.ts +2 -1
- package/src/auth-verifier.ts +1 -0
- package/src/data-plane/client/index.ts +2 -0
- package/src/data-plane/client/util.test.ts +39 -0
- package/src/data-plane/client/util.ts +9 -1
- package/src/data-plane/server/indexing/plugins/feed-generator.ts +2 -2
- package/src/data-plane/server/indexing/plugins/list.ts +2 -2
- package/src/data-plane/server/indexing/plugins/post.ts +4 -4
- package/src/data-plane/server/indexing/plugins/profile.ts +3 -3
- package/src/hydration/hydrator.ts +8 -0
- package/src/hydration/util.ts +40 -21
- package/src/views/index.ts +19 -15
- package/src/views/util.ts +1 -5
- package/tests/views/__snapshots__/profile.test.ts.snap +3 -0
- package/tests/views/blocks.test.ts +69 -0
- package/tests/views/profile.test.ts +77 -0
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -22,12 +22,14 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
22
22
|
server.add(app.bsky.graph.getStarterPacks, {
|
|
23
23
|
auth: ctx.authVerifier.standardOptional,
|
|
24
24
|
handler: async ({ auth, params, req }) => {
|
|
25
|
-
const { viewer, includeTakedowns } =
|
|
25
|
+
const { viewer, includeTakedowns, skipViewerBlocks } =
|
|
26
|
+
ctx.authVerifier.parseCreds(auth)
|
|
26
27
|
const labelers = ctx.reqLabelers(req)
|
|
27
28
|
const hydrateCtx = await ctx.hydrator.createContext({
|
|
28
29
|
viewer,
|
|
29
30
|
labelers,
|
|
30
31
|
includeTakedowns,
|
|
32
|
+
skipViewerBlocks,
|
|
31
33
|
})
|
|
32
34
|
|
|
33
35
|
const result = await getStarterPacks({ ...params, hydrateCtx }, ctx)
|
|
@@ -3,7 +3,7 @@ import { AtUriString, DidString } from '@atproto/syntax'
|
|
|
3
3
|
import { InvalidRequestError, Server } from '@atproto/xrpc-server'
|
|
4
4
|
import { AppContext } from '../../../../context'
|
|
5
5
|
import {
|
|
6
|
-
|
|
6
|
+
HydrateCtxWithViewer,
|
|
7
7
|
Hydrator,
|
|
8
8
|
mergeManyStates,
|
|
9
9
|
} from '../../../../hydration/hydrator'
|
|
@@ -35,7 +35,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
35
35
|
viewer,
|
|
36
36
|
})
|
|
37
37
|
const result = await getStarterPacksWithMembership(
|
|
38
|
-
{ ...params, hydrateCtx
|
|
38
|
+
{ ...params, hydrateCtx },
|
|
39
39
|
ctx,
|
|
40
40
|
)
|
|
41
41
|
|
|
@@ -126,7 +126,7 @@ type Context = {
|
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
type Params = app.bsky.graph.getStarterPacksWithMembership.$Params & {
|
|
129
|
-
hydrateCtx:
|
|
129
|
+
hydrateCtx: HydrateCtxWithViewer
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
type SkeletonState = {
|
|
@@ -27,12 +27,14 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
27
27
|
server.add(app.bsky.graph.searchStarterPacks, {
|
|
28
28
|
auth: ctx.authVerifier.standardOptional,
|
|
29
29
|
handler: async ({ auth, params, req }) => {
|
|
30
|
-
const { viewer, includeTakedowns } =
|
|
30
|
+
const { viewer, includeTakedowns, skipViewerBlocks } =
|
|
31
|
+
ctx.authVerifier.parseCreds(auth)
|
|
31
32
|
const labelers = ctx.reqLabelers(req)
|
|
32
33
|
const hydrateCtx = await ctx.hydrator.createContext({
|
|
33
34
|
viewer,
|
|
34
35
|
labelers,
|
|
35
36
|
includeTakedowns,
|
|
37
|
+
skipViewerBlocks,
|
|
36
38
|
})
|
|
37
39
|
const results = await searchStarterPacks({ ...params, hydrateCtx }, ctx)
|
|
38
40
|
return {
|
|
@@ -2,7 +2,7 @@ import { mapDefined } from '@atproto/common'
|
|
|
2
2
|
import { DidString } from '@atproto/syntax'
|
|
3
3
|
import { Server } from '@atproto/xrpc-server'
|
|
4
4
|
import { AppContext } from '../../../../context'
|
|
5
|
-
import {
|
|
5
|
+
import { HydrateCtxWithViewer, Hydrator } from '../../../../hydration/hydrator'
|
|
6
6
|
import { app } from '../../../../lexicons/index.js'
|
|
7
7
|
import {
|
|
8
8
|
HydrationFnInput,
|
|
@@ -32,7 +32,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
32
32
|
})
|
|
33
33
|
|
|
34
34
|
const result = await listActivitySubscriptions(
|
|
35
|
-
{ ...params, hydrateCtx
|
|
35
|
+
{ ...params, hydrateCtx },
|
|
36
36
|
ctx,
|
|
37
37
|
)
|
|
38
38
|
|
|
@@ -103,7 +103,7 @@ type Context = {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
type Params = app.bsky.notification.listActivitySubscriptions.$Params & {
|
|
106
|
-
hydrateCtx:
|
|
106
|
+
hydrateCtx: HydrateCtxWithViewer
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
type SkeletonState = {
|
|
@@ -3,7 +3,7 @@ import { AtUriString, DatetimeString, DidString } from '@atproto/syntax'
|
|
|
3
3
|
import { InvalidRequestError, Server } from '@atproto/xrpc-server'
|
|
4
4
|
import { ServerConfig } from '../../../../config'
|
|
5
5
|
import { AppContext } from '../../../../context'
|
|
6
|
-
import {
|
|
6
|
+
import { HydrateCtxWithViewer, Hydrator } from '../../../../hydration/hydrator'
|
|
7
7
|
import { app } from '../../../../lexicons/index.js'
|
|
8
8
|
import {
|
|
9
9
|
HydrationFnInput,
|
|
@@ -31,10 +31,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
31
31
|
const viewer = auth.credentials.iss
|
|
32
32
|
const labelers = ctx.reqLabelers(req)
|
|
33
33
|
const hydrateCtx = await ctx.hydrator.createContext({ labelers, viewer })
|
|
34
|
-
const result = await listNotifications(
|
|
35
|
-
{ ...params, hydrateCtx: hydrateCtx.copy({ viewer }) },
|
|
36
|
-
ctx,
|
|
37
|
-
)
|
|
34
|
+
const result = await listNotifications({ ...params, hydrateCtx }, ctx)
|
|
38
35
|
return {
|
|
39
36
|
encoding: 'application/json',
|
|
40
37
|
body: result,
|
|
@@ -254,7 +251,7 @@ type Context = {
|
|
|
254
251
|
}
|
|
255
252
|
|
|
256
253
|
type Params = app.bsky.notification.listNotifications.$Params & {
|
|
257
|
-
hydrateCtx:
|
|
254
|
+
hydrateCtx: HydrateCtxWithViewer
|
|
258
255
|
}
|
|
259
256
|
|
|
260
257
|
type SkeletonState = {
|
|
@@ -35,7 +35,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
35
35
|
server.add(app.bsky.unspecced.getPostThreadOtherV2, {
|
|
36
36
|
auth: ctx.authVerifier.optionalStandardOrRole,
|
|
37
37
|
handler: async ({ params, auth, req }) => {
|
|
38
|
-
const { viewer, includeTakedowns, include3pBlocks } =
|
|
38
|
+
const { viewer, includeTakedowns, include3pBlocks, skipViewerBlocks } =
|
|
39
39
|
ctx.authVerifier.parseCreds(auth)
|
|
40
40
|
const labelers = ctx.reqLabelers(req)
|
|
41
41
|
const hydrateCtx = await ctx.hydrator.createContext({
|
|
@@ -43,6 +43,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
43
43
|
viewer,
|
|
44
44
|
includeTakedowns,
|
|
45
45
|
include3pBlocks,
|
|
46
|
+
skipViewerBlocks,
|
|
46
47
|
})
|
|
47
48
|
|
|
48
49
|
return {
|
|
@@ -26,7 +26,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
26
26
|
server.add(app.bsky.unspecced.getPostThreadV2, {
|
|
27
27
|
auth: ctx.authVerifier.optionalStandardOrRole,
|
|
28
28
|
handler: async ({ params, auth, req }) => {
|
|
29
|
-
const { viewer, includeTakedowns, include3pBlocks } =
|
|
29
|
+
const { viewer, includeTakedowns, include3pBlocks, skipViewerBlocks } =
|
|
30
30
|
ctx.authVerifier.parseCreds(auth)
|
|
31
31
|
const labelers = ctx.reqLabelers(req)
|
|
32
32
|
const features = ctx.featureGatesClient.scope(
|
|
@@ -42,6 +42,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
42
42
|
viewer,
|
|
43
43
|
includeTakedowns,
|
|
44
44
|
include3pBlocks,
|
|
45
|
+
skipViewerBlocks,
|
|
45
46
|
features,
|
|
46
47
|
})
|
|
47
48
|
|
package/src/auth-verifier.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
import { createGrpcTransport } from '@connectrpc/connect-node'
|
|
11
11
|
import { Service } from '../../proto/bsky_connect'
|
|
12
12
|
import { HostList } from './hosts'
|
|
13
|
+
import { callerInterceptor } from './util'
|
|
13
14
|
|
|
14
15
|
export * from './hosts'
|
|
15
16
|
export * from './util'
|
|
@@ -105,6 +106,7 @@ const createBaseClient = (
|
|
|
105
106
|
httpVersion,
|
|
106
107
|
acceptCompression: [],
|
|
107
108
|
nodeOptions: { rejectUnauthorized },
|
|
109
|
+
interceptors: [callerInterceptor('appview')],
|
|
108
110
|
})
|
|
109
111
|
return createPromiseClient(Service, transport)
|
|
110
112
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/// <reference types="jest" />
|
|
2
|
+
import { callerInterceptor } from './util'
|
|
3
|
+
|
|
4
|
+
describe('callerInterceptor', () => {
|
|
5
|
+
it('sets x-atlantis-caller header on the request', async () => {
|
|
6
|
+
const interceptor = callerInterceptor('appview')
|
|
7
|
+
const expectedResponse = { status: 'ok' }
|
|
8
|
+
const next = jest.fn().mockResolvedValue(expectedResponse)
|
|
9
|
+
|
|
10
|
+
const req = { header: new Headers() }
|
|
11
|
+
const handler = interceptor(next)
|
|
12
|
+
const res = await handler(req as any)
|
|
13
|
+
|
|
14
|
+
expect(req.header.get('x-atlantis-caller')).toBe('appview')
|
|
15
|
+
expect(next).toHaveBeenCalledWith(req)
|
|
16
|
+
expect(res).toBe(expectedResponse)
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
it('uses the provided caller value', async () => {
|
|
20
|
+
const interceptor = callerInterceptor('feed-generator')
|
|
21
|
+
const next = jest.fn().mockResolvedValue({})
|
|
22
|
+
|
|
23
|
+
const req = { header: new Headers() }
|
|
24
|
+
await interceptor(next)(req as any)
|
|
25
|
+
|
|
26
|
+
expect(req.header.get('x-atlantis-caller')).toBe('feed-generator')
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('does not overwrite other existing headers', async () => {
|
|
30
|
+
const interceptor = callerInterceptor('appview')
|
|
31
|
+
const next = jest.fn().mockResolvedValue({})
|
|
32
|
+
|
|
33
|
+
const req = { header: new Headers({ 'x-other': 'value' }) }
|
|
34
|
+
await interceptor(next)(req as any)
|
|
35
|
+
|
|
36
|
+
expect(req.header.get('x-atlantis-caller')).toBe('appview')
|
|
37
|
+
expect(req.header.get('x-other')).toBe('value')
|
|
38
|
+
})
|
|
39
|
+
})
|
|
@@ -1,7 +1,15 @@
|
|
|
1
|
-
import { Code, ConnectError } from '@connectrpc/connect'
|
|
1
|
+
import { Code, ConnectError, Interceptor } from '@connectrpc/connect'
|
|
2
2
|
import * as ui8 from 'uint8arrays'
|
|
3
3
|
import { getDidKeyFromMultibase } from '@atproto/identity'
|
|
4
4
|
|
|
5
|
+
export const callerInterceptor =
|
|
6
|
+
(caller: string): Interceptor =>
|
|
7
|
+
(next) =>
|
|
8
|
+
(req) => {
|
|
9
|
+
req.header.set('x-atlantis-caller', caller)
|
|
10
|
+
return next(req)
|
|
11
|
+
}
|
|
12
|
+
|
|
5
13
|
export const isDataplaneError = (
|
|
6
14
|
err: unknown,
|
|
7
15
|
code?: Code,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Selectable } from 'kysely'
|
|
2
|
-
import { Cid } from '@atproto/lex'
|
|
2
|
+
import { Cid, getBlobCidString } from '@atproto/lex'
|
|
3
3
|
import { AtUri, normalizeDatetimeAlways } from '@atproto/syntax'
|
|
4
4
|
import { app } from '../../../../lexicons'
|
|
5
5
|
import { BackgroundQueue } from '../../background'
|
|
@@ -28,7 +28,7 @@ const insertFn = async (
|
|
|
28
28
|
descriptionFacets: obj.descriptionFacets
|
|
29
29
|
? JSON.stringify(obj.descriptionFacets)
|
|
30
30
|
: undefined,
|
|
31
|
-
avatarCid: obj.avatar
|
|
31
|
+
avatarCid: getBlobCidString(obj.avatar),
|
|
32
32
|
createdAt: normalizeDatetimeAlways(obj.createdAt),
|
|
33
33
|
indexedAt: timestamp,
|
|
34
34
|
})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Selectable } from 'kysely'
|
|
2
|
-
import { Cid } from '@atproto/lex'
|
|
2
|
+
import { Cid, getBlobCidString } from '@atproto/lex'
|
|
3
3
|
import { AtUri, normalizeDatetimeAlways } from '@atproto/syntax'
|
|
4
4
|
import { app } from '../../../../lexicons'
|
|
5
5
|
import { BackgroundQueue } from '../../background'
|
|
@@ -28,7 +28,7 @@ const insertFn = async (
|
|
|
28
28
|
descriptionFacets: obj.descriptionFacets
|
|
29
29
|
? JSON.stringify(obj.descriptionFacets)
|
|
30
30
|
: undefined,
|
|
31
|
-
avatarCid: obj.avatar
|
|
31
|
+
avatarCid: getBlobCidString(obj.avatar),
|
|
32
32
|
createdAt: normalizeDatetimeAlways(obj.createdAt),
|
|
33
33
|
indexedAt: timestamp,
|
|
34
34
|
})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Insertable, Selectable, sql } from 'kysely'
|
|
2
|
-
import { $Typed, Cid, lexParse } from '@atproto/lex'
|
|
2
|
+
import { $Typed, Cid, getBlobCidString, lexParse } from '@atproto/lex'
|
|
3
3
|
import { AtUri, normalizeDatetimeAlways } from '@atproto/syntax'
|
|
4
4
|
import { app } from '../../../../lexicons'
|
|
5
5
|
import {
|
|
@@ -152,7 +152,7 @@ const insertFn = async (
|
|
|
152
152
|
const imagesEmbed = images.map((img, i) => ({
|
|
153
153
|
postUri: uri.toString(),
|
|
154
154
|
position: i,
|
|
155
|
-
imageCid: img.image
|
|
155
|
+
imageCid: getBlobCidString(img.image),
|
|
156
156
|
alt: img.alt,
|
|
157
157
|
}))
|
|
158
158
|
embeds.push(imagesEmbed)
|
|
@@ -164,7 +164,7 @@ const insertFn = async (
|
|
|
164
164
|
uri: external.uri,
|
|
165
165
|
title: external.title,
|
|
166
166
|
description: external.description,
|
|
167
|
-
thumbCid: external.thumb
|
|
167
|
+
thumbCid: getBlobCidString(external.thumb) || null,
|
|
168
168
|
}
|
|
169
169
|
embeds.push(externalEmbed)
|
|
170
170
|
await db.insertInto('post_embed_external').values(externalEmbed).execute()
|
|
@@ -231,7 +231,7 @@ const insertFn = async (
|
|
|
231
231
|
const { video } = postEmbed
|
|
232
232
|
const videoEmbed = {
|
|
233
233
|
postUri: uri.toString(),
|
|
234
|
-
videoCid: video
|
|
234
|
+
videoCid: getBlobCidString(video),
|
|
235
235
|
// @NOTE: alt is required for image but not for video on the lexicon.
|
|
236
236
|
alt: postEmbed.alt ?? null,
|
|
237
237
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Cid } from '@atproto/lex'
|
|
1
|
+
import { Cid, getBlobCidString } from '@atproto/lex'
|
|
2
2
|
import { AtUri } from '@atproto/syntax'
|
|
3
3
|
import { app } from '../../../../lexicons'
|
|
4
4
|
import { BackgroundQueue } from '../../background'
|
|
@@ -24,8 +24,8 @@ const insertFn = async (
|
|
|
24
24
|
creator: uri.host,
|
|
25
25
|
displayName: obj.displayName,
|
|
26
26
|
description: obj.description,
|
|
27
|
-
avatarCid: obj.avatar
|
|
28
|
-
bannerCid: obj.banner
|
|
27
|
+
avatarCid: getBlobCidString(obj.avatar),
|
|
28
|
+
bannerCid: getBlobCidString(obj.banner),
|
|
29
29
|
joinedViaStarterPackUri: obj.joinedViaStarterPack?.uri,
|
|
30
30
|
createdAt: obj.createdAt ?? new Date().toISOString(),
|
|
31
31
|
indexedAt: timestamp,
|
|
@@ -85,6 +85,7 @@ export class HydrateCtx {
|
|
|
85
85
|
includeTakedowns = this.vals.includeTakedowns
|
|
86
86
|
overrideIncludeTakedownsForActor = this.vals.overrideIncludeTakedownsForActor
|
|
87
87
|
include3pBlocks = this.vals.include3pBlocks
|
|
88
|
+
skipViewerBlocks = this.vals.skipViewerBlocks
|
|
88
89
|
includeDebugField = this.vals.includeDebugField
|
|
89
90
|
features = this.vals.features
|
|
90
91
|
constructor(private vals: HydrateCtxVals) {}
|
|
@@ -98,12 +99,15 @@ export class HydrateCtx {
|
|
|
98
99
|
}
|
|
99
100
|
}
|
|
100
101
|
|
|
102
|
+
export type HydrateCtxWithViewer = HydrateCtx & { viewer: string }
|
|
103
|
+
|
|
101
104
|
export type HydrateCtxVals = {
|
|
102
105
|
labelers: ParsedLabelers
|
|
103
106
|
viewer: DidString | null
|
|
104
107
|
includeTakedowns?: boolean
|
|
105
108
|
overrideIncludeTakedownsForActor?: boolean
|
|
106
109
|
include3pBlocks?: boolean
|
|
110
|
+
skipViewerBlocks?: boolean
|
|
107
111
|
includeDebugField?: boolean
|
|
108
112
|
features: ScopedFeatureGatesClient
|
|
109
113
|
}
|
|
@@ -1357,6 +1361,7 @@ export class Hydrator {
|
|
|
1357
1361
|
viewer: vals.viewer,
|
|
1358
1362
|
includeTakedowns: vals.includeTakedowns,
|
|
1359
1363
|
include3pBlocks: vals.include3pBlocks,
|
|
1364
|
+
skipViewerBlocks: vals.skipViewerBlocks,
|
|
1360
1365
|
includeDebugField,
|
|
1361
1366
|
// create default anonymous scope
|
|
1362
1367
|
features: vals.features || this.config.featureGatesClient.scope({}),
|
|
@@ -1425,6 +1430,9 @@ const labelSubjectsForDid = (dids: DidString[]) => {
|
|
|
1425
1430
|
...dids.map((did) =>
|
|
1426
1431
|
AtUri.make(did, app.bsky.actor.profile.$type, 'self').toString(),
|
|
1427
1432
|
),
|
|
1433
|
+
...dids.map((did) =>
|
|
1434
|
+
AtUri.make(did, app.bsky.actor.status.$type, 'self').toString(),
|
|
1435
|
+
),
|
|
1428
1436
|
]
|
|
1429
1437
|
}
|
|
1430
1438
|
|
package/src/hydration/util.ts
CHANGED
|
@@ -2,19 +2,24 @@ import { Timestamp } from '@bufbuild/protobuf'
|
|
|
2
2
|
import {
|
|
3
3
|
AtUriString,
|
|
4
4
|
Cid,
|
|
5
|
-
|
|
5
|
+
InferInput,
|
|
6
|
+
InferOutput,
|
|
6
7
|
LexParseOptions,
|
|
7
8
|
LexValue,
|
|
8
9
|
RecordSchema,
|
|
9
10
|
Schema,
|
|
10
11
|
TypedLexMap,
|
|
11
12
|
ValidateOptions,
|
|
12
|
-
|
|
13
|
+
lexParseJsonBytes,
|
|
13
14
|
parseCidSafe,
|
|
14
15
|
} from '@atproto/lex'
|
|
15
16
|
import { AtUri } from '@atproto/syntax'
|
|
16
17
|
import { Record as RecordEntry } from '../proto/bsky_pb'
|
|
17
18
|
|
|
19
|
+
const PARSE_OPTIONS: LexParseOptions & ValidateOptions = {
|
|
20
|
+
strict: false,
|
|
21
|
+
}
|
|
22
|
+
|
|
18
23
|
export class HydrationMap<K, T> extends Map<K, T | null> implements Merges {
|
|
19
24
|
merge(map: HydrationMap<K, T>): this {
|
|
20
25
|
for (const [key, val] of map) {
|
|
@@ -28,8 +33,8 @@ export interface Merges {
|
|
|
28
33
|
merge<T extends this>(map: T): this
|
|
29
34
|
}
|
|
30
35
|
|
|
31
|
-
export type RecordInfo<T extends
|
|
32
|
-
record: T
|
|
36
|
+
export type RecordInfo<T extends TypedLexMap> = {
|
|
37
|
+
record: T
|
|
33
38
|
cid: string
|
|
34
39
|
sortedAt: Date
|
|
35
40
|
indexedAt: Date
|
|
@@ -70,17 +75,32 @@ export function parseRecord<TSchema extends RecordSchema>(
|
|
|
70
75
|
recordSchema: TSchema,
|
|
71
76
|
recordEntry: RecordEntry,
|
|
72
77
|
includeTakedowns: boolean,
|
|
73
|
-
): RecordInfo<
|
|
78
|
+
): RecordInfo<InferInput<TSchema>> | undefined {
|
|
74
79
|
if (!includeTakedowns && recordEntry.takenDown) {
|
|
75
80
|
return undefined
|
|
76
81
|
}
|
|
77
82
|
|
|
78
83
|
const cid = recordEntry.cid
|
|
79
|
-
if (!cid)
|
|
84
|
+
if (!cid) {
|
|
85
|
+
return undefined
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (recordEntry.record.byteLength === 0) {
|
|
89
|
+
return undefined
|
|
90
|
+
}
|
|
80
91
|
|
|
81
|
-
const record =
|
|
92
|
+
const record = lexParseJsonBytes(recordEntry.record, PARSE_OPTIONS)
|
|
82
93
|
if (!record) {
|
|
83
|
-
return
|
|
94
|
+
return undefined
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// @NOTE We cannot use parse mode here. We must return the original to ensure
|
|
98
|
+
// that the caller gets the same data as what is stored in the PDS (in case of
|
|
99
|
+
// records). This is important because the receiver of the data should be able
|
|
100
|
+
// to compute the right record CID.
|
|
101
|
+
|
|
102
|
+
if (!recordSchema.$matches(record, PARSE_OPTIONS)) {
|
|
103
|
+
return undefined
|
|
84
104
|
}
|
|
85
105
|
|
|
86
106
|
return {
|
|
@@ -92,23 +112,22 @@ export function parseRecord<TSchema extends RecordSchema>(
|
|
|
92
112
|
}
|
|
93
113
|
}
|
|
94
114
|
|
|
115
|
+
/**
|
|
116
|
+
* Decodes binary data containing a JSON representation of a Lex value, and
|
|
117
|
+
* validates it against the provided schema, in parse mode (i.e., allowing
|
|
118
|
+
* coercion & defaults).
|
|
119
|
+
*
|
|
120
|
+
* Returns undefined if the input is empty (from dataplane's empty value
|
|
121
|
+
* convention), or if the validation fails.
|
|
122
|
+
*/
|
|
95
123
|
export const parseJsonBytes = <TSchema extends Schema<LexValue>>(
|
|
96
124
|
schema: TSchema,
|
|
97
125
|
bytes: Uint8Array | undefined,
|
|
98
|
-
|
|
99
|
-
): Infer<TSchema> | undefined => {
|
|
126
|
+
): InferOutput<TSchema> | undefined => {
|
|
100
127
|
if (!bytes || bytes.byteLength === 0) return undefined
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
bytes.buffer,
|
|
105
|
-
bytes.byteOffset,
|
|
106
|
-
bytes.byteLength,
|
|
107
|
-
)
|
|
108
|
-
const jsonString = jsonBuffer.toString('utf8')
|
|
109
|
-
|
|
110
|
-
const value = lexParse(jsonString, options)
|
|
111
|
-
return schema.ifMatches(value, options)
|
|
128
|
+
const value = lexParseJsonBytes(bytes, PARSE_OPTIONS)
|
|
129
|
+
const result = schema.safeParse(value, PARSE_OPTIONS)
|
|
130
|
+
return result.success ? result.value : undefined
|
|
112
131
|
}
|
|
113
132
|
|
|
114
133
|
export const parseString = <T extends string | undefined>(
|
package/src/views/index.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { HOUR, MINUTE, mapDefined } from '@atproto/common'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
$Typed,
|
|
4
|
+
Un$Typed,
|
|
5
|
+
Unknown$TypedObject,
|
|
6
|
+
UriString,
|
|
7
|
+
getBlobCidString,
|
|
8
|
+
} from '@atproto/lex'
|
|
3
9
|
import {
|
|
4
10
|
AtUri,
|
|
5
11
|
AtUriString,
|
|
@@ -104,12 +110,7 @@ import {
|
|
|
104
110
|
isSelfLabelsType,
|
|
105
111
|
isVideoEmbedType,
|
|
106
112
|
} from './types.js'
|
|
107
|
-
import {
|
|
108
|
-
VideoUriBuilder,
|
|
109
|
-
cidFromBlobJson,
|
|
110
|
-
parsePostgate,
|
|
111
|
-
parseThreadGate,
|
|
112
|
-
} from './util'
|
|
113
|
+
import { VideoUriBuilder, parsePostgate, parseThreadGate } from './util'
|
|
113
114
|
|
|
114
115
|
const notificationDeletedRecord =
|
|
115
116
|
app.bsky.notification.defs.recordDeleted.$build({})
|
|
@@ -169,6 +170,7 @@ export class Views {
|
|
|
169
170
|
}
|
|
170
171
|
|
|
171
172
|
viewerBlockExists(did: DidString, state: HydrationState): boolean {
|
|
173
|
+
if (state.ctx?.skipViewerBlocks) return false
|
|
172
174
|
const viewer = state.profileViewers?.get(did)
|
|
173
175
|
if (!viewer) return false
|
|
174
176
|
return !!(
|
|
@@ -277,7 +279,7 @@ export class Views {
|
|
|
277
279
|
? this.imgUriBuilder.getPresetUri(
|
|
278
280
|
'banner',
|
|
279
281
|
did,
|
|
280
|
-
|
|
282
|
+
getBlobCidString(actor.profile.banner),
|
|
281
283
|
)
|
|
282
284
|
: undefined,
|
|
283
285
|
followersCount: profileAggs?.followers ?? 0,
|
|
@@ -356,7 +358,7 @@ export class Views {
|
|
|
356
358
|
? this.imgUriBuilder.getPresetUri(
|
|
357
359
|
'avatar',
|
|
358
360
|
did,
|
|
359
|
-
|
|
361
|
+
getBlobCidString(actor.profile.avatar),
|
|
360
362
|
)
|
|
361
363
|
: undefined,
|
|
362
364
|
// associated.feedgens and associated.lists info not necessarily included
|
|
@@ -576,6 +578,7 @@ export class Views {
|
|
|
576
578
|
}
|
|
577
579
|
|
|
578
580
|
const uri = AtUri.make(did, app.bsky.actor.status.$nsid, 'self').toString()
|
|
581
|
+
const labels = state.labels?.getBySubject(uri)
|
|
579
582
|
|
|
580
583
|
const minDuration = 5 * MINUTE
|
|
581
584
|
const maxDuration = 4 * HOUR
|
|
@@ -602,6 +605,7 @@ export class Views {
|
|
|
602
605
|
record.embed && isExternalEmbedType(record.embed)
|
|
603
606
|
? this.externalEmbed(did, record.embed)
|
|
604
607
|
: undefined,
|
|
608
|
+
labels,
|
|
605
609
|
expiresAt,
|
|
606
610
|
isActive,
|
|
607
611
|
}
|
|
@@ -672,7 +676,7 @@ export class Views {
|
|
|
672
676
|
? this.imgUriBuilder.getPresetUri(
|
|
673
677
|
'avatar',
|
|
674
678
|
creator,
|
|
675
|
-
|
|
679
|
+
getBlobCidString(list.record.avatar),
|
|
676
680
|
)
|
|
677
681
|
: undefined,
|
|
678
682
|
listItemCount: listAgg?.listItems ?? 0,
|
|
@@ -916,7 +920,7 @@ export class Views {
|
|
|
916
920
|
? this.imgUriBuilder.getPresetUri(
|
|
917
921
|
'avatar',
|
|
918
922
|
creatorDid,
|
|
919
|
-
|
|
923
|
+
getBlobCidString(feedgen.record.avatar),
|
|
920
924
|
)
|
|
921
925
|
: undefined,
|
|
922
926
|
likeCount: aggs?.likes ?? 0,
|
|
@@ -2076,12 +2080,12 @@ export class Views {
|
|
|
2076
2080
|
thumb: this.imgUriBuilder.getPresetUri(
|
|
2077
2081
|
'feed_thumbnail',
|
|
2078
2082
|
did,
|
|
2079
|
-
|
|
2083
|
+
getBlobCidString(img.image),
|
|
2080
2084
|
),
|
|
2081
2085
|
fullsize: this.imgUriBuilder.getPresetUri(
|
|
2082
2086
|
'feed_fullsize',
|
|
2083
2087
|
did,
|
|
2084
|
-
|
|
2088
|
+
getBlobCidString(img.image),
|
|
2085
2089
|
),
|
|
2086
2090
|
alt: img.alt,
|
|
2087
2091
|
aspectRatio: img.aspectRatio,
|
|
@@ -2092,7 +2096,7 @@ export class Views {
|
|
|
2092
2096
|
}
|
|
2093
2097
|
|
|
2094
2098
|
videoEmbed(did: DidString, embed: VideoEmbed): $Typed<VideoEmbedView> {
|
|
2095
|
-
const cid =
|
|
2099
|
+
const cid = getBlobCidString(embed.video)
|
|
2096
2100
|
return app.bsky.embed.video.view.$build({
|
|
2097
2101
|
cid,
|
|
2098
2102
|
playlist: this.videoUriBuilder.playlist({ did, cid }),
|
|
@@ -2117,7 +2121,7 @@ export class Views {
|
|
|
2117
2121
|
? this.imgUriBuilder.getPresetUri(
|
|
2118
2122
|
'feed_thumbnail',
|
|
2119
2123
|
did,
|
|
2120
|
-
|
|
2124
|
+
getBlobCidString(thumb),
|
|
2121
2125
|
)
|
|
2122
2126
|
: undefined,
|
|
2123
2127
|
},
|
package/src/views/util.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as util from 'node:util'
|
|
2
|
-
import { AtUriString,
|
|
2
|
+
import { AtUriString, DidString, UriString } from '@atproto/lex'
|
|
3
3
|
import {
|
|
4
4
|
GateRecord,
|
|
5
5
|
PostRecord,
|
|
@@ -59,10 +59,6 @@ type ParsedThreadGate = {
|
|
|
59
59
|
allowListUris?: AtUriString[]
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
export const cidFromBlobJson = (json: BlobRef): string => {
|
|
63
|
-
return json.ref.toString()
|
|
64
|
-
}
|
|
65
|
-
|
|
66
62
|
export const parsePostgate = ({
|
|
67
63
|
gate,
|
|
68
64
|
viewerDid,
|
|
@@ -722,6 +722,7 @@ Object {
|
|
|
722
722
|
"expiresAt": "1970-01-01T00:00:00.000Z",
|
|
723
723
|
"isActive": true,
|
|
724
724
|
"isDisabled": false,
|
|
725
|
+
"labels": Array [],
|
|
725
726
|
"record": Object {
|
|
726
727
|
"$type": "app.bsky.actor.status",
|
|
727
728
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
@@ -755,6 +756,7 @@ Object {
|
|
|
755
756
|
"expiresAt": "1970-01-01T00:00:00.000Z",
|
|
756
757
|
"isActive": false,
|
|
757
758
|
"isDisabled": false,
|
|
759
|
+
"labels": Array [],
|
|
758
760
|
"record": Object {
|
|
759
761
|
"$type": "app.bsky.actor.status",
|
|
760
762
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
@@ -788,6 +790,7 @@ Object {
|
|
|
788
790
|
"expiresAt": "1970-01-01T00:00:00.000Z",
|
|
789
791
|
"isActive": true,
|
|
790
792
|
"isDisabled": true,
|
|
793
|
+
"labels": Array [],
|
|
791
794
|
"record": Object {
|
|
792
795
|
"$type": "app.bsky.actor.status",
|
|
793
796
|
"createdAt": "1970-01-01T00:00:00.000Z",
|