Something went wrong with the authentication process. The following error was returned:
'+ - '
'+error.statusCode+': '+error.data+'
'+ - 'One known cause of this type of failure is if the clock is wrong on system running Node-RED.'; - res.send(resp) + + RED.httpAdmin.get('/twitter/:id', function(req,res) { + var credentials = RED.nodes.getCredentials(req.params.id); + if (credentials) { + res.send(JSON.stringify({sn:credentials.screen_name})); } else { - credentials.oauth_token = oauth_token; - credentials.oauth_token_secret = oauth_token_secret; - res.redirect('https://twitter.com/oauth/authorize?oauth_token='+oauth_token) - RED.nodes.addCredentials(req.params.id,credentials); + res.send(JSON.stringify({})); } }); -}); - -RED.httpAdmin.get('/twitter/:id/auth/callback', function(req, res, next){ - var credentials = RED.nodes.getCredentials(req.params.id); - credentials.oauth_verifier = req.query.oauth_verifier; - - oa.getOAuthAccessToken( - credentials.oauth_token, - credentials.token_secret, - credentials.oauth_verifier, - function(error, oauth_access_token, oauth_access_token_secret, results){ - if (error){ - console.log(error); - res.send("yeah something broke."); + + RED.httpAdmin.delete('/twitter/:id', function(req,res) { + RED.nodes.deleteCredentials(req.params.id); + res.send(200); + }); + + RED.httpAdmin.get('/twitter/:id/auth', function(req, res){ + var credentials = {}; + oa.getOAuthRequestToken({ + oauth_callback: req.query.callback + },function(error, oauth_token, oauth_token_secret, results){ + if (error) { + var resp = '
Something went wrong with the authentication process. The following error was returned:
'+ + '
'+error.statusCode+': '+error.data+'
'+ + 'One known cause of this type of failure is if the clock is wrong on system running Node-RED.'; + res.send(resp) } else { - credentials = {}; - credentials.access_token = oauth_access_token; - credentials.access_token_secret = oauth_access_token_secret; - credentials.screen_name = "@"+results.screen_name; + credentials.oauth_token = oauth_token; + credentials.oauth_token_secret = oauth_token_secret; + res.redirect('https://twitter.com/oauth/authorize?oauth_token='+oauth_token) RED.nodes.addCredentials(req.params.id,credentials); - res.send("
Authorised - you can close this window and return to Node-RED"); } - } - ); -}); + }); + }); + + RED.httpAdmin.get('/twitter/:id/auth/callback', function(req, res, next){ + var credentials = RED.nodes.getCredentials(req.params.id); + credentials.oauth_verifier = req.query.oauth_verifier; + + oa.getOAuthAccessToken( + credentials.oauth_token, + credentials.token_secret, + credentials.oauth_verifier, + function(error, oauth_access_token, oauth_access_token_secret, results){ + if (error){ + console.log(error); + res.send("yeah something broke."); + } else { + credentials = {}; + credentials.access_token = oauth_access_token; + credentials.access_token_secret = oauth_access_token_secret; + credentials.screen_name = "@"+results.screen_name; + RED.nodes.addCredentials(req.params.id,credentials); + res.send("Authorised - you can close this window and return to Node-RED"); + } + } + ); + }); +} diff --git a/nodes/core/social/32-feedparse.js b/nodes/core/social/32-feedparse.js index 77ae4a8d2..ad5e4995b 100644 --- a/nodes/core/social/32-feedparse.js +++ b/nodes/core/social/32-feedparse.js @@ -14,58 +14,58 @@ * limitations under the License. **/ -var RED = require(process.env.NODE_RED_HOME+"/red/red"); -var FeedParser = require("feedparser"); -var request = require("request"); - -function FeedParseNode(n) { - RED.nodes.createNode(this,n); - this.url = n.url; - this.interval = (parseInt(n.interval)||15)*60000; - var node = this; - this.interval_id = null; - this.seen = {}; - if (this.url !== "") { - var getFeed = function() { - request(node.url,function(err) { - if (err) node.error(err); - }) - .pipe(new FeedParser({feedurl:node.url})) - .on('error', function(error) { - node.error(error); +module.exports = function(RED) { + var FeedParser = require("feedparser"); + var request = require("request"); + + function FeedParseNode(n) { + RED.nodes.createNode(this,n); + this.url = n.url; + this.interval = (parseInt(n.interval)||15)*60000; + var node = this; + this.interval_id = null; + this.seen = {}; + if (this.url !== "") { + var getFeed = function() { + request(node.url,function(err) { + if (err) node.error(err); }) - .on('meta', function (meta) {}) - .on('readable', function () { - var stream = this, article; - while (article = stream.read()) { - if (!(article.guid in node.seen) || ( node.seen[article.guid] != 0 && node.seen[article.guid] != article.date.getTime())) { - node.seen[article.guid] = article.date?article.date.getTime():0; - var msg = { - topic:article.origlink||article.link, - payload: article.description, - article: article - }; - node.send(msg); + .pipe(new FeedParser({feedurl:node.url})) + .on('error', function(error) { + node.error(error); + }) + .on('meta', function (meta) {}) + .on('readable', function () { + var stream = this, article; + while (article = stream.read()) { + if (!(article.guid in node.seen) || ( node.seen[article.guid] != 0 && node.seen[article.guid] != article.date.getTime())) { + node.seen[article.guid] = article.date?article.date.getTime():0; + var msg = { + topic:article.origlink||article.link, + payload: article.description, + article: article + }; + node.send(msg); + } } - } - }) - .on('end', function () { - }); - }; - this.interval_id = setInterval(getFeed,node.interval); - getFeed(); - - } else { - this.error("Invalid url"); - } -} - -RED.nodes.registerType("feedparse",FeedParseNode); - -FeedParseNode.prototype.close = function() { - if (this.interval_id != null) { - clearInterval(this.interval_id); + }) + .on('end', function () { + }); + }; + this.interval_id = setInterval(getFeed,node.interval); + getFeed(); + + } else { + this.error("Invalid url"); + } } -} - + + RED.nodes.registerType("feedparse",FeedParseNode); + + FeedParseNode.prototype.close = function() { + if (this.interval_id != null) { + clearInterval(this.interval_id); + } + } +} diff --git a/nodes/core/social/61-email.js b/nodes/core/social/61-email.js index 4f017e18c..70eeb5106 100644 --- a/nodes/core/social/61-email.js +++ b/nodes/core/social/61-email.js @@ -14,247 +14,248 @@ * limitations under the License. **/ -var RED = require(process.env.NODE_RED_HOME+"/red/red"); -var util = require('util'); -var nodemailer = require("nodemailer"); -var Imap = null; -try { - Imap = require('imap'); -} catch (e) { - util.log("[61-email.js] - imap npm not installed - no inbound email available"); -} - -//console.log(nodemailer.Transport.transports.SMTP.wellKnownHosts); - -// module.exports = { service: "Gmail", user: "blahblah@gmail.com", pass: "password", server: "imap.gmail.com", port: "993" } -try { var globalkeys = RED.settings.email || require(process.env.NODE_RED_HOME+"/../emailkeys.js"); } -catch(err) { } - -function EmailNode(n) { - RED.nodes.createNode(this,n); - this.topic = n.topic; - this.name = n.name; - this.outserver = n.server; - this.outport = n.port; - var flag = false; - var credentials = RED.nodes.getCredentials(n.id); - if ((credentials) && (credentials.hasOwnProperty("userid"))) { this.userid = credentials.userid; } - else { - if (globalkeys) { this.userid = globalkeys.user; flag = true; } - else { this.error("No e-mail userid set"); } +module.exports = function(RED) { + var util = require('util'); + var nodemailer = require("nodemailer"); + var Imap = null; + try { + Imap = require('imap'); + } catch (e) { + util.log("[61-email.js] - imap npm not installed - no inbound email available"); } - if ((credentials) && (credentials.hasOwnProperty("password"))) { this.password = credentials.password; } - else { - if (globalkeys) { this.password = globalkeys.pass; flag = true; } - else { this.error("No e-mail password set"); } - } - if (flag) { RED.nodes.addCredentials(n.id,{userid:this.userid, password:this.password, global:true}); } - var node = this; - - var smtpTransport = nodemailer.createTransport("SMTP",{ - //service: emailkey.service, - // { - //transport: 'SMTP', - host: node.outserver, - port: node.outport, - requiresAuth: true, - secureConnection: true, - //domains: [ 'gmail.com', 'googlemail.com' ], - //}, - auth: { - user: node.userid, - pass: node.password + + //console.log(nodemailer.Transport.transports.SMTP.wellKnownHosts); + + // module.exports = { service: "Gmail", user: "blahblah@gmail.com", pass: "password", server: "imap.gmail.com", port: "993" } + try { var globalkeys = RED.settings.email || require(process.env.NODE_RED_HOME+"/../emailkeys.js"); } + catch(err) { } + + function EmailNode(n) { + RED.nodes.createNode(this,n); + this.topic = n.topic; + this.name = n.name; + this.outserver = n.server; + this.outport = n.port; + var flag = false; + var credentials = RED.nodes.getCredentials(n.id); + if ((credentials) && (credentials.hasOwnProperty("userid"))) { this.userid = credentials.userid; } + else { + if (globalkeys) { this.userid = globalkeys.user; flag = true; } + else { this.error("No e-mail userid set"); } } - }); - - this.on("input", function(msg) { - //node.log("email :",this.id,this.topic," received",msg.payload); - if (msg != null) { - if (smtpTransport) { - smtpTransport.sendMail({ - from: node.userid, // sender address - to: node.name, // comma separated list of receivers - subject: msg.topic, // subject line - text: msg.payload // plaintext body - }, function(error, response) { - if (error) { - node.error(error); - } else { - node.log("Message sent: " + response.message); + if ((credentials) && (credentials.hasOwnProperty("password"))) { this.password = credentials.password; } + else { + if (globalkeys) { this.password = globalkeys.pass; flag = true; } + else { this.error("No e-mail password set"); } + } + if (flag) { RED.nodes.addCredentials(n.id,{userid:this.userid, password:this.password, global:true}); } + var node = this; + + var smtpTransport = nodemailer.createTransport("SMTP",{ + //service: emailkey.service, + // { + //transport: 'SMTP', + host: node.outserver, + port: node.outport, + requiresAuth: true, + secureConnection: true, + //domains: [ 'gmail.com', 'googlemail.com' ], + //}, + auth: { + user: node.userid, + pass: node.password + } + }); + + this.on("input", function(msg) { + //node.log("email :",this.id,this.topic," received",msg.payload); + if (msg != null) { + if (smtpTransport) { + smtpTransport.sendMail({ + from: node.userid, // sender address + to: node.name, // comma separated list of receivers + subject: msg.topic, // subject line + text: msg.payload // plaintext body + }, function(error, response) { + if (error) { + node.error(error); + } else { + node.log("Message sent: " + response.message); + } + }); + } + else { node.warn("No Email credentials found. See info panel."); } + } + }); + } + RED.nodes.registerType("e-mail",EmailNode); + + function EmailInNode(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.repeat = n.repeat * 1000 || 300000; + this.inserver = n.server || emailkey.server || "imap.gmail.com"; + this.inport = n.port || emailkey.port || "993"; + var flag = false; + var credentials = RED.nodes.getCredentials(n.id); + if ((credentials) && (credentials.hasOwnProperty("userid"))) { this.userid = credentials.userid; } + else { + if (globalkeys) { this.userid = globalkeys.user; flag = true; } + else { this.error("No e-mail userid set"); } + } + if ((credentials) && (credentials.hasOwnProperty("password"))) { this.password = credentials.password; } + else { + if (globalkeys) { this.password = globalkeys.pass; flag = true; } + else { this.error("No e-mail password set"); } + } + if (flag) { RED.nodes.addCredentials(n.id,{userid:this.userid, password:this.password, global:true}); } + var node = this; + this.interval_id = null; + var oldmail = {}; + + var imap = new Imap({ + user: node.userid, + password: node.password, + host: node.inserver, + port: node.inport, + tls: true, + tlsOptions: { rejectUnauthorized: false }, + connTimeout: node.repeat, + authTimeout: node.repeat + }); + + if (!isNaN(this.repeat) && this.repeat > 0) { + node.log("repeat = "+this.repeat); + this.interval_id = setInterval( function() { + node.emit("input",{}); + }, this.repeat ); + } + + this.on("input", function(msg) { + imap.once('ready', function() { + var pay = {}; + imap.openBox('INBOX', true, function(err, box) { + if (box.messages.total > 0) { + var f = imap.seq.fetch(box.messages.total + ':*', { bodies: ['HEADER.FIELDS (FROM SUBJECT DATE)','TEXT'] }); + f.on('message', function(msg, seqno) { + node.log('message: #'+ seqno); + var prefix = '(#' + seqno + ') '; + msg.on('body', function(stream, info) { + var buffer = ''; + stream.on('data', function(chunk) { + buffer += chunk.toString('utf8'); + }); + stream.on('end', function() { + if (info.which !== 'TEXT') { + pay.from = Imap.parseHeader(buffer).from[0]; + pay.topic = Imap.parseHeader(buffer).subject[0]; + pay.date = Imap.parseHeader(buffer).date[0]; + } else { + var parts = buffer.split("Content-Type"); + for (var p in parts) { + if (parts[p].indexOf("text/plain") >= 0) { + pay.payload = parts[p].split("\n").slice(1,-2).join("\n").trim(); + } + if (parts[p].indexOf("text/html") >= 0) { + pay.html = parts[p].split("\n").slice(1,-2).join("\n").trim(); + } + } + //pay.body = buffer; + } + }); + }); + msg.on('end', function() { + //node.log('Finished: '+prefix); + }); + }); + f.on('error', function(err) { + node.warn('fetch error: ' + err); + }); + f.on('end', function() { + if (JSON.stringify(pay) !== oldmail) { + node.send(pay); + oldmail = JSON.stringify(pay); + node.log('received new email: '+pay.topic); + } + else { node.log('duplicate not sent: '+pay.topic); } + imap.end(); + }); + } + else { + node.log("you have achieved inbox zero"); + imap.end(); } }); - } - else { node.warn("No Email credentials found. See info panel."); } - } - }); -} -RED.nodes.registerType("e-mail",EmailNode); - -function EmailInNode(n) { - RED.nodes.createNode(this,n); - this.name = n.name; - this.repeat = n.repeat * 1000 || 300000; - this.inserver = n.server || emailkey.server || "imap.gmail.com"; - this.inport = n.port || emailkey.port || "993"; - var flag = false; - var credentials = RED.nodes.getCredentials(n.id); - if ((credentials) && (credentials.hasOwnProperty("userid"))) { this.userid = credentials.userid; } - else { - if (globalkeys) { this.userid = globalkeys.user; flag = true; } - else { this.error("No e-mail userid set"); } - } - if ((credentials) && (credentials.hasOwnProperty("password"))) { this.password = credentials.password; } - else { - if (globalkeys) { this.password = globalkeys.pass; flag = true; } - else { this.error("No e-mail password set"); } - } - if (flag) { RED.nodes.addCredentials(n.id,{userid:this.userid, password:this.password, global:true}); } - var node = this; - this.interval_id = null; - var oldmail = {}; - - var imap = new Imap({ - user: node.userid, - password: node.password, - host: node.inserver, - port: node.inport, - tls: true, - tlsOptions: { rejectUnauthorized: false }, - connTimeout: node.repeat, - authTimeout: node.repeat - }); - - if (!isNaN(this.repeat) && this.repeat > 0) { - node.log("repeat = "+this.repeat); - this.interval_id = setInterval( function() { - node.emit("input",{}); - }, this.repeat ); - } - - this.on("input", function(msg) { - imap.once('ready', function() { - var pay = {}; - imap.openBox('INBOX', true, function(err, box) { - if (box.messages.total > 0) { - var f = imap.seq.fetch(box.messages.total + ':*', { bodies: ['HEADER.FIELDS (FROM SUBJECT DATE)','TEXT'] }); - f.on('message', function(msg, seqno) { - node.log('message: #'+ seqno); - var prefix = '(#' + seqno + ') '; - msg.on('body', function(stream, info) { - var buffer = ''; - stream.on('data', function(chunk) { - buffer += chunk.toString('utf8'); - }); - stream.on('end', function() { - if (info.which !== 'TEXT') { - pay.from = Imap.parseHeader(buffer).from[0]; - pay.topic = Imap.parseHeader(buffer).subject[0]; - pay.date = Imap.parseHeader(buffer).date[0]; - } else { - var parts = buffer.split("Content-Type"); - for (var p in parts) { - if (parts[p].indexOf("text/plain") >= 0) { - pay.payload = parts[p].split("\n").slice(1,-2).join("\n").trim(); - } - if (parts[p].indexOf("text/html") >= 0) { - pay.html = parts[p].split("\n").slice(1,-2).join("\n").trim(); - } - } - //pay.body = buffer; - } - }); - }); - msg.on('end', function() { - //node.log('Finished: '+prefix); - }); - }); - f.on('error', function(err) { - node.warn('fetch error: ' + err); - }); - f.on('end', function() { - if (JSON.stringify(pay) !== oldmail) { - node.send(pay); - oldmail = JSON.stringify(pay); - node.log('received new email: '+pay.topic); - } - else { node.log('duplicate not sent: '+pay.topic); } - imap.end(); - }); - } - else { - node.log("you have achieved inbox zero"); - imap.end(); - } }); + imap.on('error', function(err) { + node.log(err); + }); + imap.connect(); }); - imap.on('error', function(err) { - node.log(err); + + this.on("error", function(err) { + node.log("error: ",err); }); - imap.connect(); - }); - - this.on("error", function(err) { - node.log("error: ",err); - }); - - this.on("close", function() { - if (this.interval_id != null) { - clearInterval(this.interval_id); - } - if (imap) { imap.destroy(); } - }); - - node.emit("input",{}); -} -if (Imap != null) { -RED.nodes.registerType("e-mail in",EmailInNode); -} - -var querystring = require('querystring'); - -RED.httpAdmin.get('/email/global',function(req,res) { - res.send(JSON.stringify({hasToken:!(globalkeys && globalkeys.userid && globalkeys.password)})); -}); - -RED.httpAdmin.get('/email/:id',function(req,res) { - var credentials = RED.nodes.getCredentials(req.params.id); - if (credentials) { - res.send(JSON.stringify({userid:credentials.userid,hasPassword:(credentials.password&&credentials.password!="")})); + + this.on("close", function() { + if (this.interval_id != null) { + clearInterval(this.interval_id); + } + if (imap) { imap.destroy(); } + }); + + node.emit("input",{}); } - else if (globalkeys && globalkeys.user && globalkeys.pass) { - RED.nodes.addCredentials(req.params.id,{userid:globalkeys.user, password:globalkeys.pass, global:true}); - credentials = RED.nodes.getCredentials(req.params.id); - res.send(JSON.stringify({userid:credentials.userid,global:credentials.global,hasPassword:(credentials.password&&credentials.password!="")})); + if (Imap != null) { + RED.nodes.registerType("e-mail in",EmailInNode); } - else { - res.send(JSON.stringify({})); - } -}); - -RED.httpAdmin.delete('/email/:id',function(req,res) { - RED.nodes.deleteCredentials(req.params.id); - res.send(200); -}); - -RED.httpAdmin.post('/email/:id',function(req,res) { - var body = ""; - req.on('data', function(chunk) { - body+=chunk; + + var querystring = require('querystring'); + + RED.httpAdmin.get('/email/global',function(req,res) { + res.send(JSON.stringify({hasToken:!(globalkeys && globalkeys.userid && globalkeys.password)})); }); - req.on('end', function(){ - var newCreds = querystring.parse(body); - var credentials = RED.nodes.getCredentials(req.params.id)||{}; - if (newCreds.userid == null || newCreds.userid == "") { - delete credentials.userid; - } else { - credentials.userid = newCreds.userid; + + RED.httpAdmin.get('/email/:id',function(req,res) { + var credentials = RED.nodes.getCredentials(req.params.id); + if (credentials) { + res.send(JSON.stringify({userid:credentials.userid,hasPassword:(credentials.password&&credentials.password!="")})); } - if (newCreds.password == "") { - delete credentials.password; - } else { - credentials.password = newCreds.password||credentials.password; + else if (globalkeys && globalkeys.user && globalkeys.pass) { + RED.nodes.addCredentials(req.params.id,{userid:globalkeys.user, password:globalkeys.pass, global:true}); + credentials = RED.nodes.getCredentials(req.params.id); + res.send(JSON.stringify({userid:credentials.userid,global:credentials.global,hasPassword:(credentials.password&&credentials.password!="")})); } - RED.nodes.addCredentials(req.params.id,credentials); + else { + res.send(JSON.stringify({})); + } + }); + + RED.httpAdmin.delete('/email/:id',function(req,res) { + RED.nodes.deleteCredentials(req.params.id); res.send(200); }); -}); + + RED.httpAdmin.post('/email/: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.userid == null || newCreds.userid == "") { + delete credentials.userid; + } else { + credentials.userid = newCreds.userid; + } + if (newCreds.password == "") { + delete credentials.password; + } else { + credentials.password = newCreds.password||credentials.password; + } + RED.nodes.addCredentials(req.params.id,credentials); + res.send(200); + }); + }); +} diff --git a/nodes/core/social/91-irc.js b/nodes/core/social/91-irc.js index eccacb7d1..708e67dcf 100644 --- a/nodes/core/social/91-irc.js +++ b/nodes/core/social/91-irc.js @@ -14,127 +14,128 @@ * limitations under the License. **/ -var RED = require(process.env.NODE_RED_HOME+"/red/red"); -var irc = require("irc"); -var util = require("util"); - -// The Server Definition - this opens (and closes) the connection -function IRCServerNode(n) { - RED.nodes.createNode(this,n); - this.server = n.server; - this.channel = n.channel; - this.nickname = n.nickname; - this.ircclient = null; - this.on("close", function() { - if (this.ircclient != null) { - this.ircclient.disconnect(); - } - }); -} -RED.nodes.registerType("irc-server",IRCServerNode); - - -// The Input Node -function IrcInNode(n) { - RED.nodes.createNode(this,n); - this.ircserver = n.ircserver; - this.serverConfig = RED.nodes.getNode(this.ircserver); - this.channel = n.channel || this.serverConfig.channel; - if (this.serverConfig.ircclient == null) { - this.serverConfig.ircclient = new irc.Client(this.serverConfig.server, this.serverConfig.nickname, { - channels: [this.channel] - }); - this.serverConfig.ircclient.addListener('error', function(message) { - util.log('[irc] '+ JSON.stringify(message)); - }); - } - this.ircclient = this.serverConfig.ircclient; - var node = this; - - this.ircclient.addListener('message', function (from, to, message) { - //util.log(from + ' => ' + to + ': ' + message); - var msg = { "topic":from, "from":from, "to":to, "payload":message }; - node.send([msg,null]); - }); - this.ircclient.addListener('pm', function(from, message) { - var msg = { "topic":from, "from":from, "to":"PRIV", "payload":message }; - node.send([msg,null]); - }); - - this.ircclient.addListener('join', function(channel, who) { - var msg = { "payload": { "type":"join", "who":who, "channel":channel } }; - node.send([null,msg]); - node.log(who+' has joined '+channel); - }); - this.ircclient.addListener('invite', function(channel, from, message) { - var msg = { "payload": { "type":"invite", "who":from, "channel":channel, "message":message } }; - node.send([null,msg]); - node.log(from+' sent invite to '+channel+': '+message); - }); - this.ircclient.addListener('part', function(channel, who, reason) { - var msg = { "payload": { "type":"part", "who":who, "channel":channel, "reason":reason } }; - node.send([null,msg]); - node.log(who+'has left '+channel+': '+reason); - }); - this.ircclient.addListener('quit', function(nick, reason, channels, message) { - var msg = { "payload": { "type":"quit", "who":nick, "channel":channels, "reason":reason } }; - node.send([null,msg]); - node.log(nick+'has quit '+channels+': '+reason); - }); - this.ircclient.addListener('kick', function(channel, who, by, reason) { - var msg = { "payload": { "type":"kick", "who":who, "channel":channel, "by":by, "reason":reason } }; - node.send([null,msg]); - node.log(who+' was kicked from '+channel+' by '+by+': '+reason); - }); - -} -RED.nodes.registerType("irc in",IrcInNode); - - -// The Output Node -function IrcOutNode(n) { - RED.nodes.createNode(this,n); - this.sendAll = n.sendObject; - this.ircserver = n.ircserver; - this.serverConfig = RED.nodes.getNode(this.ircserver); - this.channel = n.channel || this.serverConfig.channel; - if (this.serverConfig.ircclient == null) { - this.serverConfig.ircclient = new irc.Client(this.serverConfig.server, this.serverConfig.nickname, { - channels: [this.channel] - }); - this.serverConfig.ircclient.addListener('error', function(message) { - util.log('[irc] '+ JSON.stringify(message)); - }); - } - this.ircclient = this.serverConfig.ircclient; - var node = this; - - this.on("input", function(msg) { - if (Object.prototype.toString.call( msg.raw ) === '[object Array]') { - var m = msg.raw; - for (var i = 0; i < 10; i++) { - if (typeof m[i] !== "string") { m[i] = ""; } - m[i] = m[i].replace(/"/g, ""); +module.exports = function(RED) { + var irc = require("irc"); + var util = require("util"); + + // The Server Definition - this opens (and closes) the connection + function IRCServerNode(n) { + RED.nodes.createNode(this,n); + this.server = n.server; + this.channel = n.channel; + this.nickname = n.nickname; + this.ircclient = null; + this.on("close", function() { + if (this.ircclient != null) { + this.ircclient.disconnect(); } - util.log("[irc] RAW command:"+m); - node.ircclient.send(m[0],m[1],m[2],m[3],m[4],m[5],m[6],m[7],m[8],m[9]); + }); + } + RED.nodes.registerType("irc-server",IRCServerNode); + + + // The Input Node + function IrcInNode(n) { + RED.nodes.createNode(this,n); + this.ircserver = n.ircserver; + this.serverConfig = RED.nodes.getNode(this.ircserver); + this.channel = n.channel || this.serverConfig.channel; + if (this.serverConfig.ircclient == null) { + this.serverConfig.ircclient = new irc.Client(this.serverConfig.server, this.serverConfig.nickname, { + channels: [this.channel] + }); + this.serverConfig.ircclient.addListener('error', function(message) { + util.log('[irc] '+ JSON.stringify(message)); + }); } - else { - if (msg._topic) { delete msg._topic; } - if (node.sendAll == "false") { - node.ircclient.say(node.channel, JSON.stringify(msg)); + this.ircclient = this.serverConfig.ircclient; + var node = this; + + this.ircclient.addListener('message', function (from, to, message) { + //util.log(from + ' => ' + to + ': ' + message); + var msg = { "topic":from, "from":from, "to":to, "payload":message }; + node.send([msg,null]); + }); + this.ircclient.addListener('pm', function(from, message) { + var msg = { "topic":from, "from":from, "to":"PRIV", "payload":message }; + node.send([msg,null]); + }); + + this.ircclient.addListener('join', function(channel, who) { + var msg = { "payload": { "type":"join", "who":who, "channel":channel } }; + node.send([null,msg]); + node.log(who+' has joined '+channel); + }); + this.ircclient.addListener('invite', function(channel, from, message) { + var msg = { "payload": { "type":"invite", "who":from, "channel":channel, "message":message } }; + node.send([null,msg]); + node.log(from+' sent invite to '+channel+': '+message); + }); + this.ircclient.addListener('part', function(channel, who, reason) { + var msg = { "payload": { "type":"part", "who":who, "channel":channel, "reason":reason } }; + node.send([null,msg]); + node.log(who+'has left '+channel+': '+reason); + }); + this.ircclient.addListener('quit', function(nick, reason, channels, message) { + var msg = { "payload": { "type":"quit", "who":nick, "channel":channels, "reason":reason } }; + node.send([null,msg]); + node.log(nick+'has quit '+channels+': '+reason); + }); + this.ircclient.addListener('kick', function(channel, who, by, reason) { + var msg = { "payload": { "type":"kick", "who":who, "channel":channel, "by":by, "reason":reason } }; + node.send([null,msg]); + node.log(who+' was kicked from '+channel+' by '+by+': '+reason); + }); + + } + RED.nodes.registerType("irc in",IrcInNode); + + + // The Output Node + function IrcOutNode(n) { + RED.nodes.createNode(this,n); + this.sendAll = n.sendObject; + this.ircserver = n.ircserver; + this.serverConfig = RED.nodes.getNode(this.ircserver); + this.channel = n.channel || this.serverConfig.channel; + if (this.serverConfig.ircclient == null) { + this.serverConfig.ircclient = new irc.Client(this.serverConfig.server, this.serverConfig.nickname, { + channels: [this.channel] + }); + this.serverConfig.ircclient.addListener('error', function(message) { + util.log('[irc] '+ JSON.stringify(message)); + }); + } + this.ircclient = this.serverConfig.ircclient; + var node = this; + + this.on("input", function(msg) { + if (Object.prototype.toString.call( msg.raw ) === '[object Array]') { + var m = msg.raw; + for (var i = 0; i < 10; i++) { + if (typeof m[i] !== "string") { m[i] = ""; } + m[i] = m[i].replace(/"/g, ""); + } + util.log("[irc] RAW command:"+m); + node.ircclient.send(m[0],m[1],m[2],m[3],m[4],m[5],m[6],m[7],m[8],m[9]); } else { - if (typeof msg.payload === "object") { msg.payload = JSON.stringify(msg.payload); } - if (node.sendAll == "pay") { - node.ircclient.say(node.channel, msg.payload); + if (msg._topic) { delete msg._topic; } + if (node.sendAll == "false") { + node.ircclient.say(node.channel, JSON.stringify(msg)); } else { - var to = msg.topic || node.channel; - node.ircclient.say(to, msg.payload); + if (typeof msg.payload === "object") { msg.payload = JSON.stringify(msg.payload); } + if (node.sendAll == "pay") { + node.ircclient.say(node.channel, msg.payload); + } + else { + var to = msg.topic || node.channel; + node.ircclient.say(to, msg.payload); + } } } - } - }); + }); + } + RED.nodes.registerType("irc out",IrcOutNode); } -RED.nodes.registerType("irc out",IrcOutNode); diff --git a/nodes/core/storage/28-tail.js b/nodes/core/storage/28-tail.js index fe76a920a..bd30df6cf 100644 --- a/nodes/core/storage/28-tail.js +++ b/nodes/core/storage/28-tail.js @@ -14,43 +14,44 @@ * limitations under the License. **/ -var RED = require(process.env.NODE_RED_HOME+"/red/red"); -var fs = require("fs"); -var spawn = require('child_process').spawn; - -function TailNode(n) { - RED.nodes.createNode(this,n); - - this.filename = n.filename; - this.split = n.split; - var node = this; - - var err = ""; - var tail = spawn("tail", ["-f", this.filename]); - tail.stdout.on("data", function (data) { - var msg = {topic:node.filename}; - if (node.split) { - var strings = data.toString().split("\n"); - for (s in strings) { - if (strings[s] != "") { - msg.payload = strings[s]; - node.send(msg); +module.exports = function(RED) { + var fs = require("fs"); + var spawn = require('child_process').spawn; + + function TailNode(n) { + RED.nodes.createNode(this,n); + + this.filename = n.filename; + this.split = n.split; + var node = this; + + var err = ""; + var tail = spawn("tail", ["-f", this.filename]); + tail.stdout.on("data", function (data) { + var msg = {topic:node.filename}; + if (node.split) { + var strings = data.toString().split("\n"); + for (s in strings) { + if (strings[s] != "") { + msg.payload = strings[s]; + node.send(msg); + } } } - } - else { - msg.payload = data.toString(); - node.send(msg); - } - }); - - tail.stderr.on("data", function(data) { - node.warn(data.toString()); - }); - - this.on("close", function() { - if (tail) tail.kill(); - }); + else { + msg.payload = data.toString(); + node.send(msg); + } + }); + + tail.stderr.on("data", function(data) { + node.warn(data.toString()); + }); + + this.on("close", function() { + if (tail) tail.kill(); + }); + } + + RED.nodes.registerType("tail",TailNode); } - -RED.nodes.registerType("tail",TailNode); diff --git a/nodes/core/storage/50-file.js b/nodes/core/storage/50-file.js index c1b42f638..026d4fd27 100644 --- a/nodes/core/storage/50-file.js +++ b/nodes/core/storage/50-file.js @@ -14,77 +14,78 @@ * limitations under the License. **/ -var RED = require(process.env.NODE_RED_HOME+"/red/red"); -var fs = require("fs"); - -function FileNode(n) { - RED.nodes.createNode(this,n); - - this.filename = n.filename; - this.appendNewline = n.appendNewline; - this.overwriteFile = n.overwriteFile; - var node = this; - this.on("input",function(msg) { - var filename = msg.filename || this.filename; - - if (filename == "") { - node.warn('No filename specified'); - } else if (typeof msg.payload != "undefined") { - var data = msg.payload; - if (typeof data == "object") { data = JSON.stringify(data); } - if (typeof data == "boolean") { data = data.toString(); } - if (this.appendNewline) { - data += "\n"; - } - if (msg.hasOwnProperty('delete')) { - fs.unlink(filename, function (err) { - if (err) node.warn('Failed to delete file : '+err); - //console.log('Deleted file",filename); - }); - } - else { - if (this.overwriteFile) { - fs.writeFile(filename, data, function (err) { - if (err) node.warn('Failed to write to file : '+err); - //console.log('Message written to file',filename); +module.exports = function(RED) { + var fs = require("fs"); + + function FileNode(n) { + RED.nodes.createNode(this,n); + + this.filename = n.filename; + this.appendNewline = n.appendNewline; + this.overwriteFile = n.overwriteFile; + var node = this; + this.on("input",function(msg) { + var filename = msg.filename || this.filename; + + if (filename == "") { + node.warn('No filename specified'); + } else if (typeof msg.payload != "undefined") { + var data = msg.payload; + if (typeof data == "object") { data = JSON.stringify(data); } + if (typeof data == "boolean") { data = data.toString(); } + if (this.appendNewline) { + data += "\n"; + } + if (msg.hasOwnProperty('delete')) { + fs.unlink(filename, function (err) { + if (err) node.warn('Failed to delete file : '+err); + //console.log('Deleted file",filename); }); } else { - fs.appendFile(filename, data, function (err) { - if (err) node.warn('Failed to append to file : '+err); - //console.log('Message appended to file',filename); - }); + if (this.overwriteFile) { + fs.writeFile(filename, data, function (err) { + if (err) node.warn('Failed to write to file : '+err); + //console.log('Message written to file',filename); + }); + } + else { + fs.appendFile(filename, data, function (err) { + if (err) node.warn('Failed to append to file : '+err); + //console.log('Message appended to file',filename); + }); + } } } - } - }); -} -RED.nodes.registerType("file",FileNode); - -function FileInNode(n) { - RED.nodes.createNode(this,n); - - this.filename = n.filename; - this.format = n.format; - var node = this; - var options = {}; - if (this.format) { - options['encoding'] = this.format; + }); } - this.on("input",function(msg) { - var filename = msg.filename || this.filename; - - if (filename == "") { - node.warn('No filename specified'); - } else { - fs.readFile(filename,options,function(err,data) { - if (err) { - node.warn(err); - } else { - node.send({payload:data}); - } - }); + RED.nodes.registerType("file",FileNode); + + function FileInNode(n) { + RED.nodes.createNode(this,n); + + this.filename = n.filename; + this.format = n.format; + var node = this; + var options = {}; + if (this.format) { + options['encoding'] = this.format; } - }); + this.on("input",function(msg) { + var filename = msg.filename || this.filename; + + if (filename == "") { + node.warn('No filename specified'); + } else { + fs.readFile(filename,options,function(err,data) { + if (err) { + node.warn(err); + } else { + node.send({payload:data}); + } + }); + } + }); + } + RED.nodes.registerType("file in",FileInNode); } -RED.nodes.registerType("file in",FileInNode); diff --git a/nodes/core/storage/65-redisout.js b/nodes/core/storage/65-redisout.js index 17aaf9bfc..b01e8e4a0 100644 --- a/nodes/core/storage/65-redisout.js +++ b/nodes/core/storage/65-redisout.js @@ -14,83 +14,84 @@ * limitations under the License. **/ -var RED = require(process.env.NODE_RED_HOME+"/red/red"); -var util = require("util"); -var redis = require("redis"); - -var hashFieldRE = /^([^=]+)=(.*)$/; - -var redisConnectionPool = function() { - var connections = {}; - var obj = { - get: function(host,port) { - var id = host+":"+port; - if (!connections[id]) { - connections[id] = redis.createClient(port,host); - connections[id].on("error",function(err) { - util.log("[redis] "+err); - }); - connections[id].on("connect",function() { - util.log("[redis] connected to "+host+":"+port); - }); - connections[id]._id = id; - connections[id]._nodeCount = 0; - } - connections[id]._nodeCount += 1; - return connections[id]; - }, - close: function(connection) { - connection._nodeCount -= 1; - if (connection._nodeCount == 0) { - if (connection) { - clearTimeout(connection.retry_timer); - connection.end(); +module.exports = function(RED) { + var util = require("util"); + var redis = require("redis"); + + var hashFieldRE = /^([^=]+)=(.*)$/; + + var redisConnectionPool = function() { + var connections = {}; + var obj = { + get: function(host,port) { + var id = host+":"+port; + if (!connections[id]) { + connections[id] = redis.createClient(port,host); + connections[id].on("error",function(err) { + util.log("[redis] "+err); + }); + connections[id].on("connect",function() { + util.log("[redis] connected to "+host+":"+port); + }); + connections[id]._id = id; + connections[id]._nodeCount = 0; } - delete connections[connection._id]; - } - } - }; - return obj; -}(); - - -function RedisOutNode(n) { - RED.nodes.createNode(this,n); - this.port = n.port||"6379"; - this.hostname = n.hostname||"127.0.0.1"; - this.key = n.key; - this.structtype = n.structtype; - - this.client = redisConnectionPool.get(this.hostname,this.port); - - this.on("input", function(msg) { - if (msg != null) { - var k = this.key || msg.topic; - if (k) { - if (this.structtype == "string") { - this.client.set(k,msg.payload); - } else if (this.structtype == "hash") { - var r = hashFieldRE.exec(msg.payload); - if (r) { - this.client.hset(k,r[1],r[2]); - } else { - this.warn("Invalid payload for redis hash"); - } - } else if (this.structtype == "set") { - this.client.sadd(k,msg.payload); - } else if (this.structtype == "list") { - this.client.rpush(k,msg.payload); + connections[id]._nodeCount += 1; + return connections[id]; + }, + close: function(connection) { + connection._nodeCount -= 1; + if (connection._nodeCount == 0) { + if (connection) { + clearTimeout(connection.retry_timer); + connection.end(); } - } else { - this.warn("No key or topic set"); + delete connections[connection._id]; } } - }); -} - -RED.nodes.registerType("redis out",RedisOutNode); - -RedisOutNode.prototype.close = function() { - redisConnectionPool.close(this.client); + }; + return obj; + }(); + + + function RedisOutNode(n) { + RED.nodes.createNode(this,n); + this.port = n.port||"6379"; + this.hostname = n.hostname||"127.0.0.1"; + this.key = n.key; + this.structtype = n.structtype; + + this.client = redisConnectionPool.get(this.hostname,this.port); + + this.on("input", function(msg) { + if (msg != null) { + var k = this.key || msg.topic; + if (k) { + if (this.structtype == "string") { + this.client.set(k,msg.payload); + } else if (this.structtype == "hash") { + var r = hashFieldRE.exec(msg.payload); + if (r) { + this.client.hset(k,r[1],r[2]); + } else { + this.warn("Invalid payload for redis hash"); + } + } else if (this.structtype == "set") { + this.client.sadd(k,msg.payload); + } else if (this.structtype == "list") { + this.client.rpush(k,msg.payload); + } + } else { + this.warn("No key or topic set"); + } + } + }); + } + + RED.nodes.registerType("redis out",RedisOutNode); + + RedisOutNode.prototype.close = function() { + redisConnectionPool.close(this.client); + } } diff --git a/nodes/core/storage/66-mongodb.js b/nodes/core/storage/66-mongodb.js index 897c03b6d..50a3bbcc6 100644 --- a/nodes/core/storage/66-mongodb.js +++ b/nodes/core/storage/66-mongodb.js @@ -14,165 +14,166 @@ * limitations under the License. **/ -var RED = require(process.env.NODE_RED_HOME+"/red/red"); -var mongo = require('mongodb'); -var MongoClient = mongo.MongoClient; - -function MongoNode(n) { - RED.nodes.createNode(this,n); - this.hostname = n.hostname; - this.port = n.port; - this.db = n.db; - this.name = n.name; - var credentials = RED.nodes.getCredentials(n.id); - if (credentials) { - this.username = credentials.user; - this.password = credentials.password; +module.exports = function(RED) { + var mongo = require('mongodb'); + var MongoClient = mongo.MongoClient; + + function MongoNode(n) { + RED.nodes.createNode(this,n); + this.hostname = n.hostname; + this.port = n.port; + this.db = n.db; + this.name = n.name; + var credentials = RED.nodes.getCredentials(n.id); + if (credentials) { + this.username = credentials.user; + this.password = credentials.password; + } + + var url = "mongodb://"; + if (this.username && this.password) { + url += this.username+":"+this.password+"@"; + } + url += this.hostname+":"+this.port+"/"+this.db; + + this.url = url; } - var url = "mongodb://"; - if (this.username && this.password) { - url += this.username+":"+this.password+"@"; - } - url += this.hostname+":"+this.port+"/"+this.db; + RED.nodes.registerType("mongodb",MongoNode); - this.url = url; -} - -RED.nodes.registerType("mongodb",MongoNode); - -var querystring = require('querystring'); - -RED.httpAdmin.get('/mongodb/:id',function(req,res) { - var credentials = RED.nodes.getCredentials(req.params.id); - if (credentials) { - res.send(JSON.stringify({user:credentials.user,hasPassword:(credentials.password&&credentials.password!="")})); - } else { - res.send(JSON.stringify({})); - } -}); - -RED.httpAdmin.delete('/mongodb/:id',function(req,res) { - RED.nodes.deleteCredentials(req.params.id); - res.send(200); -}); - -RED.httpAdmin.post('/mongodb/:id',function(req,res) { - var body = ""; - req.on('data', function(chunk) { - body+=chunk; + var querystring = require('querystring'); + + RED.httpAdmin.get('/mongodb/:id',function(req,res) { + var credentials = RED.nodes.getCredentials(req.params.id); + if (credentials) { + res.send(JSON.stringify({user:credentials.user,hasPassword:(credentials.password&&credentials.password!="")})); + } else { + res.send(JSON.stringify({})); + } }); - req.on('end', function(){ - var newCreds = querystring.parse(body); - var credentials = RED.nodes.getCredentials(req.params.id)||{}; - if (newCreds.user == null || newCreds.user == "") { - delete credentials.user; - } else { - credentials.user = newCreds.user; - } - if (newCreds.password == "") { - delete credentials.password; - } else { - credentials.password = newCreds.password||credentials.password; - } - RED.nodes.addCredentials(req.params.id,credentials); + + RED.httpAdmin.delete('/mongodb/:id',function(req,res) { + RED.nodes.deleteCredentials(req.params.id); res.send(200); }); -}); - - -function MongoOutNode(n) { - RED.nodes.createNode(this,n); - this.collection = n.collection; - this.mongodb = n.mongodb; - this.payonly = n.payonly || false; - this.operation = n.operation; - this.mongoConfig = RED.nodes.getNode(this.mongodb); - - if (this.mongoConfig) { - var node = this; - MongoClient.connect(this.mongoConfig.url, function(err,db) { - if (err) { - node.error(err); - } else { - node.clientDb = db; - var coll = db.collection(node.collection); - node.on("input",function(msg) { - if (node.operation == "store") { - delete msg._topic; - if (node.payonly) { - if (typeof msg.payload !== "object") { msg.payload = {"payload":msg.payload}; } - coll.save(msg.payload,function(err,item){ if (err){node.error(err);} }); - } else { - coll.save(msg,function(err,item){if (err){node.error(err);}}); - } - } - else if (node.operation == "insert") { - delete msg._topic; - if (node.payonly) { - if (typeof msg.payload !== "object") { msg.payload = {"payload":msg.payload}; } - coll.insert(msg.payload,function(err,item){ if (err){node.error(err);} }); - } else { - coll.insert(msg,function(err,item){if (err){node.error(err);}}); - } - } - if (node.operation == "delete") { - coll.remove(msg.payload, {w:1}, function(err, items){ if (err) node.error(err); }); - } - }); - } + + RED.httpAdmin.post('/mongodb/:id',function(req,res) { + var body = ""; + req.on('data', function(chunk) { + body+=chunk; }); - } else { - this.error("missing mongodb configuration"); - } - - this.on("close", function() { - if (this.clientDb) { - this.clientDb.close(); - } - }); -} -RED.nodes.registerType("mongodb out",MongoOutNode); - - -function MongoInNode(n) { - RED.nodes.createNode(this,n); - this.collection = n.collection; - this.mongodb = n.mongodb; - this.mongoConfig = RED.nodes.getNode(this.mongodb); - - if (this.mongoConfig) { - var node = this; - MongoClient.connect(this.mongoConfig.url, function(err,db) { - if (err) { - node.error(err); + req.on('end', function(){ + var newCreds = querystring.parse(body); + var credentials = RED.nodes.getCredentials(req.params.id)||{}; + if (newCreds.user == null || newCreds.user == "") { + delete credentials.user; } else { - node.clientDb = db; - var coll = db.collection(node.collection); - node.on("input",function(msg) { - msg.projection = msg.projection || {}; - coll.find(msg.payload,msg.projection).sort(msg.sort).limit(msg.limit).toArray(function(err, items) { - if (err) { - node.error(err); - } else { - msg.payload = items; - delete msg.projection; - delete msg.sort; - delete msg.limit; - node.send(msg); + credentials.user = newCreds.user; + } + if (newCreds.password == "") { + delete credentials.password; + } else { + credentials.password = newCreds.password||credentials.password; + } + RED.nodes.addCredentials(req.params.id,credentials); + res.send(200); + }); + }); + + + function MongoOutNode(n) { + RED.nodes.createNode(this,n); + this.collection = n.collection; + this.mongodb = n.mongodb; + this.payonly = n.payonly || false; + this.operation = n.operation; + this.mongoConfig = RED.nodes.getNode(this.mongodb); + + if (this.mongoConfig) { + var node = this; + MongoClient.connect(this.mongoConfig.url, function(err,db) { + if (err) { + node.error(err); + } else { + node.clientDb = db; + var coll = db.collection(node.collection); + node.on("input",function(msg) { + if (node.operation == "store") { + delete msg._topic; + if (node.payonly) { + if (typeof msg.payload !== "object") { msg.payload = {"payload":msg.payload}; } + coll.save(msg.payload,function(err,item){ if (err){node.error(err);} }); + } else { + coll.save(msg,function(err,item){if (err){node.error(err);}}); + } + } + else if (node.operation == "insert") { + delete msg._topic; + if (node.payonly) { + if (typeof msg.payload !== "object") { msg.payload = {"payload":msg.payload}; } + coll.insert(msg.payload,function(err,item){ if (err){node.error(err);} }); + } else { + coll.insert(msg,function(err,item){if (err){node.error(err);}}); + } + } + if (node.operation == "delete") { + coll.remove(msg.payload, {w:1}, function(err, items){ if (err) node.error(err); }); } }); - }); + } + }); + } else { + this.error("missing mongodb configuration"); + } + + this.on("close", function() { + if (this.clientDb) { + this.clientDb.close(); } }); - } else { - this.error("missing mongodb configuration"); } - - this.on("close", function() { - if (this.clientDb) { - this.clientDb.close(); + RED.nodes.registerType("mongodb out",MongoOutNode); + + + function MongoInNode(n) { + RED.nodes.createNode(this,n); + this.collection = n.collection; + this.mongodb = n.mongodb; + this.mongoConfig = RED.nodes.getNode(this.mongodb); + + if (this.mongoConfig) { + var node = this; + MongoClient.connect(this.mongoConfig.url, function(err,db) { + if (err) { + node.error(err); + } else { + node.clientDb = db; + var coll = db.collection(node.collection); + node.on("input",function(msg) { + msg.projection = msg.projection || {}; + coll.find(msg.payload,msg.projection).sort(msg.sort).limit(msg.limit).toArray(function(err, items) { + if (err) { + node.error(err); + } else { + msg.payload = items; + delete msg.projection; + delete msg.sort; + delete msg.limit; + node.send(msg); + } + }); + }); + } + }); + } else { + this.error("missing mongodb configuration"); } - }); + + this.on("close", function() { + if (this.clientDb) { + this.clientDb.close(); + } + }); + } + RED.nodes.registerType("mongodb in",MongoInNode); } -RED.nodes.registerType("mongodb in",MongoInNode); diff --git a/red/nodes/registry.js b/red/nodes/registry.js index c467c1833..beafa9620 100644 --- a/red/nodes/registry.js +++ b/red/nodes/registry.js @@ -54,7 +54,7 @@ function loadNode(nodeDir, nodeFn) { var r = require(nodeFilename); if (typeof r === "function") { try { - var promise = r(RED); + var promise = r(require('../red')); if (promise != null && typeof promise.then === "function") { promise.then(function() { resolve(loadTemplate(templateFilename));