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'; import { SaveMediaInformationDto } from '@gitroom/nestjs-libraries/dtos/media/save.media.information.dto'; import { VideoDto } from '@gitroom/nestjs-libraries/dtos/videos/video.dto'; import { VideoFunctionDto } from '@gitroom/nestjs-libraries/dtos/videos/video.function.dto'; @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-video') generateVideo( @GetOrgFromRequest() org: Organization, @Body() body: VideoDto ) { console.log('hello'); return this._mediaService.generateVideo(org, body); } @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: '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 originalName = file?.originalname || ''; const uploadedFile = await this.storage.uploadFile(file); return this._mediaService.saveFile( org.id, uploadedFile.originalname, uploadedFile.path, originalName ); } @Post('/save-media') async saveMedia( @GetOrgFromRequest() org: Organization, @Req() req: Request, @Body('name') name: string, @Body('originalName') originalName: string ) { if (!name) { return false; } return this._mediaService.saveFile( org.id, name, process.env.CLOUDFLARE_BUCKET_URL + '/' + name, originalName || undefined ); } @Post('/information') saveMediaInformation( @GetOrgFromRequest() org: Organization, @Body() body: SaveMediaInformationDto ) { return this._mediaService.saveMediaInformation(org.id, body); } @Post('/upload-simple') @UseInterceptors(FileInterceptor('file')) @UsePipes(new CustomFileValidationPipe()) async uploadSimple( @GetOrgFromRequest() org: Organization, @UploadedFile('file') file: Express.Multer.File, @Body('preventSave') preventSave: string = 'false' ) { const originalName = file.originalname; const getFile = await this.storage.uploadFile(file); if (preventSave === 'true') { const { path } = getFile; return { path }; } return this._mediaService.saveFile( org.id, getFile.originalname, getFile.path, originalName ); } @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 originalName = req.body?.file?.name; const saveFile = await this._mediaService.saveFile( org.id, name, // @ts-ignore upload.Location, originalName || undefined ); res.status(200).json({ ...upload, saved: saveFile }); } @Get('/') getMedia( @GetOrgFromRequest() org: Organization, @Query('page') page: number, @Query('search') search?: string ) { return this._mediaService.getMedia(org.id, page, search); } @Get('/video-options') getVideos() { return this._mediaService.getVideoOptions(); } @Post('/video/function') videoFunction( @Body() body: VideoFunctionDto ) { return this._mediaService.videoFunction(body.identifier, body.functionName, body.params); } @Get('/generate-video/:type/allowed') generateVideoAllowed( @GetOrgFromRequest() org: Organization, @Param('type') type: string ) { return this._mediaService.generateVideoAllowed(org, type); } }