cose iniziali

master
Pietro Brenna 2020-02-14 15:59:14 +01:00
commit 869b8b357b
7 changed files with 509 additions and 0 deletions

1
.gitignore vendored 100644
View File

@ -0,0 +1 @@
node_modules/

155
92-xmpp.html 100644
View File

@ -0,0 +1,155 @@
<script type="text/html" data-template-name="xmpp in">
<div class="form-row">
<label for="node-input-server"><i class="fa fa-bookmark"></i> Connect as</label>
<input type="text" id="node-input-server">
</div>
<div class="form-row">
<label for="node-input-to"><i class="fa fa-envelope"></i> Buddy</label>
<input type="text" id="node-input-to" placeholder="joe@blah.im">
</div>
<div class="form-row">
<label>&nbsp;</label>
<input type="checkbox" id="node-input-join" placeholder="" style="display:inline-block; width:auto; vertical-align:top;">
<label for="node-input-join" style="width:70%;">Is a Chat Room ?</label>
</div>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
</script>
<script type="text/html" data-help-name="xmpp in">
<p>Connects to an XMPP server to receive messages.</p>
<p>The <b>Buddy</b> field is the jid of the buddy or room you want to receive messages from. Leave blank to receive from anyone.</p>
<p>Incoming messages will appear as <code>msg.payload</code> on the first output, while <code>msg.topic</code> will contain who it is from.
If part of a chat room then <code>msg.room</code> may also be set.</p>
<p>The second output will show the presence and status of a user in <code>msg.payload</code>. Again <code>msg.topic</code> will hold the users jid.</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('xmpp in', {
category: 'social-input',
color: "#F4F492",
defaults: {
name: { value: "" },
server: { type: "xmpp-server", required: true },
to: { value: "" },
join: { value: false }
},
inputs: 0,
outputs: 2,
icon: "xmpp.png",
label: function () {
return this.name || "xmpp";
},
labelStyle: function () {
return (this.name) ? "node_label_italic" : "";
}
});
</script>
<script type="text/html" data-template-name="xmpp out">
<div class="form-row">
<label for="node-input-server"><i class="fa fa-bookmark"></i> Connect as</label>
<input type="text" id="node-input-server">
</div>
<div class="form-row">
<label>&nbsp;</label>
<input type="checkbox" id="node-input-sendObject" placeholder="" style="display:inline-block; width:auto; vertical-align:top;">
<label for="node-input-sendObject" style="width:70%;">Send complete msg object ?</label>
</div>
<div class="form-row">
<label for="node-input-to"><i class="fa fa-envelope"></i> To</label>
<input type="text" id="node-input-to" placeholder="joe@blah.im">
</div>
<div class="form-row">
<label>&nbsp;</label>
<input type="checkbox" id="node-input-join" placeholder="" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-join" style="width:70%;">Is a Chat Room ?</label>
</div>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-tips">The <b>To</b> field is optional. If not set uses the <code>msg.topic</code> property of the message.</div>
</script>
<script type="text/html" data-help-name="xmpp out">
<p>Connects to an XMPP server to send messages.</p>
<p>The <b>To</b> field is optional. If not set the <code>msg.topic</code> property of the message is used.</p>
<p>If you are joining a room then the <b>To</b> field must be supplied.</p>
<p>You may also send a msg with <code>msg.presence</code> to set your presence to one of <i>chat, away, dnd</i> or <i>xa</i>.
If you do so then the <code>msg.payload</code> will set your status message.</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('xmpp out', {
category: 'social-output',
color: "#F4F492",
defaults: {
name: { value: "" },
server: { type: "xmpp-server", required: true },
to: { value: "" },
join: { value: false },
sendObject: { value: false }
},
inputs: 1,
outputs: 0,
icon: "xmpp.png",
align: "right",
label: function () {
return this.name || "xmpp";
},
labelStyle: function () {
return (this.name) ? "node_label_italic" : "";
}
});
</script>
<script type="text/html" data-template-name="xmpp-server">
<div class="form-row node-input-server">
<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%;" >
<label for="node-config-input-port" style="margin-left: 10px; width: 35px; "> Port</label>
<input type="text" id="node-config-input-port" placeholder="Port" style="width:45px">
</div>
<div class="form-row">
<label for="node-config-input-user"><i class="fa fa-user"></i> JID</label>
<input type="text" id="node-config-input-user" placeholder="joe@blah.im">
</div>
<div class="form-row">
<label for="node-config-input-nickname"><i class="fa fa-user"></i> Nickname</label>
<input type="text" id="node-config-input-nickname" placeholder="Joe (optional)">
</div>
<div class="form-row">
<label for="node-config-input-pass"><i class="fa fa-lock"></i> Password</label>
<input type="password" id="node-config-input-password">
</div>
</script>
<script type="text/javascript">
RED.nodes.registerType('xmpp-server', {
category: 'config',
defaults: {
server: { required: true },
port: { value: 5222, required: true, validate: RED.validators.number() },
user: { type: "text" },
nickname: { value: "" }
},
credentials: {
password: { type: "password" }
},
label: function () {
return this.user;
}
});
</script>
<script type="text/html" data-help-name="xmpp-server">
<p>The connection to an XMPP server to send and receive messages.</p>
<p>Connects to the standard C2S port 5222 on the server.</p>
<p>The JID is the full username of the client used to connect to the server
and must contain the resolvable fdqn of the server.</p>
<p>The nickname is optional.</p>
</script>

