Skip to content

Commit 521c873

Browse files
committed
Revisions to JS samples (closes #8, #12, #14, #15, #16)
1 parent ebffe3c commit 521c873

File tree

13 files changed

+397
-255
lines changed

13 files changed

+397
-255
lines changed

Filtered-Stream/filtered_stream.js

+80-66
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,42 @@
1+
// Open a realtime stream of Tweets, filtered according to rules
2+
// https://developer.twitter.com/en/docs/twitter-api/tweets/filtered-stream/quick-start
3+
14
const needle = require('needle');
25

36
// The code below sets the bearer token from your environment variables
4-
// To set environment variables on Mac OS X, run the export command below from the terminal:
7+
// To set environment variables on macOS or Linux, run the export command below from the terminal:
58
// export BEARER_TOKEN='YOUR-TOKEN'
6-
const token = process.env.BEARER_TOKEN;
9+
const token = process.env.BEARER_TOKEN;
710

8-
const rulesURL = 'https://api.twitter.com/2/tweets/search/stream/rules'
11+
const rulesURL = 'https://api.twitter.com/2/tweets/search/stream/rules';
912
const streamURL = 'https://api.twitter.com/2/tweets/search/stream';
1013

11-
// Edit rules as desired here below
12-
const rules = [
13-
{ 'value': 'dog has:images -is:retweet', 'tag': 'dog pictures' },
14-
{ 'value': 'cat has:images -grumpy', 'tag': 'cat pictures' },
15-
];
14+
// this sets up two rules - the value is the search terms to match on, and the tag is an identifier that
15+
// will be applied to the Tweets return to show which rule they matched
16+
// with a standard project with Basic Access, you can add up to 25 concurrent rules to your stream, and
17+
// each rule can be up to 512 characters long
18+
19+
// Edit rules as desired below
20+
const rules = [{
21+
'value': 'dog has:images -is:retweet',
22+
'tag': 'dog pictures'
23+
},
24+
{
25+
'value': 'cat has:images -grumpy',
26+
'tag': 'cat pictures'
27+
},
28+
];
1629

1730
async function getAllRules() {
1831

19-
const response = await needle('get', rulesURL, { headers: {
20-
"authorization": `Bearer ${token}`
21-
}})
32+
const response = await needle('get', rulesURL, {
33+
headers: {
34+
"authorization": `Bearer ${token}`
35+
}
36+
})
2237

2338
if (response.statusCode !== 200) {
2439
throw new Error(response.body);
25-
return null;
2640
}
2741

2842
return (response.body);
@@ -32,7 +46,7 @@ async function deleteAllRules(rules) {
3246

3347
if (!Array.isArray(rules.data)) {
3448
return null;
35-
}
49+
}
3650

3751
const ids = rules.data.map(rule => rule.id);
3852

@@ -42,16 +56,17 @@ async function deleteAllRules(rules) {
4256
}
4357
}
4458

45-
const response = await needle('post', rulesURL, data, {headers: {
46-
"content-type": "application/json",
47-
"authorization": `Bearer ${token}`
48-
}})
59+
const response = await needle('post', rulesURL, data, {
60+
headers: {
61+
"content-type": "application/json",
62+
"authorization": `Bearer ${token}`
63+
}
64+
})
4965

5066
if (response.statusCode !== 200) {
5167
throw new Error(response.body);
52-
return null;
5368
}
54-
69+
5570
return (response.body);
5671

5772
}
@@ -60,85 +75,84 @@ async function setRules() {
6075

6176
const data = {
6277
"add": rules
63-
}
78+
}
6479

65-
const response = await needle('post', rulesURL, data, {headers: {
66-
"content-type": "application/json",
67-
"authorization": `Bearer ${token}`
68-
}})
80+
const response = await needle('post', rulesURL, data, {
81+
headers: {
82+
"content-type": "application/json",
83+
"authorization": `Bearer ${token}`
84+
}
85+
})
6986

