import fs from 'fs/promises' import { Server } from 'socket.io' import { TSocket } from '#application/types' import prisma from '#application/prisma' import characterRepository from '#repositories/characterRepository' import { gameMasterLogger } from '#application/logger' import { getPublicPath } from '#application/storage' type Payload = { id: string } export default class GMTileDeleteEvent { private readonly public_folder: string constructor( private readonly io: Server, private readonly socket: TSocket ) { this.public_folder = getPublicPath('tiles') } public listen(): void { this.socket.on('gm:tile:delete', this.handleTileDelete.bind(this)) } private async handleTileDelete(data: Payload, callback: (response: boolean) => void): Promise { const character = await characterRepository.getById(this.socket.characterId as number) if (!character) return callback(false) if (character.role !== 'gm') { return } try { gameMasterLogger.info(`Deleting tile ${data.id}`) await this.deleteTileFromDatabase(data.id) await this.deleteTileFile(data.id) gameMasterLogger.info(`Tile ${data.id} deleted successfully.`) callback(true) } catch (error: any) { gameMasterLogger.error('gm:tile:delete error', error.message) callback(false) } } private async deleteTileFromDatabase(tileId: string): Promise { await prisma.tile.delete({ where: { id: tileId } }) } private async deleteTileFile(tileId: string): Promise { const finalFilePath = getPublicPath('tiles', `${tileId}.png`) try { await fs.unlink(finalFilePath) } catch (error: any) { if (error.code !== 'ENOENT') { throw error } gameMasterLogger.warn(`File ${finalFilePath} does not exist.`) } } }