kappa 0.1.5.pre → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +99 -35
- data/lib/kappa.rb +0 -78
- data/lib/kappa/channel.rb +60 -42
- data/lib/kappa/connection.rb +17 -28
- data/lib/kappa/game.rb +85 -28
- data/lib/kappa/images.rb +17 -0
- data/lib/kappa/stream.rb +100 -37
- data/lib/kappa/team.rb +51 -27
- data/lib/kappa/user.rb +69 -38
- data/lib/kappa/version.rb +1 -1
- data/lib/kappa/video.rb +64 -17
- metadata +51 -17
data/README.md
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
# <img src="https://raw.github.com/schmich/kappa/master/assets/kappa.png" /> Kappa
|
2
2
|
|
3
|
-
Kappa is
|
3
|
+
Kappa is the Ruby library for interfacing with the [Twitch.tv API](https://github.com/justintv/Twitch-API).
|
4
4
|
|
5
|
-
[![Gem Version](https://badge.fury.io/rb/kappa.png)](
|
6
|
-
[![Build Status](https://secure.travis-ci.org/schmich/
|
5
|
+
[![Gem Version](https://badge.fury.io/rb/kappa.png)](http://rubygems.org/gems/kappa)
|
6
|
+
[![Build Status](https://secure.travis-ci.org/schmich/kappa.png)](http://travis-ci.org/schmich/kappa)
|
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
10
|
|
11
11
|
## Getting Started
|
12
12
|
|
13
|
-
`gem install kappa
|
13
|
+
`gem install kappa`
|
14
14
|
|
15
15
|
```ruby
|
16
16
|
require 'kappa'
|
@@ -23,60 +23,124 @@ puts grubby.streaming?
|
|
23
23
|
|
24
24
|
## Examples
|
25
25
|
|
26
|
-
### Channels
|
26
|
+
### <a id="channels"></a>Channels
|
27
27
|
|
28
28
|
Channels serve as the home location for a [user's](#users) content. Channels have a [stream](#streams), can run commercials, store [videos](#videos), display information and status, and have a customized page including banners and backgrounds.
|
29
29
|
|
30
|
+
See also [`Kappa::V2::Channel`](http://rdoc.info/github/schmich/kappa/master/Kappa/V2/Channel) documentation.
|
31
|
+
|
30
32
|
```ruby
|
31
33
|
c = Channel.get('destiny')
|
32
|
-
|
33
|
-
c.
|
34
|
-
c.
|
35
|
-
c.
|
36
|
-
c.
|
37
|
-
c.
|
38
|
-
c.
|
39
|
-
c.streaming? # Is the channel currently streaming? (ex: true)
|
40
|
-
c.game_name # Name of the primary game for this channel (ex: "League of Legends")
|
41
|
-
c.mature? # Does the channel have mature content? (ex: true)
|
42
|
-
c.id # Unique Twitch ID (ex: 18074328)
|
43
|
-
c.created_at # When the channel was created (ex: #<DateTime: 2010-11-22T04:14:56+00:00 ((2455523j,15296s,0n),+0s,2299161j)>)
|
44
|
-
c.updated_at # When the channel was last updated, e.g. last stream time (ex: #<DateTime: 2013-05-11T19:57:29+00:00 ((2456424j,71849s,0n),+0s,2299161j)>)
|
45
|
-
c.background_url # URL for background image (ex: "http://static-cdn.jtvnw.net/jtv_user_pictures/destiny-channel_background_image-ab706db77853e079.jpeg")
|
46
|
-
c.banner_url # URL for banner image (ex: "http://static-cdn.jtvnw.net/jtv_user_pictures/destiny-channel_header_image-d2b9b2452f67ec00-640x125.jpeg")
|
47
|
-
c.logo_url # URL for logo image (ex: "http://static-cdn.jtvnw.net/jtv_user_pictures/destiny-profile_image-168e66661c484c5e-300x300.jpeg")
|
48
|
-
c.video_banner_url # URL for the image shown when the stream is offline (ex: "http://static-cdn.jtvnw.net/jtv_user_pictures/destiny-channel_offline_image-7a21fd1bd88c4ac3-640x360.jpeg")
|
49
|
-
|
50
|
-
c.videos
|
51
|
-
c.teams
|
52
|
-
c.subscribers
|
53
|
-
c.editors
|
54
|
-
c.followers
|
55
|
-
c.has_subscriber?
|
34
|
+
c.nil? # => false (channel exists)
|
35
|
+
c.stream # => #<Kappa::V2::Stream> (current live stream)
|
36
|
+
c.url # => "http://www.twitch.tv/destiny"
|
37
|
+
c.status # => "Destiny - Diamond I ADC - Number 1 Draven player..."
|
38
|
+
c.teams # => [#<Kappa::V2::Team>]
|
39
|
+
c.videos # => [#<Kappa::V2::Video>, ...]
|
40
|
+
c.followers # => [#<Kappa::V2::User>, ...]
|
56
41
|
```
|
57
42
|
|
58
|
-
### Streams
|
43
|
+
### <a id="streams"></a>Streams
|
44
|
+
|
45
|
+
Streams are video broadcasts that are currently live. They belong to a [user](#users) and are part of a [channel](#channels).
|
59
46
|
|
60
|
-
|
47
|
+
See also [`Kappa::V2::Stream`](http://rdoc.info/github/schmich/kappa/master/Kappa/V2/Stream) and [`Kappa::V2::Streams`](http://rdoc.info/github/schmich/kappa/master/Kappa/V2/Streams) documentation.
|
61
48
|
|
62
|
-
|
49
|
+
```ruby
|
50
|
+
s = Stream.get('idrajit')
|
51
|
+
s.nil? # => false (currently live)
|
52
|
+
s.game_name # => "StarCraft II: Heart of the Swarm"
|
53
|
+
s.viewer_count # => 7267
|
54
|
+
s.channel.url # => "http://www.twitch.tv/idrajit"
|
55
|
+
```
|
56
|
+
|
57
|
+
### <a id="users"></a>Users
|
63
58
|
|
64
59
|
These are members of the Twitch community who have a Twitch account. If broadcasting, they can own a [stream](#streams) that they can broadcast on their [channel](#channels). If mainly viewing, they might follow or subscribe to channels.
|
65
60
|
|
66
|
-
|
61
|
+
See also [`Kappa::V2::User`](http://rdoc.info/github/schmich/kappa/master/Kappa/V2/User) documentation.
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
u = User.get('snoopeh')
|
65
|
+
u.nil? # => false (user exists)
|
66
|
+
u.channel # => #<Kappa::V2::Channel>
|
67
|
+
u.following.map(&:name) # => ["national_esl1", "dreamhacklol", "riotgames"]
|
68
|
+
```
|
69
|
+
|
70
|
+
### <a id="videos"></a>Videos
|
67
71
|
|
68
72
|
Videos are broadcasts or highlights owned by a [channel](#channels). Broadcasts are unedited videos that are saved after a streaming session. Highlights are videos edited from broadcasts by the channel's owner.
|
69
73
|
|
70
|
-
|
74
|
+
See also [`Kappa::V2::Video`](http://rdoc.info/github/schmich/kappa/master/Kappa/V2/Video) and [`Kappa::V2::Videos`](http://rdoc.info/github/schmich/kappa/master/Kappa/V2/Videos) documentation.
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
v = Video.get('a395995729')
|
78
|
+
v.nil? # => false (video exists)
|
79
|
+
v.title # => "DreamHack Open Stockholm 26-27 April"
|
80
|
+
v.game_name # => "StarCraft II: Heart of the Swarm"
|
81
|
+
v.recorded_at # => #<DateTime: 2013-04-26T18:33:48+00:00>
|
82
|
+
v.view_count # => 12506
|
83
|
+
```
|
84
|
+
|
85
|
+
### <a id="teams"></a>Teams
|
71
86
|
|
72
87
|
Teams are an organization of [channels](#channels).
|
73
88
|
|
74
|
-
|
89
|
+
See also [`Kappa::V2::Team`](http://rdoc.info/github/schmich/kappa/master/Kappa/V2/Team) documentation.
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
t = Team.get('teamliquid')
|
93
|
+
t.display_name # => "TeamLiquid"
|
94
|
+
t.info # => "TeamLiquid is awesome. and esports. video games. \n\n"
|
95
|
+
t.updated_at # => #<DateTime: 2013-04-27T16:58:55+00:00>
|
96
|
+
```
|
97
|
+
|
98
|
+
### <a id="games"></a>Games
|
75
99
|
|
76
100
|
Games are categories (e.g. League of Legends, Diablo 3) used by [streams](#streams) and [channels](#channels). Games can be searched for by query.
|
77
101
|
|
102
|
+
See also [`Kappa::V2::Game`](http://rdoc.info/github/schmich/kappa/master/Kappa/V2/Game), [`Kappa::V2::Games`](http://rdoc.info/github/schmich/kappa/master/Kappa/V2/Games), and [`Kappa::V2::GameSuggestion`](http://rdoc.info/github/schmich/kappa/master/Kappa/V2/GameSuggestion) documentation.
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
top = Games.top(:limit => 3)
|
106
|
+
top.map(&:name) # => ["League of Legends", "Dota 2", "StarCraft II: Heart of the Swarm"]
|
107
|
+
```
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
g = Games.top(:limit => 1).first
|
111
|
+
g.name # => "League of Legends"
|
112
|
+
g.channel_count # => 906
|
113
|
+
g.viewer_count # => 79223
|
114
|
+
g.box_images.medium_url # =>"http://static-cdn.jtvnw.net/ttv-boxart/League%20of%20Legends-272x380.jpg"
|
115
|
+
```
|
116
|
+
|
117
|
+
```ruby
|
118
|
+
s = Games.find(:name => 'diablo', :live => true)
|
119
|
+
s.map(&:name) # => ["Diablo III", "Diablo II", "Diablo", "Diablo II: Lord of Destruction"]
|
120
|
+
s.map(&:popularity) # => [120, 4, 1, 1]
|
121
|
+
```
|
122
|
+
|
123
|
+
## Documentation
|
124
|
+
|
125
|
+
Detailed API documentation is available at [http://rdoc.info/github/schmich/kappa/master/frames](http://rdoc.info/github/schmich/kappa/master/frames).
|
126
|
+
|
127
|
+
## Versioning
|
128
|
+
|
129
|
+
- TODO: Semantic versioning
|
130
|
+
- TODO: Twitch API versions
|
131
|
+
|
78
132
|
## Contributing
|
79
133
|
|
134
|
+
- [Fork and clone the repo.](http://help.github.com/fork-a-repo/)
|
135
|
+
- [Create a branch for your changes.](http://learn.github.com/p/branching.html)
|
136
|
+
- Run `bundle install` to install development requirements.
|
137
|
+
- Implement your feature or bug fix.
|
138
|
+
- Add specs under the `spec` folder to prevent regressions or to test new code.
|
139
|
+
- Add [YARD](http://rubydoc.info/docs/yard/file/docs/GettingStarted.md) documentation for new features. Run `rake yard` to view documentation.
|
140
|
+
- Run `rake coverage` to run specs with code coverage. All specs must pass; coverage must remain at 100%.
|
141
|
+
- Commit and push your changes.
|
142
|
+
- [Submit a pull request.](http://help.github.com/send-pull-requests/)
|
143
|
+
|
80
144
|
## License
|
81
145
|
|
82
146
|
Copyright © 2013 Chris Schmich
|
data/lib/kappa.rb
CHANGED
@@ -9,81 +9,3 @@ require 'kappa/user'
|
|
9
9
|
require 'kappa/images'
|
10
10
|
require 'kappa/twitch'
|
11
11
|
require 'kappa/version'
|
12
|
-
|
13
|
-
# TODO
|
14
|
-
# https://github.com/justintv/Twitch-API
|
15
|
-
# Blocks
|
16
|
-
# GET /users/:login/blocks
|
17
|
-
# PUT /users/:user/blocks/:target
|
18
|
-
# DELETE /users/:user/blocks/:target
|
19
|
-
# Channels
|
20
|
-
# - GET /channels/:channel
|
21
|
-
# GET /channel
|
22
|
-
# GET /channels/:channel/editors
|
23
|
-
# PUT /channels/:channel
|
24
|
-
# GET /channels/:channel/videos
|
25
|
-
# GET /channels/:channel/follows
|
26
|
-
# DELETE /channels/:channel/stream_key
|
27
|
-
# POST /channels/:channel/commercial
|
28
|
-
# Chat
|
29
|
-
# GET /chat/:channel
|
30
|
-
# GET /chat/emoticons
|
31
|
-
# Follows
|
32
|
-
# GET /channels/:channel/follows
|
33
|
-
# GET /users/:user/follows/channels
|
34
|
-
# GET /users/:user/follows/channels/:target
|
35
|
-
# PUT /users/:user/follows/channels/:target
|
36
|
-
# DELETE /users/:user/follows/channels/:target
|
37
|
-
# Games
|
38
|
-
# - GET /games/top
|
39
|
-
# Ingests
|
40
|
-
# GET /ingests
|
41
|
-
# Root
|
42
|
-
# GET /
|
43
|
-
# Search
|
44
|
-
# GET /search/streams
|
45
|
-
# - GET /search/games
|
46
|
-
# Streams
|
47
|
-
# - GET /streams/:channel
|
48
|
-
# - GET /streams
|
49
|
-
# GET /streams/featured
|
50
|
-
# GET /streams/summary
|
51
|
-
# GET /streams/followed
|
52
|
-
# Subscriptions
|
53
|
-
# GET /channels/:channel/subscriptions
|
54
|
-
# GET /channels/:channel/subscriptions/:user
|
55
|
-
# Teams
|
56
|
-
# GET /teams
|
57
|
-
# GET /teams/:team
|
58
|
-
# Users
|
59
|
-
# GET /users/:user
|
60
|
-
# GET /user
|
61
|
-
# GET /streams/followed
|
62
|
-
# Videos
|
63
|
-
# GET /videos/:id
|
64
|
-
# GET /videos/top
|
65
|
-
# GET /channels/:channel/videos
|
66
|
-
|
67
|
-
# Overarching
|
68
|
-
# - Common query syntax
|
69
|
-
# - Access to raw properties (e.g. stream['game'] or stream.raw('game'))
|
70
|
-
# - Paginated results take a block to allow for intermediate processing/termination
|
71
|
-
|
72
|
-
# t = Kappa::Client.new
|
73
|
-
# c = t.channel('lagtvmaximusblack')
|
74
|
-
# c.editors -> [...]
|
75
|
-
# c.videos -> [...]
|
76
|
-
# c.followers -> [...]
|
77
|
-
# c.subscriptions
|
78
|
-
# c.start_commercial
|
79
|
-
# c.reset_stream_key
|
80
|
-
# c... ; c.save!
|
81
|
-
# TODO: current user channel
|
82
|
-
|
83
|
-
# t = Kappa::Client.new
|
84
|
-
# t.streams.all
|
85
|
-
# t.streams.all(:limit => 10)
|
86
|
-
# t.streams.featured
|
87
|
-
# t.streams.where(:channel => 'lagtvmaximusblack')
|
88
|
-
# t.streams.where(:channel => [...], :game => '...', :embeddable => t/f, :hls => t/f)
|
89
|
-
# t.stream_summary
|
data/lib/kappa/channel.rb
CHANGED
@@ -1,24 +1,13 @@
|
|
1
1
|
require 'cgi'
|
2
2
|
|
3
|
-
module Kappa
|
4
|
-
# @private
|
5
|
-
class ChannelBase
|
6
|
-
include IdEquality
|
7
|
-
|
8
|
-
def self.get(channel_name)
|
9
|
-
encoded_name = CGI.escape(channel_name)
|
10
|
-
json = connection.get("channels/#{encoded_name}")
|
11
|
-
if !json || json['status'] == 404
|
12
|
-
nil
|
13
|
-
else
|
14
|
-
new(json)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
3
|
module Kappa::V2
|
21
|
-
|
4
|
+
# Channels serve as the home location for a user's content. Channels have a stream, can run
|
5
|
+
# commercials, store videos, display information and status, and have a customized page including
|
6
|
+
# banners and backgrounds.
|
7
|
+
# @see .get Channel.get
|
8
|
+
# @see Stream
|
9
|
+
# @see User
|
10
|
+
class Channel
|
22
11
|
# TODO:
|
23
12
|
# c.subscriptions
|
24
13
|
# c.start_commercial
|
@@ -26,7 +15,9 @@ module Kappa::V2
|
|
26
15
|
# c.foo = 'bar' ; c.save!
|
27
16
|
# Current user's channel
|
28
17
|
include Connection
|
18
|
+
include Kappa::IdEquality
|
29
19
|
|
20
|
+
# @private
|
30
21
|
def initialize(hash)
|
31
22
|
@id = hash['_id']
|
32
23
|
@background_url = hash['background']
|
@@ -49,7 +40,22 @@ module Kappa::V2
|
|
49
40
|
end
|
50
41
|
end
|
51
42
|
|
52
|
-
#
|
43
|
+
# Get a channel by name.
|
44
|
+
# @param channel_name [String] The name of the channel to get. This is the same as the stream or user name.
|
45
|
+
# @return [Channel] A valid `Channel` object if the channel exists, `nil` otherwise.
|
46
|
+
def self.get(channel_name)
|
47
|
+
encoded_name = CGI.escape(channel_name)
|
48
|
+
json = connection.get("channels/#{encoded_name}")
|
49
|
+
|
50
|
+
# HTTP 422 can happen if the channel is associated with a Justin.tv account.
|
51
|
+
if !json || json['status'] == 404 || json['status'] == 422
|
52
|
+
nil
|
53
|
+
else
|
54
|
+
new(json)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Does this channel have mature content? This flag is specified by the owner of the channel.
|
53
59
|
# @return [Boolean] `true` if the channel has mature content, `false` otherwise.
|
54
60
|
def mature?
|
55
61
|
@mature
|
@@ -62,8 +68,8 @@ module Kappa::V2
|
|
62
68
|
Stream.get(@name)
|
63
69
|
end
|
64
70
|
|
65
|
-
#
|
66
|
-
# the stream object, you should call `#stream` instead.
|
71
|
+
# Does this channel currently have a live stream?
|
72
|
+
# @note This makes a separate request to get the channel's stream. If you want to actually use the stream object, you should call `#stream` instead.
|
67
73
|
# @return [Boolean] `true` if the channel currently has a live stream, `false` otherwise.
|
68
74
|
# @see #stream
|
69
75
|
def streaming?
|
@@ -74,6 +80,8 @@ module Kappa::V2
|
|
74
80
|
# GET /channels/:channel/editors
|
75
81
|
# https://github.com/justintv/Twitch-API/blob/master/v2_resources/channels.md#get-channelschanneleditors
|
76
82
|
#
|
83
|
+
# @private
|
84
|
+
# Private until implemented.
|
77
85
|
def editors
|
78
86
|
# TODO
|
79
87
|
end
|
@@ -82,19 +90,41 @@ module Kappa::V2
|
|
82
90
|
# GET /channels/:channels/videos
|
83
91
|
# https://github.com/justintv/Twitch-API/blob/master/v2_resources/videos.md#get-channelschannelvideos
|
84
92
|
#
|
93
|
+
# @private
|
94
|
+
# Private until implemented.
|
85
95
|
def videos(params = {})
|
86
96
|
# TODO
|
87
97
|
end
|
88
98
|
|
99
|
+
# TODO: Requires authentication.
|
100
|
+
# @private
|
101
|
+
# Private until implemented.
|
102
|
+
def subscribers
|
103
|
+
end
|
104
|
+
|
89
105
|
#
|
90
|
-
# GET /channels/:channel/
|
91
|
-
# https://github.com/justintv/Twitch-API/blob/master/v2_resources/
|
92
|
-
# TODO: Warning: this set can be very large, this can run for very long time, recommend using :limit/:offset.
|
106
|
+
# GET /channels/:channel/subscriptions/:user
|
107
|
+
# https://github.com/justintv/Twitch-API/blob/master/v2_resources/subscriptions.md#get-channelschannelsubscriptionsuser
|
93
108
|
#
|
94
|
-
|
109
|
+
# TODO: Requires authentication.
|
110
|
+
# @private
|
111
|
+
# Private until implemented.
|
112
|
+
def has_subscriber?(user)
|
113
|
+
# Support User object or username (string)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Get the users following this channel.
|
117
|
+
# @note The number of followers is potentially very large, so it's recommended that you specify a `:limit`.
|
118
|
+
# @param options [Hash] Filter criteria.
|
119
|
+
# @option options [Fixnum] :limit (none) Limit on the number of results returned.
|
120
|
+
# @option options [Fixnum] :offset (0) Offset into the result set to begin enumeration.
|
121
|
+
# @see User
|
122
|
+
# @see https://github.com/justintv/Twitch-API/blob/master/v2_resources/channels.md#get-channelschannelfollows GET /channels/:channel/follows
|
123
|
+
# @return [Array<User>] List of users following this channel.
|
124
|
+
def followers(options = {})
|
95
125
|
params = {}
|
96
126
|
|
97
|
-
limit =
|
127
|
+
limit = options[:limit]
|
98
128
|
if limit && (limit < 100)
|
99
129
|
params[:limit] = limit
|
100
130
|
else
|
@@ -112,19 +142,6 @@ module Kappa::V2
|
|
112
142
|
)
|
113
143
|
end
|
114
144
|
|
115
|
-
# TODO: Requires authentication.
|
116
|
-
def subscribers
|
117
|
-
end
|
118
|
-
|
119
|
-
#
|
120
|
-
# GET /channels/:channel/subscriptions/:user
|
121
|
-
# https://github.com/justintv/Twitch-API/blob/master/v2_resources/subscriptions.md#get-channelschannelsubscriptionsuser
|
122
|
-
#
|
123
|
-
# TODO: Requires authentication.
|
124
|
-
def has_subscriber?(user)
|
125
|
-
# Support User object or username (string)
|
126
|
-
end
|
127
|
-
|
128
145
|
# @return [Fixnum] Unique Twitch ID.
|
129
146
|
attr_reader :id
|
130
147
|
|
@@ -137,7 +154,7 @@ module Kappa::V2
|
|
137
154
|
# @return [DateTime] When the channel was created.
|
138
155
|
attr_reader :created_at
|
139
156
|
|
140
|
-
# @return [String]
|
157
|
+
# @return [String] User-friendly display name. This name is used for the channel's page title.
|
141
158
|
attr_reader :display_name
|
142
159
|
|
143
160
|
# @return [String] Name of the primary game for this channel.
|
@@ -149,10 +166,10 @@ module Kappa::V2
|
|
149
166
|
# @return [String] Unique Twitch name.
|
150
167
|
attr_reader :name
|
151
168
|
|
152
|
-
# @return [String] Current status.
|
169
|
+
# @return [String] Current status set by the channel's owner.
|
153
170
|
attr_reader :status
|
154
171
|
|
155
|
-
# @return [DateTime] When the channel was last updated
|
172
|
+
# @return [DateTime] When the channel was last updated. When a stream is started, its channel is updated.
|
156
173
|
attr_reader :updated_at
|
157
174
|
|
158
175
|
# @return [String] The URL for the channel's main page.
|
@@ -161,6 +178,7 @@ module Kappa::V2
|
|
161
178
|
# @return [String] URL for the image shown when the stream is offline.
|
162
179
|
attr_reader :video_banner_url
|
163
180
|
|
181
|
+
# @return [Array<Team>] The list of teams that this channel is associated with. Not all channels have associated teams.
|
164
182
|
attr_reader :teams
|
165
183
|
end
|
166
184
|
end
|
data/lib/kappa/connection.rb
CHANGED
@@ -13,11 +13,13 @@ module Kappa
|
|
13
13
|
def initialize(base_url = DEFAULT_BASE_URL)
|
14
14
|
@base_url = Addressable::URI.parse(base_url)
|
15
15
|
|
16
|
+
# TODO: Expose client_id so clients of the library can (optionally) set this
|
17
|
+
# themselves and avoid rate limiting. Clients should still have the option to
|
18
|
+
# not set this and use a randomly generated ID.
|
19
|
+
|
16
20
|
uuid = SecureRandom.uuid
|
17
21
|
# TODO: Use current library version.
|
18
22
|
@client_id = "Kappa-v1-#{uuid}"
|
19
|
-
|
20
|
-
@last_request_time = Time.now - RATE_LIMIT_SEC
|
21
23
|
end
|
22
24
|
|
23
25
|
def get(path, query = nil)
|
@@ -27,25 +29,26 @@ module Kappa
|
|
27
29
|
'Client-ID' => @client_id,
|
28
30
|
}.merge(custom_headers)
|
29
31
|
|
30
|
-
response =
|
31
|
-
self.class.get(request_url, :headers => headers, :query => query)
|
32
|
-
end
|
32
|
+
response = self.class.get(request_url, :headers => headers, :query => query)
|
33
33
|
|
34
34
|
# TODO: Handle non-JSON response
|
35
35
|
# TODO: Handle invalid JSON
|
36
36
|
# TODO: Handle non-200 codes
|
37
|
+
# TODO: Include HTTP status code in the return value
|
37
38
|
|
38
39
|
json = response.body
|
39
40
|
return JSON.parse(json)
|
40
41
|
end
|
41
42
|
|
42
|
-
def accumulate(
|
43
|
-
path =
|
44
|
-
params =
|
45
|
-
json =
|
46
|
-
sub_json =
|
47
|
-
klass =
|
48
|
-
|
43
|
+
def accumulate(options)
|
44
|
+
path = options[:path]
|
45
|
+
params = options[:params] || {}
|
46
|
+
json = options[:json]
|
47
|
+
sub_json = options[:sub_json]
|
48
|
+
klass = options[:class]
|
49
|
+
|
50
|
+
total_limit = options[:limit]
|
51
|
+
page_limit = params[:limit] || 100
|
49
52
|
|
50
53
|
objects = []
|
51
54
|
ids = Set.new
|
@@ -57,13 +60,13 @@ module Kappa
|
|
57
60
|
object = klass.new(object_json)
|
58
61
|
if ids.add?(object.id)
|
59
62
|
objects << object
|
60
|
-
if objects.count ==
|
63
|
+
if objects.count == total_limit
|
61
64
|
return objects
|
62
65
|
end
|
63
66
|
end
|
64
67
|
end
|
65
68
|
|
66
|
-
!current_objects.empty?
|
69
|
+
!current_objects.empty? && (current_objects.count >= page_limit)
|
67
70
|
end
|
68
71
|
|
69
72
|
return objects
|
@@ -106,20 +109,6 @@ module Kappa
|
|
106
109
|
end
|
107
110
|
|
108
111
|
private
|
109
|
-
def rate_limit
|
110
|
-
delta = Time.now - @last_request_time
|
111
|
-
delay = [RATE_LIMIT_SEC - delta, 0].max
|
112
|
-
|
113
|
-
sleep delay if delay > 0
|
114
|
-
|
115
|
-
begin
|
116
|
-
return yield
|
117
|
-
ensure
|
118
|
-
@last_request_time = Time.now
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
RATE_LIMIT_SEC = 1
|
123
112
|
DEFAULT_BASE_URL = 'https://api.twitch.tv/kraken/'
|
124
113
|
end
|
125
114
|
end
|