'use strict'; const { webdavGet, webdavPut, webdavPropfindFileId } = require('./webdav'); const { ocsRequest } = require('./ocs'); const { convertTo, extractStructure, transformStructure } = require('./collabora'); const { resolveDestNcPath, assertSafeDestination, contentTypeForFormat, replaceExtension, basenameFromNcPath, normalizeNcPath, pickMsgField } = require('./utils'); async function resolveFileId(config, msg) { if (msg.fileId) { return parseInt(msg.fileId, 10); } const ncPath = pickMsgField(msg, 'ncPath'); if (ncPath) { return webdavPropfindFileId(config, ncPath); } throw new Error('Ange msg.fileId eller msg.ncPath'); } async function loadSourceBuffer(config, msg) { if (msg.payload !== undefined && msg.payload !== null && msg.payload !== '') { if (Buffer.isBuffer(msg.payload)) { return { buffer: msg.payload, filename: msg.filename || 'payload.bin', ncPath: msg.ncPath }; } const text = typeof msg.payload === 'string' ? msg.payload : JSON.stringify(msg.payload); return { buffer: Buffer.from(text, 'utf8'), filename: msg.filename || 'payload.txt', ncPath: msg.ncPath }; } const ncPath = pickMsgField(msg, 'ncPath'); if (!ncPath) { throw new Error('Ange msg.ncPath eller msg.payload'); } const file = await webdavGet(config, ncPath); return file; } async function saveResult(config, msg, buffer, format, sourceNcPath) { const destNcPath = assertSafeDestination( resolveDestNcPath(msg, sourceNcPath, format), msg ); const contentType = contentTypeForFormat(format); const putResult = await webdavPut(config, destNcPath, buffer, contentType); return { destNcPath: putResult.destNcPath, filename: putResult.filename, contentType, statusCode: putResult.statusCode }; } async function ncFileConvert(config, msg, format) { const source = await loadSourceBuffer(config, msg); const extraFields = []; if (msg.templateNcPath) { const tpl = await webdavGet(config, msg.templateNcPath); extraFields.push({ name: 'template', buffer: tpl.buffer, filename: tpl.filename }); } if (msg.compareNcPath) { const cmp = await webdavGet(config, msg.compareNcPath); extraFields.push({ name: 'compare', buffer: cmp.buffer, filename: cmp.filename }); } const converted = await convertTo(config, { buffer: source.buffer, filename: source.filename, format, extraFields }); const saved = await saveResult(config, msg, converted.buffer, format, source.ncPath); return { ...saved, format, sourceNcPath: source.ncPath, payload: converted.buffer }; } async function ncFileToPdf(config, msg) { return ncFileConvert(config, msg, 'pdf'); } async function ncFileToPng(config, msg) { return ncFileConvert(config, msg, 'png'); } async function ncFileToHtml(config, msg) { return ncFileConvert(config, msg, 'html'); } async function htmlToOffice(config, msg) { const format = (pickMsgField(msg, 'format') || 'docx').toLowerCase(); const source = await loadSourceBuffer(config, msg); let buffer = source.buffer; let filename = source.filename || 'content.html'; if (!filename.endsWith('.html') && !filename.endsWith('.htm')) { filename = 'content.html'; } const extraFields = []; if (msg.templateNcPath) { const tpl = await webdavGet(config, msg.templateNcPath); extraFields.push({ name: 'template', buffer: tpl.buffer, filename: tpl.filename }); } const converted = await convertTo(config, { buffer, filename, format, extraFields }); const saved = await saveResult(config, msg, converted.buffer, format, msg.ncPath || filename); return { ...saved, format, payload: converted.buffer }; } async function fillTemplateSave(config, msg) { const fileId = await resolveFileId(config, msg); const fields = msg.fields || msg.transform; if (!fields) { throw new Error('Ange msg.fields eller msg.transform för mallifyllning'); } const destination = msg.destNcPath ? assertSafeDestination(normalizeNcPath(msg.destNcPath), msg) : undefined; const body = { fields }; if (destination) { body.destination = destination.startsWith('/') ? destination.slice(1) : destination; } await ocsRequest(config, { method: 'POST', path: `/ocs/v2.php/apps/richdocuments/api/v1/template/fields/fill/${fileId}`, body }); const destNcPath = destination || resolveDestNcPath(msg, msg.ncPath, 'docx'); return { fileId, destNcPath: normalizeNcPath('/' + (body.destination || destNcPath.replace(/^\//, ''))), statusCode: 200 }; } async function compareVersionsPdf(config, msg) { if (!msg.compareNcPath) { throw new Error('compareVersionsPdf kräver msg.compareNcPath (äldre version)'); } msg.format = 'pdf'; return ncFileToPdf(config, msg); } async function extractToPayload(config, msg) { if (msg.fileId) { const res = await ocsRequest(config, { method: 'GET', path: `/ocs/v2.php/apps/richdocuments/api/v1/template/fields/extract/${msg.fileId}` }); return { fields: res.data, fileId: msg.fileId }; } const source = await loadSourceBuffer(config, msg); const filter = msg.filter || 'contentcontrol'; const structure = await extractStructure(config, { buffer: source.buffer, filename: source.filename, filter }); return { structure, sourceNcPath: source.ncPath }; } async function createAssetLink(config, msg) { const assetPath = pickMsgField(msg, 'ncPath'); if (!assetPath) { throw new Error('createAssetLink kräver msg.ncPath'); } const relPath = normalizeNcPath(assetPath); const { requestBuffer } = require('./http-client'); const base = config.nextcloudUrl.replace(/\/$/, ''); const token = Buffer.from(`${config.username}:${config.password}`).toString('base64'); const res = await requestBuffer({ url: `${base}/index.php/apps/richdocuments/assets`, method: 'POST', headers: { Authorization: `Basic ${token}`, 'OCS-APIRequest': 'true', 'Content-Type': 'application/json', Accept: 'application/json' }, body: Buffer.from(JSON.stringify({ path: relPath }), 'utf8'), rejectUnauthorized: config.verifyTls !== false && config.verifyTls !== 'false' }); if (res.statusCode < 200 || res.statusCode >= 300) { throw new Error(`assets:create misslyckades (${res.statusCode})`); } const json = JSON.parse(res.body.toString('utf8')); return { assetUrl: json.url || json.assetUrl || json, ncPath: relPath }; } module.exports = { ncFileToPdf, ncFileToPng, ncFileToHtml, htmlToOffice, fillTemplateSave, compareVersionsPdf, extractToPayload, createAssetLink, loadSourceBuffer, saveResult, resolveFileId };