import { Router } from 'express'; import { authRequired } from '../middleware/authRequired.js'; import * as resultService from '../services/result.service.js'; import axios from 'axios'; import { env } from '../config/env.js'; const router = Router(); /** * GET /api/result/:generationUuid * Получить результат генерации */ router.get('/:generationUuid', authRequired, async (req, res, next) => { try { const { generationUuid } = req.params; const userId = req.user.id; // Получаем метаданные генерации из БД (только для получения scenarioId) const generationMeta = await resultService.getGenerationMeta({ userId, generationUuid }); if (!generationMeta) { return res.status(404).json({ error: 'NOT_FOUND', message: 'Result not found or access denied', }); } // Вызываем n8n webhook для получения результата const stepData = {}; const n8nUrl = 'https://n8n.uno-click.pip-test.ru/webhook/result'; const n8nResponse = await axios.post(n8nUrl, { meta: { generationUuid, userId, scenarioId: generationMeta.scenarioId, stepData }, body: stepData }); // Проверяем формат ответа от n8n const n8nData = n8nResponse.data; console.log('[result] n8n response:', JSON.stringify(n8nData, null, 2)); // n8n может вернуть данные в разных форматах // Формат 1: { response: { body: { success: {...} } } } // Формат 2: { success: {...} } // Формат 3: [{ response: { body: { success: {...} } } }] - массив let responseData = n8nData; // Если массив - берём первый элемент if (Array.isArray(n8nData) && n8nData.length > 0) { responseData = n8nData[0]; } // Если есть response.body - извлекаем if (responseData?.response?.body) { responseData = responseData.response.body; } console.log('[result] extracted responseData:', JSON.stringify(responseData, null, 2)); // Вариант 1: n8n вернул output_s3 в response_payload if (responseData?.success?.response_payload?.output_s3) { const s3Key = responseData.success.response_payload.output_s3.replace('s3://uno-click/', ''); const publicUrl = `/files/${s3Key}`; return res.json({ ok: true, result: { generationUuid, scenarioId: generationMeta.scenarioId, scenarioName: generationMeta.scenarioName, status: 'completed', files: [{ contentType: 'video', url: publicUrl, }], }, }); } // Вариант 2: n8n вернул files массив с s3:// URL if (responseData?.success?.files && Array.isArray(responseData.success.files)) { const convertedFiles = responseData.success.files.map(file => { // Конвертируем s3:// в /files/... // Поддерживаем оба формата: { url: "s3://..." } и { output_s3: "s3://..." } let fileUrl = file.url || file.output_s3; if (fileUrl && fileUrl.startsWith('s3://uno-click/')) { const s3Key = fileUrl.replace('s3://uno-click/', ''); return { contentType: file.contentType, url: `/files/${s3Key}`, }; } return file; }); return res.json({ ok: true, result: { generationUuid, scenarioId: generationMeta.scenarioId, scenarioName: generationMeta.scenarioName, status: 'completed', files: convertedFiles, }, }); } // Вариант 3: success на верхнем уровне (для совместимости) if (n8nData?.success?.files && Array.isArray(n8nData.success.files)) { const convertedFiles = n8nData.success.files.map(file => { if (file.url && file.url.startsWith('s3://uno-click/')) { const s3Key = file.url.replace('s3://uno-click/', ''); return { ...file, url: `/files/${s3Key}`, }; } return file; }); return res.json({ ok: true, result: { generationUuid, scenarioId: generationMeta.scenarioId, scenarioName: generationMeta.scenarioName, status: 'completed', files: convertedFiles, }, }); } // Вариант 4: провайдер вернул fail с сообщением — пробрасываем наверх if (responseData?.success?.code === 'fail') { return res.json({ success: { code: 'fail', message: responseData.success.message || responseData.success.msg, }, }); } // Вариант 5: ошибка от n8n с code/message — пробрасываем наверх if (responseData?.error?.code) { return res.json({ error: { code: responseData.error.code, message: responseData.error.message, }, }); } res.json({ ok: true, result: { generationUuid, scenarioId: generationMeta.scenarioId, scenarioName: generationMeta.scenarioName, ...responseData, }, }); } catch (err) { console.error('[result] Error:', err); next(err); } }); export default router;