270
92-xmpp.js 100644
View File

@ -0,0 +1,270 @@
module.exports = function(RED) {
"use strict";
var XMPP = require('simple-xmpp');
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
function XMPPServerNode(n) {
RED.nodes.createNode(this,n);
this.server = n.server;
this.port = n.port;
this.nickname = n.nickname;
this.username = n.user;
var credentials = this.credentials;
if (credentials) {
this.password = credentials.password;
}
this.client = new XMPP.SimpleXMPP();
this.connected = false;
var that = this;
this.client.con = function() {
if (that.connected === false ) {
that.connected = true;
that.client.connect({
jid : that.username,
password : that.password,
host : that.server,
port : that.port,
//skipPresence : true,
reconnect : true,
preferred : "PLAIN"
});
}
}
that.client.on('online', function(data) {
that.connected = true;
that.client.setPresence('online', data.jid.user+' is online');
that.log('connected as '+data.jid.user+' to '+data.jid._domain+":5222");
});
that.client.on('close', function() {
that.connected = false;
that.log('connection closed');
});
this.on("close", function(done) {
that.client.setPresence('offline');
that.client.disconnect();
if (that.client.conn) { that.client.conn.end(); }
that.client = null;
done();
});
}
RED.nodes.registerType("xmpp-server",XMPPServerNode,{
credentials: {
password: {type: "password"}
}
});
function XmppInNode(n) {
RED.nodes.createNode(this,n);
this.server = n.server;
this.serverConfig = RED.nodes.getNode(this.server);
this.nick = this.serverConfig.nickname || this.serverConfig.username.split("@")[0];
this.join = n.join || false;
this.sendAll = n.sendObject;
this.from = n.to || "";
var node = this;
var xmpp = this.serverConfig.client;
xmpp.on('online', function(data) {
node.status({fill:"green",shape:"dot",text:"connected"});
if ((node.join) && (node.from !== "")) {
// disable chat history
var to = node.to+'/'+node.nick;
var stanza = new xmpp.Element('presence', {"to": to}).
c('x', { xmlns: 'http://jabber.org/protocol/muc' }).
c('history', { maxstanzas:0, seconds:1 });
xmpp.conn.send(stanza);
xmpp.join(to);
}
});
// xmpp.on('chat', function(from, message) {
// var msg = { topic:from, payload:message };
// if (!node.join && ((node.from === "") || (node.from === from))) {
// node.send([msg,null]);
// }
// });
xmpp.on('stanza', function(stanza) {
if (stanza.is('message')) {
if (stanza.attrs.type == 'chat') {
//console.log(stanza);
var body = stanza.getChild('body');
if (body) {
var msg = { payload:body.getText() };
var ids = stanza.attrs.from.split('/');
if (ids[1].length !== 36) {
msg.topic = stanza.attrs.from
}
else { msg.topic = ids[0]; }
if (!node.join && ((node.from === "") || (node.from === stanza.attrs.from))) {
node.send([msg,null]);
}
}
}
}
});
xmpp.on('groupchat', function(conference, from, message, stamp) {
var msg = { topic:from, payload:message, room:conference };
if (from != node.nick) {
if ((node.join) && (node.from === conference)) {
node.send([msg,null]);
}
}
});
//xmpp.on('chatstate', function(from, state) {
//console.log('%s is currently %s', from, state);
//var msg = { topic:from, payload: {presence:state} };
//node.send([null,msg]);
//});
xmpp.on('buddy', function(jid, state, statusText) {
node.log(jid+" is "+state+" : "+statusText);
var msg = { topic:jid, payload: { presence:state, status:statusText} };
node.send([null,msg]);
});
// xmpp.on('groupbuddy', function(conference, from, state, statusText) {
// //console.log('%s: %s is in %s state - %s',conference, from, state, statusText);
// var msg = { topic:from, payload: { presence:state, status:statusText}, room:conference };
// });
xmpp.on('error', function(err) {
if (RED.settings.verbose) { node.log(err); }
if (err.hasOwnProperty("stanza")) {
if (err.stanza.name === 'stream:error') { node.error("stream:error - bad login id/pwd ?",err); }
else { node.error(err.stanza.name,err); }
node.status({fill:"red",shape:"ring",text:"bad login"});
}
else {
if (err.errno === "ETIMEDOUT") {
node.error("Timeout connecting to server",err);
node.status({fill:"red",shape:"ring",text:"timeout"});
}
else if (err === "XMPP authentication failure") {
node.error(err,err);
node.status({fill:"red",shape:"ring",text:"XMPP authentication failure"});
}
else {
node.error(err.errno,err);
node.status({fill:"red",shape:"ring",text:"error"});
}
}
});
xmpp.on('subscribe', function(from) {
xmpp.acceptSubscription(from);
});
// Now actually make the connection
try {
node.status({fill:"grey",shape:"dot",text:"connecting"});
xmpp.con();
}
catch(e) {
node.error("Bad xmpp configuration");
node.status({fill:"red",shape:"ring",text:"not connected"});
}
node.on("close", function() {
node.status({});
});
}
RED.nodes.registerType("xmpp in",XmppInNode);
function XmppOutNode(n) {
RED.nodes.createNode(this,n);
this.server = n.server;
this.serverConfig = RED.nodes.getNode(this.server);
this.nick = this.serverConfig.nickname || this.serverConfig.username.split("@")[0];
this.join = n.join || false;
this.sendAll = n.sendObject;
this.to = n.to || "";
var node = this;
var xmpp = this.serverConfig.client;
xmpp.on('online', function(data) {
node.status({fill:"green",shape:"dot",text:"connected"});
if ((node.join) && (node.from !== "")) {
// disable chat history
var to = node.to+'/'+node.nick;
var stanza = new xmpp.Element('presence', {"to": to}).
c('x', { xmlns: 'http://jabber.org/protocol/muc' }).
c('history', { maxstanzas:0, seconds:1 });
xmpp.conn.send(stanza);
xmpp.join(to);
}
});
xmpp.on('error', function(err) {
if (RED.settings.verbose) { node.log(err); }
if (err.hasOwnProperty("stanza")) {
if (err.stanza.name === 'stream:error') { node.error("stream:error - bad login id/pwd ?",err); }
else { node.error(err.stanza.name,err); }
node.status({fill:"red",shape:"ring",text:"bad login"});
}
else {
if (err.errno === "ETIMEDOUT") {
node.error("Timeout connecting to server",err);
node.status({fill:"red",shape:"ring",text:"timeout"});
}
else if (err === "XMPP authentication failure") {
node.error(err,err);
node.status({fill:"red",shape:"ring",text:"XMPP authentication failure"});
}
else {
node.error(err.errno,err);
node.status({fill:"red",shape:"ring",text:"error"});
}
}
});
// Now actually make the connection
try {
node.status({fill:"grey",shape:"dot",text:"connecting"});
xmpp.con();
}
catch(e) {
node.error("Bad xmpp configuration");
node.status({fill:"red",shape:"ring",text:"not connected"});
}
node.on("input", function(msg) {
if (msg.presence) {
if (['away', 'dnd', 'xa', 'chat'].indexOf(msg.presence) > -1 ) {
xmpp.setPresence(msg.presence, msg.payload);
}
else { node.warn("Can't set presence - invalid value: "+msg.presence); }
}
else {
var to = node.to || msg.topic || "";
if (to !== "") {
if (node.sendAll) {
xmpp.send(to, JSON.stringify(msg), node.join);
}
else if (msg.payload) {
if (typeof(msg.payload) === "object") {
xmpp.send(to, JSON.stringify(msg.payload), node.join);
}
else {
xmpp.send(to, msg.payload.toString(), node.join);
}
}
}
}
});
node.on("close", function() {
node.status({});
});
}
RED.nodes.registerType("xmpp out",XmppOutNode);
}

