Move all nodes into core subdirectory

This makes it easier to distinguish core nodes from those added later
This commit is contained in:
Nicholas O'Leary
2013-11-14 15:52:19 +00:00
parent affcc8ae65
commit 48dabffefc
70 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,192 @@
<!--
Copyright 2013 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.
-->
<script type="text/x-red" data-template-name="twitter-credentials">
<div class="form-row" id="node-config-twitter-row"></div>
<input type="hidden" id="node-config-input-screen_name">
</script>
<script type="text/javascript">
var twitterConfigNodeId = null;
var twitterConfigNodeIntervalId = null;
function showTwitterAuthStart() {
var pathname = document.location.pathname;
if (pathname.slice(-1) != "/") {
pathname += "/";
}
var callback = encodeURIComponent(location.protocol+"//"+location.hostname+":"+location.port+pathname+"twitter/"+twitterConfigNodeId+"/auth/callback");
$("#node-config-twitter-row").html('Click <a id="node-config-twitter-start" href="/twitter/'+twitterConfigNodeId+'/auth?callback='+callback+'" target="_blank"><b>here</b></a> to authenticate with Twitter.');
$("#node-config-twitter-start").click(function() {
twitterConfigNodeIntervalId = window.setTimeout(pollTwitterCredentials,2000);
});
}
function updateTwitterScreenName(sn) {
$("#node-config-input-screen_name").val(sn);
$("#node-config-twitter-row").html('<label><i class="icon-user"></i> Twitter ID</label><span class="input-xlarge uneditable-input">'+sn+'</span>');
}
function pollTwitterCredentials(e) {
$.getJSON('twitter/'+twitterConfigNodeId,function(data) {
if (data.sn) {
updateTwitterScreenName(data.sn);
twitterConfigNodeIntervalId = null;
} else {
twitterConfigNodeIntervalId = window.setTimeout(pollTwitterCredentials,2000);
}
})
}
RED.nodes.registerType('twitter-credentials',{
category: 'config',
defaults: {
screen_name: {value:""},
access_token: {value: ""},
access_token_secret: {value:""}
},
label: function() {
return this.screen_name;
},
exportable: false,
oneditprepare: function() {
twitterConfigNodeId = this.id;
if (!this.screen_name || this.screen_name == "") {
showTwitterAuthStart();
} else {
$.getJSON('twitter/'+twitterConfigNodeId,function(data) {
if (data.sn) {
updateTwitterScreenName(data.sn);
} else {
showTwitterAuthStart();
}
});
}
},
oneditsave: function() {
if (twitterConfigNodeIntervalId) {
window.clearTimeout(twitterConfigNodeIntervalId);
}
},
oneditcancel: function(adding) {
if (twitterConfigNodeIntervalId) {
window.clearTimeout(twitterConfigNodeIntervalId);
}
if (adding) {
$.ajax({
url: 'twitter/'+this.id,
type: 'DELETE',
success: function(result) {}
});
}
},
ondelete: function() {
$.ajax({
url: 'twitter/'+this.id,
type: 'DELETE',
success: function(result) {}
});
}
});
</script>
<script type="text/x-red" data-template-name="twitter in">
<div class="form-row">
<label for="node-input-twitter"><i class="icon-user"></i> Log in as</label>
<input type="text" id="node-input-twitter">
</div>
<div class="form-row">
<label for="node-input-user"><i class="icon-search"></i> Search</label>
<select type="text" id="node-input-user" style="display: inline-block; vertical-align: middle; width:60%;">
<option value="false">all public tweets</option>
<option value="true">the tweets of who you follow</option>
</select>
</div>
<div class="form-row">
<label for="node-input-tags"><i class="icon-tags"></i> for</label>
<input type="text" id="node-input-tags" placeholder="comma-separated words, @ids, #tags">
</div>
<div class="form-row">
<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: Use commas without spaces between multiple search terms. Comma = OR, Space = AND.
<br/>The Twitter API WILL NOT deliver 100% of all tweets.
<br/>Tweets of who you follow will include their retweets and favourites.</div>
</script>
<script type="text/x-red" data-help-name="twitter in">
<p>Twitter input node. Watches either the public or the user's stream for tweets containing the configured search term.</p>
<p>Sets the <b>msg.topic</b> to <i>tweets/</i> and then appends the senders screen name.</p>
<p>Sets <b>msg.location</b> to the tweeters location if known.</p>
<p>Sets <b>msg.tweet</b> to the full tweet object as documented by <a href="https://dev.twitter.com/docs/platform-objects/tweets">Twitter</a>.
</script>
<script type="text/javascript">
RED.nodes.registerType('twitter in',{
category: 'social-input',
color:"#C0DEED",
defaults: {
twitter: {type:"twitter-credentials",required:true},
tags: {value:"",required:true},
user: {value:"false",required:true},
name: {value:""},
topic: {value:"tweets"}
},
inputs:0,
outputs:1,
icon: "twitter.png",
label: function() {
return this.name||this.tags;
},
labelStyle: function() {
return this.name?"node_label_italic":"";
}
});
</script>
<script type="text/x-red" data-template-name="twitter out">
<div class="form-row">
<label for="node-input-twitter"><i class="icon-user"></i> Twitter</label>
<input type="text" id="node-input-twitter">
</div>
<div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
</script>
<script type="text/x-red" data-help-name="twitter out">
<p>Twitter out node. Tweets the <b>msg.payload</b>.</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('twitter out',{
category: 'social-output',
color:"#C0DEED",
defaults: {
twitter: {type:"twitter-credentials",required:true},
name: {value:"Tweet"}
},
inputs:1,
outputs:0,
icon: "twitter.png",
align: "right",
label: function() {
return this.name;
}
});
</script>

