+12
__generated__/index.ts
+12
__generated__/index.ts
···
16
16
import * as SocialGrainFeedGetTimeline from './types/social/grain/feed/getTimeline.ts'
17
17
import * as SocialGrainActorGetProfile from './types/social/grain/actor/getProfile.ts'
18
18
import * as SocialGrainActorSearchActors from './types/social/grain/actor/searchActors.ts'
19
+
import * as SocialGrainActorGetActorFavs from './types/social/grain/actor/getActorFavs.ts'
19
20
20
21
export const APP_BSKY_GRAPH = {
21
22
DefsModlist: 'app.bsky.graph.defs#modlist',
···
327
328
>,
328
329
) {
329
330
const nsid = 'social.grain.actor.searchActors' // @ts-ignore
331
+
return this._server.xrpc.method(nsid, cfg)
332
+
}
333
+
334
+
getActorFavs<AV extends AuthVerifier>(
335
+
cfg: ConfigOf<
336
+
AV,
337
+
SocialGrainActorGetActorFavs.Handler<ExtractAuth<AV>>,
338
+
SocialGrainActorGetActorFavs.HandlerReqCtx<ExtractAuth<AV>>
339
+
>,
340
+
) {
341
+
const nsid = 'social.grain.actor.getActorFavs' // @ts-ignore
330
342
return this._server.xrpc.method(nsid, cfg)
331
343
}
332
344
}
+50
-8
__generated__/lexicons.ts
+50
-8
__generated__/lexicons.ts
···
2855
2855
},
2856
2856
},
2857
2857
},
2858
-
errors: [
2859
-
{
2860
-
name: 'BlockedActor',
2861
-
},
2862
-
{
2863
-
name: 'BlockedByActor',
2864
-
},
2865
-
],
2866
2858
},
2867
2859
},
2868
2860
},
···
3386
3378
},
3387
3379
},
3388
3380
},
3381
+
SocialGrainActorGetActorFavs: {
3382
+
lexicon: 1,
3383
+
id: 'social.grain.actor.getActorFavs',
3384
+
defs: {
3385
+
main: {
3386
+
type: 'query',
3387
+
description:
3388
+
"Get a view of an actor's favorite galleries. Does not require auth.",
3389
+
parameters: {
3390
+
type: 'params',
3391
+
required: ['actor'],
3392
+
properties: {
3393
+
actor: {
3394
+
type: 'string',
3395
+
format: 'at-identifier',
3396
+
},
3397
+
limit: {
3398
+
type: 'integer',
3399
+
minimum: 1,
3400
+
maximum: 100,
3401
+
default: 50,
3402
+
},
3403
+
cursor: {
3404
+
type: 'string',
3405
+
},
3406
+
},
3407
+
},
3408
+
output: {
3409
+
encoding: 'application/json',
3410
+
schema: {
3411
+
type: 'object',
3412
+
required: ['items'],
3413
+
properties: {
3414
+
cursor: {
3415
+
type: 'string',
3416
+
},
3417
+
items: {
3418
+
type: 'array',
3419
+
items: {
3420
+
type: 'ref',
3421
+
ref: 'lex:social.grain.gallery.defs#galleryView',
3422
+
},
3423
+
},
3424
+
},
3425
+
},
3426
+
},
3427
+
},
3428
+
},
3429
+
},
3389
3430
SocialGrainActorProfile: {
3390
3431
lexicon: 1,
3391
3432
id: 'social.grain.actor.profile',
···
3935
3976
SocialGrainActorDefs: 'social.grain.actor.defs',
3936
3977
SocialGrainActorGetProfile: 'social.grain.actor.getProfile',
3937
3978
SocialGrainActorSearchActors: 'social.grain.actor.searchActors',
3979
+
SocialGrainActorGetActorFavs: 'social.grain.actor.getActorFavs',
3938
3980
SocialGrainActorProfile: 'social.grain.actor.profile',
3939
3981
SocialGrainPhotoDefs: 'social.grain.photo.defs',
3940
3982
SocialGrainPhotoExif: 'social.grain.photo.exif',
+37
-14
src/api/mod.ts
+37
-14
src/api/mod.ts
···
1
1
import { ProfileView } from "$lexicon/types/social/grain/actor/defs.ts";
2
2
import {
3
+
OutputSchema as GetActorFavsOutputSchema,
4
+
QueryParams as GetActorFavsQueryParams,
5
+
} from "$lexicon/types/social/grain/actor/getActorFavs.ts";
6
+
import {
3
7
OutputSchema as GetProfileOutputSchema,
4
8
QueryParams as GetProfileQueryParams,
5
9
} from "$lexicon/types/social/grain/actor/getProfile.ts";
···
9
13
} from "$lexicon/types/social/grain/actor/searchActors.ts";
10
14
import {
11
15
OutputSchema as GetTimelineOutputSchema,
16
+
QueryParams as GetTimelineQueryParams,
12
17
} from "$lexicon/types/social/grain/feed/getTimeline.ts";
13
18
import {
14
19
OutputSchema as GetActorGalleriesOutputSchema,
···
29
34
import { BffMiddleware, route } from "@bigmoves/bff";
30
35
import {
31
36
getActorGalleries,
37
+
getActorGalleryFavs,
32
38
getActorProfileDetailed,
33
39
searchActors,
34
40
} from "../lib/actor.ts";
···
39
45
import { getGalleryComments } from "../modules/comments.tsx";
40
46
41
47
export const middlewares: BffMiddleware[] = [
42
-
route("/oauth/session", (_req, _params, ctx) => {
48
+
route("/oauth/session", async (_req, _params, ctx) => {
43
49
if (!ctx.currentUser) {
44
50
return ctx.json("Unauthorized", 401);
45
51
}
···
62
68
const galleries = getActorGalleries(actor, ctx);
63
69
return ctx.json({ items: galleries } as GetActorGalleriesOutputSchema);
64
70
}),
71
+
route("/xrpc/social.grain.actor.getActorFavs", (req, _params, ctx) => {
72
+
const url = new URL(req.url);
73
+
const { actor } = getActorFavsQueryParams(url);
74
+
const galleries = getActorGalleryFavs(actor, ctx);
75
+
return ctx.json({ items: galleries } as GetActorFavsOutputSchema);
76
+
}),
65
77
route("/xrpc/social.grain.gallery.getGallery", (req, _params, ctx) => {
66
78
const url = new URL(req.url);
67
79
const { uri } = getGalleryQueryParams(url);
···
87
99
const comments = getGalleryComments(uri, ctx);
88
100
return ctx.json({ gallery, comments } as GetGalleryThreadOutputSchema);
89
101
}),
90
-
route("/xrpc/social.grain.feed.getTimeline", async (_req, _params, ctx) => {
91
-
// const url = new URL(req.url);
92
-
// const { algorithm, limit, cursor } = getTimelineQueryParams(url);
102
+
route("/xrpc/social.grain.feed.getTimeline", async (req, _params, ctx) => {
103
+
const url = new URL(req.url);
104
+
const { algorithm } = getTimelineQueryParams(url);
93
105
const items = await getTimeline(
94
106
ctx,
95
-
"timeline",
107
+
algorithm === "following" ? "following" : "timeline",
96
108
"grain",
97
109
);
98
110
return ctx.json(
···
150
162
return { actor, limit, cursor };
151
163
}
152
164
165
+
function getActorFavsQueryParams(url: URL): GetActorFavsQueryParams {
166
+
const actor = url.searchParams.get("actor");
167
+
if (!actor) throw new BadRequestError("Missing actor parameter");
168
+
const limit = parseInt(url.searchParams.get("limit") ?? "50", 10);
169
+
if (isNaN(limit) || limit <= 0) {
170
+
throw new BadRequestError("Invalid limit parameter");
171
+
}
172
+
const cursor = url.searchParams.get("cursor") ?? undefined;
173
+
return { actor, limit, cursor };
174
+
}
175
+
153
176
function getGalleryQueryParams(url: URL): GetGalleryQueryParams {
154
177
const uri = url.searchParams.get("uri");
155
178
if (!uri) throw new BadRequestError("Missing uri parameter");
···
182
205
// return { limit, cursor };
183
206
// }
184
207
185
-
// function getTimelineQueryParams(url: URL): GetTimelineQueryParams {
186
-
// const algorithm = url.searchParams.get("algorithm") ?? undefined;
187
-
// const limit = parseInt(url.searchParams.get("limit") ?? "50", 10);
188
-
// if (isNaN(limit) || limit <= 0) {
189
-
// throw new BadRequestError("Invalid limit parameter");
190
-
// }
191
-
// const cursor = url.searchParams.get("cursor") ?? undefined;
192
-
// return { algorithm, limit, cursor };
193
-
// }
208
+
function getTimelineQueryParams(url: URL): GetTimelineQueryParams {
209
+
const algorithm = url.searchParams.get("algorithm") ?? undefined;
210
+
const limit = parseInt(url.searchParams.get("limit") ?? "50", 10);
211
+
if (isNaN(limit) || limit <= 0) {
212
+
throw new BadRequestError("Invalid limit parameter");
213
+
}
214
+
const cursor = url.searchParams.get("cursor") ?? undefined;
215
+
return { algorithm, limit, cursor };
216
+
}