twitch-api 0.3.0 → 1.0.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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +130 -26
  3. data/lib/twitch/api_error.rb +5 -4
  4. data/lib/twitch/automod_message_status.rb +17 -0
  5. data/lib/twitch/bits_leader.rb +6 -1
  6. data/lib/twitch/category.rb +27 -0
  7. data/lib/twitch/channel.rb +46 -0
  8. data/lib/twitch/cheermote.rb +53 -0
  9. data/lib/twitch/cheermote_tier.rb +55 -0
  10. data/lib/twitch/cheermote_tier_image.rb +18 -0
  11. data/lib/twitch/cheermote_tier_images.rb +21 -0
  12. data/lib/twitch/client/custom_rewards.rb +35 -0
  13. data/lib/twitch/client/extensions.rb +20 -0
  14. data/lib/twitch/client/games.rb +20 -0
  15. data/lib/twitch/client/moderation.rb +28 -0
  16. data/lib/twitch/client/streams.rb +29 -0
  17. data/lib/twitch/client/subscriptions.rb +12 -0
  18. data/lib/twitch/client/users.rb +20 -0
  19. data/lib/twitch/client.rb +128 -92
  20. data/lib/twitch/clip.rb +10 -12
  21. data/lib/twitch/custom_reward.rb +91 -0
  22. data/lib/twitch/editor.rb +21 -0
  23. data/lib/twitch/entitlement_grant_url.rb +3 -2
  24. data/lib/twitch/extension.rb +37 -0
  25. data/lib/twitch/extensions_by_types.rb +32 -0
  26. data/lib/twitch/game.rb +4 -2
  27. data/lib/twitch/game_analytic.rb +4 -2
  28. data/lib/twitch/moderation_event.rb +33 -0
  29. data/lib/twitch/moderator.rb +20 -0
  30. data/lib/twitch/redemption.rb +35 -0
  31. data/lib/twitch/response.rb +42 -19
  32. data/lib/twitch/stream.rb +12 -12
  33. data/lib/twitch/stream_marker.rb +47 -0
  34. data/lib/twitch/stream_metadata.rb +29 -15
  35. data/lib/twitch/subscription.rb +28 -0
  36. data/lib/twitch/user.rb +8 -3
  37. data/lib/twitch/user_ban.rb +26 -0
  38. data/lib/twitch/user_follow.rb +10 -2
  39. data/lib/twitch/version.rb +3 -1
  40. data/lib/twitch/video.rb +9 -13
  41. data/lib/twitch-api.rb +3 -4
  42. metadata +58 -75
  43. data/.gitignore +0 -17
  44. data/.rspec +0 -3
  45. data/.travis.yml +0 -9
  46. data/Gemfile +0 -6
  47. data/Rakefile +0 -6
  48. data/bin/console +0 -14
  49. data/bin/setup +0 -8
  50. data/twitch-api.gemspec +0 -32
data/lib/twitch/client.rb CHANGED
@@ -1,140 +1,176 @@
1
- require "faraday"
2
- require "faraday_middleware"
3
-
4
- require "twitch/response"
5
- require "twitch/api_error"
6
- require "twitch/bits_leader"
7
- require "twitch/clip"
8
- require "twitch/entitlement_grant_url"
9
- require "twitch/game"
10
- require "twitch/game_analytic"
11
- require "twitch/stream"
12
- require "twitch/stream_metadata"
13
- require "twitch/user"
14
- require "twitch/user_follow"
15
- require "twitch/video"
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+ require 'faraday/parse_dates'
5
+ require 'faraday/retry'
6
+ require 'twitch_oauth2'
7
+
8
+ require_relative 'response'
9
+
10
+ require_relative 'api_error'
11
+ require_relative 'bits_leader'
12
+ require_relative 'category'
13
+ require_relative 'channel'
14
+ require_relative 'cheermote'
15
+ require_relative 'clip'
16
+ require_relative 'custom_reward'
17
+ require_relative 'editor'
18
+ require_relative 'entitlement_grant_url'
19
+ require_relative 'extension'
20
+ require_relative 'extensions_by_types'
21
+ require_relative 'game'
22
+ require_relative 'game_analytic'
23
+ require_relative 'moderation_event'
24
+ require_relative 'moderator'
25
+ require_relative 'stream'
26
+ require_relative 'stream_marker'
27
+ require_relative 'stream_metadata'
28
+ require_relative 'subscription'
29
+ require_relative 'user'
30
+ require_relative 'user_ban'
31
+ require_relative 'user_follow'
32
+ require_relative 'redemption'
33
+ require_relative 'video'
16
34
 
