From 2c0dd496ca4f6371ad455b791da82f40533a39af Mon Sep 17 00:00:00 2001 From: Raul Rene Lepsa Date: Wed, 4 Jan 2017 15:12:35 +0200 Subject: [PATCH] Fixing flow. Updating readme. Finished ES6 Rewriting. --- README.md | 6 ++--- api-functions.js | 2 +- index.js | 65 +++++++++++++++++++++++++++--------------------- package.json | 10 ++++++-- 4 files changed, 49 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 97cb79c..fc23942 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,11 @@ A Javascript bot that searches for tweets about contests and Retweets them. If n Inspired by http://www.hscott.net/twitter-contest-winning-as-a-service/ -##Disclaimer +## Disclaimer This bot is written purely for educational purposes. I hold no liability for what you do with this bot or what happens to you by using this bot. Abusing this bot can get you banned from Twitter, so make sure to read up on proper usage of the Twitter API. -##Installation +## Installation * Make sure you have NodeJS up and running * `git clone` the repository, or download the zip file and unzip it * `npm install` in the directory where you cloned the repository (this is needed for installing dependencies) @@ -16,7 +16,7 @@ This bot is written purely for educational purposes. I hold no liability for wha * run `node index.js` ## Dependencies -It makes use of the request-promise library, a HTTP JS client. +It makes use of [request-promise](https://github.com/request/request-promise) - a HTTP JS client ## Alternatives If you're looking for similar projects in alternative languages, check these out: diff --git a/api-functions.js b/api-functions.js index fe3beec..64de3d4 100644 --- a/api-functions.js +++ b/api-functions.js @@ -53,7 +53,7 @@ const API = { if (result && result.statuses) { result.statuses.forEach(item => allItems.push(item)); - console.log('So far we have a total of:', allItems.length); + console.log('[Search] So far we have', allItems.length, 'items'); // If we have the next_results, search again for the rest (sort of a pagination) const nextRes = result.search_metadata.next_results; diff --git a/index.js b/index.js index 59c0986..7fc98f2 100644 --- a/index.js +++ b/index.js @@ -23,9 +23,9 @@ class ContestJSBot { this.search(); // Start the Retweet worker after short grace period for search results to come in - setTimeout(() => this.retweetWorker.bind(this), 8000); + setTimeout(() => this.retweetWorker(), config.RETWEET_TIMEOUT); }) - .catch((err) => console.error('Your credentials are not valid. Check the config.js file and ensure you supply the correct API keys.', err.messsage)); + .catch(err => console.error('Your credentials are not valid. Check the config.js file and ensure you supply the correct API keys.', err)); } /** The Search function */ @@ -33,26 +33,33 @@ class ContestJSBot { // Don't search if limit lockout is in effect if (this.limitLockout) return; - console.log('Searching for tweets...'); - let text = ''; + const since_id = this.last_tweet_id; + console.log('[Search] Searching for tweets...'); - config.SEARCH_QUERIES.forEach((searchQuery) => { + let doSearch = (index) => { // Construct the query - text = searchQuery + config.SEARCH_QUERY_FILTERS; + let text = config.SEARCH_QUERIES[index] + config.SEARCH_QUERY_FILTERS; // Append preferred accounts if it's the case if (config.PREFERRED_ACCOUNTS) { text += ` from:${config.PREFERRED_ACCOUNTS.join(' OR from:')}`; } - API.search({text, result_type: config.RESULT_TYPE, since_id: this.last_tweet_id}) - .then(res => this.searchCallback(res)) + API.search({text, result_type: config.RESULT_TYPE, since_id}) + .then(res => { + // Call the search callback to process the data + this.searchCallback(res); + + if (config.SEARCH_QUERIES[index + 1]) { + // Sleep between searches so we do not trigger rate limit lockout + console.log(`[Search] Sleeping for ${config.RATE_SEARCH_TIMEOUT / 1000} seconds between searches so we don't trigger rate limit`); + setTimeout(() => doSearch(index++), config.RATE_SEARCH_TIMEOUT); + } + }) .catch(err => this.errorHandler(err)); + }; - // we need to wait between search queries so we do not trigger rate limit lockout - // sleepFor(config.RATE_SEARCH_TIMEOUT); - // console.log(`Sleeping for ${config.RATE_SEARCH_TIMEOUT} ms between searches so we don't trigger rate limit`); - }); + doSearch(0); } /** The Callback function for the Search API */ @@ -75,16 +82,18 @@ class ContestJSBot { if (this.blockedUsers.indexOf(searchItem.user.id) > -1) return; // We ignore users with high amounts of tweets (likely bots) - if (config.MAX_USER_TWEETS && searchItem.user.statuses_count < config.MAX_USER_TWEETS) { - // Save the search item in the Search Results array - this.searchResultsArr.push(searchItem); - } - // may be a spam bot, do we want to block them? - else if (config.MAX_USER_TWEETS_BLOCK) { - this.blockedUsers.push(searchItem.user.id); - API.blockUser(searchItem.user.id) - .then(() => console.log('Blocked possible bot user ' + searchItem.user.id)); + if (config.MAX_USER_TWEETS && searchItem.user.statuses_count >= config.MAX_USER_TWEETS) { + // may be a spam bot, do we want to block them? + if (config.MAX_USER_TWEETS_BLOCK) { + this.blockedUsers.push(searchItem.user.id); + API.blockUser(searchItem.user.id) + .then(() => console.log('Blocked possible bot user' + searchItem.user.id)); + } + return; } + + // Save the search item in the Search Results array + this.searchResultsArr.push(searchItem); }); } @@ -119,22 +128,22 @@ class ContestJSBot { this.searchResultsArr.shift(); // Retweet - console.log('[Retweeting]', searchItem.id); + console.log('[Retweeting Tweet #]', searchItem.id); API.retweet(searchItem.id_str) .then(() => { // On success, try to Favorite/Like and Follow if (searchItem.text.toLowerCase().indexOf('fav') > -1 || searchItem.text.toLowerCase().indexOf('like') > -1) { API.favorite(searchItem.id_str); - console.log('[Favorite]', searchItem.id); + console.log('[Marking as Favorite tweet #]', searchItem.id); } if (searchItem.text.toLowerCase().indexOf('follow') > -1) { API.follow(searchItem.user.id_str); - console.log('[Follow]', searchItem.user.screen_name); + console.log('[Following user]', searchItem.user.screen_name); } // Then, re-queue the RT Worker - setTimeout(() => this.retweetWorker.bind(this), config.RETWEET_TIMEOUT); + setTimeout(() => this.retweetWorker(), config.RETWEET_TIMEOUT); }) .catch(() => { console.error('[Error] RT Failed for', searchItem.id, '. Likely has already been retweeted. Adding to blacklist.'); @@ -143,7 +152,7 @@ class ContestJSBot { this.badTweetIds.push(searchItem.id); // Then, re-start the RT Worker - setTimeout(() => this.retweetWorker.bind(this), config.RETWEET_TIMEOUT); + setTimeout(() => this.retweetWorker(), config.RETWEET_TIMEOUT); }); } @@ -152,7 +161,7 @@ class ContestJSBot { else { if (this.limitLockout) { // we must schedule this to rerun, or else the program will exit when a lockout occurs - setTimeout(() => this.retweetWorker.bind(this), config.RATE_SEARCH_TIMEOUT); + setTimeout(() => this.retweetWorker(), config.RATE_SEARCH_TIMEOUT); return; } @@ -160,7 +169,7 @@ class ContestJSBot { // go fetch new results this.search(); - setTimeout(() => this.retweetWorker.bind(this), config.RATE_SEARCH_TIMEOUT); + setTimeout(() => this.retweetWorker(), config.RATE_SEARCH_TIMEOUT); } } } diff --git a/package.json b/package.json index 7182d92..0393ebc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,13 @@ { - "name": "Twitter contest JS bot", - "description": "A Javascript bot that searches for tweets about contests and retweets them.", + "name": "twitter-contest-js-bot", + "version": "2.0.0", "author": "Raul Rene Lepsa ", + "description": "A Javascript bot that searches for tweets about contests and retweets them.", + "license": "MIT", + "repository": { + "type": "git", + "url": "git://github.com/raulrene/twitter-contest-js-bot.git" + }, "dependencies": { "request-promise": "^0.4.3" }