tidy up xmpp node

This commit is contained in:
Dave Conway-Jones 2020-10-24 15:02:45 +01:00
parent 770ad94e95
commit 3b7fb0aa95
No known key found for this signature in database
GPG Key ID: 88BA2B8A411BE9FF
4 changed files with 139 additions and 64 deletions

2
.gitignore vendored
View File

@ -6,3 +6,5 @@ puball.sh
setenv.sh setenv.sh
/.project /.project
package-lock.json package-lock.json
social/xmpp/92-xmpp.old
*.tgz

View File

@ -109,7 +109,7 @@
</script> </script>
<script type="text/html" data-template-name="xmpp-server"> <script type="text/html" data-template-name="xmpp-server">
<div class="form-row node-input-server"> <div class="form-row">
<label for="node-config-input-server"><i class="fa fa-bookmark"></i> Server</label> <label for="node-config-input-server"><i class="fa fa-bookmark"></i> Server</label>
<input class="input-append-left" type="text" id="node-config-input-server" placeholder="blah.im" style="width: 40%;" > <input class="input-append-left" type="text" id="node-config-input-server" placeholder="blah.im" style="width: 40%;" >
<label for="node-config-input-port" style="margin-left: 10px; width: 35px; "> Port</label> <label for="node-config-input-port" style="margin-left: 10px; width: 35px; "> Port</label>

View File

