Skip to content

Instantly share code, notes, and snippets.

@boxmein
Created September 16, 2014 01:17
Show Gist options
  • Save boxmein/62be7fc58f3af36fb67d to your computer and use it in GitHub Desktop.
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.
// 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