17
35
  module Twitch
36
+ # Core class for requests
18
37
  class Client
19
- # Helix API endpoint.
20
- API_ENDPOINT = "https://api.twitch.tv/helix".freeze
38
+ # Base connection to Helix API.
39
+ CONNECTION = Faraday.new(
40
+ 'https://api.twitch.tv/helix', {
41
+ headers: { 'User-Agent': "twitch-api ruby client #{Twitch::VERSION}" }
42
+ }
43
+ ) do |faraday|
44
+ faraday.request :retry,
45
+ exceptions: [*Faraday::Retry::Middleware::DEFAULT_EXCEPTIONS, Faraday::ConnectionFailed]
46
+
47
+ faraday.response :parse_dates
48
+
49
+ faraday.request :json
50
+ faraday.response :json
51
+ end
52
+
53
+ attr_reader :tokens
21
54
 
22
55
  # Initializes a Twitch client.
23
- #
24
- # - client_id [String] The client ID.
25
- # Used as the Client-ID header in a request.
26
- # - access_token [String] An access token.
27
- # Used as the Authorization header in a request.
28
- # Any "Bearer " prefix will be stripped.
29
- # - with_raw [Boolean] Whether to include raw HTTP response
30
- # Intended for testing/checking API results
31
- def initialize(client_id: nil, access_token: nil, with_raw: false)
32
- if client_id.nil? && access_token.nil?
33
- raise "An identifier token (client ID or bearer token) is required"
34
- elsif !!client_id && !!access_token
35
- warn(%{WARNING:
36
- It is recommended that only one identifier token is specified.
37
- Unpredictable behavior may follow.})
38
- end
56
+ #
57
+ # - tokens [TwitchOAuth2::Tokens] Tokens object with their refreshing logic inside.
58
+ # All client and authentication information (`client_id`, `:scopes`, etc.) stores there.
59
+ def initialize(tokens:)
60
+ @tokens = tokens
39
61
 
40
- headers = {
41
- "User-Agent": "twitch-api ruby client #{Twitch::VERSION}"
42
- }
43
- unless client_id.nil?
44
- headers["Client-ID"] = client_id
45
- end
46
- unless access_token.nil?
47
- access_token = access_token.gsub(/^Bearer /, "")
48
- headers["Authorization"] = "Bearer #{access_token}"
49
- end
50
-
51
- @conn = Faraday.new(API_ENDPOINT, { headers: headers }) do |faraday|
52
- faraday.request :json
53
- faraday.response :json
54
- faraday.adapter Faraday.default_adapter
55
- end
62
+ CONNECTION.headers['Client-ID'] = self.tokens.client.client_id
56
63
 
57
- @with_raw = with_raw
64
+ renew_authorization_header
58
65
  end
59
66
 
60
67
  def create_clip(options = {})
61
- Response.new(Clip, post('clips', options))
68
+ initialize_response Clip, post('clips', options)
62
69
  end
63
70
 
64
71
  def create_entitlement_grant_url(options = {})
65
- Response.new(EntitlementGrantUrl, post('entitlements/upload', options))
72
+ initialize_response EntitlementGrantUrl, post('entitlements/upload', options)
66
73
  end
67
74
 
68
75
  def get_clips(options = {})
69
- Response.new(Clip, get('clips', options))
76
+ initialize_response Clip, get('clips', options)
70
77
  end
71
78
 
72
79
  def get_bits_leaderboard(options = {})
73
- Response.new(BitsLeader, get('bits/leaderboard', options))
80
+ initialize_response BitsLeader, get('bits/leaderboard', options)
74
81
  end
75
82
 
76
- def get_games(options = {})
77
- Response.new(Game, get('games', options))
83
+ def get_cheermotes(options = {})
84
+ initialize_response Cheermote, get('bits/cheermotes', options)
78
85
  end
79
86
 