7087
if (response.statusCode !== 201) {
7188
throw new Error(response.body);
72-
return null;
7389
}
74-
90+
7591
return (response.body);
7692

7793
}
7894

7995
function streamConnect() {
80-
//Listen to the stream
81-
const options = {
82-
timeout: 20000
83-
}
84-
96+
8597
const stream = needle.get(streamURL, {
86-
headers: {
87-
Authorization: `Bearer ${token}`
88-
}
89-
}, options);
98+
headers: {
99+
"User-Agent": "v2FilterStreamJS",
100+
"Authorization": `Bearer ${token}`
101+
},
102+
timeout: 20000
103+
});
90104

91105
stream.on('data', data => {
92-
try {
93-
const json = JSON.parse(data);
94-
console.log(json);
95-
} catch (e) {
96-
// Keep alive signal received. Do nothing.
97-
}
106+
try {
107+
const json = JSON.parse(data);
108+
console.log(json);
109+
} catch (e) {
110+
// Keep alive signal received. Do nothing.
111+
}
98112
}).on('error', error => {
99113
if (error.code === 'ETIMEDOUT') {
100114
stream.emit('timeout');
101115
}
102116
});
103117

104118
return stream;
105-
119+
106120
}
107121

108122

109123
(async () => {
110124
let currentRules;
111-
125+
112126
try {
113-
// Gets the complete list of rules currently applied to the stream
114-
currentRules = await getAllRules();
115-
116-
// Delete all rules. Comment the line below if you want to keep your existing rules.
117-
await deleteAllRules(currentRules);
118-
119-
// Add rules to the stream. Comment the line below if you don't want to add new rules.
120-
await setRules();
121-
127+
// Gets the complete list of rules currently applied to the stream
128+
currentRules = await getAllRules();
129+
130+
// Delete all rules. Comment the line below if you want to keep your existing rules.
131+
await deleteAllRules(currentRules);
132+
133+
// Add rules to the stream. Comment the line below if you don't want to add new rules.
134+
await setRules();
135+
122136
} catch (e) {
123-
console.error(e);
124-
process.exit(-1);
137+
console.error(e);
138+
process.exit(-1);
125139
}
126-
140+
127141
// Listen to the stream.
128142
// This reconnection logic will attempt to reconnect when a disconnection is detected.
129-
// To avoid rate limites, this logic implements exponential backoff, so the wait time
143+
// To avoid rate limits, this logic implements exponential backoff, so the wait time
130144
// will increase if the client cannot reconnect to the stream.
131-
132-
const filteredStream = streamConnect()
145+
146+
const filteredStream = streamConnect();
133147
let timeout = 0;
134148
filteredStream.on('timeout', () => {
135-
// Reconnect on error
136-
console.warn('A connection error occurred. Reconnecting…');
137-
setTimeout(() => {
138-
timeout++;
139-
streamConnect(token);
140-
}, 2 ** timeout);
141-
streamConnect(token);
149+
// Reconnect on error
150+
console.warn('A connection error occurred. Reconnecting…');
151+
setTimeout(() => {
152+
timeout++;
153+
streamConnect();
154+
}, 2 ** timeout);
155+
streamConnect();
142156
})
143157

144-
})();
158+
})();

Follows-Lookup/followers_lookup.js

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
// Fetch the followers of a user account, by ID
2+
// https://developer.twitter.com/en/docs/twitter-api/users/follows/quick-start
3+
14
const needle = require('needle');
25

6+
// this is the ID for @TwitterDev
37
const userId = 2244994945;
48
const url = `https://api.twitter.com/2/users/${userId}/followers`;
59
const bearerToken = process.env.BEARER_TOKEN;
@@ -13,6 +17,7 @@ const getFollowers = async () => {
1317

1418
const options = {
1519
headers: {
20+
"User-Agent": "v2FollowersJS",
1621
"authorization": `Bearer ${bearerToken}`
1722
}
1823
}
@@ -28,6 +33,8 @@ const getFollowers = async () => {
2833
}
2934
if (resp.meta.next_token) {
3035
nextToken = resp.meta.next_token;
36+
} else {
37+
hasNextPage = false;
3138
}
3239
} else {
3340
hasNextPage = false;
@@ -57,4 +64,4 @@ const getPage = async (params, options, nextToken) => {
5764
}
5865
}
5966

