FEAT: Adiciona camada de storage de mídia (LocalDiskAdapter)
Some checks failed
Deploy Dev / deploy (push) Has been cancelled
Some checks failed
Deploy Dev / deploy (push) Has been cancelled
- MediaStorageService com interface upload/getUrl/delete - LocalDiskAdapter salva em /uploads/media/ com UUID + extensão por mimetype - Cria o diretório automaticamente no boot - BASE_URL adicionado ao .env.example - MediaStorageService e LocalDiskAdapter registrados no WhatsappModule
This commit is contained in:
parent
9514d9df4d
commit
4ab3af503b
@ -12,6 +12,7 @@ DB_NAME=omnichannel
|
||||
|
||||
# HTTP/JWT
|
||||
FRONTEND_URL=http://localhost:3000
|
||||
BASE_URL=http://localhost:3001
|
||||
JWT_SECRET=change-this-long-random-secret
|
||||
JWT_EXPIRES_IN=8h
|
||||
|
||||
|
||||
48
src/modules/whatsapp/media/adapters/local-disk.adapter.ts
Normal file
48
src/modules/whatsapp/media/adapters/local-disk.adapter.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { randomUUID } from 'crypto';
|
||||
|
||||
const UPLOAD_DIR = path.resolve(process.cwd(), 'uploads', 'media');
|
||||
|
||||
const MIME_TO_EXT: Record<string, string> = {
|
||||
'image/jpeg': '.jpg',
|
||||
'image/png': '.png',
|
||||
'image/webp': '.webp',
|
||||
'audio/ogg': '.ogg',
|
||||
'audio/mpeg': '.mp3',
|
||||
'audio/mp4': '.m4a',
|
||||
'audio/amr': '.amr',
|
||||
'video/mp4': '.mp4',
|
||||
'video/3gpp': '.3gp',
|
||||
'application/pdf': '.pdf',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': '.docx',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': '.xlsx',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.presentation': '.pptx',
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class LocalDiskAdapter {
|
||||
private readonly logger = new Logger(LocalDiskAdapter.name);
|
||||
|
||||
constructor() {
|
||||
fs.mkdirSync(UPLOAD_DIR, { recursive: true });
|
||||
}
|
||||
|
||||
async upload(buffer: Buffer, mimeType: string): Promise<string> {
|
||||
const ext = MIME_TO_EXT[mimeType] ?? '.bin';
|
||||
const filename = `${randomUUID()}${ext}`;
|
||||
const filepath = path.join(UPLOAD_DIR, filename);
|
||||
fs.writeFileSync(filepath, buffer);
|
||||
this.logger.log(`Mídia salva: ${filepath}`);
|
||||
return `/uploads/media/${filename}`;
|
||||
}
|
||||
|
||||
delete(relativePath: string): void {
|
||||
try {
|
||||
fs.unlinkSync(path.join(process.cwd(), relativePath));
|
||||
} catch {
|
||||
this.logger.warn(`Falha ao deletar mídia: ${relativePath}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
20
src/modules/whatsapp/media/media-storage.service.ts
Normal file
20
src/modules/whatsapp/media/media-storage.service.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { LocalDiskAdapter } from './adapters/local-disk.adapter';
|
||||
|
||||
@Injectable()
|
||||
export class MediaStorageService {
|
||||
constructor(private readonly disk: LocalDiskAdapter) {}
|
||||
|
||||
async upload(buffer: Buffer, mimeType: string): Promise<string> {
|
||||
return this.disk.upload(buffer, mimeType);
|
||||
}
|
||||
|
||||
getUrl(relativePath: string): string {
|
||||
const base = (process.env.BASE_URL ?? 'http://localhost:3001').replace(/\/$/, '');
|
||||
return `${base}${relativePath}`;
|
||||
}
|
||||
|
||||
delete(relativePath: string): void {
|
||||
this.disk.delete(relativePath);
|
||||
}
|
||||
}
|
||||
@ -11,6 +11,8 @@ import { WhatsappTemplateService } from './whatsapp-template.service';
|
||||
import { MensagensRepository } from './repositories/mensagens.repository';
|
||||
import { WhatsappConfigRepository } from './repositories/whatsapp-config.repository';
|
||||
import { WhatsappConfigService } from './whatsapp-config.service';
|
||||
import { MediaStorageService } from './media/media-storage.service';
|
||||
import { LocalDiskAdapter } from './media/adapters/local-disk.adapter';
|
||||
|
||||
@Module({
|
||||
imports: [AttendanceModule, AuthModule, ContactsModule],
|
||||
@ -22,6 +24,8 @@ import { WhatsappConfigService } from './whatsapp-config.service';
|
||||
MensagensRepository,
|
||||
WhatsappConfigRepository,
|
||||
WhatsappConfigService,
|
||||
MediaStorageService,
|
||||
LocalDiskAdapter,
|
||||
],
|
||||
controllers: [WhatsappController, WhatsappAdminController],
|
||||
exports: [WhatsappService],
|
||||
|
||||
Loading…
Reference in New Issue
Block a user