twitch-api 0.4.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 +3 -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 +127 -100
  20. data/lib/twitch/clip.rb +5 -11
  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 +9 -11
  33. data/lib/twitch/stream_marker.rb +7 -8
  34. data/lib/twitch/stream_metadata.rb +27 -16
  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 +4 -2
  39. data/lib/twitch/version.rb +3 -1
  40. data/lib/twitch/video.rb +7 -13
  41. data/lib/twitch-api.rb +3 -4
  42. metadata +57 -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,149 +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_marker"
13
- require "twitch/stream_metadata"
14
- require "twitch/user"
15
- require "twitch/user_follow"
16
- 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'
17
34
 
18
35
  module Twitch
36
+ # Core class for requests
19
37
  class Client
20
- # Helix API endpoint.
21
- 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
22
54
 
23
55
  # Initializes a Twitch client.
24
- #
25
- # - client_id [String] The client ID.
26
- # Used as the Client-ID header in a request.
27
- # - access_token [String] An access token.
28
- # Used as the Authorization header in a request.
29
- # Any "Bearer " prefix will be stripped.
30
- # - with_raw [Boolean] Whether to include raw HTTP response
31
- # Intended for testing/checking API results
32
- def initialize(client_id: nil, access_token: nil, with_raw: false)
33
- if client_id.nil? && access_token.nil?
34
- raise "An identifier token (client ID or bearer token) is required"
35
- elsif !!client_id && !!access_token
36
- warn(%{WARNING:
37
- It is recommended that only one identifier token is specified.
38
- Unpredictable behavior may follow.})
39
- 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
40
61
 
41
- headers = {
42
- "User-Agent": "twitch-api ruby client #{Twitch::VERSION}"
43
- }
44
- unless client_id.nil?
45
- headers["Client-ID"] = client_id
46
- end
47
- unless access_token.nil?
48
- access_token = access_token.gsub(/^Bearer /, "")
49
- headers["Authorization"] = "Bearer #{access_token}"
50
- end
51
-
52
- @conn = Faraday.new(API_ENDPOINT, { headers: headers }) do |faraday|
53
- faraday.request :json
54
- faraday.response :json
55
- faraday.adapter Faraday.default_adapter
56
- end
62
+ CONNECTION.headers['Client-ID'] = self.tokens.client.client_id
57
63
 
58
- @with_raw = with_raw
64
+ renew_authorization_header
59
65
  end
60
66
 
61
67
  def create_clip(options = {})
62
- Response.new(Clip, post('clips', options))
68
+ initialize_response Clip, post('clips', options)
63
69
  end
64
70
 
65
71
  def create_entitlement_grant_url(options = {})
66
- Response.new(EntitlementGrantUrl, post('entitlements/upload', options))
67
- end
68
-
69
- def create_stream_marker(options = {})
70
- Response.new(StreamMarker, post('streams/markers', options))
72
+ initialize_response EntitlementGrantUrl, post('entitlements/upload', options)
71
73
  end
72
74
 
73
75
  def get_clips(options = {})
74
- Response.new(Clip, get('clips', options))
76
+ initialize_response Clip, get('clips', options)
75
77
  end
76
78
 
77
79
  def get_bits_leaderboard(options = {})
78
- Response.new(BitsLeader, get('bits/leaderboard', options))
80
+ initialize_response BitsLeader, get('bits/leaderboard', options)
79
81
  end
80
82
 
81
- def get_games(options = {})
82
- Response.new(Game, get('games', options))
83
+ def get_cheermotes(options = {})
84
+ initialize_response Cheermote, get('bits/cheermotes', options)
83
85
  end
84
86
 
85
- def get_top_games(options = {})
86
- Response.new(Game, get('games/top', options))
87
- end
87
+ require_relative 'client/extensions'
88
+ include Extensions
88
89
 
89
- def get_game_analytics(options = {})
90
- Response.new(GameAnalytic, get('analytics/games', options))
91
- end
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
92
98
 
93
- def get_stream_markers(options = {})
94
- Response.new(StreamMarkerResponse, get('streams/markers', options))
99
+ require_relative 'client/subscriptions'
100
+ include Subscriptions
101
+
102
+ def get_videos(options = {})
103
+ initialize_response Video, get('videos', options)
95
104
  end
96
105
 
97
- def get_streams(options = {})
98
- 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)
99
115
  end
100
116
 
101
- def get_streams_metadata(options = {})
102
- 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)
103
120
  end
104
121
 
105
- def get_users_follows(options = {})
106
- 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
107
129
  end
108
130
 
109
- def get_users(options = {})
110
- 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)
111
134
  end
112
135
 
113
- def update_user(options = {})
114
- 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)
115
139
  end
116
140
 
117
- def get_videos(options = {})
118
- 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)
119
144
  end
120
145
 
121
146
  private
122
147
 
123
- def get(resource, params)
124
- http_res = @conn.get(resource, params)
125
- finish(http_res)
126
- end
148
+ def initialize_response(data_class, http_response)
149
+ Response.new(data_class, http_response: http_response)
150
+ end
127
151
 
128
- def post(resource, params)
129
- http_res = @conn.post(resource, params)
130
- 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
131
155
  end
156
+ end
132
157
 
133
- def put(resource, params)
134
- http_res = @conn.put(resource, params)
135
- finish(http_res)
136
- end
158
+ def renew_authorization_header
159
+ CONNECTION.headers['Authorization'] = "Bearer #{tokens.access_token}"
160
+ end
137
161
 
138
- def finish(http_res)
139
- unless http_res.success?
140
- raise ApiError.new(http_res.status, http_res.body)
141
- end
162
+ def request(http_method, resource, params)
163
+ http_response = CONNECTION.public_send http_method, resource, params
142
164
 
143
- {
144
- http_res: http_res,
145
- with_raw: @with_raw
146
- }
165
+ if http_response.status == 401
166
+ renew_authorization_header
167
+
168
+ http_response = CONNECTION.public_send http_method, resource, params
147
169
  end
170
+
171
+ return http_response if http_response.success?
172
+
173
+ raise APIError.new(http_response.status, http_response.body)
174
+ end
148
175
  end
149
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.
@@ -34,14 +33,9 @@ module Twitch
34
33
  attr_reader :video_id
35
34
 
36
35
  def initialize(attributes = {})
37
- attributes.each do |k, v|
38
- if DATE_ATTRIBUTES.include?(k.to_sym)
39
- instance_variable_set("@#{k}", Time.parse(v))
40
- else
41
- instance_variable_set("@#{k}", v)
42
- end
36
+ attributes.each do |key, value|
37
+ instance_variable_set "@#{key}", value
43
38
  end
44
39
  end
45
-
46
40
  end
47
- 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