80
- def get_top_games(options = {})
81
- Response.new(Game, get('games/top', options))
82
- end
87
+ require_relative 'client/extensions'
88
+ include Extensions
89
+
90
+ require_relative 'client/games'
91
+ include Games
92
+
93
+ require_relative 'client/moderation'
94
+ include Moderation
95
+
96
+ require_relative 'client/streams'
97
+ include Streams
98
+
99
+ require_relative 'client/subscriptions'
100
+ include Subscriptions
83
101
 
84
- def get_game_analytics(options = {})
85
- Response.new(GameAnalytic, get('analytics/games', options))
102
+ def get_videos(options = {})
103
+ initialize_response Video, get('videos', options)
86
104
  end
87
105
 
88
- def get_streams(options = {})
89
- Response.new(Stream, get('streams', options))
106
+ require_relative 'client/users'
107
+ include Users
108
+
109
+ require_relative 'client/custom_rewards'
110
+ include CustomRewards
111
+
112
+ ## https://dev.twitch.tv/docs/api/reference#get-channel-information
113
+ def get_channels(options = {})
114
+ initialize_response Channel, get('channels', options)
90
115
  end
91
116
 
92
- def get_streams_metadata(options = {})
93
- Response.new(StreamMetadata, get('streams/metadata', options))
117
+ ## https://dev.twitch.tv/docs/api/reference/#search-channels
118
+ def search_channels(options = {})
119
+ initialize_response Channel, get('search/channels', options)
94
120
  end
95
121
 
96
- def get_users_follows(options = {})
97
- Response.new(UserFollow, get('users/follows', options))
122
+ ## https://dev.twitch.tv/docs/api/reference#modify-channel-information
123
+ def modify_channel(options = {})
124
+ response = patch('channels', options)
125
+
126
+ return true if response.body.empty?
127
+
128
+ response.body
98
129
  end
99
130
 
100
- def get_users(options = {})
101
- Response.new(User, get('users', options))
131
+ ## https://dev.twitch.tv/docs/api/reference/#start-commercial
132
+ def start_commercial(options = {})
133
+ initialize_response nil, post('channels/commercial', options)
102
134
  end
103
135
 
104
- def update_user(options = {})
105
- Response.new(User, put('users', options))
136
+ ## https://dev.twitch.tv/docs/api/reference/#get-channel-editors
137
+ def get_channel_editors(options = {})
138
+ initialize_response Editor, get('channels/editors', options)
106
139
  end
107
140
 
108
- def get_videos(options = {})
109
- Response.new(Video, get('videos', options))
141
+ ## https://dev.twitch.tv/docs/api/reference/#search-categories
142
+ def search_categories(options = {})
143
+ initialize_response Category, get('search/categories', options)
110
144
  end
111
145
 
112
146
  private
113
147
 
114
- def get(resource, params)
115
- http_res = @conn.get(resource, params)
116
- finish(http_res)
117
- end
148
+ def initialize_response(data_class, http_response)
149
+ Response.new(data_class, http_response: http_response)
150
+ end
118
151
 
119
- def post(resource, params)
120
- http_res = @conn.post(resource, params)
121
- finish(http_res)
152
+ %w[get post put patch].each do |http_method|
153
+ define_method http_method do |resource, params|
154
+ request http_method, resource, params
122
155
  end
156
+ end
123
157
 
124
- def put(resource, params)
125
- http_res = @conn.put(resource, params)
126
- finish(http_res)
127
- end
158
+ def renew_authorization_header
159
+ CONNECTION.headers['Authorization'] = "Bearer #{tokens.access_token}"
160
+ end
161
+
162
+ def request(http_method, resource, params)
163
+ http_response = CONNECTION.public_send http_method, resource, params
128
164
 
129
- def finish(http_res)
130
- unless http_res.success?
131
- raise ApiError.new(http_res.status, http_res.body)
132
- end
165
+ if http_response.status == 401
166
+ renew_authorization_header
133
167
 
134
- {
135
- http_res: http_res,
136
- with_raw: @with_raw
137
- }
168
+ http_response = CONNECTION.public_send http_method, resource, params
138
169
  end
170
+
171
+ return http_response if http_response.success?
172
+
173
+ raise APIError.new(http_response.status, http_response.body)
174
+ end
139
175
  end
140
176
  end
