join conference rooms when we're already connected

This commit is contained in:
Andreas Martens 2021-01-29 15:46:15 +00:00
parent d289272afe
commit af2cedf203

View File

@ -209,6 +209,21 @@ module.exports = function(RED) {
} }
}); });
function joinMUC(node, xmpp, name) {
// the presence with the muc x element signifies we want to join the muc
// if we want to support passwords, we need to add that as a child of the x element
// (third argument to the x/muc/children )
// We also turn off chat history (maxstanzas 0) because that's not what this node is about.
var stanza = xml('presence',
{"to": name},
xml("x",'http://jabber.org/protocol/muc'),
{ maxstanzas:0, seconds:1 }
);
node.serverConfig.used(node);
xmpp.send(stanza);
}
function XmppInNode(n) { function XmppInNode(n) {
RED.nodes.createNode(this,n); RED.nodes.createNode(this,n);
this.server = n.server; this.server = n.server;
@ -218,6 +233,9 @@ module.exports = function(RED) {
this.sendAll = n.sendObject; this.sendAll = n.sendObject;
// Yes, it's called "from", don't ask me why; I don't know why // Yes, it's called "from", don't ask me why; I don't know why
this.from = n.to || ""; this.from = n.to || "";
this.quiet = false;
// MUC == Multi-User-Chat == chatroom
this.muc = this.join && (this.from !== "")
var node = this; var node = this;
var xmpp = this.serverConfig.client; var xmpp = this.serverConfig.client;
@ -235,26 +253,27 @@ module.exports = function(RED) {
disconnect: Socket is disconnected disconnect: Socket is disconnected
*/ */
xmpp.on('online', async address => { // if we're already connected, then do the actions now, otherwise register a callback
if(xmpp.status === "online") {
node.status({fill:"green",shape:"dot",text:"node-red:common.status.connected"}); node.status({fill:"green",shape:"dot",text:"node-red:common.status.connected"});
if ((node.join) && (node.from !== "")) { if(node.muc) {
var to = node.from+'/'+node.nick; joinMUC(node, xmpp, node.from+'/'+node.nick);
// the presence with the muc x element signifies we want to join the muc }
// if we want to support passwords, we need to add that as a child of the x element }
// (third argument to the x/muc/children ) // sod it, register it anyway, that way things will work better on a reconnect:
// We also turn off chat history (maxstanzas 0) because that's not what this node is about. xmpp.on('online', async address => {
var stanza = xml('presence', node.quiet = false;
{"to": to}, node.status({fill:"green",shape:"dot",text:"node-red:common.status.connected"});
xml("x",'http://jabber.org/protocol/muc'), if (node.muc) {
{ maxstanzas:0, seconds:1 } // if we want to use a chatroom, we need to tell the server we want to join it
); joinMUC(node, xmpp, node.from+'/'+node.nick);
node.serverConfig.used(node);
xmpp.send(stanza).catch(error => {node.warn("Got error when sending presence: "+error)});
} }
}); });
xmpp.on('connecting', async address => { xmpp.on('connecting', async address => {
node.status({fill:"grey",shape:"dot",text:"node-red:common.status.connecting"}); if(!node.quiet) {
node.status({fill:"grey",shape:"dot",text:"node-red:common.status.connecting"});
}
}); });
xmpp.on('connect', async address => { xmpp.on('connect', async address => {
node.status({fill:"grey",shape:"dot",text:"node-red:common.status.connected"}); node.status({fill:"grey",shape:"dot",text:"node-red:common.status.connected"});
@ -279,38 +298,40 @@ module.exports = function(RED) {
// Should we listen on other's status (chatstate) or a chatroom state (groupbuddy)? // Should we listen on other's status (chatstate) or a chatroom state (groupbuddy)?
xmpp.on('error', err => { xmpp.on('error', err => {
if (RED.settings.verbose || LOGITALL) { node.log("XMPP Error: "+err); } if (RED.settings.verbose || LOGITALL) { node.log("XMPP Error: "+err); }
if (err.hasOwnProperty("stanza")) { if(!node.quiet) {
if (err.stanza.name === 'stream:error') { node.error("stream:error - bad login id/pwd ?",err); } node.quiet = true;
else { node.error(err.stanza.name,err); } if (err.hasOwnProperty("stanza")) {
node.status({fill:"red",shape:"ring",text:"bad login"}); if (err.stanza.name === 'stream:error') { node.error("stream:error - bad login id/pwd ?",err); }
} else { node.error(err.stanza.name,err); }
else { node.status({fill:"red",shape:"ring",text:"bad login"});
if (err.errno === "ETIMEDOUT") {
node.error("Timeout connecting to server",err);
node.status({fill:"red",shape:"ring",text:"timeout"});
}
if (err.errno === "ENOTFOUND") {
node.error("Server doesn't exist "+xmpp.options.service,err);
node.status({fill:"red",shape:"ring",text:"bad address"});
}
else if (err === "XMPP authentication failure") {
node.error("Authentication failure! "+err,err);
node.status({fill:"red",shape:"ring",text:"XMPP authentication failure"});
}
else if (err.name === "SASLError") {
node.error("Authorization error! "+err.condition,err);
node.status({fill:"red",shape:"ring",text:"XMPP authorization failure"});
}
else if (err == "TimeoutError") {
// Suppress it! This seems to happen with OpenFire servers and doesn't actually stop us from working
node.warn("Timed out! ");
node.status({fill:"grey",shape:"dot",text:"opening"});
// uncomment if you want it to be an error
//node.status({fill:"red",shape:"ring",text:"XMPP timeout"});
} }
else { else {
node.error(err,err); if (err.errno === "ETIMEDOUT") {
node.status({fill:"red",shape:"ring",text:"node-red:common.status.error"}); node.error("Timeout connecting to server",err);
node.status({fill:"red",shape:"ring",text:"timeout"});
}
if (err.errno === "ENOTFOUND") {
node.error("Server doesn't exist "+xmpp.options.service,err);
node.status({fill:"red",shape:"ring",text:"bad address"});
}
else if (err === "XMPP authentication failure") {
node.error("Authentication failure! "+err,err);
node.status({fill:"red",shape:"ring",text:"XMPP authentication failure"});
}
else if (err.name === "SASLError") {
node.error("Authorization error! "+err.condition,err);
node.status({fill:"red",shape:"ring",text:"XMPP authorization failure"});
}
else if (err == "TimeoutError") {
// Suppress it!
node.warn("Timed out! ");
node.status({fill:"grey",shape:"dot",text:"opening"});
//node.status({fill:"red",shape:"ring",text:"XMPP timeout"});
}
else {
node.error(err,err);
node.status({fill:"red",shape:"ring",text:"node-red:common.status.error"});
}
} }
} }
}); });
@ -395,7 +416,7 @@ module.exports = function(RED) {
if (RED.settings.verbose || LOGITALL) { if (RED.settings.verbose || LOGITALL) {
node.log("starting xmpp client"); node.log("starting xmpp client");
} }
xmpp.start().catch(error => {node.warn("Got error on start: "+error); node.warn("XMPP Status is now: "+xmpp.status)});; xmpp.start().catch(error => {node.warn("Got error on start: "+error); node.warn("XMPP Status is now: "+xmpp.status)});
} }
} }
} }
@ -421,6 +442,9 @@ module.exports = function(RED) {
this.join = n.join || false; this.join = n.join || false;
this.sendAll = n.sendObject; this.sendAll = n.sendObject;
this.to = n.to || ""; this.to = n.to || "";
this.quiet = false;
// MUC == Multi-User-Chat == chatroom
this.muc = this.join && (this.to !== "")
var node = this; var node = this;
var xmpp = this.serverConfig.client; var xmpp = this.serverConfig.client;
@ -438,27 +462,26 @@ module.exports = function(RED) {
disconnect: Socket is disconnected disconnect: Socket is disconnected
*/ */
xmpp.on('online', function(data) { // if we're already connected, then do the actions now, otherwise register a callback
if(xmpp.status === "online") {
node.status({fill:"green",shape:"dot",text:"node-red:common.status.connected"}); node.status({fill:"green",shape:"dot",text:"node-red:common.status.connected"});
if ((node.join) && (node.to !== "")) { if(node.muc){
// disable chat history joinMUC(node, xmpp, node.to+'/'+node.nick);
var to = node.to+'/'+node.nick; }
// the presence with the muc x element signifies we want to join the muc }
// if we want to support passwords, we need to add that as a child of the x element // sod it, register it anyway, that way things will work better on a reconnect:
// (third argument to the x/muc/children ) xmpp.on('online', function(data) {
// We also turn off chat history (maxstanzas 0) because that's not what this node is about. node.quiet = false;
var stanza = xml('presence', node.status({fill:"green",shape:"dot",text:"node-red:common.status.connected"});
{"to": to}, if (node.muc) {
xml("x",'http://jabber.org/protocol/muc'), joinMUC(node, xmpp,node.to+"/"+node.nick);
{ maxstanzas:0, seconds:1 }
);
node.serverConfig.used(node);
xmpp.send(stanza);
} }
}); });
xmpp.on('connecting', async address => { xmpp.on('connecting', async address => {
node.status({fill:"grey",shape:"dot",text:"node-red:common.status.connecting"}); if(!node.quiet) {
node.status({fill:"grey",shape:"dot",text:"node-red:common.status.connecting"});
}
}); });
xmpp.on('connect', async address => { xmpp.on('connect', async address => {
node.status({fill:"grey",shape:"dot",text:"node-red:common.status.connected"}); node.status({fill:"grey",shape:"dot",text:"node-red:common.status.connected"});
@ -482,37 +505,36 @@ module.exports = function(RED) {
xmpp.on('error', function(err) { xmpp.on('error', function(err) {
if (RED.settings.verbose || LOGITALL) { node.log(err); } if (RED.settings.verbose || LOGITALL) { node.log(err); }
if (err.hasOwnProperty("stanza")) { if(!node.quiet) {
if (err.stanza.name === 'stream:error') { node.error("stream:error - bad login id/pwd ?",err); } node.quiet = true;
else { node.error(err.stanza.name,err); } if (err.hasOwnProperty("stanza")) {
node.status({fill:"red",shape:"ring",text:"bad login"}); if (err.stanza.name === 'stream:error') { node.error("stream:error - bad login id/pwd ?",err); }
} else { node.error(err.stanza.name,err); }
else { node.status({fill:"red",shape:"ring",text:"bad login"});
if (err.errno === "ETIMEDOUT") {
node.error("Timeout connecting to server",err);
node.status({fill:"red",shape:"ring",text:"timeout"});
}
else if (err.errno === "ENOTFOUND") {
node.error("Server doesn't exist "+xmpp.options.service,err);
node.status({fill:"red",shape:"ring",text:"bad address"});
}
if (err.errno === "ENOTFOUND") {
node.error("Server doesn't exist "+xmpp.options.service,err);
node.status({fill:"red",shape:"ring",text:"bad address"});
}
else if (err === "XMPP authentication failure") {
node.error(err,err);
node.status({fill:"red",shape:"ring",text:"XMPP authentication failure"});
}
else if (err == "TimeoutError") {
// OK, this happens with OpenFire, suppress it. The connection seems to still work
node.status({fill:"grey",shape:"dot",text:"opening"});
node.log("Timed out! ",err);
// node.status({fill:"red",shape:"ring",text:"XMPP timeout"});
} }
else { else {
node.error("Unknown error: "+err,err); if (err.errno === "ETIMEDOUT") {
node.status({fill:"red",shape:"ring",text:"node-red:common.status.error"}); node.error("Timeout connecting to server",err);
node.status({fill:"red",shape:"ring",text:"timeout"});
}
else if (err.errno === "ENOTFOUND") {
node.error("Server doesn't exist "+xmpp.options.service,err);
node.status({fill:"red",shape:"ring",text:"bad address"});
}
else if (err === "XMPP authentication failure") {
node.error(err,err);
node.status({fill:"red",shape:"ring",text:"XMPP authentication failure"});
}
else if (err == "TimeoutError") {
// OK, this happens with OpenFire, suppress it.
node.status({fill:"grey",shape:"dot",text:"opening"});
node.log("Timed out! ",err);
// node.status({fill:"red",shape:"ring",text:"XMPP timeout"});
}
else {
node.error("Unknown error: "+err,err);
node.status({fill:"red",shape:"ring",text:"node-red:common.status.error"});
}
} }
} }
}); });