Twilio node - allow credentials to be provided in node

This commit is contained in:
Nick O'Leary 2014-04-09 11:23:46 +01:00
parent 517f6346f9
commit a0e00b9fab
2 changed files with 211 additions and 50 deletions

View File

@ -16,6 +16,17 @@
-->
<script type="text/x-red" data-template-name="twilio out">
<div class="form-row" id="node-input-credentials-row">
<label for="node-input-creds"><i class="icon-folder-close"></i> Credentials</label>
<select id="node-input-creds">
<option value="global">Use global credentials</option>
<option value="local">Use local credentials</option>
</select>
</div>
<div class="form-row" id="node-input-twilio-row">
<label for="node-input-twilio"><i class="icon-user"></i> Twilio</label>
<input type="text" id="node-input-twilio">
</div>
<div class="form-row">
<label for="node-input-number"><i class="icon-envelope"></i> SMS to</label>
<input type="text" id="node-input-number" placeholder="01234 5678901">
@ -24,36 +35,136 @@
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-tips">Tip - leave Number blank to use <b>msg.topic</b> to set the number.</div>
</script>
<script type="text/x-red" data-help-name="twilio out">
<p>Uses Twilio to send the <b>msg.payload</b> as a SMS to the configured number.</p>
<p>Uses <b>msg.topic</b> to set the phone number, if not already set in the properties.</p>
<p>You MUST configure both your Account SID and the Auth Token. Either into settings.js like this</p>
<p><pre>twilio: { account:'My-ACCOUNT-SID', authtoken:'TWILIO-TOKEN', from:'FROM-NUMBER' },</pre></p>
<p>Or as a twiliokey.js file in the directory <b>above</b> node-red.<p>
<p><pre>module.exports = { account:'My-ACCOUNT-SID', authtoken:'TWILIO-TOKEN',from:'FROM-NUMBER' }</pre></p>
<p>Sends an SMS message using the Twilio service.</p>
<p><code>msg.payload</code> is used as the body of the message. The node can be configured with the number
to send the message to. Alternatively, if the number is left blank, it can be set using <code>msg.topic</code>.</p>
<p>You must have an account with Twilio to use this node. You can register for one <a href="https://www.twilio.com/">here</a>.</p>
<p>You can either set your account details within the node, or provide it globally using either the settings file or a file
called 'twiliokey.js' located in the directory above node-red.</p>
<p>To use the settings.js file, add an entry such as:
<pre>twilio: { account:'My-ACCOUNT-SID', authtoken:'TWILIO-TOKEN', from:'FROM-NUMBER' }</pre></p>
<p>To use the 'twiliokey.js' file in the directory <b>above</b> node-red, use the following format:
<pre>module.exports = { account:'My-ACCOUNT-SID', authtoken:'TWILIO-TOKEN',from:'FROM-NUMBER' }</pre></p>
</script>
<script type="text/x-red" data-template-name="twilio-api">
<div class="form-row">
<label for="node-config-input-sid">Account SID</label>
<input type="text" id="node-config-input-sid">
</div>
<div class="form-row">
<label for="node-config-input-from"><i class="icon-envelope"></i> From</label>
<input type="text" id="node-config-input-from" placeholder="01234 5678901">
</div>
<div class="form-row">
<label for="node-config-input-token"><i class="icon-lock"></i> Token</label>
<input type="password" id="node-config-input-token">
</div>
<div class="form-row">
<label for="node-config-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-config-input-name" placeholder="Name">
</div>
</script>
<script type="text/javascript">
RED.nodes.registerType('twilio out',{
category: 'output',
defaults: {
number: {value:""},
name: {value:""}
},
color:"#ed1c24",
inputs:1,
outputs:0,
icon: "twilio.png",
align: "right",
label: function() {
return this.name||this.title||"twilio";
},
labelStyle: function() {
return this.name?"node_label_italic":"";
}
});
(function() {
var hasGlobal = false;
$.getJSON('twilio-api/global',function(data) {
hasGlobal = data.hasToken;
});
RED.nodes.registerType('twilio-api',{
category: 'config',
defaults: {
sid: {value:"",required:true},
from: {value:"",required:true},
// token -> credentials
name: { value: ""}
},
label: function() {
return this.name||this.from;
},
oneditprepare: function() {
$.getJSON('twilio-api/'+this.id,function(data) {
if (data.hasToken) {
$('#node-config-input-token').val('__PWRD__');
} else {
$('#node-config-input-token').val('');
}
});
},
oneditsave: function() {
var newToken = $('#node-config-input-token').val();
if (newToken != '__PWRD__') {
var credentials = {};
credentials.token = newToken;
$.ajax({
url: 'twilio-api/'+this.id,
type: 'POST',
data: credentials,
success:function(result){}
});
}
},
ondelete: function() {
$.ajax({
url: 'twilio-api/'+this.id,
type: 'DELETE',
success: function(result) {}
});
}
});
RED.nodes.registerType('twilio out',{
category: 'output',
defaults: {
twilio:{type:"twilio-api",validate:function(v) {
return hasGlobal || (v && v!="_ADD_");
}},
number: {value:""},
name: {value:""}
},
color:"#FF595F",
inputs:1,
outputs:0,
icon: "twilio.png",
align: "right",
label: function() {
return this.name||this.title||"twilio";
},
labelStyle: function() {
return this.name?"node_label_italic":"";
},
oneditprepare: function() {
if (hasGlobal) {
$("#node-input-creds").change(function() {
var val = $(this).val();
if (val == "global") {
$("#node-input-twilio-row").hide();
} else {
$("#node-input-twilio-row").show();
}
});
$("#node-input-credentials-row").show();
if (!this.twilio) {
$("#node-input-creds").val("global");
} else {
$("#node-input-creds").val("local");
}
$("#node-input-creds").change();
} else {
$("#node-input-credentials-row").hide();
}
}
});
})();
</script>