data/lib/twitch/clip.rb CHANGED
@@ -1,9 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Twitch
2
4
  # A small segment of a broadcast captured by another user.
3
5
  class Clip
4
- # Fields to be converted from ISO 8601 string to a typed date.
5
- DATE_ATTRIBUTES = [:created_at]
6
-
7
6
  # ID of the clip.
8
7
  attr_reader :id
9
8
  # Title of the clip.
@@ -20,24 +19,23 @@ module Twitch
20
19
  attr_reader :view_count
21
20
  # Language of the originating broadcast.
22
21
  attr_reader :language
23
- # (User) ID of the clip's source broadcast.
22
+ # (User) ID of the clip's source broadcaster.
24
23
  attr_reader :broadcaster_id
24
+ # (User) name of the clip's source broadcaster
25
+ attr_reader :broadcaster_name
25
26
  # (User) ID of the clip's creator.
26
27
  attr_reader :creator_id
28
+ # (User) name of the clip's creator.
29
+ attr_reader :creator_name
27
30
  # ID of the game being played.
28
31
  attr_reader :game_id
29
32
  # ID of the archived broadcast (may not be available).
30
33
  attr_reader :video_id
31
34
 
32
35
  def initialize(attributes = {})
33
- attributes.each do |k, v|
34
- if DATE_ATTRIBUTES.include?(k.to_sym)
35
- instance_variable_set("@#{k}", Time.parse(v))
36
- else
37
- instance_variable_set("@#{k}", v)
38
- end
36
+ attributes.each do |key, value|
37
+ instance_variable_set "@#{key}", value
39
38
  end
40
39
  end
41
-
42
40
  end
43
- end
41
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Twitch
4
+ ## Data object for Twitch custom rewards
5
+ class CustomReward
6
+ ## Data object for images of Twitch custom rewards
7
+ class CustomRewardImage
8
+ # The URL to a small version of the image.
9
+ attr_reader :url_1x
10
+ # The URL to a medium version of the image.
11
+ attr_reader :url_2x
12
+ # The URL to a large version of the image.
13
+ attr_reader :url_4x
14
+
15
+ def initialize(attributes = {})
16
+ attributes.each do |key, value|
17
+ instance_variable_set "@#{key}", value
18
+ end
19
+ end
20
+ end
21
+
22
+ # The ID that uniquely identifies the broadcaster.
23
+ attr_reader :broadcaster_id
24
+ # The broadcaster’s login name.
25
+ attr_reader :broadcaster_login
26
+ # The broadcaster’s display name.
27
+ attr_reader :broadcaster_name
28
+ # The ID that uniquely identifies this custom reward.
29
+ attr_reader :id
30
+ # The title of the reward.
31
+ attr_reader :title
32
+ # The prompt shown to the viewer when they redeem the reward if user input is required
33
+ # (see the `is_user_input_required` field).
34
+ attr_reader :prompt
35
+ # The cost of the reward in Channel Points.
36
+ attr_reader :cost
37
+ # A set of custom images for the reward.
38
+ # This field is `nil` if the broadcaster didn’t upload images.
39
+ attr_reader :image
40
+ # A set of default images for the reward.
41
+ attr_reader :default_image
42
+ # The background color to use for the reward.
43
+ # The color is in Hex format (for example, `#00E5CB`).
44
+ attr_reader :background_color
45
+ # A Boolean value that determines whether the reward is enabled.
46
+ # Is `true` if enabled; otherwise, `false`. Disabled rewards aren’t shown to the user.
47
+ attr_reader :is_enabled
48
+ # A Boolean value that determines whether the user must enter information
49
+ # when redeeming the reward. Is `true` if the user is prompted.
50
+ attr_reader :is_user_input_required
51
+ # The settings used to determine whether to apply a maximum to the number of redemptions
52
+ # allowed per live stream.
53
+ attr_reader :max_per_stream_setting
54
+ # The settings used to determine whether to apply a maximum to the number of redemptions
55
+ # allowed per user per live stream.
56
+ attr_reader :max_per_user_per_stream_setting
57
+ # The settings used to determine whether to apply a cooldown period between redemptions
58
+ # and the length of the cooldown.
59
+ attr_reader :global_cooldown_setting
60
+ # A Boolean value that determines whether the reward is currently paused.
61
+ # Is `true` if the reward is paused. Viewers can’t redeem paused rewards.
62
+ attr_reader :is_paused
63
+ # A Boolean value that determines whether the reward is currently in stock.
64
+ # Is `true` if the reward is in stock. Viewers can’t redeem out of stock rewards.
65
+ attr_reader :is_in_stock
66
+ # A Boolean value that determines whether redemptions should be set to FULFILLED status
67
+ # immediately when a reward is redeemed. If `false`, status is set to UNFULFILLED
68
+ # and follows the normal request queue process.
69
+ attr_reader :should_redemptions_skip_request_queue
70
+ # The number of redemptions redeemed during the current live stream.
71
+ # The number counts against the `max_per_stream_setting` limit.
72
+ # This field is `nil` if the broadcaster’s stream isn’t live
73
+ # or `max_per_stream_setting` isn’t enabled.
74
+ attr_reader :redemptions_redeemed_current_stream
75
+ # The timestamp of when the cooldown period expires.
76
+ # Is `nil` if the reward isn’t in a cooldown state.
77
+ # See the `global_cooldown_setting` field.
78
+ attr_reader :cooldown_expires_at
79
+
80
+ IMAGE_ATTRS = %w[image default_image].freeze
81
+ private_constant :IMAGE_ATTRS
82
+
83
+ def initialize(attributes = {})
84
+ attributes.each do |key, value|
85
+ value = CustomRewardImage.new(value) if IMAGE_ATTRS.include?(key) && !value.nil?
86
+
87
+ instance_variable_set "@#{key}", value
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Twitch
4
+ ## A user who can edit broadcast content, settings, etc.
5
+ class Editor
6
+ ## An ID that uniquely identifies a user with editor permissions.
7
+ attr_reader :user_id
8
+
9
+ ## The user’s display name.
10
+ attr_reader :user_name
11
+
12
+ ## The date and time when the user became one of the broadcaster’s editors.
13
+ attr_reader :created_at
14
+
15
+ def initialize(attributes = {})
16
+ attributes.each do |key, value|
17
+ instance_variable_set "@#{key}", value
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Twitch
2
4
  # A URL that can be used to notify users of an entitlement.
