twitter 8.2.0 → 8.3.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 (100) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.md +1 -1
  3. data/README.md +172 -10
  4. data/lib/twitter/arguments.rb +14 -1
  5. data/lib/twitter/base.rb +72 -11
  6. data/lib/twitter/basic_user.rb +7 -1
  7. data/lib/twitter/client.rb +94 -3
  8. data/lib/twitter/creatable.rb +11 -2
  9. data/lib/twitter/cursor.rb +58 -11
  10. data/lib/twitter/direct_message.rb +32 -4
  11. data/lib/twitter/direct_message_event.rb +34 -10
  12. data/lib/twitter/direct_messages/welcome_message.rb +22 -1
  13. data/lib/twitter/direct_messages/welcome_message_rule.rb +7 -0
  14. data/lib/twitter/direct_messages/welcome_message_rule_wrapper.rb +26 -3
  15. data/lib/twitter/direct_messages/welcome_message_wrapper.rb +36 -11
  16. data/lib/twitter/entities.rb +84 -8
  17. data/lib/twitter/entity/hashtag.rb +7 -1
  18. data/lib/twitter/entity/symbol.rb +7 -1
  19. data/lib/twitter/entity/uri.rb +2 -1
  20. data/lib/twitter/entity/user_mention.rb +20 -1
  21. data/lib/twitter/entity.rb +7 -1
  22. data/lib/twitter/enumerable.rb +20 -3
  23. data/lib/twitter/error.rb +137 -61
  24. data/lib/twitter/factory.rb +9 -5
  25. data/lib/twitter/geo/point.rb +37 -5
  26. data/lib/twitter/geo/polygon.rb +1 -0
  27. data/lib/twitter/geo.rb +16 -2
  28. data/lib/twitter/geo_factory.rb +7 -3
  29. data/lib/twitter/geo_results.rb +39 -8
  30. data/lib/twitter/headers.rb +44 -7
  31. data/lib/twitter/identity.rb +13 -3
  32. data/lib/twitter/language.rb +21 -1
  33. data/lib/twitter/list.rb +101 -11
  34. data/lib/twitter/media/animated_gif.rb +1 -0
  35. data/lib/twitter/media/photo.rb +19 -3
  36. data/lib/twitter/media/video.rb +21 -3
  37. data/lib/twitter/media/video_info.rb +15 -1
  38. data/lib/twitter/media_factory.rb +7 -3
  39. data/lib/twitter/metadata.rb +14 -1
  40. data/lib/twitter/null_object.rb +16 -14
  41. data/lib/twitter/oembed.rb +56 -2
  42. data/lib/twitter/place.rb +74 -6
  43. data/lib/twitter/premium_search_results.rb +87 -18
  44. data/lib/twitter/profile.rb +100 -44
  45. data/lib/twitter/profile_banner.rb +9 -4
  46. data/lib/twitter/rate_limit.rb +32 -3
  47. data/lib/twitter/relationship.rb +8 -5
  48. data/lib/twitter/rest/account_activity.rb +55 -26
  49. data/lib/twitter/rest/api.rb +2 -0
  50. data/lib/twitter/rest/client.rb +18 -0
  51. data/lib/twitter/rest/direct_messages/welcome_messages.rb +89 -18
  52. data/lib/twitter/rest/direct_messages.rb +158 -94
  53. data/lib/twitter/rest/favorites.rb +57 -21
  54. data/lib/twitter/rest/form_encoder.rb +57 -17
  55. data/lib/twitter/rest/friends_and_followers.rb +101 -35
  56. data/lib/twitter/rest/help.rb +13 -3
  57. data/lib/twitter/rest/lists.rb +133 -45
  58. data/lib/twitter/rest/oauth.rb +23 -17
  59. data/lib/twitter/rest/places_and_geo.rb +44 -28
  60. data/lib/twitter/rest/premium_search.rb +18 -13
  61. data/lib/twitter/rest/request.rb +171 -53
  62. data/lib/twitter/rest/saved_searches.rb +22 -7
  63. data/lib/twitter/rest/search.rb +20 -16
  64. data/lib/twitter/rest/spam_reporting.rb +5 -1
  65. data/lib/twitter/rest/suggested_users.rb +14 -5
  66. data/lib/twitter/rest/timelines.rb +92 -52
  67. data/lib/twitter/rest/trends.rb +31 -12
  68. data/lib/twitter/rest/tweets.rb +145 -88
  69. data/lib/twitter/rest/undocumented.rb +11 -2
  70. data/lib/twitter/rest/upload_utils.rb +42 -26
  71. data/lib/twitter/rest/users.rb +150 -71
  72. data/lib/twitter/rest/utils.rb +135 -39
  73. data/lib/twitter/saved_search.rb +23 -2
  74. data/lib/twitter/search_results.rb +62 -17
  75. data/lib/twitter/settings.rb +37 -11
  76. data/lib/twitter/size.rb +37 -3
  77. data/lib/twitter/source_user.rb +4 -3
  78. data/lib/twitter/streaming/client.rb +60 -8
  79. data/lib/twitter/streaming/connection.rb +55 -8
  80. data/lib/twitter/streaming/deleted_tweet.rb +8 -0
  81. data/lib/twitter/streaming/event.rb +43 -1
  82. data/lib/twitter/streaming/friend_list.rb +1 -0
  83. data/lib/twitter/streaming/message_parser.rb +20 -10
  84. data/lib/twitter/streaming/response.rb +31 -5
  85. data/lib/twitter/streaming/stall_warning.rb +23 -0
  86. data/lib/twitter/suggestion.rb +25 -1
  87. data/lib/twitter/target_user.rb +2 -1
  88. data/lib/twitter/trend.rb +29 -1
  89. data/lib/twitter/trend_results.rb +50 -7
  90. data/lib/twitter/tweet.rb +180 -21
  91. data/lib/twitter/user.rb +289 -53
  92. data/lib/twitter/utils.rb +12 -13
  93. data/lib/twitter/variant.rb +12 -1
  94. data/lib/twitter/version.rb +66 -29
  95. data/lib/twitter.rb +6 -1
  96. metadata +23 -57
  97. data/.yardopts +0 -16
  98. data/CHANGELOG.md +0 -1040
  99. data/CONTRIBUTING.md +0 -49
  100. data/twitter.gemspec +0 -40
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 59d807ebfc2128393a4ab392ac3a5ebd0d7f544a834f1ae08504cbe71bbde002
4
- data.tar.gz: 9113658774b1b0d05cdba8f10a741d938a29c5a0b54ef35cf6db0d005a0dc3a8
3
+ metadata.gz: e3e51290f1c00a7cccecb877674612cb6738dc57f0875b39e0ceed19665741cd
4
+ data.tar.gz: edb56f6daf0b68b9e9825235cfd8ed11ac0a829b06a13126974495705874a54c
5
5
  SHA512:
