x-twitter-scraper 0.6.0 → 0.7.0

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.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/README.md +1 -1
  4. data/lib/x_twitter_scraper/internal/type/union.rb +25 -9
  5. data/lib/x_twitter_scraper/models/content_disclosure.rb +1 -9
  6. data/lib/x_twitter_scraper/models/embedded_tweet.rb +389 -1
  7. data/lib/x_twitter_scraper/models/paginated_tweets.rb +4 -5
  8. data/lib/x_twitter_scraper/models/search_tweet.rb +371 -1
  9. data/lib/x_twitter_scraper/models/support/ticket_list_response.rb +30 -17
  10. data/lib/x_twitter_scraper/models/support/ticket_retrieve_response.rb +49 -24
  11. data/lib/x_twitter_scraper/models/support/ticket_update_response.rb +18 -6
  12. data/lib/x_twitter_scraper/models/trend_list_response.rb +28 -1
  13. data/lib/x_twitter_scraper/models/tweet_media.rb +213 -1
  14. data/lib/x_twitter_scraper/models/user_profile.rb +211 -21
  15. data/lib/x_twitter_scraper/models/x/account_connection_attempt_retrieve_response.rb +60 -26
  16. data/lib/x_twitter_scraper/models/x/account_connection_challenge_submit_response.rb +4 -4
  17. data/lib/x_twitter_scraper/models/x/account_create_response.rb +149 -2
  18. data/lib/x_twitter_scraper/models/x/account_reauth_response.rb +4 -4
  19. data/lib/x_twitter_scraper/models/x/communities/tweet_list_by_community_params.rb +3 -5
  20. data/lib/x_twitter_scraper/models/x/communities/tweet_list_params.rb +3 -5
  21. data/lib/x_twitter_scraper/models/x/community_retrieve_info_response.rb +1 -17
  22. data/lib/x_twitter_scraper/models/x/community_retrieve_search_params.rb +3 -5
  23. data/lib/x_twitter_scraper/models/x/list_retrieve_tweets_params.rb +3 -5
  24. data/lib/x_twitter_scraper/models/x/tweet_author.rb +14 -1
  25. data/lib/x_twitter_scraper/models/x/tweet_detail.rb +373 -1
  26. data/lib/x_twitter_scraper/models/x/tweet_get_quotes_params.rb +3 -5
  27. data/lib/x_twitter_scraper/models/x/tweet_get_replies_params.rb +34 -6
  28. data/lib/x_twitter_scraper/models/x/tweet_get_replies_response.rb +345 -0
  29. data/lib/x_twitter_scraper/models/x/tweet_get_thread_params.rb +3 -5
  30. data/lib/x_twitter_scraper/models/x/user_retrieve_likes_params.rb +3 -5
  31. data/lib/x_twitter_scraper/models/x/user_retrieve_media_params.rb +3 -5
  32. data/lib/x_twitter_scraper/models/x/user_retrieve_mentions_params.rb +3 -5
  33. data/lib/x_twitter_scraper/models/x/user_retrieve_replies_params.rb +3 -5
  34. data/lib/x_twitter_scraper/models/x/user_retrieve_tweets_params.rb +3 -5
  35. data/lib/x_twitter_scraper/models/x_get_article_response.rb +1 -7
  36. data/lib/x_twitter_scraper/models/x_get_trends_response.rb +28 -1
  37. data/lib/x_twitter_scraper/resources/x/account_connection_attempts.rb +1 -1
  38. data/lib/x_twitter_scraper/resources/x/accounts.rb +2 -2
  39. data/lib/x_twitter_scraper/resources/x/communities/tweets.rb +2 -2
  40. data/lib/x_twitter_scraper/resources/x/communities.rb +1 -1
  41. data/lib/x_twitter_scraper/resources/x/lists.rb +1 -1
  42. data/lib/x_twitter_scraper/resources/x/tweets.rb +14 -11
  43. data/lib/x_twitter_scraper/resources/x/users.rb +5 -5
  44. data/lib/x_twitter_scraper/version.rb +1 -1
  45. data/lib/x_twitter_scraper.rb +2 -1
  46. data/rbi/x_twitter_scraper/models/content_disclosure.rbi +1 -15
  47. data/rbi/x_twitter_scraper/models/embedded_tweet.rbi +708 -3
  48. data/rbi/x_twitter_scraper/models/paginated_tweets.rbi +4 -5
  49. data/rbi/x_twitter_scraper/models/search_tweet.rbi +674 -3
  50. data/rbi/x_twitter_scraper/models/support/ticket_list_response.rbi +75 -55
  51. data/rbi/x_twitter_scraper/models/support/ticket_retrieve_response.rbi +129 -87
  52. data/rbi/x_twitter_scraper/models/support/ticket_update_response.rbi +62 -13
  53. data/rbi/x_twitter_scraper/models/trend_list_response.rbi +40 -3
  54. data/rbi/x_twitter_scraper/models/tweet_media.rbi +313 -3
  55. data/rbi/x_twitter_scraper/models/user_profile.rbi +340 -29
  56. data/rbi/x_twitter_scraper/models/x/account_connection_attempt_retrieve_response.rbi +61 -83
  57. data/rbi/x_twitter_scraper/models/x/account_connection_challenge_submit_response.rbi +6 -6
  58. data/rbi/x_twitter_scraper/models/x/account_create_response.rbi +264 -2
  59. data/rbi/x_twitter_scraper/models/x/account_reauth_response.rbi +6 -6
  60. data/rbi/x_twitter_scraper/models/x/communities/tweet_list_by_community_params.rbi +4 -8
  61. data/rbi/x_twitter_scraper/models/x/communities/tweet_list_params.rbi +4 -8
  62. data/rbi/x_twitter_scraper/models/x/community_retrieve_info_response.rbi +0 -22
  63. data/rbi/x_twitter_scraper/models/x/community_retrieve_search_params.rbi +4 -8
  64. data/rbi/x_twitter_scraper/models/x/list_retrieve_tweets_params.rbi +4 -8
  65. data/rbi/x_twitter_scraper/models/x/tweet_author.rbi +13 -3
  66. data/rbi/x_twitter_scraper/models/x/tweet_detail.rbi +690 -3
  67. data/rbi/x_twitter_scraper/models/x/tweet_get_quotes_params.rbi +4 -8
  68. data/rbi/x_twitter_scraper/models/x/tweet_get_replies_params.rbi +68 -8
  69. data/rbi/x_twitter_scraper/models/x/tweet_get_replies_response.rbi +527 -0
  70. data/rbi/x_twitter_scraper/models/x/tweet_get_thread_params.rbi +4 -8
  71. data/rbi/x_twitter_scraper/models/x/user_retrieve_likes_params.rbi +4 -8
  72. data/rbi/x_twitter_scraper/models/x/user_retrieve_media_params.rbi +4 -8
  73. data/rbi/x_twitter_scraper/models/x/user_retrieve_mentions_params.rbi +4 -8
  74. data/rbi/x_twitter_scraper/models/x/user_retrieve_replies_params.rbi +4 -8
  75. data/rbi/x_twitter_scraper/models/x/user_retrieve_tweets_params.rbi +4 -8
  76. data/rbi/x_twitter_scraper/models/x_get_article_response.rbi +0 -9
  77. data/rbi/x_twitter_scraper/models/x_get_trends_response.rbi +40 -3
  78. data/rbi/x_twitter_scraper/resources/x/accounts.rbi +1 -1
  79. data/rbi/x_twitter_scraper/resources/x/communities/tweets.rbi +4 -8
  80. data/rbi/x_twitter_scraper/resources/x/communities.rbi +2 -4
  81. data/rbi/x_twitter_scraper/resources/x/lists.rbi +2 -4
  82. data/rbi/x_twitter_scraper/resources/x/tweets.rbi +20 -18
  83. data/rbi/x_twitter_scraper/resources/x/users.rbi +10 -20
  84. data/sig/x_twitter_scraper/models/content_disclosure.rbs +1 -11
  85. data/sig/x_twitter_scraper/models/embedded_tweet.rbs +343 -62
  86. data/sig/x_twitter_scraper/models/search_tweet.rbs +333 -70
  87. data/sig/x_twitter_scraper/models/support/ticket_list_response.rbs +29 -32
  88. data/sig/x_twitter_scraper/models/support/ticket_retrieve_response.rbs +49 -48
  89. data/sig/x_twitter_scraper/models/support/ticket_update_response.rbs +25 -7
  90. data/sig/x_twitter_scraper/models/trend_list_response.rbs +16 -20
  91. data/sig/x_twitter_scraper/models/tweet_media.rbs +146 -15
  92. data/sig/x_twitter_scraper/models/user_profile.rbs +164 -86
  93. data/sig/x_twitter_scraper/models/x/account_connection_attempt_retrieve_response.rbs +50 -33
  94. data/sig/x_twitter_scraper/models/x/account_connection_challenge_submit_response.rbs +5 -5
  95. data/sig/x_twitter_scraper/models/x/account_create_response.rbs +147 -1
  96. data/sig/x_twitter_scraper/models/x/account_reauth_response.rbs +5 -5
  97. data/sig/x_twitter_scraper/models/x/community_retrieve_info_response.rbs +0 -14
  98. data/sig/x_twitter_scraper/models/x/tweet_author.rbs +11 -3
  99. data/sig/x_twitter_scraper/models/x/tweet_detail.rbs +333 -70
  100. data/sig/x_twitter_scraper/models/x/tweet_get_replies_params.rbs +26 -0
  101. data/sig/x_twitter_scraper/models/x/tweet_get_replies_response.rbs +274 -0
  102. data/sig/x_twitter_scraper/models/x_get_article_response.rbs +0 -7
  103. data/sig/x_twitter_scraper/models/x_get_trends_response.rbs +25 -3
  104. data/sig/x_twitter_scraper/resources/x/accounts.rbs +1 -1
  105. data/sig/x_twitter_scraper/resources/x/tweets.rbs +3 -1
  106. metadata +4 -1
