refactor(socket.io): deprecate SocketModules.chats.canMessage and .markAllRead with no alternative. deprecate .getRecentChats in favour of api.chats.list

This commit is contained in:
Julian Lam
2023-11-13 15:35:46 -05:00
parent eebea4df2e
commit a4133500fe
8 changed files with 65 additions and 37 deletions

View File

@@ -4,17 +4,29 @@ get:
summary: list recent chat rooms summary: list recent chat rooms
description: This operation lists recently used chat rooms that the calling user is a part of description: This operation lists recently used chat rooms that the calling user is a part of
parameters: parameters:
- in: query
name: start
schema:
type: number
description: >
The start index from which chat rooms will be displayed.
e.g. `start` of `10` with `perPage` of 10 would result in the 10th to 19th chat rooms being returned
example: 20
- in: query - in: query
name: perPage name: perPage
schema: schema:
type: number type: number
description: The number of chat rooms displayed per page description: The number of chat rooms to be displayed per page
required: false
example: 20 example: 20
- in: query - in: query
name: page name: page
schema: schema:
type: number type: number
description: The page number description: >
***Deprecated*** — The page number.
This parameter is supeceded by `start`, and will stop working in NodeBB v4.
example: 1 example: 1
responses: responses:
'200': '200':

View File

@@ -29,29 +29,25 @@ define('forum/chats/recent', ['alerts', 'api', 'chat'], function (alerts, api, c
}); });
}; };
function loadMoreRecentChats() { async function loadMoreRecentChats() {
const recentChats = $('[component="chat/recent"]'); const recentChats = $('[component="chat/recent"]');
if (recentChats.attr('loading')) { if (recentChats.attr('loading')) {
return; return;
} }
recentChats.attr('loading', 1); recentChats.attr('loading', 1);
socket.emit('modules.chats.getRecentChats', { app.get(`/chats`, {
uid: ajaxify.data.uid, uid: ajaxify.data.uid,
after: recentChats.attr('data-nextstart'), after: recentChats.attr('data-nextstart'),
}, function (err, data) { }).then(({ rooms, nextStart }) => {
if (err) { if (rooms.length) {
return alerts.error(err); onRecentChatsLoaded({ rooms, nextStart }, function () {
}
if (data && data.rooms.length) {
onRecentChatsLoaded(data, function () {
recentChats.removeAttr('loading'); recentChats.removeAttr('loading');
recentChats.attr('data-nextstart', data.nextStart); recentChats.attr('data-nextstart', nextStart);
}); });
} else { } else {
recentChats.removeAttr('loading'); recentChats.removeAttr('loading');
} }
}); }).catch(alerts.error);
} }
function onRecentChatsLoaded(data, callback) { function onRecentChatsLoaded(data, callback) {

View File

@@ -79,13 +79,10 @@ define('chat', [
}; };
module.loadChatsDropdown = function (chatsListEl) { module.loadChatsDropdown = function (chatsListEl) {
socket.emit('modules.chats.getRecentChats', { api.get('/chats', {
uid: app.user.uid, uid: app.user.uid,
after: 0, after: 0,
}, function (err, data) { }).then((data) => {
if (err) {
return alerts.error(err);
}
const rooms = data.rooms.map((room) => { const rooms = data.rooms.map((room) => {
if (room && room.teaser) { if (room && room.teaser) {
room.teaser.timeagoLong = $.timeago(new Date(parseInt(room.teaser.timestamp, 10))); room.teaser.timeagoLong = $.timeago(new Date(parseInt(room.teaser.timestamp, 10)));
@@ -123,15 +120,17 @@ define('chat', [
listEl.addEventListener('click', onMarkReadClicked); listEl.addEventListener('click', onMarkReadClicked);
$('[component="chats/mark-all-read"]').off('click').on('click', async function () { $('[component="chats/mark-all-read"]').off('click').on('click', async function () {
await socket.emit('modules.chats.markAllRead'); const chatEls = document.querySelectorAll('[component="chat/list"] [data-roomid]');
if (ajaxify.data.template.chats) { await Promise.all(Array.prototype.map.call(chatEls, async (el) => {
$('[component="chat/nav-wrapper"] [data-roomid]').each((i, el) => { const roomId = el.getAttribute('data-roomid');
await api.del(`/chats/${roomId}/state`);
if (ajaxify.data.template.chats) {
module.markChatElUnread($(el), false); module.markChatElUnread($(el), false);
}); }
} }));
}); });
}); });
}); }).catch(alerts.error);
}; };
function onMarkReadClicked(e) { function onMarkReadClicked(e) {

View File

@@ -1,6 +1,7 @@
'use strict'; 'use strict';
const validator = require('validator'); const validator = require('validator');
const winston = require('winston');
const db = require('../database'); const db = require('../database');
const user = require('../user'); const user = require('../user');
@@ -32,12 +33,14 @@ async function rateLimitExceeded(caller, field) {
return false; return false;
} }
chatsAPI.list = async (caller, { page, perPage }) => { chatsAPI.list = async (caller, { uid, start, stop, page, perPage }) => {
const start = Math.max(0, page - 1) * perPage; if (!start && !stop && page) {
const stop = start + perPage; winston.warn('[api/chats] Sending `page` and `perPage` to .list() is deprecated in favour of `start` and `stop`. The deprecated parameters will be removed in v4.');
const { rooms } = await messaging.getRecentChats(caller.uid, caller.uid, start, stop); start = Math.max(0, page - 1) * perPage;
stop = start + perPage - 1;
}
return { rooms }; return await messaging.getRecentChats(caller.uid, uid || caller.uid, start, stop);
}; };
chatsAPI.create = async function (caller, data) { chatsAPI.create = async function (caller, data) {

View File

@@ -6,11 +6,22 @@ const helpers = require('../helpers');
const Chats = module.exports; const Chats = module.exports;
Chats.list = async (req, res) => { Chats.list = async (req, res) => {
const page = (isFinite(req.query.page) && parseInt(req.query.page, 10)) || 1; let stop;
const perPage = (isFinite(req.query.perPage) && parseInt(req.query.perPage, 10)) || 20; let { page, perPage, start, uid } = req.query;
const { rooms } = await api.chats.list(req, { page, perPage }); ([page, perPage, start, uid] = [page, perPage, start, uid].map(value => isFinite(value) && parseInt(value, 10)));
page = page || 1;
perPage = perPage || 20;
helpers.formatApiResponse(200, res, { rooms }); // start supercedes page
if (start) {
stop = start + perPage - 1;
} else {
start = Math.max(0, page - 1) * perPage;
stop = start + perPage - 1;
}
const { rooms, nextStart } = await api.chats.list(req, { start, stop, uid });
helpers.formatApiResponse(200, res, { rooms, nextStart });
}; };
Chats.create = async (req, res) => { Chats.create = async (req, res) => {

View File

@@ -173,7 +173,7 @@ Messaging.getPublicRooms = async (callerUid, uid) => {
Messaging.getRecentChats = async (callerUid, uid, start, stop) => { Messaging.getRecentChats = async (callerUid, uid, start, stop) => {
const ok = await canGet('filter:messaging.canGetRecentChats', callerUid, uid); const ok = await canGet('filter:messaging.canGetRecentChats', callerUid, uid);
if (!ok) { if (!ok) {
return null; throw new Error('[[error:no-privileges]]');
} }
const roomIds = await db.getSortedSetRevRange(`uid:${uid}:chat:rooms`, start, stop); const roomIds = await db.getSortedSetRevRange(`uid:${uid}:chat:rooms`, start, stop);

View File

@@ -45,22 +45,29 @@ SocketModules.chats.isDnD = async function (socket, uid) {
}; };
SocketModules.chats.canMessage = async function (socket, roomId) { SocketModules.chats.canMessage = async function (socket, roomId) {
sockets.warnDeprecated(socket);
await Messaging.canMessageRoom(socket.uid, roomId); await Messaging.canMessageRoom(socket.uid, roomId);
}; };
SocketModules.chats.markAllRead = async function (socket) { SocketModules.chats.markAllRead = async function (socket) {
// no v3 method ? sockets.warnDeprecated(socket);
await Messaging.markAllRead(socket.uid); await Messaging.markAllRead(socket.uid);
Messaging.pushUnreadCount(socket.uid); Messaging.pushUnreadCount(socket.uid);
}; };
SocketModules.chats.getRecentChats = async function (socket, data) { SocketModules.chats.getRecentChats = async function (socket, data) {
sockets.warnDeprecated(socket, 'GET /api/v3/chats');
if (!data || !utils.isNumber(data.after) || !utils.isNumber(data.uid)) { if (!data || !utils.isNumber(data.after) || !utils.isNumber(data.uid)) {
throw new Error('[[error:invalid-data]]'); throw new Error('[[error:invalid-data]]');
} }
const start = parseInt(data.after, 10); const start = parseInt(data.after, 10);
const stop = start + 9; const stop = start + 9;
return await Messaging.getRecentChats(socket.uid, data.uid, start, stop); const { uid } = data;
return api.chats.list(socket, { uid, start, stop });
}; };
SocketModules.chats.hasPrivateChat = async function (socket, uid) { SocketModules.chats.hasPrivateChat = async function (socket, uid) {

View File

@@ -80,7 +80,7 @@ describe('Messaging Library', () => {
meta.configs.chatMessageDelay = chatMessageDelay; meta.configs.chatMessageDelay = chatMessageDelay;
}); });
describe('.canMessage()', () => { describe('.canMessageUser()', () => {
it('should allow messages to be sent to an unrestricted user', (done) => { it('should allow messages to be sent to an unrestricted user', (done) => {
Messaging.canMessageUser(mocks.users.baz.uid, mocks.users.herp.uid, (err) => { Messaging.canMessageUser(mocks.users.baz.uid, mocks.users.herp.uid, (err) => {
assert.ifError(err); assert.ifError(err);