142 lines
5.0 KiB
JavaScript
142 lines
5.0 KiB
JavaScript
/**
|
|
* Exporte l'affiche Penpot en PNG
|
|
*/
|
|
import http from 'http';
|
|
import fs from 'fs';
|
|
|
|
const MCP = { host: '192.168.1.150', port: 9002 };
|
|
|
|
let sessionId = null;
|
|
let msgId = 1;
|
|
|
|
function postMCP(body) {
|
|
return new Promise((resolve, reject) => {
|
|
const payload = JSON.stringify(body);
|
|
const headers = {
|
|
'Content-Type': 'application/json',
|
|
'Content-Length': Buffer.byteLength(payload),
|
|
'Accept': 'application/json, text/event-stream',
|
|
};
|
|
if (sessionId) headers['mcp-session-id'] = sessionId;
|
|
const req = http.request({ ...MCP, path: '/mcp', method: 'POST', headers }, res => {
|
|
if (res.headers['mcp-session-id']) sessionId = res.headers['mcp-session-id'];
|
|
let data = ''; res.setEncoding('utf8');
|
|
res.on('data', c => data += c);
|
|
res.on('end', () => {
|
|
const ct = res.headers['content-type'] || '';
|
|
if (ct.includes('text/event-stream')) {
|
|
let result = null, error = null;
|
|
for (const line of data.split('\n')) {
|
|
if (line.startsWith('data:')) {
|
|
const raw = line.slice(5).trim();
|
|
if (!raw || raw === '[DONE]') continue;
|
|
try {
|
|
const j = JSON.parse(raw);
|
|
if (j.result !== undefined) result = j.result;
|
|
if (j.error) error = j.error;
|
|
} catch {}
|
|
}
|
|
}
|
|
if (error) reject(new Error(JSON.stringify(error)));
|
|
else resolve(result);
|
|
} else {
|
|
try {
|
|
const j = JSON.parse(data);
|
|
if (j.error) reject(new Error(JSON.stringify(j.error)));
|
|
else resolve(j.result ?? j);
|
|
} catch { resolve(data || null); }
|
|
}
|
|
});
|
|
});
|
|
req.on('error', reject); req.write(payload); req.end();
|
|
});
|
|
}
|
|
|
|
async function initMCP() {
|
|
await postMCP({ jsonrpc: '2.0', id: msgId++, method: 'initialize', params: { protocolVersion: '2025-03-26', capabilities: {}, clientInfo: { name: 'nox', version: '1.0' } } });
|
|
await postMCP({ jsonrpc: '2.0', method: 'notifications/initialized', params: {} }).catch(() => {});
|
|
console.log('✅ Session:', sessionId);
|
|
}
|
|
|
|
async function callTool(name, args = {}) {
|
|
const result = await postMCP({ jsonrpc: '2.0', id: msgId++, method: 'tools/call', params: { name, arguments: args } });
|
|
if (!result) return null;
|
|
if (result.content) {
|
|
// Cherche le contenu JSON ou texte
|
|
for (const c of result.content) {
|
|
if (c.type === 'image') return c; // image directe
|
|
try { return JSON.parse(c.text); } catch {}
|
|
}
|
|
return result.content.map(c => c.text).join('\n');
|
|
}
|
|
return result;
|
|
}
|
|
|
|
await initMCP();
|
|
|
|
// Trouver le fichier créé
|
|
const profile = await callTool('get_profile', {});
|
|
const projectId = profile?.defaultProjectId;
|
|
|
|
const filesResult = await callTool('list_files', { projectId });
|
|
console.log('Files:', JSON.stringify(filesResult).slice(0, 400));
|
|
|
|
// Trouver l'affiche
|
|
let fileId = null, fileName = null;
|
|
if (Array.isArray(filesResult)) {
|
|
const f = filesResult.find(f => f.name?.includes('SOLDES'));
|
|
fileId = f?.id; fileName = f?.name;
|
|
} else {
|
|
const match = JSON.stringify(filesResult).match(/"id":"([0-9a-f-]+)"[^}]*"name":"[^"]*SOLDES/);
|
|
if (match) fileId = match[1];
|
|
}
|
|
console.log('Affiche fileId:', fileId, fileName);
|
|
|
|
if (!fileId) { console.error('Fichier non trouvé'); process.exit(1); }
|
|
|
|
// Lister les pages
|
|
const pages = await callTool('list_pages', { fileId });
|
|
console.log('Pages:', JSON.stringify(pages).slice(0, 200));
|
|
let pageId = null;
|
|
if (Array.isArray(pages)) pageId = pages[0]?.id;
|
|
else { const m = JSON.stringify(pages).match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/g); pageId = m?.find(u => u !== fileId); }
|
|
console.log('PageId:', pageId);
|
|
|
|
// Lister les shapes pour trouver le frame
|
|
const shapes = await callTool('get_page_shapes', { fileId, pageId });
|
|
console.log('Shapes:', JSON.stringify(shapes).slice(0, 400));
|
|
|
|
// Trouver le frame principal
|
|
let frameId = null;
|
|
if (Array.isArray(shapes)) {
|
|
const frame = shapes.find(s => s.name === 'Affiche SOLDES' || s.type === 'frame');
|
|
frameId = frame?.id;
|
|
} else {
|
|
const m = JSON.stringify(shapes).match(/"id":"([0-9a-f-]+)"/g);
|
|
frameId = m?.[0]?.match(/"id":"([0-9a-f-]+)"/)?.[1];
|
|
}
|
|
console.log('FrameId:', frameId);
|
|
|
|
// Export en PNG
|
|
console.log('\n📸 Export PNG...');
|
|
const exportResult = await callTool('export_shape', {
|
|
fileId,
|
|
pageId,
|
|
shapeId: frameId,
|
|
format: 'png',
|
|
scale: 2,
|
|
});
|
|
console.log('Export result type:', typeof exportResult, JSON.stringify(exportResult).slice(0, 300));
|
|
|
|
// Sauvegarder si base64
|
|
if (exportResult?.imageData || exportResult?.data) {
|
|
const b64 = exportResult.imageData || exportResult.data;
|
|
const buf = Buffer.from(b64, 'base64');
|
|
fs.writeFileSync('/home/node/.openclaw/workspace/affiche-soldes.png', buf);
|
|
console.log('✅ Sauvegardé: affiche-soldes.png', buf.length, 'bytes');
|
|
} else if (exportResult?.url) {
|
|
console.log('URL export:', exportResult.url);
|
|
} else {
|
|
console.log('Format inattendu:', JSON.stringify(exportResult).slice(0, 500));
|
|
}
|