chat: Allow `chatNewMessage` hook to modify more values

pull/5002/head
Richard Hansen 2021-04-08 21:39:11 -04:00 committed by webzwo0i
parent 1ad134a538
commit 74554d36a5
2 changed files with 26 additions and 23 deletions

View File

@ -294,6 +294,11 @@ Things in context:
This hook is called on the client side whenever a chat message is received from
the server. It can be used to create different notifications for chat messages.
Hoook functions can modify the `author`, `authorName`, `duration`, `sticky`,
`text`, and `timeStr` context properties to change how the message is processed.
The `text` and `timeStr` properties may contain HTML, but plugins should be
careful to sanitize any added user input to avoid introducing an XSS
vulnerability.
## collectContentPre

View File

@ -109,14 +109,6 @@ exports.chat = (() => {
// correct the time
msg.time += this._pad.clientTimeOffset;
// create the time string
let minutes = `${new Date(msg.time).getMinutes()}`;
let hours = `${new Date(msg.time).getHours()}`;
if (minutes.length === 1) minutes = `0${minutes}`;
if (hours.length === 1) hours = `0${hours}`;
const timeStr = `${hours}:${minutes}`;
// create the authorclass
if (!msg.userId) {
/*
* If, for a bug or a database corruption, the message coming from the
@ -129,25 +121,25 @@ exports.chat = (() => {
'Replacing with "unknown". This may be a bug or a database corruption.');
}
msg.userId = padutils.escapeHtml(msg.userId);
const authorClass = `author-${msg.userId.replace(/[^a-y0-9]/g, (c) => {
const authorClass = (authorId) => `author-${authorId.replace(/[^a-y0-9]/g, (c) => {
if (c === '.') return '-';
return `z${c.charCodeAt(0)}z`;
})}`;
const text = padutils.escapeHtmlWithClickableLinks(msg.text, '_blank');
const authorName = msg.userName == null ? html10n.get('pad.userlist.unnamed')
: padutils.escapeHtml(msg.userName);
// the hook args
const ctx = {
authorName,
authorName: msg.userName != null ? msg.userName : html10n.get('pad.userlist.unnamed'),
author: msg.userId,
text,
text: padutils.escapeHtmlWithClickableLinks(msg.text, '_blank'),
sticky: false,
timestamp: msg.time,
timeStr,
timeStr: (() => {
let minutes = `${new Date(msg.time).getMinutes()}`;
let hours = `${new Date(msg.time).getHours()}`;
if (minutes.length === 1) minutes = `0${minutes}`;
if (hours.length === 1) hours = `0${hours}`;
return `${hours}:${minutes}`;
})(),
duration: 4000,
};
@ -160,7 +152,7 @@ exports.chat = (() => {
// does this message contain this user's name? (is the curretn user mentioned?)
const myName = $('#myusernameedit').val();
const wasMentioned =
text.toLowerCase().indexOf(myName.toLowerCase()) !== -1 && myName !== 'undefined';
ctx.text.toLowerCase().indexOf(myName.toLowerCase()) !== -1 && myName !== 'undefined';
// If the user was mentioned, make the message sticky
if (wasMentioned && !alreadyFocused && !isHistoryAdd && !chatOpen) {
@ -171,9 +163,14 @@ exports.chat = (() => {
// Call chat message hook
hooks.aCallAll('chatNewMessage', ctx, () => {
const cls = authorClass(ctx.author);
const html =
`<p data-authorId='${msg.userId}' class='${authorClass}'><b>${authorName}:</b>` +
`<span class='time ${authorClass}'>${ctx.timeStr}</span> ${ctx.text}</p>`;
`<p data-authorId='${padutils.escapeHtml(ctx.author)}' class='${cls}'>` +
`<b>${padutils.escapeHtml(ctx.authorName)}:</b>` +
// ctx.text was HTML-escaped before calling the hook, and ctx.timeStr couldn't have had
// any HTML. Hook functions are trusted to not introduce an XSS vulnerability by adding
// unescaped user input to either ctx.text or ctx.timeStr.
`<span class='time ${cls}'>${ctx.timeStr}</span> ${ctx.text}</p>`;
if (isHistoryAdd) $(html).insertAfter('#chatloadmessagesbutton');
else $('#chattext').append(html);
@ -186,9 +183,10 @@ exports.chat = (() => {
if (!chatOpen && ctx.duration > 0) {
$.gritter.add({
// Note: ctx.authorName and ctx.text are already HTML-escaped.
text: $('<p>')
.append($('<span>').addClass('author-name').html(ctx.authorName))
.append($('<span>').addClass('author-name').text(ctx.authorName))
// ctx.text was HTML-escaped before calling the hook. Hook functions are trusted
// to not introduce an XSS vulnerability by adding unescaped user input.
.append(ctx.text),
sticky: ctx.sticky,
time: 5000,