6
- metadata.gz: 0eeaff88905056ae36daf1ddc6ffe027c10163271587a81d1a09413e1c17abf51cf1e104d5239faf92654caac643ec069c278da3ee481339f2a7128cfbc91473
7
- data.tar.gz: 8895aef36dbcf669fe49042a775634c3aef1bb3de499e158d1270b14f5463e46e82c952051883e00627c41aea55e7322f3349510f24b108a3d0cc5f47e7678e0
6
+ metadata.gz: ce9c4b4231288f4889726413ab97baab2905fc3e2d66dd50d3ac90fb6378019088b4c25d9cca4c62406fd91d2387020cdaaf604ec182c663be2cdfcc1c098739
7
+ data.tar.gz: af70e5b070b1c17f565057712c292a71449384b651803932b0fadba22fb4e76131f1e1b9a1d103bdaed0201ee300957dc83d7cb8850e514daa47a615040aa65d
data/LICENSE.md CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2006-2025 Erik Berlin, John Nunemaker, Wynn Netherland, Steve Richert, Steve Agalloco
1
+ Copyright (c) 2006-2026 Erik Berlin, John Nunemaker, Wynn Netherland, Steve Richert, Steve Agalloco
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,18 +1,23 @@
1
1
  # The Twitter Ruby Gem
