generated from fahricansecer/boilerplate-be
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
// Path: src/modules/content-generation/content-generation.service.ts
|
||||
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { randomUUID } from 'crypto';
|
||||
import { PrismaService } from '../../database/prisma.service';
|
||||
import { NicheService, Niche, NicheAnalysis } from './services/niche.service';
|
||||
import { DeepResearchService, ResearchResult, ResearchQuery } from './services/deep-research.service';
|
||||
@@ -9,8 +10,11 @@ import { PlatformGeneratorService, Platform, GeneratedContent, MultiPlatformCont
|
||||
import { HashtagService, HashtagSet } from './services/hashtag.service';
|
||||
import { BrandVoiceService, BrandVoice, VoiceApplication } from './services/brand-voice.service';
|
||||
import { VariationService, VariationSet, VariationOptions } from './services/variation.service';
|
||||
import { SeoService, FullSeoAnalysis } from '../seo/seo.service';
|
||||
import { SeoService, FullSeoAnalysis as SeoDTO } from '../seo/seo.service';
|
||||
import { NeuroMarketingService } from '../neuro-marketing/neuro-marketing.service';
|
||||
import { StorageService } from '../visual-generation/services/storage.service';
|
||||
import { ContentType as PrismaContentType, ContentStatus as PrismaContentStatus, MasterContentType as PrismaMasterContentType } from '@prisma/client';
|
||||
|
||||
|
||||
export interface ContentGenerationRequest {
|
||||
topic: string;
|
||||
@@ -62,8 +66,10 @@ export class ContentGenerationService {
|
||||
private readonly variationService: VariationService,
|
||||
private readonly seoService: SeoService,
|
||||
private readonly neuroService: NeuroMarketingService,
|
||||
private readonly storageService: StorageService,
|
||||
) { }
|
||||
|
||||
|
||||
// ========== FULL GENERATION WORKFLOW ==========
|
||||
|
||||
/**
|
||||
@@ -79,6 +85,7 @@ export class ContentGenerationService {
|
||||
brandVoiceId,
|
||||
variationCount = 3,
|
||||
} = request;
|
||||
console.log(`[ContentGenerationService] Starting generation for topic: ${topic}, platforms: ${platforms.join(', ')}`);
|
||||
|
||||
// Analyze niche if provided
|
||||
let nicheAnalysis: NicheAnalysis | undefined;
|
||||
@@ -101,6 +108,7 @@ export class ContentGenerationService {
|
||||
const platformContent: GeneratedContent[] = [];
|
||||
for (const platform of platforms) {
|
||||
try {
|
||||
console.log(`[ContentGenerationService] Generating for platform: ${platform}`);
|
||||
// Use AI generation when available
|
||||
const aiContent = await this.platformService.generateAIContent(
|
||||
topic,
|
||||
@@ -109,6 +117,11 @@ export class ContentGenerationService {
|
||||
'standard',
|
||||
'tr',
|
||||
);
|
||||
console.log(`[ContentGenerationService] AI content length for ${platform}: ${aiContent?.length || 0}`);
|
||||
|
||||
if (!aiContent || aiContent.trim().length === 0) {
|
||||
console.warn(`[ContentGenerationService] AI Content is empty for ${platform}`);
|
||||
}
|
||||
|
||||
const config = this.platformService.getPlatformConfig(platform);
|
||||
let content: GeneratedContent = {
|
||||
@@ -135,12 +148,15 @@ export class ContentGenerationService {
|
||||
}
|
||||
|
||||
platformContent.push(content);
|
||||
console.log(`[ContentGenerationService] Successfully pushed content for ${platform}`);
|
||||
} catch (error) {
|
||||
this.logger.error(`Failed to generate content for platform ${platform}: ${error.message}`);
|
||||
// Continue to next platform
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`[ContentGenerationService] Generated content for ${platformContent.length} platforms`);
|
||||
|
||||
// Generate variations for primary platform
|
||||
const variations: VariationSet[] = [];
|
||||
if (variationCount > 0 && platformContent.length > 0) {
|
||||
@@ -189,7 +205,7 @@ export class ContentGenerationService {
|
||||
}
|
||||
|
||||
return {
|
||||
id: `gen-${Date.now()}`,
|
||||
id: randomUUID(),
|
||||
topic,
|
||||
niche: nicheAnalysis,
|
||||
research,
|
||||
@@ -201,6 +217,101 @@ export class ContentGenerationService {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Persist generated content bundle to database
|
||||
*/
|
||||
async saveGeneratedBundle(userId: string, bundle: GeneratedContentBundle): Promise<{ masterContentId: string }> {
|
||||
console.log(`[ContentGenerationService] Saving bundle for user ${userId}, topic: ${bundle.topic}`);
|
||||
try {
|
||||
return await this.prisma.$transaction(async (tx) => {
|
||||
// 1. Create DeepResearch if it exists in bundle
|
||||
let researchId: string | undefined;
|
||||
if (bundle.research) {
|
||||
const research = await tx.deepResearch.create({
|
||||
data: {
|
||||
userId,
|
||||
topic: bundle.topic,
|
||||
query: bundle.topic, // Simplified for now
|
||||
summary: bundle.research.summary,
|
||||
sources: JSON.parse(JSON.stringify(bundle.research.sources)),
|
||||
keyFindings: JSON.parse(JSON.stringify(bundle.research.keyFindings)),
|
||||
status: 'completed',
|
||||
completedAt: new Date(),
|
||||
}
|
||||
});
|
||||
researchId = research.id;
|
||||
}
|
||||
|
||||
// 2. Create MasterContent
|
||||
const masterContent = await tx.masterContent.create({
|
||||
data: {
|
||||
userId,
|
||||
title: bundle.topic,
|
||||
body: bundle.platforms[0]?.content || '', // Use first platform as master body for now
|
||||
type: PrismaMasterContentType.BLOG, // Default
|
||||
status: PrismaContentStatus.DRAFT,
|
||||
researchId,
|
||||
summary: bundle.research?.summary,
|
||||
}
|
||||
});
|
||||
|
||||
// 3. Create platform-specific content
|
||||
for (const platformContent of bundle.platforms) {
|
||||
// Map SocialPlatform/Platform to ContentType enum
|
||||
let contentType: PrismaContentType = PrismaContentType.BLOG;
|
||||
if (platformContent.platform === 'twitter') contentType = PrismaContentType.TWITTER;
|
||||
else if (platformContent.platform === 'instagram') contentType = PrismaContentType.INSTAGRAM;
|
||||
else if (platformContent.platform === 'linkedin') contentType = PrismaContentType.LINKEDIN;
|
||||
else if (platformContent.platform === 'facebook') contentType = PrismaContentType.FACEBOOK;
|
||||
else if (platformContent.platform === 'tiktok') contentType = PrismaContentType.TIKTOK;
|
||||
|
||||
const content = await tx.content.create({
|
||||
data: {
|
||||
userId,
|
||||
masterContentId: masterContent.id,
|
||||
type: contentType,
|
||||
title: `${bundle.topic} - ${platformContent.platform}`,
|
||||
body: platformContent.content,
|
||||
hashtags: platformContent.hashtags,
|
||||
status: PrismaContentStatus.DRAFT,
|
||||
researchId,
|
||||
}
|
||||
});
|
||||
|
||||
// Save SEO data if available
|
||||
if (bundle.seo) {
|
||||
await tx.contentSeo.create({
|
||||
data: {
|
||||
contentId: content.id,
|
||||
metaTitle: bundle.seo.meta.title,
|
||||
metaDescription: bundle.seo.meta.description,
|
||||
seoScore: bundle.seo.score,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Save Psychology data if available
|
||||
if (bundle.neuro) {
|
||||
await tx.contentPsychology.create({
|
||||
data: {
|
||||
contentId: content.id,
|
||||
triggersUsed: bundle.neuro.triggersUsed,
|
||||
engagementScore: bundle.neuro.score,
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`[ContentGenerationService] Bundle saved successfully. MasterContentId: ${masterContent.id}`);
|
||||
return { masterContentId: masterContent.id };
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`[ContentGenerationService] Failed to save bundle:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ========== NICHE OPERATIONS ==========
|
||||
|
||||
getNiches(): Niche[] {
|
||||
|
||||
Reference in New Issue
Block a user