x-twitter-scraper 0.10.5 → 0.10.6
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/README.md +49 -17
- data/lib/x_twitter_scraper/client.rb +0 -13
- data/lib/x_twitter_scraper/file_part.rb +0 -3
- data/lib/x_twitter_scraper/internal/transport/base_client.rb +3 -211
- data/lib/x_twitter_scraper/internal/transport/pooled_net_requester.rb +2 -56
- data/lib/x_twitter_scraper/internal/type/array_of.rb +1 -77
- data/lib/x_twitter_scraper/internal/type/base_model.rb +3 -133
- data/lib/x_twitter_scraper/internal/type/base_page.rb +0 -13
- data/lib/x_twitter_scraper/internal/type/boolean.rb +0 -38
- data/lib/x_twitter_scraper/internal/type/converter.rb +0 -136
- data/lib/x_twitter_scraper/internal/type/enum.rb +1 -80
- data/lib/x_twitter_scraper/internal/type/file_input.rb +0 -39
- data/lib/x_twitter_scraper/internal/type/hash_of.rb +1 -77
- data/lib/x_twitter_scraper/internal/type/request_parameters.rb +0 -13
- data/lib/x_twitter_scraper/internal/type/union.rb +0 -101
- data/lib/x_twitter_scraper/internal/type/unknown.rb +0 -40
- data/lib/x_twitter_scraper/internal/util.rb +2 -307
- data/lib/x_twitter_scraper/models/account_retrieve_response.rb +0 -3
- data/lib/x_twitter_scraper/models/compose_create_params.rb +0 -4
- data/lib/x_twitter_scraper/models/compose_create_response.rb +0 -4
- data/lib/x_twitter_scraper/models/credit_retrieve_balance_response.rb +0 -3
- data/lib/x_twitter_scraper/models/credit_topup_balance_response.rb +0 -3
- data/lib/x_twitter_scraper/models/draft_list_params.rb +0 -3
- data/lib/x_twitter_scraper/models/draw_export_params.rb +0 -3
- data/lib/x_twitter_scraper/models/draw_list_params.rb +0 -3
- data/lib/x_twitter_scraper/models/draw_run_response.rb +0 -3
- data/lib/x_twitter_scraper/models/embedded_tweet.rb +0 -3
- data/lib/x_twitter_scraper/models/event.rb +0 -3
- data/lib/x_twitter_scraper/models/event_list_params.rb +0 -3
- data/lib/x_twitter_scraper/models/extraction_estimate_cost_params.rb +0 -3
- data/lib/x_twitter_scraper/models/extraction_list_params.rb +0 -3
- data/lib/x_twitter_scraper/models/extraction_run_params.rb +0 -3
- data/lib/x_twitter_scraper/models/guest_wallet_create_response.rb +0 -3
- data/lib/x_twitter_scraper/models/guest_wallet_retrieve_status_response.rb +0 -3
- data/lib/x_twitter_scraper/models/guest_wallet_topup_response.rb +0 -3
- data/lib/x_twitter_scraper/models/radar_item.rb +0 -3
- data/lib/x_twitter_scraper/models/radar_retrieve_trending_topics_params.rb +0 -3
- data/lib/x_twitter_scraper/models/search_tweet.rb +0 -3
- data/lib/x_twitter_scraper/models/trend_list_params.rb +0 -3
- data/lib/x_twitter_scraper/models/webhook.rb +0 -3
- data/lib/x_twitter_scraper/models/x/communities/join_create_response.rb +0 -3
- data/lib/x_twitter_scraper/models/x/communities/join_delete_all_response.rb +0 -4
- data/lib/x_twitter_scraper/models/x/communities/tweet_list_by_community_params.rb +0 -4
- data/lib/x_twitter_scraper/models/x/communities/tweet_list_params.rb +0 -3
- data/lib/x_twitter_scraper/models/x/community_create_response.rb +0 -3
- data/lib/x_twitter_scraper/models/x/community_delete_response.rb +0 -3
- data/lib/x_twitter_scraper/models/x/community_retrieve_members_params.rb +0 -3
- data/lib/x_twitter_scraper/models/x/community_retrieve_moderators_params.rb +0 -4
- data/lib/x_twitter_scraper/models/x/community_retrieve_search_params.rb +0 -3
- data/lib/x_twitter_scraper/models/x/dm_retrieve_history_params.rb +0 -3
- data/lib/x_twitter_scraper/models/x/dm_retrieve_history_response.rb +0 -4
- data/lib/x_twitter_scraper/models/x/dm_send_response.rb +0 -3
- data/lib/x_twitter_scraper/models/x/list_retrieve_followers_params.rb +0 -3
- data/lib/x_twitter_scraper/models/x/list_retrieve_members_params.rb +0 -3
- data/lib/x_twitter_scraper/models/x/list_retrieve_tweets_params.rb +0 -3
- data/lib/x_twitter_scraper/models/x/media_upload_response.rb +0 -3
- data/lib/x_twitter_scraper/models/x/profile_update_avatar_response.rb +0 -3
- data/lib/x_twitter_scraper/models/x/profile_update_banner_response.rb +0 -3
- data/lib/x_twitter_scraper/models/x/profile_update_response.rb +0 -3
- data/lib/x_twitter_scraper/models/x/tweet_create_params.rb +0 -3
- data/lib/x_twitter_scraper/models/x/tweet_create_response.rb +0 -3
- data/lib/x_twitter_scraper/models/x/tweet_delete_response.rb +0 -3
- data/lib/x_twitter_scraper/models/x/tweet_detail.rb +0 -3
- data/lib/x_twitter_scraper/models/x/tweet_get_favoriters_params.rb +0 -3
- data/lib/x_twitter_scraper/models/x/tweet_get_quotes_params.rb +0 -3
- data/lib/x_twitter_scraper/models/x/tweet_get_replies_params.rb +0 -3
- data/lib/x_twitter_scraper/models/x/tweet_get_retweeters_params.rb +0 -3
- data/lib/x_twitter_scraper/models/x/tweet_get_thread_params.rb +0 -3
- data/lib/x_twitter_scraper/models/x/tweet_retrieve_response.rb +0 -3
- data/lib/x_twitter_scraper/models/x/tweet_search_params.rb +0 -3
- data/lib/x_twitter_scraper/models/x/tweets/like_create_response.rb +0 -3
- data/lib/x_twitter_scraper/models/x/tweets/like_delete_response.rb +0 -3
- data/lib/x_twitter_scraper/models/x/tweets/retweet_create_response.rb +0 -3
- data/lib/x_twitter_scraper/models/x/tweets/retweet_delete_response.rb +0 -3
- data/lib/x_twitter_scraper/models/x/user_remove_follower_response.rb +0 -3
- data/lib/x_twitter_scraper/models/x/user_retrieve_batch_params.rb +0 -3
- data/lib/x_twitter_scraper/models/x/user_retrieve_batch_response.rb +0 -3
- data/lib/x_twitter_scraper/models/x/user_retrieve_followers_params.rb +0 -3
- data/lib/x_twitter_scraper/models/x/user_retrieve_followers_you_know_params.rb +0 -4
- data/lib/x_twitter_scraper/models/x/user_retrieve_following_params.rb +0 -3
- data/lib/x_twitter_scraper/models/x/user_retrieve_likes_params.rb +0 -3
- data/lib/x_twitter_scraper/models/x/user_retrieve_media_params.rb +0 -3
- data/lib/x_twitter_scraper/models/x/user_retrieve_mentions_params.rb +0 -3
- data/lib/x_twitter_scraper/models/x/user_retrieve_replies_params.rb +0 -3
- data/lib/x_twitter_scraper/models/x/user_retrieve_search_params.rb +0 -3
- data/lib/x_twitter_scraper/models/x/user_retrieve_tweets_params.rb +0 -3
- data/lib/x_twitter_scraper/models/x/user_retrieve_verified_followers_params.rb +0 -4
- data/lib/x_twitter_scraper/models/x/users/follow_create_response.rb +0 -3
- data/lib/x_twitter_scraper/models/x/users/follow_delete_all_response.rb +0 -3
- data/lib/x_twitter_scraper/models/x/write_action_retrieve_response.rb +0 -3
- data/lib/x_twitter_scraper/models/x/x_account.rb +0 -3
- data/lib/x_twitter_scraper/models/x_get_article_response.rb +0 -4
- data/lib/x_twitter_scraper/request_options.rb +0 -2
- data/lib/x_twitter_scraper/resources/drafts.rb +0 -3
- data/lib/x_twitter_scraper/resources/draws.rb +0 -6
- data/lib/x_twitter_scraper/resources/events.rb +0 -3
- data/lib/x_twitter_scraper/resources/extractions.rb +0 -9
- data/lib/x_twitter_scraper/resources/guest_wallets.rb +0 -6
- data/lib/x_twitter_scraper/resources/radar.rb +0 -3
- data/lib/x_twitter_scraper/resources/support/tickets.rb +0 -6
- data/lib/x_twitter_scraper/resources/trends.rb +0 -3
- data/lib/x_twitter_scraper/resources/x/communities/join.rb +0 -6
- data/lib/x_twitter_scraper/resources/x/communities/tweets.rb +0 -7
- data/lib/x_twitter_scraper/resources/x/communities.rb +0 -16
- data/lib/x_twitter_scraper/resources/x/dm.rb +0 -6
- data/lib/x_twitter_scraper/resources/x/lists.rb +0 -9
- data/lib/x_twitter_scraper/resources/x/media.rb +0 -3
- data/lib/x_twitter_scraper/resources/x/profile.rb +0 -9
- data/lib/x_twitter_scraper/resources/x/tweets/like.rb +0 -6
- data/lib/x_twitter_scraper/resources/x/tweets/retweet.rb +0 -6
- data/lib/x_twitter_scraper/resources/x/tweets.rb +0 -24
- data/lib/x_twitter_scraper/resources/x/users/follow.rb +0 -6
- data/lib/x_twitter_scraper/resources/x/users.rb +0 -38
- data/lib/x_twitter_scraper/resources/x.rb +0 -3
- data/lib/x_twitter_scraper/version.rb +1 -1
- data/lib/x_twitter_scraper.rb +0 -5
- data/rbi/x_twitter_scraper/client.rbi +0 -4
- data/rbi/x_twitter_scraper/file_part.rbi +0 -1
- data/rbi/x_twitter_scraper/internal/transport/base_client.rbi +0 -19
- data/rbi/x_twitter_scraper/internal/transport/pooled_net_requester.rbi +0 -9
- data/rbi/x_twitter_scraper/internal/type/array_of.rbi +0 -10
- data/rbi/x_twitter_scraper/internal/type/base_model.rbi +0 -47
- data/rbi/x_twitter_scraper/internal/type/base_page.rbi +0 -4
- data/rbi/x_twitter_scraper/internal/type/boolean.rbi +0 -8
- data/rbi/x_twitter_scraper/internal/type/converter.rbi +0 -36
- data/rbi/x_twitter_scraper/internal/type/enum.rbi +0 -20
- data/rbi/x_twitter_scraper/internal/type/file_input.rbi +0 -10
- data/rbi/x_twitter_scraper/internal/type/hash_of.rbi +0 -10
- data/rbi/x_twitter_scraper/internal/type/request_parameters.rbi +0 -4
- data/rbi/x_twitter_scraper/internal/type/union.rbi +0 -18
- data/rbi/x_twitter_scraper/internal/type/unknown.rbi +0 -8
- data/rbi/x_twitter_scraper/internal/util.rbi +0 -75
- data/rbi/x_twitter_scraper/internal.rbi +0 -2
- data/rbi/x_twitter_scraper/request_options.rbi +0 -1
- data/sig/x_twitter_scraper/internal/transport/base_client.rbs +0 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 46ffcafe78f6098cd45fa1a0f213515a2fb7d789f27ced4809ac735108a33084
|
|
4
|
+
data.tar.gz: a69999072784ab52f468234a7bfe343ad687c34dec12c78d19ecfb90b26ddccb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 41655fce506cc950e43ff05a0387836d0b6476ac218988637e99e4bd6069b5f9cd541a9819f6623e4e1b8f71c2ce91bb302aba829703a7a31f847b4a1a300315
|
|
7
|
+
data.tar.gz: 910c622be7636cf6fe992ac2851849a12cd6cdf191a8a57d27eadffe9829c63c80434189a7209c6745e15bf476c6cd6dc58705961c47d0848c3e5b9c314c3d25
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.10.6 (2026-10-14)
|
|
4
|
+
|
|
5
|
+
[Full changelog from v0.10.5 to v0.10.6](https://github.com/Xquik-dev/x-twitter-scraper-ruby/compare/v0.10.5...v0.10.6)
|
|
6
|
+
|
|
7
|
+
The API and its behavior are the same as in 0.10.5.
|
|
8
|
+
|
|
9
|
+
### Documentation
|
|
10
|
+
|
|
11
|
+
* The README uses sentence case headings, active voice and whole sentences. Its facts, links and legal lines stay the same.
|
|
12
|
+
|
|
13
|
+
### Chores
|
|
14
|
+
|
|
15
|
+
* 24 development and test gems move to their latest stable release. The 3 runtime dependencies stay the same.
|
|
16
|
+
|
|
3
17
|
## 0.10.5 (2026-10-13)
|
|
4
18
|
|
|
5
19
|
[Full changelog from v0.10.4 to v0.10.5](https://github.com/Xquik-dev/x-twitter-scraper-ruby/compare/v0.10.4...v0.10.5)
|
data/README.md
CHANGED
|
@@ -14,11 +14,43 @@ Xquik charges only for delivered, unique, filter-matching results and never pads
|
|
|
14
14
|
> Xquik is an independent third-party service. Not affiliated with X Corp.
|
|
15
15
|
> "Twitter" and "X" are trademarks of X Corp.
|
|
16
16
|
|
|
17
|
-
[Ruby SDK
|
|
17
|
+
[Ruby SDK guide](https://docs.xquik.com/sdks/ruby) | [REST API](https://docs.xquik.com/api-reference/overview) | [RubyDoc](https://gemdocs.org/gems/x-twitter-scraper) | [Webhooks](https://docs.xquik.com/api-reference/webhooks/create)
|
|
18
|
+
|
|
19
|
+
<!-- trust:start -->
|
|
20
|
+
|
|
21
|
+
## Trust & usage
|
|
22
|
+
|
|
23
|
+
[](https://xquik.com/trust#downloads)
|
|
24
|
+
[](https://apify.com/xquik)
|
|
25
|
+
[](https://apify.com/xquik)
|
|
26
|
+
[](https://apify.com/xquik/x-tweet-scraper/reviews)
|
|
27
|
+
[](https://xquik.com/trust#accounts)
|
|
28
|
+
[](https://xquik.com/trust#skill-installs)
|
|
29
|
+
[](https://trustmrr.com/startup/xquik)
|
|
30
|
+
[](https://xquik.com/trust#speed)
|
|
31
|
+
[](https://github.com/Xquik-dev)
|
|
32
|
+
[](https://rubygems.org/gems/x-twitter-scraper)
|
|
33
|
+
[](https://www.bestpractices.dev/projects/13739)
|
|
34
|
+
|
|
35
|
+
- 51,000+ downloads of Xquik's Twitter API packages on npm, PyPI, RubyGems, NuGet, Packagist & Terraform ([source](https://xquik.com/trust#downloads)) <!-- trust:downloads 51020 -->
|
|
36
|
+
- 7,800+ users of Xquik's Twitter scraper Actors on Apify ([source](https://apify.com/xquik)) <!-- trust:apify-users 7800 -->
|
|
37
|
+
- 5,700,000+ runs of Xquik's Twitter scraper Actors on Apify ([source](https://apify.com/xquik)) <!-- trust:apify-runs 5704701 -->
|
|
38
|
+
- 4.66 of 5 for the X Tweet Scraper from 16 Apify reviews ([source](https://apify.com/xquik/x-tweet-scraper/reviews)) <!-- trust:apify-rating 4.66 16 -->
|
|
39
|
+
- 3,900+ accounts on xquik.com ([source](https://xquik.com/trust#accounts)) <!-- trust:accounts 3924 -->
|
|
40
|
+
- 1,600+ installs of Xquik's Twitter Skills on skills.sh ([source](https://xquik.com/trust#skill-installs)) <!-- trust:skill-installs 1612 -->
|
|
41
|
+
- $38,000+ in revenue verified by TrustMRR ([source](https://trustmrr.com/startup/xquik)) <!-- trust:revenue 38115 -->
|
|
42
|
+
- 501 ms median REST API read time over the last 7 days ([source](https://xquik.com/trust#speed)) <!-- trust:rest-p50 501 -->
|
|
43
|
+
- 370+ GitHub stars across Xquik's repos ([source](https://github.com/Xquik-dev)) <!-- trust:github-stars 374 -->
|
|
44
|
+
- 9,900+ downloads of x-twitter-scraper on RubyGems ([source](https://rubygems.org/gems/x-twitter-scraper)) <!-- trust:rubygems-x-twitter-scraper 9982 -->
|
|
45
|
+
- This repo meets the OpenSSF Best Practices passing criteria ([source](https://www.bestpractices.dev/projects/13739)) <!-- trust:openssf-x-twitter-scraper-ruby 1 -->
|
|
46
|
+
|
|
47
|
+
Checked on 2026-10-15. See each number with its date & source on [xquik.com/trust](https://xquik.com/trust) or as [JSON](https://xquik.com/trust.json).
|
|
48
|
+
|
|
49
|
+
<!-- trust:end -->
|
|
18
50
|
|
|
19
51
|
## Common Twitter & X tasks
|
|
20
52
|
|
|
21
|
-
| Task | REST
|
|
53
|
+
| Task | REST route | Usage |
|
|
22
54
|
| --- | --- | --- |
|
|
23
55
|
| Search tweets without the X API | `GET /x/tweets/search` | Use keyword or advanced operator queries. |
|
|
24
56
|
| Read an X profile timeline | `GET /x/users/{id}/tweets` | Paginate bounded results. |
|
|
@@ -32,18 +64,14 @@ Xquik charges only for delivered, unique, filter-matching results and never pads
|
|
|
32
64
|
|
|
33
65
|
## Installation
|
|
34
66
|
|
|
35
|
-
|
|
67
|
+
The SDK requires Ruby 3.2.0 or later.
|
|
36
68
|
|
|
37
69
|
Add the gem to your `Gemfile`.
|
|
38
70
|
|
|
39
|
-
<!-- x-release-please-start-version -->
|
|
40
|
-
|
|
41
71
|
```ruby
|
|
42
|
-
gem "x-twitter-scraper", "~> 0.10.
|
|
72
|
+
gem "x-twitter-scraper", "~> 0.10.6"
|
|
43
73
|
```
|
|
44
74
|
|
|
45
|
-
<!-- x-release-please-end -->
|
|
46
|
-
|
|
47
75
|
## Usage
|
|
48
76
|
|
|
49
77
|
```ruby
|
|
@@ -51,7 +79,7 @@ require "bundler/setup"
|
|
|
51
79
|
require "x_twitter_scraper"
|
|
52
80
|
|
|
53
81
|
x_twitter_scraper = XTwitterScraper::Client.new(
|
|
54
|
-
api_key: ENV["X_TWITTER_SCRAPER_API_KEY"] # Optional
|
|
82
|
+
api_key: ENV["X_TWITTER_SCRAPER_API_KEY"] # Optional. The client reads this variable.
|
|
55
83
|
)
|
|
56
84
|
|
|
57
85
|
response = x_twitter_scraper.x.tweets.search(q: "from:elonmusk", limit: 10)
|
|
@@ -77,7 +105,7 @@ rescue XTwitterScraper::Errors::APIStatusError => e
|
|
|
77
105
|
end
|
|
78
106
|
```
|
|
79
107
|
|
|
80
|
-
| Cause | Error
|
|
108
|
+
| Cause | Error type |
|
|
81
109
|
| ---------------- | -------------------------- |
|
|
82
110
|
| HTTP 400 | `BadRequestError` |
|
|
83
111
|
| HTTP 401 | `AuthenticationError` |
|
|
@@ -151,7 +179,7 @@ account =
|
|
|
151
179
|
puts(account[:my_undocumented_property])
|
|
152
180
|
```
|
|
153
181
|
|
|
154
|
-
Use `client.request` for undocumented endpoints
|
|
182
|
+
Use `client.request` for undocumented endpoints. It keeps authentication and retries.
|
|
155
183
|
|
|
156
184
|
```ruby
|
|
157
185
|
response = client.request(
|
|
@@ -167,7 +195,7 @@ response = client.request(
|
|
|
167
195
|
|
|
168
196
|
Clients are thread-safe. Fork them only when no HTTP requests are in flight.
|
|
169
197
|
Each client has an HTTP connection pool with a default size of 99.
|
|
170
|
-
Reuse
|
|
198
|
+
Reuse 1 client per application in most cases.
|
|
171
199
|
Requests wait when every connection is busy. This wait counts toward the request timeout.
|
|
172
200
|
Other SDK classes do not lock their data.
|
|
173
201
|
|
|
@@ -178,10 +206,8 @@ The gem ships [RBI](https://sorbet.org/docs/rbi) definitions without `sorbet-run
|
|
|
178
206
|
Pass request hashes or typed parameter objects.
|
|
179
207
|
|
|
180
208
|
```ruby
|
|
181
|
-
# Hashes work without type safety:
|
|
182
209
|
x_twitter_scraper.x.tweets.search(q: "from:elonmusk", limit: 10)
|
|
183
210
|
|
|
184
|
-
# Splat a complete Params object:
|
|
185
211
|
params = XTwitterScraper::X::TweetSearchParams.new(q: "from:elonmusk", limit: 10)
|
|
186
212
|
x_twitter_scraper.x.tweets.search(**params)
|
|
187
213
|
```
|
|
@@ -201,13 +227,11 @@ T.reveal_type(XTwitterScraper::AccountUpdateLocaleParams::Locale::EN)
|
|
|
201
227
|
Enum parameters accept constants or literal values.
|
|
202
228
|
|
|
203
229
|
```ruby
|
|
204
|
-
# Enum constants preserve tagged type information:
|
|
205
230
|
x_twitter_scraper.account.update_locale(
|
|
206
231
|
locale: XTwitterScraper::AccountUpdateLocaleParams::Locale::EN,
|
|
207
232
|
# …
|
|
208
233
|
)
|
|
209
234
|
|
|
210
|
-
# Literal values also work:
|
|
211
235
|
x_twitter_scraper.account.update_locale(
|
|
212
236
|
locale: :en,
|
|
213
237
|
# …
|
|
@@ -218,7 +242,15 @@ x_twitter_scraper.account.update_locale(
|
|
|
218
242
|
|
|
219
243
|
This package follows [SemVer](https://semver.org/spec/v2.0.0.html). Version `0` releases may change APIs.
|
|
220
244
|
|
|
221
|
-
Changes to non-runtime `*.rbi` and `*.rbs` definitions
|
|
245
|
+
Changes to non-runtime `*.rbi` and `*.rbs` definitions are non-breaking.
|
|
246
|
+
|
|
247
|
+
## More Xquik tools
|
|
248
|
+
|
|
249
|
+
- [X (Twitter) scraper API & Twitter MCP server](https://github.com/Xquik-dev/x-twitter-scraper) with REST, MCP & Skill setup.
|
|
250
|
+
- Twitter API SDKs for [TypeScript](https://github.com/Xquik-dev/x-twitter-scraper-typescript), [Python](https://github.com/Xquik-dev/x-twitter-scraper-python), [Go](https://github.com/Xquik-dev/x-twitter-scraper-go), [Java](https://github.com/Xquik-dev/x-twitter-scraper-java), [Kotlin](https://github.com/Xquik-dev/x-twitter-scraper-kotlin), [C#](https://github.com/Xquik-dev/x-twitter-scraper-csharp) & [PHP](https://github.com/Xquik-dev/x-twitter-scraper-php).
|
|
251
|
+
- [Twitter CLI & X CLI](https://github.com/Xquik-dev/x-twitter-scraper-cli) for terminal workflows.
|
|
252
|
+
- [Twitter advanced search operators](https://github.com/Xquik-dev/x-twitter-advanced-search) with tested examples.
|
|
253
|
+
- [Xquik X API & Twitter scraper](https://xquik.com) and the [Twitter API documentation](https://docs.xquik.com/api-reference/overview).
|
|
222
254
|
|
|
223
255
|
## Help & contributing
|
|
224
256
|
|
|
@@ -88,33 +88,20 @@ module XTwitterScraper
|
|
|
88
88
|
# @return [XTwitterScraper::Resources::GuestWallets]
|
|
89
89
|
attr_reader :guest_wallets
|
|
90
90
|
|
|
91
|
-
# @api private
|
|
92
|
-
#
|
|
93
|
-
# @param security [Hash{Symbol=>Boolean}]
|
|
94
|
-
#
|
|
95
|
-
# @return [Hash{String=>String}]
|
|
96
91
|
private def auth_headers(security:)
|
|
97
92
|
{auth_api_key:, oauth_bearer:}.slice(*security.keys).values.reduce({}, :merge)
|
|
98
93
|
end
|
|
99
94
|
|
|
100
|
-
# @api private
|
|
101
|
-
#
|
|
102
|
-
# @return [Hash{String=>String}]
|
|
103
95
|
private def auth_api_key
|
|
104
96
|
{"x-api-key" => @api_key}
|
|
105
97
|
end
|
|
106
98
|
|
|
107
|
-
# @api private
|
|
108
|
-
#
|
|
109
|
-
# @return [Hash{String=>String}]
|
|
110
99
|
private def oauth_bearer
|
|
111
100
|
return {} if @bearer_token.nil?
|
|
112
101
|
|
|
113
102
|
{"authorization" => "Bearer #{@bearer_token}"}
|
|
114
103
|
end
|
|
115
104
|
|
|
116
|
-
# Creates and returns a new client for interacting with the API.
|
|
117
|
-
#
|
|
118
105
|
# @param api_key [String, nil] Defaults to `ENV["X_TWITTER_SCRAPER_API_KEY"]`
|
|
119
106
|
#
|
|
120
107
|
# @param bearer_token [String, nil] OAuth 2.1 access token Defaults to `ENV["X_TWITTER_SCRAPER_BEARER_TOKEN"]`
|
|
@@ -7,16 +7,12 @@
|
|
|
7
7
|
module XTwitterScraper
|
|
8
8
|
module Internal
|
|
9
9
|
module Transport
|
|
10
|
-
# @api private
|
|
11
|
-
#
|
|
12
|
-
# @abstract
|
|
13
10
|
class BaseClient
|
|
14
11
|
extend XTwitterScraper::Internal::Util::SorbetRuntimeSupport
|
|
15
12
|
|
|
16
|
-
# from whatwg fetch spec
|
|
17
13
|
MAX_REDIRECTS = 20
|
|
18
14
|
|
|
19
|
-
# rubocop:disable Style/MutableConstant
|
|
15
|
+
# rubocop:disable-next Style/MutableConstant
|
|
20
16
|
PLATFORM_HEADERS =
|
|
21
17
|
{
|
|
22
18
|
"x-stainless-arch" => XTwitterScraper::Internal::Util.arch,
|
|
@@ -26,14 +22,8 @@ module XTwitterScraper
|
|
|
26
22
|
"x-stainless-runtime" => ::RUBY_ENGINE,
|
|
27
23
|
"x-stainless-runtime-version" => ::RUBY_ENGINE_VERSION
|
|
28
24
|
}
|
|
29
|
-
# rubocop:enable Style/MutableConstant
|
|
30
25
|
|
|
31
26
|
class << self
|
|
32
|
-
# @api private
|
|
33
|
-
#
|
|
34
|
-
# @param req [Hash{Symbol=>Object}]
|
|
35
|
-
#
|
|
36
|
-
# @raise [ArgumentError]
|
|
37
27
|
def validate!(req)
|
|
38
28
|
keys = [
|
|
39
29
|
:method,
|
|
@@ -60,50 +50,18 @@ module XTwitterScraper
|
|
|
60
50
|
end
|
|
61
51
|
end
|
|
62
52
|
|
|
63
|
-
# @api private
|
|
64
|
-
#
|
|
65
|
-
# @param status [Integer]
|
|
66
|
-
# @param headers [Hash{String=>String}]
|
|
67
|
-
#
|
|
68
|
-
# @return [Boolean]
|
|
69
53
|
def should_retry?(status, headers:)
|
|
70
54
|
coerced = XTwitterScraper::Internal::Util.coerce_boolean(headers["x-should-retry"])
|
|
71
55
|
case [coerced, status]
|
|
72
56
|
in [true | false, _]
|
|
73
57
|
coerced
|
|
74
58
|
in [_, 408 | 409 | 429 | (500..)]
|
|
75
|
-
# retry on:
|
|
76
|
-
# 408: timeouts
|
|
77
|
-
# 409: locks
|
|
78
|
-
# 429: rate limits
|
|
79
|
-
# 500+: unknown errors
|
|
80
59
|
true
|
|
81
60
|
else
|
|
82
61
|
false
|
|
83
62
|
end
|
|
84
63
|
end
|
|
85
64
|
|
|
86
|
-
# @api private
|
|
87
|
-
#
|
|
88
|
-
# @param request [Hash{Symbol=>Object}] .
|
|
89
|
-
#
|
|
90
|
-
# @option request [Symbol] :method
|
|
91
|
-
#
|
|
92
|
-
# @option request [URI::Generic] :url
|
|
93
|
-
#
|
|
94
|
-
# @option request [Hash{String=>String}] :headers
|
|
95
|
-
#
|
|
96
|
-
# @option request [Object] :body
|
|
97
|
-
#
|
|
98
|
-
# @option request [Integer] :max_retries
|
|
99
|
-
#
|
|
100
|
-
# @option request [Float] :timeout
|
|
101
|
-
#
|
|
102
|
-
# @param status [Integer]
|
|
103
|
-
#
|
|
104
|
-
# @param response_headers [Hash{String=>String}]
|
|
105
|
-
#
|
|
106
|
-
# @return [Hash{Symbol=>Object}]
|
|
107
65
|
def follow_redirect(request, status:, response_headers:)
|
|
108
66
|
method, url, headers = request.fetch_values(:method, :url, :headers)
|
|
109
67
|
location =
|
|
@@ -132,7 +90,6 @@ module XTwitterScraper
|
|
|
132
90
|
nil
|
|
133
91
|
end
|
|
134
92
|
|
|
135
|
-
# from whatwg fetch spec
|
|
136
93
|
case [status, method]
|
|
137
94
|
in [301 | 302, :post] | [303, _]
|
|
138
95
|
drop = %w[content-encoding content-language content-length content-location content-type]
|
|
@@ -145,7 +102,6 @@ module XTwitterScraper
|
|
|
145
102
|
else
|
|
146
103
|
end
|
|
147
104
|
|
|
148
|
-
# from undici
|
|
149
105
|
if XTwitterScraper::Internal::Util.uri_origin(url) != XTwitterScraper::Internal::Util.uri_origin(location)
|
|
150
106
|
drop = %w[authorization cookie host proxy-authorization]
|
|
151
107
|
request = {**request, headers: request.fetch(:headers).except(*drop)}
|
|
@@ -154,10 +110,6 @@ module XTwitterScraper
|
|
|
154
110
|
request
|
|
155
111
|
end
|
|
156
112
|
|
|
157
|
-
# @api private
|
|
158
|
-
#
|
|
159
|
-
# @param status [Integer, XTwitterScraper::Errors::APIConnectionError]
|
|
160
|
-
# @param stream [Enumerable<String>, nil]
|
|
161
113
|
def reap_connection!(status, stream:)
|
|
162
114
|
case status
|
|
163
115
|
in (..199) | (300..499)
|
|
@@ -169,40 +121,8 @@ module XTwitterScraper
|
|
|
169
121
|
end
|
|
170
122
|
end
|
|
171
123
|
|
|
172
|
-
|
|
173
|
-
attr_reader :base_url
|
|
124
|
+
attr_reader :base_url, :timeout, :max_retries, :initial_retry_delay, :max_retry_delay, :headers, :idempotency_header, :requester
|
|
174
125
|
|
|
175
|
-
# @return [Float]
|
|
176
|
-
attr_reader :timeout
|
|
177
|
-
|
|
178
|
-
# @return [Integer]
|
|
179
|
-
attr_reader :max_retries
|
|
180
|
-
|
|
181
|
-
# @return [Float]
|
|
182
|
-
attr_reader :initial_retry_delay
|
|
183
|
-
|
|
184
|
-
# @return [Float]
|
|
185
|
-
attr_reader :max_retry_delay
|
|
186
|
-
|
|
187
|
-
# @return [Hash{String=>String}]
|
|
188
|
-
attr_reader :headers
|
|
189
|
-
|
|
190
|
-
# @return [String, nil]
|
|
191
|
-
attr_reader :idempotency_header
|
|
192
|
-
|
|
193
|
-
# @api private
|
|
194
|
-
# @return [XTwitterScraper::Internal::Transport::PooledNetRequester]
|
|
195
|
-
attr_reader :requester
|
|
196
|
-
|
|
197
|
-
# @api private
|
|
198
|
-
#
|
|
199
|
-
# @param base_url [String]
|
|
200
|
-
# @param timeout [Float]
|
|
201
|
-
# @param max_retries [Integer]
|
|
202
|
-
# @param initial_retry_delay [Float]
|
|
203
|
-
# @param max_retry_delay [Float]
|
|
204
|
-
# @param headers [Hash{String=>String, Integer, Array<String, Integer, nil>, nil}]
|
|
205
|
-
# @param idempotency_header [String, nil]
|
|
206
126
|
def initialize(
|
|
207
127
|
base_url:,
|
|
208
128
|
timeout: 0.0,
|
|
@@ -231,60 +151,12 @@ module XTwitterScraper
|
|
|
231
151
|
@max_retry_delay = max_retry_delay
|
|
232
152
|
end
|
|
233
153
|
|
|
234
|
-
# @api private
|
|
235
|
-
#
|
|
236
|
-
# @return [Hash{String=>String}]
|
|
237
154
|
private def auth_headers = {}
|
|
238
155
|
|
|
239
|
-
# @api private
|
|
240
|
-
#
|
|
241
|
-
# @return [String]
|
|
242
156
|
private def user_agent = "#{self.class.name}/Ruby #{XTwitterScraper::VERSION}"
|
|
243
157
|
|
|
244
|
-
# @api private
|
|
245
|
-
#
|
|
246
|
-
# @return [String]
|
|
247
158
|
private def generate_idempotency_key = "stainless-ruby-retry-#{SecureRandom.uuid}"
|
|
248
159
|
|
|
249
|
-
# @api private
|
|
250
|
-
#
|
|
251
|
-
# @param req [Hash{Symbol=>Object}] .
|
|
252
|
-
#
|
|
253
|
-
# @option req [Symbol] :method
|
|
254
|
-
#
|
|
255
|
-
# @option req [String, Array<String>] :path
|
|
256
|
-
#
|
|
257
|
-
# @option req [Hash{String=>Array<String>, String, nil}, nil] :query
|
|
258
|
-
#
|
|
259
|
-
# @option req [Hash{String=>String, Integer, Array<String, Integer, nil>, nil}, nil] :headers
|
|
260
|
-
#
|
|
261
|
-
# @option req [Object, nil] :body
|
|
262
|
-
#
|
|
263
|
-
# @option req [Symbol, Integer, Array<Symbol, Integer>, Proc, nil] :unwrap
|
|
264
|
-
#
|
|
265
|
-
# @option req [Class<XTwitterScraper::Internal::Type::BasePage>, nil] :page
|
|
266
|
-
#
|
|
267
|
-
# @option req [Class<XTwitterScraper::Internal::Type::BaseStream>, nil] :stream
|
|
268
|
-
#
|
|
269
|
-
# @option req [XTwitterScraper::Internal::Type::Converter, Class, nil] :model
|
|
270
|
-
#
|
|
271
|
-
# @option req [Hash{Symbol=>Boolean}, nil] :security
|
|
272
|
-
#
|
|
273
|
-
# @param opts [Hash{Symbol=>Object}] .
|
|
274
|
-
#
|
|
275
|
-
# @option opts [String, nil] :idempotency_key
|
|
276
|
-
#
|
|
277
|
-
# @option opts [Hash{String=>Array<String>, String, nil}, nil] :extra_query
|
|
278
|
-
#
|
|
279
|
-
# @option opts [Hash{String=>String, nil}, nil] :extra_headers
|
|
280
|
-
#
|
|
281
|
-
# @option opts [Object, nil] :extra_body
|
|
282
|
-
#
|
|
283
|
-
# @option opts [Integer, nil] :max_retries
|
|
284
|
-
#
|
|
285
|
-
# @option opts [Float, nil] :timeout
|
|
286
|
-
#
|
|
287
|
-
# @return [Hash{Symbol=>Object}]
|
|
288
160
|
private def build_request(req, opts)
|
|
289
161
|
method, uninterpolated_path = req.fetch_values(:method, :path)
|
|
290
162
|
|
|
@@ -328,9 +200,6 @@ module XTwitterScraper
|
|
|
328
200
|
XTwitterScraper::Internal::Util.deep_merge(*[req[:body], opts[:extra_body]].compact)
|
|
329
201
|
end
|
|
330
202
|
|
|
331
|
-
# Generated methods always pass `req[:body]` for operations that define a
|
|
332
|
-
# request body, so only elide the content-type header when the operation
|
|
333
|
-
# has no body at all, not when an optional body param was omitted.
|
|
334
203
|
headers.delete("content-type") if body.nil? && !req.key?(:body)
|
|
335
204
|
|
|
336
205
|
url = XTwitterScraper::Internal::Util.join_parsed_uri(
|
|
@@ -348,14 +217,7 @@ module XTwitterScraper
|
|
|
348
217
|
}
|
|
349
218
|
end
|
|
350
219
|
|
|
351
|
-
# @api private
|
|
352
|
-
#
|
|
353
|
-
# @param headers [Hash{String=>String}]
|
|
354
|
-
# @param retry_count [Integer]
|
|
355
|
-
#
|
|
356
|
-
# @return [Float]
|
|
357
220
|
private def retry_delay(headers, retry_count:)
|
|
358
|
-
# Non-standard extension
|
|
359
221
|
span = Float(headers["retry-after-ms"], exception: false)&.then { _1 / 1000 }
|
|
360
222
|
return span if span
|
|
361
223
|
|
|
@@ -374,30 +236,6 @@ module XTwitterScraper
|
|
|
374
236
|
(@initial_retry_delay * scale * jitter).clamp(0, @max_retry_delay)
|
|
375
237
|
end
|
|
376
238
|
|
|
377
|
-
# @api private
|
|
378
|
-
#
|
|
379
|
-
# @param request [Hash{Symbol=>Object}] .
|
|
380
|
-
#
|
|
381
|
-
# @option request [Symbol] :method
|
|
382
|
-
#
|
|
383
|
-
# @option request [URI::Generic] :url
|
|
384
|
-
#
|
|
385
|
-
# @option request [Hash{String=>String}] :headers
|
|
386
|
-
#
|
|
387
|
-
# @option request [Object] :body
|
|
388
|
-
#
|
|
389
|
-
# @option request [Integer] :max_retries
|
|
390
|
-
#
|
|
391
|
-
# @option request [Float] :timeout
|
|
392
|
-
#
|
|
393
|
-
# @param redirect_count [Integer]
|
|
394
|
-
#
|
|
395
|
-
# @param retry_count [Integer]
|
|
396
|
-
#
|
|
397
|
-
# @param send_retry_header [Boolean]
|
|
398
|
-
#
|
|
399
|
-
# @raise [XTwitterScraper::Errors::APIError]
|
|
400
|
-
# @return [Array(Integer, Net::HTTPResponse, Enumerable<String>)]
|
|
401
239
|
def send_request(request, redirect_count:, retry_count:, send_retry_header:)
|
|
402
240
|
url, headers, max_retries, timeout = request.fetch_values(:url, :headers, :max_retries, :timeout)
|
|
403
241
|
input = {**request.except(:timeout), deadline: XTwitterScraper::Internal::Util.monotonic_secs + timeout}
|
|
@@ -467,47 +305,6 @@ module XTwitterScraper
|
|
|
467
305
|
end
|
|
468
306
|
end
|
|
469
307
|
|
|
470
|
-
# Execute the request specified by `req`. This is the method that all resource
|
|
471
|
-
# methods call into.
|
|
472
|
-
#
|
|
473
|
-
# @overload request(method, path, query: {}, headers: {}, body: nil, unwrap: nil, page: nil, stream: nil, model: XTwitterScraper::Internal::Type::Unknown, security: {auth_api_key: true, oauth_bearer: true}, options: {})
|
|
474
|
-
#
|
|
475
|
-
# @param method [Symbol]
|
|
476
|
-
#
|
|
477
|
-
# @param path [String, Array<String>]
|
|
478
|
-
#
|
|
479
|
-
# @param query [Hash{String=>Array<String>, String, nil}, nil]
|
|
480
|
-
#
|
|
481
|
-
# @param headers [Hash{String=>String, Integer, Array<String, Integer, nil>, nil}, nil]
|
|
482
|
-
#
|
|
483
|
-
# @param body [Object, nil]
|
|
484
|
-
#
|
|
485
|
-
# @param unwrap [Symbol, Integer, Array<Symbol, Integer>, Proc, nil]
|
|
486
|
-
#
|
|
487
|
-
# @param page [Class<XTwitterScraper::Internal::Type::BasePage>, nil]
|
|
488
|
-
#
|
|
489
|
-
# @param stream [Class<XTwitterScraper::Internal::Type::BaseStream>, nil]
|
|
490
|
-
#
|
|
491
|
-
# @param model [XTwitterScraper::Internal::Type::Converter, Class, nil]
|
|
492
|
-
#
|
|
493
|
-
# @param security [Hash{Symbol=>Boolean}, nil]
|
|
494
|
-
#
|
|
495
|
-
# @param options [XTwitterScraper::RequestOptions, Hash{Symbol=>Object}, nil] .
|
|
496
|
-
#
|
|
497
|
-
# @option options [String, nil] :idempotency_key
|
|
498
|
-
#
|
|
499
|
-
# @option options [Hash{String=>Array<String>, String, nil}, nil] :extra_query
|
|
500
|
-
#
|
|
501
|
-
# @option options [Hash{String=>String, nil}, nil] :extra_headers
|
|
502
|
-
#
|
|
503
|
-
# @option options [Object, nil] :extra_body
|
|
504
|
-
#
|
|
505
|
-
# @option options [Integer, nil] :max_retries
|
|
506
|
-
#
|
|
507
|
-
# @option options [Float, nil] :timeout
|
|
508
|
-
#
|
|
509
|
-
# @raise [XTwitterScraper::Errors::APIError]
|
|
510
|
-
# @return [Object]
|
|
511
308
|
def request(req)
|
|
512
309
|
self.class.validate!(req)
|
|
513
310
|
model = req.fetch(:model) { XTwitterScraper::Internal::Type::Unknown }
|
|
@@ -517,7 +314,6 @@ module XTwitterScraper
|
|
|
517
314
|
request = build_request(req.except(:options), opts)
|
|
518
315
|
url = request.fetch(:url)
|
|
519
316
|
|
|
520
|
-
# Don't send the current retry count in the headers if the caller modified the header defaults.
|
|
521
317
|
send_retry_header = request.fetch(:headers)["x-stainless-retry-count"] == "0"
|
|
522
318
|
status, response, stream = send_request(
|
|
523
319
|
request,
|
|
@@ -547,13 +343,9 @@ module XTwitterScraper
|
|
|
547
343
|
end
|
|
548
344
|
end
|
|
549
345
|
|
|
550
|
-
# @api private
|
|
551
|
-
#
|
|
552
|
-
# @return [String]
|
|
553
346
|
def inspect
|
|
554
|
-
# rubocop:disable Layout/LineLength
|
|
347
|
+
# rubocop:disable-next Layout/LineLength
|
|
555
348
|
"#<#{self.class.name}:0x#{object_id.to_s(16)} base_url=#{@base_url} max_retries=#{@max_retries} timeout=#{@timeout}>"
|
|
556
|
-
# rubocop:enable Layout/LineLength
|
|
557
349
|
end
|
|
558
350
|
|
|
559
351
|
define_sorbet_constant!(:RequestComponents) do
|
|
@@ -7,23 +7,14 @@
|
|
|
7
7
|
module XTwitterScraper
|
|
8
8
|
module Internal
|
|
9
9
|
module Transport
|
|
10
|
-
# @api private
|
|
11
10
|
class PooledNetRequester
|
|
12
11
|
extend XTwitterScraper::Internal::Util::SorbetRuntimeSupport
|
|
13
12
|
|
|
14
|
-
# from the golang stdlib
|
|
15
|
-
# https://github.com/golang/go/blob/c8eced8580028328fde7c03cbfcb720ce15b2358/src/net/http/transport.go#L49
|
|
16
13
|
KEEP_ALIVE_TIMEOUT = 30
|
|
17
14
|
|
|
18
15
|
DEFAULT_MAX_CONNECTIONS = [Etc.nprocessors, 99].max
|
|
19
16
|
|
|
20
17
|
class << self
|
|
21
|
-
# @api private
|
|
22
|
-
#
|
|
23
|
-
# @param cert_store [OpenSSL::X509::Store]
|
|
24
|
-
# @param url [URI::Generic]
|
|
25
|
-
#
|
|
26
|
-
# @return [Net::HTTP]
|
|
27
18
|
def connect(cert_store:, url:)
|
|
28
19
|
port =
|
|
29
20
|
case [url.port, url.scheme]
|
|
@@ -43,36 +34,18 @@ module XTwitterScraper
|
|
|
43
34
|
end
|
|
44
35
|
end
|
|
45
36
|
|
|
46
|
-
# @api private
|
|
47
|
-
#
|
|
48
|
-
# @param conn [Net::HTTP]
|
|
49
|
-
# @param deadline [Float]
|
|
50
37
|
def calibrate_socket_timeout(conn, deadline)
|
|
51
38
|
timeout = deadline - XTwitterScraper::Internal::Util.monotonic_secs
|
|
52
39
|
conn.open_timeout = conn.read_timeout = conn.write_timeout = conn.continue_timeout = timeout
|
|
53
40
|
end
|
|
54
41
|
|
|
55
|
-
# @api private
|
|
56
|
-
#
|
|
57
|
-
# @param request [Hash{Symbol=>Object}] .
|
|
58
|
-
#
|
|
59
|
-
# @option request [Symbol] :method
|
|
60
|
-
#
|
|
61
|
-
# @option request [URI::Generic] :url
|
|
62
|
-
#
|
|
63
|
-
# @option request [Hash{String=>String}] :headers
|
|
64
|
-
#
|
|
65
|
-
# @param blk [Proc]
|
|
66
|
-
#
|
|
67
|
-
# @yieldparam [String]
|
|
68
|
-
# @return [Array(Net::HTTPGenericRequest, Proc)]
|
|
69
42
|
def build_request(request, &blk)
|
|
70
43
|
method, url, headers, body = request.fetch_values(:method, :url, :headers, :body)
|
|
71
44
|
req = Net::HTTPGenericRequest.new(
|
|
72
45
|
method.to_s.upcase,
|
|
73
46
|
!body.nil?,
|
|
74
47
|
method != :head,
|
|
75
|
-
URI(url.to_s)
|
|
48
|
+
URI(url.to_s)
|
|
76
49
|
)
|
|
77
50
|
|
|
78
51
|
headers.each { req[_1] = _2 }
|
|
@@ -95,14 +68,6 @@ module XTwitterScraper
|
|
|
95
68
|
end
|
|
96
69
|
end
|
|
97
70
|
|
|
98
|
-
# @api private
|
|
99
|
-
#
|
|
100
|
-
# @param url [URI::Generic]
|
|
101
|
-
# @param deadline [Float]
|
|
102
|
-
# @param blk [Proc]
|
|
103
|
-
#
|
|
104
|
-
# @raise [Timeout::Error]
|
|
105
|
-
# @yieldparam [Net::HTTP]
|
|
106
71
|
private def with_pool(url, deadline:, &blk)
|
|
107
72
|
origin = XTwitterScraper::Internal::Util.uri_origin(url)
|
|
108
73
|
timeout = deadline - XTwitterScraper::Internal::Util.monotonic_secs
|
|
@@ -116,28 +81,13 @@ module XTwitterScraper
|
|
|
116
81
|
pool.with(timeout: timeout, &blk)
|
|
117
82
|
end
|
|
118
83
|
|
|
119
|
-
# @api private
|
|
120
|
-
#
|
|
121
|
-
# @param request [Hash{Symbol=>Object}] .
|
|
122
|
-
#
|
|
123
|
-
# @option request [Symbol] :method
|
|
124
|
-
#
|
|
125
|
-
# @option request [URI::Generic] :url
|
|
126
|
-
#
|
|
127
|
-
# @option request [Hash{String=>String}] :headers
|
|
128
|
-
#
|
|
129
|
-
# @option request [Object] :body
|
|
130
|
-
#
|
|
131
|
-
# @option request [Float] :deadline
|
|
132
|
-
#
|
|
133
|
-
# @return [Array(Integer, Net::HTTPResponse, Enumerable<String>)]
|
|
134
84
|
def execute(request)
|
|
135
85
|
url, deadline = request.fetch_values(:url, :deadline)
|
|
136
86
|
|
|
137
87
|
req = nil
|
|
138
88
|
finished = false
|
|
139
89
|
|
|
140
|
-
# rubocop:disable Metrics/BlockLength
|
|
90
|
+
# rubocop:disable-next Metrics/BlockLength
|
|
141
91
|
enum = Enumerator.new do |y|
|
|
142
92
|
next if finished
|
|
143
93
|
|
|
@@ -185,7 +135,6 @@ module XTwitterScraper
|
|
|
185
135
|
rescue StandardError
|
|
186
136
|
raise XTwitterScraper::Errors::APIConnectionError.new(url: url, request: req)
|
|
187
137
|
end
|
|
188
|
-
# rubocop:enable Metrics/BlockLength
|
|
189
138
|
|
|
190
139
|
_, response = enum.next
|
|
191
140
|
body = XTwitterScraper::Internal::Util.fused_enum(enum, external: true) do
|
|
@@ -195,9 +144,6 @@ module XTwitterScraper
|
|
|
195
144
|
[Integer(response.code), response, body]
|
|
196
145
|
end
|
|
197
146
|
|
|
198
|
-
# @api private
|
|
199
|
-
#
|
|
200
|
-
# @param size [Integer]
|
|
201
147
|
def initialize(size: self.class::DEFAULT_MAX_CONNECTIONS)
|
|
202
148
|
@mutex = Mutex.new
|
|
203
149
|
@size = size
|