Created
September 16, 2014 01:17
-
-
Save boxmein/62be7fc58f3af36fb67d to your computer and use it in GitHub Desktop.
A Twitter bot that reverses the text it gets from @mentions from a specific user ID.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// A Twitter bot! Experimental! | |
// Reverses words of text sent to it. | |
//# node {{f}} # don't forget to add environment vars! | |
// npm install twit | |
var Twit = require('twit'); | |
// how many @mentions from the top to fetch, to look for | |
// TODO: go through many pages of @mentions | |
// TODO: add since_id for the last tweet this fetched | |
var COUNT = process.env['COUNT'] || 15; | |
// Strip out mentions from the produce | |
// Matches @.... mentions | |
var mention = /@.+?\s+/g; | |
// Queue to fire off functions (such as posting Tweets) | |
// and an interval for when to do so, in milliseconds. | |
var queue = []; | |
var INTERVAL = process.env['INTERVAL'] || 15000; | |
// User ID to filter requests for | |
// If 0, go find the piece of code and edit it out ;) | |
var filter_id = parseInt(process.env['USER_ID'], 10); | |
// Crudely stolen from Underscore.js | |
var _={}; | |
_.debounce = function(func, wait, immediate) { | |
var timeout; | |
return function() { | |
var context = this, args = arguments; | |
var later = function() { | |
timeout = null; | |
if (!immediate) func.apply(context, args); | |
}; | |
var callNow = immediate && !timeout; | |
clearTimeout(timeout); | |
timeout = setTimeout(later, wait); | |
if (callNow) func.apply(context, args); | |
}; | |
}; | |
// Clear the queue - set every pending function to run | |
// at intervals of #{INTERVAL} * index | |
function runQueue() { | |
console.log('clearing the queue...'); | |
var item; | |
for (var i=0;i<queue.length;i++) { | |
setTimeout(queue[i], INTERVAL*i); | |
console.log('added queue item to run: ' + queue[i] + | |
' in ms: ' + INTERVAL*i); | |
} | |
// Clear the queue, we're done here. | |
queue = []; | |
} | |
// we're calling runq inside the code, make it so it calls at least | |
// 15s apart | |
var runq = _.debounce(runQueue, 15000); | |
// Set up Twit client. | |
// Get your keys from: | |
// https://apps.twitter.com/app/<your app ID>/keys | |
var T = new Twit({ | |
consumer_key: process.env['API_KEY'], | |
consumer_secret: process.env['API_SECRET'], | |
access_token: process.env['ACCESS_TOKEN'], | |
access_token_secret: process.env['ACCESS_TOKEN_SECRET'] | |
}); | |
// Get #{count} mentions | |
T.get('statuses/mentions_timeline', { | |
count: COUNT | |
}, | |
function(err, data, response) { | |
// we did something wrong, or we're over the limit. hear twitter out | |
if (response.statusCode !== 200) { | |
if (response.statusCode === 429) { | |
console.log('aborting: we hit the rate limit!'); | |
} else if (response.statusCode === 403) { | |
console.log('aborting: unauthorized!'); | |
} else { | |
console.log('aborting: http ' + response.statusCode); | |
} | |
return; | |
} | |
// we're in the clear! | |
console.log('requests left:', response.headers['x-rate-limit-remaining']); | |
console.log('requests will reset on', | |
new Date( | |
Date.now() + Number(response.headers['x-rate-limit-reset'])/1000)); | |
// Actually go over the entries | |
for (var i=0;i<data.length;i++) { | |
// Mangle the tweet text | |
var reversed = data[i].text.replace(mention, '') | |
.split(' ') | |
.reverse() | |
.join(' '); | |
// Nicely log every Tweet and its reversed text | |
console.log('from @' + data[i].user.screen_name + '/'+data[i].user.id); | |
console.log('\treversed:', reversed); | |
// Create the entire Tweet response | |
var status = '@'+data[i].user.screen_name + ' ' + reversed; | |
if (data[i].user.id == filter_id) { | |
console.log('found a tweet from the filter, posting response'); | |
// Push the tweet-sending-function into the tweet queue | |
queue.push( | |
// Create a tweet-sending-function by running a function to | |
// return it, taking the tweet content as an argument. | |
// Javascript scoping is weird. | |
(function(status) { | |
// Return a function that calls statuses/update with our | |
// tweet text. | |
return function() { | |
console.log('posting tweet!'); | |
// Call statuses/update with our tweet text. | |
// Then, handle possible statuses, and stop. | |
T.post('statuses/update', { | |
'status': status }, function(err, data, response) { | |
if (response.statusCode == 403) { | |
console.log('already posted that tweet. bye'); | |
} else if (response.statusCode == 200) { | |
console.log('yay! all worked out after all!'); | |
} }); }; })(status)); | |
// Clear the queue, if it hasn't been cleared in 15 seconds. | |
runq(); | |
} | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment