roooooms 2
This commit is contained in:
26
src/routes/api/routes/rooms.ts
Normal file
26
src/routes/api/routes/rooms.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import z from "zod";
|
||||
import { createHonoRoute } from "../../../util/import.ts";
|
||||
import { typedZValidator } from "../../../util/validators.ts";
|
||||
import Server from "../../../server/server.ts";
|
||||
|
||||
export const route = createHonoRoute("/rooms");
|
||||
|
||||
const getRoomDetailsParamSchema = z.object({
|
||||
id: z.coerce.number().max(Math.pow(2, 31))
|
||||
});
|
||||
route.app.get('/v4/details/:id', typedZValidator('param', getRoomDetailsParamSchema), async (c, nxt) => {
|
||||
const room = await Server.Rooms.get(parseInt(c.req.param('id')));
|
||||
if (room === null) return await nxt();
|
||||
else return c.json(await room.export());
|
||||
});
|
||||
const getRoomByNameParamSchema = z.object({
|
||||
name: z.string()
|
||||
});
|
||||
route.app.get('/v2/name/:name', typedZValidator('param', getRoomByNameParamSchema), async (c, nxt) => {
|
||||
const id = await Server.Rooms.getIdFromName(c.req.param('name'));
|
||||
if (id == null) return await nxt();
|
||||
|
||||
const room = await Server.Rooms.get(id);
|
||||
if (room == null) return await nxt();
|
||||
else return c.json((await room.export()).Room);
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
import z from "zod";
|
||||
import { authenticate, genericResponse } from "../../../util/api.ts";
|
||||
import { authenticate } from "../../../util/api.ts";
|
||||
import { createHonoRoute } from "../../../util/import.ts";
|
||||
import { typedZValidator } from "../../../util/validators.ts";
|
||||
import { HonoEnv } from "../../../util/types.ts";
|
||||
@@ -23,7 +23,6 @@ const settingsSetSchema = z.object({
|
||||
});
|
||||
route.app.post('/v2/set', typedZValidator('json', settingsSetSchema), async c => {
|
||||
const { Key, Value } = c.req.valid('json');
|
||||
if (!Key) return c.json(genericResponse(false, "Internal Server Error"), 500);
|
||||
|
||||
await c.get('profile').Settings.setSetting(Key, Value);
|
||||
return c.status(200);
|
||||
|
||||
@@ -2,39 +2,50 @@ import z from "zod";
|
||||
import Server from "../../server/server.ts";
|
||||
import { createHonoRoute } from "../../util/import.ts";
|
||||
import { typedZValidator } from "../../util/validators.ts";
|
||||
import { FileType, File } from "../../server/content/base.ts";
|
||||
import sharp from "sharp";
|
||||
import path from "node:path";
|
||||
import { RootPath } from "../../util/path.ts";
|
||||
import Logging from "@proxnet/undead-logging";
|
||||
import { statusResponse } from "../../util/api.ts";
|
||||
import { HTTPStatus } from "@oneday/http-status";
|
||||
import { Buffer } from "node:buffer";
|
||||
|
||||
export const route = createHonoRoute('/img');
|
||||
|
||||
async function convertImage(query: {cropSquare?: boolean | undefined;width?: number | undefined;height?: number | undefined;}, data: Uint8Array<ArrayBufferLike>): Promise<Uint8Array<ArrayBufferLike>> {
|
||||
const image = sharp(data);
|
||||
const rootMetadata = await image.metadata();
|
||||
const squareSize = Math.min(rootMetadata.width, rootMetadata.height);
|
||||
if (query.cropSquare) image.resize(squareSize, squareSize);
|
||||
const log = new Logging("ImageRoute");
|
||||
|
||||
const newImage = sharp(await image.png().toBuffer());
|
||||
if (query.width && query.height)
|
||||
newImage.resize(query.width, query.height);
|
||||
else if (query.width)
|
||||
newImage.resize(query.width);
|
||||
else if (query.height)
|
||||
newImage.resize(undefined, query.height);
|
||||
async function convertImage(query: ImageQuery, data: Uint8Array<ArrayBufferLike>): Promise<Uint8Array<ArrayBufferLike> | null> {
|
||||
try {
|
||||
const image = sharp(data);
|
||||
const rootMetadata = await image.metadata();
|
||||
const squareSize = Math.min(rootMetadata.width, rootMetadata.height);
|
||||
if (query.cropSquare) image.resize(squareSize, squareSize);
|
||||
|
||||
return await newImage.png().toBuffer();
|
||||
const newImage = sharp(await image.png().toBuffer());
|
||||
if (query.width && query.height)
|
||||
newImage.resize(query.width, query.height);
|
||||
else if (query.width)
|
||||
newImage.resize(query.width);
|
||||
else if (query.height)
|
||||
newImage.resize(undefined, query.height);
|
||||
|
||||
return await newImage.png().toBuffer();
|
||||
} catch (err) {
|
||||
log.w(`Image transformation failed: ${(err as Error).stack}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const imgNameParamSchema = z.object({
|
||||
imgName: z.string().min(4).includes('.')
|
||||
imgName: z.string().min(5).includes('.')
|
||||
});
|
||||
const imgQuerySchema = z.object({
|
||||
cropSquare: z.coerce.boolean().optional(),
|
||||
width: z.coerce.number().min(64).max(3840).optional(),
|
||||
height: z.coerce.number().min(64).max(2160).optional(),
|
||||
});
|
||||
type ImageQuery = z.infer<typeof imgQuerySchema>;
|
||||
|
||||
route.app.get('/:imgName',
|
||||
typedZValidator('param', imgNameParamSchema),
|
||||
typedZValidator('query', imgQuerySchema),
|
||||
@@ -43,29 +54,29 @@ route.app.get('/:imgName',
|
||||
const { imgName } = c.req.valid('param');
|
||||
const query = c.req.valid('query');
|
||||
|
||||
const file: File | null = await Server.Content.getFile(`img/${imgName}`);
|
||||
let raw: Uint8Array<ArrayBuffer> | null = null;
|
||||
if (!file) {
|
||||
try {
|
||||
raw = await Deno.readFile(path.join(RootPath, "res/baseimg/", imgName));
|
||||
} catch {
|
||||
raw = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!raw && file && file.Meta.Type !== FileType.Image) return c.status(404);
|
||||
|
||||
try {
|
||||
let result: Uint8Array<ArrayBufferLike> | null = null;
|
||||
if (file) result = await convertImage(query, file.Data);
|
||||
else if (raw) result = await convertImage(query, raw);
|
||||
|
||||
if (result) return c.body(result, 200, { "Cache-Control": "public, no-transform, max-age=1800", "Content-Type": "image/png" });
|
||||
else return c.status(404);
|
||||
|
||||
} catch (err) {
|
||||
new Logging("ImageRoute").w(`Sharp error: ${err}`);
|
||||
return c.status(500);
|
||||
const datas: Uint8Array<ArrayBufferLike>[] = (await Promise.all<Uint8Array<ArrayBufferLike> | null>([
|
||||
new Promise(resolve => {
|
||||
Deno.readFile(path.join(RootPath, "res/baseimg/", imgName)).then(img => {
|
||||
resolve(img);
|
||||
}).catch(() => {
|
||||
resolve(null);
|
||||
});
|
||||
}),
|
||||
new Promise(resolve => {
|
||||
Server.Content.getFile(`img/${imgName}`).then(file => {
|
||||
if (file) resolve(file.Data);
|
||||
else resolve(null);
|
||||
}).catch(() => {
|
||||
resolve(null);
|
||||
});
|
||||
})
|
||||
])).filter(val => val !== null);
|
||||
|
||||
if (datas.length == 0) return statusResponse(c, HTTPStatus.NotFound);
|
||||
else {
|
||||
const result = await convertImage(query, datas[0]);
|
||||
if (result == null) return statusResponse(c, HTTPStatus.InternalServerError, "Image transformation failed. Contact an administrator.");
|
||||
return c.body(Buffer.from(result), 200, { "Cache-Control": "public, no-transform, max-age=1800", "Content-Type": "image/png" });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user