mirror of
https://github.com/versia-pub/server.git
synced 2026-03-13 22:09:16 +01:00
Refactors, bugfixing
This commit is contained in:
parent
5812618170
commit
e26d604a54
42 changed files with 370 additions and 376 deletions
|
|
@ -19,7 +19,10 @@ export default apiRoute(async (req, matchedRoute, extraData) => {
|
|||
return xmlResponse(`
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
|
||||
<Link rel="lrdd" template="${config.http.base_url}/.well-known/webfinger?resource={uri}"/>
|
||||
<Link rel="lrdd" template="${new URL(
|
||||
"/.well-known/webfinger",
|
||||
config.http.base_url,
|
||||
).toString()}?resource={uri}"/>
|
||||
</XRD>
|
||||
`);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { apiRoute, applyConfig } from "@api";
|
||||
import { redirect } from "@response";
|
||||
|
||||
export const meta = applyConfig({
|
||||
allowedMethods: ["GET"],
|
||||
|
|
@ -15,10 +16,8 @@ export const meta = applyConfig({
|
|||
export default apiRoute(async (req, matchedRoute, extraData) => {
|
||||
const config = await extraData.configManager.getConfig();
|
||||
|
||||
return new Response("", {
|
||||
status: 301,
|
||||
headers: {
|
||||
Location: `${config.http.base_url}/.well-known/nodeinfo/2.0`,
|
||||
},
|
||||
});
|
||||
return redirect(
|
||||
new URL("/.well-known/nodeinfo/2.0", config.http.base_url),
|
||||
301,
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -41,18 +41,11 @@ export default apiRoute(async (req, matchedRoute, extraData) => {
|
|||
links: [
|
||||
{
|
||||
rel: "self",
|
||||
type: "application/activity+json",
|
||||
href: `${config.http.base_url}/users/${user.username}/actor`,
|
||||
},
|
||||
{
|
||||
rel: "https://webfinger.net/rel/profile-page",
|
||||
type: "text/html",
|
||||
href: `${config.http.base_url}/users/${user.username}`,
|
||||
},
|
||||
{
|
||||
rel: "self",
|
||||
type: 'application/activity+json; profile="https://www.w3.org/ns/activitystreams"',
|
||||
href: `${config.http.base_url}/users/${user.username}/actor`,
|
||||
type: "application/json",
|
||||
href: new URL(
|
||||
`/users/${user.id}`,
|
||||
config.http.base_url,
|
||||
).toString(),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { apiRoute, applyConfig } from "@api";
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
import { errorResponse, jsonResponse } from "@response";
|
||||
import { client } from "~database/datasource";
|
||||
import { userToAPI } from "~database/entities/User";
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { apiRoute, applyConfig } from "@api";
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
import { errorResponse, jsonResponse } from "@response";
|
||||
import { client } from "~database/datasource";
|
||||
import { userToAPI } from "~database/entities/User";
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ export default apiRoute<{
|
|||
|
||||
if (!self) return errorResponse("Unauthorized", 401);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { notifications, duration } = extraData.parsedRequest;
|
||||
|
||||
const user = await client.user.findUnique({
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
import { apiRoute, applyConfig } from "@api";
|
||||
import type { Prisma, Status, User } from "@prisma/client";
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
import { errorResponse, jsonResponse } from "@response";
|
||||
import { fetchTimeline } from "@timelines";
|
||||
import { client } from "~database/datasource";
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { apiRoute, applyConfig } from "@api";
|
||||
import { jsonResponse } from "@response";
|
||||
import { jsonResponse, response } from "@response";
|
||||
import { tempmailDomains } from "@tempmail";
|
||||
import ISO6391 from "iso-639-1";
|
||||
import { client } from "~database/datasource";
|
||||
|
|
@ -200,7 +200,5 @@ export default apiRoute<{
|
|||
email: body.email ?? "",
|
||||
});
|
||||
|
||||
return new Response("", {
|
||||
status: 200,
|
||||
});
|
||||
return response(null, 200);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { apiRoute, applyConfig } from "@api";
|
||||
import { errorResponse, jsonResponse } from "@response";
|
||||
import { fetchTimeline } from "@timelines";
|
||||
import { client } from "~database/datasource";
|
||||
import { userToAPI } from "~database/entities/User";
|
||||
import { userToAPI, type UserWithRelations } from "~database/entities/User";
|
||||
import { userRelations } from "~database/entities/relations";
|
||||
|
||||
export const meta = applyConfig({
|
||||
|
|
@ -13,25 +14,48 @@ export const meta = applyConfig({
|
|||
},
|
||||
auth: {
|
||||
required: true,
|
||||
oauthPermissions: ["read:blocks"],
|
||||
},
|
||||
});
|
||||
|
||||
export default apiRoute(async (req, matchedRoute, extraData) => {
|
||||
export default apiRoute<{
|
||||
max_id?: string;
|
||||
since_id?: string;
|
||||
min_id?: string;
|
||||
limit?: number;
|
||||
}>(async (req, matchedRoute, extraData) => {
|
||||
const { user } = extraData.auth;
|
||||
|
||||
if (!user) return errorResponse("Unauthorized", 401);
|
||||
|
||||
const blocks = await client.user.findMany({
|
||||
where: {
|
||||
relationshipSubjects: {
|
||||
some: {
|
||||
ownerId: user.id,
|
||||
blocking: true,
|
||||
const { max_id, since_id, limit = 40 } = extraData.parsedRequest;
|
||||
|
||||
const { objects: blocks, link } = await fetchTimeline<UserWithRelations>(
|
||||
client.user,
|
||||
{
|
||||
where: {
|
||||
relationshipSubjects: {
|
||||
some: {
|
||||
ownerId: user.id,
|
||||
blocking: true,
|
||||
},
|
||||
},
|
||||
id: {
|
||||
lt: max_id,
|
||||
gte: since_id,
|
||||
},
|
||||
},
|
||||
include: userRelations,
|
||||
take: Number(limit),
|
||||
},
|
||||
include: userRelations,
|
||||
});
|
||||
req,
|
||||
);
|
||||
|
||||
return jsonResponse(blocks.map((u) => userToAPI(u)));
|
||||
return jsonResponse(
|
||||
blocks.map((u) => userToAPI(u)),
|
||||
200,
|
||||
{
|
||||
Link: link,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
import { apiRoute, applyConfig } from "@api";
|
||||
import { errorResponse, jsonResponse } from "@response";
|
||||
import { fetchTimeline } from "@timelines";
|
||||
import { client } from "~database/datasource";
|
||||
import { statusToAPI } from "~database/entities/Status";
|
||||
import {
|
||||
statusToAPI,
|
||||
type StatusWithRelations,
|
||||
} from "~database/entities/Status";
|
||||
import { statusAndUserRelations } from "~database/entities/relations";
|
||||
|
||||
export const meta = applyConfig({
|
||||
|
|
@ -32,35 +36,29 @@ export default apiRoute<{
|
|||
|
||||
if (!user) return errorResponse("Unauthorized", 401);
|
||||
|
||||
const objects = await client.status.findMany({
|
||||
where: {
|
||||
id: {
|
||||
lt: max_id ?? undefined,
|
||||
gte: since_id ?? undefined,
|
||||
gt: min_id ?? undefined,
|
||||
},
|
||||
likes: {
|
||||
some: {
|
||||
likerId: user.id,
|
||||
const { objects, link } = await fetchTimeline<StatusWithRelations>(
|
||||
client.status,
|
||||
{
|
||||
where: {
|
||||
id: {
|
||||
lt: max_id ?? undefined,
|
||||
gte: since_id ?? undefined,
|
||||
gt: min_id ?? undefined,
|
||||
},
|
||||
likes: {
|
||||
some: {
|
||||
likerId: user.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
include: statusAndUserRelations,
|
||||
take: Number(limit),
|
||||
orderBy: {
|
||||
id: "desc",
|
||||
},
|
||||
},
|
||||
include: statusAndUserRelations,
|
||||
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"`,
|
||||
);
|
||||
}
|
||||
req,
|
||||
);
|
||||
|
||||
return jsonResponse(
|
||||
await Promise.all(
|
||||
|
|
@ -68,7 +66,7 @@ export default apiRoute<{
|
|||
),
|
||||
200,
|
||||
{
|
||||
Link: linkHeader.join(", "),
|
||||
Link: link,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { apiRoute, applyConfig } from "@api";
|
||||
import { errorResponse, jsonResponse } from "@response";
|
||||
import { fetchTimeline } from "@timelines";
|
||||
import { client } from "~database/datasource";
|
||||
import { userToAPI } from "~database/entities/User";
|
||||
import { userToAPI, type UserWithRelations } from "~database/entities/User";
|
||||
import { userRelations } from "~database/entities/relations";
|
||||
|
||||
export const meta = applyConfig({
|
||||
|
|
@ -32,42 +33,36 @@ export default apiRoute<{
|
|||
|
||||
if (!user) return errorResponse("Unauthorized", 401);
|
||||
|
||||
const objects = await client.user.findMany({
|
||||
where: {
|
||||
id: {
|
||||
lt: max_id ?? undefined,
|
||||
gte: since_id ?? undefined,
|
||||
gt: min_id ?? undefined,
|
||||
},
|
||||
relationships: {
|
||||
some: {
|
||||
subjectId: user.id,
|
||||
requested: true,
|
||||
const { objects, link } = await fetchTimeline<UserWithRelations>(
|
||||
client.user,
|
||||
{
|
||||
where: {
|
||||
id: {
|
||||
lt: max_id ?? undefined,
|
||||
gte: since_id ?? undefined,
|
||||
gt: min_id ?? undefined,
|
||||
},
|
||||
relationships: {
|
||||
some: {
|
||||
subjectId: user.id,
|
||||
requested: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
include: userRelations,
|
||||
take: Number(limit),
|
||||
orderBy: {
|
||||
id: "desc",
|
||||
},
|
||||
},
|
||||
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"`,
|
||||
);
|
||||
}
|
||||
req,
|
||||
);
|
||||
|
||||
return jsonResponse(
|
||||
objects.map((user) => userToAPI(user)),
|
||||
200,
|
||||
{
|
||||
Link: linkHeader.join(", "),
|
||||
Link: link,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { apiRoute, applyConfig } from "@api";
|
||||
import { errorResponse, jsonResponse } from "@response";
|
||||
import { errorResponse, jsonResponse, response } from "@response";
|
||||
import type { MediaBackend } from "media-manager";
|
||||
import { MediaBackendType } from "media-manager";
|
||||
import { client } from "~database/datasource";
|
||||
|
|
@ -52,9 +52,7 @@ export default apiRoute<{
|
|||
if (attachment.url) {
|
||||
return jsonResponse(attachmentToAPI(attachment));
|
||||
}
|
||||
return new Response(null, {
|
||||
status: 206,
|
||||
});
|
||||
return response(null, 206);
|
||||
}
|
||||
case "PUT": {
|
||||
const { description, thumbnail } = extraData.parsedRequest;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { apiRoute, applyConfig } from "@api";
|
||||
import { errorResponse, jsonResponse } from "@response";
|
||||
import { fetchTimeline } from "@timelines";
|
||||
import { client } from "~database/datasource";
|
||||
import { userToAPI } from "~database/entities/User";
|
||||
import { userToAPI, type UserWithRelations } from "~database/entities/User";
|
||||
import { userRelations } from "~database/entities/relations";
|
||||
|
||||
export const meta = applyConfig({
|
||||
|
|
@ -13,25 +14,40 @@ export const meta = applyConfig({
|
|||
},
|
||||
auth: {
|
||||
required: true,
|
||||
oauthPermissions: ["read:mutes"],
|
||||
},
|
||||
});
|
||||
|
||||
export default apiRoute(async (req, matchedRoute, extraData) => {
|
||||
export default apiRoute<{
|
||||
max_id?: string;
|
||||
since_id?: string;
|
||||
limit?: number;
|
||||
}>(async (req, matchedRoute, extraData) => {
|
||||
const { user } = extraData.auth;
|
||||
const { max_id, since_id, limit = 40 } = extraData.parsedRequest;
|
||||
|
||||
if (!user) return errorResponse("Unauthorized", 401);
|
||||
|
||||
const blocks = await client.user.findMany({
|
||||
where: {
|
||||
relationshipSubjects: {
|
||||
some: {
|
||||
ownerId: user.id,
|
||||
muting: true,
|
||||
const { objects: blocks, link } = await fetchTimeline<UserWithRelations>(
|
||||
client.user,
|
||||
{
|
||||
where: {
|
||||
relationshipSubjects: {
|
||||
some: {
|
||||
ownerId: user.id,
|
||||
muting: true,
|
||||
},
|
||||
},
|
||||
id: {
|
||||
lt: max_id,
|
||||
gte: since_id,
|
||||
},
|
||||
},
|
||||
include: userRelations,
|
||||
take: Number(limit),
|
||||
},
|
||||
include: userRelations,
|
||||
});
|
||||
req,
|
||||
);
|
||||
|
||||
return jsonResponse(blocks.map((u) => userToAPI(u)));
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import { apiRoute, applyConfig } from "@api";
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import { errorResponse, jsonResponse } from "@response";
|
||||
import { fetchTimeline } from "@timelines";
|
||||
import { client } from "~database/datasource";
|
||||
import { notificationToAPI } from "~database/entities/Notification";
|
||||
import {
|
||||
|
|
@ -50,53 +52,49 @@ export default apiRoute<{
|
|||
return errorResponse("Can't use both types and exclude_types", 400);
|
||||
}
|
||||
|
||||
const objects = await client.notification.findMany({
|
||||
where: {
|
||||
notifiedId: user.id,
|
||||
id: {
|
||||
lt: max_id,
|
||||
gt: min_id,
|
||||
gte: since_id,
|
||||
const { objects, link } = await fetchTimeline<
|
||||
Prisma.NotificationGetPayload<{
|
||||
include: {
|
||||
account: {
|
||||
include: typeof userRelations;
|
||||
};
|
||||
status: {
|
||||
include: typeof statusAndUserRelations;
|
||||
};
|
||||
};
|
||||
}>
|
||||
>(
|
||||
client.notification,
|
||||
{
|
||||
where: {
|
||||
id: {
|
||||
lt: max_id ?? undefined,
|
||||
gte: since_id ?? undefined,
|
||||
gt: min_id ?? undefined,
|
||||
},
|
||||
accountId: account_id,
|
||||
},
|
||||
type: {
|
||||
in: types,
|
||||
notIn: exclude_types,
|
||||
include: {
|
||||
account: {
|
||||
include: userRelations,
|
||||
},
|
||||
status: {
|
||||
include: statusAndUserRelations,
|
||||
},
|
||||
},
|
||||
accountId: account_id,
|
||||
orderBy: {
|
||||
id: "desc",
|
||||
},
|
||||
take: Number(limit),
|
||||
},
|
||||
include: {
|
||||
account: {
|
||||
include: userRelations,
|
||||
},
|
||||
status: {
|
||||
include: statusAndUserRelations,
|
||||
},
|
||||
},
|
||||
orderBy: {
|
||||
id: "desc",
|
||||
},
|
||||
take: Number(limit),
|
||||
});
|
||||
|
||||
// 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[0].id}&limit=${limit}>; rel="next"`,
|
||||
);
|
||||
linkHeader.push(
|
||||
`<${urlWithoutQuery}?since_id=${
|
||||
objects.at(-1)?.id
|
||||
}&limit=${limit}>; rel="prev"`,
|
||||
);
|
||||
}
|
||||
req,
|
||||
);
|
||||
|
||||
return jsonResponse(
|
||||
await Promise.all(objects.map((n) => notificationToAPI(n))),
|
||||
200,
|
||||
{
|
||||
Link: linkHeader.join(", "),
|
||||
Link: link,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
import { apiRoute, applyConfig } from "@api";
|
||||
import { errorResponse, jsonResponse } from "@response";
|
||||
import { client } from "~database/datasource";
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { apiRoute, applyConfig } from "@api";
|
||||
import { errorResponse, jsonResponse } from "@response";
|
||||
import { fetchTimeline } from "@timelines";
|
||||
import { client } from "~database/datasource";
|
||||
import { isViewableByUser } from "~database/entities/Status";
|
||||
import { userToAPI } from "~database/entities/User";
|
||||
import { userToAPI, type UserWithRelations } from "~database/entities/User";
|
||||
import {
|
||||
statusAndUserRelations,
|
||||
userRelations,
|
||||
|
|
@ -42,63 +43,48 @@ export default apiRoute<{
|
|||
if (!status || !isViewableByUser(status, user))
|
||||
return errorResponse("Record not found", 404);
|
||||
|
||||
const {
|
||||
max_id = null,
|
||||
min_id = null,
|
||||
since_id = null,
|
||||
limit = 40,
|
||||
} = extraData.parsedRequest;
|
||||
const { max_id, min_id, since_id, limit = 40 } = extraData.parsedRequest;
|
||||
|
||||
// Check for limit limits
|
||||
if (limit > 80) return errorResponse("Invalid limit (maximum is 80)", 400);
|
||||
if (limit < 1) return errorResponse("Invalid limit", 400);
|
||||
|
||||
const objects = await client.user.findMany({
|
||||
where: {
|
||||
likes: {
|
||||
some: {
|
||||
likedId: status.id,
|
||||
const { objects, link } = await fetchTimeline<UserWithRelations>(
|
||||
client.user,
|
||||
{
|
||||
where: {
|
||||
likes: {
|
||||
some: {
|
||||
likedId: status.id,
|
||||
},
|
||||
},
|
||||
id: {
|
||||
lt: max_id,
|
||||
gte: since_id,
|
||||
gt: min_id,
|
||||
},
|
||||
},
|
||||
id: {
|
||||
lt: max_id ?? undefined,
|
||||
gte: since_id ?? undefined,
|
||||
gt: min_id ?? undefined,
|
||||
},
|
||||
},
|
||||
include: {
|
||||
...userRelations,
|
||||
likes: {
|
||||
where: {
|
||||
likedId: status.id,
|
||||
include: {
|
||||
...userRelations,
|
||||
likes: {
|
||||
where: {
|
||||
likedId: status.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
take: Number(limit),
|
||||
orderBy: {
|
||||
id: "desc",
|
||||
},
|
||||
},
|
||||
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[0].id}&limit=${limit}>; rel="next"`,
|
||||
);
|
||||
linkHeader.push(
|
||||
`<${urlWithoutQuery}?since_id=${
|
||||
objects[objects.length - 1].id
|
||||
}&limit=${limit}>; rel="prev"`,
|
||||
);
|
||||
}
|
||||
req,
|
||||
);
|
||||
|
||||
return jsonResponse(
|
||||
objects.map((user) => userToAPI(user)),
|
||||
200,
|
||||
{
|
||||
Link: linkHeader.join(", "),
|
||||
Link: link,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
import { apiRoute, applyConfig } from "@api";
|
||||
import { errorResponse, jsonResponse } from "@response";
|
||||
import { client } from "~database/datasource";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
import { apiRoute, applyConfig } from "@api";
|
||||
import { errorResponse, jsonResponse } from "@response";
|
||||
import { client } from "~database/datasource";
|
||||
|
|
@ -58,7 +57,10 @@ export default apiRoute<{
|
|||
authorId: user.id,
|
||||
reblogId: status.id,
|
||||
isReblog: true,
|
||||
uri: `${config.http.base_url}/statuses/FAKE-${crypto.randomUUID()}`,
|
||||
uri: new URL(
|
||||
`/statuses/FAKE-${crypto.randomUUID()}`,
|
||||
config.http.base_url,
|
||||
).toString(),
|
||||
visibility,
|
||||
sensitive: false,
|
||||
},
|
||||
|
|
@ -68,7 +70,10 @@ export default apiRoute<{
|
|||
await client.status.update({
|
||||
where: { id: newReblog.id },
|
||||
data: {
|
||||
uri: `${config.http.base_url}/statuses/${newReblog.id}`,
|
||||
uri: new URL(
|
||||
`/statuses/${newReblog.id}`,
|
||||
config.http.base_url,
|
||||
).toString(),
|
||||
},
|
||||
include: statusAndUserRelations,
|
||||
});
|
||||
|
|
@ -89,7 +94,10 @@ export default apiRoute<{
|
|||
await statusToAPI(
|
||||
{
|
||||
...newReblog,
|
||||
uri: `${config.http.base_url}/statuses/${newReblog.id}`,
|
||||
uri: new URL(
|
||||
`/statuses/${newReblog.id}`,
|
||||
config.http.base_url,
|
||||
).toString(),
|
||||
},
|
||||
user,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { apiRoute, applyConfig } from "@api";
|
||||
import { errorResponse, jsonResponse } from "@response";
|
||||
import { fetchTimeline } from "@timelines";
|
||||
import { client } from "~database/datasource";
|
||||
import { isViewableByUser } from "~database/entities/Status";
|
||||
import { userToAPI } from "~database/entities/User";
|
||||
import { type UserWithRelations, userToAPI } from "~database/entities/User";
|
||||
import {
|
||||
statusAndUserRelations,
|
||||
userRelations,
|
||||
|
|
@ -53,53 +54,43 @@ export default apiRoute<{
|
|||
if (limit > 80) return errorResponse("Invalid limit (maximum is 80)", 400);
|
||||
if (limit < 1) return errorResponse("Invalid limit", 400);
|
||||
|
||||
const objects = await client.user.findMany({
|
||||
where: {
|
||||
statuses: {
|
||||
some: {
|
||||
reblogId: status.id,
|
||||
const { objects, link } = await fetchTimeline<UserWithRelations>(
|
||||
client.user,
|
||||
{
|
||||
where: {
|
||||
statuses: {
|
||||
some: {
|
||||
reblogId: status.id,
|
||||
},
|
||||
},
|
||||
id: {
|
||||
lt: max_id ?? undefined,
|
||||
gte: since_id ?? undefined,
|
||||
gt: min_id ?? undefined,
|
||||
},
|
||||
},
|
||||
id: {
|
||||
lt: max_id ?? undefined,
|
||||
gte: since_id ?? undefined,
|
||||
gt: min_id ?? undefined,
|
||||
},
|
||||
},
|
||||
include: {
|
||||
...userRelations,
|
||||
statuses: {
|
||||
where: {
|
||||
reblogId: status.id,
|
||||
include: {
|
||||
...userRelations,
|
||||
statuses: {
|
||||
where: {
|
||||
reblogId: status.id,
|
||||
},
|
||||
include: statusAndUserRelations,
|
||||
},
|
||||
include: statusAndUserRelations,
|
||||
},
|
||||
take: Number(limit),
|
||||
orderBy: {
|
||||
id: "desc",
|
||||
},
|
||||
},
|
||||
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[0].id}&limit=${limit}>; rel="next"`,
|
||||
);
|
||||
linkHeader.push(
|
||||
`<${urlWithoutQuery}?since_id=${
|
||||
objects[objects.length - 1].id
|
||||
}&limit=${limit}>; rel="prev"`,
|
||||
);
|
||||
}
|
||||
req,
|
||||
);
|
||||
|
||||
return jsonResponse(
|
||||
objects.map((user) => userToAPI(user)),
|
||||
200,
|
||||
{
|
||||
Link: linkHeader.join(", "),
|
||||
Link: link,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
import { apiRoute, applyConfig } from "@api";
|
||||
import { errorResponse, jsonResponse } from "@response";
|
||||
import { client } from "~database/datasource";
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { apiRoute, applyConfig } from "@api";
|
||||
import { errorResponse } from "@response";
|
||||
import { errorResponse, response } from "@response";
|
||||
|
||||
export const meta = applyConfig({
|
||||
allowedMethods: ["GET"],
|
||||
route: "/media/:id",
|
||||
route: "/api/v1/media/:id",
|
||||
ratelimits: {
|
||||
max: 100,
|
||||
duration: 60,
|
||||
|
|
@ -35,11 +35,9 @@ export default apiRoute(async (req, matchedRoute) => {
|
|||
if (!(await file.exists())) return errorResponse("File not found", 404);
|
||||
|
||||
// Can't directly copy file into Response because this crashes Bun for now
|
||||
return new Response(buffer, {
|
||||
headers: {
|
||||
"Content-Type": file.type || "application/octet-stream",
|
||||
"Content-Length": `${file.size - start}`,
|
||||
"Content-Range": `bytes ${start}-${end}/${file.size}`,
|
||||
},
|
||||
return response(buffer, 200, {
|
||||
"Content-Type": file.type || "application/octet-stream",
|
||||
"Content-Length": `${file.size - start}`,
|
||||
"Content-Range": `bytes ${start}-${end}/${file.size}`,
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -157,7 +157,6 @@ export default apiRoute(async (req, matchedRoute, extraData) => {
|
|||
return redirectToLogin("No user found with that account");
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (!flow.application) return redirectToLogin("Invalid client_id");
|
||||
|
||||
const code = randomBytes(32).toString("hex");
|
||||
|
|
|
|||
|
|
@ -51,14 +51,11 @@ export default apiRoute(async (req, matchedRoute, extraData) => {
|
|||
last: `${host}/users/${uuid}/outbox?page=1`,
|
||||
total_items: totalStatuses,
|
||||
// Server actor
|
||||
author: `${config.http.base_url}/users/actor`,
|
||||
next:
|
||||
statuses.length === 20
|
||||
? `${host}/users/${uuid}/outbox?page=${pageNumber + 1}`
|
||||
: undefined,
|
||||
prev:
|
||||
pageNumber > 1
|
||||
? `${host}/users/${uuid}/outbox?page=${pageNumber - 1}`
|
||||
author: new URL("/users/actor", config.http.base_url).toString(),
|
||||
next: statuses.length === 20
|
||||
? new URL(`/users/${uuid}/outbox?page=${pageNumber + 1}`, config.http.base_url).toString(),
|
||||
prev: pageNumber > 1
|
||||
? new URL(`/users/${uuid}/outbox?page=${pageNumber - 1}`, config.http.base_url).toString()
|
||||
: undefined,
|
||||
items: statuses.map((s) => statusToLysand(s)),
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue