Comparing version 2.0.0 to 3.0.0
/* | ||
Install Instructions: | ||
1. Replace the strings in this object to include your Twitter App Credentials. | ||
2. Rename this file to `local-config.js` | ||
*/ | ||
Install Instructions: | ||
1. Replace the strings in this object to include your Twitter App Credentials. | ||
2. Rename this file to `local-config.js` | ||
*/ | ||
module.exports = { | ||
@@ -16,1 +13,2 @@ consumerKey: 'YOUR_CONSUMER_KEY', | ||
}; | ||
@@ -1,1 +0,1 @@ | ||
[{"created_at":"Sun Dec 27 11:56:56 +0000 2015","id":681081326330576900,"id_str":"681081326330576896","text":"Running some final tests for #birdwatch version 1.0.0!","source":"<a href=\"http://twitter.com\" rel=\"nofollow\">Twitter Web Client</a>","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":4610920816,"id_str":"4610920816","name":"Bird Watch","screen_name":"birdwatchnpm","location":"","description":"This is an account to test the functionality of the Birdwatch module: https://t.co/5kQUCHlgNL","url":null,"entities":{"description":{"urls":[{"url":"https://t.co/5kQUCHlgNL","expanded_url":"https://github.com/radiovisual/birdwatch","display_url":"github.com/radiovisual/bi…","indices":[70,93]}]}},"protected":false,"followers_count":1,"friends_count":0,"listed_count":3,"created_at":"Sat Dec 26 12:52:22 +0000 2015","favourites_count":0,"utc_offset":null,"time_zone":null,"geo_enabled":false,"verified":false,"statuses_count":7,"lang":"en","contributors_enabled":false,"is_translator":false,"is_translation_enabled":false,"profile_background_color":"F5F8FA","profile_background_image_url":null,"profile_background_image_url_https":null,"profile_background_tile":false,"profile_image_url":"http://abs.twimg.com/sticky/default_profile_images/default_profile_5_normal.png","profile_image_url_https":"https://abs.twimg.com/sticky/default_profile_images/default_profile_5_normal.png","profile_link_color":"2B7BB9","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"has_extended_profile":false,"default_profile":true,"default_profile_image":true,"following":false,"follow_request_sent":false,"notifications":false},"geo":null,"coordinates":null,"place":null,"contributors":null,"is_quote_status":false,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[{"text":"birdwatch","indices":[29,39]}],"symbols":[],"user_mentions":[],"urls":[]},"favorited":false,"retweeted":false,"lang":"en","html":"Running some final tests for <a href=\"https://twitter.com/hashtag/birdwatch\">#birdwatch</a> version 1.0.0!"},{"created_at":"Sat Dec 26 13:03:44 +0000 2015","id":680735749923299300,"id_str":"680735749923299328","text":"This account will be used to help test the functionality of Birdwatch. #birdwatch","source":"<a href=\"http://twitter.com\" rel=\"nofollow\">Twitter Web Client</a>","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":4610920816,"id_str":"4610920816","name":"Bird Watch","screen_name":"birdwatchnpm","location":"","description":"This is an account to test the functionality of the Birdwatch module: https://t.co/5kQUCHlgNL","url":null,"entities":{"description":{"urls":[{"url":"https://t.co/5kQUCHlgNL","expanded_url":"https://github.com/radiovisual/birdwatch","display_url":"github.com/radiovisual/bi…","indices":[70,93]}]}},"protected":false,"followers_count":1,"friends_count":0,"listed_count":3,"created_at":"Sat Dec 26 12:52:22 +0000 2015","favourites_count":0,"utc_offset":null,"time_zone":null,"geo_enabled":false,"verified":false,"statuses_count":7,"lang":"en","contributors_enabled":false,"is_translator":false,"is_translation_enabled":false,"profile_background_color":"F5F8FA","profile_background_image_url":null,"profile_background_image_url_https":null,"profile_background_tile":false,"profile_image_url":"http://abs.twimg.com/sticky/default_profile_images/default_profile_5_normal.png","profile_image_url_https":"https://abs.twimg.com/sticky/default_profile_images/default_profile_5_normal.png","profile_link_color":"2B7BB9","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"has_extended_profile":false,"default_profile":true,"default_profile_image":true,"following":false,"follow_request_sent":false,"notifications":false},"geo":null,"coordinates":null,"place":null,"contributors":null,"is_quote_status":false,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[{"text":"birdwatch","indices":[71,81]}],"symbols":[],"user_mentions":[],"urls":[]},"favorited":false,"retweeted":false,"lang":"en","html":"This account will be used to help test the functionality of Birdwatch. <a href=\"https://twitter.com/hashtag/birdwatch\">#birdwatch</a>"}] | ||
[{"created_at":"Mon Jul 10 14:14:42 +0000 2015","text":"test tweet #10","retweeted_status":{},"html":"test tweet #10"},{"created_at":"Mon Jul 09 14:14:42 +0000 2015","text":"test tweet #09","retweeted_status":{},"html":"test tweet #09"},{"created_at":"Mon Jul 08 14:14:42 +0000 2015","text":"test tweet #08","retweeted_status":{},"html":"test tweet #08"},{"created_at":"Mon Jul 07 14:14:42 +0000 2015","text":"test tweet #07","retweeted_status":{},"html":"test tweet #07"},{"created_at":"Mon Jul 06 14:14:42 +0000 2015","text":"test tweet #06","retweeted_status":{},"html":"test tweet #06"},{"created_at":"Mon Jul 05 14:14:42 +0000 2015","text":"test tweet #05","html":"test tweet #05"},{"created_at":"Mon Jul 04 14:14:42 +0000 2015","text":"test tweet #04","html":"test tweet #04"},{"created_at":"Mon Jul 03 14:14:42 +0000 2015","text":"test tweet #03","html":"test tweet #03"},{"created_at":"Mon Jul 02 14:14:42 +0000 2015","text":"test tweet #02","html":"test tweet #02"},{"created_at":"Mon Jul 01 14:14:42 +0000 2015","text":"test tweet #01","html":"test tweet #01"}] |
@@ -31,2 +31,6 @@ 'use strict'; | ||
var _getPort = require('get-port'); | ||
var _getPort2 = _interopRequireDefault(_getPort); | ||
var _report = require('./report'); | ||
@@ -47,8 +51,23 @@ | ||
this.options = (0, _objectAssign2['default'])({}, options); | ||
this.options.testData = this.options.testData || null; | ||
this.options.refreshTime = this.options.refreshTime || 600; | ||
this.options.logReports = this.options.logReports || false; | ||
var defaults = { | ||
logReports: true, | ||
server: true, | ||
port: 8417, | ||
testData: null, | ||
refreshTime: 600, | ||
url: '/birdwatch/tweets', | ||
cacheDir: __dirname + '/cache', | ||
sortBy: function sortBy(tweet) { | ||
return new Date(tweet.created_at) * -1; | ||
} | ||
}; | ||
this.options = (0, _objectAssign2['default'])(defaults, options); | ||
if (typeof this.options.sortBy !== 'function') { | ||
throw new TypeError('sortBy value must be a function.'); | ||
} | ||
this.feeds = []; | ||
this.allTweets = []; | ||
this.filteredTweets = []; | ||
@@ -75,2 +94,4 @@ this.tweets = []; | ||
options = options || {}; | ||
options.limit = options.limit || 12; | ||
this._feed.push({ screenname: screenname, options: options }); | ||
@@ -97,5 +118,12 @@ | ||
self = this; | ||
context$2$0.next = 3; | ||
return _regeneratorRuntime.awrap((0, _getPort2['default'])().then(function (port) { | ||
if (self.options.port === 0) { | ||
_this.options.port = port; | ||
} | ||
})); | ||
case 3: | ||
if (!(!this.feed() || this.feed().length === 0)) { | ||
context$2$0.next = 3; | ||
context$2$0.next = 5; | ||
break; | ||
@@ -106,6 +134,9 @@ } | ||
case 3: | ||
context$2$0.next = 5; | ||
case 5: | ||
_report2['default'].logStartMessage(self.refreshTime, self); | ||
context$2$0.next = 8; | ||
return _regeneratorRuntime.awrap(_Promise.all(this.feed().map(function (feed) { | ||
var options = (0, _objectAssign2['default'])({}, _this.options, feed.options); | ||
var options = (0, _objectAssign2['default'])({}, self.options, feed.options); | ||
@@ -123,28 +154,26 @@ if (!feed.screenname) { | ||
} | ||
_this.feeds.push({ screenname: feed.screenname, options: options }); | ||
self.feeds.push({ screenname: feed.screenname, options: options }); | ||
}))); | ||
case 5: | ||
if (self.logReports) { | ||
_report2['default'].logStartMessage(this.refreshTime, this.feeds.length); | ||
} | ||
context$2$0.next = 8; | ||
return _regeneratorRuntime.awrap(this.processFeeds(this.feeds, this.options)); | ||
case 8: | ||
context$2$0.next = 10; | ||
return _regeneratorRuntime.awrap(this.sortTweets()); | ||
return _regeneratorRuntime.awrap(self.processFeeds(self.feeds, self.options)); | ||
case 10: | ||
this.tweets = context$2$0.sent; | ||
context$2$0.next = 12; | ||
return _regeneratorRuntime.awrap(self.startTimer(self.feeds, self.options)); | ||
this.saveToCacheFile(); | ||
this.startTimer(this.feeds, this.options); | ||
case 12: | ||
if (!self.options.server) { | ||
context$2$0.next = 15; | ||
break; | ||
} | ||
return context$2$0.abrupt('return', this); | ||
context$2$0.next = 15; | ||
return _regeneratorRuntime.awrap(self.startServer()); | ||
case 14: | ||
case 15: | ||
return context$2$0.abrupt('return', _Promise.resolve(self.tweets)); | ||
case 16: | ||
case 'end': | ||
@@ -151,0 +180,0 @@ return context$2$0.stop(); |
'use strict'; | ||
var chalk = require('chalk'); | ||
var version = require('./../package').version; | ||
module.exports.logStartMessage = function (refreshTime, feedNum) { | ||
module.exports.logStartMessage = function (refreshTime, birdwatch) { | ||
var feeds = birdwatch.feed().length; | ||
var refreshSeconds = birdwatch.options.refreshTime; | ||
var refreshMinutes = Math.round(refreshSeconds / 60); | ||
var cache = birdwatch.options.cacheDir + '/cached_tweets.json'; | ||
var server = birdwatch.options.server; | ||
var port = birdwatch.options.port; | ||
var url = birdwatch.options.url; | ||
var vers = 'v' + version; | ||
console.log('\n\n'); | ||
console.log(chalk.cyan('| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |')); | ||
console.log(chalk.cyan('|') + ' Running Birdwatch ' + chalk.gray(version)); | ||
console.log(chalk.cyan('|') + ' ' + chalk.gray(' Monitoring Feeds: ') + ' ' + chalk.white(feedNum)); | ||
console.log(chalk.cyan('|') + ' ' + chalk.gray(' Refresh Time: ') + ' ' + chalk.white(refreshTime) + ' secs (' + secondsToMinutes(refreshTime) + ' mins)'); | ||
console.log(chalk.cyan('| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |\n')); | ||
console.log(chalk.cyan('| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ')); | ||
console.log(chalk.cyan('|') + ' Running Birdwatch ' + chalk.gray(vers)); | ||
console.log(chalk.cyan('|') + ' ' + chalk.gray(' Monitoring Feeds: ') + ' ' + chalk.white(feeds)); | ||
console.log(chalk.cyan('|') + ' ' + chalk.gray(' Refresh Time: ') + ' ' + chalk.white(refreshSeconds) + ' secs (' + refreshMinutes + ' min)'); | ||
console.log(chalk.cyan('|') + ' ' + chalk.gray(' Cache File: ') + ' ' + chalk.white(cache)); | ||
if (server) { | ||
console.log(chalk.cyan('|') + ' ' + chalk.gray(' Birdwatch Server: ') + ' localhost:' + chalk.cyan(port) + url); | ||
} | ||
console.log(chalk.cyan('| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ')); | ||
}; | ||
@@ -35,6 +48,2 @@ | ||
function secondsToMinutes(seconds) { | ||
return Math.round(seconds / 60); | ||
} | ||
module.exports.processBirdwatchingMessage = function () { | ||
@@ -41,0 +50,0 @@ console.log(chalk.cyan('\nLet\'s go Birdwatching!') + ' ' + chalk.gray(new Date())); |
@@ -18,3 +18,3 @@ 'use strict'; | ||
exports.saveToCacheFile = saveToCacheFile; | ||
exports.getCachedTweets = getCachedTweets; | ||
exports.startServer = startServer; | ||
@@ -33,2 +33,6 @@ var _objectAssign = require('object-assign'); | ||
var _report = require('./report'); | ||
var _report2 = _interopRequireDefault(_report); | ||
var _mkdirp = require('mkdirp'); | ||
@@ -38,6 +42,2 @@ | ||
var _report = require('./report'); | ||
var _report2 = _interopRequireDefault(_report); | ||
var _oauth = require('oauth'); | ||
@@ -51,2 +51,6 @@ | ||
var _pify = require('pify'); | ||
var _pify2 = _interopRequireDefault(_pify); | ||
var _fs = require('fs'); | ||
@@ -56,2 +60,4 @@ | ||
var server = require('express')(); | ||
/** | ||
@@ -73,2 +79,3 @@ * Process the feeds by starting the promise chain. | ||
self.filteredTweets = []; | ||
self.allTweets = []; | ||
@@ -80,6 +87,5 @@ // Let's go Birdwatching! | ||
context$1$0.next = 5; | ||
return _regeneratorRuntime.awrap(_Promise.all(feeds.map(function (feed) { | ||
return new _Promise(function callee$2$0(resolve, reject) { | ||
var options, screenname, p; | ||
return context$1$0.abrupt('return', _Promise.all(feeds.map(function (feed, index) { | ||
new _Promise(function callee$2$0(resolve) { | ||
var options, screenname; | ||
return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { | ||
@@ -90,11 +96,26 @@ while (1) switch (context$3$0.prev = context$3$0.next) { | ||
screenname = feed.screenname; | ||
p = getTwitterData(screenname, options).then(function (tweets) { | ||
return self.filterTweets(tweets, screenname, options); | ||
}).then(resolve); | ||
context$3$0.next = 4; | ||
return _regeneratorRuntime.awrap(self.getTwitterData(screenname, options)); | ||
p['catch'](function (error) { | ||
reject(error); | ||
}); | ||
case 4: | ||
context$3$0.next = 6; | ||
return _regeneratorRuntime.awrap(self.filterTweets(screenname, options)); | ||
case 4: | ||
case 6: | ||
context$3$0.next = 8; | ||
return _regeneratorRuntime.awrap(self.sortTweets()); | ||
case 8: | ||
if (!(index === feeds.length - 1)) { | ||
context$3$0.next = 11; | ||
break; | ||
} | ||
context$3$0.next = 11; | ||
return _regeneratorRuntime.awrap(self.saveToCacheFile()); | ||
case 11: | ||
resolve(self.tweets); | ||
case 12: | ||
case 'end': | ||
@@ -123,31 +144,26 @@ return context$3$0.stop(); | ||
function getTwitterData(screenname, options) { | ||
return _regeneratorRuntime.async(function getTwitterData$(context$1$0) { | ||
while (1) switch (context$1$0.prev = context$1$0.next) { | ||
case 0: | ||
if (options.logReports) { | ||
_report2['default'].reportFetchingMessage(screenname, options.filterTags); | ||
} | ||
var self = this; | ||
return context$1$0.abrupt('return', new _Promise(function (resolve, reject) { | ||
if (options.testData) { | ||
resolve(options.testData); | ||
} | ||
if (self.options.logReports) { | ||
_report2['default'].reportFetchingMessage(screenname, options.filterTags); | ||
} | ||
var credentials = require('./../local-config.js'); | ||
return new _Promise(function (resolve, reject) { | ||
if (options.testData) { | ||
self.allTweets = options.testData; | ||
resolve(); | ||
} | ||
var oauth = new _oauth2['default'].OAuth('https://api.twitter.com/oauth/request_token', 'https://api.twitter.com/oauth/access_token', credentials.consumerKey, credentials.consumerSecret, '1.0A', null, 'HMAC-SHA1'); | ||
var credentials = getCredentials(); | ||
oauth.get('https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=' + screenname + '&include_rts=1&count=200', credentials.accessToken, credentials.accessTokenSecret, function (err, data) { | ||
if (err) { | ||
reject(err); | ||
} | ||
resolve(JSON.parse(data)); | ||
}); | ||
})); | ||
var oauth = new _oauth2['default'].OAuth('https://api.twitter.com/oauth/request_token', 'https://api.twitter.com/oauth/access_token', credentials.consumerKey, credentials.consumerSecret, '1.0A', null, 'HMAC-SHA1'); | ||
case 2: | ||
case 'end': | ||
return context$1$0.stop(); | ||
} | ||
}, null, this); | ||
oauth.get('https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=' + screenname + '&include_rts=1&count=200', credentials.accessToken, credentials.accessTokenSecret, function (err, data) { | ||
if (err) { | ||
reject(err); | ||
} | ||
self.allTweets = JSON.parse(data); | ||
resolve(); | ||
}); | ||
}); | ||
} | ||
@@ -158,3 +174,2 @@ | ||
* | ||
* @param {Object} tweetdata - the returned tweet data from Twitter | ||
* @param {String} screenname - the screenname of the current feed | ||
@@ -165,35 +180,36 @@ * @param {Object} options - the feed options | ||
function filterTweets(tweetdata, screenname, options) { | ||
var self; | ||
return _regeneratorRuntime.async(function filterTweets$(context$1$0) { | ||
while (1) switch (context$1$0.prev = context$1$0.next) { | ||
case 0: | ||
self = this; | ||
return context$1$0.abrupt('return', new _Promise(function (resolve) { | ||
for (var i in tweetdata) { | ||
if (({}).hasOwnProperty.call(tweetdata, i)) { | ||
var tweet = tweetdata[i]; | ||
var isRetweet = tweet.retweeted_status; | ||
function filterTweets(screenname, options) { | ||
var self = this; | ||
var limit = options.limit; | ||
var count = 0; | ||
if (isRetweet && options.removeRetweets) { | ||
continue; | ||
} | ||
var tweetdata = self.allTweets; | ||
tweet.html = tweet.html || (0, _tweetPatch2['default'])(tweet); | ||
return new _Promise(function (resolve) { | ||
for (var i in tweetdata) { | ||
if (({}).hasOwnProperty.call(tweetdata, i)) { | ||
var tweet = tweetdata[i]; | ||
var isRetweet = tweet.retweeted_status; | ||
if (options.filterTags && options.filterTags.test(tweet.text)) { | ||
self.filteredTweets.push(tweet); | ||
} else if (!options.filterTags) { | ||
self.filteredTweets.push(tweet); | ||
} | ||
} | ||
} | ||
resolve(self.filteredTweets); | ||
})); | ||
if (isRetweet && options.removeRetweets) { | ||
continue; | ||
} | ||
case 2: | ||
case 'end': | ||
return context$1$0.stop(); | ||
tweet.html = tweet.html || (0, _tweetPatch2['default'])(tweet); | ||
if (options.filterTags && options.filterTags.test(tweet.text)) { | ||
self.filteredTweets.push(tweet); | ||
count++; | ||
} else if (!options.filterTags) { | ||
self.filteredTweets.push(tweet); | ||
count++; | ||
} | ||
if (count >= limit) { | ||
break; | ||
} | ||
} | ||
} | ||
}, null, this); | ||
resolve(self.filteredTweets); | ||
}); | ||
} | ||
@@ -209,30 +225,8 @@ | ||
function sortTweets() { | ||
var self, sortBy; | ||
return _regeneratorRuntime.async(function sortTweets$(context$1$0) { | ||
while (1) switch (context$1$0.prev = context$1$0.next) { | ||
case 0: | ||
self = this; | ||
sortBy = self.options.sortBy || function (tweet) { | ||
return new Date(tweet.created_at) * -1; | ||
}; | ||
if (!(typeof sortBy !== 'function')) { | ||
context$1$0.next = 4; | ||
break; | ||
} | ||
throw new TypeError('sortBy value must be a function.'); | ||
case 4: | ||
return context$1$0.abrupt('return', new _Promise(function (resolve) { | ||
var sorted = _underscore2['default'].sortBy(self.filteredTweets, sortBy); | ||
resolve(sorted); | ||
})); | ||
case 5: | ||
case 'end': | ||
return context$1$0.stop(); | ||
} | ||
}, null, this); | ||
var self = this; | ||
return new _Promise(function (resolve) { | ||
var sorted = _underscore2['default'].sortBy(self.filteredTweets, self.options.sortBy); | ||
self.tweets = sorted; | ||
resolve(sorted); | ||
}); | ||
} | ||
@@ -265,7 +259,9 @@ | ||
case 4: | ||
self.tweets = context$2$0.sent; | ||
context$2$0.next = 6; | ||
return _regeneratorRuntime.awrap(self.saveToCacheFile()); | ||
saveToCacheFile(); | ||
case 6: | ||
return context$2$0.abrupt('return', _Promise.resolve()); | ||
case 6: | ||
case 7: | ||
case 'end': | ||
@@ -284,26 +280,65 @@ return context$2$0.stop(); | ||
function saveToCacheFile() { | ||
var _this3 = this; | ||
var self = this; | ||
var file = _path2['default'].join(self.options.cacheDir, 'cached_tweets.json'); | ||
var cacheFile = __dirname + '/cache/cached_tweets.json'; | ||
var getDirName = _path2['default'].dirname; | ||
return new _Promise(function callee$1$0(resolve, reject) { | ||
return _regeneratorRuntime.async(function callee$1$0$(context$2$0) { | ||
while (1) switch (context$2$0.prev = context$2$0.next) { | ||
case 0: | ||
context$2$0.next = 2; | ||
return _regeneratorRuntime.awrap((0, _pify2['default'])(_mkdirp2['default'])(self.options.cacheDir)); | ||
function writeFile(path, contents) { | ||
(0, _mkdirp2['default'])(getDirName(path), function (err) { | ||
if (err) { | ||
console.error(err); | ||
case 2: | ||
_fs2['default'].writeFile(file, JSON.stringify(self.tweets), function (err) { | ||
if (err) { | ||
reject(err); | ||
} | ||
resolve(); | ||
}); | ||
case 3: | ||
case 'end': | ||
return context$2$0.stop(); | ||
} | ||
_fs2['default'].writeFile(path, contents); | ||
}); | ||
} | ||
writeFile(cacheFile, JSON.stringify(self.tweets)); | ||
}, null, _this3); | ||
}); | ||
} | ||
/** | ||
* Get the cached tweets object | ||
* Start the birdwatch server | ||
* | ||
* @returns {Array} | ||
* @api private | ||
*/ | ||
function getCachedTweets() { | ||
return this.tweets; | ||
function startServer() { | ||
var self; | ||
return _regeneratorRuntime.async(function startServer$(context$1$0) { | ||
while (1) switch (context$1$0.prev = context$1$0.next) { | ||
case 0: | ||
self = this; | ||
server.get(self.options.url, function (req, res) { | ||
res.json(self.tweets); | ||
}); | ||
server.listen(self.options.port); | ||
case 3: | ||
case 'end': | ||
return context$1$0.stop(); | ||
} | ||
}, null, this); | ||
} | ||
/** | ||
* Get the Twitter Credentials from local-config.js | ||
* | ||
* @returns {object} | ||
* @api private | ||
*/ | ||
function getCredentials() { | ||
return require('./../local-config.js'); | ||
} |
{ | ||
"name": "birdwatch", | ||
"version": "2.0.0", | ||
"version": "3.0.0", | ||
"description": "Monitor, filter, cache and serve specific twitter feeds.", | ||
"main": "dist/index.js", | ||
"files" : [ | ||
"files": [ | ||
"dist", | ||
@@ -14,4 +14,4 @@ "birdwatch-config.js" | ||
"scripts": { | ||
"test": "xo && npm run prepublish && ava", | ||
"prepublish": "babel lib --out-dir=dist --optional=runtime" | ||
"test": "xo && npm run build && ava", | ||
"build": "babel lib --out-dir=dist --optional=runtime" | ||
}, | ||
@@ -55,2 +55,5 @@ "repository": { | ||
"chalk": "~1.1.0", | ||
"clear": "0.0.1", | ||
"express": "^4.13.4", | ||
"get-port": "^2.1.0", | ||
"hash-regex": "^1.0.0", | ||
@@ -67,2 +70,7 @@ "is-regexp": "~1.0.0", | ||
"babel": "^5.8.23", | ||
"got": "^6.1.1", | ||
"pify": "^2.3.0", | ||
"rimraf": "^2.5.1", | ||
"selective-whitespace": "^1.0.0", | ||
"xmark": "0.0.4", | ||
"xo": "*" | ||
@@ -73,7 +81,9 @@ }, | ||
"ignores": [ | ||
"local-config.js", | ||
"dist/**", | ||
"test/**" | ||
] | ||
"local-config.js" | ||
], | ||
"rules" : { | ||
"no-new": 0 | ||
} | ||
} | ||
} |
140
readme.md
@@ -12,3 +12,3 @@ # Birdwatch :baby_chick::watch: | ||
**Note:** This is a work in progress. *Pull requests welcome!* | ||
**Note:** This is a work in progress. If you find any bugs, or have suggestions [please report them](https://github.com/radiovisual/birdwatch/issues). If you want to help, pull requests are always appreciated! | ||
@@ -26,3 +26,3 @@ ## Installation | ||
3. Rename the file to `local-config.js` | ||
4. *Now you're ready to birdwatch!* | ||
4. *Now you're ready to birdwatch!* :baby_chick: :bowtie: | ||
@@ -32,30 +32,41 @@ ## Usage | ||
```js | ||
var Birdwatch = require('birdwatch'); | ||
var birdwatch = new Birdwatch() | ||
.feed('gulpjs') | ||
.feed('reactjs', {filterTags: ['tag1', 'tag2']}) | ||
.feed('nodejs', {filterTags: /#tag1|#tag2/i, removeRetweets:true}) | ||
.start(); | ||
new Birdwatch() | ||
.feed('justinbieber') | ||
.feed('taylorswift13', {filterTags:['tagOne', 'tagTwo']}) | ||
.start() | ||
.then(tweets => { | ||
console.log('birdwatch is ready to serve %s tweets', tweets.length); | ||
}); | ||
``` | ||
// Now get your tweets in JSON format to serve or print | ||
birdwatch.getCachedTweets(); | ||
By default, Birdwatch will launch a server on port `8417` for you, but you can change the port number using the `port` option. After running the code above, you can access your tweets at the default location: | ||
``` | ||
http://localhost:8417/birdwatch/tweets | ||
``` | ||
## Extra Features | ||
### Cached HTML Tweet | ||
- If birdwatch can't find an `html` string on the returned tweet data, then it adds one for you using [tweet-patch](https://github.com/radiovisual/tweet-patch). | ||
This means the plain-text hashtags, user-mentions and hyperlinks are converted to twitter-ready HTML. Example below. | ||
If birdwatch can't find an `html` string on the returned tweet data, (which is sometimes the default from the Twitter API), then one will be rebuilt and added for you via [tweet-patch](https://github.com/radiovisual/tweet-patch). This means the **plaintext** hashtags, user-mentions and hyperlinks are converted back to twitter-ready markup for you. ::heart_eyes:: (You're welcome) Example below. | ||
- ```js | ||
cached_tweets[0].text; | ||
//=> "This is the #plaintext tweet" | ||
```js | ||
cached_tweets[0].text; | ||
//=> "This is the #plaintext tweet" | ||
cached_tweets[0].html; | ||
//=> "This is the <a href="https://twitter.com/hashtag/plaintext">#plaintext</a> tweet" | ||
``` | ||
cached_tweets[0].html; | ||
//=> "This is the <a href="https://twitter.com/hashtag/plaintext">#plaintext</a> tweet" | ||
``` | ||
### Built-in Server | ||
Birdwatch v3 comes equipped with it's own built-in server. You don't have to configure the server at all, it will launch just fine using the defaults, but in case you need more control, you can configure the server by: | ||
- [Turning it on or off](https://github.com/radiovisual/birdwatch#server) using the `server: <true|false>` option. | ||
- [Override the url to the Birdwatch cache](https://github.com/radiovisual/birdwatch#cacheDir) with the `cacheDir: <path>` option | ||
- [Specify the port](https://github.com/radiovisual/birdwatch#port) you want the server to run on with the `port: <portnumber>` option | ||
- [Optionally serve test data](https://github.com/radiovisual/birdwatch#testData) in a JSON format using the `testData: <json>` option | ||
**Tip:** If you have your own caching server, just turn the Birdwatch server off, and feed your server the Birdwatch cache file. | ||
## API | ||
@@ -67,10 +78,19 @@ | ||
Type: `object` | ||
Type: `object` | ||
Options set here will override the defaults in the constructor. | ||
##### logReports | ||
Type: `boolean` | ||
Default: `true` | ||
Pretty-print birdwatch activity to the console. | ||
# ![birdwatch](media/screenshot-v.3.0.0.png) | ||
##### refreshTime | ||
Type: `Number`<br> | ||
Default: `600` | ||
Type: `Number` | ||
Default: `600` | ||
@@ -80,15 +100,34 @@ The number of seconds to wait before the cache updates again. The default is 10 minutes (600 seconds) | ||
**Tip:** Update your cache frequently, but not frequently enough to hit any [Twitter API Rate Limits](https://dev.twitter.com/rest/public/rate-limits). | ||
##### logReports | ||
Type: `Boolean`<br> | ||
Default: `false` | ||
##### server | ||
Shows a pretty-printed update to the console. Useful for debugging and logging. | ||
Type: `boolean` | ||
Default: `true` | ||
# ![birdwatch](media/screenshot-v.1.0.0.png) | ||
Boolean to turn the server off or on. Turn the server off if you want to run your own server. Your own server can do whatever it wants with the cache file in `birdwatch/dist/cache/` | ||
##### port | ||
Type: `number` | ||
Default: `8417` | ||
Assign a port to the Birdwatch server. If you set a port of `0` the server will assign an open port for you, and you can get the port number with the `logReport: true` setting or using `birdwatch.options.port` | ||
##### url | ||
Type: `string` | ||
Default: `/birdwatch/tweets` | ||
The url you want to use to access the cached tweets. Requires the server to be running. | ||
##### cacheDir | ||
Type: `string` | ||
Default: `${__dirname}/cache/` | ||
Override the location of the cache file. Make sure you have appropriate read/write permissions on this directory. | ||
##### testData | ||
Type: `json`<br> | ||
Type: `json` | ||
@@ -99,3 +138,4 @@ Serve tweet data in JSON format to birdwatch. Useful for testing/debugging without making network requests. | ||
Type: `function`<br> | ||
Type: `function` | ||
Default: `tweet => { return new Date(tweet.created_at) * -1; }` | ||
@@ -110,4 +150,4 @@ Override the custom sorting function. Birdwatch defaults sorting to chronological order. | ||
*Required*<br> | ||
Type: `string` | ||
*Required* | ||
Type: `string` | ||
@@ -118,3 +158,3 @@ The screenname of the twitter account you want to watch. | ||
Type: `object` | ||
Type: `object` | ||
@@ -125,3 +165,3 @@ Feed options. | ||
Type: `Regex|Array`<br> | ||
Type: `Regex|Array` | ||
@@ -135,9 +175,15 @@ The regular expression containing the tags you want to filter with, or an array of strings. For example, all of these examples will result in the same filter: | ||
``` | ||
**Tip:** If you need help writing your regular expressions, try [regexpal.com](http://regexpal.com/) | ||
##### limit | ||
**Tip:** If you need help writing your regular expressions, try [regexpal.com](http://regexpal.com/) | ||
Type: `number` | ||
Default: `12` | ||
Set a limit on how many tweets you want to cache from the feed. If you are watching three feeds with a limit of 10, you will have a cache of 30 tweets. | ||
##### removeRetweets | ||
Type: `boolean`<br> | ||
Default: `false` | ||
Type: `boolean` | ||
Default: `false` | ||
@@ -150,18 +196,2 @@ Use this if you want to remove retweets from the feed you are watching. | ||
### birdwatch.getCachedTweets() | ||
Use this to access the birdwatch cache of tweets in the JSON format | ||
Returns: `Array` | ||
### Notes on Release 1.0 | ||
- Birdwatch is now in its `1.0` release, which means some subtle API changes have occurred: | ||
- `.start()` and `.getCachedTweets()` no longer return a Promise. | ||
- Custom sorting functions can now be passed to the Birdwatch instance. | ||
- Birdwatch saves the filtered and sorted tweets to the hard disk, so you can use the cache file anyway you want, **but Birdwatch only uses in-memory cache to serve data**. [Discussion here](https://github.com/radiovisual/birdwatch/issues/9). | ||
- Internally, the entire codebase has adopted the ES6 syntax (transpiles with Babel). | ||
- The unit testing framework has migrated from Mocha to AVA. | ||
- Simplified install process. | ||
### License | ||
@@ -168,0 +198,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
454
190
25252
12
8
+ Addedclear@0.0.1
+ Addedexpress@^4.13.4
+ Addedget-port@^2.1.0
+ Addedaccepts@1.3.8(transitive)
+ Addedarray-flatten@1.1.1(transitive)
+ Addedbody-parser@1.20.3(transitive)
+ Addedbytes@3.1.2(transitive)
+ Addedcall-bind@1.0.7(transitive)
+ Addedclear@0.0.1(transitive)
+ Addedcontent-disposition@0.5.4(transitive)
+ Addedcontent-type@1.0.5(transitive)
+ Addedcookie@0.7.1(transitive)
+ Addedcookie-signature@1.0.6(transitive)
+ Addeddebug@2.6.9(transitive)
+ Addeddefine-data-property@1.1.4(transitive)
+ Addeddepd@2.0.0(transitive)
+ Addeddestroy@1.2.0(transitive)
+ Addedee-first@1.1.1(transitive)
+ Addedencodeurl@1.0.22.0.0(transitive)
+ Addedes-define-property@1.0.0(transitive)
+ Addedes-errors@1.3.0(transitive)
+ Addedescape-html@1.0.3(transitive)
+ Addedetag@1.8.1(transitive)
+ Addedexpress@4.21.1(transitive)
+ Addedfinalhandler@1.3.1(transitive)
+ Addedforwarded@0.2.0(transitive)
+ Addedfresh@0.5.2(transitive)
+ Addedget-intrinsic@1.2.4(transitive)
+ Addedget-port@2.1.0(transitive)
+ Addedgopd@1.0.1(transitive)
+ Addedhas-property-descriptors@1.0.2(transitive)
+ Addedhas-proto@1.0.3(transitive)
+ Addedhas-symbols@1.0.3(transitive)
+ Addedhttp-errors@2.0.0(transitive)
+ Addediconv-lite@0.4.24(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedipaddr.js@1.9.1(transitive)
+ Addedmedia-typer@0.3.0(transitive)
+ Addedmerge-descriptors@1.0.3(transitive)
+ Addedmethods@1.1.2(transitive)
+ Addedmime@1.6.0(transitive)
+ Addedmime-db@1.52.0(transitive)
+ Addedmime-types@2.1.35(transitive)
+ Addedms@2.0.02.1.3(transitive)
+ Addednegotiator@0.6.3(transitive)
+ Addedobject-inspect@1.13.3(transitive)
+ Addedon-finished@2.4.1(transitive)
+ Addedparseurl@1.3.3(transitive)
+ Addedpath-to-regexp@0.1.10(transitive)
+ Addedproxy-addr@2.0.7(transitive)
+ Addedqs@6.13.0(transitive)
+ Addedrange-parser@1.2.1(transitive)
+ Addedraw-body@2.5.2(transitive)
+ Addedsafe-buffer@5.2.1(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedsend@0.19.0(transitive)
+ Addedserve-static@1.16.2(transitive)
+ Addedset-function-length@1.2.2(transitive)
+ Addedsetprototypeof@1.2.0(transitive)
+ Addedside-channel@1.0.6(transitive)
+ Addedstatuses@2.0.1(transitive)
+ Addedtoidentifier@1.0.1(transitive)
+ Addedtype-is@1.6.18(transitive)
+ Addedunpipe@1.0.0(transitive)
+ Addedutils-merge@1.0.1(transitive)
+ Addedvary@1.1.2(transitive)