60-
getFollowers();
67+
getFollowers();

Follows-Lookup/following_lookup.js

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
// Fetch the users being followed by a specific account, by ID
2+
// https://developer.twitter.com/en/docs/twitter-api/users/follows/quick-start
3+
14
const needle = require('needle');
25

6+
// this is the ID for @TwitterDev
37
const userId = 2244994945;
48
const url = `https://api.twitter.com/2/users/${userId}/following`;
59
const bearerToken = process.env.BEARER_TOKEN;
@@ -13,6 +17,7 @@ const getFollowing = async () => {
1317

1418
const options = {
1519
headers: {
20+
"User-Agent": "v2FollowingJS",
1621
"Authorization": `Bearer ${bearerToken}`
1722
}
1823
}
@@ -28,6 +33,8 @@ const getFollowing = async () => {
2833
}
2934
if (resp.meta.next_token) {
3035
nextToken = resp.meta.next_token;
36+
} else {
37+
hasNextPage = false;
3138
}
3239
} else {
3340
hasNextPage = false;
@@ -57,4 +64,4 @@ const getPage = async (params, options, nextToken) => {
5764
}
5865
}
5966

60-
getFollowing();
67+
getFollowing();
+23-15
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,36 @@
1+
// Search for public Tweets across the whole Twitter archive
2+
// https://developer.twitter.com/en/docs/twitter-api/tweets/search/quick-start/full-archive-search
3+
14
const needle = require('needle');
25

36
// The code below sets the bearer token from your environment variables
4-
// To set environment variables on Mac OS X, run the export command below from the terminal:
5-
// export BEARER_TOKEN='YOUR-TOKEN'
6-
const token = process.env.BEARER_TOKEN;
7+
// To set environment variables on macOS or Linux, run the export command below from the terminal:
8+
// export BEARER_TOKEN='YOUR-TOKEN'
9+
const token = process.env.BEARER_TOKEN;
710

811
const endpointUrl = 'https://api.twitter.com/2/tweets/search/all'
912

1013
async function getRequest() {
1114

12-
// Edit query parameters below
15+
// These are the parameters for the API request
16+
// specify Tweet IDs to fetch, and any additional fields that are required
17+
// by default, only the Tweet ID and text are returned
1318
const params = {
14-
'query': 'from:twitterdev -is:retweet',
15-
'tweet.fields': 'author_id'
16-
}
19+
'query': 'from:twitterdev -is:retweet',
20+
'tweet.fields': 'author_id'
21+
}
1722

18-
const res = await needle('get', endpointUrl, params, { headers: {
19-
"authorization": `Bearer ${token}`
20-
}})
23+
const res = await needle('get', endpointUrl, params, {
24+
headers: {
25+
"User-Agent": "v2FullArchiveJS",
26+
"authorization": `Bearer ${token}`
27+
}
28+
})
2129

22-
if(res.body) {
30+
if (res.body) {
2331
return res.body;
2432
} else {
25-
throw new Error ('Unsuccessful request')
33+
throw new Error('Unsuccessful request');
2634
}
2735
}
2836

@@ -31,11 +39,11 @@ async function getRequest() {
3139
try {
3240
// Make request
3341
const response = await getRequest();
34-
console.log(response)
42+
console.log(response);
3543

36-
} catch(e) {
44+
} catch (e) {
3745
console.log(e);
3846
process.exit(-1);
3947
}
4048
process.exit();
41-
})();
49+
})();

0 commit comments

Comments
 (0)