roooooms 2

This commit is contained in:
2025-09-06 22:22:36 -04:00
parent 03b751dda6
commit 2aa5352350
15 changed files with 473 additions and 1004 deletions

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

View File

@@ -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);

View File

@@ -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" });
}
}