kappa 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Dependency Status](https://gemnasium.com/schmich/kappa.png)](https://gemnasium.com/schmich/kappa)
|
8
8
|
[![Coverage Status](https://coveralls.io/repos/schmich/kappa/badge.png?branch=master)](https://coveralls.io/r/schmich/kappa?branch=master)
|
9
9
|
[![Code Climate](https://codeclimate.com/github/schmich/kappa.png)](https://codeclimate.com/github/schmich/kappa)
|
10
|
+
[![Bitdeli](https://d2weczhvl823v0.cloudfront.net/schmich/kappa/trend.png)](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
|