1
0
mirror of https://github.com/node-red/node-red-nodes.git synced 2023-10-10 13:36:58 +02:00

Updates on Twitter-In node: 1. Node now takes topic string input rather than hard-coded 2. "Sticky" followers: If new input string suggests updates in handles to follow, creates "sticky" new intervals - meaning previously followed handles are maintained, new ones added 3. Node now takes refresh time as an input value, previously hardcoded at 60s

This commit is contained in:
hgill 2021-05-05 22:20:02 +05:30
parent 4bd657fcd8
commit 3bb5bcf9b5
3 changed files with 78 additions and 19 deletions

View File

@ -96,6 +96,10 @@
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></span></label> <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></span></label>
<input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name"> <input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
</div> </div>
<div class="form-row">
<label for="node-input-pollInterval"><i class="fa fa-clock"></i> <span data-i18n="twitter.label.pollInterval"></span></label>
<input type="text" id="node-input-pollInterval" data-i18n="[placeholder]twitter.placeholder.pollInterval">
</div>
<div class="form-tips"><span data-i18n="[html]twitter.tip"></span></div> <div class="form-tips"><span data-i18n="[html]twitter.tip"></span></div>
</script> </script>
@ -108,7 +112,8 @@
tags: {value:""}, tags: {value:""},
user: {value:"false",required:true}, user: {value:"false",required:true},
name: {value:""}, name: {value:""},
inputs: {value:0} inputs: {value:0},
pollInterval: {value:60000}
}, },
inputs: 0, inputs: 0,
outputs: 1, outputs: 1,
@ -139,6 +144,7 @@
var userph = this._("twitter.placeholder.user"); var userph = this._("twitter.placeholder.user");
var forlabel = this._("twitter.label.for"); var forlabel = this._("twitter.label.for");
var forph = this._("twitter.placeholder.for"); var forph = this._("twitter.placeholder.for");
var pollInterval = this._("twitter.placeholder.pollInterval")
$("#node-input-user").change(function() { $("#node-input-user").change(function() {
var type = $("#node-input-user option:selected").val(); var type = $("#node-input-user option:selected").val();
if (type == "user") { if (type == "user") {
@ -156,7 +162,7 @@
$("#node-input-user").change(); $("#node-input-user").change();
}, },
oneditsave: function() { oneditsave: function() {
if ($('#node-input-tags').val() === '' && $("#node-input-user option:selected").val() === 'false') { if ($('#node-input-tags').val() === ''/* && $("#node-input-user option:selected").val() === 'false'*/) {
this.inputs = 1; this.inputs = 1;
} }
else { else {

View File

@ -169,6 +169,7 @@ module.exports = function(RED) {
this.twitterConfig = RED.nodes.getNode(this.twitter); this.twitterConfig = RED.nodes.getNode(this.twitter);
this.poll_ids = []; this.poll_ids = [];
this.timeout_ids = []; this.timeout_ids = [];
this.pollInterval=n.pollInterval || 60000;
var credentials = RED.nodes.getCredentials(this.twitter); var credentials = RED.nodes.getCredentials(this.twitter);
this.status({}); this.status({});
@ -177,17 +178,60 @@ module.exports = function(RED) {
var node = this; var node = this;
if (this.user === "true") { if (this.user === "true") {
// Poll User Home Timeline 1/min // Poll User Home Timeline 1/min
this.poll(60000,"https://api.twitter.com/1.1/statuses/home_timeline.json"); this.poll(node.pollInterval,"https://api.twitter.com/1.1/statuses/home_timeline.json");
} else if (this.user === "user") { } else if (this.user === "user") {
var users = node.tags.split(/\s*,\s*/).filter(v=>!!v); var tags= node.tags || "";
var users = tags.split(/\s*,\s*/).filter(v=>!!v);
/* // Block no longer reqd as accepts msg.payload
if (users.length === 0) { if (users.length === 0) {
node.error(RED._("twitter.warn.nousers")); node.error(RED._("twitter.warn.nousers"));
return; return;
} }
*/
// Poll User timeline // Poll User timeline
node.lastMessageTS = new Date();
node.status({fill:"green",shape:"ring",text:"Initializing"});
users.forEach(function(user) { users.forEach(function(user) {
node.poll(60000,"https://api.twitter.com/1.1/statuses/user_timeline.json",{screen_name: user}); node.poll(node.pollInterval,"https://api.twitter.com/1.1/statuses/user_timeline.json",{screen_name: user});
}) })
node.on("input", function(msg) { // sticky polling - identifies already tracked handles vs add/remove handles
var payloadtags=msg.payload.split(/\s*,\s*/).filter(v=>!!v);
var screennames=node.poll_ids.map(p=>p.asset.opts.screen_name);
var newusers=payloadtags.filter(x=>!screennames.includes(x));
var removeusers=screennames.filter(x=>!payloadtags.includes(x));
newusers.forEach(function(user) { //start tracking new users in msg.payload
node.warn("Twitter-In: New Handle: "+user)
node.status({fill:"green",shape:"ring",text:"Adding handles"});
node.lastMessageTS = new Date();
node.poll(node.pollInterval,"https://api.twitter.com/1.1/statuses/user_timeline.json",{screen_name: user});
});
removeusers.forEach(function(user) { // remove any tracked users missing from msg.payload
node.poll_ids.forEach((p,i)=>{
if(user===p.asset.opts.screen_name){
node.status({fill:"green",shape:"ring",text:"Removing handles"});
node.lastMessageTS = new Date();
node.warn("Twitter-In: Delete Handle: "+p.asset.opts.screen_name);
clearInterval(p.interval);
node.poll_ids.splice(i,1);
}
})
});
});
function checklastMessageTS() {
if(node.lastMessageTS != null){
var timeDiff = new Date() - node.lastMessageTS;
if(timeDiff > 5000){
node.status({fill:"yellow",shape:"ring",text:"Idle @ "+node.lastMessageTS.toLocaleTimeString()});
node.lastMessageTS=null;
}
}
}
node.interval = setInterval(checklastMessageTS, 1000);
} else if (this.user === "dm") { } else if (this.user === "dm") {
node.pollDirectMessages(); node.pollDirectMessages();
} else if (this.user === "event") { } else if (this.user === "event") {
@ -312,8 +356,11 @@ module.exports = function(RED) {
catch (err) { catch (err) {
node.error(err); node.error(err);
} }
} }
this.on('close', function() { this.on('close', function() {
clearInterval(node.interval);
if (this.tout) { clearTimeout(this.tout); } if (this.tout) { clearTimeout(this.tout); }
if (this.tout2) { clearTimeout(this.tout2); } if (this.tout2) { clearTimeout(this.tout2); }
if (this.stream) { if (this.stream) {
@ -328,7 +375,7 @@ module.exports = function(RED) {
} }
if (this.poll_ids) { if (this.poll_ids) {
for (var i=0; i<this.poll_ids.length; i++) { for (var i=0; i<this.poll_ids.length; i++) {
clearInterval(this.poll_ids[i]); clearInterval(this.poll_ids[i].interval);
} }
} }
}); });
@ -342,7 +389,7 @@ module.exports = function(RED) {
TwitterInNode.prototype.poll = function(interval, url, opts) { TwitterInNode.prototype.poll = function(interval, url, opts) {
var node = this; var node = this;
var opts = opts || {}; var opts = opts || {};
var pollId; var pollId={};
opts.count = 1; opts.count = 1;
this.twitterConfig.get(url,opts).then(function(result) { this.twitterConfig.get(url,opts).then(function(result) {
if (result.status === 429) { if (result.status === 429) {
@ -359,12 +406,15 @@ module.exports = function(RED) {
if (res.length > 0) { if (res.length > 0) {
since = res[0].id_str; since = res[0].id_str;
} }
pollId = setInterval(function() { pollId.asset={url:url,opts:opts};
pollId.interval = setInterval(function() {
node.lastMessageTS = new Date();
node.status({fill:"blue",shape:"ring",text:"Polling"});
opts.since_id = since; opts.since_id = since;
node.twitterConfig.get(url,opts).then(function(result) { node.twitterConfig.get(url,opts).then(function(result) {
if (result.status === 429) { if (result.status === 429) {
node.warn("Rate limit hit. Waiting "+Math.floor(result.rateLimitTimeout/1000)+" seconds to try again"); node.warn("Rate limit hit. Waiting "+Math.floor(result.rateLimitTimeout/1000)+" seconds to try again");
clearInterval(pollId); clearInterval(pollId.interval);
node.timeout_ids.push(setTimeout(function() { node.timeout_ids.push(setTimeout(function() {
node.poll(interval,url,opts); node.poll(interval,url,opts);
},result.rateLimitTimeout)) },result.rateLimitTimeout))
@ -378,7 +428,7 @@ module.exports = function(RED) {
// 'since_id parameter is invalid' - reset it for next time // 'since_id parameter is invalid' - reset it for next time
delete opts.since_id; delete opts.since_id;
} }
clearInterval(pollId); clearInterval(pollId.interval);
node.timeout_ids.push(setTimeout(function() { node.timeout_ids.push(setTimeout(function() {
node.poll(interval,url,opts); node.poll(interval,url,opts);
},interval)) },interval))
@ -409,7 +459,7 @@ module.exports = function(RED) {
} }
}).catch(function(err) { }).catch(function(err) {
node.error(err); node.error(err);
clearInterval(pollId); clearInterval(pollId.interval);
node.timeout_ids.push(setTimeout(function() { node.timeout_ids.push(setTimeout(function() {
delete opts.since_id; delete opts.since_id;
delete opts.count; delete opts.count;
@ -433,7 +483,7 @@ module.exports = function(RED) {
var node = this; var node = this;
var opts = {}; var opts = {};
var url = "https://api.twitter.com/1.1/direct_messages/events/list.json"; var url = "https://api.twitter.com/1.1/direct_messages/events/list.json";
var pollId; var pollId={};
opts.count = 50; opts.count = 50;
this.twitterConfig.get(url,opts).then(function(result) { this.twitterConfig.get(url,opts).then(function(result) {
if (result.status === 429) { if (result.status === 429) {
@ -457,11 +507,12 @@ module.exports = function(RED) {
if (messages.length > 0) { if (messages.length > 0) {
since = messages[0].id; since = messages[0].id;
} }
pollId = setInterval(function() { pollId.asset={url:url,opts:opts};
pollId.interval = setInterval(function() {
node.twitterConfig.get(url,opts).then(function(result) { node.twitterConfig.get(url,opts).then(function(result) {
if (result.status === 429) { if (result.status === 429) {
node.warn("Rate limit hit. Waiting "+Math.floor(result.rateLimitTimeout/1000)+" seconds to try again"); node.warn("Rate limit hit. Waiting "+Math.floor(result.rateLimitTimeout/1000)+" seconds to try again");
clearInterval(pollId); clearInterval(pollId.interval);
node.timeout_ids.push(setTimeout(function() { node.timeout_ids.push(setTimeout(function() {
node.pollDirectMessages(); node.pollDirectMessages();
},result.rateLimitTimeout)) },result.rateLimitTimeout))
@ -471,7 +522,7 @@ module.exports = function(RED) {
var res = result.body; var res = result.body;
if (res.errors) { if (res.errors) {
node.error(res.errors[0].message); node.error(res.errors[0].message);
clearInterval(pollId); clearInterval(pollId.interval);
node.timeout_ids.push(setTimeout(function() { node.timeout_ids.push(setTimeout(function() {
node.pollDirectMessages(); node.pollDirectMessages();
},interval)) },interval))
@ -532,7 +583,7 @@ module.exports = function(RED) {
} }
}).catch(function(err) { }).catch(function(err) {
node.error(err); node.error(err);
clearInterval(pollId); clearInterval(pollId.interval);
node.timeout_ids.push(setTimeout(function() { node.timeout_ids.push(setTimeout(function() {
node.pollDirectMessages(); node.pollDirectMessages();
},interval)) },interval))

View File

@ -16,11 +16,13 @@
"copy-accessToken": "Create a new 'Access token & access token secret' and copy them", "copy-accessToken": "Create a new 'Access token & access token secret' and copy them",
"access_key": "Access token", "access_key": "Access token",
"access_secret": "Access token secret", "access_secret": "Access token secret",
"enter-id": "Set your Twitter ID" "enter-id": "Set your Twitter ID",
"pollInterval": "Poll Interval"
}, },
"placeholder": { "placeholder": {
"for": "comma-separated words, @ids, #tags", "for": "comma-separated words, @ids, #tags",
"user": "comma-separated @twitter handles" "user": "comma-separated @twitter handles",
"pollInterval": "Time in milliseconds, default 60000 (1 minute)"
}, },
"search": { "search": {
"public": "all public tweets", "public": "all public tweets",