- Columna username (unique, nullable) en auth.users - Campo username en CreateUserDto y UpdateUserDto Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
101 lines
3.6 KiB
TypeScript
101 lines
3.6 KiB
TypeScript
import {
|
|
Controller,
|
|
Post,
|
|
Get,
|
|
Query,
|
|
UseGuards,
|
|
Body,
|
|
} from '@nestjs/common';
|
|
import {
|
|
ApiTags,
|
|
ApiOperation,
|
|
ApiResponse,
|
|
ApiBearerAuth,
|
|
ApiQuery,
|
|
} from '@nestjs/swagger';
|
|
import { ContentGeneratorService, GenerationResult } from './content-generator.service';
|
|
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
|
|
import { RolesGuard } from '../../common/guards/roles.guard';
|
|
import { Roles } from '../../common/decorators/roles.decorator';
|
|
|
|
@ApiTags('Content Generator')
|
|
@Controller('content-generator')
|
|
@UseGuards(JwtAuthGuard, RolesGuard)
|
|
@Roles('admin')
|
|
@ApiBearerAuth('JWT-auth')
|
|
export class ContentGeneratorController {
|
|
constructor(private readonly contentGeneratorService: ContentGeneratorService) {}
|
|
|
|
@Get('stats')
|
|
@ApiOperation({ summary: 'Get content generation statistics' })
|
|
@ApiResponse({ status: 200, description: 'Statistics retrieved successfully' })
|
|
async getStats() {
|
|
return this.contentGeneratorService.getStats();
|
|
}
|
|
|
|
@Post('generate-descriptions')
|
|
@ApiOperation({ summary: 'Generate descriptions for monuments (Admin only)' })
|
|
@ApiQuery({ name: 'limit', required: false, type: Number, description: 'Max places to process (default: 10)' })
|
|
@ApiQuery({ name: 'languages', required: false, type: String, description: 'Comma-separated language codes (default: es,en,fr,it,de)' })
|
|
@ApiQuery({ name: 'onlyMissing', required: false, type: Boolean, description: 'Only process places without description (default: true)' })
|
|
@ApiResponse({ status: 200, description: 'Descriptions generated successfully' })
|
|
async generateDescriptions(
|
|
@Query('limit') limit?: number,
|
|
@Query('languages') languages?: string,
|
|
@Query('onlyMissing') onlyMissing?: boolean,
|
|
) {
|
|
const languageList = languages ? languages.split(',').map(l => l.trim()) : undefined;
|
|
|
|
const results = await this.contentGeneratorService.generateAllDescriptions({
|
|
limit: limit || 10,
|
|
languages: languageList,
|
|
onlyMissing: onlyMissing !== false,
|
|
});
|
|
|
|
return {
|
|
success: true,
|
|
processed: results.length,
|
|
successful: results.filter(r => r.success).length,
|
|
failed: results.filter(r => !r.success).length,
|
|
results,
|
|
};
|
|
}
|
|
|
|
@Post('generate-audios')
|
|
@ApiOperation({ summary: 'Generate audio files for monuments (Admin only)' })
|
|
@ApiQuery({ name: 'limit', required: false, type: Number, description: 'Max places to process (default: 10)' })
|
|
@ApiQuery({ name: 'languages', required: false, type: String, description: 'Comma-separated language codes (default: es,en,fr,it,de)' })
|
|
@ApiResponse({ status: 200, description: 'Audios generated successfully' })
|
|
async generateAudios(
|
|
@Query('limit') limit?: number,
|
|
@Query('languages') languages?: string,
|
|
) {
|
|
const languageList = languages ? languages.split(',').map(l => l.trim()) : undefined;
|
|
|
|
const results = await this.contentGeneratorService.generateAllAudios({
|
|
limit: limit || 10,
|
|
languages: languageList,
|
|
});
|
|
|
|
return {
|
|
success: true,
|
|
processed: results.length,
|
|
successful: results.filter(r => r.success).length,
|
|
failed: results.filter(r => !r.success).length,
|
|
results,
|
|
};
|
|
}
|
|
|
|
@Post('generate-single')
|
|
@ApiOperation({ summary: 'Generate content for a single place' })
|
|
async generateSingle(
|
|
@Body() body: { placeId: number; languages?: string[] },
|
|
) {
|
|
// This would be implemented to generate content for a specific place
|
|
return {
|
|
message: 'Single place generation not yet implemented',
|
|
placeId: body.placeId,
|
|
};
|
|
}
|
|
}
|