diff --git a/src/ep.json b/src/ep.json index 7c76b4dd766..e8ca7f95626 100644 --- a/src/ep.json +++ b/src/ep.json @@ -24,7 +24,9 @@ "clientVars": "ep_etherpad-lite/node/chat", "eejsBlock_mySettings": "ep_etherpad-lite/node/chat", "eejsBlock_stickyContainer": "ep_etherpad-lite/node/chat", + "exportEtherpad": "ep_etherpad-lite/node/chat", "handleMessage": "ep_etherpad-lite/node/chat", + "importEtherpad": "ep_etherpad-lite/node/chat", "padCheck": "ep_etherpad-lite/node/chat", "padCopy": "ep_etherpad-lite/node/chat", "padLoad": "ep_etherpad-lite/node/chat", diff --git a/src/node/chat.js b/src/node/chat.js index dc9f0ef1744..44ad045962a 100644 --- a/src/node/chat.js +++ b/src/node/chat.js @@ -2,6 +2,7 @@ const ChatMessage = require('../static/js/ChatMessage'); const CustomError = require('./utils/customError'); +const Stream = require('./utils/Stream'); const api = require('./db/API'); const assert = require('assert').strict; const authorManager = require('./db/AuthorManager'); @@ -107,6 +108,21 @@ exports.eejsBlock_stickyContainer = (hookName, context) => { /* eslint-enable max-len */ }; +exports.exportEtherpad = async (hookName, {pad, data, dstPadId}) => { + const ops = (function* () { + const {chatHead = -1} = pad; + data[`pad:${dstPadId}`].chatHead = chatHead; + for (let i = 0; i <= chatHead; ++i) { + yield (async () => { + const v = await pad.db.get(`pad:${pad.id}:chat:${i}`); + if (v == null) return; + data[`pad:${dstPadId}:chat:${i}`] = v; + })(); + } + })(); + for (const op of new Stream(ops).batch(100).buffer(99)) await op; +}; + exports.handleMessage = async (hookName, {message, sessionInfo, socket}) => { const {authorId, padId, readOnly} = sessionInfo; if (message.type !== 'COLLABROOM' || readOnly) return; @@ -141,6 +157,19 @@ exports.handleMessage = async (hookName, {message, sessionInfo, socket}) => { return null; // Important! Returning null (not undefined!) stops further processing. }; +exports.importEtherpad = async (hookName, {pad, data, srcPadId}) => { + const ops = (function* () { + const {chatHead = -1} = data[`pad:${srcPadId}`]; + pad.chatHead = chatHead; + for (let i = 0; i <= chatHead; ++i) { + const v = data[`pad:${srcPadId}:chat:${i}`]; + if (v == null) continue; + yield pad.db.set(`pad:${pad.id}:chat:${i}`, v); + } + })(); + for (const op of new Stream(ops).batch(100).buffer(99)) await op; +}; + exports.padCheck = async (hookName, {pad}) => { assert(Number.isInteger(pad.chatHead)); assert(pad.chatHead >= -1); diff --git a/src/node/utils/ExportEtherpad.js b/src/node/utils/ExportEtherpad.js index e20739ad3ef..dfb486e2e7e 100644 --- a/src/node/utils/ExportEtherpad.js +++ b/src/node/utils/ExportEtherpad.js @@ -50,7 +50,6 @@ exports.getPadRaw = async (padId, readOnlyId) => { })()]; } for (let i = 0; i <= pad.head; ++i) yield [`${dstPfx}:revs:${i}`, pad.getRevision(i)]; - for (let i = 0; i <= pad.chatHead; ++i) yield [`${dstPfx}:chat:${i}`, pad.getChatMessage(i)]; for (const gen of pluginRecords) yield* gen; })(); const data = {[dstPfx]: pad}; diff --git a/src/node/utils/ImportEtherpad.js b/src/node/utils/ImportEtherpad.js index 6d858c7bdeb..46c296fc02b 100644 --- a/src/node/utils/ImportEtherpad.js +++ b/src/node/utils/ImportEtherpad.js @@ -74,7 +74,9 @@ exports.setPadRaw = async (padId, r, authorId = '') => { return; } value.padIDs = {[padId]: 1}; - } else if (padKeyPrefixes.includes(prefix)) { + } else if (padKeyPrefixes.includes(prefix) && + // Chat message handling was moved to the importEtherpad hook. + (keyParts[0] !== 'pad' || keyParts[2] !== 'chat')) { checkOriginalPadId(id); if (prefix === 'pad' && keyParts.length === 2) { const pool = new AttributePool().fromJsonable(value.pool);