3
5
  class EntitlementGrantUrl
@@ -8,6 +10,5 @@ module Twitch
8
10
  def initialize(attributes = {})
9
11
  @url = attributes['url']
10
12
  end
11
-
12
13
  end
13
- end
14
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Twitch
4
+ # A feature used to augment dynamic information on a stream.
5
+ class Extension
6
+ # ID of the extension.
7
+ attr_reader :id
8
+ # Version number of the extension.
9
+ attr_reader :version
10
+ # Name of the extension.
11
+ attr_reader :name
12
+ # Whether the extension is configured such that it can be activated.
13
+ attr_reader :can_activate
14
+ # The extension types that you can activate for this extension. Possible values are:
15
+ # `component`, `mobile`, `overlay`, `panel`
16
+ attr_reader :type
17
+
18
+ # Optional attributes for extensions from `get` methods results
19
+
20
+ # A Boolean value that determines the extension’s activation state.
21
+ # If false, the user has not configured this component extension.
22
+ attr_reader :active
23
+
24
+ # Optional attributes for extensions with `component` type
25
+
26
+ # The x-coordinate where the extension is placed.
27
+ attr_reader :x
28
+ # The y-coordinate where the extension is placed.
29
+ attr_reader :y
30
+
31
+ def initialize(attributes = {})
32
+ attributes.each do |key, value|
33
+ instance_variable_set "@#{key}", value
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Twitch
4
+ # A dictionary (Hash) of Extensions by their types and placements
5
+ class ExtensionsByTypes
6
+ # A dictionary that contains the data for a panel extension.
7
+ # The dictionary’s key is a sequential number beginning with 1.
8
+ # The following fields contain the panel’s data for each key.
9
+ attr_reader :panel
10
+
11
+ # A dictionary that contains the data for a video-overlay extension.
12
+ # The dictionary’s key is a sequential number beginning with 1.
13
+ # The following fields contain the overlay’s data for each key.
14
+ attr_reader :overlay
15
+
16
+ # A dictionary that contains the data for a video-component extension.
17
+ # The dictionary’s key is a sequential number beginning with 1.
18
+ # The following fields contain the component’s data for each key.
19
+ attr_reader :component
20
+
21
+ def initialize(attributes = {})
22
+ %w[panel overlay component].each do |type|
23
+ instance_variable_set(
24
+ "@#{type}",
25
+ attributes[type].transform_values do |extension_data|
26
+ Extension.new(extension_data)
27
+ end
28
+ )
29
+ end
30
+ end
31
+ end
32
+ end
data/lib/twitch/game.rb CHANGED
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Twitch
2
- # A filterable category for a stream.
4
+ # A filterable category for a stream.
3
5
  # (not necessarily limited to games, e.g. 'IRL')
