/** * 云函数:jimengManager * 代理即梦图片、视频、数字人、动作迁移等任务接口,避免前端暴露上游地址和 token。 * * 部署后把函数 objectId 填入 src/app/services/cloud-functions.ts 的 jimeng。 */ const JIMENG_TOKEN = 'Bearer r:f0333969e312a40e4703e8fe4ed1c600'; const JIMENG_BASE_URL = 'https://server.fmode.cn/api/volcengine/jimeng'; const PARSE_BASE_URL = 'https://server.fmode.cn/parse'; const PARSE_APP_ID = 'ncloudmaster'; const ALLOWED_ENDPOINTS = new Set([ 'getVideoV3_720p', 'getVideoV3_1080p', 'getVideoV3_Pro', 'getText2ImgV31', 'getImgV4', 'getDataByTask02', 'getOhIdentifyMain', 'getOhDateByTask', 'getOmniHuman', 'getActorV2', ]); async function handler(request, response) { try { const action = pickParam(request, 'action') || 'call'; if (action === 'call') { const endpoint = String(pickParam(request, 'endpoint') || '').trim(); const payload = pickParam(request, 'payload', 'data') || {}; if (!ALLOWED_ENDPOINTS.has(endpoint)) { return response.json({ code: 400, success: false, error: '不支持的生成接口' }); } const upstreamPayload = stripEmpty({ ...payload, token: JIMENG_TOKEN }); const data = await postJson(`${JIMENG_BASE_URL}/${endpoint}`, upstreamPayload); response.json(data); return; } if (action === 'getWorkResult') { const workId = String(pickParam(request, 'workId', 'objectId') || '').trim(); if (!workId) { return response.json({ code: 400, success: false, error: '缺少作品 ID' }); } const data = await getJson(`${PARSE_BASE_URL}/classes/ImagineWork/${encodeURIComponent(workId)}`, { 'X-Parse-Application-Id': PARSE_APP_ID, }); response.json({ code: 200, success: true, data }); return; } response.json({ code: 400, success: false, error: `未知 action: ${action}` }); } catch (error) { console.error('jimengManager failed:', error && error.message ? error.message : error); response.json({ code: 500, success: false, error: error && error.message ? error.message : '生成服务调用失败' }); } } function pickParam(request, ...names) { const sources = [request.params, request.body, request]; for (const src of sources) { if (!src || typeof src !== 'object') continue; for (const n of names) { const v = src[n]; if (v !== undefined && v !== null && v !== '') return v; } } return null; } function stripEmpty(value) { if (!value || typeof value !== 'object') return value; const out = Array.isArray(value) ? [] : {}; for (const [key, val] of Object.entries(value)) { if (val === undefined || val === null || val === '') continue; if (val && typeof val === 'object' && !Array.isArray(val)) { const nested = stripEmpty(val); if (Object.keys(nested).length) out[key] = nested; } else { out[key] = val; } } return out; } async function postJson(url, body) { const r = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body), }); return readResponse(r); } async function getJson(url, headers) { const r = await fetch(url, { method: 'GET', headers }); const data = await readResponse(r); if (data && data.success === false) throw new Error(data.error || '查询结果失败'); return data; } async function readResponse(r) { const text = await r.text(); let data = null; try { data = text ? JSON.parse(text) : null; } catch {} if (!r.ok) { return { code: r.status, success: false, error: readError(data, text) || `HTTP ${r.status}` }; } return data || { code: 500, success: false, error: '服务返回异常' }; } function readError(data, fallback) { return data?.error?.message || data?.error || data?.message || data?.msg || fallback || ''; }