@@ -153,10 +153,8 @@ module XTwitterScraper
153
153
  sig { params(min_retweets: Integer).void }
154
154
  attr_writer :min_retweets
155
155
 
156
- # Maximum items requested from this page (1-100, default 20). The response can
157
- # contain fewer items because the source returned fewer, filters removed items, or
158
- # remaining credits cover fewer results. Keep requesting next_cursor while
159
- # has_next_page is true, even when a page is empty. The deprecated limit and count
156
+ # Maximum page items (1-100, default 20). Source, filters, or credits can reduce
157
+ # results. Continue while has_next_page is true. Deprecated limit and count
160
158
  # aliases remain accepted.
161
159
  sig { returns(T.nilable(Integer)) }
162
160
  attr_reader :page_size
@@ -355,10 +353,8 @@ module XTwitterScraper
355
353
  min_replies: nil,
356
354
  # Minimum retweets threshold.
357
355
  min_retweets: nil,
358
- # Maximum items requested from this page (1-100, default 20). The response can
359
- # contain fewer items because the source returned fewer, filters removed items, or
360
- # remaining credits cover fewer results. Keep requesting next_cursor while
361
- # has_next_page is true, even when a page is empty. The deprecated limit and count
356
+ # Maximum page items (1-100, default 20). Source, filters, or credits can reduce
357
+ # results. Continue while has_next_page is true. Deprecated limit and count
362
358
  # aliases remain accepted.