4
6
  class Game
5
7
  # ID of the game.
@@ -8,7 +10,7 @@ module Twitch
8
10
  attr_reader :name
9
11
  # Box art URL template.
10
12
  #
11
- # Substitute the {width} and {height} string tokens
13
+ # Substitute the {width} and {height} string tokens
12
14
  # with your desired numeric values.
13
15
  attr_reader :box_art_url
14
16
 
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Twitch
2
- # A
4
+ # Data object for `/analytics/games` requests
3
5
  class GameAnalytic
4
6
  # ID of the game requested.
5
7
  attr_reader :game_id
@@ -11,4 +13,4 @@ module Twitch
11
13
  @url = attributes['URL']
12
14
  end
13
15
  end
14
- end
16
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Twitch
4
+ # Information about a moderation action.
5
+ # The action is determined based on the `event_type` field.
6
+ class ModerationEvent
7
+ # Fields to be converted from ISO 8601 string to a typed date.
8
+ DATE_ATTRIBUTES = %i[event_timestamp].freeze
9
+
10
+ # ID of the moderation event.
11
+ attr_reader :id
12
+ # Event type.
13
+ # The `moderation.user` prefix is for user bans and unbans in a channel.
14
+ # The `moderation.moderator` prefix is for addition and removal of moderators in a channel.
15
+ attr_reader :event_type
16
+ # Time at which the event happened.
17
+ attr_reader :event_timestamp
18
+ # Version of the endpoint the data was retrieved from.
19
+ attr_reader :version
20
+ # A hash containing information about the moderation action.
21
+ attr_reader :event_data
22
+
23
+ def initialize(attributes = {})
24
+ attributes.each do |key, value|
25
+ if DATE_ATTRIBUTES.include?(key.to_sym)
26
+ instance_variable_set "@#{key}", Time.parse(value)
27
+ else
28
+ instance_variable_set "@#{key}", value
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Twitch
4
+ # A user who wields some form of power in a broadcaster's Twitch chat.
5
+ # This is simply a user ID/name pair.
6
+ class Moderator
7
+ # User ID of the moderator.
8
+ attr_reader :user_id
9
+ # The user’s login name.
10
+ attr_reader :user_login
11
+ # The user’s display name.
12
+ attr_reader :user_name
13
+
14
+ def initialize(attributes = {})
15
+ attributes.each do |key, value|
16
+ instance_variable_set "@#{key}", value
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Twitch
4
+ # Data object for Twitch users
5
+ class Redemption
6
+ # ID of the broadcaster.
7
+ attr_reader :broadcaster_id
8
+ # Unformatted (lowercase) username of thebroadcaster.
9
+ attr_reader :broadcaster_login
10
+ # Formatted username of the broadcaster.
11
+ attr_reader :broadcaster_display_name
12
+ # ID of the redemption.
13
+ attr_reader :id
14
+ # ID of the user.
15
+ attr_reader :user_id
16
+ # Unformatted (lowercase) username of the user.
17
+ attr_reader :user_login
18
+ # Formatted username of the user.
19
+ attr_reader :user_name
20
+ # The associated reward being redeemed
21
+ attr_reader :reward
22
+ # The user input (e.g. text) if allowed by the reward
23
+ attr_reader :user_input
24
+ # The status of the redemption's fulfillment
25
+ attr_reader :status
26
+ # The timestamp of the redemption
27
+ attr_reader :redeemed_at
28
+
29
+ def initialize(attributes = {})
30
+ attributes.each do |key, value|
31
+ instance_variable_set "@#{key}", value
32
+ end
33
+ end
34
+ end
35
+ end