2
2
 
3
- ## 📣 This gem is no longer maintained
4
- The Twitter Ruby Gem is no longer maintained and will not support X (Twitter) API v2.
3
+ [![Lint](https://github.com/sferik/twitter-ruby/actions/workflows/lint.yml/badge.svg)](https://github.com/sferik/twitter-ruby/actions/workflows/lint.yml)
4
+ [![Test](https://github.com/sferik/twitter-ruby/actions/workflows/test.yml/badge.svg)](https://github.com/sferik/twitter-ruby/actions/workflows/test.yml)
5
+ [![Mutant](https://github.com/sferik/twitter-ruby/actions/workflows/mutant.yml/badge.svg)](https://github.com/sferik/twitter-ruby/actions/workflows/mutant.yml)
6
+ [![Typecheck](https://github.com/sferik/twitter-ruby/actions/workflows/typecheck.yml/badge.svg)](https://github.com/sferik/twitter-ruby/actions/workflows/typecheck.yml)
7
+ [![Yardstick](https://github.com/sferik/twitter-ruby/actions/workflows/yardstick.yml/badge.svg)](https://github.com/sferik/twitter-ruby/actions/workflows/yardstick.yml)
8
+ [![Gem Version](https://badge.fury.io/rb/twitter.svg)][gem]
5
9
 
6
- ## 🎉 Here’s the good news
7
- We recommend switching to the [X gem][x], which supports both API v1.1 and v2
8
- to make the transition easier. It’s a robust, modern libary that is designed to
9
- ensure you’ll be able to easily integrate any new changes X may roll out.
10
+ The Twitter Ruby Gem provides a Ruby interface to the X (Twitter) API v1.1.
11
+
12
+ For new projects, or if you need API v2 support, use the [X gem][x] as a more
13
+ modern alternative. It supports both API v1.1 and API v2.
10
14
 
11
15
  [x]: https://sferik.github.io/x-ruby/
16
+ [gem]: https://rubygems.org/gems/twitter
12
17
 
13
18
  ## 💖 Sponsoring
14
- The [X gem][x] is free to use, but with new API pricing tiers, it actually costs
15
- money to develop and maintain. By contributing to the project, you help us:
19
+ Open source maintenance takes real time and effort. By sponsoring development,
20
+ you help us:
16
21
 
17
22
  1. 🛠 Maintain the library: Keeping it up-to-date and secure.
18
23
  2. 🌈 Add new features: Enhancements that make your life easier.
@@ -32,13 +37,170 @@ Thanks for considering sponsorship. Together we can make the X gem even better!
32
37
  [sponsor]: https://github.com/sponsors/sferik
33
38
 
34
39
  ## Announcements
35
- You should [follow @gem][follow] on Twitter for announcements and updates about
40
+ You should [follow @gem][follow] on X for announcements and updates about
36
41
  this library.
37
42
 
38
43
  [follow]: https://x.com/gem
39
44
 
45
+ ## Configuration
46
+ Twitter API v1.1 requests require OAuth credentials, so you'll need to
47
+ [register an app in the X developer portal][register] first.
48
+
49
+ [register]: https://developer.x.com/en/portal/dashboard
50
+
51
+ After creating an app, you'll have a consumer key/secret pair and an access
52
+ token/secret pair. Configure these before making requests.
53
+
54
+ You can pass configuration options as a block to `Twitter::REST::Client.new`.
55
+
56
+ ```ruby
57
+ client = Twitter::REST::Client.new do |config|
58
+ config.consumer_key = "YOUR_CONSUMER_KEY"
59
+ config.consumer_secret = "YOUR_CONSUMER_SECRET"
60
+ config.access_token = "YOUR_ACCESS_TOKEN"
61
+ config.access_token_secret = "YOUR_ACCESS_SECRET"
62
+ end
63
+ ```
64
+
65
+ ## Usage Examples
66
+ After configuring a `client`, you can do the following things.
67
+
68
+ **Tweet (as the authenticated user)**
69
+
70
+ ```ruby
71
+ client.update("I'm tweeting with @gem!")
72
+ ```
73
+
74
+ **Follow a user (by screen name or user ID)**
75
+
76
+ ```ruby
77
+ client.follow("gem")
78
+ client.follow(213747670)
79
+ ```
80
+
81
+ **Fetch a user (by screen name or user ID)**
82
+
83
+ ```ruby
84
+ client.user("gem")
85
+ client.user(213747670)
86
+ ```
87
+
88
+ **Fetch a cursored list of followers (by screen name, user ID, or the authenticated user)**
89
+
90
+ ```ruby
91
+ client.followers("gem")
92
+ client.followers(213747670)
93
+ client.followers
94
+ ```
95
+
96
+ **Fetch a cursored list of friends (by screen name, user ID, or the authenticated user)**
97
+
98
+ ```ruby
99
+ client.friends("gem")
100
+ client.friends(213747670)
101
+ client.friends
102
+ ```
103
+
104
+ **Fetch the timeline of Tweets by a user**
105
+
106
+ ```ruby
107
+ client.user_timeline("gem")
108
+ client.user_timeline(213747670)
109
+ ```
110
+
111
+ **Fetch the home timeline**
112
+
113
+ ```ruby
114
+ client.home_timeline
115
+ ```
116
+
117
+ **Fetch the mentions timeline**
118
+
119
+ ```ruby
120
+ client.mentions_timeline
121
+ ```
122
+
123
+ **Fetch a Tweet by ID**
124
+
125
+ ```ruby
126
+ client.status(27558893223)
127
+ ```
128
+
129
+ **Search recent matching Tweets**
130
+
131
+ ```ruby
132
+ client.search("to:justinbieber marry me", result_type: "recent").take(3).map do |tweet|
133
+ "#{tweet.user.screen_name}: #{tweet.text}"
134
+ end
135
+ ```
136
+
137
+ **Find a Japanese-language Tweet tagged #ruby (excluding retweets)**
138
+
139
+ ```ruby
140
+ client.search("#ruby -rt", lang: "ja").first.text
141
+ ```
142
+
143
+ For more usage examples, see the full [documentation][].
144
+
145
+ [documentation]: https://rubydoc.info/gems/twitter
146
+
147
+ ## Streaming
148
+ This gem includes streaming clients for legacy API v1.1 streaming endpoints.
149
+ Endpoint availability and access requirements depend on your developer account.
150
+
151
+ **Configuration works just like `Twitter::REST::Client`**
152
+
153
+ ```ruby
154
+ client = Twitter::Streaming::Client.new do |config|
155
+ config.consumer_key = "YOUR_CONSUMER_KEY"
156
+ config.consumer_secret = "YOUR_CONSUMER_SECRET"
157
+ config.access_token = "YOUR_ACCESS_TOKEN"
158
+ config.access_token_secret = "YOUR_ACCESS_SECRET"
159
+ end
160
+ ```
161
+
162
+ **Stream a random sample of Tweets**
163
+
164
+ ```ruby
165
+ client.sample do |object|
166
+ puts object.text if object.is_a?(Twitter::Tweet)
167
+ end
168
+ ```
169
+
170
+ **Stream mentions of coffee or tea**
171
+
172
+ ```ruby
173
+ topics = ["coffee", "tea"]
174
+ client.filter(track: topics.join(",")) do |object|
175
+ puts object.text if object.is_a?(Twitter::Tweet)
176
+ end
177
+ ```
178
+
179
+ **Stream Tweets, events, and direct messages for the authenticated user**
180
+
181
+ ```ruby
182
+ client.user do |object|
183
+ case object
184
+ when Twitter::Tweet
185
+ puts "It's a tweet!"
186
+ when Twitter::DirectMessage
187
+ puts "It's a direct message!"
188
+ when Twitter::Streaming::StallWarning
189
+ warn "Falling behind!"
190
+ end
191
+ end
192
+ ```
193
+
194
+ An `object` may be one of the following:
195
+ * `Twitter::Tweet`
196
+ * `Twitter::DirectMessage`
197
+ * `Twitter::Streaming::DeletedTweet`
198
+ * `Twitter::Streaming::Event`
199
+ * `Twitter::Streaming::FriendList`
200
+ * `Twitter::Streaming::StallWarning`
201
+
40
202
  ## Copyright
41
- Copyright (c) 2006-2025 Erik Berlin, John Nunemaker, Wynn Netherland, Steve Richert, Steve Agalloco.
203
+ Copyright (c) 2006-2026 Erik Berlin, John Nunemaker, Wynn Netherland, Steve Richert, Steve Agalloco.
42
204
  See [LICENSE][] for details.
43
205
 
44
206
  [license]: LICENSE.md
@@ -1,13 +1,26 @@
1
1
  module Twitter
2
+ # An Array subclass that extracts options from arguments
2
3
  class Arguments < Array
4
+ # The options hash extracted from the arguments
5
+ #
6
+ # @api public
7
+ # @example
8
+ # args = Twitter::Arguments.new([:user1, :user2, {trim_user: true}])
9
+ # args.options # => {trim_user: true}
3
10
  # @return [Hash]
4
11
  attr_reader :options
5
12
 
6
13
  # Initializes a new Arguments object
7
14
  #
15
+ # @api public
16
+ # @example
17
+ # args = Twitter::Arguments.new([:user1, :user2, {trim_user: true}])
18
+ # args # => [:user1, :user2]
19
+ # args.options # => {trim_user: true}
20
+ # @param args [Array] An array of arguments, optionally ending with a Hash
8
21
  # @return [Twitter::Arguments]
9
22
  def initialize(args)
10
- @options = args.last.is_a?(::Hash) ? args.pop : {}
23
+ @options = args.last.is_a?(Hash) ? args.pop : {} # : Hash[Symbol, untyped]
11
24
  super(args.flatten)
12
25
  end
13
26
  end
data/lib/twitter/base.rb CHANGED
@@ -1,23 +1,46 @@
1
- require "addressable/uri"
1
+ require "uri"
2
2
  require "forwardable"
3
3
  require "memoizable"
4
4
  require "twitter/null_object"
5
5
  require "twitter/utils"
6
6
 
7
7
  module Twitter
8
+ # Base class for Twitter objects
8
9
  class Base
9
10
  extend Forwardable
10
11
  include Memoizable
11
12
  include Twitter::Utils
13
+
14
+ # The raw attributes hash
15
+ #
16
+ # @api public
17
+ # @example
18
+ # user.attrs # => {id: 123, name: "John"}
12
19
  # @return [Hash]
13
20
  attr_reader :attrs
14
- alias to_h attrs
15
- alias to_hash to_h
21
+
22
+ # @!method to_h
23
+ # Converts the object to a hash
24
+ # @api public
25
+ # @example
26
+ # user.to_h # => {id: 123, name: "John"}
27
+ # @return [Hash]
28
+ alias_method :to_h, :attrs
29
+
30
+ # @!method to_hash
31
+ # Converts the object to a hash
32
+ # @api public
33
+ # @example
34
+ # user.to_hash # => {id: 123, name: "John"}
35
+ # @return [Hash]
36
+ alias_method :to_hash, :to_h
16
37
 
17
38
  class << self
18
39
  # Define methods that retrieve the value from attributes
19
40
  #
41
+ # @api private
20
42
  # @param attrs [Array, Symbol]
43
+ # @return [void]
21
44
  def attr_reader(*attrs)
22
45
  attrs.each do |attr|
23
46
  define_attribute_method(attr)
@@ -25,6 +48,11 @@ module Twitter
25
48
  end
26
49
  end
27
50
 
51
+ # Define predicate methods for attributes
52
+ #
53
+ # @api private
54
+ # @param attrs [Array, Symbol]
55
+ # @return [void]
28
56
  def predicate_attr_reader(*attrs)
29
57
  attrs.each do |attr|
30
58
  define_predicate_method(attr)
@@ -33,9 +61,11 @@ module Twitter
33
61
 
34
62
  # Define object methods from attributes
35
63
  #
64
+ # @api private
36
65
  # @param klass [Symbol]
37
66
  # @param key1 [Symbol]
38
67
  # @param key2 [Symbol]
68
+ # @return [void]
39
69
  def object_attr_reader(klass, key1, key2 = nil)
40
70
  define_attribute_method(key1, klass, key2)
41
71
  define_predicate_method(key1)
@@ -43,7 +73,9 @@ module Twitter
43
73
 
44
74
  # Define URI methods from attributes
45
75
  #
76
+ # @api private
46
77
  # @param attrs [Array, Symbol]
78
+ # @return [void]
47
79
  def uri_attr_reader(*attrs)
48
80
  attrs.each do |uri_key|
49
81
  array = uri_key.to_s.split("_")
@@ -58,6 +90,9 @@ module Twitter
58
90
  end
59
91
 
60
92
  # Define display_uri attribute methods
93
+ #
94
+ # @api private
95
+ # @return [void]
61
96
  def display_uri_attr_reader
62
97
  define_attribute_method(:display_url)
63
98
  alias_method(:display_uri, :display_url)
@@ -67,26 +102,30 @@ module Twitter
67
102
 
68
103
  # Dynamically define a method for a URI
69
104
  #
105
+ # @api private
70
106
  # @param key1 [Symbol]
71
107
  # @param key2 [Symbol]
108
+ # @return [void]
72
109
  def define_uri_method(key1, key2)
73
110
  define_method(key1) do
74
- Addressable::URI.parse(@attrs[key2].chomp("#")) unless @attrs[key2].nil?
111
+ URI.parse(@attrs[key2].chomp("#").gsub(/[^\x00-\x7F]/) { |c| c.bytes.map { |b| format("%%%02X", b) }.join }) unless @attrs[key2].nil? # steep:ignore FallbackAny,NoMethod
75
112
  end
76
113
  memoize(key1)
77
114
  end
78
115
 
79
116
  # Dynamically define a method for an attribute
80
117
  #
118
+ # @api private
81
119
  # @param key1 [Symbol]
82
120
  # @param klass [Symbol]
83
121
  # @param key2 [Symbol]
122
+ # @return [void]
84
123
  def define_attribute_method(key1, klass = nil, key2 = nil)
85
124
  define_method(key1) do
86
- if attr_falsey_or_empty?(key1)
125
+ if attr_falsey_or_empty?(key1) # steep:ignore NoMethod
87
126
  NullObject.new
88
127
  else
89
- klass.nil? ? @attrs[key1] : Twitter.const_get(klass).new(attrs_for_object(key1, key2))
128
+ klass.nil? ? @attrs[key1] : Twitter.const_get(klass).new(attrs_for_object(key1, key2)) # steep:ignore NoMethod,FallbackAny
90
129
  end
91
130
  end
92
131
  memoize(key1)
@@ -94,11 +133,13 @@ module Twitter
94
133
 
95
134
  # Dynamically define a predicate method for an attribute
96
135
  #
136
+ # @api private
97
137
  # @param key1 [Symbol]
98
138
  # @param key2 [Symbol]
139
+ # @return [void]
99
140
  def define_predicate_method(key1, key2 = key1)
100
141
  define_method(:"#{key1}?") do
101
- !attr_falsey_or_empty?(key2)
142
+ !attr_falsey_or_empty?(key2) # steep:ignore NoMethod
102
143
  end
103
144
  memoize(:"#{key1}?")
104
145
  end
@@ -106,28 +147,48 @@ module Twitter
106
147
 
107
148
  # Initializes a new object
108
149
  #
150
+ # @api public
151
+ # @example
152
+ # Twitter::Base.new(id: 123, name: "John")
109
153
  # @param attrs [Hash]
110
154
  # @return [Twitter::Base]
111
- def initialize(attrs = {})
155
+ def initialize(attrs = nil)
112
156
  @attrs = attrs || {}
113
157
  end
114
158
 
115
159
  # Fetches an attribute of an object using hash notation
116
160
  #
161
+ # @api public
162
+ # @deprecated Use attribute methods instead
163
+ # @example
164
+ # user[:id] # => 123
117
165
  # @param method [String, Symbol] Message to send to the object
166
+ # @return [Object, nil]
118
167
  def [](method)
119
- warn "#{Kernel.caller.first}: [DEPRECATION] #[#{method.inspect}] is deprecated. Use ##{method} to fetch the value."
120
- send(method.to_sym)
168
+ location = caller_locations(1, 1)&.first
169
+ warn "#{location&.path}:#{location&.lineno}: [DEPRECATION] #[#{method.inspect}] is deprecated. Use ##{method} to fetch the value."
170
+ public_send(method.to_sym)
121
171
  rescue NoMethodError
122
172
  nil
123
173
  end
124
174
 
125
- private
175
+ private
126
176
 
177
+ # Check if an attribute is falsey or empty
178
+ #
179
+ # @api private
180
+ # @param key [Symbol]
181
+ # @return [Boolean]
127
182
  def attr_falsey_or_empty?(key)
128
183
  !@attrs[key] || (@attrs[key].respond_to?(:empty?) && @attrs[key].empty?)
129
184
  end
130
185
 
186
+ # Get attributes for creating a nested object
187
+ #
188
+ # @api private
189
+ # @param key1 [Symbol]
190
+ # @param key2 [Symbol]
191
+ # @return [Hash]
131
192
  def attrs_for_object(key1, key2 = nil)
132
193
  if key2.nil?
133
194
  @attrs[key1]
@@ -2,7 +2,13 @@ require "twitter/identity"
2
2
  require "twitter/utils"
3
3
 
4
4
  module Twitter
5
- class BasicUser < Twitter::Identity
5
+ # Represents a basic Twitter user with minimal attributes
6
+ class BasicUser < Identity
7
+ # The user's screen name (handle)
8
+ #
9
+ # @api public
10
+ # @example
11
+ # user.screen_name # => "sferik"
6
12
  # @return [String]
7
13
  attr_reader :screen_name
8
14
 
@@ -3,13 +3,79 @@ require "twitter/utils"
3
3
  require "twitter/version"
4
4
 
5
5
  module Twitter
6
+ # Base client class for Twitter API authentication
6
7
  class Client
7
8
  include Twitter::Utils
8
- attr_accessor :access_token, :access_token_secret, :consumer_key, :consumer_secret, :proxy, :timeouts, :dev_environment
9
+
10
+ # The OAuth access token
11
+ #
12
+ # @api public
13
+ # @example
14
+ # client.access_token # => "token"
15
+ # @return [String]
16
+ attr_accessor :access_token
17
+
18
+ # The OAuth access token secret
19
+ #
20
+ # @api public
21
+ # @example
22
+ # client.access_token_secret # => "secret"
23
+ # @return [String]
24
+ attr_accessor :access_token_secret
25
+
26
+ # The OAuth consumer key
27
+ #
28
+ # @api public
29
+ # @example
30
+ # client.consumer_key # => "key"
31
+ # @return [String]
32
+ attr_accessor :consumer_key
33
+
34
+ # The OAuth consumer secret
35
+ #
36
+ # @api public
37
+ # @example
38
+ # client.consumer_secret # => "secret"
39
+ # @return [String]
40
+ attr_accessor :consumer_secret
41
+
42
+ # The proxy server URI
43
+ #
44
+ # @api public
45
+ # @example
46
+ # client.proxy # => "http://proxy.example.com:8080"
47
+ # @return [String]
48
+ attr_accessor :proxy
49
+
50
+ # The HTTP request timeouts
51
+ #
52
+ # @api public
53
+ # @example
54
+ # client.timeouts # => {connect: 5, read: 10}
55
+ # @return [Hash]
56
+ attr_accessor :timeouts
57
+
58
+ # The development environment name for Premium API endpoints
59
+ #
60
+ # @api public
61
+ # @example
62
+ # client.dev_environment # => "dev"
63
+ # @return [String]
64
+ attr_accessor :dev_environment
65
+
66
+ # The user agent string sent with requests
67
+ #
68
+ # @api public
69
+ # @example
70
+ # client.user_agent = "MyApp/1.0"
71
+ # @return [String]
9
72
  attr_writer :user_agent
10
73
 
11
74
  # Initializes a new Client object
12
75
  #
76
+ # @api public
77
+ # @example
78
+ # client = Twitter::Client.new(consumer_key: "key")
13
79
  # @param options [Hash]
14
80
  # @return [Twitter::Client]
15
81
  def initialize(options = {})
@@ -19,33 +85,58 @@ module Twitter
19
85
  yield(self) if block_given?
20
86
  end
21
87
 
88
+ # Check if user token credentials are present
89
+ #
90
+ # @api public
91
+ # @example
92
+ # client.user_token? # => true
22
93
  # @return [Boolean]
23
94
  def user_token?
24
95
  !(blank_string?(access_token) || blank_string?(access_token_secret))
25
96
  end
26
97
 
98
+ # The user agent string sent with requests
99
+ #
100
+ # @api public
101
+ # @example
102
+ # client.user_agent # => "TwitterRubyGem/8.2.0"
27
103
  # @return [String]
28
104
  def user_agent
29
105
  @user_agent ||= "TwitterRubyGem/#{Twitter::Version}"
30
106
  end
31
107
 
108
+ # The OAuth credentials hash
109
+ #
110
+ # @api public
111
+ # @example
112
+ # client.credentials # => {consumer_key: "key", ...}
32
113
  # @return [Hash]
33
114
  def credentials
34
115
  {
35
116
  consumer_key:,
36
117
  consumer_secret:,
37
118
  token: access_token,
38
- token_secret: access_token_secret,
119
+ token_secret: access_token_secret
39
120
  }
40
121
  end
41
122
 
123
+ # Check if all credentials are present
124
+ #
125
+ # @api public
126
+ # @example
127
+ # client.credentials? # => true
42
128
  # @return [Boolean]
43
129
  def credentials?
44
130
  credentials.values.none? { |v| blank_string?(v) }
45
131
  end
46
132
 
47
- private
133
+ private
48
134
 
135
+ # Check if string is blank or nil
136
+ #
137
+ # @api private
138
+ # @param string [String]
139
+ # @return [Boolean]
49
140
  def blank_string?(string)
50
141
  string.respond_to?(:empty?) ? string.empty? : !string
51
142
  end
@@ -2,14 +2,18 @@ require "time"
2
2
  require "memoizable"
3
3
 
4
4
  module Twitter
5
+ # Provides created_at functionality for Twitter objects
5
6
  module Creatable
6
7
  include Memoizable
7
8
 
8
9
  # Time when the object was created on Twitter
9
10
  #
11
+ # @api public
12
+ # @example
13
+ # tweet.created_at # => 2025-01-15 12:00:00 UTC
10
14
  # @return [Time]
11
15
  def created_at
12
- time = @attrs[:created_at]
16
+ time = @attrs[:created_at] # steep:ignore FallbackAny
13
17
  return if time.nil?
14
18
 
15
19
  time = Time.parse(time) unless time.is_a?(Time)
@@ -17,9 +21,14 @@ module Twitter
17
21
  end
18
22
  memoize :created_at
19
23
 
24
+ # Check if the created_at attribute is present
25
+ #
26
+ # @api public
27
+ # @example
28
+ # tweet.created? # => true
20
29
  # @return [Boolean]
21
30
  def created?
22
- !!@attrs[:created_at]
31
+ !!@attrs[:created_at] # steep:ignore FallbackAny
23
32
  end
24
33
  memoize :created?
25
34
  end