kappa 1.0.1 → 1.0.2
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.
- checksums.yaml +7 -0
- data/.yardopts +6 -6
- data/LICENSE +19 -19
- 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 +289 -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 +23 -44
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
|