generated from fahricansecer/boilerplate-be
feat: SEO Power Engine backend updates and remove temp media files
Backend Deploy 🚀 / build-and-deploy (push) Has been cancelled
Backend Deploy 🚀 / build-and-deploy (push) Has been cancelled
This commit is contained in:
@@ -26,7 +26,15 @@ import {
|
||||
} from '@nestjs/swagger';
|
||||
import { FileInterceptor } from '@nestjs/platform-express';
|
||||
import { ProjectsService } from './projects.service';
|
||||
import { CreateProjectDto, UpdateProjectDto, CreateFromTweetDto, CreateFromYoutubeDto, CreateFromDocumentDto, CreateFromExtractedTextDto } from './dto/project.dto';
|
||||
import {
|
||||
CreateProjectDto,
|
||||
UpdateProjectDto,
|
||||
CreateFromTweetDto,
|
||||
CreateFromYoutubeDto,
|
||||
CreateFromDocumentDto,
|
||||
CreateFromExtractedTextDto,
|
||||
CreateFromTextDto,
|
||||
} from './dto/project.dto';
|
||||
|
||||
@ApiTags('projects')
|
||||
@ApiBearerAuth()
|
||||
@@ -71,6 +79,17 @@ export class ProjectsController {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Render kuyruğu genel görünümü — aktif, bekleyen ve son tamamlanan işler.
|
||||
*/
|
||||
@Get('render-queue')
|
||||
@ApiOperation({ summary: 'Render kuyruğu genel görünümünü getir' })
|
||||
@ApiResponse({ status: 200, description: 'Render kuyruk özeti' })
|
||||
async getRenderQueue(@Req() req: any) {
|
||||
const userId = req.user?.id || req.user?.sub;
|
||||
return this.projectsService.getRenderQueue(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tek bir projeyi sahneleri ve medya asset'leriyle birlikte getirir.
|
||||
*/
|
||||
@@ -157,17 +176,6 @@ export class ProjectsController {
|
||||
return this.projectsService.cancelRenderJob(userId, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render kuyruğu genel görünümü — aktif, bekleyen ve son tamamlanan işler.
|
||||
*/
|
||||
@Get('render-queue')
|
||||
@ApiOperation({ summary: 'Render kuyruğu genel görünümünü getir' })
|
||||
@ApiResponse({ status: 200, description: 'Render kuyruk özeti' })
|
||||
async getRenderQueue(@Req() req: any) {
|
||||
const userId = req.user?.id || req.user?.sub;
|
||||
return this.projectsService.getRenderQueue(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* X/Twitter tweet URL'sinden otomatik proje oluşturur ve senaryo üretir.
|
||||
* Tweet çekilir → prompt'a dönüştürülür → AI senaryo üretir → proje kaydedilir.
|
||||
@@ -190,12 +198,26 @@ export class ProjectsController {
|
||||
@HttpCode(HttpStatus.CREATED)
|
||||
@ApiOperation({ summary: 'YouTube videosundan proje oluştur' })
|
||||
@ApiResponse({ status: 201, description: 'YouTube videosundan proje oluşturuldu ve senaryo üretildi' })
|
||||
@ApiResponse({ status: 400, description: 'Geçersiz YouTube URL\'si veya video bulunamadı' })
|
||||
async createFromYoutube(@Body() dto: CreateFromYoutubeDto, @Req() req: any) {
|
||||
const userId = req.user?.id || req.user?.sub;
|
||||
this.logger.log(`YouTube'dan proje oluşturuluyor: ${dto.youtubeUrl}`);
|
||||
return this.projectsService.createFromYoutube(userId, dto);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serbest metin veya fikir üzerinden proje oluşturur.
|
||||
*/
|
||||
@Post('from-text')
|
||||
@HttpCode(HttpStatus.CREATED)
|
||||
@ApiOperation({ summary: 'Serbest metinden proje oluştur' })
|
||||
@ApiResponse({ status: 201, description: 'Metinden proje oluşturuldu ve senaryo üretildi' })
|
||||
async createFromText(@Body() dto: CreateFromTextDto, @Req() req: any) {
|
||||
const userId = req.user?.id || req.user?.sub;
|
||||
this.logger.log(`Serbest metinden proje oluşturuluyor...`);
|
||||
return this.projectsService.createFromText(userId, dto);
|
||||
}
|
||||
|
||||
/**
|
||||
* Yüklenen dokümandan (Word, PDF, Excel vb.) otomatik proje oluşturur.
|
||||
*/
|
||||
@@ -285,6 +307,75 @@ export class ProjectsController {
|
||||
return this.projectsService.regenerateScene(userId, id, sceneId);
|
||||
}
|
||||
|
||||
@Delete(':id/media/:mediaId')
|
||||
@ApiOperation({ summary: 'Sahnede bulunan bir medyayı (MediaAsset) sil' })
|
||||
@ApiResponse({ status: 200, description: 'Medya başarıyla silindi' })
|
||||
async deleteMedia(
|
||||
@Param('id', ParseUUIDPipe) id: string,
|
||||
@Param('mediaId', ParseUUIDPipe) mediaId: string,
|
||||
@Req() req: any,
|
||||
) {
|
||||
const userId = req.user?.id || req.user?.sub;
|
||||
this.logger.log(`Medya silme isteği. Proje: ${id}, Medya: ${mediaId}`);
|
||||
return this.projectsService.deleteSceneMedia(userId, id, mediaId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Proje için 5 yeni SEO-optimized başlık üretir (Gemini AI).
|
||||
*/
|
||||
@Post(':id/generate-seo-titles')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@ApiOperation({ summary: 'AI ile 5 yeni SEO başlığı üret' })
|
||||
@ApiResponse({ status: 200, description: 'SEO başlıkları başarıyla üretildi' })
|
||||
async generateSeoTitles(
|
||||
@Param('id', ParseUUIDPipe) id: string,
|
||||
@Req() req: any,
|
||||
) {
|
||||
const userId = req.user?.id || req.user?.sub;
|
||||
this.logger.log(`SEO başlık üretimi isteniyor: ${id}`);
|
||||
return this.projectsService.generateSeoTitles(userId, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alternatif SEO başlıklarından birini seçerek projenin ana başlığını günceller.
|
||||
*/
|
||||
@Patch(':id/select-title')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@ApiOperation({ summary: 'SEO başlığı seç ve proje başlığını güncelle' })
|
||||
@ApiResponse({ status: 200, description: 'Başlık başarıyla güncellendi' })
|
||||
async selectSeoTitle(
|
||||
@Param('id', ParseUUIDPipe) id: string,
|
||||
@Body('title') title: string,
|
||||
@Req() req: any,
|
||||
) {
|
||||
const userId = req.user?.id || req.user?.sub;
|
||||
if (!title) {
|
||||
throw new BadRequestException('Başlık (title) belirtilmelidir.');
|
||||
}
|
||||
this.logger.log(`SEO başlık seçimi: ${id} — "${title}"`);
|
||||
return this.projectsService.selectSeoTitle(userId, id, title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Projeyi farklı bir dile çevirir.
|
||||
*/
|
||||
@Post(':id/translate')
|
||||
@HttpCode(HttpStatus.CREATED)
|
||||
@ApiOperation({ summary: 'Projeyi farklı bir dile çevir ve kopyasını oluştur' })
|
||||
@ApiResponse({ status: 201, description: 'Proje çevirisi başarıyla tamamlandı' })
|
||||
async translateProject(
|
||||
@Param('id', ParseUUIDPipe) id: string,
|
||||
@Body('targetLanguage') targetLanguage: string,
|
||||
@Req() req: any,
|
||||
) {
|
||||
if (!targetLanguage) {
|
||||
throw new BadRequestException('Hedef dil (targetLanguage) belirtilmelidir.');
|
||||
}
|
||||
const userId = req.user?.id || req.user?.sub;
|
||||
this.logger.log(`Proje çevirisi isteniyor: ${id} -> ${targetLanguage}`);
|
||||
return this.projectsService.translateProject(userId, id, targetLanguage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sahne için ID bazında görsel üret (Gemini AI).
|
||||
* Kullanıcı custom prompt sağlarsa, önce prompt güncellenir ardından resim üretilir.
|
||||
|
||||
Reference in New Issue
Block a user