Socket
Socket
Sign inDemoInstall

twitter-lite

Package Overview
Dependencies
9
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.9.2 to 0.9.3

4

CHANGELOG.md

@@ -0,1 +1,5 @@

# v0.9.3, 2019-Mar-25
- Return `_headers` in stream creation errors as well
# v0.9.1, 2019-Jan-16

@@ -2,0 +6,0 @@

36

package.json
{
"name": "twitter-lite",
"version": "0.9.2",
"version": "0.9.3",
"description": "A tiny, full-featured client / server library for the Twitter API",

@@ -14,2 +14,5 @@ "source": [

"author": "Peter Piekarczyk <peter@peterp.me>",
"contributors": [
"Dan Dascalescu (https://github.com/dandv)"
],
"license": "MIT",

@@ -23,9 +26,9 @@ "files": [

"twitter",
"rest",
"api",
"twitter api",
"node-twitter",
"twitter oauth",
"twitter rest",
"rest",
"api",
"streams",
"twitter api"
"twitter stream"
],

@@ -39,20 +42,19 @@ "dependencies": {

"dotenv": "^6.2.0",
"eslint": "^5.15.3",
"eslint-plugin-jest": "^22.4.1",
"flow-bin": "^0.68.0",
"husky": "^0.14.3",
"husky": "^1.3.1",
"jest": "^23.6.0",
"lint-staged": "^8.1.0",
"microbundle": "^0.4.3",
"prettier": "^1.15.3"
"microbundle": "^0.4.3"
},
"scripts": {
"lint": "eslint ./",
"prepare": "microbundle",
"test": "jest",
"release": "npm run -s prepare && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish",
"precommit": "lint-staged"
"test": "eslint . && jest --detectOpenHandles",
"release": "npm run -s prepare && npm test && git tag $npm_package_version && git push && git push --tags && npm publish"
},
"lint-staged": {
"*.{js,md}": [
"prettier --write",
"git add"
]
"husky": {
"hooks": {
"pre-commit": "eslint ."
}
},

@@ -59,0 +61,0 @@ "jest": {

@@ -7,2 +7,3 @@ # Twitter Lite

## Features

@@ -18,2 +19,3 @@

## Why

@@ -23,2 +25,3 @@

## Installation

@@ -34,2 +37,3 @@

## Usage

@@ -154,2 +158,3 @@

## Streams

@@ -184,4 +189,4 @@

To stop a stream, call `stream.destroy()`. That might take a while though, if the stream receives a lot of traffic. Also, if you attempt to destroy a stream from an `on` handler, you may get an error about writing to a destroyed stream.
To avoid both these issues, [defer](https://stackoverflow.com/questions/49804108/write-after-end-stream-error/53878933#53878933) the `destroy()` call:
To stop a stream, call `stream.destroy()`. That might take a while though, if the stream receives a lot of traffic. Also, if you attempt to destroy a stream from an `on` handler, you *may* get an error about writing to a destroyed stream.
In that case, try to [defer](https://stackoverflow.com/questions/49804108/write-after-end-stream-error/53878933#53878933) the `destroy()` call:

@@ -192,4 +197,5 @@ ```es6

After you've destroyed a stream, you can create another one - see the ["should switch from one stream to another" test](https://github.com/draftbit/twitter-lite/blob/9e0845585c756aee10e8b0acaabfbc3e4f32b81c/test/stream.test.js#L131).
After calling `stream.destroy()`, you can recreate the stream, if you wait long enough - see the "should reuse stream N times" test. Note that Twitter may return a "420 Enhance your calm" error if you switch streams too fast. There are no response headers specifying how long to wait, and [the error](https://stackoverflow.com/questions/13438965/avoid-420s-with-streaming-api), as well as [streaming limits](https://stackoverflow.com/questions/34962677/twitter-streaming-api-limits) in general, are poorly documented. Trial and error has shown that for tracked keywords, waiting 20 to 30 seconds between re-creating streams was enough.
## Methods

@@ -289,5 +295,6 @@

## Contributing
With the library nearing v1.0, contributions are welcome! Areas especially in need of help involve multimedia (see [#33](https://github.com/draftbit/twitter-lite/issues/33) for example), adding tests (see [these](https://github.com/ttezel/twit/tree/master/tests) for reference), and [getting v1.0 out the door](https://github.com/draftbit/twitter-lite/issues/21).
With the library nearing v1.0, contributions are welcome! Areas especially in need of help involve multimedia (see [#33](https://github.com/draftbit/twitter-lite/issues/33) for example), and adding tests (see [these](https://github.com/ttezel/twit/tree/master/tests) for reference).

@@ -308,8 +315,7 @@ ### Development

6. Add your contribution, along with test case(s). Note: feel free to skip the ["should DM user"](https://github.com/draftbit/twitter-lite/blob/34e8dbb3efb9a45564275f16473af59dbc4409e5/twitter.test.js#L167) test during development by changing that `it()` call to `it.skip()`, but remember to revert that change before committing. This will prevent your account from being flagged as [abusing the API to send too many DMs](https://github.com/draftbit/twitter-lite/commit/5ee2ce4232faa07453ea2f0b4d63ee7a6d119ce7).
7. Make sure all tests pass.
8. `git add` the changed files
9. `npm run precommit` to lint with [prettier](https://www.npmjs.com/package/prettier)
10. Commit using a [descriptive message](https://chris.beams.io/posts/git-commit/) (please squash commits into one per fix/improvement!)
11. `git push` and submit your PR!
7. Make sure all tests pass. **NOTE: tests will take over 10 minutes to finish.**
8. Commit using a [descriptive message](https://chris.beams.io/posts/git-commit/) (please squash commits into one per fix/improvement!)
9. `git push` and submit your PR!
## Credits

@@ -316,0 +322,0 @@

@@ -1,3 +0,3 @@

const EventEmitter = require("events");
const END = "\r\n";
const EventEmitter = require('events');
const END = '\r\n';
const END_LENGTH = 2;

@@ -8,7 +8,7 @@

super();
this.buffer = "";
this.buffer = '';
}
parse(buffer) {
this.buffer += buffer.toString("utf8");
this.buffer += buffer.toString('utf8');
let index;

@@ -23,9 +23,9 @@ let json;

json = JSON.parse(json);
this.emit(json.event || "data", json);
this.emit(json.event || 'data', json);
} catch (error) {
error.source = json;
this.emit("error", error);
this.emit('error', error);
}
} else {
this.emit("ping");
this.emit('ping');
}

@@ -32,0 +32,0 @@ }

@@ -1,8 +0,8 @@

const crypto = require("crypto");
const OAuth = require("oauth-1.0a");
const Fetch = require("cross-fetch");
const querystring = require("querystring");
const Stream = require("./stream");
const crypto = require('crypto');
const OAuth = require('oauth-1.0a');
const Fetch = require('cross-fetch');
const querystring = require('querystring');
const Stream = require('./stream');
const getUrl = (subdomain, endpoint = "1.1") =>
const getUrl = (subdomain, endpoint = '1.1') =>
`https://${subdomain}.twitter.com/${endpoint}`;

@@ -13,9 +13,9 @@

consumer: { key, secret },
signature_method: "HMAC-SHA1",
signature_method: 'HMAC-SHA1',
hash_function(baseString, key) {
return crypto
.createHmac("sha1", key)
.createHmac('sha1', key)
.update(baseString)
.digest("base64");
}
.digest('base64');
},
});

@@ -27,3 +27,3 @@

const defaults = {
subdomain: "api",
subdomain: 'api',
consumer_key: null,

@@ -33,3 +33,3 @@ consumer_secret: null,

access_token_secret: null,
bearer_token: null
bearer_token: null,
};

@@ -42,10 +42,10 @@

const JSON_ENDPOINTS = [
"direct_messages/events/new",
"direct_messages/welcome_messages/new",
"direct_messages/welcome_messages/rules/new"
'direct_messages/events/new',
'direct_messages/welcome_messages/new',
'direct_messages/welcome_messages/rules/new',
];
const baseHeaders = {
"Content-Type": "application/json",
Accept: "application/json"
'Content-Type': 'application/json',
Accept: 'application/json',
};

@@ -56,7 +56,7 @@

return string
.replace(/!/g, "%21")
.replace(/\*/g, "%2A")
.replace(/'/g, "%27")
.replace(/\(/g, "%28")
.replace(/\)/g, "%29");
.replace(/!/g, '%21')
.replace(/\*/g, '%2A')
.replace(/'/g, '%27')
.replace(/\(/g, '%28')
.replace(/\)/g, '%29');
}

@@ -67,6 +67,6 @@

const config = Object.assign({}, defaults, options);
this.authType = config.bearer_token ? "App" : "User";
this.authType = config.bearer_token ? 'App' : 'User';
this.client = createOauthClient({
key: config.consumer_key,
secret: config.consumer_secret
secret: config.consumer_secret,
});

@@ -76,7 +76,7 @@

key: config.access_token_key,
secret: config.access_token_secret
secret: config.access_token_secret,
};
this.url = getUrl(config.subdomain);
this.oauth = getUrl(config.subdomain, "oauth");
this.oauth = getUrl(config.subdomain, 'oauth');
this.config = config;

@@ -92,7 +92,7 @@ }

static _handleResponse(response) {
const headers = response.headers.raw(); // https://github.com/bitinn/node-fetch/issues/495
const headers = response.headers.raw(); // TODO: see #44
// Return empty response on 204 "No content"
if (response.status === 204)
return {
_headers: headers
_headers: headers,
};

@@ -109,13 +109,13 @@ // Otherwise, parse JSON response

Authorization:
"Basic " +
'Basic ' +
Buffer.from(
this.config.consumer_key + ":" + this.config.consumer_secret
).toString("base64"),
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
this.config.consumer_key + ':' + this.config.consumer_secret
).toString('base64'),
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
};
const results = await Fetch("https://api.twitter.com/oauth2/token", {
method: "POST",
body: "grant_type=client_credentials",
headers
const results = await Fetch('https://api.twitter.com/oauth2/token', {
method: 'POST',
body: 'grant_type=client_credentials',
headers,
}).then(Twitter._handleResponse);

@@ -129,3 +129,3 @@

url: `${this.oauth}/request_token`,
method: "POST"
method: 'POST',
};

@@ -135,3 +135,3 @@

if (twitterCallbackUrl) parameters = { oauth_callback: twitterCallbackUrl };
if (parameters) requestData.url += "?" + querystring.stringify(parameters);
if (parameters) requestData.url += '?' + querystring.stringify(parameters);

@@ -143,4 +143,4 @@ const headers = this.client.toHeader(

const results = await Fetch(requestData.url, {
method: "POST",
headers: Object.assign({}, baseHeaders, headers)
method: 'POST',
headers: Object.assign({}, baseHeaders, headers),
})

@@ -156,7 +156,7 @@ .then(res => res.text())

url: `${this.oauth}/access_token`,
method: "POST"
method: 'POST',
};
let parameters = { oauth_verifier: options.verifier };
if (parameters) requestData.url += "?" + querystring.stringify(parameters);
if (parameters) requestData.url += '?' + querystring.stringify(parameters);

@@ -166,3 +166,3 @@ const headers = this.client.toHeader(

key: options.key,
secret: options.secret
secret: options.secret,
})

@@ -172,4 +172,4 @@ );