View File

@@ -0,0 +1,209 @@
/**
* Copyright 2013 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.
**/
var RED = require(process.env.NODE_RED_HOME+"/red/red");
var ntwitter = require('ntwitter');
var OAuth= require('oauth').OAuth;
function TwitterNode(n) {
RED.nodes.createNode(this,n);
this.screen_name = n.screen_name;
}
RED.nodes.registerType("twitter-credentials",TwitterNode);
function TwitterInNode(n) {
RED.nodes.createNode(this,n);
this.active = true;
this.user = n.user;
this.tags = n.tags.replace(/ /g,'');
this.twitter = n.twitter;
this.topic = n.topic||"tweets";
this.twitterConfig = RED.nodes.getNode(this.twitter);
var credentials = RED.nodes.getCredentials(this.twitter);
if (credentials && credentials.screen_name == this.twitterConfig.screen_name) {
var twit = new ntwitter({
consumer_key: "OKjYEd1ef2bfFolV25G5nQ",
consumer_secret: "meRsltCktVMUI8gmggpXett7WBLd1k0qidYazoML6g",
access_token_key: credentials.access_token,
access_token_secret: credentials.access_token_secret
});
var node = this;
if (this.tags !== "") {
try {
var thing = 'statuses/filter';
if (this.user == "true") { thing = 'user'; }
function setupStream() {
if (node.active) {
twit.stream(thing, { track: [node.tags] }, function(stream) {
//twit.stream('user', { track: [node.tags] }, function(stream) {
//twit.stream('site', { track: [node.tags] }, function(stream) {
//twit.stream('statuses/filter', { track: [node.tags] }, function(stream) {
node.stream = stream;
stream.on('data', function(tweet) {
//console.log(tweet.user);
if (tweet.user !== undefined) {
var where = tweet.user.location||"";
var la = tweet.lang || tweet.user.lang;
//console.log(tweet.user.location,"=>",tweet.user.screen_name,"=>",pay);
var msg = { topic:node.topic+"/"+tweet.user.screen_name, payload:tweet.text, location:where, lang:la, tweet:tweet };
node.send(msg);
}
});
stream.on('error', function(tweet) {
node.warn(tweet);
setTimeout(setupStream,5000);
});
stream.on('destroy', function (response) {
if (this.active) {
node.warn("twitter ended unexpectedly");
setTimeout(setupStream,5000);
}
});
});
}
}
setupStream();
}
catch (err) {
node.error(err);
}
} else {
this.error("Invalid tag property");
}
} else {
this.error("missing twitter credentials");
}
}
RED.nodes.registerType("twitter in",TwitterInNode);
TwitterInNode.prototype.close = function() {
if (this.stream) {
this.active = false;
this.stream.destroy();
}
}
function TwitterOutNode(n) {
RED.nodes.createNode(this,n);
this.topic = n.topic;
this.twitter = n.twitter;
this.twitterConfig = RED.nodes.getNode(this.twitter);
var credentials = RED.nodes.getCredentials(this.twitter);
var node = this;
if (credentials && credentials.screen_name == this.twitterConfig.screen_name) {
var twit = new ntwitter({
consumer_key: "OKjYEd1ef2bfFolV25G5nQ",
consumer_secret: "meRsltCktVMUI8gmggpXett7WBLd1k0qidYazoML6g",
access_token_key: credentials.access_token,
access_token_secret: credentials.access_token_secret
}).verifyCredentials(function (err, data) {
if (err) {
node.error("Error verifying credentials: " + err);
} else {
node.on("input", function(msg) {
if (msg != null) {
if (msg.payload.length > 140) {
msg.payload = msg.payload.slice(0,139);
node.warn("Tweet greater than 140 : truncated");
}
twit.updateStatus(msg.payload, function (err, data) {
if (err) node.error(err);
});
}
});
}
});
}
}
RED.nodes.registerType("twitter out",TwitterOutNode);
var oa = new OAuth(
"https://api.twitter.com/oauth/request_token",
"https://api.twitter.com/oauth/access_token",
"OKjYEd1ef2bfFolV25G5nQ",
"meRsltCktVMUI8gmggpXett7WBLd1k0qidYazoML6g",
"1.0",
null,
"HMAC-SHA1"
);
var credentials = {};
RED.app.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 {
res.send(JSON.stringify({}));
}
});
RED.app.delete('/twitter/:id', function(req,res) {
RED.nodes.deleteCredentials(req.params.id);
res.send(200);
});
RED.app.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) {
console.log(error);
res.send("yeah no. didn't work.")
}
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);
}
});
});
RED.app.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("<html><head></head><body>Authorised - you can close this window and return to Node-RED</body></html>");
}
}
);
});

