@pipedream/twitter 0.3.2 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/actions/add-user-to-list/add-user-to-list.mjs +62 -0
- package/actions/advanced-search/advanced-search.mjs +113 -0
- package/actions/common.mjs +29 -0
- package/actions/create-tweet/create-tweet.mjs +146 -0
- package/actions/delete-tweet/delete-tweet.mjs +42 -0
- package/actions/follow-user/follow-user.mjs +48 -0
- package/actions/get-tweet/get-tweet.mjs +42 -0
- package/actions/get-user/get-user.mjs +50 -0
- package/actions/like-tweet/like-tweet.mjs +42 -0
- package/actions/list-favorites/list-favorites.mjs +63 -0
- package/actions/list-followers/list-followers.mjs +67 -0
- package/actions/list-lists/list-lists.mjs +69 -0
- package/actions/list-mentions/list-mentions.mjs +55 -0
- package/actions/list-pending-followers/list-pending-followers.mjs +32 -0
- package/actions/list-retweets/list-retweets.mjs +54 -0
- package/actions/list-user-tweets/list-user-tweets.mjs +80 -0
- package/actions/retweet/retweet.mjs +27 -0
- package/actions/simple-search/simple-search.mjs +62 -0
- package/actions/simple-search-in-list/simple-search-in-list.mjs +48 -0
- package/actions/unfollow-user/unfollow-user.mjs +48 -0
- package/actions/unlike-tweet/unlike-tweet.mjs +40 -0
- package/package.json +21 -21
- package/readme.md +0 -4
- package/sources/common/followed.mjs +37 -0
- package/sources/common/followers.mjs +158 -0
- package/sources/common/tweets.mjs +154 -0
- package/sources/{language-codes.js → language-codes.mjs} +6 -2
- package/sources/my-liked-tweets/my-liked-tweets.mjs +29 -0
- package/sources/my-tweets/my-tweets.mjs +48 -0
- package/sources/new-follower-of-me/new-follower-of-me.mjs +69 -0
- package/sources/new-follower-of-user/new-follower-of-user.mjs +25 -0
- package/sources/new-list-followed/new-list-followed.mjs +24 -0
- package/sources/new-trends-by-geo/new-trends-by-geo.mjs +39 -0
- package/sources/new-tweet-in-list/new-tweet-in-list.mjs +49 -0
- package/sources/new-unfollower-of-me/{new-unfollower-of-me.js → new-unfollower-of-me.mjs} +5 -4
- package/sources/new-unfollower-of-user/new-unfollower-of-user.mjs +25 -0
- package/sources/new-user-followed/new-user-followed.mjs +25 -0
- package/sources/search-mentions/search-mentions.mjs +143 -0
- package/sources/tweets-liked-by-user/tweets-liked-by-user.mjs +37 -0
- package/sources/user-tweets/user-tweets.mjs +49 -0
- package/sources/watch-retweets-of-me/watch-retweets-of-me.mjs +36 -0
- package/sources/watch-retweets-of-my-tweet/watch-retweets-of-my-tweet.mjs +44 -0
- package/sources/watch-retweets-of-user-tweet/watch-retweets-of-user-tweet.mjs +34 -0
- package/twitter.app.mjs +1149 -0
- package/sources/common-followers.js +0 -99
- package/sources/my-liked-tweets/my-liked-tweets.js +0 -26
- package/sources/my-tweets/my-tweets.js +0 -83
- package/sources/new-follower-of-me/new-follower-of-me.js +0 -68
- package/sources/new-follower-of-user/new-follower-of-user.js +0 -69
- package/sources/new-trends-by-geo/new-trends-by-geo.js +0 -29
- package/sources/new-unfollower-of-user/new-unfollower-of-user.js +0 -22
- package/sources/search-mentions/search-mentions.js +0 -76
- package/sources/tweets-liked-by-user/tweets-liked-by-user.js +0 -27
- package/sources/user-tweets/user-tweets.js +0 -66
- package/twitter.app.js +0 -461
package/twitter.app.js
DELETED
|
@@ -1,461 +0,0 @@
|
|
|
1
|
-
const axios = require('axios')
|
|
2
|
-
const querystring = require('querystring')
|
|
3
|
-
const moment = require('moment')
|
|
4
|
-
|
|
5
|
-
module.exports = {
|
|
6
|
-
type: "app",
|
|
7
|
-
app: "twitter",
|
|
8
|
-
propDefinitions: {
|
|
9
|
-
q: {
|
|
10
|
-
type: "string",
|
|
11
|
-
label: 'Search Term',
|
|
12
|
-
description: "Search for keywords `star wars`, screen names `@starwars`, or hashtags `#starwars`. You can also use Twitter's [standard search operators](https://developer.twitter.com/en/docs/tweets/rules-and-filtering/overview/standard-operators).",
|
|
13
|
-
},
|
|
14
|
-
keyword_filter: {
|
|
15
|
-
type: "string",
|
|
16
|
-
label: 'Keywords',
|
|
17
|
-
description: "Filter tweets based on keywords `star wars`, user mentions `@starwars`, or hashtags `#starwars`. You can also use Twitter's [standard search operators](https://developer.twitter.com/en/docs/tweets/rules-and-filtering/overview/standard-operators).",
|
|
18
|
-
optional: true,
|
|
19
|
-
},
|
|
20
|
-
result_type: {
|
|
21
|
-
type: "string",
|
|
22
|
-
label: "Result Type",
|
|
23
|
-
description: `Specifies the type of results you want to retrieve.`,
|
|
24
|
-
optional: true,
|
|
25
|
-
options: [
|
|
26
|
-
{ label: "Recent", value: "recent" },
|
|
27
|
-
{ label: "Popular", value: "popular" },
|
|
28
|
-
{ label: "Mixed", value: "mixed" },
|
|
29
|
-
],
|
|
30
|
-
default: 'recent',
|
|
31
|
-
},
|
|
32
|
-
count: {
|
|
33
|
-
type: "integer",
|
|
34
|
-
min: 1,
|
|
35
|
-
max: 100,
|
|
36
|
-
label: "Count (advanced)",
|
|
37
|
-
description: "The maximum number of tweets to return per API request (up to `100`)",
|
|
38
|
-
optional: true,
|
|
39
|
-
default: 100,
|
|
40
|
-
},
|
|
41
|
-
maxRequests: {
|
|
42
|
-
type: "integer",
|
|
43
|
-
min: 1,
|
|
44
|
-
max: 180,
|
|
45
|
-
label: "Max API Requests per Execution (advanced)",
|
|
46
|
-
description: "The maximum number of API requests to make per execution (e.g., multiple requests are required to retrieve paginated results). **Note:** Twitter [rate limits API requests](https://developer.twitter.com/en/docs/basics/rate-limiting) per 15 minute interval.",
|
|
47
|
-
optional: true,
|
|
48
|
-
default: 1,
|
|
49
|
-
},
|
|
50
|
-
from: {
|
|
51
|
-
type: "string",
|
|
52
|
-
label: "From",
|
|
53
|
-
description: "The screen name of the user (e.g., `pipedream`)",
|
|
54
|
-
},
|
|
55
|
-
geocode: {
|
|
56
|
-
type: "string",
|
|
57
|
-
label: "Geocode",
|
|
58
|
-
description: "Returns tweets by users located within a given radius of the given latitude/longitude. The location is preferentially taking from the Geotagging API, but will fall back to their Twitter profile. The parameter value is specified by `latitude,longitude,radius`, where radius units must be specified as either `mi` (miles) or `km` (kilometers). Note that you cannot use the near operator via the API to geocode arbitrary locations; however you can use this geocode parameter to search near geocodes directly.",
|
|
59
|
-
optional: true,
|
|
60
|
-
},
|
|
61
|
-
includeRetweets: {
|
|
62
|
-
type: "string",
|
|
63
|
-
label: "Retweets",
|
|
64
|
-
description: "Select whether to `include`, `exclude` or `only` include retweets in emitted events.",
|
|
65
|
-
optional: true,
|
|
66
|
-
options: [
|
|
67
|
-
{ label: "Include", value: "include" },
|
|
68
|
-
{ label: "Exclude", value: "exclude" },
|
|
69
|
-
{ label: "Only include retweets", value: "only" },
|
|
70
|
-
],
|
|
71
|
-
default: "include",
|
|
72
|
-
},
|
|
73
|
-
includeReplies: {
|
|
74
|
-
type: "string",
|
|
75
|
-
label: "Replies",
|
|
76
|
-
description: "Select whether to `include`, `exclude` or `only` include replies in emitted events.",
|
|
77
|
-
optional: true,
|
|
78
|
-
options: [
|
|
79
|
-
{ label: "Include", value: "include" },
|
|
80
|
-
{ label: "Exclude", value: "exclude" },
|
|
81
|
-
{ label: "Only include replies", value: "only" },
|
|
82
|
-
],
|
|
83
|
-
default: "include",
|
|
84
|
-
},
|
|
85
|
-
enrichTweets: {
|
|
86
|
-
type: "boolean",
|
|
87
|
-
label: "Enrich Tweets",
|
|
88
|
-
description: "Enrich each tweet with epoch (milliseconds) and ISO8601 conversions of Twitter's `created_at` timestamp.",
|
|
89
|
-
optional: true,
|
|
90
|
-
default: true,
|
|
91
|
-
},
|
|
92
|
-
locale: {
|
|
93
|
-
type: "string",
|
|
94
|
-
label: "Locale",
|
|
95
|
-
description: "Specify the language of the query you are sending (only `ja` is currently effective). This is intended for language-specific consumers and the default should work in the majority of cases.",
|
|
96
|
-
optional: true,
|
|
97
|
-
},
|
|
98
|
-
lang: {
|
|
99
|
-
type: "string",
|
|
100
|
-
label: "Language",
|
|
101
|
-
description: "Restricts tweets to the given language. Language detection is best-effort.",
|
|
102
|
-
optional: true,
|
|
103
|
-
async options(context) {
|
|
104
|
-
const { page } = context;
|
|
105
|
-
if (page !== 0) {
|
|
106
|
-
return {
|
|
107
|
-
options: [],
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const isoLanguages = require('./sources/language-codes');
|
|
112
|
-
return isoLanguages.map(isoLanguage => {
|
|
113
|
-
const {
|
|
114
|
-
English: language,
|
|
115
|
-
alpha2: code,
|
|
116
|
-
} = isoLanguage;
|
|
117
|
-
return {
|
|
118
|
-
label: `${language} (${code})`,
|
|
119
|
-
value: code,
|
|
120
|
-
};
|
|
121
|
-
})
|
|
122
|
-
}
|
|
123
|
-
},
|
|
124
|
-
screen_name: {
|
|
125
|
-
type: "string",
|
|
126
|
-
label: "Screen Name",
|
|
127
|
-
description: "The screen name of the user (e.g., `pipedream`)"
|
|
128
|
-
},
|
|
129
|
-
trendLocation: {
|
|
130
|
-
type: "string",
|
|
131
|
-
label: "Location",
|
|
132
|
-
async options(opts) {
|
|
133
|
-
const trendLocations = await this.getTrendLocations()
|
|
134
|
-
return trendLocations.map(location => {
|
|
135
|
-
return { label: `${location.name}, ${location.countryCode} (${location.placeType.name})`, value: location.woeid }
|
|
136
|
-
})
|
|
137
|
-
},
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
methods: {
|
|
141
|
-
async _getAuthorizationHeader({ data, method, url }) {
|
|
142
|
-
const requestData = {
|
|
143
|
-
data,
|
|
144
|
-
method,
|
|
145
|
-
url,
|
|
146
|
-
}
|
|
147
|
-
const token = {
|
|
148
|
-
key: this.$auth.oauth_access_token,
|
|
149
|
-
secret: this.$auth.oauth_refresh_token,
|
|
150
|
-
}
|
|
151
|
-
return (await axios({
|
|
152
|
-
method: 'POST',
|
|
153
|
-
url: this.$auth.oauth_signer_uri,
|
|
154
|
-
data: {
|
|
155
|
-
requestData,
|
|
156
|
-
token,
|
|
157
|
-
}
|
|
158
|
-
})).data
|
|
159
|
-
},
|
|
160
|
-
async _makeRequest(config, attempt = 0) {
|
|
161
|
-
if (!config.headers) config.headers = {}
|
|
162
|
-
if (config.params) {
|
|
163
|
-
const query = querystring.stringify(config.params)
|
|
164
|
-
delete config.params
|
|
165
|
-
const sep = config.url.indexOf('?') === -1 ? '?' : '&'
|
|
166
|
-
config.url += `${sep}${query}`
|
|
167
|
-
config.url = config.url.replace('?&','?')
|
|
168
|
-
}
|
|
169
|
-
let authorization, count = 0
|
|
170
|
-
const maxTries = 3
|
|
171
|
-
while(true) {
|
|
172
|
-
try {
|
|
173
|
-
authorization = await this._getAuthorizationHeader(config)
|
|
174
|
-
break
|
|
175
|
-
} catch (err) {
|
|
176
|
-
// handle exception
|
|
177
|
-
if (++count == maxTries) {
|
|
178
|
-
throw err
|
|
179
|
-
}
|
|
180
|
-
const milliseconds = 1000 * count
|
|
181
|
-
await new Promise(resolve => setTimeout(resolve, milliseconds))
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
config.headers.authorization = authorization
|
|
185
|
-
return axios(config)
|
|
186
|
-
},
|
|
187
|
-
async getFollowers(screen_name) {
|
|
188
|
-
return (await this._makeRequest({
|
|
189
|
-
url: `https://api.twitter.com/1.1/followers/ids.json?`,
|
|
190
|
-
params: {
|
|
191
|
-
screen_name,
|
|
192
|
-
stringify_ids: true,
|
|
193
|
-
}
|
|
194
|
-
})).data.ids
|
|
195
|
-
},
|
|
196
|
-
async *getAllFollowers(screenName) {
|
|
197
|
-
const url = `https://api.twitter.com/1.1/followers/ids.json?`;
|
|
198
|
-
const baseParams = {
|
|
199
|
-
screen_name: screenName,
|
|
200
|
-
stringify_ids: true,
|
|
201
|
-
};
|
|
202
|
-
const config = {
|
|
203
|
-
url,
|
|
204
|
-
params: baseParams,
|
|
205
|
-
};
|
|
206
|
-
const { data } = await this._makeRequest(config);
|
|
207
|
-
let {
|
|
208
|
-
ids,
|
|
209
|
-
next_cursor: nextCursor,
|
|
210
|
-
previous_cursor: prevCursor,
|
|
211
|
-
} = data;
|
|
212
|
-
while (nextCursor !== 0 || prevCursor === 0) {
|
|
213
|
-
for (const id of ids) {
|
|
214
|
-
yield id;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
if (nextCursor === 0) {
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
const params = {
|
|
222
|
-
...baseParams,
|
|
223
|
-
cursor: nextCursor,
|
|
224
|
-
};
|
|
225
|
-
const config = {
|
|
226
|
-
url,
|
|
227
|
-
params,
|
|
228
|
-
};
|
|
229
|
-
const { data } = await this._makeRequest(config);
|
|
230
|
-
({
|
|
231
|
-
ids,
|
|
232
|
-
next_cursor: nextCursor,
|
|
233
|
-
previous_cursor: prevCursor,
|
|
234
|
-
} = data);
|
|
235
|
-
}
|
|
236
|
-
},
|
|
237
|
-
async getLikedTweets(opts = {}) {
|
|
238
|
-
const {
|
|
239
|
-
screen_name,
|
|
240
|
-
count = 200,
|
|
241
|
-
tweet_mode = 'extended',
|
|
242
|
-
} = opts
|
|
243
|
-
return (await this._makeRequest({
|
|
244
|
-
url: `https://api.twitter.com/1.1/favorites/list.json`,
|
|
245
|
-
params: {
|
|
246
|
-
screen_name,
|
|
247
|
-
count,
|
|
248
|
-
tweet_mode,
|
|
249
|
-
}
|
|
250
|
-
})).data
|
|
251
|
-
},
|
|
252
|
-
async lookupUsers(userIdArray) {
|
|
253
|
-
return (await this._makeRequest({
|
|
254
|
-
url: `https://api.twitter.com/1.1/users/lookup.json`,
|
|
255
|
-
params: {
|
|
256
|
-
user_id: userIdArray.join(),
|
|
257
|
-
}
|
|
258
|
-
})).data
|
|
259
|
-
},
|
|
260
|
-
async search(opts = {}) {
|
|
261
|
-
const { q, since_id, tweet_mode, count, result_type, lang, locale, geocode, max_id } = opts
|
|
262
|
-
return (await this._makeRequest({
|
|
263
|
-
url: `https://api.twitter.com/1.1/search/tweets.json`,
|
|
264
|
-
params: {
|
|
265
|
-
q,
|
|
266
|
-
since_id,
|
|
267
|
-
max_id,
|
|
268
|
-
tweet_mode,
|
|
269
|
-
count,
|
|
270
|
-
result_type,
|
|
271
|
-
lang,
|
|
272
|
-
locale,
|
|
273
|
-
geocode,
|
|
274
|
-
}
|
|
275
|
-
}))
|
|
276
|
-
},
|
|
277
|
-
async getTrendLocations() {
|
|
278
|
-
return (await this._makeRequest({
|
|
279
|
-
url: `https://api.twitter.com/1.1/trends/available.json`,
|
|
280
|
-
})).data
|
|
281
|
-
},
|
|
282
|
-
async getTrends(opts = {}) {
|
|
283
|
-
const {
|
|
284
|
-
id = 1,
|
|
285
|
-
} = opts
|
|
286
|
-
return (await this._makeRequest({
|
|
287
|
-
url: `https://api.twitter.com/1.1/trends/place.json`,
|
|
288
|
-
params: {
|
|
289
|
-
id,
|
|
290
|
-
}
|
|
291
|
-
})).data
|
|
292
|
-
},
|
|
293
|
-
async getUserTimeline(opts = {}) {
|
|
294
|
-
const {
|
|
295
|
-
screen_name,
|
|
296
|
-
count = 100,
|
|
297
|
-
exclude_replies,
|
|
298
|
-
include_rts,
|
|
299
|
-
since_id,
|
|
300
|
-
} = opts
|
|
301
|
-
|
|
302
|
-
const params = {
|
|
303
|
-
screen_name,
|
|
304
|
-
count,
|
|
305
|
-
exclude_replies,
|
|
306
|
-
include_rts,
|
|
307
|
-
tweet_mode: 'extended',
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
if(since_id) {
|
|
311
|
-
params.since_id = since_id
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
return (await this._makeRequest({
|
|
315
|
-
url: `https://api.twitter.com/1.1/statuses/user_timeline.json`,
|
|
316
|
-
method: 'get',
|
|
317
|
-
params,
|
|
318
|
-
})).data
|
|
319
|
-
},
|
|
320
|
-
async searchHelper(opts = {}) {
|
|
321
|
-
const tweets = []
|
|
322
|
-
|
|
323
|
-
const {
|
|
324
|
-
tweet_mode = 'extended',
|
|
325
|
-
result_type,
|
|
326
|
-
count = 100,
|
|
327
|
-
lang,
|
|
328
|
-
locale,
|
|
329
|
-
geocode,
|
|
330
|
-
enrichTweets = true,
|
|
331
|
-
includeReplies = true,
|
|
332
|
-
includeRetweets = true,
|
|
333
|
-
} = opts
|
|
334
|
-
|
|
335
|
-
let { q, max_id, since_id } = opts
|
|
336
|
-
let min_id
|
|
337
|
-
|
|
338
|
-
if(includeReplies === 'exclude') {
|
|
339
|
-
q = `${q} -filter:replies`
|
|
340
|
-
} else if(includeReplies === 'only') {
|
|
341
|
-
q = `${q} filter:replies`
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
if(includeRetweets === 'exclude') {
|
|
345
|
-
q = `${q} -filter:nativeretweets`
|
|
346
|
-
} else if(includeRetweets === 'only') {
|
|
347
|
-
q = `${q} filter:nativeretweets`
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
const response = await this.search({ q, since_id, tweet_mode, count, result_type, lang, locale, geocode, max_id })
|
|
351
|
-
|
|
352
|
-
if(!response) {
|
|
353
|
-
console.log(`Last request was not successful.`)
|
|
354
|
-
return {
|
|
355
|
-
statusCode: "Error",
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
for (let tweet of response.data.statuses) {
|
|
360
|
-
if ((!since_id || (since_id && tweet.id_str !== since_id)) && (!max_id || (max_id && tweet.id_str !== max_id))) {
|
|
361
|
-
if (enrichTweets) {
|
|
362
|
-
tweet.created_at_timestamp = moment(tweet.created_at, 'ddd MMM DD HH:mm:ss Z YYYY').valueOf()
|
|
363
|
-
tweet.created_at_iso8601 = moment(tweet.created_at, 'ddd MMM DD HH:mm:ss Z YYYY').toISOString()
|
|
364
|
-
}
|
|
365
|
-
tweets.push(tweet)
|
|
366
|
-
if (!max_id || tweet.id_str > max_id) {
|
|
367
|
-
max_id = tweet.id_str
|
|
368
|
-
if(!min_id) {
|
|
369
|
-
min_id = max_id
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
if (tweet.id_str < max_id) {
|
|
373
|
-
min_id = tweet.id_str
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
return {
|
|
379
|
-
tweets,
|
|
380
|
-
max_id,
|
|
381
|
-
min_id,
|
|
382
|
-
count,
|
|
383
|
-
resultCount: response.data.statuses.length,
|
|
384
|
-
statusCode: response.status,
|
|
385
|
-
}
|
|
386
|
-
},
|
|
387
|
-
async paginatedSearch(opts = {}) {
|
|
388
|
-
const {
|
|
389
|
-
count = 100,
|
|
390
|
-
q,
|
|
391
|
-
since_id,
|
|
392
|
-
lang,
|
|
393
|
-
locale,
|
|
394
|
-
geocode,
|
|
395
|
-
result_type,
|
|
396
|
-
enrichTweets,
|
|
397
|
-
includeReplies,
|
|
398
|
-
includeRetweets,
|
|
399
|
-
limitFirstPage = true,
|
|
400
|
-
} = opts
|
|
401
|
-
|
|
402
|
-
let { max_id, maxRequests = 1 } = opts, totalRequests = 0
|
|
403
|
-
|
|
404
|
-
const tweets = []
|
|
405
|
-
|
|
406
|
-
if (limitFirstPage) {
|
|
407
|
-
maxRequests = 1
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
//console.log(maxPages)
|
|
411
|
-
|
|
412
|
-
for (let request = 0; request < maxRequests; request++) {
|
|
413
|
-
const response = await this.searchHelper({
|
|
414
|
-
count,
|
|
415
|
-
q,
|
|
416
|
-
since_id,
|
|
417
|
-
max_id,
|
|
418
|
-
lang,
|
|
419
|
-
locale,
|
|
420
|
-
geocode,
|
|
421
|
-
result_type,
|
|
422
|
-
enrichTweets,
|
|
423
|
-
includeReplies,
|
|
424
|
-
includeRetweets,
|
|
425
|
-
})
|
|
426
|
-
|
|
427
|
-
// increment the count of requests to report out after all requests are complete
|
|
428
|
-
totalRequests++
|
|
429
|
-
|
|
430
|
-
if (!response) {
|
|
431
|
-
break
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
tweets.push(...response.tweets)
|
|
435
|
-
|
|
436
|
-
//console.log(`resultCount: ${response.resultCount} count: ${response.count}`)
|
|
437
|
-
|
|
438
|
-
if (since_id && totalRequests === maxRequests && response.resultCount === response.count) {
|
|
439
|
-
console.log(`The last API request returned the maximum number of results. There may be additional tweets matching your search criteria. To return more tweets, increase the maximum number of API requests per execution.`)
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
if (response.length === 0 || response.resultCount < response.count) {
|
|
443
|
-
break
|
|
444
|
-
}
|
|
445
|
-
max_id = response.min_id
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
console.log(`Made ${totalRequests} requests to the Twitter API and returned ${tweets.length} tweets.`)
|
|
449
|
-
|
|
450
|
-
return tweets
|
|
451
|
-
},
|
|
452
|
-
async verifyCredentials() {
|
|
453
|
-
return (await this._makeRequest({
|
|
454
|
-
url: `https://api.twitter.com/1.1/account/verify_credentials.json`,
|
|
455
|
-
})).data
|
|
456
|
-
},
|
|
457
|
-
webhooks: {
|
|
458
|
-
// TODO
|
|
459
|
-
},
|
|
460
|
-
},
|
|
461
|
-
}
|