feat: Add following and followers endpoints

This commit is contained in:
Jesse Wierzbinski 2023-12-01 13:44:48 -10:00
parent d7398e1f5f
commit 45a8a2678e
No known key found for this signature in database
3 changed files with 180 additions and 121 deletions

View 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(", "),
}
);
};

View 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(", "),
}
);
};