chat: Move Pad chat methods to `chat.js`

rhansen-chat
Richard Hansen 2022-04-08 03:46:47 -04:00
parent 2d3418caf7
commit cdea600acc
4 changed files with 64 additions and 31 deletions

View File

@ -93,6 +93,9 @@
`authorId` context property instead. Also, the hook now runs asynchronously.
* Chat API deprecations and removals (no replacements planned):
* Server-side:
* The `Pad.appendChatMessage()` method is deprecated.
* The `Pad.getChatMessage()` method is deprecated.
* The `Pad.getChatMessages()` method is deprecated.
* The `sendChatMessageToPadClients()` function in
`src/node/handler/PadMessageHandler.js` is deprecated.
* Client-side:

View File

@ -4,17 +4,53 @@ const ChatMessage = require('../static/js/ChatMessage');
const api = require('./db/API');
const authorManager = require('./db/AuthorManager');
const hooks = require('../static/js/pluginfw/hooks.js');
const pad = require('./db/Pad');
const padManager = require('./db/PadManager');
const padMessageHandler = require('./handler/PadMessageHandler');
let socketio;
const appendChatMessage = async (pad, msg) => {
pad.chatHead++;
await Promise.all([
// Don't save the display name in the database because the user can change it at any time. The
// `displayName` property will be populated with the current value when the message is read from
// the database.
pad.db.set(`pad:${pad.id}:chat:${pad.chatHead}`, {...msg, displayName: undefined}),
pad.saveToDatabase(),
]);
};
const getChatMessage = async (pad, entryNum) => {
const entry = await pad.db.get(`pad:${pad.id}:chat:${entryNum}`);
if (entry == null) return null;
const message = ChatMessage.fromObject(entry);
message.displayName = await authorManager.getAuthorName(message.authorId);
return message;
};
const getChatMessages = async (pad, start, end) => {
const entries = await Promise.all(
[...Array(end + 1 - start).keys()].map((i) => getChatMessage(pad, start + i)));
// sort out broken chat entries
// it looks like in happened in the past that the chat head was
// incremented, but the chat message wasn't added
return entries.filter((entry) => {
const pass = (entry != null);
if (!pass) {
console.warn(`WARNING: Found broken chat entry in pad ${pad.id}`);
}
return pass;
});
};
const sendChatMessageToPadClients = async (message, padId) => {
const pad = await padManager.getPad(padId, null, message.authorId);
await hooks.aCallAll('chatNewMessage', {message, pad, padId});
// pad.appendChatMessage() ignores the displayName property so we don't need to wait for
// appendChatMessage() ignores the displayName property so we don't need to wait for
// authorManager.getAuthorName() to resolve before saving the message to the database.
const promise = pad.appendChatMessage(message);
const promise = appendChatMessage(pad, message);
message.displayName = await authorManager.getAuthorName(message.authorId);
socketio.sockets.in(padId).json.send({
type: 'COLLABROOM',
@ -91,7 +127,7 @@ exports.handleMessage = async (hookName, {message, sessionInfo, socket}) => {
type: 'COLLABROOM',
data: {
type: 'CHAT_MESSAGES',
messages: await pad.getChatMessages(start, end),
messages: await getChatMessages(pad, start, end),
},
});
break;
@ -107,9 +143,16 @@ exports.socketio = (hookName, {io}) => {
};
api.registerChatHandlers({
getChatMessages,
sendChatMessageToPadClients,
});
pad.registerLegacyChatMethodHandlers({
appendChatMessage,
getChatMessage,
getChatMessages,
});
padMessageHandler.registerLegacyChatHandlers({
sendChatMessageToPadClients,
});

View File

@ -338,7 +338,7 @@ exports.getChatHistory = async (padID, start, end) => {
}
// the the whole message-log and return it to the client
const messages = await pad.getChatMessages(start, end);
const messages = await chat.getChatMessages(pad, start, end);
return {messages};
};

View File

@ -22,6 +22,10 @@ const hooks = require('../../static/js/pluginfw/hooks');
const {padutils: {warnDeprecated}} = require('../../static/js/pad_utils');
const promises = require('../utils/promises');
let chat = null;
exports.registerLegacyChatMethodHandlers = (handlers) => chat = handlers;
/**
* Copied from the Etherpad source code. It converts Windows line breaks to Unix
* line breaks and convert Tabs to spaces
@ -287,6 +291,7 @@ class Pad {
/**
* Adds a chat message to the pad, including saving it to the database.
*
* @deprecated
* @param {(ChatMessage|string)} msgOrText - Either a chat message object (recommended) or a
* string containing the raw text of the user's chat message (deprecated).
* @param {?string} [authorId] - The user's author ID. Deprecated; use `msgOrText.authorId`
@ -295,31 +300,24 @@ class Pad {
* `msgOrText.time` instead.
*/
async appendChatMessage(msgOrText, authorId = null, time = null) {
warnDeprecated('Pad.appendChatMessage() is deprecated');
const msg =
msgOrText instanceof ChatMessage ? msgOrText : new ChatMessage(msgOrText, authorId, time);
this.chatHead++;
await Promise.all([
// Don't save the display name in the database because the user can change it at any time. The
// `displayName` property will be populated with the current value when the message is read
// from the database.
this.db.set(`pad:${this.id}:chat:${this.chatHead}`, {...msg, displayName: undefined}),
this.saveToDatabase(),
]);
await chat.appendChatMessage(this, msg);
}
/**
* @deprecated
* @param {number} entryNum - ID of the desired chat message.
* @returns {?ChatMessage}
*/
async getChatMessage(entryNum) {
const entry = await this.db.get(`pad:${this.id}:chat:${entryNum}`);
if (entry == null) return null;
const message = ChatMessage.fromObject(entry);
message.displayName = await authorManager.getAuthorName(message.authorId);
return message;
warnDeprecated('Pad.getChatMessage() is deprecated');
return await chat.getChatMessage(this, entryNum);
}
/**
* @deprecated
* @param {number} start - ID of the first desired chat message.
* @param {number} end - ID of the last desired chat message.
* @returns {ChatMessage[]} Any existing messages with IDs between `start` (inclusive) and `end`
@ -327,19 +325,8 @@ class Pad {
* interval as is typical in code.
*/
async getChatMessages(start, end) {
const entries =
await Promise.all(Stream.range(start, end + 1).map(this.getChatMessage.bind(this)));
// sort out broken chat entries
// it looks like in happened in the past that the chat head was
// incremented, but the chat message wasn't added
return entries.filter((entry) => {
const pass = (entry != null);
if (!pass) {
console.warn(`WARNING: Found broken chat entry in pad ${this.id}`);
}
return pass;
});
warnDeprecated('Pad.getChatMessages() is deprecated');
return await chat.getChatMessages(this, start, end);
}
async init(text, authorId = '') {
@ -709,7 +696,7 @@ class Pad {
const chats = Stream.range(0, this.chatHead + 1)
.map(async (c) => {
try {
const msg = await this.getChatMessage(c);
const msg = await chat.getChatMessage(this, c);
assert(msg != null);
assert(msg instanceof ChatMessage);
} catch (err) {