const results = await Fetch(requestData.url, {
method: "POST",
headers: Object.assign({}, baseHeaders, headers)
method: 'POST',
headers: Object.assign({}, baseHeaders, headers),
})

@@ -184,3 +184,3 @@ .then(res => res.text())

* Construct the data and headers for an authenticated HTTP request to the Twitter API
* @param {string} method - "GET" or "POST"
* @param {string} method - 'GET' or 'POST'
* @param {string} resource - the API endpoint

@@ -194,10 +194,10 @@ * @param {object} parameters

url: `${this.url}/${resource}.json`,
method
method,
};
if (parameters)
if (method === "POST") requestData.data = parameters;
else requestData.url += "?" + querystring.stringify(parameters);
if (method === 'POST') requestData.data = parameters;
else requestData.url += '?' + querystring.stringify(parameters);
let headers = {};
if (this.authType === "User") {
if (this.authType === 'User') {
headers = this.client.toHeader(

@@ -208,3 +208,3 @@ this.client.authorize(requestData, this.token)

headers = {
Authorization: `Bearer ${this.config.bearer_token}`
Authorization: `Bearer ${this.config.bearer_token}`,
};

@@ -214,3 +214,3 @@ }

requestData,
headers
headers,
};

@@ -228,3 +228,3 @@ }

