@atproto/bsky 0.0.151 → 0.0.153
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/unspecced/getPostThreadHiddenV2.d.ts +4 -0
- package/dist/api/app/bsky/unspecced/getPostThreadHiddenV2.d.ts.map +1 -0
- package/dist/api/app/bsky/unspecced/getPostThreadHiddenV2.js +77 -0
- package/dist/api/app/bsky/unspecced/getPostThreadHiddenV2.js.map +1 -0
- package/dist/api/app/bsky/unspecced/getPostThreadV2.d.ts +4 -0
- package/dist/api/app/bsky/unspecced/getPostThreadV2.d.ts.map +1 -0
- package/dist/api/app/bsky/unspecced/getPostThreadV2.js +86 -0
- package/dist/api/app/bsky/unspecced/getPostThreadV2.js.map +1 -0
- package/dist/api/com/atproto/repo/getRecord.d.ts.map +1 -1
- package/dist/api/com/atproto/repo/getRecord.js +1 -1
- package/dist/api/com/atproto/repo/getRecord.js.map +1 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +4 -0
- package/dist/api/index.js.map +1 -1
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +17 -0
- package/dist/config.js.map +1 -1
- package/dist/data-plane/server/db/migrations/20250528T221913281Z-add-record-tags.d.ts +4 -0
- package/dist/data-plane/server/db/migrations/20250528T221913281Z-add-record-tags.d.ts.map +1 -0
- package/dist/data-plane/server/db/migrations/20250528T221913281Z-add-record-tags.js +11 -0
- package/dist/data-plane/server/db/migrations/20250528T221913281Z-add-record-tags.js.map +1 -0
- package/dist/data-plane/server/db/migrations/index.d.ts +1 -0
- package/dist/data-plane/server/db/migrations/index.d.ts.map +1 -1
- package/dist/data-plane/server/db/migrations/index.js +2 -1
- package/dist/data-plane/server/db/migrations/index.js.map +1 -1
- package/dist/data-plane/server/db/tables/record.d.ts +1 -0
- package/dist/data-plane/server/db/tables/record.d.ts.map +1 -1
- package/dist/data-plane/server/db/tables/record.js.map +1 -1
- package/dist/data-plane/server/routes/records.d.ts.map +1 -1
- package/dist/data-plane/server/routes/records.js +1 -0
- package/dist/data-plane/server/routes/records.js.map +1 -1
- package/dist/hydration/feed.d.ts +1 -0
- package/dist/hydration/feed.d.ts.map +1 -1
- package/dist/hydration/feed.js +2 -0
- package/dist/hydration/feed.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/lexicon/index.d.ts +6 -2
- package/dist/lexicon/index.d.ts.map +1 -1
- package/dist/lexicon/index.js +12 -4
- package/dist/lexicon/index.js.map +1 -1
- package/dist/lexicon/lexicons.d.ts +508 -82
- package/dist/lexicon/lexicons.d.ts.map +1 -1
- package/dist/lexicon/lexicons.js +264 -42
- package/dist/lexicon/lexicons.js.map +1 -1
- package/dist/lexicon/types/app/bsky/unspecced/getPostThreadHiddenV2.d.ts +63 -0
- package/dist/lexicon/types/app/bsky/unspecced/getPostThreadHiddenV2.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/unspecced/getPostThreadHiddenV2.js +25 -0
- package/dist/lexicon/types/app/bsky/unspecced/getPostThreadHiddenV2.js.map +1 -0
- package/dist/lexicon/types/app/bsky/unspecced/getPostThreadV2.d.ts +92 -0
- package/dist/lexicon/types/app/bsky/unspecced/getPostThreadV2.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/unspecced/getPostThreadV2.js +52 -0
- package/dist/lexicon/types/app/bsky/unspecced/getPostThreadV2.js.map +1 -0
- package/dist/proto/bsky_pb.d.ts +4 -0
- package/dist/proto/bsky_pb.d.ts.map +1 -1
- package/dist/proto/bsky_pb.js +16 -0
- package/dist/proto/bsky_pb.js.map +1 -1
- package/dist/proto/bsync_connect.d.ts +19 -1
- package/dist/proto/bsync_connect.d.ts.map +1 -1
- package/dist/proto/bsync_connect.js +18 -0
- package/dist/proto/bsync_connect.js.map +1 -1
- package/dist/proto/bsync_pb.d.ts +150 -0
- package/dist/proto/bsync_pb.d.ts.map +1 -1
- package/dist/proto/bsync_pb.js +401 -1
- package/dist/proto/bsync_pb.js.map +1 -1
- package/dist/views/index.d.ts +40 -0
- package/dist/views/index.d.ts.map +1 -1
- package/dist/views/index.js +499 -0
- package/dist/views/index.js.map +1 -1
- package/dist/views/threads-v2.d.ts +65 -0
- package/dist/views/threads-v2.d.ts.map +1 -0
- package/dist/views/threads-v2.js +205 -0
- package/dist/views/threads-v2.js.map +1 -0
- package/package.json +5 -5
- package/proto/bsky.proto +1 -0
- package/src/api/app/bsky/unspecced/getPostThreadHiddenV2.ts +117 -0
- package/src/api/app/bsky/unspecced/getPostThreadV2.ts +130 -0
- package/src/api/com/atproto/repo/getRecord.ts +4 -1
- package/src/api/index.ts +4 -0
- package/src/config.ts +24 -0
- package/src/data-plane/server/db/migrations/20250528T221913281Z-add-record-tags.ts +9 -0
- package/src/data-plane/server/db/migrations/index.ts +1 -0
- package/src/data-plane/server/db/tables/record.ts +1 -0
- package/src/data-plane/server/routes/records.ts +1 -0
- package/src/hydration/feed.ts +4 -0
- package/src/index.ts +2 -0
- package/src/lexicon/index.ts +33 -9
- package/src/lexicon/lexicons.ts +284 -43
- package/src/lexicon/types/app/bsky/unspecced/getPostThreadHiddenV2.ts +95 -0
- package/src/lexicon/types/app/bsky/unspecced/getPostThreadV2.ts +160 -0
- package/src/proto/bsky_pb.ts +12 -0
- package/src/proto/bsync_connect.ts +22 -0
- package/src/proto/bsync_pb.ts +355 -0
- package/src/views/index.ts +780 -0
- package/src/views/threads-v2.ts +381 -0
- package/tests/seed/thread-v2.ts +874 -0
- package/tests/seed/util.ts +52 -0
- package/tests/views/__snapshots__/thread-v2.test.ts.snap +1091 -0
- package/tests/views/thread-v2.test.ts +2121 -0
- package/tsconfig.build.tsbuildinfo +1 -1
- package/tsconfig.tests.tsbuildinfo +1 -1
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { ServerConfig } from '../../../../config'
|
|
2
|
+
import { AppContext } from '../../../../context'
|
|
3
|
+
import { Code, DataPlaneClient, isDataplaneError } from '../../../../data-plane'
|
|
4
|
+
import { HydrateCtx, Hydrator } from '../../../../hydration/hydrator'
|
|
5
|
+
import { Server } from '../../../../lexicon'
|
|
6
|
+
import { QueryParams } from '../../../../lexicon/types/app/bsky/unspecced/getPostThreadHiddenV2'
|
|
7
|
+
import {
|
|
8
|
+
HydrationFnInput,
|
|
9
|
+
PresentationFnInput,
|
|
10
|
+
SkeletonFnInput,
|
|
11
|
+
createPipeline,
|
|
12
|
+
noRules,
|
|
13
|
+
} from '../../../../pipeline'
|
|
14
|
+
import { Views } from '../../../../views'
|
|
15
|
+
import { resHeaders } from '../../../util'
|
|
16
|
+
|
|
17
|
+
// No parents for hidden replies (it would be the anchor post).
|
|
18
|
+
const ABOVE = 0
|
|
19
|
+
|
|
20
|
+
// For hidden replies we don't get more than the top-level replies.
|
|
21
|
+
// To get nested replies, load the thread as one of the hidden replies as anchor.
|
|
22
|
+
const BELOW = 1
|
|
23
|
+
|
|
24
|
+
// It doesn't really matter since BELOW is 1, so it will not be used.
|
|
25
|
+
const BRANCHING_FACTOR = 0
|
|
26
|
+
|
|
27
|
+
export default function (server: Server, ctx: AppContext) {
|
|
28
|
+
const getPostThreadHidden = createPipeline(
|
|
29
|
+
skeleton,
|
|
30
|
+
hydration,
|
|
31
|
+
noRules, // handled in presentation: 3p block-violating replies are turned to #blockedPost, viewer blocks turned to #notFoundPost.
|
|
32
|
+
presentation,
|
|
33
|
+
)
|
|
34
|
+
server.app.bsky.unspecced.getPostThreadHiddenV2({
|
|
35
|
+
auth: ctx.authVerifier.optionalStandardOrRole,
|
|
36
|
+
handler: async ({ params, auth, req }) => {
|
|
37
|
+
const { viewer, includeTakedowns, include3pBlocks } =
|
|
38
|
+
ctx.authVerifier.parseCreds(auth)
|
|
39
|
+
const labelers = ctx.reqLabelers(req)
|
|
40
|
+
const hydrateCtx = await ctx.hydrator.createContext({
|
|
41
|
+
labelers,
|
|
42
|
+
viewer,
|
|
43
|
+
includeTakedowns,
|
|
44
|
+
include3pBlocks,
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
encoding: 'application/json',
|
|
49
|
+
body: await getPostThreadHidden({ ...params, hydrateCtx }, ctx),
|
|
50
|
+
headers: resHeaders({
|
|
51
|
+
labelers: hydrateCtx.labelers,
|
|
52
|
+
}),
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const skeleton = async (inputs: SkeletonFnInput<Context, Params>) => {
|
|
59
|
+
const { ctx, params } = inputs
|
|
60
|
+
const anchor = await ctx.hydrator.resolveUri(params.anchor)
|
|
61
|
+
try {
|
|
62
|
+
const res = await ctx.dataplane.getThread({
|
|
63
|
+
postUri: anchor,
|
|
64
|
+
above: ABOVE,
|
|
65
|
+
below: BELOW,
|
|
66
|
+
})
|
|
67
|
+
return {
|
|
68
|
+
anchor,
|
|
69
|
+
uris: res.uris,
|
|
70
|
+
}
|
|
71
|
+
} catch (err) {
|
|
72
|
+
if (isDataplaneError(err, Code.NotFound)) {
|
|
73
|
+
return {
|
|
74
|
+
anchor,
|
|
75
|
+
uris: [],
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
throw err
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const hydration = async (
|
|
84
|
+
inputs: HydrationFnInput<Context, Params, Skeleton>,
|
|
85
|
+
) => {
|
|
86
|
+
const { ctx, params, skeleton } = inputs
|
|
87
|
+
return ctx.hydrator.hydrateThreadPosts(
|
|
88
|
+
skeleton.uris.map((uri) => ({ uri })),
|
|
89
|
+
params.hydrateCtx,
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const presentation = (
|
|
94
|
+
inputs: PresentationFnInput<Context, Params, Skeleton>,
|
|
95
|
+
) => {
|
|
96
|
+
const { ctx, params, skeleton, hydration } = inputs
|
|
97
|
+
const thread = ctx.views.threadHiddenV2(skeleton, hydration, {
|
|
98
|
+
below: BELOW,
|
|
99
|
+
branchingFactor: BRANCHING_FACTOR,
|
|
100
|
+
prioritizeFollowedUsers: params.prioritizeFollowedUsers,
|
|
101
|
+
})
|
|
102
|
+
return { thread }
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
type Context = {
|
|
106
|
+
dataplane: DataPlaneClient
|
|
107
|
+
hydrator: Hydrator
|
|
108
|
+
views: Views
|
|
109
|
+
cfg: ServerConfig
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
type Params = QueryParams & { hydrateCtx: HydrateCtx }
|
|
113
|
+
|
|
114
|
+
type Skeleton = {
|
|
115
|
+
anchor: string
|
|
116
|
+
uris: string[]
|
|
117
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { ServerConfig } from '../../../../config'
|
|
2
|
+
import { AppContext } from '../../../../context'
|
|
3
|
+
import { Code, DataPlaneClient, isDataplaneError } from '../../../../data-plane'
|
|
4
|
+
import { HydrateCtx, Hydrator } from '../../../../hydration/hydrator'
|
|
5
|
+
import { Server } from '../../../../lexicon'
|
|
6
|
+
import { QueryParams } from '../../../../lexicon/types/app/bsky/unspecced/getPostThreadV2'
|
|
7
|
+
import {
|
|
8
|
+
HydrationFnInput,
|
|
9
|
+
PresentationFnInput,
|
|
10
|
+
SkeletonFnInput,
|
|
11
|
+
createPipeline,
|
|
12
|
+
noRules,
|
|
13
|
+
} from '../../../../pipeline'
|
|
14
|
+
import { postUriToThreadgateUri } from '../../../../util/uris'
|
|
15
|
+
import { Views } from '../../../../views'
|
|
16
|
+
import { resHeaders } from '../../../util'
|
|
17
|
+
|
|
18
|
+
export default function (server: Server, ctx: AppContext) {
|
|
19
|
+
const getPostThread = createPipeline(
|
|
20
|
+
skeleton,
|
|
21
|
+
hydration,
|
|
22
|
+
noRules, // handled in presentation: 3p block-violating replies are turned to #blockedPost, viewer blocks turned to #notFoundPost.
|
|
23
|
+
presentation,
|
|
24
|
+
)
|
|
25
|
+
server.app.bsky.unspecced.getPostThreadV2({
|
|
26
|
+
auth: ctx.authVerifier.optionalStandardOrRole,
|
|
27
|
+
handler: async ({ params, auth, req }) => {
|
|
28
|
+
const { viewer, includeTakedowns, include3pBlocks } =
|
|
29
|
+
ctx.authVerifier.parseCreds(auth)
|
|
30
|
+
const labelers = ctx.reqLabelers(req)
|
|
31
|
+
const hydrateCtx = await ctx.hydrator.createContext({
|
|
32
|
+
labelers,
|
|
33
|
+
viewer,
|
|
34
|
+
includeTakedowns,
|
|
35
|
+
include3pBlocks,
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
encoding: 'application/json',
|
|
40
|
+
body: await getPostThread({ ...params, hydrateCtx }, ctx),
|
|
41
|
+
headers: resHeaders({
|
|
42
|
+
labelers: hydrateCtx.labelers,
|
|
43
|
+
}),
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const skeleton = async (inputs: SkeletonFnInput<Context, Params>) => {
|
|
50
|
+
const { ctx, params } = inputs
|
|
51
|
+
const anchor = await ctx.hydrator.resolveUri(params.anchor)
|
|
52
|
+
try {
|
|
53
|
+
const res = await ctx.dataplane.getThread({
|
|
54
|
+
postUri: anchor,
|
|
55
|
+
above: calculateAbove(ctx, params),
|
|
56
|
+
below: calculateBelow(ctx, anchor, params),
|
|
57
|
+
})
|
|
58
|
+
return {
|
|
59
|
+
anchor,
|
|
60
|
+
uris: res.uris,
|
|
61
|
+
}
|
|
62
|
+
} catch (err) {
|
|
63
|
+
if (isDataplaneError(err, Code.NotFound)) {
|
|
64
|
+
return {
|
|
65
|
+
anchor,
|
|
66
|
+
uris: [],
|
|
67
|
+
}
|
|
68
|
+
} else {
|
|
69
|
+
throw err
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const hydration = async (
|
|
75
|
+
inputs: HydrationFnInput<Context, Params, Skeleton>,
|
|
76
|
+
) => {
|
|
77
|
+
const { ctx, params, skeleton } = inputs
|
|
78
|
+
return ctx.hydrator.hydrateThreadPosts(
|
|
79
|
+
skeleton.uris.map((uri) => ({ uri })),
|
|
80
|
+
params.hydrateCtx,
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const presentation = (
|
|
85
|
+
inputs: PresentationFnInput<Context, Params, Skeleton>,
|
|
86
|
+
) => {
|
|
87
|
+
const { ctx, params, skeleton, hydration } = inputs
|
|
88
|
+
const { hasHiddenReplies, thread } = ctx.views.threadV2(skeleton, hydration, {
|
|
89
|
+
above: calculateAbove(ctx, params),
|
|
90
|
+
below: calculateBelow(ctx, skeleton.anchor, params),
|
|
91
|
+
branchingFactor: params.branchingFactor,
|
|
92
|
+
prioritizeFollowedUsers: params.prioritizeFollowedUsers,
|
|
93
|
+
sort: params.sort,
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
const rootUri =
|
|
97
|
+
hydration.posts?.get(skeleton.anchor)?.record.reply?.root.uri ??
|
|
98
|
+
skeleton.anchor
|
|
99
|
+
const threadgate = ctx.views.threadgate(
|
|
100
|
+
postUriToThreadgateUri(rootUri),
|
|
101
|
+
hydration,
|
|
102
|
+
)
|
|
103
|
+
return { hasHiddenReplies, thread, threadgate }
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
type Context = {
|
|
107
|
+
dataplane: DataPlaneClient
|
|
108
|
+
hydrator: Hydrator
|
|
109
|
+
views: Views
|
|
110
|
+
cfg: ServerConfig
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
type Params = QueryParams & { hydrateCtx: HydrateCtx }
|
|
114
|
+
|
|
115
|
+
type Skeleton = {
|
|
116
|
+
anchor: string
|
|
117
|
+
uris: string[]
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const calculateAbove = (ctx: Context, params: Params) => {
|
|
121
|
+
return params.above ? ctx.cfg.maxThreadParents : 0
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const calculateBelow = (ctx: Context, anchor: string, params: Params) => {
|
|
125
|
+
let maxDepth = ctx.cfg.maxThreadDepth
|
|
126
|
+
if (ctx.cfg.bigThreadUris.has(anchor) && ctx.cfg.bigThreadDepth) {
|
|
127
|
+
maxDepth = ctx.cfg.bigThreadDepth
|
|
128
|
+
}
|
|
129
|
+
return maxDepth ? Math.min(maxDepth, params.below) : params.below
|
|
130
|
+
}
|
|
@@ -25,7 +25,10 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
25
25
|
const result = await ctx.hydrator.getRecord(uri, includeTakedowns)
|
|
26
26
|
|
|
27
27
|
if (!result || (cid && result.cid !== cid)) {
|
|
28
|
-
throw new InvalidRequestError(
|
|
28
|
+
throw new InvalidRequestError(
|
|
29
|
+
`Could not locate record: ${uri}`,
|
|
30
|
+
'RecordNotFound',
|
|
31
|
+
)
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
return {
|
package/src/api/index.ts
CHANGED
|
@@ -49,6 +49,8 @@ import registerPush from './app/bsky/notification/registerPush'
|
|
|
49
49
|
import updateSeen from './app/bsky/notification/updateSeen'
|
|
50
50
|
import getConfig from './app/bsky/unspecced/getConfig'
|
|
51
51
|
import getPopularFeedGenerators from './app/bsky/unspecced/getPopularFeedGenerators'
|
|
52
|
+
import getPostThreadHiddenV2 from './app/bsky/unspecced/getPostThreadHiddenV2'
|
|
53
|
+
import getPostThreadV2 from './app/bsky/unspecced/getPostThreadV2'
|
|
52
54
|
import getUnspeccedSuggestedFeeds from './app/bsky/unspecced/getSuggestedFeeds'
|
|
53
55
|
import getSuggestedStarterPacks from './app/bsky/unspecced/getSuggestedStarterPacks'
|
|
54
56
|
import getSuggestedUsers from './app/bsky/unspecced/getSuggestedUsers'
|
|
@@ -82,6 +84,8 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
82
84
|
getListFeed(server, ctx)
|
|
83
85
|
getQuotes(server, ctx)
|
|
84
86
|
getPostThread(server, ctx)
|
|
87
|
+
getPostThreadHiddenV2(server, ctx)
|
|
88
|
+
getPostThreadV2(server, ctx)
|
|
85
89
|
getPosts(server, ctx)
|
|
86
90
|
searchPosts(server, ctx)
|
|
87
91
|
getActorLikes(server, ctx)
|
package/src/config.ts
CHANGED
|
@@ -56,6 +56,9 @@ export interface ServerConfigValues {
|
|
|
56
56
|
bigThreadUris: Set<string>
|
|
57
57
|
bigThreadDepth?: number
|
|
58
58
|
maxThreadDepth?: number
|
|
59
|
+
maxThreadParents: number
|
|
60
|
+
threadTagsHide: Set<string>
|
|
61
|
+
threadTagsBumpDown: Set<string>
|
|
59
62
|
// notifications
|
|
60
63
|
notificationsDelayMs?: number
|
|
61
64
|
// client config
|
|
@@ -191,6 +194,13 @@ export class ServerConfig {
|
|
|
191
194
|
const maxThreadDepth = process.env.BSKY_MAX_THREAD_DEPTH
|
|
192
195
|
? parseInt(process.env.BSKY_MAX_THREAD_DEPTH || '', 10)
|
|
193
196
|
: undefined
|
|
197
|
+
const maxThreadParents = process.env.BSKY_MAX_THREAD_PARENTS
|
|
198
|
+
? parseInt(process.env.BSKY_MAX_THREAD_PARENTS || '', 10)
|
|
199
|
+
: 50
|
|
200
|
+
const threadTagsHide = new Set(envList(process.env.BSKY_THREAD_TAGS_HIDE))
|
|
201
|
+
const threadTagsBumpDown = new Set(
|
|
202
|
+
envList(process.env.BSKY_THREAD_TAGS_BUMP_DOWN),
|
|
203
|
+
)
|
|
194
204
|
|
|
195
205
|
const notificationsDelayMs = process.env.BSKY_NOTIFICATIONS_DELAY_MS
|
|
196
206
|
? parseInt(process.env.BSKY_NOTIFICATIONS_DELAY_MS || '', 10)
|
|
@@ -258,6 +268,9 @@ export class ServerConfig {
|
|
|
258
268
|
bigThreadUris,
|
|
259
269
|
bigThreadDepth,
|
|
260
270
|
maxThreadDepth,
|
|
271
|
+
maxThreadParents,
|
|
272
|
+
threadTagsHide,
|
|
273
|
+
threadTagsBumpDown,
|
|
261
274
|
notificationsDelayMs,
|
|
262
275
|
disableSsrfProtection,
|
|
263
276
|
proxyAllowHTTP2,
|
|
@@ -458,6 +471,17 @@ export class ServerConfig {
|
|
|
458
471
|
return this.cfg.maxThreadDepth
|
|
459
472
|
}
|
|
460
473
|
|
|
474
|
+
get maxThreadParents() {
|
|
475
|
+
return this.cfg.maxThreadParents
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
get threadTagsHide() {
|
|
479
|
+
return this.cfg.threadTagsHide
|
|
480
|
+
}
|
|
481
|
+
get threadTagsBumpDown() {
|
|
482
|
+
return this.cfg.threadTagsBumpDown
|
|
483
|
+
}
|
|
484
|
+
|
|
461
485
|
get notificationsDelayMs() {
|
|
462
486
|
return this.cfg.notificationsDelayMs ?? 0
|
|
463
487
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Kysely } from 'kysely'
|
|
2
|
+
|
|
3
|
+
export async function up(db: Kysely<unknown>): Promise<void> {
|
|
4
|
+
await db.schema.alterTable('record').addColumn('tags', 'jsonb').execute()
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export async function down(db: Kysely<unknown>): Promise<void> {
|
|
8
|
+
await db.schema.alterTable('record').dropColumn('tags').execute()
|
|
9
|
+
}
|
|
@@ -49,3 +49,4 @@ export * as _20250116T222618297Z from './20250116T222618297Z-post-embed-video'
|
|
|
49
49
|
export * as _20250207T174822012Z from './20250207T174822012Z-add-label-exp'
|
|
50
50
|
export * as _20250404T163421487Z from './20250404T163421487Z-verifications'
|
|
51
51
|
export * as _20250526T023712742Z from './20250526T023712742Z-like-repost-via'
|
|
52
|
+
export * as _20250528T221913281Z from './20250528T221913281Z-add-record-tags'
|
package/src/hydration/feed.ts
CHANGED
|
@@ -25,6 +25,7 @@ export type Post = RecordInfo<PostRecord> & {
|
|
|
25
25
|
violatesEmbeddingRules: boolean
|
|
26
26
|
hasThreadGate: boolean
|
|
27
27
|
hasPostGate: boolean
|
|
28
|
+
tags: Set<string>
|
|
28
29
|
}
|
|
29
30
|
export type Posts = HydrationMap<Post>
|
|
30
31
|
|
|
@@ -37,6 +38,7 @@ export type PostViewerState = {
|
|
|
37
38
|
export type PostViewerStates = HydrationMap<PostViewerState>
|
|
38
39
|
|
|
39
40
|
export type ThreadContext = {
|
|
41
|
+
// Whether the root author has liked the post.
|
|
40
42
|
like?: string
|
|
41
43
|
}
|
|
42
44
|
|
|
@@ -112,6 +114,7 @@ export class FeedHydrator {
|
|
|
112
114
|
const violatesEmbeddingRules = res.meta[i].violatesEmbeddingRules
|
|
113
115
|
const hasThreadGate = res.meta[i].hasThreadGate
|
|
114
116
|
const hasPostGate = res.meta[i].hasPostGate
|
|
117
|
+
const tags = new Set<string>(res.records[i].tags ?? [])
|
|
115
118
|
return acc.set(
|
|
116
119
|
uri,
|
|
117
120
|
record
|
|
@@ -121,6 +124,7 @@ export class FeedHydrator {
|
|
|
121
124
|
violatesEmbeddingRules,
|
|
122
125
|
hasThreadGate,
|
|
123
126
|
hasPostGate,
|
|
127
|
+
tags,
|
|
124
128
|
}
|
|
125
129
|
: null,
|
|
126
130
|
)
|
package/src/index.ts
CHANGED
|
@@ -125,6 +125,8 @@ export class BskyAppView {
|
|
|
125
125
|
imgUriBuilder: imgUriBuilder,
|
|
126
126
|
videoUriBuilder: videoUriBuilder,
|
|
127
127
|
indexedAtEpoch: config.indexedAtEpoch,
|
|
128
|
+
threadTagsBumpDown: [...config.threadTagsBumpDown],
|
|
129
|
+
threadTagsHide: [...config.threadTagsHide],
|
|
128
130
|
})
|
|
129
131
|
|
|
130
132
|
const bsyncClient = createBsyncClient({
|
package/src/lexicon/index.ts
CHANGED
|
@@ -108,8 +108,8 @@ import * as AppBskyFeedGetFeedGenerators from './types/app/bsky/feed/getFeedGene
|
|
|
108
108
|
import * as AppBskyFeedGetFeedSkeleton from './types/app/bsky/feed/getFeedSkeleton.js'
|
|
109
109
|
import * as AppBskyFeedGetLikes from './types/app/bsky/feed/getLikes.js'
|
|
110
110
|
import * as AppBskyFeedGetListFeed from './types/app/bsky/feed/getListFeed.js'
|
|
111
|
-
import * as AppBskyFeedGetPosts from './types/app/bsky/feed/getPosts.js'
|
|
112
111
|
import * as AppBskyFeedGetPostThread from './types/app/bsky/feed/getPostThread.js'
|
|
112
|
+
import * as AppBskyFeedGetPosts from './types/app/bsky/feed/getPosts.js'
|
|
113
113
|
import * as AppBskyFeedGetQuotes from './types/app/bsky/feed/getQuotes.js'
|
|
114
114
|
import * as AppBskyFeedGetRepostedBy from './types/app/bsky/feed/getRepostedBy.js'
|
|
115
115
|
import * as AppBskyFeedGetSuggestedFeeds from './types/app/bsky/feed/getSuggestedFeeds.js'
|
|
@@ -145,6 +145,8 @@ import * as AppBskyNotificationRegisterPush from './types/app/bsky/notification/
|
|
|
145
145
|
import * as AppBskyNotificationUpdateSeen from './types/app/bsky/notification/updateSeen.js'
|
|
146
146
|
import * as AppBskyUnspeccedGetConfig from './types/app/bsky/unspecced/getConfig.js'
|
|
147
147
|
import * as AppBskyUnspeccedGetPopularFeedGenerators from './types/app/bsky/unspecced/getPopularFeedGenerators.js'
|
|
148
|
+
import * as AppBskyUnspeccedGetPostThreadHiddenV2 from './types/app/bsky/unspecced/getPostThreadHiddenV2.js'
|
|
149
|
+
import * as AppBskyUnspeccedGetPostThreadV2 from './types/app/bsky/unspecced/getPostThreadV2.js'
|
|
148
150
|
import * as AppBskyUnspeccedGetSuggestedFeeds from './types/app/bsky/unspecced/getSuggestedFeeds.js'
|
|
149
151
|
import * as AppBskyUnspeccedGetSuggestedFeedsSkeleton from './types/app/bsky/unspecced/getSuggestedFeedsSkeleton.js'
|
|
150
152
|
import * as AppBskyUnspeccedGetSuggestedStarterPacks from './types/app/bsky/unspecced/getSuggestedStarterPacks.js'
|
|
@@ -1497,25 +1499,25 @@ export class AppBskyFeedNS {
|
|
|
1497
1499
|
return this._server.xrpc.method(nsid, cfg)
|
|
1498
1500
|
}
|
|
1499
1501
|
|
|
1500
|
-
|
|
1502
|
+
getPostThread<AV extends AuthVerifier>(
|
|
1501
1503
|
cfg: ConfigOf<
|
|
1502
1504
|
AV,
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
+
AppBskyFeedGetPostThread.Handler<ExtractAuth<AV>>,
|
|
1506
|
+
AppBskyFeedGetPostThread.HandlerReqCtx<ExtractAuth<AV>>
|
|
1505
1507
|
>,
|
|
1506
1508
|
) {
|
|
1507
|
-
const nsid = 'app.bsky.feed.
|
|
1509
|
+
const nsid = 'app.bsky.feed.getPostThread' // @ts-ignore
|
|
1508
1510
|
return this._server.xrpc.method(nsid, cfg)
|
|
1509
1511
|
}
|
|
1510
1512
|
|
|
1511
|
-
|
|
1513
|
+
getPosts<AV extends AuthVerifier>(
|
|
1512
1514
|
cfg: ConfigOf<
|
|
1513
1515
|
AV,
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
+
AppBskyFeedGetPosts.Handler<ExtractAuth<AV>>,
|
|
1517
|
+
AppBskyFeedGetPosts.HandlerReqCtx<ExtractAuth<AV>>
|
|
1516
1518
|
>,
|
|
1517
1519
|
) {
|
|
1518
|
-
const nsid = 'app.bsky.feed.
|
|
1520
|
+
const nsid = 'app.bsky.feed.getPosts' // @ts-ignore
|
|
1519
1521
|
return this._server.xrpc.method(nsid, cfg)
|
|
1520
1522
|
}
|
|
1521
1523
|
|
|
@@ -1944,6 +1946,28 @@ export class AppBskyUnspeccedNS {
|
|
|
1944
1946
|
return this._server.xrpc.method(nsid, cfg)
|
|
1945
1947
|
}
|
|
1946
1948
|
|
|
1949
|
+
getPostThreadHiddenV2<AV extends AuthVerifier>(
|
|
1950
|
+
cfg: ConfigOf<
|
|
1951
|
+
AV,
|
|
1952
|
+
AppBskyUnspeccedGetPostThreadHiddenV2.Handler<ExtractAuth<AV>>,
|
|
1953
|
+
AppBskyUnspeccedGetPostThreadHiddenV2.HandlerReqCtx<ExtractAuth<AV>>
|
|
1954
|
+
>,
|
|
1955
|
+
) {
|
|
1956
|
+
const nsid = 'app.bsky.unspecced.getPostThreadHiddenV2' // @ts-ignore
|
|
1957
|
+
return this._server.xrpc.method(nsid, cfg)
|
|
1958
|
+
}
|
|
1959
|
+
|
|
1960
|
+
getPostThreadV2<AV extends AuthVerifier>(
|
|
1961
|
+
cfg: ConfigOf<
|
|
1962
|
+
AV,
|
|
1963
|
+
AppBskyUnspeccedGetPostThreadV2.Handler<ExtractAuth<AV>>,
|
|
1964
|
+
AppBskyUnspeccedGetPostThreadV2.HandlerReqCtx<ExtractAuth<AV>>
|
|
1965
|
+
>,
|
|
1966
|
+
) {
|
|
1967
|
+
const nsid = 'app.bsky.unspecced.getPostThreadV2' // @ts-ignore
|
|
1968
|
+
return this._server.xrpc.method(nsid, cfg)
|
|
1969
|
+
}
|
|
1970
|
+
|
|
1947
1971
|
getSuggestedFeeds<AV extends AuthVerifier>(
|
|
1948
1972
|
cfg: ConfigOf<
|
|
1949
1973
|
AV,
|