kappa 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +6 -0
- data/LICENSE +19 -0
- data/README.md +285 -285
- data/lib/kappa.rb +15 -15
- data/lib/kappa/channel.rb +214 -214
- data/lib/kappa/configuration.rb +88 -88
- data/lib/kappa/connection.rb +139 -139
- data/lib/kappa/errors.rb +43 -43
- data/lib/kappa/game.rb +216 -216
- data/lib/kappa/id_equality.rb +17 -17
- data/lib/kappa/images.rb +44 -44
- data/lib/kappa/proxy.rb +32 -32
- data/lib/kappa/query.rb +22 -22
- data/lib/kappa/status.rb +16 -16
- data/lib/kappa/stream.rb +288 -288
- data/lib/kappa/team.rb +132 -132
- data/lib/kappa/user.rb +159 -159
- data/lib/kappa/version.rb +3 -3
- data/lib/kappa/video.rb +229 -229
- metadata +18 -16
data/lib/kappa/configuration.rb
CHANGED
@@ -1,88 +1,88 @@
|
|
1
|
-
require 'securerandom'
|
2
|
-
|
3
|
-
module Twitch
|
4
|
-
@query = nil
|
5
|
-
|
6
|
-
# Configure global settings for interacting with Twitch. Future requests
|
7
|
-
# through the `Twitch` module will use these settings.
|
8
|
-
# @example
|
9
|
-
# Twitch.configure do |config|
|
10
|
-
# config.client_id = 'sc2daily-v1.0.0'
|
11
|
-
# config.api = Twitch::V2
|
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
|
22
|
-
def self.configure(&block)
|
23
|
-
@query = instance(&block)
|
24
|
-
nil
|
25
|
-
end
|
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.
|
48
|
-
def self.instance(&block)
|
49
|
-
config = Configuration.new
|
50
|
-
config.instance_eval(&block)
|
51
|
-
connection = config.create(:Connection, config.client_id)
|
52
|
-
return config.create(:Query, connection)
|
53
|
-
end
|
54
|
-
|
55
|
-
# @private
|
56
|
-
def self.method_missing(*args)
|
57
|
-
@query ||= create_default_query
|
58
|
-
@query.send(*args)
|
59
|
-
end
|
60
|
-
|
61
|
-
# @private
|
62
|
-
class Configuration
|
63
|
-
def initialize
|
64
|
-
@api = Twitch::V2
|
65
|
-
end
|
66
|
-
|
67
|
-
def client_id
|
68
|
-
# Generate a random client_id if it's not already set.
|
69
|
-
@client_id ||= "Kappa-%s" % SecureRandom.uuid
|
70
|
-
@client_id
|
71
|
-
end
|
72
|
-
|
73
|
-
def create(symbol, *args)
|
74
|
-
@api.const_get(symbol).new(*args)
|
75
|
-
end
|
76
|
-
|
77
|
-
attr_writer :client_id
|
78
|
-
attr_accessor :api
|
79
|
-
end
|
80
|
-
|
81
|
-
private
|
82
|
-
# @private
|
83
|
-
def self.create_default_query
|
84
|
-
config = Configuration.new
|
85
|
-
connection = config.create(:Connection, config.client_id)
|
86
|
-
return config.create(:Query, connection)
|
87
|
-
end
|
88
|
-
end
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
module Twitch
|
4
|
+
@query = nil
|
5
|
+
|
6
|
+
# Configure global settings for interacting with Twitch. Future requests
|
7
|
+
# through the `Twitch` module will use these settings.
|
8
|
+
# @example
|
9
|
+
# Twitch.configure do |config|
|
10
|
+
# config.client_id = 'sc2daily-v1.0.0'
|
11
|
+
# config.api = Twitch::V2
|
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
|
22
|
+
def self.configure(&block)
|
23
|
+
@query = instance(&block)
|
24
|
+
nil
|
25
|
+
end
|
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.
|
48
|
+
def self.instance(&block)
|
49
|
+
config = Configuration.new
|
50
|
+
config.instance_eval(&block)
|
51
|
+
connection = config.create(:Connection, config.client_id)
|
52
|
+
return config.create(:Query, connection)
|
53
|
+
end
|
54
|
+
|
55
|
+
# @private
|
56
|
+
def self.method_missing(*args)
|
57
|
+
@query ||= create_default_query
|
58
|
+
@query.send(*args)
|
59
|
+
end
|
60
|
+
|
61
|
+
# @private
|
62
|
+
class Configuration
|
63
|
+
def initialize
|
64
|
+
@api = Twitch::V2
|
65
|
+
end
|
66
|
+
|
67
|
+
def client_id
|
68
|
+
# Generate a random client_id if it's not already set.
|
69
|
+
@client_id ||= "Kappa-%s" % SecureRandom.uuid
|
70
|
+
@client_id
|
71
|
+
end
|
72
|
+
|
73
|
+
def create(symbol, *args)
|
74
|
+
@api.const_get(symbol).new(*args)
|
75
|
+
end
|
76
|
+
|
77
|
+
attr_writer :client_id
|
78
|
+
attr_accessor :api
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
# @private
|
83
|
+
def self.create_default_query
|
84
|
+
config = Configuration.new
|
85
|
+
connection = config.create(:Connection, config.client_id)
|
86
|
+
return config.create(:Query, connection)
|
87
|
+
end
|
88
|
+
end
|
data/lib/kappa/connection.rb
CHANGED
@@ -1,139 +1,139 @@
|
|
1
|
-
require 'httparty'
|
2
|
-
require 'addressable/uri'
|
3
|
-
require 'json'
|
4
|
-
require 'set'
|
5
|
-
|
6
|
-
module Twitch
|
7
|
-
# @private
|
8
|
-
class Connection
|
9
|
-
include HTTParty
|
10
|
-
|
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
|
-
|
15
|
-
@client_id = client_id
|
16
|
-
@base_url = Addressable::URI.parse(base_url)
|
17
|
-
end
|
18
|
-
|
19
|
-
def get(path, query = nil)
|
20
|
-
raise ArgumentError, 'path' if !path || path.empty?
|
21
|
-
|
22
|
-
request_url = @base_url + path
|
23
|
-
|
24
|
-
all_headers = {
|
25
|
-
'Client-ID' => @client_id,
|
26
|
-
'Kappa-Version' => Twitch::VERSION
|
27
|
-
}.merge(headers())
|
28
|
-
|
29
|
-
response = self.class.get(request_url, :headers => all_headers, :query => query)
|
30
|
-
|
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
|
49
|
-
end
|
50
|
-
|
51
|
-
def accumulate(options, &block)
|
52
|
-
path = options[:path]
|
53
|
-
params = options[:params] || {}
|
54
|
-
json = options[:json]
|
55
|
-
sub_json = options[:sub_json]
|
56
|
-
create = options[:create]
|
57
|
-
|
58
|
-
raise ArgumentError, 'json' if json.nil?
|
59
|
-
raise ArgumentError, 'path' if path.nil?
|
60
|
-
raise ArgumentError, 'create' if create.nil?
|
61
|
-
|
62
|
-
if create.is_a? Class
|
63
|
-
klass = create
|
64
|
-
create = -> hash { klass.new(hash) }
|
65
|
-
end
|
66
|
-
|
67
|
-
total_limit = options[:limit]
|
68
|
-
page_limit = [total_limit || 100, 100].min
|
69
|
-
offset = options[:offset] || 0
|
70
|
-
|
71
|
-
ids = Set.new
|
72
|
-
objects = []
|
73
|
-
count = 0
|
74
|
-
|
75
|
-
block ||= -> object {
|
76
|
-
objects << object
|
77
|
-
}
|
78
|
-
|
79
|
-
paginate(path, page_limit, offset, params) do |response_json|
|
80
|
-
current_objects = response_json[json]
|
81
|
-
current_objects.each do |object_json|
|
82
|
-
object_json = object_json[sub_json] if sub_json
|
83
|
-
object = create.call(object_json)
|
84
|
-
if ids.add?(object.id)
|
85
|
-
count += 1
|
86
|
-
block.call(object)
|
87
|
-
if count == total_limit
|
88
|
-
return block_given? ? nil : objects
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
break if current_objects.empty? || (current_objects.count < page_limit)
|
94
|
-
end
|
95
|
-
|
96
|
-
return block_given? ? nil : objects
|
97
|
-
end
|
98
|
-
|
99
|
-
def paginate(path, limit, offset, params = {})
|
100
|
-
path_uri = Addressable::URI.parse(path)
|
101
|
-
query = { 'limit' => limit, 'offset' => offset }
|
102
|
-
path_uri.query_values ||= {}
|
103
|
-
path_uri.query_values = path_uri.query_values.merge(query)
|
104
|
-
|
105
|
-
request_url = path_uri.to_s
|
106
|
-
|
107
|
-
json = get(request_url, params)
|
108
|
-
|
109
|
-
loop do
|
110
|
-
break if json['error'] && (json['status'] == 503)
|
111
|
-
yield json
|
112
|
-
|
113
|
-
links = json['_links']
|
114
|
-
next_url = links['next']
|
115
|
-
|
116
|
-
next_uri = Addressable::URI.parse(next_url)
|
117
|
-
offset = next_uri.query_values['offset'].to_i
|
118
|
-
|
119
|
-
total = json['_total']
|
120
|
-
break if total && (offset > total)
|
121
|
-
|
122
|
-
request_url = next_url
|
123
|
-
json = get(request_url, params)
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
private
|
128
|
-
DEFAULT_BASE_URL = 'https://api.twitch.tv/kraken/'
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
module Twitch::V2
|
133
|
-
# @private
|
134
|
-
class Connection < Twitch::Connection
|
135
|
-
def headers
|
136
|
-
{ 'Accept' => 'application/vnd.twitchtv.v2+json' }
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
1
|
+
require 'httparty'
|
2
|
+
require 'addressable/uri'
|
3
|
+
require 'json'
|
4
|
+
require 'set'
|
5
|
+
|
6
|
+
module Twitch
|
7
|
+
# @private
|
8
|
+
class Connection
|
9
|
+
include HTTParty
|
10
|
+
|
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
|
+
|
15
|
+
@client_id = client_id
|
16
|
+
@base_url = Addressable::URI.parse(base_url)
|
17
|
+
end
|
18
|
+
|
19
|
+
def get(path, query = nil)
|
20
|
+
raise ArgumentError, 'path' if !path || path.empty?
|
21
|
+
|
22
|
+
request_url = @base_url + path
|
23
|
+
|
24
|
+
all_headers = {
|
25
|
+
'Client-ID' => @client_id,
|
26
|
+
'Kappa-Version' => Twitch::VERSION
|
27
|
+
}.merge(headers())
|
28
|
+
|
29
|
+
response = self.class.get(request_url, :headers => all_headers, :query => query)
|
30
|
+
|
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
|
49
|
+
end
|
50
|
+
|
51
|
+
def accumulate(options, &block)
|
52
|
+
path = options[:path]
|
53
|
+
params = options[:params] || {}
|
54
|
+
json = options[:json]
|
55
|
+
sub_json = options[:sub_json]
|
56
|
+
create = options[:create]
|
57
|
+
|
58
|
+
raise ArgumentError, 'json' if json.nil?
|
59
|
+
raise ArgumentError, 'path' if path.nil?
|
60
|
+
raise ArgumentError, 'create' if create.nil?
|
61
|
+
|
62
|
+
if create.is_a? Class
|
63
|
+
klass = create
|
64
|
+
create = -> hash { klass.new(hash) }
|
65
|
+
end
|
66
|
+
|
67
|
+
total_limit = options[:limit]
|
68
|
+
page_limit = [total_limit || 100, 100].min
|
69
|
+
offset = options[:offset] || 0
|
70
|
+
|
71
|
+
ids = Set.new
|
72
|
+
objects = []
|
73
|
+
count = 0
|
74
|
+
|
75
|
+
block ||= -> object {
|
76
|
+
objects << object
|
77
|
+
}
|
78
|
+
|
79
|
+
paginate(path, page_limit, offset, params) do |response_json|
|
80
|
+
current_objects = response_json[json]
|
81
|
+
current_objects.each do |object_json|
|
82
|
+
object_json = object_json[sub_json] if sub_json
|
83
|
+
object = create.call(object_json)
|
84
|
+
if ids.add?(object.id)
|
85
|
+
count += 1
|
86
|
+
block.call(object)
|
87
|
+
if count == total_limit
|
88
|
+
return block_given? ? nil : objects
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
break if current_objects.empty? || (current_objects.count < page_limit)
|
94
|
+
end
|
95
|
+
|
96
|
+
return block_given? ? nil : objects
|
97
|
+
end
|
98
|
+
|
99
|
+
def paginate(path, limit, offset, params = {})
|
100
|
+
path_uri = Addressable::URI.parse(path)
|
101
|
+
query = { 'limit' => limit, 'offset' => offset }
|
102
|
+
path_uri.query_values ||= {}
|
103
|
+
path_uri.query_values = path_uri.query_values.merge(query)
|
104
|
+
|
105
|
+
request_url = path_uri.to_s
|
106
|
+
|
107
|
+
json = get(request_url, params)
|
108
|
+
|
109
|
+
loop do
|
110
|
+
break if json['error'] && (json['status'] == 503)
|
111
|
+
yield json
|
112
|
+
|
113
|
+
links = json['_links']
|
114
|
+
next_url = links['next']
|
115
|
+
|
116
|
+
next_uri = Addressable::URI.parse(next_url)
|
117
|
+
offset = next_uri.query_values['offset'].to_i
|
118
|
+
|
119
|
+
total = json['_total']
|
120
|
+
break if total && (offset > total)
|
121
|
+
|
122
|
+
request_url = next_url
|
123
|
+
json = get(request_url, params)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
private
|
128
|
+
DEFAULT_BASE_URL = 'https://api.twitch.tv/kraken/'
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
module Twitch::V2
|
133
|
+
# @private
|
134
|
+
class Connection < Twitch::Connection
|
135
|
+
def headers
|
136
|
+
{ 'Accept' => 'application/vnd.twitchtv.v2+json' }
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|