kappa 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.
- data/README.md +115 -26
- data/lib/kappa.rb +2 -0
- data/lib/kappa/channel.rb +34 -36
- data/lib/kappa/configuration.rb +35 -1
- data/lib/kappa/connection.rb +40 -13
- data/lib/kappa/errors.rb +43 -0
- data/lib/kappa/game.rb +54 -8
- data/lib/kappa/status.rb +16 -0
- data/lib/kappa/stream.rb +101 -20
- data/lib/kappa/team.rb +20 -9
- data/lib/kappa/user.rb +28 -16
- data/lib/kappa/version.rb +1 -1
- data/lib/kappa/video.rb +65 -8
- metadata +6 -4
data/README.md
CHANGED
@@ -7,7 +7,6 @@ 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")
|
11
10
|
|
12
11
|
## Getting Started
|
13
12
|
|
@@ -22,6 +21,10 @@ frag = Twitch.channels.get('lethalfrag')
|
|
22
21
|
puts frag.streaming?
|
23
22
|
```
|
24
23
|
|
24
|
+
```ruby
|
25
|
+
gem 'kappa', '~> 1.0'
|
26
|
+
```
|
27
|
+
|
25
28
|
## Configuration
|
26
29
|
|
27
30
|
When making requests to Twitch, you must specify a client ID for your application.
|
@@ -36,13 +39,79 @@ Twitch.configure do |config|
|
|
36
39
|
end
|
37
40
|
```
|
38
41
|
|
39
|
-
|
42
|
+
See the [`Twitch.configure`](http://rdoc.info/gems/kappa/Twitch#configure-class_method) documentation.
|
40
43
|
|
41
|
-
|
44
|
+
## Examples
|
45
|
+
|
46
|
+
Get the featured streams on the Twitch.tv homepage:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
Twitch.streams.featured do |stream|
|
50
|
+
channel = stream.channel
|
51
|
+
puts "#{channel.display_name}: #{stream.viewer_count} viewers"
|
52
|
+
puts "#{channel.status}"
|
53
|
+
puts '-' * 80
|
54
|
+
end
|
55
|
+
```
|
56
|
+
|
57
|
+
See if certain users are streaming:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
users = ['destiny', 'followgrubby', 'incontroltv']
|
61
|
+
Twitch.streams.find(:channel => users) do |stream|
|
62
|
+
puts "#{stream.channel.name} is streaming #{stream.game_name}."
|
63
|
+
end
|
64
|
+
```
|
65
|
+
|
66
|
+
Get the most popular games being streamed:
|
42
67
|
|
43
|
-
|
68
|
+
```ruby
|
69
|
+
Twitch.games.top(:limit => 3) do |game|
|
70
|
+
print "#{game.name}: "
|
71
|
+
print "#{game.viewer_count} viewers in "
|
72
|
+
puts "#{game.channel_count} channels"
|
73
|
+
end
|
74
|
+
```
|
44
75
|
|
45
|
-
|
76
|
+
Get streams for a particular game:
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
Twitch.streams.find(:game => 'League of Legends') do |stream|
|
80
|
+
next if stream.viewer_count < 1000
|
81
|
+
puts "#{stream.channel.display_name}: #{stream.viewer_count}"
|
82
|
+
end
|
83
|
+
```
|
84
|
+
|
85
|
+
Get info for a single user:
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
user = Twitch.users.get('lethalfrag')
|
89
|
+
stream = user.stream
|
90
|
+
|
91
|
+
puts user.display_name
|
92
|
+
if stream
|
93
|
+
puts "Streaming #{stream.game_name} at #{stream.url}"
|
94
|
+
else
|
95
|
+
puts 'Not streaming.'
|
96
|
+
end
|
97
|
+
```
|
98
|
+
|
99
|
+
Get the followers of a channel:
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
channel = Twitch.channels.get('day9tv')
|
103
|
+
channel.followers do |user|
|
104
|
+
puts user.display_name
|
105
|
+
end
|
106
|
+
```
|
107
|
+
|
108
|
+
## Resources
|
109
|
+
|
110
|
+
### <a id="channels"></a>Channels
|
111
|
+
|
112
|
+
Channels serve as the home location for a [user's](#users) content. Channels have a [stream](#streams),
|
113
|
+
can run commercials, store [videos](#videos), display information and status, and have a customized page
|
114
|
+
including banners and backgrounds. See the [`Channel`](http://rdoc.info/gems/kappa/Twitch/V2/Channel) documentation.
|
46
115
|
|
47
116
|
```ruby
|
48
117
|
c = Twitch.channels.get('destiny')
|
@@ -57,9 +126,9 @@ c.followers # => [#<Kappa::V2::User>, ...]
|
|
57
126
|
|
58
127
|
### <a id="streams"></a>Streams
|
59
128
|
|
60
|
-
Streams are video broadcasts that are currently live. They belong to a [user](#users) and are part of a
|
61
|
-
|
62
|
-
|
129
|
+
Streams are video broadcasts that are currently live. They belong to a [user](#users) and are part of a
|
130
|
+
[channel](#channels). See the [`Stream`](http://rdoc.info/gems/kappa/Twitch/V2/Stream) and
|
131
|
+
[`Streams`](http://rdoc.info/gems/kappa/Twitch/V2/Streams) documentation.
|
63
132
|
|
64
133
|
```ruby
|
65
134
|
s = Twitch.streams.get('idrajit')
|
@@ -71,9 +140,9 @@ s.channel.url # => "http://www.twitch.tv/idrajit"
|
|
71
140
|
|
72
141
|
### <a id="users"></a>Users
|
73
142
|
|
74
|
-
These are members of the Twitch community who have a Twitch account. If broadcasting, they can own a
|
75
|
-
|
76
|
-
See
|
143
|
+
These are members of the Twitch community who have a Twitch account. If broadcasting, they can own a
|
144
|
+
[stream](#streams) that they can broadcast on their [channel](#channels). If mainly viewing, they might
|
145
|
+
follow or subscribe to channels. See the [`User`](http://rdoc.info/gems/kappa/Twitch/V2/User) documentation.
|
77
146
|
|
78
147
|
```ruby
|
79
148
|
u = Twitch.users.get('snoopeh')
|
@@ -84,9 +153,10 @@ u.following.map(&:name) # => ["national_esl1", "dreamhacklol", "riotgames"]
|
|
84
153
|
|
85
154
|
### <a id="videos"></a>Videos
|
86
155
|
|
87
|
-
Videos are broadcasts or highlights owned by a [channel](#channels). Broadcasts are unedited videos that are saved
|
88
|
-
|
89
|
-
|
156
|
+
Videos are broadcasts or highlights owned by a [channel](#channels). Broadcasts are unedited videos that are saved
|
157
|
+
after a streaming session. Highlights are videos edited from broadcasts by the channel's owner. See the
|
158
|
+
[`Video`](http://rdoc.info/gems/kappa/Twitch/V2/Video) and [`Videos`](http://rdoc.info/gems/kappa/Twitch/V2/Videos)
|
159
|
+
documentation.
|
90
160
|
|
91
161
|
```ruby
|
92
162
|
v = Twitch.videos.get('a395995729')
|
@@ -99,9 +169,8 @@ v.view_count # => 12506
|
|
99
169
|
|
100
170
|
### <a id="teams"></a>Teams
|
101
171
|
|
102
|
-
Teams are an organization of [channels](#channels).
|
103
|
-
|
104
|
-
See also [`Team`](http://rdoc.info/gems/kappa/Kappa/V2/Team) documentation.
|
172
|
+
Teams are an organization of [channels](#channels). See the [`Team`](http://rdoc.info/gems/kappa/Twitch/V2/Team)
|
173
|
+
documentation.
|
105
174
|
|
106
175
|
```ruby
|
107
176
|
t = Twitch.teams.get('teamliquid')
|
@@ -113,13 +182,14 @@ t.updated_at # => 2013-05-24 00:17:10 UTC
|
|
113
182
|
|
114
183
|
### <a id="games"></a>Games
|
115
184
|
|
116
|
-
Games are categories (e.g. League of Legends, Diablo 3) used by [streams](#streams) and [channels](#channels).
|
117
|
-
|
118
|
-
|
185
|
+
Games are categories (e.g. League of Legends, Diablo 3) used by [streams](#streams) and [channels](#channels).
|
186
|
+
Games can be searched for by query. See the [`Game`](http://rdoc.info/gems/kappa/Twitch/V2/Game),
|
187
|
+
[`Games`](http://rdoc.info/gems/kappa/Twitch/V2/Games), and
|
188
|
+
[`GameSuggestion`](http://rdoc.info/gems/kappa/Twitch/V2/GameSuggestion) documentation.
|
119
189
|
|
120
190
|
```ruby
|
121
|
-
top = Twitch.games.top(:limit =>
|
122
|
-
top.map(&:name) # => ["League of Legends", "
|
191
|
+
top = Twitch.games.top(:limit => 2)
|
192
|
+
top.map(&:name) # => ["League of Legends", "StarCraft II: Heart of the Swarm"]
|
123
193
|
```
|
124
194
|
|
125
195
|
```ruby
|
@@ -127,16 +197,34 @@ g = Twitch.games.top(:limit => 1).first
|
|
127
197
|
g.name # => "League of Legends"
|
128
198
|
g.channel_count # => 906
|
129
199
|
g.viewer_count # => 79223
|
130
|
-
g.box_images.medium_url # =>"http://static-cdn.jtvnw.net/ttv-boxart/
|
200
|
+
g.box_images.medium_url # =>"http://static-cdn.jtvnw.net/ttv-boxart/31412.jpg"
|
131
201
|
```
|
132
202
|
|
133
203
|
```ruby
|
134
204
|
s = Twitch.games.find(:name => 'diablo', :live => true)
|
135
|
-
s.map(&:name) # => ["Diablo III", "Diablo II", "Diablo"
|
136
|
-
s.map(&:popularity) # => [120, 4, 1
|
205
|
+
s.map(&:name) # => ["Diablo III", "Diablo II", "Diablo"]
|
206
|
+
s.map(&:popularity) # => [120, 4, 1]
|
137
207
|
```
|
138
208
|
|
139
|
-
##
|
209
|
+
## Errors
|
210
|
+
|
211
|
+
All errors derive from `Twitch::Error`.
|
212
|
+
|
213
|
+
- `Twitch:Error` - Base class for all errors.
|
214
|
+
- `Twitch::Error::ResponseError` - Base class for all Twitch.tv API response errors.
|
215
|
+
- `Twitch::Error::FormatError` - The returned data was incorrectly formatted (e.g. invalid JSON).
|
216
|
+
- `Twitch::Error::ClientError` - The server returned a 4xx status code.
|
217
|
+
- `Twitch::Error::ServerError` - The server returned a 5xx status code.
|
218
|
+
|
219
|
+
All `ResponseError` errors have additional diagnostic information:
|
220
|
+
|
221
|
+
```ruby
|
222
|
+
e.status # => 422
|
223
|
+
e.body # => '{"status":422,"message":"...","error":"..."}'
|
224
|
+
e.url # => "https://api.twitch.tv/streams/desrow"
|
225
|
+
```
|
226
|
+
|
227
|
+
See the [`ResponseError`](http://rdoc.info/gems/kappa/Twitch/Error/ResponseError) documentation.
|
140
228
|
|
141
229
|
## Documentation
|
142
230
|
|
@@ -194,3 +282,4 @@ end
|
|
194
282
|
Copyright © 2013 Chris Schmich
|
195
283
|
<br />
|
196
284
|
MIT License, See [LICENSE](LICENSE) for details.
|
285
|
+
[](http://githalytics.com/schmich/kappa)
|
data/lib/kappa.rb
CHANGED
data/lib/kappa/channel.rb
CHANGED
@@ -68,57 +68,57 @@ module Twitch::V2
|
|
68
68
|
# Get the users following this channel.
|
69
69
|
# @note The number of followers is potentially very large, so it's recommended that you specify a `:limit`.
|
70
70
|
# @example
|
71
|
-
#
|
71
|
+
# channel.followers(:limit => 20)
|
72
|
+
# @example
|
73
|
+
# channel.followers do |follower|
|
74
|
+
# puts follower.display_name
|
75
|
+
# end
|
72
76
|
# @param options [Hash] Filter criteria.
|
73
|
-
# @option options [Fixnum] :limit (
|
77
|
+
# @option options [Fixnum] :limit (nil) Limit on the number of results returned.
|
74
78
|
# @option options [Fixnum] :offset (0) Offset into the result set to begin enumeration.
|
79
|
+
# @yield Optional. If a block is given, each follower is yielded.
|
80
|
+
# @yieldparam [User] follower Current follower.
|
75
81
|
# @see User
|
76
82
|
# @see https://github.com/justintv/Twitch-API/blob/master/v2_resources/channels.md#get-channelschannelfollows GET /channels/:channel/follows
|
77
|
-
# @return [Array<User>]
|
78
|
-
|
83
|
+
# @return [Array<User>] Users following this channel, if no block is given.
|
84
|
+
# @return [nil] If a block is given.
|
85
|
+
def followers(options = {}, &block)
|
86
|
+
name = CGI.escape(@name)
|
79
87
|
return @query.connection.accumulate(
|
80
|
-
:path => "channels/#{
|
88
|
+
:path => "channels/#{name}/follows",
|
81
89
|
:json => 'follows',
|
82
90
|
:sub_json => 'user',
|
83
91
|
:create => -> hash { User.new(hash, @query) },
|
84
92
|
:limit => options[:limit],
|
85
|
-
:offset => options[:offset]
|
93
|
+
:offset => options[:offset],
|
94
|
+
&block
|
86
95
|
)
|
87
96
|
end
|
88
97
|
|
89
98
|
# Get the videos for a channel, most recently created first.
|
90
99
|
# @note This incurs additional web requests.
|
100
|
+
# @note You can get videos directly from a channel name via {Videos#for_channel}.
|
101
|
+
# @example
|
102
|
+
# v = channel.videos(:type => :broadcasts)
|
91
103
|
# @example
|
92
|
-
#
|
93
|
-
#
|
104
|
+
# channel.videos(:type => :highlights) do |video|
|
105
|
+
# next if video.view_count < 10000
|
106
|
+
# puts video.url
|
107
|
+
# end
|
94
108
|
# @param options [Hash] Filter criteria.
|
95
109
|
# @option options [Symbol] :type (:highlights) The type of videos to return. Valid values are `:broadcasts`, `:highlights`.
|
96
|
-
# @option options [Fixnum] :limit (
|
110
|
+
# @option options [Fixnum] :limit (nil) Limit on the number of results returned.
|
97
111
|
# @option options [Fixnum] :offset (0) Offset into the result set to begin enumeration.
|
112
|
+
# @yield Optional. If a block is given, each video is yielded.
|
113
|
+
# @yieldparam [Video] video Current video.
|
98
114
|
# @see Video
|
115
|
+
# @see Videos#for_channel Videos#for_channel
|
99
116
|
# @see https://github.com/justintv/Twitch-API/blob/master/v2_resources/videos.md#get-channelschannelvideos GET /channels/:channel/videos
|
100
117
|
# @raise [ArgumentError] If `:type` is not one of `:broadcasts` or `:highlights`.
|
101
|
-
# @return [Array<Video>]
|
102
|
-
|
103
|
-
|
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
|
-
)
|
118
|
+
# @return [Array<Video>] Videos for the channel, if no block is given.
|
119
|
+
# @return [nil] If a block is given.
|
120
|
+
def videos(options = {}, &block)
|
121
|
+
@query.videos.for_channel(@name, options, &block)
|
122
122
|
end
|
123
123
|
|
124
124
|
# @example
|
@@ -170,7 +170,7 @@ module Twitch::V2
|
|
170
170
|
|
171
171
|
# @example
|
172
172
|
# 2013-07-21 05:27:58 UTC
|
173
|
-
# @return [Time] When the channel was last updated (UTC). For example, when a stream is started,
|
173
|
+
# @return [Time] When the channel was last updated (UTC). For example, when a stream is started or a channel's status is changed, the channel is updated.
|
174
174
|
attr_reader :updated_at
|
175
175
|
|
176
176
|
# @example
|
@@ -202,13 +202,11 @@ module Twitch::V2
|
|
202
202
|
# @param channel_name [String] The name of the channel to get. This is the same as the stream or user name.
|
203
203
|
# @return [Channel] A valid `Channel` object if the channel exists, `nil` otherwise.
|
204
204
|
def get(channel_name)
|
205
|
-
|
206
|
-
json = @query.connection.get("channels/#{encoded_name}")
|
205
|
+
name = CGI.escape(channel_name)
|
207
206
|
|
208
207
|
# HTTP 422 can happen if the channel is associated with a Justin.tv account.
|
209
|
-
|
210
|
-
|
211
|
-
else
|
208
|
+
Twitch::Status.map(404 => nil, 422 => nil) do
|
209
|
+
json = @query.connection.get("channels/#{name}")
|
212
210
|
Channel.new(json, @query)
|
213
211
|
end
|
214
212
|
end
|
data/lib/kappa/configuration.rb
CHANGED
@@ -3,16 +3,48 @@ require 'securerandom'
|
|
3
3
|
module Twitch
|
4
4
|
@query = nil
|
5
5
|
|
6
|
-
# Configure global settings for interacting with Twitch. Future requests
|
6
|
+
# Configure global settings for interacting with Twitch. Future requests
|
7
|
+
# through the `Twitch` module will use these settings.
|
7
8
|
# @example
|
8
9
|
# Twitch.configure do |config|
|
9
10
|
# config.client_id = 'sc2daily-v1.0.0'
|
10
11
|
# config.api = Twitch::V2
|
11
12
|
# end
|
13
|
+
#
|
14
|
+
# streams = Twitch.streams.featured(:limit => 10)
|
15
|
+
# @param client_id [String] When making requests to Twitch,
|
16
|
+
# you must specify a client ID for your application. If you do not specify a client ID,
|
17
|
+
# Twitch reserves the right to rate-limit your application without warning. If unspecified,
|
18
|
+
# this defaults to a random string, but in real applications, you should set this explicitly.
|
19
|
+
# @param api [Module] The version of the Twitch API to use. Defaults to `Twitch::V2`, the only
|
20
|
+
# API version currently supported.
|
21
|
+
# @return [nil] nil
|
12
22
|
def self.configure(&block)
|
13
23
|
@query = instance(&block)
|
24
|
+
nil
|
14
25
|
end
|
15
26
|
|
27
|
+
# Create a new interface to Twitch. This allows you to have multiple separate
|
28
|
+
# connections to Twitch in the same process, each with its own configuration.
|
29
|
+
# @example
|
30
|
+
# client_a = Twitch.instance do |config|
|
31
|
+
# config.client_id = 'App-A-v2.0.0'
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# client_b = Twitch.instance do |config|
|
35
|
+
# config.client_id = 'App-B-v3.0.0'
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# streams = client_a.streams.featured(:limit => 10)
|
39
|
+
# channel = client_b.channels.get('destiny')
|
40
|
+
# @param client_id [String] When making requests to Twitch,
|
41
|
+
# you must specify a client ID for your application. If you do not specify a client ID,
|
42
|
+
# Twitch reserves the right to rate-limit your application without warning. If unspecified,
|
43
|
+
# this defaults to a random string, but in real applications, you should set this explicitly.
|
44
|
+
# @param api [Module] The version of the Twitch API to use. Defaults to `Twitch::V2`, the only
|
45
|
+
# API version currently supported.
|
46
|
+
# @return [Object] A Twitch query object through which you can make requests. The methods on this
|
47
|
+
# object are the same as the methods on the default `Twitch` object.
|
16
48
|
def self.instance(&block)
|
17
49
|
config = Configuration.new
|
18
50
|
config.instance_eval(&block)
|
@@ -20,6 +52,7 @@ module Twitch
|
|
20
52
|
return config.create(:Query, connection)
|
21
53
|
end
|
22
54
|
|
55
|
+
# @private
|
23
56
|
def self.method_missing(*args)
|
24
57
|
@query ||= create_default_query
|
25
58
|
@query.send(*args)
|
@@ -46,6 +79,7 @@ module Twitch
|
|
46
79
|
end
|
47
80
|
|
48
81
|
private
|
82
|
+
# @private
|
49
83
|
def self.create_default_query
|
50
84
|
config = Configuration.new
|
51
85
|
connection = config.create(:Connection, config.client_id)
|
data/lib/kappa/connection.rb
CHANGED
@@ -9,11 +9,16 @@ module Twitch
|
|
9
9
|
include HTTParty
|
10
10
|
|
11
11
|
def initialize(client_id, base_url = DEFAULT_BASE_URL)
|
12
|
+
raise ArgumentError, 'client_id' if !client_id || client_id.empty?
|
13
|
+
raise ArgumentError, 'base_url' if !base_url || base_url.empty?
|
14
|
+
|
12
15
|
@client_id = client_id
|
13
16
|
@base_url = Addressable::URI.parse(base_url)
|
14
17
|
end
|
15
18
|
|
16
19
|
def get(path, query = nil)
|
20
|
+
raise ArgumentError, 'path' if !path || path.empty?
|
21
|
+
|
17
22
|
request_url = @base_url + path
|
18
23
|
|
19
24
|
all_headers = {
|
@@ -23,11 +28,27 @@ module Twitch
|
|
23
28
|
|
24
29
|
response = self.class.get(request_url, :headers => all_headers, :query => query)
|
25
30
|
|
26
|
-
|
27
|
-
|
31
|
+
url = response.request.last_uri.to_s
|
32
|
+
status = response.code
|
33
|
+
body = response.body
|
34
|
+
|
35
|
+
case status
|
36
|
+
when 400...500
|
37
|
+
raise Error::ClientError.new("HTTP client error, status #{status}.", url, status, body)
|
38
|
+
when 500...600
|
39
|
+
raise Error::ServerError.new("HTTP server error, status #{status}.", url, status, body)
|
40
|
+
else
|
41
|
+
# Ignore, assume success.
|
42
|
+
end
|
43
|
+
|
44
|
+
begin
|
45
|
+
return JSON.parse(body)
|
46
|
+
rescue JSON::ParserError => e
|
47
|
+
raise Error::FormatError.new(e, url, status, body)
|
48
|
+
end
|
28
49
|
end
|
29
50
|
|
30
|
-
def accumulate(options)
|
51
|
+
def accumulate(options, &block)
|
31
52
|
path = options[:path]
|
32
53
|
params = options[:params] || {}
|
33
54
|
json = options[:json]
|
@@ -47,8 +68,13 @@ module Twitch
|
|
47
68
|
page_limit = [total_limit || 100, 100].min
|
48
69
|
offset = options[:offset] || 0
|
49
70
|
|
50
|
-
objects = []
|
51
71
|
ids = Set.new
|
72
|
+
objects = []
|
73
|
+
count = 0
|
74
|
+
|
75
|
+
block ||= -> object {
|
76
|
+
objects << object
|
77
|
+
}
|
52
78
|
|
53
79
|
paginate(path, page_limit, offset, params) do |response_json|
|
54
80
|
current_objects = response_json[json]
|
@@ -56,17 +82,18 @@ module Twitch
|
|
56
82
|
object_json = object_json[sub_json] if sub_json
|
57
83
|
object = create.call(object_json)
|
58
84
|
if ids.add?(object.id)
|
59
|
-
|
60
|
-
|
61
|
-
|
85
|
+
count += 1
|
86
|
+
block.call(object)
|
87
|
+
if count == total_limit
|
88
|
+
return block_given? ? nil : objects
|
62
89
|
end
|
63
90
|
end
|
64
91
|
end
|
65
92
|
|
66
|
-
|
93
|
+
break if current_objects.empty? || (current_objects.count < page_limit)
|
67
94
|
end
|
68
95
|
|
69
|
-
return objects
|
96
|
+
return block_given? ? nil : objects
|
70
97
|
end
|
71
98
|
|
72
99
|
def paginate(path, limit, offset, params = {})
|
@@ -81,7 +108,7 @@ module Twitch
|
|
81
108
|
|
82
109
|
loop do
|
83
110
|
break if json['error'] && (json['status'] == 503)
|
84
|
-
|
111
|
+
yield json
|
85
112
|
|
86
113
|
links = json['_links']
|
87
114
|
next_url = links['next']
|
@@ -105,8 +132,8 @@ end
|
|
105
132
|
module Twitch::V2
|
106
133
|
# @private
|
107
134
|
class Connection < Twitch::Connection
|
108
|
-
|
109
|
-
|
110
|
-
|
135
|
+
def headers
|
136
|
+
{ 'Accept' => 'application/vnd.twitchtv.v2+json' }
|
137
|
+
end
|
111
138
|
end
|
112
139
|
end
|
data/lib/kappa/errors.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
module Twitch
|
2
|
+
# The base class for all `Twitch` errors.
|
3
|
+
class Error < StandardError
|
4
|
+
# An error that occurred as the result of a request to the Twitch.tv API.
|
5
|
+
class ResponseError < Error
|
6
|
+
# @private
|
7
|
+
def initialize(arg, url, status, body)
|
8
|
+
super(arg)
|
9
|
+
@url = url
|
10
|
+
@status = status
|
11
|
+
@body = body
|
12
|
+
end
|
13
|
+
|
14
|
+
# @example
|
15
|
+
# "https://api.twitch.tv/kraken/streams?limit=100&offset=0"
|
16
|
+
# @return [String] The request URL that resulted in this response error.
|
17
|
+
attr_reader :url
|
18
|
+
|
19
|
+
# @example
|
20
|
+
# 500
|
21
|
+
# @return [Fixnum] The HTTP status code for the response.
|
22
|
+
attr_reader :status
|
23
|
+
|
24
|
+
# @example
|
25
|
+
# '{"status":422,"message":"Channel desrow is not available on Twitch","error":"Unprocessable Entity"}'
|
26
|
+
# @return [String] The response body.
|
27
|
+
attr_reader :body
|
28
|
+
end
|
29
|
+
|
30
|
+
# An error indicating an HTTP client error code (4xx) from the Twitch.tv API.
|
31
|
+
class ClientError < ResponseError
|
32
|
+
end
|
33
|
+
|
34
|
+
# An error indicating an HTTP server error code (5xx) from the Twitch.tv API.
|
35
|
+
class ServerError < ResponseError
|
36
|
+
end
|
37
|
+
|
38
|
+
# An error indicating a malformed response from the Twitch.tv API.
|
39
|
+
# All Twitch.tv responses are expected to valid JSON objects.
|
40
|
+
class FormatError < ResponseError
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/kappa/game.rb
CHANGED
@@ -8,7 +8,8 @@ module Twitch::V2
|
|
8
8
|
include Twitch::IdEquality
|
9
9
|
|
10
10
|
# @private
|
11
|
-
def initialize(hash)
|
11
|
+
def initialize(hash, query)
|
12
|
+
@query = query
|
12
13
|
@channel_count = hash['channels']
|
13
14
|
@viewer_count = hash['viewers']
|
14
15
|
|
@@ -20,6 +21,34 @@ module Twitch::V2
|
|
20
21
|
@logo_images = Images.new(game['logo'])
|
21
22
|
end
|
22
23
|
|
24
|
+
# Get streams for this game.
|
25
|
+
# @example
|
26
|
+
# game.streams
|
27
|
+
# @example
|
28
|
+
# game.streams(:embeddable => true, :limit => 20)
|
29
|
+
# @example
|
30
|
+
# game.streams do |stream|
|
31
|
+
# next if stream.viewer_count < 1000
|
32
|
+
# puts stream.url
|
33
|
+
# end
|
34
|
+
# @param options [Hash] Search criteria.
|
35
|
+
# @option options [Array<String, Channel, #name>] :channel Only return streams for these channels.
|
36
|
+
# If a channel is not currently streaming, it is omitted. You must specify an array of channels
|
37
|
+
# or channel names.
|
38
|
+
# @option options [Boolean] :embeddable (nil) If `true`, limit the streams to those that can be embedded. If `false` or `nil`, do not limit.
|
39
|
+
# @option options [Boolean] :hls (nil) If `true`, limit the streams to those using HLS (HTTP Live Streaming). If `false` or `nil`, do not limit.
|
40
|
+
# @option options [Fixnum] :limit (nil) Limit on the number of results returned.
|
41
|
+
# @option options [Fixnum] :offset (0) Offset into the result set to begin enumeration.
|
42
|
+
# @yield Optional. If a block is given, each stream found is yielded.
|
43
|
+
# @yieldparam [Stream] stream Current stream.
|
44
|
+
# @see https://github.com/justintv/Twitch-API/blob/master/v2_resources/streams.md#get-streams GET /streams
|
45
|
+
# @raise [ArgumentError] If `:channel` is not an array.
|
46
|
+
# @return [Array<Stream>] Streams matching the specified criteria, if no block is given.
|
47
|
+
# @return [nil] If a block is given.
|
48
|
+
def streams(options = {}, &block)
|
49
|
+
@query.streams.find(options.merge(:game => @name), &block)
|
50
|
+
end
|
51
|
+
|
23
52
|
# @example
|
24
53
|
# 21799
|
25
54
|
# @return [Fixnum] Unique Twitch ID.
|
@@ -108,14 +137,22 @@ module Twitch::V2
|
|
108
137
|
# Twitch.games.top
|
109
138
|
# @example
|
110
139
|
# Twitch.games.top(:limit => 10)
|
140
|
+
# @example
|
141
|
+
# Twitch.games.top do |game|
|
142
|
+
# next if game.viewer_count < 10000
|
143
|
+
# puts game.name
|
144
|
+
# end
|
111
145
|
# @param options [Hash] Filter criteria.
|
112
146
|
# @option options [Boolean] :hls (nil) If `true`, limit the games to those that have any streams using HLS (HTTP Live Streaming). If `false` or `nil`, do not limit.
|
113
|
-
# @option options [Fixnum] :limit (
|
147
|
+
# @option options [Fixnum] :limit (nil) Limit on the number of results returned.
|
114
148
|
# @option options [Fixnum] :offset (0) Offset into the result set to begin enumeration.
|
149
|
+
# @yield Optional. If a block is given, each top game is yielded.
|
150
|
+
# @yieldparam [Game] game Current game.
|
115
151
|
# @see Game Game
|
116
152
|
# @see https://github.com/justintv/Twitch-API/blob/master/v2_resources/games.md#get-gamestop GET /games/top
|
117
|
-
# @return [Array<Game>]
|
118
|
-
|
153
|
+
# @return [Array<Game>] Games sorted by number of current viewers on Twitch, highest first, if no block is given.
|
154
|
+
# @return [nil] If a block is given.
|
155
|
+
def top(options = {}, &block)
|
119
156
|
params = {}
|
120
157
|
|
121
158
|
if options[:hls]
|
@@ -126,9 +163,10 @@ module Twitch::V2
|
|
126
163
|
:path => 'games/top',
|
127
164
|
:params => params,
|
128
165
|
:json => 'top',
|
129
|
-
:create => Game,
|
166
|
+
:create => -> hash { Game.new(hash, @query) },
|
130
167
|
:limit => options[:limit],
|
131
|
-
:offset => options[:offset]
|
168
|
+
:offset => options[:offset],
|
169
|
+
&block
|
132
170
|
)
|
133
171
|
end
|
134
172
|
|
@@ -137,14 +175,22 @@ module Twitch::V2
|
|
137
175
|
# Twitch.games.find(:name => 'diablo')
|
138
176
|
# @example
|
139
177
|
# Twitch.games.find(:name => 'starcraft', :live => true)
|
178
|
+
# @example
|
179
|
+
# Twitch.games.find(:name => 'starcraft') do |suggestion|
|
180
|
+
# next if suggestion.name =~ /heart of the swarm/i
|
181
|
+
# puts suggestion.name
|
182
|
+
# end
|
140
183
|
# @param options [Hash] Search criteria.
|
141
184
|
# @option options [String] :name Game name search term. This can be a partial name, e.g. `"league"`.
|
142
185
|
# @option options [Boolean] :live (false) If `true`, only returns games that are currently live on at least one channel.
|
143
|
-
# @option options [Fixnum] :limit (
|
186
|
+
# @option options [Fixnum] :limit (nil) Limit on the number of results returned.
|
187
|
+
# @yield Optional. If a block is given, each game suggestion is yielded.
|
188
|
+
# @yieldparam [GameSuggestion] suggestion Current game suggestion.
|
144
189
|
# @see GameSuggestion GameSuggestion
|
145
190
|
# @see https://github.com/justintv/Twitch-API/blob/master/v2_resources/search.md#get-searchgames GET /search/games
|
146
191
|
# @raise [ArgumentError] If `:name` is not specified.
|
147
|
-
# @return [Array<GameSuggestion>]
|
192
|
+
# @return [Array<GameSuggestion>] Games matching the criteria, if no block is given.
|
193
|
+
# @return [nil] If a block is given.
|
148
194
|
def find(options)
|
149
195
|
raise ArgumentError, 'options' if options.nil?
|
150
196
|
raise ArgumentError, 'name' if options[:name].nil?
|
data/lib/kappa/status.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module Twitch
|
2
|
+
# @private
|
3
|
+
class Status
|
4
|
+
def self.map(status_map, &block)
|
5
|
+
begin
|
6
|
+
block.call
|
7
|
+
rescue Error::ClientError, Error::ServerError => e
|
8
|
+
if status_map.include? e.status
|
9
|
+
status_map[e.status]
|
10
|
+
else
|
11
|
+
raise
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/kappa/stream.rb
CHANGED
@@ -71,6 +71,26 @@ module Twitch::V2
|
|
71
71
|
attr_reader :url
|
72
72
|
end
|
73
73
|
|
74
|
+
# Site-wide stream summary statistics.
|
75
|
+
# @see Streams#summary Streams#summary
|
76
|
+
class StreamSummary
|
77
|
+
# @private
|
78
|
+
def initialize(hash)
|
79
|
+
@viewer_count = hash['viewers']
|
80
|
+
@channel_count = hash['channels']
|
81
|
+
end
|
82
|
+
|
83
|
+
# @example
|
84
|
+
# 194774
|
85
|
+
# @return [Fixnum] The sum of all viewers across all live streams.
|
86
|
+
attr_reader :viewer_count
|
87
|
+
|
88
|
+
# @example
|
89
|
+
# 4144
|
90
|
+
# @return [Fixnum] The count of all channels currently streaming.
|
91
|
+
attr_reader :channel_count
|
92
|
+
end
|
93
|
+
|
74
94
|
# Query class for finding featured streams or streams meeting certain criteria.
|
75
95
|
# @see Stream
|
76
96
|
class Streams
|
@@ -91,40 +111,79 @@ module Twitch::V2
|
|
91
111
|
# @param stream_name [String] The name of the stream to get. This is the same as the channel or user name.
|
92
112
|
# @see #find
|
93
113
|
# @see https://github.com/justintv/Twitch-API/blob/master/v2_resources/streams.md#get-streamschannel GET /streams/:channel
|
94
|
-
# @return [Stream] A valid `Stream` object if the stream exists and is
|
114
|
+
# @return [Stream] A valid `Stream` object, if the stream exists and is live.
|
115
|
+
# @return [nil] If the stream does not exist or is not live.
|
95
116
|
def get(stream_name)
|
96
|
-
|
97
|
-
|
98
|
-
stream
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
Stream.new(stream, @query)
|
117
|
+
name = CGI.escape(stream_name)
|
118
|
+
|
119
|
+
# HTTP 422 can happen if the stream is associated with a Justin.tv account.
|
120
|
+
Twitch::Status.map(404 => nil, 422 => nil) do
|
121
|
+
json = @query.connection.get("streams/#{name}")
|
122
|
+
stream = json['stream']
|
123
|
+
stream.nil? ? nil : Stream.new(stream, @query)
|
103
124
|
end
|
104
125
|
end
|
105
126
|
|
106
|
-
# Get
|
127
|
+
# Get all currently live streams.
|
128
|
+
# @example
|
129
|
+
# Twitch.streams.all
|
130
|
+
# @example
|
131
|
+
# Twitch.streams.all(:offset => 100, :limit => 10)
|
132
|
+
# @example
|
133
|
+
# Twitch.streams.all do |stream|
|
134
|
+
# next if stream.viewer_count < 1000
|
135
|
+
# puts stream.url
|
136
|
+
# end
|
137
|
+
# @param options [Hash] Limit criteria.
|
138
|
+
# @option options [Fixnum] :limit (nil) Limit on the number of results returned.
|
139
|
+
# @option options [Fixnum] :offset (0) Offset into the result set to begin enumeration.
|
140
|
+
# @yield Optional. If a block is given, each stream is yielded.
|
141
|
+
# @yieldparam [Stream] stream Current stream.
|
142
|
+
# @see #get
|
143
|
+
# @see https://github.com/justintv/Twitch-API/blob/master/v2_resources/streams.md#get-streams GET /streams
|
144
|
+
# @return [Array<Stream>] Currently live streams, if no block is given.
|
145
|
+
# @return [nil] If a block is given.
|
146
|
+
def all(options = {}, &block)
|
147
|
+
return @query.connection.accumulate(
|
148
|
+
:path => 'streams',
|
149
|
+
:json => 'streams',
|
150
|
+
:create => -> hash { Stream.new(hash, @query) },
|
151
|
+
:limit => options[:limit],
|
152
|
+
:offset => options[:offset],
|
153
|
+
&block
|
154
|
+
)
|
155
|
+
end
|
156
|
+
|
157
|
+
# Get streams for a specific game, for a set of channels, or by other criteria.
|
107
158
|
# @example
|
108
159
|
# Twitch.streams.find(:game => 'League of Legends', :limit => 50)
|
109
160
|
# @example
|
110
161
|
# Twitch.streams.find(:channel => ['fgtvlive', 'incontroltv', 'destiny'])
|
111
162
|
# @example
|
112
163
|
# Twitch.streams.find(:game => 'Diablo III', :channel => ['nl_kripp', 'protech'])
|
164
|
+
# @example
|
165
|
+
# Twitch.streams.find(:game => 'League of Legends') do |stream|
|
166
|
+
# next if stream.viewer_count < 1000
|
167
|
+
# puts stream.url
|
168
|
+
# end
|
113
169
|
# @param options [Hash] Search criteria.
|
114
|
-
# @option options [String
|
115
|
-
# @option options [Array<String
|
170
|
+
# @option options [String, Game, #name] :game Only return streams currently streaming the specified game.
|
171
|
+
# @option options [Array<String, Channel, #name>] :channel Only return streams for these channels.
|
116
172
|
# If a channel is not currently streaming, it is omitted. You must specify an array of channels
|
117
173
|
# or channel names. If you want to find the stream for a single channel, see {Streams#get}.
|
118
174
|
# @option options [Boolean] :embeddable (nil) If `true`, limit the streams to those that can be embedded. If `false` or `nil`, do not limit.
|
119
175
|
# @option options [Boolean] :hls (nil) If `true`, limit the streams to those using HLS (HTTP Live Streaming). If `false` or `nil`, do not limit.
|
120
|
-
# @option options [Fixnum] :limit (
|
176
|
+
# @option options [Fixnum] :limit (nil) Limit on the number of results returned.
|
121
177
|
# @option options [Fixnum] :offset (0) Offset into the result set to begin enumeration.
|
178
|
+
# @yield Optional. If a block is given, each stream found is yielded.
|
179
|
+
# @yieldparam [Stream] stream Current stream.
|
122
180
|
# @see #get
|
123
181
|
# @see https://github.com/justintv/Twitch-API/blob/master/v2_resources/streams.md#get-streams GET /streams
|
124
182
|
# @raise [ArgumentError] If `options` does not specify a search criteria (`:game`, `:channel`, `:embeddable`, or `:hls`).
|
125
183
|
# @raise [ArgumentError] If `:channel` is not an array.
|
126
|
-
# @return [Array<Stream>]
|
127
|
-
|
184
|
+
# @return [Array<Stream>] Streams matching the specified criteria, if no block is given.
|
185
|
+
# @return [nil] If a block is given.
|
186
|
+
def find(options, &block)
|
128
187
|
check = options.dup
|
129
188
|
check.delete(:limit)
|
130
189
|
check.delete(:offset)
|
@@ -170,23 +229,32 @@ module Twitch::V2
|
|
170
229
|
:json => 'streams',
|
171
230
|
:create => -> hash { Stream.new(hash, @query) },
|
172
231
|
:limit => options[:limit],
|
173
|
-
:offset => options[:offset]
|
232
|
+
:offset => options[:offset],
|
233
|
+
&block
|
174
234
|
)
|
175
235
|
end
|
176
236
|
|
177
|
-
# Get the
|
237
|
+
# Get the currently featured (promoted) streams. This includes the streams shown on the Twitch homepage.
|
178
238
|
# @note There is no guarantee of how many streams are featured at any given time.
|
179
239
|
# @example
|
180
240
|
# Twitch.streams.featured
|
181
241
|
# @example
|
182
242
|
# Twitch.streams.featured(:limit => 5)
|
243
|
+
# @example
|
244
|
+
# Twitch.streams.featured do |stream|
|
245
|
+
# next if stream.viewer_count < 1000
|
246
|
+
# puts stream.url
|
247
|
+
# end
|
183
248
|
# @param options [Hash] Filter criteria.
|
184
249
|
# @option options [Boolean] :hls (nil) If `true`, limit the streams to those using HLS (HTTP Live Streaming). If `false` or `nil`, do not limit.
|
185
|
-
# @option options [Fixnum] :limit (
|
250
|
+
# @option options [Fixnum] :limit (nil) Limit on the number of results returned.
|
186
251
|
# @option options [Fixnum] :offset (0) Offset into the result set to begin enumeration.
|
252
|
+
# @yield Optional. If a block is given, each featured stream is yielded.
|
253
|
+
# @yieldparam [Stream] stream Current stream.
|
187
254
|
# @see https://github.com/justintv/Twitch-API/blob/master/v2_resources/streams.md#get-streamsfeatured GET /streams/featured
|
188
|
-
# @return [Array<Stream>]
|
189
|
-
|
255
|
+
# @return [Array<Stream>] Featured streams, if no block is given.
|
256
|
+
# @return [nil] If a block is given.
|
257
|
+
def featured(options = {}, &block)
|
190
258
|
params = {}
|
191
259
|
|
192
260
|
if options[:hls]
|
@@ -200,8 +268,21 @@ module Twitch::V2
|
|
200
268
|
:sub_json => 'stream',
|
201
269
|
:create => -> hash { Stream.new(hash, @query) },
|
202
270
|
:limit => options[:limit],
|
203
|
-
:offset => options[:offset]
|
271
|
+
:offset => options[:offset],
|
272
|
+
&block
|
204
273
|
)
|
205
274
|
end
|
275
|
+
|
276
|
+
# Get site-wide stream summary statistics.
|
277
|
+
# @example
|
278
|
+
# summary = Twitch.streams.summary
|
279
|
+
# summary.viewer_count # => 194774
|
280
|
+
# summary.channel_count # => 4144
|
281
|
+
# @see https://github.com/justintv/Twitch-API/blob/master/v2_resources/streams.md#gedt-streamssummary GET /streams/summary
|
282
|
+
# @return [StreamSummary] Stream summary statistics.
|
283
|
+
def summary
|
284
|
+
json = @query.connection.get('streams/summary')
|
285
|
+
StreamSummary.new(json)
|
286
|
+
end
|
206
287
|
end
|
207
288
|
end
|
data/lib/kappa/team.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'cgi'
|
1
2
|
require 'time'
|
2
3
|
|
3
4
|
module Twitch::V2
|
@@ -20,7 +21,9 @@ module Twitch::V2
|
|
20
21
|
@display_name = hash['display_name']
|
21
22
|
@updated_at = Time.parse(hash['updated_at']).utc
|
22
23
|
@created_at = Time.parse(hash['created_at']).utc
|
23
|
-
|
24
|
+
|
25
|
+
name = CGI.escape(@name)
|
26
|
+
@url = "http://www.twitch.tv/team/#{name}"
|
24
27
|
end
|
25
28
|
|
26
29
|
# @example
|
@@ -91,10 +94,9 @@ module Twitch::V2
|
|
91
94
|
# @return [Team] A valid `Team` object if the team exists, `nil` otherwise.
|
92
95
|
# @see https://github.com/justintv/Twitch-API/blob/master/v2_resources/teams.md#get-teamsteam GET /teams/:team
|
93
96
|
def get(team_name)
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
else
|
97
|
+
name = CGI.escape(team_name)
|
98
|
+
Twitch::Status.map(404 => nil) do
|
99
|
+
json = @query.connection.get("teams/#{name}")
|
98
100
|
Team.new(json)
|
99
101
|
end
|
100
102
|
end
|
@@ -104,17 +106,26 @@ module Twitch::V2
|
|
104
106
|
# Twitch.teams.all
|
105
107
|
# @example
|
106
108
|
# Twitch.teams.all(:limit => 10)
|
109
|
+
# @example
|
110
|
+
# Twitch.teams do |team|
|
111
|
+
# next if (Time.now - team.updated_at) > (60 * 60 * 24)
|
112
|
+
# puts team.url
|
113
|
+
# end
|
107
114
|
# @param options [Hash] Filter criteria.
|
108
|
-
# @option options [Fixnum] :limit (
|
115
|
+
# @option options [Fixnum] :limit (nil) Limit on the number of results returned.
|
116
|
+
# @yield Optional. If a block is given, each team is yielded.
|
117
|
+
# @yieldparam [Team] team Current team.
|
109
118
|
# @see https://github.com/justintv/Twitch-API/blob/master/v2_resources/teams.md#get-teams GET /teams
|
110
|
-
# @return [Array<Team>]
|
111
|
-
|
119
|
+
# @return [Array<Team>] All active teams, if no block is given.
|
120
|
+
# @return [nil] If a block is given.
|
121
|
+
def all(options = {}, &block)
|
112
122
|
return @query.connection.accumulate(
|
113
123
|
:path => 'teams',
|
114
124
|
:json => 'teams',
|
115
125
|
:create => Team,
|
116
126
|
:limit => options[:limit],
|
117
|
-
:offset => options[:offset]
|
127
|
+
:offset => options[:offset],
|
128
|
+
&block
|
118
129
|
)
|
119
130
|
end
|
120
131
|
end
|
data/lib/kappa/user.rb
CHANGED
@@ -54,27 +54,39 @@ module Twitch::V2
|
|
54
54
|
end
|
55
55
|
|
56
56
|
# Get the channels the user is currently following.
|
57
|
+
# @example
|
58
|
+
# user.following(:limit => 10)
|
59
|
+
# @example
|
60
|
+
# user.following do |channel|
|
61
|
+
# next if channel.game_name !~ /starcraft/i
|
62
|
+
# puts channel.display_name
|
63
|
+
# end
|
57
64
|
# @param options [Hash] Filter criteria.
|
58
|
-
# @option options [Fixnum] :limit (
|
65
|
+
# @option options [Fixnum] :limit (nil) Limit on the number of results returned.
|
59
66
|
# @option options [Fixnum] :offset (0) Offset into the result set to begin enumeration.
|
67
|
+
# @yield Optional. If a block is given, each followed channel is yielded.
|
68
|
+
# @yieldparam [Channel] channel Current channel.
|
60
69
|
# @see #following?
|
61
70
|
# @see https://github.com/justintv/Twitch-API/blob/master/v2_resources/follows.md#get-usersuserfollowschannels GET /users/:user/follows/channels
|
62
|
-
# @return [Array<Channel>]
|
63
|
-
|
71
|
+
# @return [Array<Channel>] Channels the user is currently following, if no block is given.
|
72
|
+
# @return [nil] If a block is given.
|
73
|
+
def following(options = {}, &block)
|
74
|
+
name = CGI.escape(@name)
|
64
75
|
return @query.connection.accumulate(
|
65
|
-
:path => "users/#{
|
76
|
+
:path => "users/#{name}/follows/channels",
|
66
77
|
:json => 'follows',
|
67
78
|
:sub_json => 'channel',
|
68
79
|
:create => -> hash { Channel.new(hash, @query) },
|
69
80
|
:limit => options[:limit],
|
70
|
-
:offset => options[:offset]
|
81
|
+
:offset => options[:offset],
|
82
|
+
&block
|
71
83
|
)
|
72
84
|
end
|
73
85
|
|
74
|
-
# @param
|
86
|
+
# @param target [String, Channel, User, Stream, #name] The name of the channel to check.
|
75
87
|
# @return [Boolean] `true` if the user is following the channel, `false` otherwise.
|
76
88
|
# @see #following
|
77
|
-
# @see https://github.com/justintv/Twitch-API/blob/master/v2_resources/follows.md#get-usersuserfollowschannelstarget GET /users/:user/follows
|
89
|
+
# @see https://github.com/justintv/Twitch-API/blob/master/v2_resources/follows.md#get-usersuserfollowschannelstarget GET /users/:user/follows/channels/:target
|
78
90
|
def following?(target)
|
79
91
|
name = if target.respond_to?(:name)
|
80
92
|
target.name
|
@@ -82,11 +94,13 @@ module Twitch::V2
|
|
82
94
|
target.to_s
|
83
95
|
end
|
84
96
|
|
85
|
-
|
97
|
+
user_name = CGI.escape(@name)
|
98
|
+
channel_name = CGI.escape(name)
|
86
99
|
|
87
|
-
|
88
|
-
|
89
|
-
|
100
|
+
Twitch::Status.map(404 => false) do
|
101
|
+
@query.connection.get("users/#{user_name}/follows/channels/#{channel_name}")
|
102
|
+
true
|
103
|
+
end
|
90
104
|
end
|
91
105
|
|
92
106
|
# @example
|
@@ -135,11 +149,9 @@ module Twitch::V2
|
|
135
149
|
# @see https://github.com/justintv/Twitch-API/blob/master/v2_resources/users.md#get-usersuser GET /users/:user
|
136
150
|
# @return [User] A valid `User` object if the user exists, `nil` otherwise.
|
137
151
|
def get(user_name)
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
nil
|
142
|
-
else
|
152
|
+
name = CGI.escape(user_name)
|
153
|
+
Twitch::Status.map(404 => nil) do
|
154
|
+
json = @query.connection.get("users/#{name}")
|
143
155
|
User.new(json, @query)
|
144
156
|
end
|
145
157
|
end
|
data/lib/kappa/version.rb
CHANGED
data/lib/kappa/video.rb
CHANGED
@@ -120,11 +120,9 @@ module Twitch::V2
|
|
120
120
|
def get(id)
|
121
121
|
raise ArgumentError, 'id' if !id || id.strip.empty?
|
122
122
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
nil
|
127
|
-
else
|
123
|
+
id = CGI.escape(id)
|
124
|
+
Twitch::Status.map(404 => nil) do
|
125
|
+
json = @query.connection.get("videos/#{id}")
|
128
126
|
Video.new(json, @query)
|
129
127
|
end
|
130
128
|
end
|
@@ -137,15 +135,23 @@ module Twitch::V2
|
|
137
135
|
# Twitch.videos.top(:period => :month, :game => 'Super Meat Boy')
|
138
136
|
# @example
|
139
137
|
# Twitch.videos.top(:period => :all, :limit => 10)
|
138
|
+
# @example
|
139
|
+
# Twitch.videos.top(:period => :all) do |video|
|
140
|
+
# next if video.view_count < 10000
|
141
|
+
# puts video.url
|
142
|
+
# end
|
140
143
|
# @param options [Hash] Filter criteria.
|
141
144
|
# @option options [Symbol] :period (:week) Return videos only in this time period. Valid values are `:week`, `:month`, `:all`.
|
142
145
|
# @option options [String] :game (nil) Return videos only for this game.
|
143
|
-
# @option options [Fixnum] :limit (
|
146
|
+
# @option options [Fixnum] :limit (nil) Limit on the number of results returned.
|
144
147
|
# @option options [Fixnum] :offset (0) Offset into the result set to begin enumeration.
|
148
|
+
# @yield Optional. If a block is given, each top video is yielded.
|
149
|
+
# @yieldparam [Video] video Current video.
|
145
150
|
# @see https://github.com/justintv/Twitch-API/blob/master/v2_resources/videos.md#get-videostop GET /videos/top
|
146
151
|
# @raise [ArgumentError] If `:period` is not one of `:week`, `:month`, or `:all`.
|
147
|
-
# @return [Array<Video>]
|
148
|
-
|
152
|
+
# @return [Array<Video>] Top videos, if no block is given.
|
153
|
+
# @return [nil] If a block is given.
|
154
|
+
def top(options = {}, &block)
|
149
155
|
params = {}
|
150
156
|
|
151
157
|
if options[:game]
|
@@ -165,6 +171,57 @@ module Twitch::V2
|
|
165
171
|
:json => 'videos',
|
166
172
|
:create => -> hash { Video.new(hash, @query) },
|
167
173
|
:limit => options[:limit],
|
174
|
+
:offset => options[:offset],
|
175
|
+
&block
|
176
|
+
)
|
177
|
+
end
|
178
|
+
|
179
|
+
# Get the videos for a channel, most recently created first.
|
180
|
+
# @example
|
181
|
+
# v = Twitch.videos.for_channel('dreamhacktv')
|
182
|
+
# @example
|
183
|
+
# v = Twitch.videos.for_channel('dreamhacktv', :type => :highlights, :limit => 10)
|
184
|
+
# @example
|
185
|
+
# Twitch.videos.for_channel('dreamhacktv') do |video|
|
186
|
+
# next if video.view_count < 10000
|
187
|
+
# puts video.url
|
188
|
+
# end
|
189
|
+
# @param options [Hash] Filter criteria.
|
190
|
+
# @option options [Symbol] :type (:highlights) The type of videos to return. Valid values are `:broadcasts`, `:highlights`.
|
191
|
+
# @option options [Fixnum] :limit (nil) Limit on the number of results returned.
|
192
|
+
# @option options [Fixnum] :offset (0) Offset into the result set to begin enumeration.
|
193
|
+
# @yield Optional. If a block is given, each video is yielded.
|
194
|
+
# @yieldparam [Video] video Current video.
|
195
|
+
# @see Channel#videos Channel#videos
|
196
|
+
# @see https://github.com/justintv/Twitch-API/blob/master/v2_resources/videos.md#get-channelschannelvideos GET /channels/:channel/videos
|
197
|
+
# @raise [ArgumentError] If `:type` is not one of `:broadcasts` or `:highlights`.
|
198
|
+
# @return [Array<Video>] Videos for the channel, if no block is given.
|
199
|
+
# @return [nil] If a block is given.
|
200
|
+
def for_channel(channel, options = {})
|
201
|
+
if channel.respond_to?(:name)
|
202
|
+
channel_name = channel.name
|
203
|
+
else
|
204
|
+
channel_name = channel.to_s
|
205
|
+
end
|
206
|
+
|
207
|
+
params = {}
|
208
|
+
|
209
|
+
type = options[:type] || :highlights
|
210
|
+
if !type.nil?
|
211
|
+
if ![:broadcasts, :highlights].include?(type)
|
212
|
+
raise ArgumentError, 'type'
|
213
|
+
end
|
214
|
+
|
215
|
+
params[:broadcasts] = (type == :broadcasts)
|
216
|
+
end
|
217
|
+
|
218
|
+
name = CGI.escape(channel_name)
|
219
|
+
return @query.connection.accumulate(
|
220
|
+
:path => "channels/#{name}/videos",
|
221
|
+
:params => params,
|
222
|
+
:json => 'videos',
|
223
|
+
:create => -> hash { Video.new(hash, @query) },
|
224
|
+
:limit => options[:limit],
|
168
225
|
:offset => options[:offset]
|
169
226
|
)
|
170
227
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kappa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-08-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: httparty
|
@@ -171,8 +171,8 @@ dependencies:
|
|
171
171
|
- - ! '>='
|
172
172
|
- !ruby/object:Gem::Version
|
173
173
|
version: '0'
|
174
|
-
description: ! "
|
175
|
-
users, channels, streams, and
|
174
|
+
description: ! " The Ruby library for interfacing with the Twitch.tv API\n including
|
175
|
+
users, channels, streams, games, and videos.\n"
|
176
176
|
email: schmch@gmail.com
|
177
177
|
executables: []
|
178
178
|
extensions: []
|
@@ -185,8 +185,10 @@ files:
|
|
185
185
|
- lib/kappa/team.rb
|
186
186
|
- lib/kappa/images.rb
|
187
187
|
- lib/kappa/user.rb
|
188
|
+
- lib/kappa/status.rb
|
188
189
|
- lib/kappa/id_equality.rb
|
189
190
|
- lib/kappa/query.rb
|
191
|
+
- lib/kappa/errors.rb
|
190
192
|
- lib/kappa/channel.rb
|
191
193
|
- lib/kappa/proxy.rb
|
192
194
|
- lib/kappa/game.rb
|