363
359
  page_size: nil,
364
360
  # Quote mode.
@@ -93,6 +93,15 @@ module XTwitterScraper
93
93
  sig { params(language: String).void }
94
94
  attr_writer :language
95
95
 
96
+ # With mode=complete, maximum combined direct and nested reply rows (1-25000).
97
+ # Without complete mode, this is the deprecated pageSize alias and uses the normal
98
+ # 1-100 page range.
99
+ sig { returns(T.nilable(Integer)) }
100
+ attr_reader :limit
101
+
102
+ sig { params(limit: Integer).void }
103
+ attr_writer :limit
104
+
96
105
  # Filter by media type.
97
106
  sig do
98
107
  returns(
@@ -146,10 +155,24 @@ module XTwitterScraper
146
155
  sig { params(min_retweets: Integer).void }
147
156
  attr_writer :min_retweets
148
157
 
149
- # Maximum items requested from this page (1-100, default 20). The response can
150
- # contain fewer items because the source returned fewer, filters removed items, or
151
- # remaining credits cover fewer results. Keep requesting next_cursor while
152
- # has_next_page is true, even when a page is empty. The deprecated limit and count
158
+ # Set complete for maximum-coverage collection. Complete mode accepts only limit.
159
+ # Remove cursor, pageSize, count, time ranges, and tweet filters.
160
+ sig do
161
+ returns(
162
+ T.nilable(XTwitterScraper::X::TweetGetRepliesParams::Mode::OrSymbol)
163
+ )
164
+ end
165
+ attr_reader :mode
166
+
167
+ sig do
168
+ params(
169
+ mode: XTwitterScraper::X::TweetGetRepliesParams::Mode::OrSymbol
170
+ ).void
171
+ end
172
+ attr_writer :mode
173
+
174
+ # Maximum page items (1-100, default 20). Source, filters, or credits can reduce
175
+ # results. Continue while has_next_page is true. Deprecated limit and count
153
176
  # aliases remain accepted.
154
177
  sig { returns(T.nilable(Integer)) }
155
178
  attr_reader :page_size
@@ -286,6 +309,7 @@ module XTwitterScraper
286
309
  hashtags: String,
287
310
  in_reply_to_tweet_id: String,
288
311
  language: String,
312
+ limit: Integer,
289
313
  media_type:
290
314
  XTwitterScraper::X::TweetGetRepliesParams::MediaType::OrSymbol,
291
315
  mentioning: String,
@@ -293,6 +317,7 @@ module XTwitterScraper
293
317
  min_quotes: Integer,
294
318
  min_replies: Integer,
295
319
  min_retweets: Integer,
320
+ mode: XTwitterScraper::X::TweetGetRepliesParams::Mode::OrSymbol,
296
321
  page_size: Integer,
297
322
  quotes: XTwitterScraper::X::TweetGetRepliesParams::Quotes::OrSymbol,
298
323
  quotes_of_tweet_id: String,
@@ -334,6 +359,10 @@ module XTwitterScraper
334
359
  in_reply_to_tweet_id: nil,
335
360
  # Language code filter, e.g. en or tr.
336
361
  language: nil,
362
+ # With mode=complete, maximum combined direct and nested reply rows (1-25000).
363
+ # Without complete mode, this is the deprecated pageSize alias and uses the normal
364
+ # 1-100 page range.
365
+ limit: nil,
337
366
  # Filter by media type.
338
367
  media_type: nil,
339
368
  # Filter tweets mentioning a username.
@@ -346,10 +375,11 @@ module XTwitterScraper
346
375
  min_replies: nil,
347
376
  # Minimum retweets threshold.
348
377
  min_retweets: nil,
349
- # Maximum items requested from this page (1-100, default 20). The response can
350
- # contain fewer items because the source returned fewer, filters removed items, or
351
- # remaining credits cover fewer results. Keep requesting next_cursor while
352
- # has_next_page is true, even when a page is empty. The deprecated limit and count
378
+ # Set complete for maximum-coverage collection. Complete mode accepts only limit.
379
+ # Remove cursor, pageSize, count, time ranges, and tweet filters.
380
+ mode: nil,
381
+ # Maximum page items (1-100, default 20). Source, filters, or credits can reduce
382
+ # results. Continue while has_next_page is true. Deprecated limit and count
353
383
  # aliases remain accepted.
354
384
  page_size: nil,
355
385
  # Quote mode.
@@ -394,6 +424,7 @@ module XTwitterScraper
394
424
  hashtags: String,
395
425
  in_reply_to_tweet_id: String,
396
426
  language: String,
427
+ limit: Integer,
397
428
  media_type:
398
429
  XTwitterScraper::X::TweetGetRepliesParams::MediaType::OrSymbol,
399
430
  mentioning: String,
@@ -401,6 +432,7 @@ module XTwitterScraper
401
432
  min_quotes: Integer,
402
433
  min_replies: Integer,
403
434
  min_retweets: Integer,
435
+ mode: XTwitterScraper::X::TweetGetRepliesParams::Mode::OrSymbol,
404
436
  page_size: Integer,
405
437
  quotes:
406
438
  XTwitterScraper::X::TweetGetRepliesParams::Quotes::OrSymbol,
@@ -479,6 +511,34 @@ module XTwitterScraper
479
511
  end
480
512
  end
481
513
 
514
+ # Set complete for maximum-coverage collection. Complete mode accepts only limit.
515
+ # Remove cursor, pageSize, count, time ranges, and tweet filters.
516
+ module Mode
517
+ extend XTwitterScraper::Internal::Type::Enum
518
+
519
+ TaggedSymbol =
520
+ T.type_alias do
521
+ T.all(Symbol, XTwitterScraper::X::TweetGetRepliesParams::Mode)
522
+ end
523
+ OrSymbol = T.type_alias { T.any(Symbol, String) }
524
+
525
+ COMPLETE =
526
+ T.let(
527
+ :complete,
528
+ XTwitterScraper::X::TweetGetRepliesParams::Mode::TaggedSymbol
529
+ )
530
+
531
+ sig do
532
+ override.returns(
533
+ T::Array[
534
+ XTwitterScraper::X::TweetGetRepliesParams::Mode::TaggedSymbol
535
+ ]
536
+ )
537
+ end
538
+ def self.values
539
+ end
540
+ end
541
+
482
542
  # Quote mode.
483
543
  module Quotes
484
544
  extend XTwitterScraper::Internal::Type::Enum
@@ -0,0 +1,527 @@
1
+ # typed: strong
2
+
3
+ module XTwitterScraper
4
+ module Models
5
+ module X
6
+ class TweetGetRepliesResponse < XTwitterScraper::Models::PaginatedTweets
7
+ OrHash =
8
+ T.type_alias do
9
+ T.any(
10
+ XTwitterScraper::Models::X::TweetGetRepliesResponse,
11
+ XTwitterScraper::Internal::AnyHash
12
+ )
13
+ end
14
+
15
+ # Evidence for direct-reply coverage and collector behavior.
16
+ sig do
17
+ returns(
18
+ T.nilable(
19
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic
20
+ )
21
+ )
22
+ end
23
+ attr_reader :diagnostic
24
+
25
+ sig do
26
+ params(
27
+ diagnostic:
28
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic::OrHash
29
+ ).void
30
+ end
31
+ attr_writer :diagnostic
32
+
33
+ # Nested replies. Excluded from direct coverage.
34
+ sig { returns(T.nilable(T::Array[XTwitterScraper::SearchTweet])) }
35
+ attr_reader :nested_replies
36
+
37
+ sig do
38
+ params(
39
+ nested_replies: T::Array[XTwitterScraper::SearchTweet::OrHash]
40
+ ).void
41
+ end
42
+ attr_writer :nested_replies
43
+
44
+ # Reply rows. Complete mode also returns nested replies and coverage diagnostics.
45
+ # Keep nested replies separate from direct coverage.
46
+ sig do
47
+ params(
48
+ diagnostic:
49
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic::OrHash,
50
+ nested_replies: T::Array[XTwitterScraper::SearchTweet::OrHash]
51
+ ).returns(T.attached_class)
52
+ end
53
+ def self.new(
54
+ # Evidence for direct-reply coverage and collector behavior.
55
+ diagnostic: nil,
56
+ # Nested replies. Excluded from direct coverage.
57
+ nested_replies: nil
58
+ )
59
+ end
60
+
61
+ sig do
62
+ override.returns(
63
+ {
64
+ diagnostic:
65
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic,
66
+ nested_replies: T::Array[XTwitterScraper::SearchTweet]
67
+ }
68
+ )
69
+ end
70
+ def to_hash
71
+ end
72
+
73
+ class Diagnostic < XTwitterScraper::Internal::Type::BaseModel
74
+ OrHash =
75
+ T.type_alias do
76
+ T.any(
77
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic,
78
+ XTwitterScraper::Internal::AnyHash
79
+ )
80
+ end
81
+
82
+ # Whether coverage met the target without truncation.
83
+ sig { returns(T::Boolean) }
84
+ attr_accessor :complete
85
+
86
+ # Unique direct replies as a percentage of the reported count.
87
+ sig { returns(Float) }
88
+ attr_accessor :coverage_percentage
89
+
90
+ # Cursor requests that failed.
91
+ sig { returns(Integer) }
92
+ attr_accessor :cursor_failures
93
+
94
+ # Duplicate tweet IDs removed across pages and strategies.
95
+ sig { returns(Integer) }
96
+ attr_accessor :duplicate_count
97
+
98
+ # Empty pages rejected because they did not make progress.
99
+ sig { returns(Integer) }
100
+ attr_accessor :empty_false_progress_pages
101
+
102
+ # Malformed response items rejected.
103
+ sig { returns(Integer) }
104
+ attr_accessor :malformed_count
105
+
106
+ # Expected response modules or fields missing from X.
107
+ sig { returns(T::Array[String]) }
108
+ attr_accessor :missing_response_modules_or_fields
109
+
110
+ # Unique nested replies kept outside direct coverage.
111
+ sig { returns(Integer) }
112
+ attr_accessor :nested_reply_count
113
+
114
+ # Total pages attempted across all strategies.
115
+ sig { returns(Integer) }
116
+ attr_accessor :pages_attempted
117
+
118
+ # Recommended next action when coverage is incomplete.
119
+ sig { returns(String) }
120
+ attr_accessor :recommended_fallback
121
+
122
+ # Repeated cursors rejected to prevent loops.
123
+ sig { returns(Integer) }
124
+ attr_accessor :repeated_cursor_count
125
+
126
+ # Reply count reported on the source post.
127
+ sig { returns(Integer) }
128
+ attr_accessor :reported_reply_count
129
+
130
+ # Whether the requested row limit truncated safe results.
131
+ sig { returns(T::Boolean) }
132
+ attr_accessor :response_truncated
133
+
134
+ # Field-presence counts across the collected direct replies.
135
+ sig do
136
+ returns(
137
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic::Richness
138
+ )
139
+ end
140
+ attr_reader :richness
141
+
142
+ sig do
143
+ params(
144
+ richness:
145
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic::Richness::OrHash
146
+ ).void
147
+ end
148
+ attr_writer :richness
149
+
150
+ # Per-strategy pagination and contribution evidence.
151
+ sig do
152
+ returns(
153
+ T::Array[
154
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic::StrategiesAttempted
155
+ ]
156
+ )
157
+ end
158
+ attr_accessor :strategies_attempted
159
+
160
+ # Minimum direct replies required for the coverage target.
161
+ sig { returns(Integer) }
162
+ attr_accessor :target_direct_replies
163
+
164
+ # Unique replies whose parent ID equals the source post ID.
165
+ sig { returns(Integer) }
166
+ attr_accessor :unique_direct_replies
167
+
168
+ # Tweets rejected because they belonged elsewhere.
169
+ sig { returns(Integer) }
170
+ attr_accessor :unrelated_count
171
+
172
+ # Evidence for direct-reply coverage and collector behavior.
173
+ sig do
174
+ params(
175
+ complete: T::Boolean,
176
+ coverage_percentage: Float,
177
+ cursor_failures: Integer,
178
+ duplicate_count: Integer,
179
+ empty_false_progress_pages: Integer,
180
+ malformed_count: Integer,
181
+ missing_response_modules_or_fields: T::Array[String],
182
+ nested_reply_count: Integer,
183
+ pages_attempted: Integer,
184
+ recommended_fallback: String,
185
+ repeated_cursor_count: Integer,
186
+ reported_reply_count: Integer,
187
+ response_truncated: T::Boolean,
188
+ richness:
189
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic::Richness::OrHash,
190
+ strategies_attempted:
191
+ T::Array[
192
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic::StrategiesAttempted::OrHash
193
+ ],
194
+ target_direct_replies: Integer,
195
+ unique_direct_replies: Integer,
196
+ unrelated_count: Integer
197
+ ).returns(T.attached_class)
198
+ end
199
+ def self.new(
200
+ # Whether coverage met the target without truncation.
201
+ complete:,
202
+ # Unique direct replies as a percentage of the reported count.
203
+ coverage_percentage:,
204
+ # Cursor requests that failed.
205
+ cursor_failures:,
206
+ # Duplicate tweet IDs removed across pages and strategies.
207
+ duplicate_count:,
208
+ # Empty pages rejected because they did not make progress.
209
+ empty_false_progress_pages:,
210
+ # Malformed response items rejected.
211
+ malformed_count:,
212
+ # Expected response modules or fields missing from X.
213
+ missing_response_modules_or_fields:,
214
+ # Unique nested replies kept outside direct coverage.
215
+ nested_reply_count:,
216
+ # Total pages attempted across all strategies.
217
+ pages_attempted:,
218
+ # Recommended next action when coverage is incomplete.
219
+ recommended_fallback:,
220
+ # Repeated cursors rejected to prevent loops.
221
+ repeated_cursor_count:,
222
+ # Reply count reported on the source post.
223
+ reported_reply_count:,
224
+ # Whether the requested row limit truncated safe results.
225
+ response_truncated:,
226
+ # Field-presence counts across the collected direct replies.
227
+ richness:,
228
+ # Per-strategy pagination and contribution evidence.
229
+ strategies_attempted:,
230
+ # Minimum direct replies required for the coverage target.
231
+ target_direct_replies:,
232
+ # Unique replies whose parent ID equals the source post ID.
233
+ unique_direct_replies:,
234
+ # Tweets rejected because they belonged elsewhere.
235
+ unrelated_count:
236
+ )
237
+ end
238
+
239
+ sig do
240
+ override.returns(
241
+ {
242
+ complete: T::Boolean,
243
+ coverage_percentage: Float,
244
+ cursor_failures: Integer,
245
+ duplicate_count: Integer,
246
+ empty_false_progress_pages: Integer,
247
+ malformed_count: Integer,
248
+ missing_response_modules_or_fields: T::Array[String],
249
+ nested_reply_count: Integer,
250
+ pages_attempted: Integer,
251
+ recommended_fallback: String,
252
+ repeated_cursor_count: Integer,
253
+ reported_reply_count: Integer,
254
+ response_truncated: T::Boolean,
255
+ richness:
256
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic::Richness,
257
+ strategies_attempted:
258
+ T::Array[
259
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic::StrategiesAttempted
260
+ ],
261
+ target_direct_replies: Integer,
262
+ unique_direct_replies: Integer,
263
+ unrelated_count: Integer
264
+ }
265
+ )
266
+ end
267
+ def to_hash
268
+ end
269
+
270
+ class Richness < XTwitterScraper::Internal::Type::BaseModel
271
+ OrHash =
272
+ T.type_alias do
273
+ T.any(
274
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic::Richness,
275
+ XTwitterScraper::Internal::AnyHash
276
+ )
277
+ end
278
+
279
+ # Replies with article content.
280
+ sig { returns(Integer) }
281
+ attr_accessor :article
282
+
283
+ # Replies with author details.
284
+ sig { returns(Integer) }
285
+ attr_accessor :author
286
+
287
+ # Replies with card metadata.
288
+ sig { returns(Integer) }
289
+ attr_accessor :card
290
+
291
+ # Replies with community-note data.
292
+ sig { returns(Integer) }
293
+ attr_accessor :community_note
294
+
295
+ # Replies with a creation timestamp.
296
+ sig { returns(Integer) }
297
+ attr_accessor :created_at
298
+
299
+ # Replies with engagement counts.
300
+ sig { returns(Integer) }
301
+ attr_accessor :engagement_counts
302
+
303
+ # Replies with entity metadata.
304
+ sig { returns(Integer) }
305
+ attr_accessor :entities
306
+
307
+ # Replies with a language value.
308
+ sig { returns(Integer) }
309
+ attr_accessor :language
310
+
311
+ # Replies with media metadata.
312
+ sig { returns(Integer) }
313
+ attr_accessor :media
314
+
315
+ # Replies with quoted or reposted tweet data.
316
+ sig { returns(Integer) }
317
+ attr_accessor :quoted_or_reposted_tweet
318
+
319
+ # Replies with text.
320
+ sig { returns(Integer) }
321
+ attr_accessor :text
322
+
323
+ # Total unique direct replies evaluated for richness.
324
+ sig { returns(Integer) }
325
+ attr_accessor :total_replies
326
+
327
+ # Replies with a canonical URL.
328
+ sig { returns(Integer) }
329
+ attr_accessor :url
330
+
331
+ # Field-presence counts across the collected direct replies.
332
+ sig do
333
+ params(
334
+ article: Integer,
335
+ author: Integer,
336
+ card: Integer,
337
+ community_note: Integer,
338
+ created_at: Integer,
339
+ engagement_counts: Integer,
340
+ entities: Integer,
341
+ language: Integer,
342
+ media: Integer,
343
+ quoted_or_reposted_tweet: Integer,
344
+ text: Integer,
345
+ total_replies: Integer,
346
+ url: Integer
347
+ ).returns(T.attached_class)
348
+ end
349
+ def self.new(
350
+ # Replies with article content.
351
+ article:,
352
+ # Replies with author details.
353
+ author:,
354
+ # Replies with card metadata.
355
+ card:,
356
+ # Replies with community-note data.
357
+ community_note:,
358
+ # Replies with a creation timestamp.
359
+ created_at:,
360
+ # Replies with engagement counts.
361
+ engagement_counts:,
362
+ # Replies with entity metadata.
363
+ entities:,
364
+ # Replies with a language value.
365
+ language:,
366
+ # Replies with media metadata.
367
+ media:,
368
+ # Replies with quoted or reposted tweet data.
369
+ quoted_or_reposted_tweet:,
370
+ # Replies with text.
371
+ text:,
372
+ # Total unique direct replies evaluated for richness.
373
+ total_replies:,
374
+ # Replies with a canonical URL.
375
+ url:
376
+ )
377
+ end
378
+
379
+ sig do
380
+ override.returns(
381
+ {
382
+ article: Integer,
383
+ author: Integer,
384
+ card: Integer,
385
+ community_note: Integer,
386
+ created_at: Integer,
387
+ engagement_counts: Integer,
388
+ entities: Integer,
389
+ language: Integer,
390
+ media: Integer,
391
+ quoted_or_reposted_tweet: Integer,
392
+ text: Integer,
393
+ total_replies: Integer,
394
+ url: Integer
395
+ }
396
+ )
397
+ end
398
+ def to_hash
399
+ end
400
+ end
401
+
402
+ class StrategiesAttempted < XTwitterScraper::Internal::Type::BaseModel
403
+ OrHash =
404
+ T.type_alias do
405
+ T.any(
406
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic::StrategiesAttempted,
407
+ XTwitterScraper::Internal::AnyHash
408
+ )
409
+ end
410
+
411
+ sig { returns(String) }
412
+ attr_accessor :name
413
+
414
+ sig { returns(Integer) }
415
+ attr_accessor :new_direct_replies
416
+
417
+ sig { returns(Integer) }
418
+ attr_accessor :new_nested_replies
419
+
420
+ sig { returns(Integer) }
421
+ attr_accessor :pages_attempted
422
+
423
+ sig do
424
+ returns(
425
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic::StrategiesAttempted::StopReason::TaggedSymbol
426
+ )
427
+ end
428
+ attr_accessor :stop_reason
429
+
430
+ sig do
431
+ params(
432
+ name: String,
433
+ new_direct_replies: Integer,
434
+ new_nested_replies: Integer,
435
+ pages_attempted: Integer,
436
+ stop_reason:
437
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic::StrategiesAttempted::StopReason::OrSymbol
438
+ ).returns(T.attached_class)
439
+ end
440
+ def self.new(
441
+ name:,
442
+ new_direct_replies:,
443
+ new_nested_replies:,
444
+ pages_attempted:,
445
+ stop_reason:
446
+ )
447
+ end
448
+
449
+ sig do
450
+ override.returns(
451
+ {
452
+ name: String,
453
+ new_direct_replies: Integer,
454
+ new_nested_replies: Integer,
455
+ pages_attempted: Integer,
456
+ stop_reason:
457
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic::StrategiesAttempted::StopReason::TaggedSymbol
458
+ }
459
+ )
460
+ end
461
+ def to_hash
462
+ end
463
+
464
+ module StopReason
465
+ extend XTwitterScraper::Internal::Type::Enum
466
+
467
+ TaggedSymbol =
468
+ T.type_alias do
469
+ T.all(
470
+ Symbol,
471
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic::StrategiesAttempted::StopReason
472
+ )
473
+ end
474
+ OrSymbol = T.type_alias { T.any(Symbol, String) }
475
+
476
+ DEADLINE =
477
+ T.let(
478
+ :deadline,
479
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic::StrategiesAttempted::StopReason::TaggedSymbol
480
+ )
481
+ EMPTY_PAGES =
482
+ T.let(
483
+ :empty_pages,
484
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic::StrategiesAttempted::StopReason::TaggedSymbol
485
+ )
486
+ ERROR =
487
+ T.let(
488
+ :error,
489
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic::StrategiesAttempted::StopReason::TaggedSymbol
490
+ )
491
+ MISSING_CURSOR =
492
+ T.let(
493
+ :missing_cursor,
494
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic::StrategiesAttempted::StopReason::TaggedSymbol
495
+ )
496
+ NO_NEXT_PAGE =
497
+ T.let(
498
+ :no_next_page,
499
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic::StrategiesAttempted::StopReason::TaggedSymbol
500
+ )
501
+ PAGE_CAP =
502
+ T.let(
503
+ :page_cap,
504
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic::StrategiesAttempted::StopReason::TaggedSymbol
505
+ )
506
+ REPEATED_CURSOR =
507
+ T.let(
508
+ :repeated_cursor,
509
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic::StrategiesAttempted::StopReason::TaggedSymbol
510
+ )
511
+
512
+ sig do
513
+ override.returns(
514
+ T::Array[
515
+ XTwitterScraper::Models::X::TweetGetRepliesResponse::Diagnostic::StrategiesAttempted::StopReason::TaggedSymbol
516
+ ]
517
+ )
518
+ end
519
+ def self.values
520
+ end
521
+ end
522
+ end
523
+ end
524
+ end
525
+ end
526
+ end
527
+ end