mirror of
https://iceshrimp.dev/limepotato/jormungandr-bite.git
synced 2024-11-25 03:17:38 -07:00
[mastodon-client] Move link header pagination to middleware
This commit is contained in:
parent
3d320c0895
commit
081b836e92
11 changed files with 98 additions and 55 deletions
|
@ -81,7 +81,7 @@ export function setupEndpointsAccount(router: Router): void {
|
|||
const followers = await UserConverter.encodeMany(res.data, ctx.cache);
|
||||
|
||||
ctx.body = followers.map((account) => convertAccountId(account));
|
||||
PaginationHelpers.appendLinkPaginationHeader(args, ctx, res, 40);
|
||||
ctx.pagination = res.pagination;
|
||||
},
|
||||
);
|
||||
router.get<{ Params: { id: string } }>(
|
||||
|
@ -95,7 +95,7 @@ export function setupEndpointsAccount(router: Router): void {
|
|||
const following = await UserConverter.encodeMany(res.data, ctx.cache);
|
||||
|
||||
ctx.body = following.map((account) => convertAccountId(account));
|
||||
PaginationHelpers.appendLinkPaginationHeader(args, ctx, res, 40);
|
||||
ctx.pagination = res.pagination;
|
||||
},
|
||||
);
|
||||
router.get<{ Params: { id: string } }>(
|
||||
|
@ -181,7 +181,7 @@ export function setupEndpointsAccount(router: Router): void {
|
|||
const res = await UserHelpers.getUserBookmarks(ctx.user, args.max_id, args.since_id, args.min_id, args.limit);
|
||||
const bookmarks = await NoteConverter.encodeMany(res.data, ctx.user, ctx.cache);
|
||||
ctx.body = bookmarks.map(s => convertStatusIds(s));
|
||||
PaginationHelpers.appendLinkPaginationHeader(args, ctx, res, 20);
|
||||
ctx.pagination = res.pagination;
|
||||
}
|
||||
);
|
||||
router.get("/v1/favourites",
|
||||
|
@ -191,7 +191,7 @@ export function setupEndpointsAccount(router: Router): void {
|
|||
const res = await UserHelpers.getUserFavorites(ctx.user, args.max_id, args.since_id, args.min_id, args.limit);
|
||||
const favorites = await NoteConverter.encodeMany(res.data, ctx.user, ctx.cache);
|
||||
ctx.body = favorites.map(s => convertStatusIds(s));
|
||||
PaginationHelpers.appendLinkPaginationHeader(args, ctx, res, 20);
|
||||
ctx.pagination = res.pagination;
|
||||
}
|
||||
);
|
||||
router.get("/v1/mutes",
|
||||
|
@ -200,7 +200,7 @@ export function setupEndpointsAccount(router: Router): void {
|
|||
const args = normalizeUrlQuery(convertPaginationArgsIds(limitToInt(ctx.query as any)));
|
||||
const res = await UserHelpers.getUserMutes(ctx.user, args.max_id, args.since_id, args.min_id, args.limit, ctx.cache);
|
||||
ctx.body = res.data.map(m => convertAccountId(m));
|
||||
PaginationHelpers.appendLinkPaginationHeader(args, ctx, res, 40);
|
||||
ctx.pagination = res.pagination;
|
||||
}
|
||||
);
|
||||
router.get("/v1/blocks",
|
||||
|
@ -210,7 +210,7 @@ export function setupEndpointsAccount(router: Router): void {
|
|||
const res = await UserHelpers.getUserBlocks(ctx.user, args.max_id, args.since_id, args.min_id, args.limit);
|
||||
const blocks = await UserConverter.encodeMany(res.data, ctx.cache);
|
||||
ctx.body = blocks.map(b => convertAccountId(b));
|
||||
PaginationHelpers.appendLinkPaginationHeader(args, ctx, res, 40);
|
||||
ctx.pagination = res.pagination;
|
||||
}
|
||||
);
|
||||
router.get("/v1/follow_requests",
|
||||
|
@ -220,7 +220,7 @@ export function setupEndpointsAccount(router: Router): void {
|
|||
const res = await UserHelpers.getUserFollowRequests(ctx.user, args.max_id, args.since_id, args.min_id, args.limit);
|
||||
const requests = await UserConverter.encodeMany(res.data, ctx.cache);
|
||||
ctx.body = requests.map(b => convertAccountId(b));
|
||||
PaginationHelpers.appendLinkPaginationHeader(args, ctx, res, 40);
|
||||
ctx.pagination = res.pagination;
|
||||
}
|
||||
);
|
||||
router.post<{ Params: { id: string } }>(
|
||||
|
|
|
@ -75,7 +75,7 @@ export function setupEndpointsList(router: Router): void {
|
|||
const accounts = await UserConverter.encodeMany(res.data);
|
||||
|
||||
ctx.body = accounts.map(account => convertAccountId(account));
|
||||
PaginationHelpers.appendLinkPaginationHeader(args, ctx, res, 40);
|
||||
ctx.pagination = res.pagination;
|
||||
},
|
||||
);
|
||||
router.post<{ Params: { id: string } }>(
|
||||
|
|
|
@ -118,7 +118,7 @@ export function setupEndpointsStatus(router: Router): void {
|
|||
const res = await NoteHelpers.getNoteRebloggedBy(note, ctx.user, args.max_id, args.since_id, args.min_id, args.limit);
|
||||
const users = await UserConverter.encodeMany(res.data, ctx.cache);
|
||||
ctx.body = users.map(m => convertAccountId(m));
|
||||
PaginationHelpers.appendLinkPaginationHeader(args, ctx, res, 40);
|
||||
ctx.pagination = res.pagination;
|
||||
}
|
||||
);
|
||||
router.get<{ Params: { id: string } }>(
|
||||
|
@ -131,7 +131,7 @@ export function setupEndpointsStatus(router: Router): void {
|
|||
const res = await NoteHelpers.getNoteFavoritedBy(note, args.max_id, args.since_id, args.min_id, args.limit);
|
||||
const users = await UserConverter.encodeMany(res.data, ctx.cache);
|
||||
ctx.body = users.map(m => convertAccountId(m));
|
||||
PaginationHelpers.appendLinkPaginationHeader(args, ctx, res, 40);
|
||||
ctx.pagination = res.pagination;
|
||||
}
|
||||
);
|
||||
router.post<{ Params: { id: string } }>(
|
||||
|
|
|
@ -121,7 +121,7 @@ export function setupEndpointsTimeline(router: Router): void {
|
|||
const res = await TimelineHelpers.getConversations(ctx.user, args.max_id, args.since_id, args.min_id, args.limit);
|
||||
|
||||
ctx.body = res.data.map(c => convertConversationIds(c));
|
||||
PaginationHelpers.appendLinkPaginationHeader(args, ctx, res, 20);
|
||||
ctx.pagination = res.pagination;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { ILocalUser, User } from "@/models/entities/user.js";
|
||||
import { Blockings, UserListJoinings, UserLists, Users } from "@/models/index.js";
|
||||
import { LinkPaginationObject } from "@/server/api/mastodon/helpers/user.js";
|
||||
import { LinkPaginationObject } from "@/server/api/mastodon/middleware/pagination.js";
|
||||
import { PaginationHelpers } from "@/server/api/mastodon/helpers/pagination.js";
|
||||
import { UserList } from "@/models/entities/user-list.js";
|
||||
import { pushUserToUserList } from "@/services/user-list/push.js";
|
||||
|
@ -54,8 +54,11 @@ export class ListHelpers {
|
|||
|
||||
return {
|
||||
data: users,
|
||||
pagination: {
|
||||
limit: limit,
|
||||
maxId: p.map(p => p.id).at(-1),
|
||||
minId: p.map(p => p.id)[0],
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -14,7 +14,8 @@ import deleteNote from "@/services/note/delete.js";
|
|||
import { genId } from "@/misc/gen-id.js";
|
||||
import { PaginationHelpers } from "@/server/api/mastodon/helpers/pagination.js";
|
||||
import { UserConverter } from "@/server/api/mastodon/converters/user.js";
|
||||
import { LinkPaginationObject, UserHelpers } from "@/server/api/mastodon/helpers/user.js";
|
||||
import { UserHelpers } from "@/server/api/mastodon/helpers/user.js";
|
||||
import { LinkPaginationObject } from "@/server/api/mastodon/middleware/pagination.js"
|
||||
import { addPinned, removePinned } from "@/services/i/pin.js";
|
||||
import { NoteConverter } from "@/server/api/mastodon/converters/note.js";
|
||||
import { convertId, IdType } from "@/misc/convert-id.js";
|
||||
|
@ -158,8 +159,11 @@ export class NoteHelpers {
|
|||
|
||||
return {
|
||||
data: users,
|
||||
pagination: {
|
||||
limit: limit,
|
||||
maxId: p.map(p => p.id).at(-1),
|
||||
minId: p.map(p => p.id)[0],
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -45,20 +45,4 @@ export class PaginationHelpers {
|
|||
public static async execQuery<T extends ObjectLiteral>(query: SelectQueryBuilder<T>, limit: number, reverse: boolean): Promise<T[]> {
|
||||
return query.take(limit).getMany().then(found => reverse ? found.reverse() : found);
|
||||
}
|
||||
|
||||
public static appendLinkPaginationHeader(args: any, ctx: any, res: any, defaultLimit: number): void {
|
||||
const link: string[] = [];
|
||||
const limit = args.limit ?? defaultLimit;
|
||||
if (res.maxId) {
|
||||
const l = `<${config.url}/api${ctx.path}?limit=${limit}&max_id=${convertId(res.maxId, IdType.MastodonId)}>; rel="next"`;
|
||||
link.push(l);
|
||||
}
|
||||
if (res.minId) {
|
||||
const l = `<${config.url}/api${ctx.path}?limit=${limit}&min_id=${convertId(res.minId, IdType.MastodonId)}>; rel="prev"`;
|
||||
link.push(l);
|
||||
}
|
||||
if (link.length > 0) {
|
||||
ctx.response.append('Link', link.join(', '));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,12 +12,13 @@ import { generateMutedUserRenotesQueryForNotes } from "@/server/api/common/gener
|
|||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { PaginationHelpers } from "@/server/api/mastodon/helpers/pagination.js";
|
||||
import { UserList } from "@/models/entities/user-list.js";
|
||||
import { LinkPaginationObject, UserHelpers } from "@/server/api/mastodon/helpers/user.js";
|
||||
import { UserHelpers } from "@/server/api/mastodon/helpers/user.js";
|
||||
import { UserConverter } from "@/server/api/mastodon/converters/user.js";
|
||||
import { NoteConverter } from "@/server/api/mastodon/converters/note.js";
|
||||
import { awaitAll } from "@/prelude/await-all.js";
|
||||
import { unique } from "@/prelude/array.js";
|
||||
import { MastoApiError } from "@/server/api/mastodon/middleware/catch-errors.js";
|
||||
import { LinkPaginationObject } from "@/server/api/mastodon/middleware/pagination.js";
|
||||
|
||||
export class TimelineHelpers {
|
||||
public static async getHomeTimeline(user: ILocalUser, maxId: string | undefined, sinceId: string | undefined, minId: string | undefined, limit: number = 20): Promise<Note[]> {
|
||||
|
@ -212,8 +213,11 @@ export class TimelineHelpers {
|
|||
});
|
||||
const res = {
|
||||
data: Promise.all(conversations.map(c => awaitAll(c))),
|
||||
pagination: {
|
||||
limit: limit,
|
||||
maxId: p.map(p => p.threadId ?? p.id).at(-1),
|
||||
minId: p.map(p => p.threadId ?? p.id)[0],
|
||||
}
|
||||
};
|
||||
|
||||
return awaitAll(res);
|
||||
|
|
|
@ -40,6 +40,7 @@ import { MediaHelpers } from "@/server/api/mastodon/helpers/media.js";
|
|||
import { UserProfile } from "@/models/entities/user-profile.js";
|
||||
import { verifyLink } from "@/services/fetch-rel-me.js";
|
||||
import { MastoApiError } from "@/server/api/mastodon/middleware/catch-errors.js";
|
||||
import { LinkPaginationObject } from "@/server/api/mastodon/middleware/pagination.js";
|
||||
|
||||
export type AccountCache = {
|
||||
locks: AsyncLock;
|
||||
|
@ -47,12 +48,6 @@ export type AccountCache = {
|
|||
users: User[];
|
||||
};
|
||||
|
||||
export type LinkPaginationObject<T> = {
|
||||
data: T;
|
||||
maxId?: string | undefined;
|
||||
minId?: string | undefined;
|
||||
}
|
||||
|
||||
export type updateCredsData = {
|
||||
display_name: string;
|
||||
note: string;
|
||||
|
@ -259,8 +254,11 @@ export class UserHelpers {
|
|||
|
||||
return {
|
||||
data: result,
|
||||
pagination: {
|
||||
limit: limit,
|
||||
maxId: p.map(p => p.id).at(-1),
|
||||
minId: p.map(p => p.id)[0],
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -286,8 +284,11 @@ export class UserHelpers {
|
|||
|
||||
return {
|
||||
data: users,
|
||||
pagination: {
|
||||
limit: limit,
|
||||
maxId: p.map(p => p.id).at(-1),
|
||||
minId: p.map(p => p.id)[0],
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -313,8 +314,11 @@ export class UserHelpers {
|
|||
|
||||
return {
|
||||
data: users,
|
||||
pagination: {
|
||||
limit: limit,
|
||||
maxId: p.map(p => p.id).at(-1),
|
||||
minId: p.map(p => p.id)[0],
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -398,8 +402,11 @@ export class UserHelpers {
|
|||
.then(res => {
|
||||
return {
|
||||
data: res.map(p => p.note as Note),
|
||||
pagination: {
|
||||
limit: limit,
|
||||
maxId: res.map(p => p.id).at(-1),
|
||||
minId: res.map(p => p.id)[0],
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -422,8 +429,11 @@ export class UserHelpers {
|
|||
.then(res => {
|
||||
return {
|
||||
data: res.map(p => p.note as Note),
|
||||
pagination: {
|
||||
limit: limit,
|
||||
maxId: res.map(p => p.id).at(-1),
|
||||
minId: res.map(p => p.id)[0],
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -467,8 +477,11 @@ export class UserHelpers {
|
|||
|
||||
return {
|
||||
data: p.map(p => type === "followers" ? p.follower : p.followee).filter(p => p) as User[],
|
||||
pagination: {
|
||||
limit: limit,
|
||||
maxId: p.map(p => p.id).at(-1),
|
||||
minId: p.map(p => p.id)[0],
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import { apiLogger } from "@/server/api/logger.js";
|
|||
import { CacheMiddleware } from "@/server/api/mastodon/middleware/cache.js";
|
||||
import { KoaBodyMiddleware } from "@/server/api/mastodon/middleware/koa-body.js";
|
||||
import { NormalizeQueryMiddleware } from "@/server/api/mastodon/middleware/normalize-query.js";
|
||||
import { PaginationMiddleware } from "@/server/api/mastodon/middleware/pagination.js";
|
||||
|
||||
export const logger = apiLogger.createSubLogger("mastodon");
|
||||
export type MastoContext = RouterContext & DefaultContext;
|
||||
|
@ -36,8 +37,9 @@ export function setupMastodonApi(router: Router): void {
|
|||
|
||||
function setupMiddleware(router: Router): void {
|
||||
router.use(KoaBodyMiddleware());
|
||||
router.use(CatchErrorsMiddleware);
|
||||
router.use(NormalizeQueryMiddleware);
|
||||
router.use(PaginationMiddleware);
|
||||
router.use(AuthMiddleware);
|
||||
router.use(CacheMiddleware);
|
||||
router.use(CatchErrorsMiddleware);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
import { MastoContext } from "@/server/api/mastodon/index.js";
|
||||
import config from "@/config/index.js";
|
||||
import { convertId, IdType } from "@/misc/convert-id.js";
|
||||
|
||||
type PaginationData = {
|
||||
limit: number;
|
||||
maxId?: string | undefined;
|
||||
minId?: string | undefined;
|
||||
}
|
||||
|
||||
export type LinkPaginationObject<T> = {
|
||||
data: T;
|
||||
pagination?: PaginationData;
|
||||
}
|
||||
|
||||
export async function PaginationMiddleware(ctx: MastoContext, next: () => Promise<any>) {
|
||||
await next();
|
||||
if (!ctx.pagination) return;
|
||||
|
||||
const link: string[] = [];
|
||||
const limit = ctx.pagination.limit;
|
||||
if (ctx.pagination.maxId) {
|
||||
const l = `<${config.url}/api${ctx.path}?limit=${limit}&max_id=${convertId(ctx.pagination.maxId, IdType.MastodonId)}>; rel="next"`;
|
||||
link.push(l);
|
||||
}
|
||||
if (ctx.pagination.minId) {
|
||||
const l = `<${config.url}/api${ctx.path}?limit=${limit}&min_id=${convertId(ctx.pagination.maxId, IdType.MastodonId)}>; rel="prev"`;
|
||||
link.push(l);
|
||||
}
|
||||
if (link.length > 0) {
|
||||
ctx.response.append('Link', link.join(', '));
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue