mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-01-01 13:20:41 +01:00
feat: #11881, limit room names
This commit is contained in:
@@ -64,6 +64,7 @@
|
||||
"maximumAboutMeLength": 1000,
|
||||
"maximumUsersInChatRoom": 0,
|
||||
"maximumChatMessageLength": 1000,
|
||||
"maximumChatRoomNameLength": 50,
|
||||
"maximumProfileImageSize": 256,
|
||||
"maximumCoverImageSize": 2048,
|
||||
"profileImageDimension": 200,
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"disable-editing": "Disable chat message editing/deletion",
|
||||
"disable-editing-help": "Administrators and global moderators are exempt from this restriction",
|
||||
"max-length": "Maximum length of chat messages",
|
||||
"max-chat-room-name-length": "Maximum length of chat room names",
|
||||
"max-room-size": "Maximum number of users in chat rooms",
|
||||
"delay": "Time between chat messages in milliseconds",
|
||||
"notification-delay": "Notification delay for chat messages. (0 for no delay)",
|
||||
|
||||
@@ -191,7 +191,7 @@
|
||||
"chat-room-does-not-exist": "Chat room does not exist.",
|
||||
"cant-add-users-to-chat-room": "Can't add users to chat room.",
|
||||
"cant-remove-users-from-chat-room": "Can't remove users from chat room.",
|
||||
"chat-room-name-too-long": "Chat room name too long.",
|
||||
"chat-room-name-too-long": "Chat room name too long. Names can't be longer than %1 characters.",
|
||||
|
||||
"already-voting-for-this-post": "You have already voted for this post.",
|
||||
"reputation-system-disabled": "Reputation system is disabled.",
|
||||
|
||||
@@ -396,29 +396,30 @@ define('forum/chats', [
|
||||
});
|
||||
};
|
||||
|
||||
Chats.addRenameHandler = function (roomId, buttonEl, roomName) {
|
||||
let modal;
|
||||
|
||||
buttonEl.on('click', function () {
|
||||
app.parseAndTranslate('modals/rename-room', {
|
||||
name: roomName || ajaxify.data.roomName,
|
||||
}, function (html) {
|
||||
modal = bootbox.dialog({
|
||||
title: '[[modules:chat.rename-room]]',
|
||||
message: html,
|
||||
onEscape: true,
|
||||
buttons: {
|
||||
save: {
|
||||
label: '[[global:save]]',
|
||||
className: 'btn-primary',
|
||||
callback: function () {
|
||||
api.put(`/chats/${roomId}`, {
|
||||
name: modal.find('#roomName').val(),
|
||||
}).catch(alerts.error);
|
||||
},
|
||||
Chats.addRenameHandler = function (roomId, buttonEl) {
|
||||
buttonEl.on('click', async function () {
|
||||
const { roomName } = await api.get(`/chats/${roomId}`);
|
||||
const html = await app.parseAndTranslate('modals/rename-room', {
|
||||
name: roomName,
|
||||
});
|
||||
const modal = bootbox.dialog({
|
||||
title: '[[modules:chat.rename-room]]',
|
||||
message: html,
|
||||
onEscape: true,
|
||||
buttons: {
|
||||
save: {
|
||||
label: '[[global:save]]',
|
||||
className: 'btn-primary',
|
||||
callback: function () {
|
||||
api.put(`/chats/${roomId}`, {
|
||||
name: modal.find('#roomName').val(),
|
||||
}).then(() => {
|
||||
modal.modal('hide');
|
||||
}).catch(alerts.error);
|
||||
return false;
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -586,7 +587,15 @@ define('forum/chats', [
|
||||
if (roomEl.length) {
|
||||
const titleEl = roomEl.find('[component="chat/room/title"]');
|
||||
ajaxify.data.roomName = data.newName;
|
||||
titleEl.text(data.newName);
|
||||
titleEl.translateText(data.newName ? data.newName : ajaxify.data.usernames);
|
||||
}
|
||||
const titleEl = $(`[component="chat/main-wrapper"][data-roomid="${data.roomId}"] [component="chat/header/title"]`);
|
||||
if (titleEl.length) {
|
||||
titleEl.html(
|
||||
data.newName ?
|
||||
`<i class="fa ${ajaxify.data.icon} text-muted"></i> ${data.newName}` :
|
||||
ajaxify.data.chatWithMessage
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -232,9 +232,18 @@ define('chat', [
|
||||
};
|
||||
|
||||
module.onRoomRename = function (data) {
|
||||
const newTitle = $('<div></div>').html(data.newName).text();
|
||||
const modal = module.getModal(data.roomId);
|
||||
modal.find('[component="chat/room/name"]').text(newTitle);
|
||||
const titleEl = modal.find('[component="chat/room/name"]');
|
||||
const icon = titleEl.attr('data-icon');
|
||||
if (titleEl.length) {
|
||||
titleEl.html(
|
||||
data.newName ?
|
||||
`<i class="fa ${icon} text-muted"></i> ${data.newName}` :
|
||||
data.chatWithMessage
|
||||
);
|
||||
}
|
||||
|
||||
const newTitle = $('<div></div>').html(data.newName).text();
|
||||
taskbar.update('chat', modal.attr('data-uuid'), {
|
||||
title: newTitle,
|
||||
});
|
||||
@@ -347,7 +356,7 @@ define('chat', [
|
||||
});
|
||||
|
||||
Chats.addActionHandlers(chatModal.find('[component="chat/messages"]'), roomId);
|
||||
Chats.addRenameHandler(roomId, chatModal.find('[data-action="rename"]'), data.roomName);
|
||||
Chats.addRenameHandler(roomId, chatModal.find('[data-action="rename"]'));
|
||||
Chats.addLeaveHandler(roomId, chatModal.find('[data-action="leave"]'));
|
||||
Chats.addDeleteHandler(roomId, chatModal.find('[data-action="delete"]'));
|
||||
Chats.addSendHandlers(roomId, chatModal.find('.chat-input'), chatModal.find('[data-action="send"]'));
|
||||
|
||||
@@ -103,17 +103,10 @@ chatsAPI.update = async (caller, data) => {
|
||||
}
|
||||
|
||||
if (data.hasOwnProperty('name')) {
|
||||
if (!data.name) {
|
||||
if (!data.name && data.name !== '') {
|
||||
throw new Error('[[error:invalid-data]]');
|
||||
}
|
||||
await messaging.renameRoom(caller.uid, data.roomId, data.name);
|
||||
const ioRoom = require('../socket.io').in(`chat_room_${data.roomId}`);
|
||||
if (ioRoom) {
|
||||
ioRoom.emit('event:chats.roomRename', {
|
||||
roomId: data.roomId,
|
||||
newName: validator.escape(String(data.name)),
|
||||
});
|
||||
}
|
||||
}
|
||||
const [roomData, isAdmin] = await Promise.all([
|
||||
messaging.getRoomData(data.roomId),
|
||||
@@ -130,9 +123,20 @@ chatsAPI.update = async (caller, data) => {
|
||||
if (data.hasOwnProperty('notificationSetting') && isAdmin) {
|
||||
await db.setObjectField(`chat:room:${data.roomId}`, 'notificationSetting', data.notificationSetting);
|
||||
}
|
||||
return messaging.loadRoom(caller.uid, {
|
||||
const loadedRoom = await messaging.loadRoom(caller.uid, {
|
||||
roomId: data.roomId,
|
||||
});
|
||||
if (data.hasOwnProperty('name')) {
|
||||
const ioRoom = require('../socket.io').in(`chat_room_${data.roomId}`);
|
||||
if (ioRoom) {
|
||||
ioRoom.emit('event:chats.roomRename', {
|
||||
roomId: data.roomId,
|
||||
newName: validator.escape(String(data.name)),
|
||||
chatWithMessage: loadedRoom.chatWithMessage,
|
||||
});
|
||||
}
|
||||
}
|
||||
return loadedRoom;
|
||||
};
|
||||
|
||||
chatsAPI.rename = async (caller, data) => {
|
||||
|
||||
@@ -213,8 +213,8 @@ Messaging.getRecentChats = async (callerUid, uid, start, stop) => {
|
||||
});
|
||||
room.users = room.users.filter(user => user && parseInt(user.uid, 10));
|
||||
room.lastUser = room.users[0];
|
||||
room.usernames = Messaging.generateUsernames(room.users, uid);
|
||||
room.chatWithMessage = await Messaging.generateChatWithMessage(room.users, uid, results.settings.userLang);
|
||||
room.usernames = Messaging.generateUsernames(room, uid);
|
||||
room.chatWithMessage = await Messaging.generateChatWithMessage(room, uid, results.settings.userLang);
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -228,21 +228,21 @@ Messaging.getRecentChats = async (callerUid, uid, start, stop) => {
|
||||
});
|
||||
};
|
||||
|
||||
Messaging.generateUsernames = function (users, excludeUid) {
|
||||
users = users.filter(u => u && parseInt(u.uid, 10) !== excludeUid);
|
||||
Messaging.generateUsernames = function (room, excludeUid) {
|
||||
const users = room.users.filter(u => u && parseInt(u.uid, 10) !== excludeUid);
|
||||
const usernames = users.map(u => u.username);
|
||||
if (users.length > 3) {
|
||||
return translator.compile(
|
||||
'modules:chat.usernames-and-x-others',
|
||||
usernames.slice(0, 2).join(', '),
|
||||
usernames.length - 2
|
||||
room.userCount - 2
|
||||
);
|
||||
}
|
||||
return usernames.join(', ');
|
||||
};
|
||||
|
||||
Messaging.generateChatWithMessage = async function (users, callerUid, userLang) {
|
||||
users = users.filter(u => u && parseInt(u.uid, 10) !== callerUid);
|
||||
Messaging.generateChatWithMessage = async function (room, callerUid, userLang) {
|
||||
const users = room.users.filter(u => u && parseInt(u.uid, 10) !== callerUid);
|
||||
const usernames = users.map(u => `<a href="${relative_path}/uid/${u.uid}">${u.username}</a>`);
|
||||
let compiled = '';
|
||||
if (!users.length) {
|
||||
@@ -252,7 +252,7 @@ Messaging.generateChatWithMessage = async function (users, callerUid, userLang)
|
||||
compiled = translator.compile(
|
||||
'modules:chat.chat-with-usernames-and-x-others',
|
||||
usernames.slice(0, 2).join(', '),
|
||||
usernames.length - 2
|
||||
room.userCount - 2
|
||||
);
|
||||
} else {
|
||||
compiled = translator.compile(
|
||||
|
||||
@@ -78,6 +78,10 @@ module.exports = function (Messaging) {
|
||||
if (Array.isArray(data)) { // old usage second param used to be toUids
|
||||
data = { uids: data };
|
||||
}
|
||||
if (data.hasOwnProperty('roomName')) {
|
||||
checkRoomName(data.roomName);
|
||||
}
|
||||
|
||||
const now = Date.now();
|
||||
const roomId = await db.incrObjectField('global', 'nextChatRoomId');
|
||||
const room = {
|
||||
@@ -87,7 +91,7 @@ module.exports = function (Messaging) {
|
||||
};
|
||||
|
||||
if (data.hasOwnProperty('roomName') && data.roomName) {
|
||||
room.roomName = String(data.roomName);
|
||||
room.roomName = String(data.roomName).trim();
|
||||
}
|
||||
if (Array.isArray(data.groups) && data.groups.length) {
|
||||
room.groups = JSON.stringify(data.groups);
|
||||
@@ -397,13 +401,8 @@ module.exports = function (Messaging) {
|
||||
};
|
||||
|
||||
Messaging.renameRoom = async function (uid, roomId, newName) {
|
||||
if (!newName) {
|
||||
throw new Error('[[error:invalid-data]]');
|
||||
}
|
||||
newName = newName.trim();
|
||||
if (newName.length > 75) {
|
||||
throw new Error('[[error:chat-room-name-too-long]]');
|
||||
}
|
||||
newName = String(newName).trim();
|
||||
checkRoomName(newName);
|
||||
|
||||
const payload = await plugins.hooks.fire('filter:chat.renameRoom', {
|
||||
uid: uid,
|
||||
@@ -424,6 +423,15 @@ module.exports = function (Messaging) {
|
||||
});
|
||||
};
|
||||
|
||||
function checkRoomName(roomName) {
|
||||
if (!roomName && roomName !== '') {
|
||||
throw new Error('[[error:invalid-room-name]]');
|
||||
}
|
||||
if (roomName.length > meta.config.maximumChatRoomNameLength) {
|
||||
throw new Error(`[[error:chat-room-name-too-long, ${meta.config.maximumChatRoomNameLength}]]`);
|
||||
}
|
||||
}
|
||||
|
||||
Messaging.canReply = async (roomId, uid) => {
|
||||
const inRoom = await db.isSortedSetMember(`chat:room:${roomId}:uids`, uid);
|
||||
const data = await plugins.hooks.fire('filter:messaging.canReply', { uid: uid, roomId: roomId, inRoom: inRoom, canReply: inRoom });
|
||||
@@ -517,8 +525,8 @@ module.exports = function (Messaging) {
|
||||
room.canReply = canReply;
|
||||
room.groupChat = room.hasOwnProperty('groupChat') ? room.groupChat : users.length > 2;
|
||||
room.icon = Messaging.getRoomIcon(room);
|
||||
room.usernames = Messaging.generateUsernames(users, uid);
|
||||
room.chatWithMessage = await Messaging.generateChatWithMessage(users, uid, settings.userLang);
|
||||
room.usernames = Messaging.generateUsernames(room, uid);
|
||||
room.chatWithMessage = await Messaging.generateChatWithMessage(room, uid, settings.userLang);
|
||||
room.maximumUsersInChatRoom = meta.config.maximumUsersInChatRoom;
|
||||
room.maximumChatMessageLength = meta.config.maximumChatMessageLength;
|
||||
room.showUserInput = !room.maximumUsersInChatRoom || room.maximumUsersInChatRoom > 2;
|
||||
|
||||
@@ -31,6 +31,11 @@
|
||||
<input id="chatDeleteDuration" type="text" class="form-control" value="0" data-field="chatDeleteDuration">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="maximumChatRoomNameLength">[[admin/settings/chat:max-chat-room-name-length]]</label>
|
||||
<input id="maximumChatRoomNameLength" type="text" class="form-control" value="50" data-field="maximumChatRoomNameLength">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="maximumChatMessageLength">[[admin/settings/chat:max-length]]</label>
|
||||
<input id="maximumChatMessageLength" type="text" class="form-control" value="1000" data-field="maximumChatMessageLength">
|
||||
|
||||
Reference in New Issue
Block a user