14
LICENSE 100644
View File

@ -0,0 +1,14 @@
Copyright 2016 JS Foundation and other contributors, https://js.foundation/
Copyright 2013-2016 IBM Corp.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

45
README.md 100644
View File

@ -0,0 +1,45 @@
node-red-node-xmpp
==================
A <a href="http://nodered.org" target="_new">Node-RED</a> node to talk to an XMPP server.
Install
-------
Run the following command in your Node-RED user directory - typically `~/.node-red`
npm install node-red-node-xmpp
Usage
-----
Provides two nodes - one to send messages, and one to receive.
### Receive
Connects to an XMPP server to receive messages.</p>
The **Buddy** field is the id of the buddy or room you want to receive messages from.
Incoming messages will appear as `msg.payload` on the first output, while `msg.topic` will contain who it is from.
The second output will show the presence and status of a user in `msg.payload`.
Again `msg.topic` will hold the user.
### Send
Connects to an XMPP server to send messages.
The **To** field is optional. If not set the `msg.topic` property of the message is used to set that value.
If you are joining a chat room then the **To** field must be filled in with the room name.
You may also send a msg with `msg.presence` to set your presence to one of
1. chat
2. away
3. dnd
4. xa
If you do this then the `msg.payload` is used to set your status message.

BIN
icons/xmpp.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

24
package.json 100644
View File

@ -0,0 +1,24 @@
{
"name" : "node-red-node-xmpp",
"version" : "0.2.4",
"description" : "A Node-RED node to talk to an XMPP server",
"dependencies" : {
"simple-xmpp" : "^1.3.1"
},
"repository" : {
"type":"git",
"url":"https://github.com/node-red/node-red-nodes/tree/master/social/xmpp"
},
"license": "Apache-2.0",
"keywords": [ "node-red", "xmpp" ],
"node-red" : {
"nodes" : {
"xmpp": "92-xmpp.js"
}
},
"author": {
"name": "Dave Conway-Jones",
"email": "ceejay@vnet.ibm.com",
"url": "http://nodered.org"
}
}