You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

40 lines
1.4 KiB

import { createHash } from 'node:crypto';
import { avatarPresets } from '../shared/avatars.mjs';
export function avatarReference(user) {
if (user?.avatar?.preset)
return avatarPresets.find((p) => p.id === user.avatar.preset)?.src;
if (user?.avatar?.image)
return `/api/avatars/${user.id}?v=${user.avatar.revision}`;
}
export function validateAvatar(input) {
if ('preset' in input) {
if (input.preset === null) return null;
if (!avatarPresets.some((p) => p.id === input.preset))
throw Error('Elige un avatar de la lista.');
return { preset: input.preset };
}
if (
typeof input.image !== 'string' ||
!/^data:image\/png;base64,[A-Za-z0-9+/]+={0,2}$/.test(input.image) ||
input.image.length > 90000
)
throw Error('La imagen del avatar no es válida.');
const bytes = Buffer.from(input.image.slice(22), 'base64');
if (
bytes.length < 45 ||
bytes.length > 65536 ||
bytes.subarray(0, 8).toString('hex') !== '89504e470d0a1a0a' ||
bytes.toString('ascii', 12, 16) !== 'IHDR' ||
bytes.readUInt32BE(8) !== 13
)
throw Error('El avatar debe ser una imagen PNG.');
const width = bytes.readUInt32BE(16),
height = bytes.readUInt32BE(20);
if (width < 1 || height < 1 || width > 256 || height > 256)
throw Error('La imagen del avatar debe medir como máximo 256 píxeles.');
return {
image: input.image,
revision: createHash('sha256').update(bytes).digest('hex').slice(0, 16),
};
}

Powered by TurnKey Linux.