@atproto/bsky 0.0.98 → 0.0.99
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/api/app/bsky/unspecced/getConfig.d.ts.map +1 -1
- package/dist/api/app/bsky/unspecced/getConfig.js +1 -0
- package/dist/api/app/bsky/unspecced/getConfig.js.map +1 -1
- package/dist/api/app/bsky/unspecced/getTrendingTopics.d.ts +4 -0
- package/dist/api/app/bsky/unspecced/getTrendingTopics.d.ts.map +1 -0
- package/dist/api/app/bsky/unspecced/getTrendingTopics.js +51 -0
- package/dist/api/app/bsky/unspecced/getTrendingTopics.js.map +1 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +2 -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 +15 -0
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +2 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +3 -0
- package/dist/context.js.map +1 -1
- package/dist/hydration/actor.d.ts.map +1 -1
- package/dist/hydration/actor.js +6 -6
- package/dist/hydration/actor.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/lexicon/index.d.ts +2 -0
- package/dist/lexicon/index.d.ts.map +1 -1
- package/dist/lexicon/index.js +4 -0
- package/dist/lexicon/index.js.map +1 -1
- package/dist/lexicon/lexicons.d.ts +134 -0
- package/dist/lexicon/lexicons.d.ts.map +1 -1
- package/dist/lexicon/lexicons.js +68 -0
- package/dist/lexicon/lexicons.js.map +1 -1
- package/dist/lexicon/types/app/bsky/unspecced/defs.d.ts +9 -0
- package/dist/lexicon/types/app/bsky/unspecced/defs.d.ts.map +1 -1
- package/dist/lexicon/types/app/bsky/unspecced/defs.js +10 -0
- package/dist/lexicon/types/app/bsky/unspecced/defs.js.map +1 -1
- package/dist/lexicon/types/app/bsky/unspecced/getTrendingTopics.d.ts +39 -0
- package/dist/lexicon/types/app/bsky/unspecced/getTrendingTopics.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/unspecced/getTrendingTopics.js +3 -0
- package/dist/lexicon/types/app/bsky/unspecced/getTrendingTopics.js.map +1 -0
- package/package.json +4 -4
- package/src/api/app/bsky/unspecced/getConfig.ts +1 -0
- package/src/api/app/bsky/unspecced/getTrendingTopics.ts +97 -0
- package/src/api/index.ts +2 -0
- package/src/config.ts +21 -0
- package/src/context.ts +5 -0
- package/src/hydration/actor.ts +9 -9
- package/src/index.ts +11 -0
- package/src/lexicon/index.ts +12 -0
- package/src/lexicon/lexicons.ts +69 -0
- package/src/lexicon/types/app/bsky/unspecced/defs.ts +20 -0
- package/src/lexicon/types/app/bsky/unspecced/getTrendingTopics.ts +49 -0
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -20,4 +20,13 @@ export interface SkeletonSearchStarterPack {
|
|
|
20
20
|
}
|
|
21
21
|
export declare function isSkeletonSearchStarterPack(v: unknown): v is SkeletonSearchStarterPack;
|
|
22
22
|
export declare function validateSkeletonSearchStarterPack(v: unknown): ValidationResult;
|
|
23
|
+
export interface TrendingTopic {
|
|
24
|
+
topic: string;
|
|
25
|
+
displayName?: string;
|
|
26
|
+
description?: string;
|
|
27
|
+
link: string;
|
|
28
|
+
[k: string]: unknown;
|
|
29
|
+
}
|
|
30
|
+
export declare function isTrendingTopic(v: unknown): v is TrendingTopic;
|
|
31
|
+
export declare function validateTrendingTopic(v: unknown): ValidationResult;
|
|
23
32
|
//# sourceMappingURL=defs.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defs.d.ts","sourceRoot":"","sources":["../../../../../../src/lexicon/types/app/bsky/unspecced/defs.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,gBAAgB,EAAW,MAAM,kBAAkB,CAAA;AAK5D,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAA;IACX,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACrB;AAED,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,kBAAkB,CAMxE;AAED,wBAAgB,0BAA0B,CAAC,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAEvE;AAED,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAA;IACX,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACrB;AAED,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,mBAAmB,CAM1E;AAED,wBAAgB,2BAA2B,CAAC,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAExE;AAED,MAAM,WAAW,yBAAyB;IACxC,GAAG,EAAE,MAAM,CAAA;IACX,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACrB;AAED,wBAAgB,2BAA2B,CACzC,CAAC,EAAE,OAAO,GACT,CAAC,IAAI,yBAAyB,CAMhC;AAED,wBAAgB,iCAAiC,CAC/C,CAAC,EAAE,OAAO,GACT,gBAAgB,CAKlB"}
|
|
1
|
+
{"version":3,"file":"defs.d.ts","sourceRoot":"","sources":["../../../../../../src/lexicon/types/app/bsky/unspecced/defs.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,gBAAgB,EAAW,MAAM,kBAAkB,CAAA;AAK5D,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAA;IACX,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACrB;AAED,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,kBAAkB,CAMxE;AAED,wBAAgB,0BAA0B,CAAC,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAEvE;AAED,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAA;IACX,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACrB;AAED,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,mBAAmB,CAM1E;AAED,wBAAgB,2BAA2B,CAAC,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAExE;AAED,MAAM,WAAW,yBAAyB;IACxC,GAAG,EAAE,MAAM,CAAA;IACX,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACrB;AAED,wBAAgB,2BAA2B,CACzC,CAAC,EAAE,OAAO,GACT,CAAC,IAAI,yBAAyB,CAMhC;AAED,wBAAgB,iCAAiC,CAC/C,CAAC,EAAE,OAAO,GACT,gBAAgB,CAKlB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACrB;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,aAAa,CAM9D;AAED,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAElE"}
|
|
@@ -6,6 +6,8 @@ exports.isSkeletonSearchActor = isSkeletonSearchActor;
|
|
|
6
6
|
exports.validateSkeletonSearchActor = validateSkeletonSearchActor;
|
|
7
7
|
exports.isSkeletonSearchStarterPack = isSkeletonSearchStarterPack;
|
|
8
8
|
exports.validateSkeletonSearchStarterPack = validateSkeletonSearchStarterPack;
|
|
9
|
+
exports.isTrendingTopic = isTrendingTopic;
|
|
10
|
+
exports.validateTrendingTopic = validateTrendingTopic;
|
|
9
11
|
const lexicons_1 = require("../../../../lexicons");
|
|
10
12
|
const util_1 = require("../../../../util");
|
|
11
13
|
function isSkeletonSearchPost(v) {
|
|
@@ -32,4 +34,12 @@ function isSkeletonSearchStarterPack(v) {
|
|
|
32
34
|
function validateSkeletonSearchStarterPack(v) {
|
|
33
35
|
return lexicons_1.lexicons.validate('app.bsky.unspecced.defs#skeletonSearchStarterPack', v);
|
|
34
36
|
}
|
|
37
|
+
function isTrendingTopic(v) {
|
|
38
|
+
return ((0, util_1.isObj)(v) &&
|
|
39
|
+
(0, util_1.hasProp)(v, '$type') &&
|
|
40
|
+
v.$type === 'app.bsky.unspecced.defs#trendingTopic');
|
|
41
|
+
}
|
|
42
|
+
function validateTrendingTopic(v) {
|
|
43
|
+
return lexicons_1.lexicons.validate('app.bsky.unspecced.defs#trendingTopic', v);
|
|
44
|
+
}
|
|
35
45
|
//# sourceMappingURL=defs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defs.js","sourceRoot":"","sources":["../../../../../../src/lexicon/types/app/bsky/unspecced/defs.ts"],"names":[],"mappings":";;AAaA,oDAMC;AAED,gEAEC;AAOD,sDAMC;AAED,kEAEC;AAOD,kEAQC;AAED,8EAOC;
|
|
1
|
+
{"version":3,"file":"defs.js","sourceRoot":"","sources":["../../../../../../src/lexicon/types/app/bsky/unspecced/defs.ts"],"names":[],"mappings":";;AAaA,oDAMC;AAED,gEAEC;AAOD,sDAMC;AAED,kEAEC;AAOD,kEAQC;AAED,8EAOC;AAUD,0CAMC;AAED,sDAEC;AAhFD,mDAA+C;AAC/C,2CAAiD;AAQjD,SAAgB,oBAAoB,CAAC,CAAU;IAC7C,OAAO,CACL,IAAA,YAAK,EAAC,CAAC,CAAC;QACR,IAAA,cAAO,EAAC,CAAC,EAAE,OAAO,CAAC;QACnB,CAAC,CAAC,KAAK,KAAK,4CAA4C,CACzD,CAAA;AACH,CAAC;AAED,SAAgB,0BAA0B,CAAC,CAAU;IACnD,OAAO,mBAAQ,CAAC,QAAQ,CAAC,4CAA4C,EAAE,CAAC,CAAC,CAAA;AAC3E,CAAC;AAOD,SAAgB,qBAAqB,CAAC,CAAU;IAC9C,OAAO,CACL,IAAA,YAAK,EAAC,CAAC,CAAC;QACR,IAAA,cAAO,EAAC,CAAC,EAAE,OAAO,CAAC;QACnB,CAAC,CAAC,KAAK,KAAK,6CAA6C,CAC1D,CAAA;AACH,CAAC;AAED,SAAgB,2BAA2B,CAAC,CAAU;IACpD,OAAO,mBAAQ,CAAC,QAAQ,CAAC,6CAA6C,EAAE,CAAC,CAAC,CAAA;AAC5E,CAAC;AAOD,SAAgB,2BAA2B,CACzC,CAAU;IAEV,OAAO,CACL,IAAA,YAAK,EAAC,CAAC,CAAC;QACR,IAAA,cAAO,EAAC,CAAC,EAAE,OAAO,CAAC;QACnB,CAAC,CAAC,KAAK,KAAK,mDAAmD,CAChE,CAAA;AACH,CAAC;AAED,SAAgB,iCAAiC,CAC/C,CAAU;IAEV,OAAO,mBAAQ,CAAC,QAAQ,CACtB,mDAAmD,EACnD,CAAC,CACF,CAAA;AACH,CAAC;AAUD,SAAgB,eAAe,CAAC,CAAU;IACxC,OAAO,CACL,IAAA,YAAK,EAAC,CAAC,CAAC;QACR,IAAA,cAAO,EAAC,CAAC,EAAE,OAAO,CAAC;QACnB,CAAC,CAAC,KAAK,KAAK,uCAAuC,CACpD,CAAA;AACH,CAAC;AAED,SAAgB,qBAAqB,CAAC,CAAU;IAC9C,OAAO,mBAAQ,CAAC,QAAQ,CAAC,uCAAuC,EAAE,CAAC,CAAC,CAAA;AACtE,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED CODE - DO NOT MODIFY
|
|
3
|
+
*/
|
|
4
|
+
import express from 'express';
|
|
5
|
+
import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server';
|
|
6
|
+
import * as AppBskyUnspeccedDefs from './defs';
|
|
7
|
+
export interface QueryParams {
|
|
8
|
+
/** DID of the account making the request (not included for public/unauthenticated queries). Used to boost followed accounts in ranking. */
|
|
9
|
+
viewer?: string;
|
|
10
|
+
limit: number;
|
|
11
|
+
}
|
|
12
|
+
export type InputSchema = undefined;
|
|
13
|
+
export interface OutputSchema {
|
|
14
|
+
topics: AppBskyUnspeccedDefs.TrendingTopic[];
|
|
15
|
+
suggested: AppBskyUnspeccedDefs.TrendingTopic[];
|
|
16
|
+
[k: string]: unknown;
|
|
17
|
+
}
|
|
18
|
+
export type HandlerInput = undefined;
|
|
19
|
+
export interface HandlerSuccess {
|
|
20
|
+
encoding: 'application/json';
|
|
21
|
+
body: OutputSchema;
|
|
22
|
+
headers?: {
|
|
23
|
+
[key: string]: string;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export interface HandlerError {
|
|
27
|
+
status: number;
|
|
28
|
+
message?: string;
|
|
29
|
+
}
|
|
30
|
+
export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough;
|
|
31
|
+
export type HandlerReqCtx<HA extends HandlerAuth = never> = {
|
|
32
|
+
auth: HA;
|
|
33
|
+
params: QueryParams;
|
|
34
|
+
input: HandlerInput;
|
|
35
|
+
req: express.Request;
|
|
36
|
+
res: express.Response;
|
|
37
|
+
};
|
|
38
|
+
export type Handler<HA extends HandlerAuth = never> = (ctx: HandlerReqCtx<HA>) => Promise<HandlerOutput> | HandlerOutput;
|
|
39
|
+
//# sourceMappingURL=getTrendingTopics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getTrendingTopics.d.ts","sourceRoot":"","sources":["../../../../../../src/lexicon/types/app/bsky/unspecced/getTrendingTopics.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,OAAO,MAAM,SAAS,CAAA;AAK7B,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AACtE,OAAO,KAAK,oBAAoB,MAAM,QAAQ,CAAA;AAE9C,MAAM,WAAW,WAAW;IAC1B,2IAA2I;IAC3I,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,MAAM,WAAW,GAAG,SAAS,CAAA;AAEnC,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,oBAAoB,CAAC,aAAa,EAAE,CAAA;IAC5C,SAAS,EAAE,oBAAoB,CAAC,aAAa,EAAE,CAAA;IAC/C,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACrB;AAED,MAAM,MAAM,YAAY,GAAG,SAAS,CAAA;AAEpC,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,kBAAkB,CAAA;IAC5B,IAAI,EAAE,YAAY,CAAA;IAClB,OAAO,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAA;CACpC;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,cAAc,GAAG,kBAAkB,CAAA;AAC9E,MAAM,MAAM,aAAa,CAAC,EAAE,SAAS,WAAW,GAAG,KAAK,IAAI;IAC1D,IAAI,EAAE,EAAE,CAAA;IACR,MAAM,EAAE,WAAW,CAAA;IACnB,KAAK,EAAE,YAAY,CAAA;IACnB,GAAG,EAAE,OAAO,CAAC,OAAO,CAAA;IACpB,GAAG,EAAE,OAAO,CAAC,QAAQ,CAAA;CACtB,CAAA;AACD,MAAM,MAAM,OAAO,CAAC,EAAE,SAAS,WAAW,GAAG,KAAK,IAAI,CACpD,GAAG,EAAE,aAAa,CAAC,EAAE,CAAC,KACnB,OAAO,CAAC,aAAa,CAAC,GAAG,aAAa,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getTrendingTopics.js","sourceRoot":"","sources":["../../../../../../src/lexicon/types/app/bsky/unspecced/getTrendingTopics.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto/bsky",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.99",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Reference implementation of app.bsky App View (Bluesky API)",
|
|
6
6
|
"keywords": [
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"structured-headers": "^1.0.1",
|
|
43
43
|
"typed-emitter": "^2.1.0",
|
|
44
44
|
"uint8arrays": "3.0.0",
|
|
45
|
-
"@atproto/api": "^0.13.
|
|
45
|
+
"@atproto/api": "^0.13.21",
|
|
46
46
|
"@atproto/common": "^0.4.5",
|
|
47
47
|
"@atproto/crypto": "^0.4.2",
|
|
48
48
|
"@atproto/identity": "^0.4.3",
|
|
@@ -66,9 +66,9 @@
|
|
|
66
66
|
"jest": "^28.1.2",
|
|
67
67
|
"ts-node": "^10.8.2",
|
|
68
68
|
"typescript": "^5.6.3",
|
|
69
|
-
"@atproto/api": "^0.13.
|
|
69
|
+
"@atproto/api": "^0.13.21",
|
|
70
70
|
"@atproto/lex-cli": "^0.5.3",
|
|
71
|
-
"@atproto/pds": "^0.4.
|
|
71
|
+
"@atproto/pds": "^0.4.77",
|
|
72
72
|
"@atproto/xrpc": "^0.6.5"
|
|
73
73
|
},
|
|
74
74
|
"scripts": {
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { noUndefinedVals } from '@atproto/common'
|
|
2
|
+
import AppContext from '../../../../context'
|
|
3
|
+
import { Server } from '../../../../lexicon'
|
|
4
|
+
import {
|
|
5
|
+
createPipeline,
|
|
6
|
+
HydrationFnInput,
|
|
7
|
+
PresentationFnInput,
|
|
8
|
+
RulesFnInput,
|
|
9
|
+
SkeletonFnInput,
|
|
10
|
+
} from '../../../../pipeline'
|
|
11
|
+
import { HydrateCtx, Hydrator } from '../../../../hydration/hydrator'
|
|
12
|
+
import { Views } from '../../../../views'
|
|
13
|
+
import { QueryParams } from '../../../../lexicon/types/app/bsky/unspecced/getTrendingTopics'
|
|
14
|
+
import AtpAgent from '@atproto/api'
|
|
15
|
+
import { TrendingTopic } from '../../../../lexicon/types/app/bsky/unspecced/defs'
|
|
16
|
+
import { InternalServerError } from '@atproto/xrpc-server'
|
|
17
|
+
|
|
18
|
+
export default function (server: Server, ctx: AppContext) {
|
|
19
|
+
const getTrendingTopics = createPipeline(
|
|
20
|
+
skeleton,
|
|
21
|
+
hydration,
|
|
22
|
+
noBlocksOrMutes,
|
|
23
|
+
presentation,
|
|
24
|
+
)
|
|
25
|
+
server.app.bsky.unspecced.getTrendingTopics({
|
|
26
|
+
auth: ctx.authVerifier.standardOptional,
|
|
27
|
+
handler: async ({ auth, params, req }) => {
|
|
28
|
+
const viewer = auth.credentials.iss
|
|
29
|
+
const labelers = ctx.reqLabelers(req)
|
|
30
|
+
const hydrateCtx = await ctx.hydrator.createContext({ labelers, viewer })
|
|
31
|
+
const headers = noUndefinedVals({
|
|
32
|
+
'accept-language': req.headers['accept-language'],
|
|
33
|
+
})
|
|
34
|
+
const { ...result } = await getTrendingTopics(
|
|
35
|
+
{ ...params, hydrateCtx: hydrateCtx.copy({ viewer }), headers },
|
|
36
|
+
ctx,
|
|
37
|
+
)
|
|
38
|
+
return {
|
|
39
|
+
encoding: 'application/json',
|
|
40
|
+
body: result,
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const skeleton = async (input: SkeletonFnInput<Context, Params>) => {
|
|
47
|
+
const { params, ctx } = input
|
|
48
|
+
if (ctx.topicsAgent) {
|
|
49
|
+
const res = await ctx.topicsAgent.app.bsky.unspecced.getTrendingTopics(
|
|
50
|
+
{
|
|
51
|
+
viewer: params.viewer,
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
headers: params.headers,
|
|
55
|
+
},
|
|
56
|
+
)
|
|
57
|
+
return res.data
|
|
58
|
+
} else {
|
|
59
|
+
throw new InternalServerError('Topics agent not available')
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const hydration = async (
|
|
64
|
+
_: HydrationFnInput<Context, Params, SkeletonState>,
|
|
65
|
+
) => {
|
|
66
|
+
return {}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const noBlocksOrMutes = (
|
|
70
|
+
input: RulesFnInput<Context, Params, SkeletonState>,
|
|
71
|
+
) => {
|
|
72
|
+
const { skeleton } = input
|
|
73
|
+
return skeleton
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const presentation = (
|
|
77
|
+
input: PresentationFnInput<Context, Params, SkeletonState>,
|
|
78
|
+
) => {
|
|
79
|
+
const { skeleton } = input
|
|
80
|
+
return skeleton
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
type Context = {
|
|
84
|
+
hydrator: Hydrator
|
|
85
|
+
views: Views
|
|
86
|
+
topicsAgent: AtpAgent | undefined
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
type Params = QueryParams & {
|
|
90
|
+
hydrateCtx: HydrateCtx & { viewer: string | null }
|
|
91
|
+
headers: Record<string, string>
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
type SkeletonState = {
|
|
95
|
+
topics: TrendingTopic[]
|
|
96
|
+
suggested: TrendingTopic[]
|
|
97
|
+
}
|
package/src/api/index.ts
CHANGED
|
@@ -38,6 +38,7 @@ import unmuteActorList from './app/bsky/graph/unmuteActorList'
|
|
|
38
38
|
import muteThread from './app/bsky/graph/muteThread'
|
|
39
39
|
import unmuteThread from './app/bsky/graph/unmuteThread'
|
|
40
40
|
import getSuggestedFollowsByActor from './app/bsky/graph/getSuggestedFollowsByActor'
|
|
41
|
+
import getTrendingTopics from './app/bsky/unspecced/getTrendingTopics'
|
|
41
42
|
import getLabelerServices from './app/bsky/labeler/getServices'
|
|
42
43
|
import searchActors from './app/bsky/actor/searchActors'
|
|
43
44
|
import searchActorsTypeahead from './app/bsky/actor/searchActorsTypeahead'
|
|
@@ -104,6 +105,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
104
105
|
muteThread(server, ctx)
|
|
105
106
|
unmuteThread(server, ctx)
|
|
106
107
|
getSuggestedFollowsByActor(server, ctx)
|
|
108
|
+
getTrendingTopics(server, ctx)
|
|
107
109
|
getLabelerServices(server, ctx)
|
|
108
110
|
searchActors(server, ctx)
|
|
109
111
|
searchActorsTypeahead(server, ctx)
|
package/src/config.ts
CHANGED
|
@@ -24,6 +24,8 @@ export interface ServerConfigValues {
|
|
|
24
24
|
searchUrl?: string
|
|
25
25
|
suggestionsUrl?: string
|
|
26
26
|
suggestionsApiKey?: string
|
|
27
|
+
topicsUrl?: string
|
|
28
|
+
topicsApiKey?: string
|
|
27
29
|
cdnUrl?: string
|
|
28
30
|
videoPlaylistUrlPattern?: string
|
|
29
31
|
videoThumbnailUrlPattern?: string
|
|
@@ -47,6 +49,7 @@ export interface ServerConfigValues {
|
|
|
47
49
|
maxThreadDepth?: number
|
|
48
50
|
// client config
|
|
49
51
|
clientCheckEmailConfirmed?: boolean
|
|
52
|
+
topicsEnabled?: boolean
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
export class ServerConfig {
|
|
@@ -82,6 +85,8 @@ export class ServerConfig {
|
|
|
82
85
|
undefined
|
|
83
86
|
const suggestionsUrl = process.env.BSKY_SUGGESTIONS_URL || undefined
|
|
84
87
|
const suggestionsApiKey = process.env.BSKY_SUGGESTIONS_API_KEY || undefined
|
|
88
|
+
const topicsUrl = process.env.BSKY_TOPICS_URL || undefined
|
|
89
|
+
const topicsApiKey = process.env.BSKY_TOPICS_API_KEY
|
|
85
90
|
let dataplaneUrls = overrides?.dataplaneUrls
|
|
86
91
|
dataplaneUrls ??= process.env.BSKY_DATAPLANE_URLS
|
|
87
92
|
? process.env.BSKY_DATAPLANE_URLS.split(',')
|
|
@@ -130,6 +135,7 @@ export class ServerConfig {
|
|
|
130
135
|
: process.env.BSKY_STATSIG_ENV || 'development'
|
|
131
136
|
const clientCheckEmailConfirmed =
|
|
132
137
|
process.env.BSKY_CLIENT_CHECK_EMAIL_CONFIRMED === 'true'
|
|
138
|
+
const topicsEnabled = process.env.BSKY_TOPICS_ENABLED === 'true'
|
|
133
139
|
const indexedAtEpoch = process.env.BSKY_INDEXED_AT_EPOCH
|
|
134
140
|
? new Date(process.env.BSKY_INDEXED_AT_EPOCH)
|
|
135
141
|
: undefined
|
|
@@ -158,6 +164,8 @@ export class ServerConfig {
|
|
|
158
164
|
searchUrl,
|
|
159
165
|
suggestionsUrl,
|
|
160
166
|
suggestionsApiKey,
|
|
167
|
+
topicsUrl,
|
|
168
|
+
topicsApiKey,
|
|
161
169
|
didPlcUrl,
|
|
162
170
|
labelsFromIssuerDids,
|
|
163
171
|
handleResolveNameservers,
|
|
@@ -180,6 +188,7 @@ export class ServerConfig {
|
|
|
180
188
|
statsigKey,
|
|
181
189
|
statsigEnv,
|
|
182
190
|
clientCheckEmailConfirmed,
|
|
191
|
+
topicsEnabled,
|
|
183
192
|
indexedAtEpoch,
|
|
184
193
|
bigThreadUris,
|
|
185
194
|
bigThreadDepth,
|
|
@@ -285,6 +294,14 @@ export class ServerConfig {
|
|
|
285
294
|
return this.cfg.suggestionsApiKey
|
|
286
295
|
}
|
|
287
296
|
|
|
297
|
+
get topicsUrl() {
|
|
298
|
+
return this.cfg.topicsUrl
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
get topicsApiKey() {
|
|
302
|
+
return this.cfg.topicsApiKey
|
|
303
|
+
}
|
|
304
|
+
|
|
288
305
|
get cdnUrl() {
|
|
289
306
|
return this.cfg.cdnUrl
|
|
290
307
|
}
|
|
@@ -341,6 +358,10 @@ export class ServerConfig {
|
|
|
341
358
|
return this.cfg.clientCheckEmailConfirmed
|
|
342
359
|
}
|
|
343
360
|
|
|
361
|
+
get topicsEnabled() {
|
|
362
|
+
return this.cfg.topicsEnabled
|
|
363
|
+
}
|
|
364
|
+
|
|
344
365
|
get indexedAtEpoch() {
|
|
345
366
|
return this.cfg.indexedAtEpoch
|
|
346
367
|
}
|
package/src/context.ts
CHANGED
|
@@ -25,6 +25,7 @@ export class AppContext {
|
|
|
25
25
|
dataplane: DataPlaneClient
|
|
26
26
|
searchAgent: AtpAgent | undefined
|
|
27
27
|
suggestionsAgent: AtpAgent | undefined
|
|
28
|
+
topicsAgent: AtpAgent | undefined
|
|
28
29
|
hydrator: Hydrator
|
|
29
30
|
views: Views
|
|
30
31
|
signingKey: Keypair
|
|
@@ -52,6 +53,10 @@ export class AppContext {
|
|
|
52
53
|
return this.opts.suggestionsAgent
|
|
53
54
|
}
|
|
54
55
|
|
|
56
|
+
get topicsAgent(): AtpAgent | undefined {
|
|
57
|
+
return this.opts.topicsAgent
|
|
58
|
+
}
|
|
59
|
+
|
|
55
60
|
get hydrator(): Hydrator {
|
|
56
61
|
return this.opts.hydrator
|
|
57
62
|
}
|
package/src/hydration/actor.ts
CHANGED
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
HydrationMap,
|
|
6
6
|
RecordInfo,
|
|
7
7
|
parseRecord,
|
|
8
|
-
parseRecordBytes,
|
|
9
8
|
parseString,
|
|
10
9
|
safeTakedownRef,
|
|
11
10
|
} from './util'
|
|
@@ -116,18 +115,19 @@ export class ActorHydrator {
|
|
|
116
115
|
) {
|
|
117
116
|
return acc.set(did, null)
|
|
118
117
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
118
|
+
|
|
119
|
+
const profile = actor.profile
|
|
120
|
+
? parseRecord<ProfileRecord>(actor.profile, includeTakedowns)
|
|
121
|
+
: undefined
|
|
122
|
+
|
|
123
123
|
return acc.set(did, {
|
|
124
124
|
did,
|
|
125
125
|
handle: parseString(actor.handle),
|
|
126
|
-
profile:
|
|
126
|
+
profile: profile?.record,
|
|
127
127
|
profileCid: profile?.cid,
|
|
128
|
-
profileTakedownRef:
|
|
129
|
-
sortedAt: profile?.sortedAt
|
|
130
|
-
indexedAt: profile?.indexedAt
|
|
128
|
+
profileTakedownRef: profile?.takedownRef,
|
|
129
|
+
sortedAt: profile?.sortedAt,
|
|
130
|
+
indexedAt: profile?.indexedAt,
|
|
131
131
|
takedownRef: safeTakedownRef(actor),
|
|
132
132
|
isLabeler: actor.labeler ?? false,
|
|
133
133
|
allowIncomingChatsFrom: actor.allowIncomingChatsFrom || undefined,
|
package/src/index.ts
CHANGED
|
@@ -96,6 +96,16 @@ export class BskyAppView {
|
|
|
96
96
|
)
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
const topicsAgent = config.topicsUrl
|
|
100
|
+
? new AtpAgent({ service: config.topicsUrl })
|
|
101
|
+
: undefined
|
|
102
|
+
if (topicsAgent && config.topicsApiKey) {
|
|
103
|
+
topicsAgent.api.setHeader(
|
|
104
|
+
'authorization',
|
|
105
|
+
`Bearer ${config.topicsApiKey}`,
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
|
|
99
109
|
const dataplane = createDataPlaneClient(config.dataplaneUrls, {
|
|
100
110
|
httpVersion: config.dataplaneHttpVersion,
|
|
101
111
|
rejectUnauthorized: !config.dataplaneIgnoreBadTls,
|
|
@@ -146,6 +156,7 @@ export class BskyAppView {
|
|
|
146
156
|
dataplane,
|
|
147
157
|
searchAgent,
|
|
148
158
|
suggestionsAgent,
|
|
159
|
+
topicsAgent,
|
|
149
160
|
hydrator,
|
|
150
161
|
views,
|
|
151
162
|
signingKey,
|
package/src/lexicon/index.ts
CHANGED
|
@@ -140,6 +140,7 @@ import * as AppBskyUnspeccedGetConfig from './types/app/bsky/unspecced/getConfig
|
|
|
140
140
|
import * as AppBskyUnspeccedGetPopularFeedGenerators from './types/app/bsky/unspecced/getPopularFeedGenerators'
|
|
141
141
|
import * as AppBskyUnspeccedGetSuggestionsSkeleton from './types/app/bsky/unspecced/getSuggestionsSkeleton'
|
|
142
142
|
import * as AppBskyUnspeccedGetTaggedSuggestions from './types/app/bsky/unspecced/getTaggedSuggestions'
|
|
143
|
+
import * as AppBskyUnspeccedGetTrendingTopics from './types/app/bsky/unspecced/getTrendingTopics'
|
|
143
144
|
import * as AppBskyUnspeccedSearchActorsSkeleton from './types/app/bsky/unspecced/searchActorsSkeleton'
|
|
144
145
|
import * as AppBskyUnspeccedSearchPostsSkeleton from './types/app/bsky/unspecced/searchPostsSkeleton'
|
|
145
146
|
import * as AppBskyUnspeccedSearchStarterPacksSkeleton from './types/app/bsky/unspecced/searchStarterPacksSkeleton'
|
|
@@ -1853,6 +1854,17 @@ export class AppBskyUnspeccedNS {
|
|
|
1853
1854
|
return this._server.xrpc.method(nsid, cfg)
|
|
1854
1855
|
}
|
|
1855
1856
|
|
|
1857
|
+
getTrendingTopics<AV extends AuthVerifier>(
|
|
1858
|
+
cfg: ConfigOf<
|
|
1859
|
+
AV,
|
|
1860
|
+
AppBskyUnspeccedGetTrendingTopics.Handler<ExtractAuth<AV>>,
|
|
1861
|
+
AppBskyUnspeccedGetTrendingTopics.HandlerReqCtx<ExtractAuth<AV>>
|
|
1862
|
+
>,
|
|
1863
|
+
) {
|
|
1864
|
+
const nsid = 'app.bsky.unspecced.getTrendingTopics' // @ts-ignore
|
|
1865
|
+
return this._server.xrpc.method(nsid, cfg)
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1856
1868
|
searchActorsSkeleton<AV extends AuthVerifier>(
|
|
1857
1869
|
cfg: ConfigOf<
|
|
1858
1870
|
AV,
|
package/src/lexicon/lexicons.ts
CHANGED
|
@@ -9257,6 +9257,24 @@ export const schemaDict = {
|
|
|
9257
9257
|
},
|
|
9258
9258
|
},
|
|
9259
9259
|
},
|
|
9260
|
+
trendingTopic: {
|
|
9261
|
+
type: 'object',
|
|
9262
|
+
required: ['topic', 'link'],
|
|
9263
|
+
properties: {
|
|
9264
|
+
topic: {
|
|
9265
|
+
type: 'string',
|
|
9266
|
+
},
|
|
9267
|
+
displayName: {
|
|
9268
|
+
type: 'string',
|
|
9269
|
+
},
|
|
9270
|
+
description: {
|
|
9271
|
+
type: 'string',
|
|
9272
|
+
},
|
|
9273
|
+
link: {
|
|
9274
|
+
type: 'string',
|
|
9275
|
+
},
|
|
9276
|
+
},
|
|
9277
|
+
},
|
|
9260
9278
|
},
|
|
9261
9279
|
},
|
|
9262
9280
|
AppBskyUnspeccedGetConfig: {
|
|
@@ -9437,6 +9455,56 @@ export const schemaDict = {
|
|
|
9437
9455
|
},
|
|
9438
9456
|
},
|
|
9439
9457
|
},
|
|
9458
|
+
AppBskyUnspeccedGetTrendingTopics: {
|
|
9459
|
+
lexicon: 1,
|
|
9460
|
+
id: 'app.bsky.unspecced.getTrendingTopics',
|
|
9461
|
+
defs: {
|
|
9462
|
+
main: {
|
|
9463
|
+
type: 'query',
|
|
9464
|
+
description: 'Get a list of trending topics',
|
|
9465
|
+
parameters: {
|
|
9466
|
+
type: 'params',
|
|
9467
|
+
properties: {
|
|
9468
|
+
viewer: {
|
|
9469
|
+
type: 'string',
|
|
9470
|
+
format: 'did',
|
|
9471
|
+
description:
|
|
9472
|
+
'DID of the account making the request (not included for public/unauthenticated queries). Used to boost followed accounts in ranking.',
|
|
9473
|
+
},
|
|
9474
|
+
limit: {
|
|
9475
|
+
type: 'integer',
|
|
9476
|
+
minimum: 1,
|
|
9477
|
+
maximum: 25,
|
|
9478
|
+
default: 10,
|
|
9479
|
+
},
|
|
9480
|
+
},
|
|
9481
|
+
},
|
|
9482
|
+
output: {
|
|
9483
|
+
encoding: 'application/json',
|
|
9484
|
+
schema: {
|
|
9485
|
+
type: 'object',
|
|
9486
|
+
required: ['topics', 'suggested'],
|
|
9487
|
+
properties: {
|
|
9488
|
+
topics: {
|
|
9489
|
+
type: 'array',
|
|
9490
|
+
items: {
|
|
9491
|
+
type: 'ref',
|
|
9492
|
+
ref: 'lex:app.bsky.unspecced.defs#trendingTopic',
|
|
9493
|
+
},
|
|
9494
|
+
},
|
|
9495
|
+
suggested: {
|
|
9496
|
+
type: 'array',
|
|
9497
|
+
items: {
|
|
9498
|
+
type: 'ref',
|
|
9499
|
+
ref: 'lex:app.bsky.unspecced.defs#trendingTopic',
|
|
9500
|
+
},
|
|
9501
|
+
},
|
|
9502
|
+
},
|
|
9503
|
+
},
|
|
9504
|
+
},
|
|
9505
|
+
},
|
|
9506
|
+
},
|
|
9507
|
+
},
|
|
9440
9508
|
AppBskyUnspeccedSearchActorsSkeleton: {
|
|
9441
9509
|
lexicon: 1,
|
|
9442
9510
|
id: 'app.bsky.unspecced.searchActorsSkeleton',
|
|
@@ -10920,6 +10988,7 @@ export const ids = {
|
|
|
10920
10988
|
'app.bsky.unspecced.getSuggestionsSkeleton',
|
|
10921
10989
|
AppBskyUnspeccedGetTaggedSuggestions:
|
|
10922
10990
|
'app.bsky.unspecced.getTaggedSuggestions',
|
|
10991
|
+
AppBskyUnspeccedGetTrendingTopics: 'app.bsky.unspecced.getTrendingTopics',
|
|
10923
10992
|
AppBskyUnspeccedSearchActorsSkeleton:
|
|
10924
10993
|
'app.bsky.unspecced.searchActorsSkeleton',
|
|
10925
10994
|
AppBskyUnspeccedSearchPostsSkeleton: 'app.bsky.unspecced.searchPostsSkeleton',
|
|
@@ -63,3 +63,23 @@ export function validateSkeletonSearchStarterPack(
|
|
|
63
63
|
v,
|
|
64
64
|
)
|
|
65
65
|
}
|
|
66
|
+
|
|
67
|
+
export interface TrendingTopic {
|
|
68
|
+
topic: string
|
|
69
|
+
displayName?: string
|
|
70
|
+
description?: string
|
|
71
|
+
link: string
|
|
72
|
+
[k: string]: unknown
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function isTrendingTopic(v: unknown): v is TrendingTopic {
|
|
76
|
+
return (
|
|
77
|
+
isObj(v) &&
|
|
78
|
+
hasProp(v, '$type') &&
|
|
79
|
+
v.$type === 'app.bsky.unspecced.defs#trendingTopic'
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function validateTrendingTopic(v: unknown): ValidationResult {
|
|
84
|
+
return lexicons.validate('app.bsky.unspecced.defs#trendingTopic', v)
|
|
85
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED CODE - DO NOT MODIFY
|
|
3
|
+
*/
|
|
4
|
+
import express from 'express'
|
|
5
|
+
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
|
6
|
+
import { lexicons } from '../../../../lexicons'
|
|
7
|
+
import { isObj, hasProp } from '../../../../util'
|
|
8
|
+
import { CID } from 'multiformats/cid'
|
|
9
|
+
import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
|
|
10
|
+
import * as AppBskyUnspeccedDefs from './defs'
|
|
11
|
+
|
|
12
|
+
export interface QueryParams {
|
|
13
|
+
/** DID of the account making the request (not included for public/unauthenticated queries). Used to boost followed accounts in ranking. */
|
|
14
|
+
viewer?: string
|
|
15
|
+
limit: number
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type InputSchema = undefined
|
|
19
|
+
|
|
20
|
+
export interface OutputSchema {
|
|
21
|
+
topics: AppBskyUnspeccedDefs.TrendingTopic[]
|
|
22
|
+
suggested: AppBskyUnspeccedDefs.TrendingTopic[]
|
|
23
|
+
[k: string]: unknown
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type HandlerInput = undefined
|
|
27
|
+
|
|
28
|
+
export interface HandlerSuccess {
|
|
29
|
+
encoding: 'application/json'
|
|
30
|
+
body: OutputSchema
|
|
31
|
+
headers?: { [key: string]: string }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface HandlerError {
|
|
35
|
+
status: number
|
|
36
|
+
message?: string
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough
|
|
40
|
+
export type HandlerReqCtx<HA extends HandlerAuth = never> = {
|
|
41
|
+
auth: HA
|
|
42
|
+
params: QueryParams
|
|
43
|
+
input: HandlerInput
|
|
44
|
+
req: express.Request
|
|
45
|
+
res: express.Response
|
|
46
|
+
}
|
|
47
|
+
export type Handler<HA extends HandlerAuth = never> = (
|
|
48
|
+
ctx: HandlerReqCtx<HA>,
|
|
49
|
+
) => Promise<HandlerOutput> | HandlerOutput
|