View File

@ -17,47 +17,97 @@
var RED = require(process.env.NODE_RED_HOME+"/red/red");
var util = require('util');
// Either add a line like this to settings.js
// twilio: { account:'My-ACCOUNT-SID', authtoken:'TWILIO-TOKEN',from:'FROM-NUMBER' },
// Or as a twiliokey.js file in the directory ABOVE node-red.
// module.exports = { account:'My-ACCOUNT-SID', authtoken:'TWILIO-TOKEN',from:'FROM-NUMBER' }
var twilio = require('twilio');
try {
var twiliokey = RED.settings.twilio || require(process.env.NODE_RED_HOME+"/../twiliokey.js");
}
catch(err) {
util.log("[56-twilio.js] Error: Failed to load Twilio credentials");
}
if (twiliokey) {
var twilioClient = require('twilio')(twiliokey.account, twiliokey.authtoken);
var fromNumber = twiliokey.from;
}
var querystring = require('querystring');
RED.httpAdmin.get('/twilio-api/global',function(req,res) {
res.send(JSON.stringify({hasToken:!(twiliokey && twiliokey.account && twiliokey.authtoken)}));
});
RED.httpAdmin.get('/twilio-api/:id',function(req,res) {
var credentials = RED.nodes.getCredentials(req.params.id);
if (credentials) {
res.send(JSON.stringify({hasToken:(credentials.token&&credentials.token!="")}));
} else {
res.send(JSON.stringify({}));
}
});
RED.httpAdmin.delete('/twilio-api/:id',function(req,res) {
RED.nodes.deleteCredentials(req.params.id);
res.send(200);
});
RED.httpAdmin.post('/twilio-api/:id',function(req,res) {
var body = "";
req.on('data', function(chunk) {
body+=chunk;
});
req.on('end', function(){
var newCreds = querystring.parse(body);
var credentials = RED.nodes.getCredentials(req.params.id)||{};
if (newCreds.token == "") {
delete credentials.token;
} else {
credentials.token = newCreds.token;
}
RED.nodes.addCredentials(req.params.id,credentials);
res.send(200);
});
});
function TwilioAPINode(n) {
RED.nodes.createNode(this,n);
this.sid = n.sid;
this.from = n.from;
this.name = n.name;
var credentials = RED.nodes.getCredentials(n.id);
if (credentials) {
this.token = credentials.token;
}
}
RED.nodes.registerType("twilio-api",TwilioAPINode);
function TwilioOutNode(n) {
RED.nodes.createNode(this,n);
this.number = n.number;
this.api = RED.nodes.getNode(n.twilio);
if (this.api) {
this.twilioClient = twilio(this.api.sid,this.api.token);
this.fromNumber = this.api.from;
} else if (twiliokey) {
this.twilioClient = twilio(twiliokey.account, twiliokey.authtoken);
this.fromNumber = twiliokey.from;
} else {
this.error("missing twilio credentials");
return;
}
var node = this;
this.on("input",function(msg) {
if (typeof(msg.payload) == 'object') {
msg.payload = JSON.stringify(msg.payload);
}
if (twiliokey) {
try {
// Send SMS
var tonum = node.number || msg.topic;
twilioClient.sendMessage( {to: tonum, from: fromNumber, body: msg.payload}, function(err, response) {
if (err) node.error(err);
//console.log(response);
});
}
catch (err) {
node.error(err);
}
}
else {
node.warn("Twilio credentials not set/found. See node info.");
try {
// Send SMS
var tonum = node.number || msg.topic;
node.twilioClient.sendMessage( {to: tonum, from: node.fromNumber, body: msg.payload}, function(err, response) {
if (err) {
node.error(err);
}
//console.log(response);
});
} catch (err) {
node.error(err);
}
});
}