View File

@@ -0,0 +1,57 @@
<!--
Copyright 2013 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.
-->
<script type="text/x-red" data-template-name="feedparse">
<div class="form-row">
<label for="node-input-url"><i class="icon-globe"></i> Feed url</label>
<input type="text" id="node-input-url">
</div>
<div class="form-row">
<label for="node-input-interval"><i class="icon-repeat"></i> Repeat <span style="font-size: 0.9em;">(M)</span></label>
<input type="text" id="node-input-interval" placeholder="minutes">
</div>
<div class="form-row">
<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"></div> -->
</script>
<script type="text/x-red" data-help-name="feedparse">
<p>Monitors an RSS/atom feed for new entries.</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('feedparse',{
category: 'advanced-input',
color:"#C0DEED",
defaults: {
name: {value:""},
url: {value:"", required:true},
interval: { value:15, required: true,validate:RED.validators.number()}
},
inputs:0,
outputs:1,
icon: "feed.png",
label: function() {
return this.name||this.url;
},
labelStyle: function() {
return this.name?"node_label_italic":"";
}
});
</script>

View File

@@ -0,0 +1,75 @@
/**
* Copyright 2013 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.
**/
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);
})
.on('meta', function (meta) {})
.on('article', function (article) {
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: {
summary:article.summary,
link:article.link,
date: article.date,
pubdate: article.pubdate,
author: article.author,
guid: article.guid,
}
};
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);
}
}

View File

@@ -0,0 +1,50 @@
<!--
Copyright 2013 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.
-->
<script type="text/x-red" data-template-name="email">
<div class="form-row">
<label for="node-input-name"><i class="icon-envelope"></i> To</label>
<input type="text" id="node-input-name" placeholder="email@address.com">
</div>
</script>
<script type="text/x-red" data-help-name="email">
<p>Sends the <b>msg.payload</b> as an email, with a subject of <b>msg.topic</b>.</p>
<p>It sends the message to the configured recipient <i>only</i>.</p>
<p><b>msg.topic</b> is used to set the subject of the email, and <b>msg.payload</b> is the body text.</p>
<p>Uses the nodemailer module - you also need to pre-configure your email SMTP settings in ../../emailkeys.js - see INSTALL file for details.</p>
<p><pre>module.exports = { service: "Gmail", user: "blahblah@gmail.com", pass: "password", server: "imap.gmail.com", port: "993" }</pre></p>
</script>
<script type="text/javascript">
RED.nodes.registerType('email',{
category: 'social-output',
color:"#c7e9c0",
defaults: {
name: {value:"",required:true}
},
inputs:1,
outputs:0,
icon: "envelope.png",
align: "right",
label: function() {
return this.name;
},
labelStyle: function() {
return (this.name||!this.topic)?"node_label_italic":"";
}
});
</script>

View File