const { requestData, headers } = this._makeRequest(
"GET",
'GET',
resource,

@@ -237,3 +237,3 @@ parameters

.then(results =>
"errors" in results ? Promise.reject(results) : results
'errors' in results ? Promise.reject(results) : results
);

@@ -252,3 +252,3 @@ }

const { requestData, headers } = this._makeRequest(
"POST",
'POST',
resource,

@@ -263,13 +263,13 @@ JSON_ENDPOINTS.includes(resource) ? null : body // don't sign JSON bodies; only parameters

body = percentEncode(querystring.stringify(body));
postHeaders["Content-Type"] = "application/x-www-form-urlencoded";
postHeaders['Content-Type'] = 'application/x-www-form-urlencoded';
}
return Fetch(requestData.url, {
method: "POST",
method: 'POST',
headers: postHeaders,
body
body,
})
.then(Twitter._handleResponse)
.then(results =>
"errors" in results ? Promise.reject(results) : results
'errors' in results ? Promise.reject(results) : results
);

@@ -285,4 +285,4 @@ }

stream(resource, parameters) {
if (this.authType !== "User")
throw new Error("Streams require user context authentication");
if (this.authType !== 'User')
throw new Error('Streams require user context authentication');

@@ -294,4 +294,4 @@ const stream = new Stream();

const requestData = {
url: `${getUrl("stream")}/${resource}.json`,
method: "POST"
url: `${getUrl('stream')}/${resource}.json`,
method: 'POST',
};

@@ -305,8 +305,8 @@ if (parameters) requestData.data = parameters;

const request = Fetch(requestData.url, {
method: "POST",
method: 'POST',
headers: {
...headers,
"Content-Type": "application/x-www-form-urlencoded"
'Content-Type': 'application/x-www-form-urlencoded',
},
body: percentEncode(querystring.stringify(parameters))
body: percentEncode(querystring.stringify(parameters)),
});

@@ -318,12 +318,15 @@

response.status === 200
? stream.emit("start", response)
: stream.emit("error", Error(`Status Code: ${response.status}`));
if (response.ok) {
stream.emit('start', response);
} else {
response._headers = response.headers.raw(); // TODO: see #44 - could omit the line
stream.emit('error', response);
}
response.body
.on("data", chunk => stream.parse(chunk))
.on("error", error => stream.emit("error", error))
.on("end", () => stream.emit("end", response));
.on('data', chunk => stream.parse(chunk))
.on('error', error => stream.emit('error', error)) // no point in adding the original response headers
.on('end', () => stream.emit('end', response));
})
.catch(error => stream.emit("error", error));
.catch(error => stream.emit('error', error));

@@ -330,0 +333,0 @@ return stream;

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc