Bug 1205727 - Implement invite and me commands for XMPP muc. r=aleth
This commit is contained in:
Родитель
07154e24ee
Коммит
57c77eaa53
|
@ -74,6 +74,12 @@ conversation.error.banKickCommandNotAllowed=You don't have the required privileg
|
|||
conversation.error.banKickCommandConflict=Sorry, you can't remove yourself from the room.
|
||||
conversation.error.changeNickFailedConflict=Could not change your nick to %S as this nick is already in use.
|
||||
conversation.error.changeNickFailedNotAcceptable=Could not change your nick to %S as nicks are locked down in this room.
|
||||
conversation.error.inviteFailedForbidden=You don't have the required privileges to invite users to this room.
|
||||
# %S is the jid of user that is invited.
|
||||
conversation.error.failedJIDNotFound=Could not reach %S.
|
||||
# %S is the jid that is invalid.
|
||||
conversation.error.invalidJID=%S is an invalid jid (Jabber identifiers must be of the form user@domain).
|
||||
conversation.error.commandFailedNotInRoom=You have to rejoin the room to be able to use this command.
|
||||
conversation.error.unknownError=Unknown error
|
||||
|
||||
# LOCALIZATION NOTE (tooltip.*):
|
||||
|
@ -135,6 +141,12 @@ conversation.message.parted.you.reason=You have left the room: %S
|
|||
conversation.message.parted=%1$S has left the room.
|
||||
conversation.message.parted.reason=%1$S has left the room: %2$S
|
||||
|
||||
# LOCALIZATION NOTE (conversation.message.invitationDeclined*):
|
||||
# %1$S is the invitee that declined the invitation.
|
||||
# %2$S is the decline message supplied by the invitee.
|
||||
conversation.message.invitationDeclined=%1$S has declined your invitation.
|
||||
conversation.message.invitationDeclined.reason=%1$S has declined your invitation: %2$S
|
||||
|
||||
# LOCALIZATION NOTE (conversation.message.banned.*):
|
||||
# These are displayed as a system message when a participant is banned from
|
||||
# a room.
|
||||
|
@ -229,5 +241,7 @@ command.part2=%S [<message>]: Leave the current room with an optional mess
|
|||
command.topic=%S [<new topic>]: Set this room's topic.
|
||||
command.ban=%S <nick>[<message>]: Ban someone from the room. You must be a room administrator to do this.
|
||||
command.kick=%S <nick>[<message>]: Remove someone from the room. You must be a room moderator to do this.
|
||||
command.invite=%S <jid>[<message>]: Invite a user to join the current room with an optional message.
|
||||
command.me=%S <action to perform>: Perform an action.
|
||||
command.nick=%S <new nickname>: Change your nickname.
|
||||
command.msg=%S <nick> <message>: Send a private message to a participant in the room.
|
||||
|
|
|
@ -22,6 +22,17 @@ function getAccount(aConv) {
|
|||
return getConv(aConv)._account;
|
||||
}
|
||||
|
||||
function getMUC(aConv) {
|
||||
let conv = getConv(aConv);
|
||||
if (conv.left) {
|
||||
conv.writeMessage(conv.name,
|
||||
_("conversation.error.commandFailedNotInRoom"),
|
||||
{system: true});
|
||||
return null;
|
||||
}
|
||||
return conv;
|
||||
}
|
||||
|
||||
// Trims the string and splits it in two parts on the first space
|
||||
// if there is one. Returns the non-empty parts in an array.
|
||||
function splitInput(aString) {
|
||||
|
@ -33,7 +44,7 @@ function splitInput(aString) {
|
|||
let offset = params.indexOf(" ");
|
||||
if (offset != -1) {
|
||||
splitParams.push(params.slice(0, offset));
|
||||
splitParams.push(params.slice(offset + 1));
|
||||
splitParams.push(params.slice(offset + 1).trimLeft());
|
||||
}
|
||||
else
|
||||
splitParams.push(params);
|
||||
|
@ -90,9 +101,10 @@ var commands = [
|
|||
get helpString() { return _("command.topic", "topic"); },
|
||||
usageContext: Ci.imICommand.CMD_CONTEXT_CHAT,
|
||||
run: function(aMsg, aConv) {
|
||||
let conv = getConv(aConv);
|
||||
if (!conv.left)
|
||||
conv.topic = aMsg;
|
||||
let conv = getMUC(aConv);
|
||||
if (!conv)
|
||||
return true;
|
||||
conv.topic = aMsg;
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
@ -105,9 +117,9 @@ var commands = [
|
|||
if (!params.length)
|
||||
return false;
|
||||
|
||||
let conv = getConv(aConv);
|
||||
if (!conv.left)
|
||||
conv.ban(params[0], params[1]);
|
||||
let conv = getMUC(aConv);
|
||||
if (conv)
|
||||
conv.ban(...params);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
@ -120,9 +132,53 @@ var commands = [
|
|||
if (!params.length)
|
||||
return false;
|
||||
|
||||
let conv = getMUC(aConv);
|
||||
if (conv)
|
||||
conv.kick(...params);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "invite",
|
||||
get helpString() { return _("command.invite", "invite"); },
|
||||
usageContext: Ci.imICommand.CMD_CONTEXT_CHAT,
|
||||
run: function(aMsg, aConv) {
|
||||
let params = splitInput(aMsg);
|
||||
if (!params.length)
|
||||
return false;
|
||||
|
||||
let conv = getMUC(aConv);
|
||||
if (!conv)
|
||||
return true;
|
||||
|
||||
// Check user's jid is valid.
|
||||
let account = getAccount(aConv);
|
||||
let jid = account._parseJID(params[0]);
|
||||
if (!jid) {
|
||||
conv.writeMessage(conv.name,
|
||||
_("conversation.error.invalidJID", params[0]),
|
||||
{system: true});
|
||||
return true;
|
||||
}
|
||||
conv.invite(...params);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "me",
|
||||
get helpString() { return _("command.me", "me"); },
|
||||
usageContext: Ci.imICommand.CMD_CONTEXT_CHAT,
|
||||
run: function(aMsg, aConv) {
|
||||
let params = aMsg.trim();
|
||||
if (!params)
|
||||
return false;
|
||||
|
||||
// XEP-0245: The /me Command.
|
||||
// We need to append "/me " in the first four characters of the message
|
||||
// body.
|
||||
let conv = getConv(aConv);
|
||||
if (!conv.left)
|
||||
conv.ban(params[0], params[1]);
|
||||
conv.sendMsg("/me " + params);
|
||||
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
@ -135,8 +191,8 @@ var commands = [
|
|||
if (!params[0])
|
||||
return false;
|
||||
|
||||
let conv = getConv(aConv);
|
||||
if (!conv.left)
|
||||
let conv = getMUC(aConv);
|
||||
if (conv)
|
||||
conv.setNick(params[0]);
|
||||
return true;
|
||||
}
|
||||
|
@ -151,8 +207,8 @@ var commands = [
|
|||
return false;
|
||||
let [nickName, msg] = params;
|
||||
|
||||
let conv = getConv(aConv);
|
||||
if (conv.left)
|
||||
let conv = getMUC(aConv);
|
||||
if (!conv)
|
||||
return true;
|
||||
|
||||
if (!conv._participants.has(nickName)) {
|
||||
|
|
|
@ -423,6 +423,24 @@ const XMPPMUCConversationPrototype = {
|
|||
delete this.chatRoomFields;
|
||||
},
|
||||
|
||||
// Invites a user to MUC conversation.
|
||||
invite: function(aJID, aMsg = null) {
|
||||
// XEP-0045 (7.8): Inviting Another User to a Room.
|
||||
// XEP-0045 (7.8.2): Mediated Invitation.
|
||||
let invite = Stanza.node("invite", null, {to: aJID},
|
||||
aMsg ? Stanza.node("reason", null, null, aMsg) : null);
|
||||
let x = Stanza.node("x", Stanza.NS.muc_user, null, invite);
|
||||
let s = Stanza.node("message", null, {to: this.name}, x);
|
||||
this._account.sendStanza(s, this._account.handleErrors({
|
||||
forbidden: _("conversation.error.inviteFailedForbidden"),
|
||||
// ejabberd uses error not-allowed to indicate that this account does not
|
||||
// have the required privileges to invite users instead of forbidden error,
|
||||
// and this is not mentioned in the spec (XEP-0045).
|
||||
notAllowed: _("conversation.error.inviteFailedForbidden"),
|
||||
itemNotFound: _("conversation.error.failedJIDNotFound", aJID)
|
||||
}, this));
|
||||
},
|
||||
|
||||
// Bans a participant from MUC conversation.
|
||||
ban: function(aNickName, aMsg = null) {
|
||||
// XEP-0045 (9.1): Banning a User.
|
||||
|
@ -485,6 +503,29 @@ const XMPPMUCConversationPrototype = {
|
|||
}, this));
|
||||
},
|
||||
|
||||
// Called by the account when a message stanza is received for this muc and
|
||||
// needs to be handled.
|
||||
onMessageStanza: function(aStanza) {
|
||||
let x = aStanza.getElement(["x"]);
|
||||
let decline = x.getElement(["decline"]);
|
||||
if (decline) {
|
||||
// XEP-0045 (7.8): Inviting Another User to a Room.
|
||||
// XEP-0045 (7.8.2): Mediated Invitation.
|
||||
let invitee = decline.attributes["jid"];
|
||||
let reasonNode = decline.getElement(["reason"]);
|
||||
let reason = reasonNode ? reasonNode.innerText : "";
|
||||
let msg;
|
||||
if (reason)
|
||||
msg = _("conversation.message.invitationDeclined.reason", invitee, reason);
|
||||
else
|
||||
msg = _("conversation.message.invitationDeclined", invitee);
|
||||
|
||||
this.writeMessage(this.name, msg, {system: true});
|
||||
}
|
||||
else
|
||||
this.WARN("Unhandled message stanza.");
|
||||
},
|
||||
|
||||
/* Called when the user closed the conversation */
|
||||
close: function() {
|
||||
if (!this.left)
|
||||
|
@ -1647,6 +1688,7 @@ const XMPPAccountPrototype = {
|
|||
let norm = this.normalize(from);
|
||||
|
||||
let type = aStanza.attributes["type"];
|
||||
let x = aStanza.getElement(["x"]);
|
||||
let body;
|
||||
let b = aStanza.getElement(["body"]);
|
||||
if (b) {
|
||||
|
@ -1735,6 +1777,15 @@ const XMPPAccountPrototype = {
|
|||
if (conv)
|
||||
conv.incomingMessage(null, aStanza);
|
||||
}
|
||||
else if (x && x.uri == Stanza.NS.muc_user) {
|
||||
let muc = this._mucs.get(norm);
|
||||
if (!muc) {
|
||||
this.WARN("Received a groupchat message for unknown MUC " + norm);
|
||||
return;
|
||||
}
|
||||
muc.onMessageStanza(aStanza);
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't create a conversation to only display the typing notifications.
|
||||
if (!this._conv.has(norm) && !this._conv.has(from))
|
||||
|
|
Загрузка…
Ссылка в новой задаче