@@ -0,0 +1,55 @@
/**
* Copyright 2013 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.
**/
var RED = require(process.env.NODE_RED_HOME+"/red/red");
var nodemailer = require("nodemailer");
var emailkey = require(process.env.NODE_RED_HOME+"/../emailkeys.js");
var smtpTransport = nodemailer.createTransport("SMTP",{
service: emailkey.service,
auth: {
user: emailkey.user,
pass: emailkey.pass
}
});
function EmailNode(n) {
RED.nodes.createNode(this,n);
this.topic = n.topic;
this.name = n.name;
var node = this;
this.on("input", function(msg) {
//node.log("email :",this.id,this.topic," received",msg.payload);
if (msg != null) {
smtpTransport.sendMail({
from: emailkey.user, // 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);
}
});
}
});
}
RED.nodes.registerType("email",EmailNode);

View File

@@ -0,0 +1,54 @@
<!--
Copyright 2013 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.
-->
<script type="text/x-red" data-template-name="imap">
<div class="form-row node-input-repeat">
<label for="node-input-repeat"><i class="icon-repeat"></i>Repeat (S)</label>
<input type="text" id="node-input-repeat" placeholder="300">
</div>
<div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
</script>
<script type="text/x-red" data-help-name="imap">
<p>Repeatedly gets a <b>single email</b> from an IMAP server and forwards on as a msg if not already seen.</p>
<p>The subject is loaded into <b>msg.topic</b> and <b>msg.payload</b> is the body text. <b>msg.from</b> is also set if you need it.</p>
<p>Uses the imap module - you also need to pre-configure your email settings in ../../emailkeys.js - see INSTALL file for details.</p>
<p><pre>module.exports = { service: "Gmail", user: "blahblah@gmail.com", pass: "password", server: "imap.gmail.com", port: "993" }</pre></p>
<p><b>Note:</b> this node <i>only</i> gets the most recent single email from the inbox, so set the repeat (polling) time appropriately.</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('imap',{
category: 'social-input',
color:"#c7e9c0",
defaults: {
repeat: {value:"300",required:true},
name: {value:""}
},
inputs:0,
outputs:1,
icon: "envelope.png",
label: function() {
return this.name||"IMAP";
},
labelStyle: function() {
return (this.name||!this.topic)?"node_label_italic":"";
}
});
</script>

View File

@@ -0,0 +1,108 @@
/**
* Copyright 2013 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.
**/
var RED = require(process.env.NODE_RED_HOME+"/red/red");
var Imap = require('imap');
var util = require('util');
var oldmail = {};
try {
var emailkey = RED.settings.email || require(process.env.NODE_RED_HOME+"/../emailkeys.js");
} catch(err) {
throw new Error("Failed to load Email credentials");
}
var imap = new Imap({
user: emailkey.user,
password: emailkey.pass,
host: emailkey.server||"imap.gmail.com",
port: emailkey.port||"993",
secure: true
});
function fail(err) {
util.log('[imap] : ' + err);
}
function openInbox(cb) {
imap.connect(function(err) {
if (err) fail(err);
imap.openBox('INBOX', true, cb);
});
}
function ImapNode(n) {
RED.nodes.createNode(this,n);
this.name = n.name;
this.repeat = n.repeat * 1000;
var node = this;
this.interval_id = null;
if (this.repeat && !isNaN(this.repeat) && this.repeat > 0) {
this.log("repeat = "+this.repeat);
this.interval_id = setInterval( function() {
node.emit("input",{});
}, this.repeat );
}
this.on("input", function(msg) {
openInbox(function(err, mailbox) {
if (err) fail(err);
imap.seq.fetch(mailbox.messages.total + ':*', { struct: false },
{ headers: ['from', 'subject'],
body: true,
cb: function(fetch) {
fetch.on('message', function(msg) {
//node.log('Saw message no. ' + msg.seqno);
var pay = {};
var body = '';
msg.on('headers', function(hdrs) {
pay.from = hdrs.from[0];
pay.topic = hdrs.subject[0];
});
msg.on('data', function(chunk) {
body += chunk.toString('utf8');
});
msg.on('end', function() {
pay.payload = body;
if ((pay.topic !== oldmail.topic)|(pay.payload !== oldmail.payload)) {
oldmail = pay;
//node.log("From: "+pay.from);
node.log("Subj: "+pay.topic);
//node.log("Body: "+pay.payload);
node.send(pay);
}
});
});
}
}, function(err) {
if (err) node.log("Err : "+err);
//node.log("Done fetching messages.");
imap.logout();
}
);
});
});
this.on("close", function() {
if (this.interval_id != null) {
clearInterval(this.interval_id);
}
});
}
RED.nodes.registerType("imap",ImapNode);

