mirror of
https://github.com/versia-pub/server.git
synced 2026-03-13 13:59:16 +01:00
feat: Add following and followers endpoints
This commit is contained in:
parent
d7398e1f5f
commit
45a8a2678e
3 changed files with 180 additions and 121 deletions
89
server/api/api/v1/accounts/[id]/followers.ts
Normal file
89
server/api/api/v1/accounts/[id]/followers.ts
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
import { errorResponse, jsonResponse } from "@response";
|
||||
import type { MatchedRoute } from "bun";
|
||||
import { userRelations, userToAPI } from "~database/entities/User";
|
||||
import { applyConfig } from "@api";
|
||||
import { client } from "~database/datasource";
|
||||
|
||||
export const meta = applyConfig({
|
||||
allowedMethods: ["GET"],
|
||||
ratelimits: {
|
||||
max: 60,
|
||||
duration: 60,
|
||||
},
|
||||
route: "/accounts/:id/followers",
|
||||
auth: {
|
||||
required: false,
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Fetch all statuses for a user
|
||||
*/
|
||||
export default async (
|
||||
req: Request,
|
||||
matchedRoute: MatchedRoute
|
||||
): Promise<Response> => {
|
||||
const id = matchedRoute.params.id;
|
||||
|
||||
// TODO: Add pinned
|
||||
const {
|
||||
max_id,
|
||||
min_id,
|
||||
since_id,
|
||||
limit = 20,
|
||||
}: {
|
||||
max_id?: string;
|
||||
since_id?: string;
|
||||
min_id?: string;
|
||||
limit?: number;
|
||||
} = matchedRoute.query;
|
||||
|
||||
const user = await client.user.findUnique({
|
||||
where: { id },
|
||||
include: userRelations,
|
||||
});
|
||||
|
||||
if (limit < 1 || limit > 40) return errorResponse("Invalid limit", 400);
|
||||
|
||||
if (!user) return errorResponse("User not found", 404);
|
||||
|
||||
const objects = await client.user.findMany({
|
||||
where: {
|
||||
relationships: {
|
||||
some: {
|
||||
subjectId: user.id,
|
||||
following: true,
|
||||
},
|
||||
},
|
||||
id: {
|
||||
lt: max_id,
|
||||
gt: min_id,
|
||||
gte: since_id,
|
||||
},
|
||||
},
|
||||
include: userRelations,
|
||||
take: Number(limit),
|
||||
orderBy: {
|
||||
id: "desc",
|
||||
},
|
||||
});
|
||||
|
||||
// Constuct HTTP Link header (next and prev)
|
||||
const linkHeader = [];
|
||||
if (objects.length > 0) {
|
||||
const urlWithoutQuery = req.url.split("?")[0];
|
||||
linkHeader.push(
|
||||
`<${urlWithoutQuery}?max_id=${objects.at(-1)?.id}>; rel="next"`,
|
||||
`<${urlWithoutQuery}?min_id=${objects[0].id}>; rel="prev"`
|
||||
);
|
||||
}
|
||||
|
||||
return jsonResponse(
|
||||
await Promise.all(objects.map(object => userToAPI(object))),
|
||||
200,
|
||||
{
|
||||
Link: linkHeader.join(", "),
|
||||
}
|
||||
);
|
||||
};
|
||||
89
server/api/api/v1/accounts/[id]/following.ts
Normal file
89
server/api/api/v1/accounts/[id]/following.ts
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
import { errorResponse, jsonResponse } from "@response";
|
||||
import type { MatchedRoute } from "bun";
|
||||
import { userRelations, userToAPI } from "~database/entities/User";
|
||||
import { applyConfig } from "@api";
|
||||
import { client } from "~database/datasource";
|
||||
|
||||
export const meta = applyConfig({
|
||||
allowedMethods: ["GET"],
|
||||
ratelimits: {
|
||||
max: 60,
|
||||
duration: 60,
|
||||
},
|
||||
route: "/accounts/:id/following",
|
||||
auth: {
|
||||
required: false,
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Fetch all statuses for a user
|
||||
*/
|
||||
export default async (
|
||||
req: Request,
|
||||
matchedRoute: MatchedRoute
|
||||
): Promise<Response> => {
|
||||
const id = matchedRoute.params.id;
|
||||
|
||||
// TODO: Add pinned
|
||||
const {
|
||||
max_id,
|
||||
min_id,
|
||||
since_id,
|
||||
limit = 20,
|
||||
}: {
|
||||
max_id?: string;
|
||||
since_id?: string;
|
||||
min_id?: string;
|
||||
limit?: number;
|
||||
} = matchedRoute.query;
|
||||
|
||||
const user = await client.user.findUnique({
|
||||
where: { id },
|
||||
include: userRelations,
|
||||
});
|
||||
|
||||
if (limit < 1 || limit > 40) return errorResponse("Invalid limit", 400);
|
||||
|
||||
if (!user) return errorResponse("User not found", 404);
|
||||
|
||||
const objects = await client.user.findMany({
|
||||
where: {
|
||||
relationshipSubjects: {
|
||||
some: {
|
||||
ownerId: user.id,
|
||||
following: true,
|
||||
},
|
||||
},
|
||||
id: {
|
||||
lt: max_id,
|
||||
gt: min_id,
|
||||
gte: since_id,
|
||||
},
|
||||
},
|
||||
include: userRelations,
|
||||
take: Number(limit),
|
||||
orderBy: {
|
||||
id: "desc",
|
||||
},
|
||||
});
|
||||
|
||||
// Constuct HTTP Link header (next and prev)
|
||||
const linkHeader = [];
|
||||
if (objects.length > 0) {
|
||||
const urlWithoutQuery = req.url.split("?")[0];
|
||||
linkHeader.push(
|
||||
`<${urlWithoutQuery}?max_id=${objects.at(-1)?.id}>; rel="next"`,
|
||||
`<${urlWithoutQuery}?min_id=${objects[0].id}>; rel="prev"`
|
||||
);
|
||||
}
|
||||
|
||||
return jsonResponse(
|
||||
await Promise.all(objects.map(object => userToAPI(object))),
|
||||
200,
|
||||
{
|
||||
Link: linkHeader.join(", "),
|
||||
}
|
||||
);
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue