├── .babelrc ├── .editorconfig ├── .eslintrc.json ├── .gitignore ├── .npmignore ├── .travis.yml ├── README.md ├── index.js ├── package.json └── test.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "es2015" 4 | ], 5 | "plugins": [ 6 | "add-module-exports" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | charset = utf-8 6 | trim_trailing_whitespace = true 7 | insert_final_newline = true 8 | 9 | [{package.json,*.js,*.yml}] 10 | indent_style = space 11 | indent_size = 2 12 | 13 | [*.md] 14 | trim_trailing_whitespace = false 15 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "airbnb/base", 3 | "plugins": [ 4 | "require-path-exists" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | coverage 4 | npm-debug.log 5 | index.es5.js 6 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | coverage 4 | npm-debug.log 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - v5 4 | - v4 5 | - '0.12' 6 | - '0.10' 7 | after_script: 8 | - 'npm run coveralls' 9 | - 'npm run coveralls' 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # get-tweets 2 | 3 | [![NPM version][npm-image]][npm-url] 4 | [![Build Status][travis-image]][travis-url] 5 | [![Coveralls Status][coveralls-image]][coveralls-url] 6 | [![Dependency Status][depstat-image]][depstat-url] 7 | 8 | > Get latest tweets 9 | 10 | ## Install 11 | 12 | npm install --save get-tweets 13 | 14 | ## Usage 15 | 16 | ```js 17 | import getTweets from 'get-tweets'; 18 | import tokens from 'twitter-tokens'; 19 | 20 | getTweets(tokens, 'largescalejs_ru', '424119506508980224').then(tweets => { 21 | console.log(tweets); 22 | }); 23 | ``` 24 | 25 | ## API 26 | 27 | ### getTweets(tokens, username, sinceId) 28 | 29 | Return a promise that resolves to tweets. 30 | 31 | #### tokens 32 | 33 | *Required* 34 | Type: `Object` 35 | 36 | Valid [Twitter developer credentials (tokens)][how-to-get] 37 | in the form of a set of consumer and access tokens/keys. 38 | You can use [twitter-tokens][tokens], to simplify getting tokens. 39 | 40 | [how-to-get]: https://iamstarkov.com/get-twitter-tokens/ 41 | [tokens]: https://www.npmjs.com/package/twitter-tokens 42 | 43 | #### username 44 | 45 | *Required* 46 | Type: `String` 47 | 48 | Twitter username. 49 | 50 | #### sinceId 51 | 52 | *Required* 53 | Type: `String` 54 | 55 | `id_str` of tweet since which you want to get latest tweets. Result array will not contain this tweet. If you want it to contain that tweet use _[bignum-dec][dec]_: `getMentions(tokens, bignumDec(tweet.id_str), cb);`. See [tests][tests] for details. 56 | 57 | > Return results with an ID greater than (that is, more recent than) the specified ID. There are limits to the number of Tweets which can be accessed through the API. If the limit of Tweets has occured since the `since_id`, the `since_id` will be forced to the oldest ID available. 58 | > — [Twitter API `statuses/user_timeline`][user_timeline] 59 | 60 | [tests]: https://github.com/iamstarkov/get-tweets/blob/master/test.js 61 | [dec]: https://github.com/iamstarkov/bignum-dec 62 | [user_timeline]: https://dev.twitter.com/rest/reference/get/statuses/user_timeline 63 | 64 | ## Related 65 | 66 | * [get-twitter-info][get-twitter-info] — get info about target username 67 | * [get-twitter-followers][get-twitter-followers] — get followers for target username 68 | * [tweet-links][tweet-links] — extract links from tweet 69 | * [tweets-stats][tweets-stats] — get statistics from array of tweets 70 | * [twitter-mentions][twitter-mentions] — get latest mentions for target username 71 | * [twitter-profile-media][twitter-profile-media] — get twitter profile image and banner 72 | * [twitter-tokens][twitter-tokens] — get twitter tokens 73 | 74 | ## License 75 | 76 | MIT © [Vladimir Starkov](https://iamstarkov.com/) 77 | 78 | [npm-url]: https://npmjs.org/package/get-tweets 79 | [npm-image]: https://img.shields.io/npm/v/get-tweets.svg?style=flat-square 80 | 81 | [travis-url]: https://travis-ci.org/iamstarkov/get-tweets 82 | [travis-image]: https://img.shields.io/travis/iamstarkov/get-tweets.svg?style=flat-square 83 | 84 | [coveralls-url]: https://coveralls.io/r/iamstarkov/get-tweets 85 | [coveralls-image]: https://img.shields.io/coveralls/iamstarkov/get-tweets.svg?style=flat-square 86 | 87 | [depstat-url]: https://david-dm.org/iamstarkov/get-tweets 88 | [depstat-image]: https://img.shields.io/david/iamstarkov/get-tweets.svg?style=flat-square 89 | 90 | [get-twitter-info]: https://github.com/iamstarkov/get-twitter-info 91 | [get-twitter-followers]: https://github.com/iamstarkov/get-twitter-followers 92 | [tweet-links]: https://github.com/iamstarkov/tweet-links 93 | [tweets-stats]: https://github.com/iamstarkov/tweets-stats 94 | [twitter-mentions]: https://github.com/iamstarkov/twitter-mentions 95 | [twitter-profile-media]: https://github.com/andrepolischuk/twitter-profile-media 96 | [twitter-tokens]: https://github.com/iamstarkov/twitter-tokens 97 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import Twitter from 'twit'; 2 | import dec from 'bignum-dec'; 3 | import { merge, pipe, prop, last, concat, isEmpty } from 'ramda'; 4 | 5 | const defaults = { 6 | count: 200, 7 | trim_user: true, 8 | include_rts: true, 9 | exclude_replies: false, 10 | }; 11 | 12 | function getNextOptions(options, tweets) { 13 | return (isEmpty(tweets)) 14 | ? options 15 | : merge(options, { max_id: pipe(last, prop('id_str'), dec)(tweets) }); 16 | } 17 | 18 | function accumulate(client, options, tweets) { 19 | const nextOptions = getNextOptions(options, tweets); 20 | return client.get('statuses/user_timeline', nextOptions).then(({ data }) => { 21 | const accumulatedTweets = concat(tweets, data); 22 | return (isEmpty(data)) 23 | ? accumulatedTweets 24 | : accumulate(client, nextOptions, accumulatedTweets); 25 | }); 26 | } 27 | 28 | export default function getTweets(tokens, username, sinceId) { 29 | const client = new Twitter(tokens); 30 | const options = merge(defaults, { screen_name: username, since_id: sinceId }); 31 | return accumulate(client, options, []); 32 | } 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "get-tweets", 3 | "version": "4.0.0", 4 | "description": "Get latest tweets", 5 | "main": "index.es5.js", 6 | "scripts": { 7 | "coverage": "isparta cover _mocha index.js -- --timeout 1000000 --require babel-core/register", 8 | "precoveralls": "npm run coverage", 9 | "coveralls": "coveralls < coverage/lcov.info", 10 | "test": "mocha --timeout 1000000 --require babel-core/register", 11 | "tdd": "npm test -- --watch", 12 | "transpile": "babel index.js > index.es5.js", 13 | "prepublish": "npm run transpile", 14 | "postpublish": "rm index.es5.js && git push --follow-tags" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/iamstarkov/get-tweets.git" 19 | }, 20 | "keywords": [ 21 | "twitter", 22 | "data", 23 | "automatisation", 24 | "automation" 25 | ], 26 | "author": "Vladimir Starkov (http://iamstarkov.com/)", 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/iamstarkov/get-tweets/issues" 30 | }, 31 | "homepage": "https://github.com/iamstarkov/get-tweets#readme", 32 | "dependencies": { 33 | "bignum-dec": "^1.0.0", 34 | "ramda": "^0.19.1", 35 | "twit": "^2.2.2" 36 | }, 37 | "devDependencies": { 38 | "babel-cli": "^6.4.5", 39 | "babel-core": "^6.4.5", 40 | "babel-plugin-add-module-exports": "^0.1.2", 41 | "babel-preset-es2015": "^6.3.13", 42 | "bignum-dec": "^1.0.1", 43 | "coveralls": "*", 44 | "eslint": "^1.10.3", 45 | "eslint-config-airbnb": "^5.0.0", 46 | "eslint-plugin-require-path-exists": "^1.1.5", 47 | "isparta": "*", 48 | "mocha": "*", 49 | "twitter-tokens": "*" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 3 | import { equal } from 'assert'; 4 | import { last } from 'ramda'; 5 | import getTweets from './index'; 6 | import tokens from 'twitter-tokens'; 7 | import dec from 'bignum-dec'; 8 | 9 | it('getTweets', done => { 10 | getTweets(tokens, 'largescalejs_ru', '424119506508980224').then(res => { 11 | equal(res.length, 36); 12 | done(); 13 | }); 14 | }); 15 | 16 | it('getTweets including since_id', done => { 17 | getTweets(tokens, 'largescalejs_ru', dec('424119506508980224')).then(res => { 18 | equal(res.length, 37); 19 | equal(last(res).id_str, '424119506508980224'); 20 | done(); 21 | }); 22 | }); 23 | --------------------------------------------------------------------------------