@ -22,7 +22,7 @@ module.exports = function(RED) {
this.port = 5222; this.port = 5222;
} }
else{ else{
this.port = n.port; this.port = parseInt(n.port);
} }
// The password is obfuscated and stored in a separate location // The password is obfuscated and stored in a separate location
@ -32,8 +32,15 @@ module.exports = function(RED) {
} }
// The basic xmpp client object, this will be referred to as "xmpp" in the nodes. // The basic xmpp client object, this will be referred to as "xmpp" in the nodes.
// note we're not actually connecting here. // note we're not actually connecting here.
var proto = "xmpp";
if (this.port === 5223) {
proto = "xmpps";
}
if (RED.settings.verbose || LOGITALL) {
this.log("Setting up connection xmpp: {service: "+proto+"://"+this.server+":"+this.port+", username: "+this.username+", password: "+this.password+"}");
}
this.client = client({ this.client = client({
service: 'xmpp://' + this.server + ':' + this.port, service: proto+'://' + this.server + ':' + this.port,
username: this.username, username: this.username,
password: this.password password: this.password
}); });
@ -67,7 +74,6 @@ module.exports = function(RED) {
if (that.client && that.client.connected) { if (that.client && that.client.connected) {
return that.client.stop(done); return that.client.stop(done);
} else { } else {
that.client.stop();
return done(); return done();
} }
} }
@ -101,11 +107,22 @@ module.exports = function(RED) {
if ("undefined" !== typeof textObj) { if ("undefined" !== typeof textObj) {
text = textObj.getText(); text = textObj.getText();
} }
else{
textObj = err.getChild('code');
if ("undefined" !== typeof textObj) {
text = textObj.getText();
}
}
if (RED.settings.verbose || LOGITALL) {that.log("Culprit: "+that.lastUsed); } if (RED.settings.verbose || LOGITALL) {that.log("Culprit: "+that.lastUsed); }
if ("undefined" !== typeof that.lastUsed) { if ("undefined" !== typeof that.lastUsed) {
that.lastUsed.status({fill:"red",shape:"ring",text:text}); that.lastUsed.status({fill:"red",shape:"ring",text:text});
that.lastUsed.warn(text); that.lastUsed.warn(text);
} }
if (RED.settings.verbose || LOGITALL) {
that.log("We did wrong: "+text);
that.log(stanza);
}
// maybe throw the message or summit // maybe throw the message or summit
//that.error(text); //that.error(text);
} }
@ -128,7 +145,26 @@ module.exports = function(RED) {
} }
} }
} }
else if (stanza.is('iq')) {
if (RED.settings.verbose || LOGITALL) {that.log("got an iq query"); }
if (stanza.attrs.type === 'error') {
if (RED.settings.verbose || LOGITALL) {that.log("oh noes, it's an error"); }
if (stanza.attrs.id === that.lastUsed.id) {
that.lastUsed.status({fill:"red", shape:"ring", text:stanza.getChild('error')});
that.lastUsed.warn(stanza.getChild('error'));
}
}
else if (stanza.attrs.type === 'result') {
// AM To-Do check for 'bind' result with our current jid
var query = stanza.getChild('query');
if (RED.settings.verbose || LOGITALL) {that.log("result!"); }
if (RED.settings.verbose || LOGITALL) {that.log(query); }
}
}
}); });
// We shouldn't have any errors here that the input/output nodes can't handle // We shouldn't have any errors here that the input/output nodes can't handle
// if you need to see everything though; uncomment this block // if you need to see everything though; uncomment this block
// this.client.on('error', err => { // this.client.on('error', err => {
@ -153,11 +189,18 @@ module.exports = function(RED) {
// gets called when the node is destroyed, e.g. if N-R is being stopped. // gets called when the node is destroyed, e.g. if N-R is being stopped.
this.on("close", async done => { this.on("close", async done => {
if(that.connected){ if (that.client.connected) {
await that.client.send(xml('presence', {type: 'unavailable'})); await that.client.send(xml('presence', {type: 'unavailable'}));
try{
if (RED.settings.verbose || LOGITALL) {
that.log("Calling stop() after close, status is "+that.client.status);
}
await that.client.stop().then(that.log("XMPP client stopped")).catch(error=>{that.warn("Got an error whilst closing xmpp session: "+error)});
}
catch(e) {
that.warn(e);
}
} }
that.client.stop().catch(that.error);
done(); done();
}); });
} }
@ -175,6 +218,7 @@ module.exports = function(RED) {
this.nick = this.serverConfig.nickname || this.serverConfig.username.split("@")[0]; this.nick = this.serverConfig.nickname || this.serverConfig.username.split("@")[0];
this.join = n.join || false; this.join = n.join || false;
this.sendAll = n.sendObject; this.sendAll = n.sendObject;
// Yes, it's called "from", don't ask me why; I don't know why
this.from = n.to || ""; this.from = n.to || "";
var node = this; var node = this;
@ -207,7 +251,7 @@ module.exports = function(RED) {
{ maxstanzas:0, seconds:1 } { maxstanzas:0, seconds:1 }
); );
node.serverConfig.used(node); node.serverConfig.used(node);
xmpp.send(stanza); xmpp.send(stanza).catch(error => {node.warn("Got error when sending presence: "+error)});
} }
}); });
@ -236,7 +280,7 @@ 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(err); } if (RED.settings.verbose || LOGITALL) { node.log("XMPP Error: "+err); }
if (err.hasOwnProperty("stanza")) { if (err.hasOwnProperty("stanza")) {
if (err.stanza.name === 'stream:error') { node.error("stream:error - bad login id/pwd ?",err); } if (err.stanza.name === 'stream:error') { node.error("stream:error - bad login id/pwd ?",err); }
else { node.error(err.stanza.name,err); } else { node.error(err.stanza.name,err); }
@ -252,11 +296,21 @@ module.exports = function(RED) {
node.status({fill:"red",shape:"ring",text:"bad address"}); node.status({fill:"red",shape:"ring",text:"bad address"});
} }
else if (err === "XMPP authentication failure") { else if (err === "XMPP authentication failure") {
node.error(err,err); node.error("Authentication failure! "+err,err);
node.status({fill:"red",shape:"ring",text:"XMPP authentication failure"}); 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 { else {
node.error(err.errno,err); node.error(err,err);
node.status({fill:"red",shape:"ring",text:"node-red:common.status.error"}); node.status({fill:"red",shape:"ring",text:"node-red:common.status.error"});
} }
} }
@ -276,7 +330,8 @@ module.exports = function(RED) {
msg.topic = stanza.attrs.from msg.topic = stanza.attrs.from
} }
else { msg.topic = ids[0]; } else { msg.topic = ids[0]; }
if (!node.join && ((node.from === "") || (node.from === stanza.attrs.from))) { // if (RED.settings.verbose || LOGITALL) {node.log("Received a message from "+stanza.attrs.from); }
if (!node.join && ((node.from === "") || (node.from === stanza.attrs.to))) {
node.send([msg,null]); node.send([msg,null]);
} }
} }
@ -330,8 +385,6 @@ module.exports = function(RED) {
} }
}); });
// xmpp.on('subscribe', from => { // xmpp.on('subscribe', from => {
// xmpp.acceptSubscription(from); // xmpp.acceptSubscription(from);
// }); // });
@ -346,7 +399,10 @@ module.exports = function(RED) {
else{ else{
node.status({fill:"grey",shape:"dot",text:"node-red:common.status.connecting"}); node.status({fill:"grey",shape:"dot",text:"node-red:common.status.connecting"});
if (xmpp.status === "offline") { if (xmpp.status === "offline") {
xmpp.start(); if (RED.settings.verbose || LOGITALL) {
node.log("starting xmpp client");
}
xmpp.start().catch(error => {node.warn("Got error on start: "+error); node.warn("XMPP Status is now: "+xmpp.status)});
} }
} }
} }
@ -392,7 +448,7 @@ module.exports = function(RED) {
xmpp.on('online', function(data) { xmpp.on('online', function(data) {
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.join) && (node.to !== "")) {
// disable chat history // disable chat history
var to = node.to+'/'+node.nick; var to = node.to+'/'+node.nick;
// the presence with the muc x element signifies we want to join the muc // the presence with the muc x element signifies we want to join the muc
@ -444,7 +500,7 @@ module.exports = function(RED) {
node.error("Timeout connecting to server",err); node.error("Timeout connecting to server",err);
node.status({fill:"red",shape:"ring",text:"timeout"}); node.status({fill:"red",shape:"ring",text:"timeout"});
} }
if (err.errno === "ENOTFOUND") { else if (err.errno === "ENOTFOUND") {
node.error("Server doesn't exist "+xmpp.options.service,err); node.error("Server doesn't exist "+xmpp.options.service,err);
node.status({fill:"red",shape:"ring",text:"bad address"}); node.status({fill:"red",shape:"ring",text:"bad address"});
} }
@ -452,8 +508,14 @@ module.exports = function(RED) {
node.error(err,err); node.error(err,err);
node.status({fill:"red",shape:"ring",text:"XMPP authentication failure"}); 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 { else {
node.error(err.errno,err); node.error("Unknown error: "+err,err);
node.status({fill:"red",shape:"ring",text:"node-red:common.status.error"}); node.status({fill:"red",shape:"ring",text:"node-red:common.status.error"});
} }
} }
@ -496,6 +558,17 @@ module.exports = function(RED) {
node.serverConfig.used(node); node.serverConfig.used(node);
xmpp.send(stanza); xmpp.send(stanza);
} }
else if (msg.command === "get") {
var to = node.to || msg.topic || "";
var stanza = xml('iq',
{type:'get', id:node.id, to: to},
xml('query', 'http://jabber.org/protocol/muc#admin',
xml('item',{affiliation:msg.payload})));
node.serverConfig.used(node);
if (RED.settings.verbose || LOGITALL) {node.log("sending stanza "+stanza.toString()); }
xmpp.send(stanza);
}
} }
else { else {
var to = node.to || msg.topic || ""; var to = node.to || msg.topic || "";

View File

@ -1,6 +1,6 @@
{ {
"name": "node-red-node-xmpp", "name": "node-red-node-xmpp",
"version": "0.3.0", "version": "0.3.1",
"description": "A Node-RED node to talk to an XMPP server", "description": "A Node-RED node to talk to an XMPP server",
"dependencies": { "dependencies": {
"@xmpp/client": "^0.11.1" "@xmpp/client": "^0.11.1"