Case-insensitive matching of moderation commands.

Also add `/subject` as alias to `/topic`
This commit is contained in:
JC Brand 2017-02-01 17:36:20 +00:00
parent 46e231b4b3
commit bcbeb8da6c
4 changed files with 73 additions and 31 deletions

View File

@ -2,6 +2,8 @@
## 3.0.0 (Unreleased) ## 3.0.0 (Unreleased)
- Use lodash instead of underscore.js [jcbrand] - Use lodash instead of underscore.js [jcbrand]
- Case insensitive matching of moderation commands. [jcbrand]
- Add `/subject` as alias to `/topic` [jcbrand]
## 2.0.5 (2017-02-01) ## 2.0.5 (2017-02-01)
- #743, #751, #753 Update to Strophe 1.2.12. SASL-EXTERNAL now has reduced priority, so it won't - #743, #751, #753 Update to Strophe 1.2.12. SASL-EXTERNAL now has reduced priority, so it won't

View File

@ -1151,6 +1151,43 @@
test_utils.clearBrowserStorage(); test_utils.clearBrowserStorage();
}); });
it("to set the room subject", mock.initConverse(function (converse) {
var sent_stanza;
test_utils.openChatRoom(converse, 'lounge', 'localhost', 'dummy');
var view = converse.chatboxviews.get('lounge@localhost');
spyOn(view, 'onMessageSubmitted').andCallThrough();
spyOn(view, 'clearChatRoomMessages');
spyOn(converse.connection, 'send').andCallFake(function (stanza) {
sent_stanza = stanza;
});
// Check the alias /topic
var $textarea = view.$el.find('.chat-textarea');
$textarea.val('/topic This is the room subject');
$textarea.trigger($.Event('keypress', {keyCode: 13}));
expect(view.onMessageSubmitted).toHaveBeenCalled();
expect(converse.connection.send).toHaveBeenCalled();
expect(sent_stanza.outerHTML).toBe(
'<message to="lounge@localhost" from="dummy@localhost/resource" type="groupchat" xmlns="jabber:client">'+
'<subject xmlns="jabber:client">This is the room subject</subject>'+
'</message>');
// Check /subject
$textarea.val('/subject This is a new subject');
$textarea.trigger($.Event('keypress', {keyCode: 13}));
expect(sent_stanza.outerHTML).toBe(
'<message to="lounge@localhost" from="dummy@localhost/resource" type="groupchat" xmlns="jabber:client">'+
'<subject xmlns="jabber:client">This is a new subject</subject>'+
'</message>');
// Check case insensitivity
$textarea.val('/Subject This is yet another subject');
$textarea.trigger($.Event('keypress', {keyCode: 13}));
expect(sent_stanza.outerHTML).toBe(
'<message to="lounge@localhost" from="dummy@localhost/resource" type="groupchat" xmlns="jabber:client">'+
'<subject xmlns="jabber:client">This is yet another subject</subject>'+
'</message>');
}));
it("to clear messages", mock.initConverse(function (converse) { it("to clear messages", mock.initConverse(function (converse) {
test_utils.openChatRoom(converse, 'lounge', 'localhost', 'dummy'); test_utils.openChatRoom(converse, 'lounge', 'localhost', 'dummy');
var view = converse.chatboxviews.get('lounge@localhost'); var view = converse.chatboxviews.get('lounge@localhost');
@ -1160,7 +1197,6 @@
view.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13})); view.$el.find('textarea.chat-textarea').trigger($.Event('keypress', {keyCode: 13}));
expect(view.onMessageSubmitted).toHaveBeenCalled(); expect(view.onMessageSubmitted).toHaveBeenCalled();
expect(view.clearChatRoomMessages).toHaveBeenCalled(); expect(view.clearChatRoomMessages).toHaveBeenCalled();
})); }));
it("to make a user an owner", mock.initConverse(function (converse) { it("to make a user an owner", mock.initConverse(function (converse) {

View File

@ -568,11 +568,12 @@
keyPressed: function (ev) { keyPressed: function (ev) {
/* Event handler for when a key is pressed in a chat box textarea. /* Event handler for when a key is pressed in a chat box textarea.
*/ */
var $textarea = $(ev.target), message; var textarea = ev.target, message;
if (ev.keyCode === KEY.ENTER) { if (ev.keyCode === KEY.ENTER) {
ev.preventDefault(); ev.preventDefault();
message = $textarea.val(); message = textarea.value;
$textarea.val('').focus(); textarea.value = '';
textarea.focus();
if (message !== '') { if (message !== '') {
this.onMessageSubmitted(message); this.onMessageSubmitted(message);
converse.emit('messageSend', message); converse.emit('messageSend', message);

View File

@ -874,17 +874,18 @@
return this.sendChatRoomMessage(text); return this.sendChatRoomMessage(text);
} }
var match = text.replace(/^\s*/, "").match(/^\/(.*?)(?: (.*))?$/) || [false, '', ''], var match = text.replace(/^\s*/, "").match(/^\/(.*?)(?: (.*))?$/) || [false, '', ''],
args = match[2] && match[2].splitOnce(' ') || []; args = match[2] && match[2].splitOnce(' ') || [],
switch (match[1]) { command = match[1].toLowerCase();
switch (command) {
case 'admin': case 'admin':
if (!this.validateRoleChangeCommand(match[1], args)) { break; } if (!this.validateRoleChangeCommand(command, args)) { break; }
this.setAffiliation('admin', this.setAffiliation('admin',
[{ 'jid': args[0], [{ 'jid': args[0],
'reason': args[1] 'reason': args[1]
}]).fail(this.onCommandError.bind(this)); }]).fail(this.onCommandError.bind(this));
break; break;
case 'ban': case 'ban':
if (!this.validateRoleChangeCommand(match[1], args)) { break; } if (!this.validateRoleChangeCommand(command, args)) { break; }
this.setAffiliation('outcast', this.setAffiliation('outcast',
[{ 'jid': args[0], [{ 'jid': args[0],
'reason': args[1] 'reason': args[1]
@ -894,44 +895,45 @@
this.clearChatRoomMessages(); this.clearChatRoomMessages();
break; break;
case 'deop': case 'deop':
if (!this.validateRoleChangeCommand(match[1], args)) { break; } if (!this.validateRoleChangeCommand(command, args)) { break; }
this.modifyRole( this.modifyRole(
this.model.get('jid'), args[0], 'occupant', args[1], this.model.get('jid'), args[0], 'occupant', args[1],
undefined, this.onCommandError.bind(this)); undefined, this.onCommandError.bind(this));
break; break;
case 'help': case 'help':
this.showHelpMessages([ this.showHelpMessages([
'<strong>/admin</strong>: ' +__("Change user's affiliation to admin"), '<strong>/admin</strong>: ' +__("Change user's affiliation to admin"),
'<strong>/ban</strong>: ' +__('Ban user from room'), '<strong>/ban</strong>: ' +__('Ban user from room'),
'<strong>/clear</strong>: ' +__('Remove messages'), '<strong>/clear</strong>: ' +__('Remove messages'),
'<strong>/deop</strong>: ' +__('Change user role to occupant'), '<strong>/deop</strong>: ' +__('Change user role to occupant'),
'<strong>/help</strong>: ' +__('Show this menu'), '<strong>/help</strong>: ' +__('Show this menu'),
'<strong>/kick</strong>: ' +__('Kick user from room'), '<strong>/kick</strong>: ' +__('Kick user from room'),
'<strong>/me</strong>: ' +__('Write in 3rd person'), '<strong>/me</strong>: ' +__('Write in 3rd person'),
'<strong>/member</strong>: '+__('Grant membership to a user'), '<strong>/member</strong>: ' +__('Grant membership to a user'),
'<strong>/mute</strong>: ' +__("Remove user's ability to post messages"), '<strong>/mute</strong>: ' +__("Remove user's ability to post messages"),
'<strong>/nick</strong>: ' +__('Change your nickname'), '<strong>/nick</strong>: ' +__('Change your nickname'),
'<strong>/op</strong>: ' +__('Grant moderator role to user'), '<strong>/op</strong>: ' +__('Grant moderator role to user'),
'<strong>/owner</strong>: ' +__('Grant ownership of this room'), '<strong>/owner</strong>: ' +__('Grant ownership of this room'),
'<strong>/revoke</strong>: '+__("Revoke user's membership"), '<strong>/revoke</strong>: ' +__("Revoke user's membership"),
'<strong>/topic</strong>: ' +__('Set room topic'), '<strong>/subject</strong>: ' +__('Set room subject'),
'<strong>/voice</strong>: ' +__('Allow muted user to post messages') '<strong>/topic</strong>: ' +__('Set room subject (alias for /subject)'),
'<strong>/voice</strong>: ' +__('Allow muted user to post messages')
]); ]);
break; break;
case 'kick': case 'kick':
if (!this.validateRoleChangeCommand(match[1], args)) { break; } if (!this.validateRoleChangeCommand(command, args)) { break; }
this.modifyRole( this.modifyRole(
this.model.get('jid'), args[0], 'none', args[1], this.model.get('jid'), args[0], 'none', args[1],
undefined, this.onCommandError.bind(this)); undefined, this.onCommandError.bind(this));
break; break;
case 'mute': case 'mute':
if (!this.validateRoleChangeCommand(match[1], args)) { break; } if (!this.validateRoleChangeCommand(command, args)) { break; }
this.modifyRole( this.modifyRole(
this.model.get('jid'), args[0], 'visitor', args[1], this.model.get('jid'), args[0], 'visitor', args[1],
undefined, this.onCommandError.bind(this)); undefined, this.onCommandError.bind(this));
break; break;
case 'member': case 'member':
if (!this.validateRoleChangeCommand(match[1], args)) { break; } if (!this.validateRoleChangeCommand(command, args)) { break; }
this.setAffiliation('member', this.setAffiliation('member',
[{ 'jid': args[0], [{ 'jid': args[0],
'reason': args[1] 'reason': args[1]
@ -945,26 +947,27 @@
}).tree()); }).tree());
break; break;
case 'owner': case 'owner':
if (!this.validateRoleChangeCommand(match[1], args)) { break; } if (!this.validateRoleChangeCommand(command, args)) { break; }
this.setAffiliation('owner', this.setAffiliation('owner',
[{ 'jid': args[0], [{ 'jid': args[0],
'reason': args[1] 'reason': args[1]
}]).fail(this.onCommandError.bind(this)); }]).fail(this.onCommandError.bind(this));
break; break;
case 'op': case 'op':
if (!this.validateRoleChangeCommand(match[1], args)) { break; } if (!this.validateRoleChangeCommand(command, args)) { break; }
this.modifyRole( this.modifyRole(
this.model.get('jid'), args[0], 'moderator', args[1], this.model.get('jid'), args[0], 'moderator', args[1],
undefined, this.onCommandError.bind(this)); undefined, this.onCommandError.bind(this));
break; break;
case 'revoke': case 'revoke':
if (!this.validateRoleChangeCommand(match[1], args)) { break; } if (!this.validateRoleChangeCommand(command, args)) { break; }
this.setAffiliation('none', this.setAffiliation('none',
[{ 'jid': args[0], [{ 'jid': args[0],
'reason': args[1] 'reason': args[1]
}]).fail(this.onCommandError.bind(this)); }]).fail(this.onCommandError.bind(this));
break; break;
case 'topic': case 'topic':
case 'subject':
converse.connection.send( converse.connection.send(
$msg({ $msg({
to: this.model.get('jid'), to: this.model.get('jid'),
@ -974,7 +977,7 @@
); );
break; break;
case 'voice': case 'voice':
if (!this.validateRoleChangeCommand(match[1], args)) { break; } if (!this.validateRoleChangeCommand(command, args)) { break; }
this.modifyRole( this.modifyRole(
this.model.get('jid'), args[0], 'occupant', args[1], this.model.get('jid'), args[0], 'occupant', args[1],
undefined, this.onCommandError.bind(this)); undefined, this.onCommandError.bind(this));