import { ForbiddenException, Injectable, NotFoundException, } from '@nestjs/common'; import { stat } from 'node:fs/promises'; import { PrismaService } from '../../infrastructure/database/prisma.service'; import { LocalFilesystemStorageService } from '../storage/storage.service'; export interface AudioAssetDownload { filePath: string; contentLength: number; } @Injectable() export class AssetsService { constructor( private readonly prismaService: PrismaService, private readonly storageService: LocalFilesystemStorageService, ) {} async getOwnedAudioAssetDownload( assetId: string, deviceId: string, ): Promise { const device = await this.prismaService.device.findUnique({ where: { id: deviceId }, select: { userId: true, }, }); if (!device) { throw new NotFoundException('Device not found'); } const asset = await this.prismaService.audioAsset.findUnique({ where: { id: assetId }, select: { userId: true, storageKey: true, }, }); if (!asset) { throw new NotFoundException('Audio asset not found'); } if (asset.userId !== device.userId) { throw new ForbiddenException('Audio asset does not belong to this device user.'); } const filePath = this.storageService.resolve(asset.storageKey); try { const fileStats = await stat(filePath); if (!fileStats.isFile()) { throw new NotFoundException('Audio asset file not found'); } return { filePath, contentLength: fileStats.size, }; } catch (error) { if (error instanceof NotFoundException) { throw error; } throw new NotFoundException('Audio asset file not found'); } } }