kappa 0.3.0 → 0.4.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.
- data/README.md +35 -23
- data/lib/kappa.rb +2 -1
- data/lib/kappa/channel.rb +100 -27
- data/lib/kappa/configuration.rb +54 -0
- data/lib/kappa/connection.rb +22 -39
- data/lib/kappa/game.rb +43 -20
- data/lib/kappa/id_equality.rb +1 -1
- data/lib/kappa/images.rb +11 -1
- data/lib/kappa/query.rb +22 -0
- data/lib/kappa/stream.rb +69 -47
- data/lib/kappa/team.rb +50 -28
- data/lib/kappa/user.rb +56 -33
- data/lib/kappa/version.rb +2 -2
- data/lib/kappa/video.rb +61 -39
- metadata +8 -6
- data/lib/kappa/twitch.rb +0 -13
data/README.md
CHANGED
@@ -7,6 +7,7 @@ Kappa is the Ruby library for interfacing with the [Twitch.tv API](https://githu
|
|
7
7
|
[](https://gemnasium.com/schmich/kappa)
|
8
8
|
[](https://coveralls.io/r/schmich/kappa?branch=master)
|
9
9
|
[](https://codeclimate.com/github/schmich/kappa)
|
10
|
+
[](https://bitdeli.com/free "Bitdeli")
|
10
11
|
|
11
12
|
## Getting Started
|
12
13
|
|
@@ -17,10 +18,22 @@ gem install kappa
|
|
17
18
|
```ruby
|
18
19
|
require 'kappa'
|
19
20
|
|
20
|
-
|
21
|
+
frag = Twitch.channels.get('lethalfrag')
|
22
|
+
puts frag.streaming?
|
23
|
+
```
|
24
|
+
|
25
|
+
## Configuration
|
26
|
+
|
27
|
+
When making requests to Twitch, you must specify a client ID for your application.
|
28
|
+
If you do not specify a client ID, Twitch reserves the right to rate-limit your application
|
29
|
+
without warning.
|
30
|
+
|
31
|
+
Your client ID can be specified through configuration, for example:
|
21
32
|
|
22
|
-
|
23
|
-
|
33
|
+
```ruby
|
34
|
+
Twitch.configure do |config|
|
35
|
+
config.client_id = 'sc2daily-v1.0.0'
|
36
|
+
end
|
24
37
|
```
|
25
38
|
|
26
39
|
## Overview
|
@@ -32,7 +45,7 @@ Channels serve as the home location for a [user's](#users) content. Channels hav
|
|
32
45
|
See also [`Channel`](http://rdoc.info/gems/kappa/Kappa/V2/Channel) documentation.
|
33
46
|
|
34
47
|
```ruby
|
35
|
-
c =
|
48
|
+
c = Twitch.channels.get('destiny')
|
36
49
|
c.nil? # => false (channel exists)
|
37
50
|
c.stream # => #<Kappa::V2::Stream> (current live stream)
|
38
51
|
c.url # => "http://www.twitch.tv/destiny"
|
@@ -49,7 +62,7 @@ Streams are video broadcasts that are currently live. They belong to a [user](#u
|
|
49
62
|
See also [`Stream`](http://rdoc.info/gems/kappa/Kappa/V2/Stream) and [`Streams`](http://rdoc.info/gems/kappa/Kappa/V2/Streams) documentation.
|
50
63
|
|
51
64
|
```ruby
|
52
|
-
s =
|
65
|
+
s = Twitch.streams.get('idrajit')
|
53
66
|
s.nil? # => false (currently live)
|
54
67
|
s.game_name # => "StarCraft II: Heart of the Swarm"
|
55
68
|
s.viewer_count # => 7267
|
@@ -63,7 +76,7 @@ These are members of the Twitch community who have a Twitch account. If broadcas
|
|
63
76
|
See also [`User`](http://rdoc.info/gems/kappa/Kappa/V2/User) documentation.
|
64
77
|
|
65
78
|
```ruby
|
66
|
-
u =
|
79
|
+
u = Twitch.users.get('snoopeh')
|
67
80
|
u.nil? # => false (user exists)
|
68
81
|
u.channel # => #<Kappa::V2::Channel>
|
69
82
|
u.following.map(&:name) # => ["national_esl1", "dreamhacklol", "riotgames"]
|
@@ -76,7 +89,7 @@ Videos are broadcasts or highlights owned by a [channel](#channels). Broadcasts
|
|
76
89
|
See also [`Video`](http://rdoc.info/gems/kappa/Kappa/V2/Video) and [`Videos`](http://rdoc.info/gems/kappa/Kappa/V2/Videos) documentation.
|
77
90
|
|
78
91
|
```ruby
|
79
|
-
v =
|
92
|
+
v = Twitch.videos.get('a395995729')
|
80
93
|
v.nil? # => false (video exists)
|
81
94
|
v.title # => "DreamHack Open Stockholm 26-27 April"
|
82
95
|
v.game_name # => "StarCraft II: Heart of the Swarm"
|
@@ -91,7 +104,7 @@ Teams are an organization of [channels](#channels).
|
|
91
104
|
See also [`Team`](http://rdoc.info/gems/kappa/Kappa/V2/Team) documentation.
|
92
105
|
|
93
106
|
```ruby
|
94
|
-
t =
|
107
|
+
t = Twitch.teams.get('teamliquid')
|
95
108
|
t.nil? # => false (team exists)
|
96
109
|
t.display_name # => "TeamLiquid"
|
97
110
|
t.info # => "TeamLiquid is awesome. and esports. video games. \n\n"
|
@@ -105,12 +118,12 @@ Games are categories (e.g. League of Legends, Diablo 3) used by [streams](#strea
|
|
105
118
|
See also [`Game`](http://rdoc.info/gems/kappa/Kappa/V2/Game), [`Games`](http://rdoc.info/gems/kappa/Kappa/V2/Games), and [`GameSuggestion`](http://rdoc.info/gems/kappa/Kappa/V2/GameSuggestion) documentation.
|
106
119
|
|
107
120
|
```ruby
|
108
|
-
top =
|
121
|
+
top = Twitch.games.top(:limit => 3)
|
109
122
|
top.map(&:name) # => ["League of Legends", "Dota 2", "StarCraft II: Heart of the Swarm"]
|
110
123
|
```
|
111
124
|
|
112
125
|
```ruby
|
113
|
-
g =
|
126
|
+
g = Twitch.games.top(:limit => 1).first
|
114
127
|
g.name # => "League of Legends"
|
115
128
|
g.channel_count # => 906
|
116
129
|
g.viewer_count # => 79223
|
@@ -118,7 +131,7 @@ g.box_images.medium_url # =>"http://static-cdn.jtvnw.net/ttv-boxart/League%20of
|
|
118
131
|
```
|
119
132
|
|
120
133
|
```ruby
|
121
|
-
s =
|
134
|
+
s = Twitch.games.find(:name => 'diablo', :live => true)
|
122
135
|
s.map(&:name) # => ["Diablo III", "Diablo II", "Diablo", "Diablo II: Lord of Destruction"]
|
123
136
|
s.map(&:popularity) # => [120, 4, 1, 1]
|
124
137
|
```
|
@@ -149,26 +162,25 @@ backwards-compatible bugfixes will result in a new patch version (e.g. `x.x.1` t
|
|
149
162
|
|
150
163
|
### Twitch API versions
|
151
164
|
|
152
|
-
Twitch supports multiple versions of their API simultaneously, with each version potentially providing different data
|
165
|
+
Twitch supports multiple versions of their API simultaneously, with each version potentially providing different data
|
166
|
+
and behaving differently. Because of this, you can specify which version of the Twitch API you wish to use.
|
167
|
+
This is done through Kappa configuration.
|
153
168
|
|
154
|
-
For example, if you want to use the
|
169
|
+
For example, if you want to use the V2 Twitch API:
|
155
170
|
|
156
171
|
```ruby
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
```
|
162
|
-
```ruby
|
163
|
-
# Option 2: Specify the full class name each time.
|
164
|
-
c = Kappa::V2::Channel.get('day9tv')
|
165
|
-
u = Kappa::V2::User.get('artosis')
|
172
|
+
Twitch.configure do |config|
|
173
|
+
config.client_id = 'sc2daily-v1.0.0'
|
174
|
+
config.api = Twitch::V2
|
175
|
+
end
|
166
176
|
```
|
167
177
|
|
178
|
+
`Twitch::V2` is the default and is currently the only supported API version.
|
179
|
+
|
168
180
|
## Contributing
|
169
181
|
|
170
182
|
- [Fork and clone the repo.](http://help.github.com/fork-a-repo/)
|
171
|
-
- [Create a branch for your changes.](http://
|
183
|
+
- [Create a branch for your changes.](http://git-scm.com/book/en/Git-Branching-Basic-Branching-and-Merging)
|
172
184
|
- Run `bundle install` to install development requirements.
|
173
185
|
- Implement your feature or bug fix.
|
174
186
|
- Add specs under the `spec` folder to prevent regressions or to test new code.
|
data/lib/kappa.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'kappa/id_equality'
|
2
2
|
require 'kappa/proxy'
|
3
3
|
require 'kappa/connection'
|
4
|
+
require 'kappa/configuration'
|
5
|
+
require 'kappa/query'
|
4
6
|
require 'kappa/channel'
|
5
7
|
require 'kappa/stream'
|
6
8
|
require 'kappa/game'
|
@@ -8,5 +10,4 @@ require 'kappa/video'
|
|
8
10
|
require 'kappa/team'
|
9
11
|
require 'kappa/user'
|
10
12
|
require 'kappa/images'
|
11
|
-
require 'kappa/twitch'
|
12
13
|
require 'kappa/version'
|
data/lib/kappa/channel.rb
CHANGED
@@ -1,19 +1,20 @@
|
|
1
1
|
require 'cgi'
|
2
2
|
require 'time'
|
3
3
|
|
4
|
-
module
|
4
|
+
module Twitch::V2
|
5
5
|
# Channels serve as the home location for a user's content. Channels have a stream, can run
|
6
6
|
# commercials, store videos, display information and status, and have a customized page including
|
7
7
|
# banners and backgrounds.
|
8
|
-
# @see
|
8
|
+
# @see Channels#get Channels#get
|
9
|
+
# @see Channels
|
9
10
|
# @see Stream
|
10
11
|
# @see User
|
11
12
|
class Channel
|
12
|
-
include
|
13
|
-
include Kappa::IdEquality
|
13
|
+
include Twitch::IdEquality
|
14
14
|
|
15
15
|
# @private
|
16
|
-
def initialize(hash)
|
16
|
+
def initialize(hash, query)
|
17
|
+
@query = query
|
17
18
|
@id = hash['_id']
|
18
19
|
@background_url = hash['background']
|
19
20
|
@banner_url = hash['banner']
|
@@ -35,21 +36,6 @@ module Kappa::V2
|
|
35
36
|
end
|
36
37
|
end
|
37
38
|
|
38
|
-
# Get a channel by name.
|
39
|
-
# @param channel_name [String] The name of the channel to get. This is the same as the stream or user name.
|
40
|
-
# @return [Channel] A valid `Channel` object if the channel exists, `nil` otherwise.
|
41
|
-
def self.get(channel_name)
|
42
|
-
encoded_name = CGI.escape(channel_name)
|
43
|
-
json = connection.get("channels/#{encoded_name}")
|
44
|
-
|
45
|
-
# HTTP 422 can happen if the channel is associated with a Justin.tv account.
|
46
|
-
if !json || json['status'] == 404 || json['status'] == 422
|
47
|
-
nil
|
48
|
-
else
|
49
|
-
new(json)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
39
|
# Does this channel have mature content? This flag is specified by the owner of the channel.
|
54
40
|
# @return [Boolean] `true` if the channel has mature content, `false` otherwise.
|
55
41
|
def mature?
|
@@ -61,7 +47,7 @@ module Kappa::V2
|
|
61
47
|
# @return [Stream] Live stream object for this channel, or `nil` if the channel is not currently streaming.
|
62
48
|
# @see #streaming?
|
63
49
|
def stream
|
64
|
-
|
50
|
+
@query.streams.get(@name)
|
65
51
|
end
|
66
52
|
|
67
53
|
# Does this channel currently have a live stream?
|
@@ -76,11 +62,13 @@ module Kappa::V2
|
|
76
62
|
# @note This incurs an additional web request.
|
77
63
|
# @return [User] The user that owns this channel.
|
78
64
|
def user
|
79
|
-
|
65
|
+
@query.users.get(@name)
|
80
66
|
end
|
81
67
|
|
82
68
|
# Get the users following this channel.
|
83
69
|
# @note The number of followers is potentially very large, so it's recommended that you specify a `:limit`.
|
70
|
+
# @example
|
71
|
+
# f = c.followers(:limit => 20)
|
84
72
|
# @param options [Hash] Filter criteria.
|
85
73
|
# @option options [Fixnum] :limit (none) Limit on the number of results returned.
|
86
74
|
# @option options [Fixnum] :offset (0) Offset into the result set to begin enumeration.
|
@@ -88,56 +76,141 @@ module Kappa::V2
|
|
88
76
|
# @see https://github.com/justintv/Twitch-API/blob/master/v2_resources/channels.md#get-channelschannelfollows GET /channels/:channel/follows
|
89
77
|
# @return [Array<User>] List of users following this channel.
|
90
78
|
def followers(options = {})
|
91
|
-
|
92
|
-
|
93
|
-
return connection.accumulate(
|
79
|
+
return @query.connection.accumulate(
|
94
80
|
:path => "channels/#{@name}/follows",
|
95
|
-
:params => params,
|
96
81
|
:json => 'follows',
|
97
82
|
:sub_json => 'user',
|
98
|
-
:
|
83
|
+
:create => -> hash { User.new(hash, @query) },
|
99
84
|
:limit => options[:limit],
|
100
85
|
:offset => options[:offset]
|
101
86
|
)
|
102
87
|
end
|
103
88
|
|
89
|
+
# Get the videos for a channel, most recently created first.
|
90
|
+
# @note This incurs additional web requests.
|
91
|
+
# @example
|
92
|
+
# c = Twitch.channels.get('idrajit')
|
93
|
+
# v = c.videos(:type => :broadcasts)
|
94
|
+
# @param options [Hash] Filter criteria.
|
95
|
+
# @option options [Symbol] :type (:highlights) The type of videos to return. Valid values are `:broadcasts`, `:highlights`.
|
96
|
+
# @option options [Fixnum] :limit (none) Limit on the number of results returned.
|
97
|
+
# @option options [Fixnum] :offset (0) Offset into the result set to begin enumeration.
|
98
|
+
# @see Video
|
99
|
+
# @see https://github.com/justintv/Twitch-API/blob/master/v2_resources/videos.md#get-channelschannelvideos GET /channels/:channel/videos
|
100
|
+
# @raise [ArgumentError] If `:type` is not one of `:broadcasts` or `:highlights`.
|
101
|
+
# @return [Array<Video>] List of videos for the channel.
|
102
|
+
def videos(options = {})
|
103
|
+
params = {}
|
104
|
+
|
105
|
+
type = options[:type] || :highlights
|
106
|
+
if !type.nil?
|
107
|
+
if ![:broadcasts, :highlights].include?(type)
|
108
|
+
raise ArgumentError, 'type'
|
109
|
+
end
|
110
|
+
|
111
|
+
params[:broadcasts] = (type == :broadcasts)
|
112
|
+
end
|
113
|
+
|
114
|
+
return @query.connection.accumulate(
|
115
|
+
:path => "channels/#{@name}/videos",
|
116
|
+
:params => params,
|
117
|
+
:json => 'videos',
|
118
|
+
:create => -> hash { Video.new(hash, @query) },
|
119
|
+
:limit => options[:limit],
|
120
|
+
:offset => options[:offset]
|
121
|
+
)
|
122
|
+
end
|
123
|
+
|
124
|
+
# @example
|
125
|
+
# 23460970
|
104
126
|
# @return [Fixnum] Unique Twitch ID.
|
105
127
|
attr_reader :id
|
106
128
|
|
129
|
+
# @example
|
130
|
+
# "http://static-cdn.jtvnw.net/jtv_user_pictures/lethalfrag-channel_background_image-833a4324bc698c9b.jpeg"
|
107
131
|
# @return [String] URL for background image.
|
108
132
|
attr_reader :background_url
|
109
133
|
|
134
|
+
# @example
|
135
|
+
# "http://static-cdn.jtvnw.net/jtv_user_pictures/lethalfrag-channel_header_image-463a4670c91c2b61-640x125.jpeg"
|
110
136
|
# @return [String] URL for banner image.
|
111
137
|
attr_reader :banner_url
|
112
138
|
|
139
|
+
# @example
|
140
|
+
# 2011-07-15 07:53:58 UTC
|
113
141
|
# @return [Time] When the channel was created (UTC).
|
114
142
|
attr_reader :created_at
|
115
143
|
|
144
|
+
# @example
|
145
|
+
# "Lethalfrag"
|
146
|
+
# @see #name
|
116
147
|
# @return [String] User-friendly display name. This name is used for the channel's page title.
|
117
148
|
attr_reader :display_name
|
118
149
|
|
150
|
+
# @example
|
151
|
+
# "Super Meat Boy"
|
119
152
|
# @return [String] Name of the primary game for this channel.
|
120
153
|
attr_reader :game_name
|
121
154
|
|
155
|
+
# @example
|
156
|
+
# "http://static-cdn.jtvnw.net/jtv_user_pictures/lethalfrag-profile_image-050adf252718823b-300x300.png"
|
122
157
|
# @return [String] URL for the logo image.
|
123
158
|
attr_reader :logo_url
|
124
159
|
|
160
|
+
# @example
|
161
|
+
# "lethalfrag"
|
162
|
+
# @see #display_name
|
125
163
|
# @return [String] Unique Twitch name.
|
126
164
|
attr_reader :name
|
127
165
|
|
166
|
+
# @example
|
167
|
+
# "(Day 563/731) | Dinner and a Game (Cooking at http://twitch.tv/lookatmychicken)"
|
128
168
|
# @return [String] Current status set by the channel's owner.
|
129
169
|
attr_reader :status
|
130
170
|
|
171
|
+
# @example
|
172
|
+
# 2013-07-21 05:27:58 UTC
|
131
173
|
# @return [Time] When the channel was last updated (UTC). For example, when a stream is started, its channel is updated.
|
132
174
|
attr_reader :updated_at
|
133
175
|
|
176
|
+
# @example
|
177
|
+
# "http://www.twitch.tv/lethalfrag"
|
134
178
|
# @return [String] The URL for the channel's main page.
|
135
179
|
attr_reader :url
|
136
180
|
|
181
|
+
# @example
|
182
|
+
# "http://static-cdn.jtvnw.net/jtv_user_pictures/lethalfrag-channel_offline_image-3b801b2ccc11830b-640x360.jpeg"
|
137
183
|
# @return [String] URL for the image shown when the stream is offline.
|
138
184
|
attr_reader :video_banner_url
|
139
185
|
|
186
|
+
# @see Team
|
140
187
|
# @return [Array<Team>] The list of teams that this channel is associated with. Not all channels have associated teams.
|
141
188
|
attr_reader :teams
|
142
189
|
end
|
190
|
+
|
191
|
+
# Query class for finding channels.
|
192
|
+
# @see Channel
|
193
|
+
class Channels
|
194
|
+
# @private
|
195
|
+
def initialize(query)
|
196
|
+
@query = query
|
197
|
+
end
|
198
|
+
|
199
|
+
# Get a channel by name.
|
200
|
+
# @example
|
201
|
+
# c = Twitch.channels.get('day9tv')
|
202
|
+
# @param channel_name [String] The name of the channel to get. This is the same as the stream or user name.
|
203
|
+
# @return [Channel] A valid `Channel` object if the channel exists, `nil` otherwise.
|
204
|
+
def get(channel_name)
|
205
|
+
encoded_name = CGI.escape(channel_name)
|
206
|
+
json = @query.connection.get("channels/#{encoded_name}")
|
207
|
+
|
208
|
+
# HTTP 422 can happen if the channel is associated with a Justin.tv account.
|
209
|
+
if !json || json['status'] == 404 || json['status'] == 422
|
210
|
+
nil
|
211
|
+
else
|
212
|
+
Channel.new(json, @query)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
143
216
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
module Twitch
|
4
|
+
@query = nil
|
5
|
+
|
6
|
+
# Configure global settings for interacting with Twitch. Future requests will use these settings.
|
7
|
+
# @example
|
8
|
+
# Twitch.configure do |config|
|
9
|
+
# config.client_id = 'sc2daily-v1.0.0'
|
10
|
+
# config.api = Twitch::V2
|
11
|
+
# end
|
12
|
+
def self.configure(&block)
|
13
|
+
@query = instance(&block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.instance(&block)
|
17
|
+
config = Configuration.new
|
18
|
+
config.instance_eval(&block)
|
19
|
+
connection = config.create(:Connection, config.client_id)
|
20
|
+
return config.create(:Query, connection)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.method_missing(*args)
|
24
|
+
@query ||= create_default_query
|
25
|
+
@query.send(*args)
|
26
|
+
end
|
27
|
+
|
28
|
+
# @private
|
29
|
+
class Configuration
|
30
|
+
def initialize
|
31
|
+
@api = Twitch::V2
|
32
|
+
end
|
33
|
+
|
34
|
+
def client_id
|
35
|
+
# Generate a random client_id if it's not already set.
|
36
|
+
@client_id ||= "Kappa-%s" % SecureRandom.uuid
|
37
|
+
@client_id
|
38
|
+
end
|
39
|
+
|
40
|
+
def create(symbol, *args)
|
41
|
+
@api.const_get(symbol).new(*args)
|
42
|
+
end
|
43
|
+
|
44
|
+
attr_writer :client_id
|
45
|
+
attr_accessor :api
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
def self.create_default_query
|
50
|
+
config = Configuration.new
|
51
|
+
connection = config.create(:Connection, config.client_id)
|
52
|
+
return config.create(:Query, connection)
|
53
|
+
end
|
54
|
+
end
|
data/lib/kappa/connection.rb
CHANGED
@@ -1,30 +1,27 @@
|
|
1
1
|
require 'httparty'
|
2
2
|
require 'addressable/uri'
|
3
|
-
require 'securerandom'
|
4
3
|
require 'json'
|
5
|
-
require 'singleton'
|
6
4
|
require 'set'
|
7
5
|
|
8
|
-
module
|
6
|
+
module Twitch
|
9
7
|
# @private
|
10
|
-
class
|
8
|
+
class Connection
|
11
9
|
include HTTParty
|
12
10
|
|
13
|
-
def initialize(base_url = DEFAULT_BASE_URL)
|
11
|
+
def initialize(client_id, base_url = DEFAULT_BASE_URL)
|
12
|
+
@client_id = client_id
|
14
13
|
@base_url = Addressable::URI.parse(base_url)
|
15
|
-
|
16
|
-
uuid = SecureRandom.uuid
|
17
|
-
@client_id = "Kappa-v1-#{uuid}"
|
18
14
|
end
|
19
15
|
|
20
16
|
def get(path, query = nil)
|
21
17
|
request_url = @base_url + path
|
22
18
|
|
23
|
-
|
19
|
+
all_headers = {
|
24
20
|
'Client-ID' => @client_id,
|
25
|
-
|
21
|
+
'Kappa-Version' => Twitch::VERSION
|
22
|
+
}.merge(headers())
|
26
23
|
|
27
|
-
response = self.class.get(request_url, :headers =>
|
24
|
+
response = self.class.get(request_url, :headers => all_headers, :query => query)
|
28
25
|
|
29
26
|
json = response.body
|
30
27
|
return JSON.parse(json)
|
@@ -35,11 +32,16 @@ module Kappa
|
|
35
32
|
params = options[:params] || {}
|
36
33
|
json = options[:json]
|
37
34
|
sub_json = options[:sub_json]
|
38
|
-
|
35
|
+
create = options[:create]
|
39
36
|
|
40
37
|
raise ArgumentError, 'json' if json.nil?
|
41
38
|
raise ArgumentError, 'path' if path.nil?
|
42
|
-
raise ArgumentError, '
|
39
|
+
raise ArgumentError, 'create' if create.nil?
|
40
|
+
|
41
|
+
if create.is_a? Class
|
42
|
+
klass = create
|
43
|
+
create = -> hash { klass.new(hash) }
|
44
|
+
end
|
43
45
|
|
44
46
|
total_limit = options[:limit]
|
45
47
|
page_limit = [total_limit || 100, 100].min
|
@@ -48,11 +50,11 @@ module Kappa
|
|
48
50
|
objects = []
|
49
51
|
ids = Set.new
|
50
52
|
|
51
|
-
|
53
|
+
paginate(path, page_limit, offset, params) do |response_json|
|
52
54
|
current_objects = response_json[json]
|
53
55
|
current_objects.each do |object_json|
|
54
56
|
object_json = object_json[sub_json] if sub_json
|
55
|
-
object =
|
57
|
+
object = create.call(object_json)
|
56
58
|
if ids.add?(object.id)
|
57
59
|
objects << object
|
58
60
|
if !total_limit.nil? && (objects.count == total_limit)
|
@@ -67,7 +69,7 @@ module Kappa
|
|
67
69
|
return objects
|
68
70
|
end
|
69
71
|
|
70
|
-
def
|
72
|
+
def paginate(path, limit, offset, params = {})
|
71
73
|
path_uri = Addressable::URI.parse(path)
|
72
74
|
query = { 'limit' => limit, 'offset' => offset }
|
73
75
|
path_uri.query_values ||= {}
|
@@ -91,7 +93,7 @@ module Kappa
|
|
91
93
|
break if total && (offset > total)
|
92
94
|
|
93
95
|
request_url = next_url
|
94
|
-
json = get(request_url)
|
96
|
+
json = get(request_url, params)
|
95
97
|
end
|
96
98
|
end
|
97
99
|
|
@@ -100,30 +102,11 @@ module Kappa
|
|
100
102
|
end
|
101
103
|
end
|
102
104
|
|
103
|
-
module
|
105
|
+
module Twitch::V2
|
104
106
|
# @private
|
105
|
-
|
106
|
-
|
107
|
-
include Singleton
|
108
|
-
|
109
|
-
private
|
110
|
-
def custom_headers
|
107
|
+
class Connection < Twitch::Connection
|
108
|
+
def headers
|
111
109
|
{ 'Accept' => 'application/vnd.twitchtv.v2+json' }
|
112
110
|
end
|
113
|
-
end
|
114
|
-
|
115
|
-
def self.included(base)
|
116
|
-
base.extend(ClassMethods)
|
117
|
-
end
|
118
|
-
|
119
|
-
def connection
|
120
|
-
Impl.instance
|
121
|
-
end
|
122
|
-
|
123
|
-
module ClassMethods
|
124
|
-
def connection
|
125
|
-
Impl.instance
|
126
|
-
end
|
127
|
-
end
|
128
111
|
end
|
129
112
|
end
|