View File

@@ -0,0 +1,130 @@
<!--
Copyright 2013 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.
-->
<script type="text/x-red" data-template-name="irc in">
<div class="form-row">
<label for="node-input-ircserver"><i class="icon-tasks"></i> IRC Server</label>
<input type="text" id="node-input-ircserver">
</div>
<div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
</script>
<script type="text/x-red" data-help-name="irc in">
<p>Connects to a channel on an IRC server</p>
<p>Any messages on that channel will appear on the <b>msg.payload</b> at the output, while <b>msg.topic</b> will contain who it is from.</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('irc in',{
category: 'social-input',
defaults: {
name: {value:""},
ircserver: {type:"irc-server", required:true}
},
color:"Silver",
inputs:0,
outputs:1,
icon: "hash.png",
label: function() {
var ircNode = RED.nodes.node(this.ircserver);
return this.name||(ircNode?ircNode.label():"irc");
},
labelStyle: function() {
return this.name?"node_label_italic":"";
}
});
</script>
<script type="text/x-red" data-template-name="irc out">
<div class="form-row">
<label for="node-input-ircserver"><i class="icon-tasks"></i> IRC Server</label>
<input type="text" id="node-input-ircserver">
</div>
<div class="form-row">
<label for="node-input-sendObject"><i class="icon-check"></i> Action</label>
<select type="text" id="node-input-sendObject" style="display: inline-block; vertical-align: middle; width:70%;">
<option value="pay">Send msg.payload to channel</option>
<option value="true">Send msg.payload to id in msg.topic</option>
<option value="false">Send complete msg object to channel</option>
</select>
</div>
<div class="form-row">
<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">Sending the complete object will stringify the whole msg object before sending.</div>
</script>
<script type="text/x-red" data-help-name="irc out">
<p>Sends messages to a channel on an IRC server</p>
<p>You can send just the <b>msg.payload</b>, or the complete <b>msg</b> object to the selected channel,
or you can select to use <b>msg.topic</b> to send the <b>msg.payload</b> to a specific user in the channel (private conversation).</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('irc out',{
category: 'social-output',
defaults: {
name: {value:""},
sendObject: {value:"pay", required:true},
ircserver: {type:"irc-server", required:true}
},
color:"Silver",
inputs:1,
outputs:0,
icon: "hash.png",
align: "right",
label: function() {
return this.name || (this.ircserver)?RED.nodes.node(this.ircserver).label():"irc";
},
labelStyle: function() {
return this.name?"node_label_italic":"";
}
});
</script>
<script type="text/x-red" data-template-name="irc-server">
<div class="form-row">
<label for="node-config-input-server"><i class="icon-tasks"></i> IRC Server</label>
<input type="text" id="node-config-input-server" placeholder="irc.UK-IRC.net">
</div>
<div class="form-row">
<label for="node-config-input-channel"><i class="icon-tasks"></i> Channel</label>
<input type="text" id="node-config-input-channel" placeholder="#node-red">
</div>
<div class="form-row">
<label for="node-config-input-nickname"><i class="icon-tasks"></i> Nickname</label>
<input type="text" id="node-config-input-nickname" placeholder="joe123">
</div>
<div class="form-tips">The channel to join must start with a # (as per normal irc rules...)</div>
</script>
<script type="text/javascript">
RED.nodes.registerType('irc-server',{
category: 'config',
defaults: {
channel: {value:"",required:true,validate:RED.validators.regex(/^#/)},
server: {value:"",required:true},
nickname: {value:"",required:true}
},
label: function() {
return this.server+":"+this.channel;
}
});
</script>

View File

@@ -0,0 +1,98 @@
/**
* Copyright 2013 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.
**/
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);
if (this.serverConfig.ircclient == null) {
this.serverConfig.ircclient = new irc.Client(this.serverConfig.server, this.serverConfig.nickname, {
channels: [this.serverConfig.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, "to":to, "payload":message };
node.send(msg);
});
}
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 = this.serverConfig.channel;
if (this.serverConfig.ircclient == null) {
this.serverConfig.ircclient = new irc.Client(this.serverConfig.server, this.serverConfig.nickname, {
channels: [this.serverConfig.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) {
//console.log(msg,node.channel);
if (msg._topic) { delete msg._topic; }
if (node.sendAll == "false") {
node.ircclient.say(node.channel, JSON.stringify(msg));
}
else {
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);