mirror of
https://github.com/versia-pub/server.git
synced 2026-03-14 06:19:15 +01:00
refactor(api): 🚚 Use api/ for API routes instead of server/api/
This commit is contained in:
parent
dfc0bf4595
commit
3c1b330d4b
143 changed files with 5 additions and 5 deletions
111
api/api/v1/media/:id/index.ts
Normal file
111
api/api/v1/media/:id/index.ts
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
import {
|
||||
apiRoute,
|
||||
applyConfig,
|
||||
auth,
|
||||
handleZodError,
|
||||
idValidator,
|
||||
} from "@/api";
|
||||
import { response } from "@/response";
|
||||
import { zValidator } from "@hono/zod-validator";
|
||||
import { z } from "zod";
|
||||
import { MediaManager } from "~/classes/media/media-manager";
|
||||
import { RolePermissions } from "~/drizzle/schema";
|
||||
import { config } from "~/packages/config-manager/index";
|
||||
import { Attachment } from "~/packages/database-interface/attachment";
|
||||
|
||||
export const meta = applyConfig({
|
||||
allowedMethods: ["GET", "PUT"],
|
||||
ratelimits: {
|
||||
max: 10,
|
||||
duration: 60,
|
||||
},
|
||||
route: "/api/v1/media/:id",
|
||||
auth: {
|
||||
required: true,
|
||||
oauthPermissions: ["write:media"],
|
||||
},
|
||||
permissions: {
|
||||
required: [RolePermissions.ManageOwnMedia],
|
||||
},
|
||||
});
|
||||
|
||||
export const schemas = {
|
||||
param: z.object({
|
||||
id: z.string(),
|
||||
}),
|
||||
form: z.object({
|
||||
thumbnail: z.instanceof(File).optional(),
|
||||
description: z
|
||||
.string()
|
||||
.max(config.validation.max_media_description_size)
|
||||
.optional(),
|
||||
focus: z.string().optional(),
|
||||
}),
|
||||
};
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.on(
|
||||
meta.allowedMethods,
|
||||
meta.route,
|
||||
zValidator("param", schemas.param, handleZodError),
|
||||
zValidator("form", schemas.form, handleZodError),
|
||||
auth(meta.auth, meta.permissions),
|
||||
async (context) => {
|
||||
const { id } = context.req.valid("param");
|
||||
|
||||
if (!id.match(idValidator)) {
|
||||
return context.json(
|
||||
{ error: "Invalid ID, must be of type UUIDv7" },
|
||||
404,
|
||||
);
|
||||
}
|
||||
|
||||
const attachment = await Attachment.fromId(id);
|
||||
|
||||
if (!attachment) {
|
||||
return context.json({ error: "Media not found" }, 404);
|
||||
}
|
||||
|
||||
switch (context.req.method) {
|
||||
case "GET": {
|
||||
if (attachment.data.url) {
|
||||
return context.json(attachment.toApi());
|
||||
}
|
||||
return response(null, 206);
|
||||
}
|
||||
case "PUT": {
|
||||
const { description, thumbnail } =
|
||||
context.req.valid("form");
|
||||
|
||||
let thumbnailUrl = attachment.data.thumbnailUrl;
|
||||
|
||||
const mediaManager = new MediaManager(config);
|
||||
|
||||
if (thumbnail) {
|
||||
const { path } = await mediaManager.addFile(thumbnail);
|
||||
thumbnailUrl = Attachment.getUrl(path);
|
||||
}
|
||||
|
||||
const descriptionText =
|
||||
description || attachment.data.description;
|
||||
|
||||
if (
|
||||
descriptionText !== attachment.data.description ||
|
||||
thumbnailUrl !== attachment.data.thumbnailUrl
|
||||
) {
|
||||
await attachment.update({
|
||||
description: descriptionText,
|
||||
thumbnailUrl,
|
||||
});
|
||||
|
||||
return context.json(attachment.toApi());
|
||||
}
|
||||
|
||||
return context.json(attachment.toApi());
|
||||
}
|
||||
}
|
||||
|
||||
return context.json({ error: "Method not allowed" }, 405);
|
||||
},
|
||||
),
|
||||
);
|
||||
102
api/api/v1/media/index.ts
Normal file
102
api/api/v1/media/index.ts
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
import { apiRoute, applyConfig, auth, handleZodError } from "@/api";
|
||||
import { zValidator } from "@hono/zod-validator";
|
||||
import sharp from "sharp";
|
||||
import { z } from "zod";
|
||||
import { MediaManager } from "~/classes/media/media-manager";
|
||||
import { RolePermissions } from "~/drizzle/schema";
|
||||
import { config } from "~/packages/config-manager/index";
|
||||
import { Attachment } from "~/packages/database-interface/attachment";
|
||||
|
||||
export const meta = applyConfig({
|
||||
allowedMethods: ["POST"],
|
||||
ratelimits: {
|
||||
max: 10,
|
||||
duration: 60,
|
||||
},
|
||||
route: "/api/v1/media",
|
||||
auth: {
|
||||
required: true,
|
||||
oauthPermissions: ["write:media"],
|
||||
},
|
||||
permissions: {
|
||||
required: [RolePermissions.ManageOwnMedia],
|
||||
},
|
||||
});
|
||||
|
||||
export const schemas = {
|
||||
form: z.object({
|
||||
file: z.instanceof(File),
|
||||
thumbnail: z.instanceof(File).optional(),
|
||||
description: z
|
||||
.string()
|
||||
.max(config.validation.max_media_description_size)
|
||||
.optional(),
|
||||
focus: z.string().optional(),
|
||||
}),
|
||||
};
|
||||
|
||||
export default apiRoute((app) =>
|
||||
app.on(
|
||||
meta.allowedMethods,
|
||||
meta.route,
|
||||
zValidator("form", schemas.form, handleZodError),
|
||||
auth(meta.auth, meta.permissions),
|
||||
async (context) => {
|
||||
const { file, thumbnail, description } = context.req.valid("form");
|
||||
|
||||
if (file.size > config.validation.max_media_size) {
|
||||
return context.json(
|
||||
{
|
||||
error: `File too large, max size is ${config.validation.max_media_size} bytes`,
|
||||
},
|
||||
413,
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
config.validation.enforce_mime_types &&
|
||||
!config.validation.allowed_mime_types.includes(file.type)
|
||||
) {
|
||||
return context.json({ error: "Invalid file type" }, 415);
|
||||
}
|
||||
|
||||
const sha256 = new Bun.SHA256();
|
||||
|
||||
const isImage = file.type.startsWith("image/");
|
||||
|
||||
const metadata = isImage
|
||||
? await sharp(await file.arrayBuffer()).metadata()
|
||||
: null;
|
||||
|
||||
const mediaManager = new MediaManager(config);
|
||||
|
||||
const { path, blurhash } = await mediaManager.addFile(file);
|
||||
|
||||
const url = Attachment.getUrl(path);
|
||||
|
||||
let thumbnailUrl = "";
|
||||
|
||||
if (thumbnail) {
|
||||
const { path } = await mediaManager.addFile(thumbnail);
|
||||
|
||||
thumbnailUrl = Attachment.getUrl(path);
|
||||
}
|
||||
|
||||
const newAttachment = await Attachment.insert({
|
||||
url,
|
||||
thumbnailUrl,
|
||||
sha256: sha256.update(await file.arrayBuffer()).digest("hex"),
|
||||
mimeType: file.type,
|
||||
description: description ?? "",
|
||||
size: file.size,
|
||||
blurhash: blurhash ?? undefined,
|
||||
width: metadata?.width ?? undefined,
|
||||
height: metadata?.height ?? undefined,
|
||||
});
|
||||
|
||||
// TODO: Add job to process videos and other media
|
||||
|
||||
return context.json(newAttachment.toApi());
|
||||
},
|
||||
),
|
||||
);
|
||||
Loading…
Add table
Add a link
Reference in a new issue