1
0
forked from noxious/server

93 lines
3.0 KiB
TypeScript

import fs from 'fs'
import { Request, Response } from 'express'
import sharp from 'sharp'
import { BaseController } from '#application/base/baseController'
import Storage from '#application/storage'
import { UUID } from '#application/types'
import CharacterHairRepository from '#repositories/characterHairRepository'
import CharacterRepository from '#repositories/characterRepository'
import CharacterTypeRepository from '#repositories/characterTypeRepository'
interface AvatarOptions {
characterTypeId: UUID
characterHairId?: UUID
}
export class AvatarController extends BaseController {
private readonly characterTypeRepository = new CharacterTypeRepository()
private readonly characterHairRepository = new CharacterHairRepository()
private readonly characterRepository = new CharacterRepository()
/**
* Get avatar by character
* @param req
* @param res
*/
public async getByName(req: Request, res: Response) {
const character = await this.characterRepository.getByName(req.params.characterName)
if (!character?.characterType) {
return this.sendError(res, 'Character or character type not found', 404)
}
return this.generateAvatar(res, {
characterTypeId: character.characterType.id,
characterHairId: character.characterHair?.id
})
}
/**
* Get avatar by character type and hair
* @param req
* @param res
*/
public async getByParams(req: Request, res: Response) {
return this.generateAvatar(res, {
characterTypeId: req.params.characterTypeId as UUID,
characterHairId: req.params.characterHairId ? (req.params.characterHairId as UUID) : undefined
})
}
/**
* Generate avatar
* @param res
* @param options
* @private
*/
private async generateAvatar(res: Response, options: AvatarOptions) {
try {
const characterType = await this.characterTypeRepository.getById(options.characterTypeId)
if (!characterType?.sprite?.id) {
return this.sendError(res, 'Character type not found', 404)
}
const bodySpritePath = Storage.getPublicPath('sprites', characterType.sprite.id, 'idle_right_down.png')
if (!fs.existsSync(bodySpritePath)) {
return this.sendError(res, 'Body sprite file not found', 404)
}
let avatar = sharp(bodySpritePath).extend({
top: 2,
bottom: 2,
background: { r: 0, g: 0, b: 0, alpha: 0 }
})
if (options.characterHairId) {
const characterHair = await this.characterHairRepository.getById(options.characterHairId)
if (characterHair?.sprite?.id) {
const hairSpritePath = Storage.getPublicPath('sprites', characterHair.sprite.id, 'front.png')
if (fs.existsSync(hairSpritePath)) {
avatar = avatar.composite([{ input: hairSpritePath, gravity: 'north' }])
}
}
}
res.setHeader('Content-Type', 'image/png')
return avatar.pipe(res)
} catch (error) {
return this.sendError(res, 'Error generating avatar', 500)
}
}
}