import { Body, Controller, Delete, Get, Param, Post, Query, Req, Res, UploadedFile, UseInterceptors, UsePipes, } from '@nestjs/common'; import { Request, Response } from 'express'; import { GetOrgFromRequest } from '@gitroom/nestjs-libraries/user/org.from.request'; import { Organization } from '@prisma/client'; import { MediaService } from '@gitroom/nestjs-libraries/database/prisma/media/media.service'; import { ApiTags } from '@nestjs/swagger'; import handleR2Upload from '@gitroom/nestjs-libraries/upload/r2.uploader'; import { FileInterceptor } from '@nestjs/platform-express'; import { CustomFileValidationPipe } from '@gitroom/nestjs-libraries/upload/custom.upload.validation'; import { SubscriptionService } from '@gitroom/nestjs-libraries/database/prisma/subscriptions/subscription.service'; import { UploadFactory } from '@gitroom/nestjs-libraries/upload/upload.factory'; @ApiTags('Media') @Controller('/media') export class MediaController { private storage = UploadFactory.createStorage(); constructor( private _mediaService: MediaService, private _subscriptionService: SubscriptionService ) {} @Delete('/:id') deleteMedia(@GetOrgFromRequest() org: Organization, @Param('id') id: string) { return this._mediaService.deleteMedia(org.id, id); } @Post('/generate-image') async generateImage( @GetOrgFromRequest() org: Organization, @Req() req: Request, @Body('prompt') prompt: string, isPicturePrompt = false ) { const total = await this._subscriptionService.checkCredits(org); if (process.env.STRIPE_PUBLISHABLE_KEY && total.credits <= 0) { return false; } return { output: (isPicturePrompt ? '' : 'data:image/png;base64,') + (await this._mediaService.generateImage(prompt, org, isPicturePrompt)), }; } @Post('/generate-image-with-prompt') async generateImageFromText( @GetOrgFromRequest() org: Organization, @Req() req: Request, @Body('prompt') prompt: string ) { const image = await this.generateImage(org, req, prompt, true); if (!image) { return false; } const file = await this.storage.uploadSimple(image.output); return this._mediaService.saveFile(org.id, file.split('/').pop(), file); } @Post('/upload-server') @UseInterceptors(FileInterceptor('file')) @UsePipes(new CustomFileValidationPipe()) async uploadServer( @GetOrgFromRequest() org: Organization, @UploadedFile() file: Express.Multer.File ) { const uploadedFile = await this.storage.uploadFile(file); return this._mediaService.saveFile( org.id, uploadedFile.originalname, uploadedFile.path ); } @Post('/upload-simple') @UseInterceptors(FileInterceptor('file')) async uploadSimple( @GetOrgFromRequest() org: Organization, @UploadedFile('file') file: Express.Multer.File ) { const getFile = await this.storage.uploadFile(file); return this._mediaService.saveFile( org.id, getFile.originalname, getFile.path ); } @Post('/:endpoint') async uploadFile( @GetOrgFromRequest() org: Organization, @Req() req: Request, @Res() res: Response, @Param('endpoint') endpoint: string ) { const upload = await handleR2Upload(endpoint, req, res); if (endpoint !== 'complete-multipart-upload') { return upload; } // @ts-ignore const name = upload.Location.split('/').pop(); const saveFile = await this._mediaService.saveFile( org.id, name, // @ts-ignore upload.Location ); res.status(200).json({ ...upload, saved: saveFile }); } @Get('/') getMedia( @GetOrgFromRequest() org: Organization, @Query('page') page: number ) { return this._mediaService.getMedia(org.id, page); } }