rublox 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/Gemfile +6 -6
- data/LICENSE +21 -21
- data/{README.MD → README.md} +68 -68
- data/Rakefile +33 -33
- data/lib/rublox/derive/group.rb +50 -50
- data/lib/rublox/derive/user.rb +89 -89
- data/lib/rublox/models/full_group.rb +60 -60
- data/lib/rublox/models/full_user.rb +49 -49
- data/lib/rublox/models/group_member.rb +54 -54
- data/lib/rublox/models/group_role.rb +355 -70
- data/lib/rublox/models/group_shout.rb +62 -62
- data/lib/rublox/models/limited_user.rb +34 -34
- data/lib/rublox/models/presence.rb +98 -98
- data/lib/rublox/util/cache.rb +39 -39
- data/lib/rublox/util/errors.rb +109 -109
- data/lib/rublox/util/http_client.rb +95 -95
- data/lib/rublox/util/pages.rb +85 -85
- data/lib/rublox/util/url.rb +25 -25
- data/lib/rublox/version.rb +6 -6
- data/lib/rublox.rb +136 -136
- data/rublox.gemspec +32 -32
- metadata +5 -6
- data/CHANGELOG.MD +0 -4
@@ -1,95 +1,95 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "http"
|
4
|
-
require "json"
|
5
|
-
|
6
|
-
require "rublox/util/errors"
|
7
|
-
|
8
|
-
module Rublox
|
9
|
-
# @note Only use if you have an use case that the library doesn't cover (and
|
10
|
-
# create an issue and perhaps we'll implement it!).
|
11
|
-
# The {HTTPClient} is a wrapper around the http library, designed specifically
|
12
|
-
# for the Roblox API. It automatically handles the X-CSRF-TOKEN and the
|
13
|
-
# .ROBLOSECURITY cookie.
|
14
|
-
class HTTPClient
|
15
|
-
# @param roblosecurity [String]
|
16
|
-
def initialize(roblosecurity = "")
|
17
|
-
@client = HTTP.cookies(
|
18
|
-
{
|
19
|
-
".ROBLOSECURITY": roblosecurity
|
20
|
-
}
|
21
|
-
)
|
22
|
-
end
|
23
|
-
|
24
|
-
# Send a GET request to the specified URL.
|
25
|
-
# @param url [String]
|
26
|
-
# @return [Hash]
|
27
|
-
def get(url, *args)
|
28
|
-
request(:get, url, *args)
|
29
|
-
end
|
30
|
-
|
31
|
-
# Send a POST request to the specified URL.
|
32
|
-
# @param url [String]
|
33
|
-
# @return [Hash]
|
34
|
-
def post(url, *args)
|
35
|
-
request(:post, url, *args)
|
36
|
-
end
|
37
|
-
|
38
|
-
# Send a PATCH request to the specified URL.
|
39
|
-
# @param url [String]
|
40
|
-
# @return [Hash]
|
41
|
-
def patch(url, *args)
|
42
|
-
request(:patch, url, *args)
|
43
|
-
end
|
44
|
-
|
45
|
-
# Send a DELETE request to the specified URL.
|
46
|
-
# @param url [String]
|
47
|
-
# @return [Hash]
|
48
|
-
def delete(url, *args)
|
49
|
-
request(:delete, url, *args)
|
50
|
-
end
|
51
|
-
|
52
|
-
private
|
53
|
-
|
54
|
-
# @param verb [Symbol]
|
55
|
-
# @param url [String]
|
56
|
-
# @return [Hash]
|
57
|
-
def request(verb, url, *args)
|
58
|
-
response = @client.request(verb, url, *args)
|
59
|
-
return JSON.parse(response.body) if response.status == 200
|
60
|
-
|
61
|
-
handle_status_code(response, verb, url, *args)
|
62
|
-
end
|
63
|
-
|
64
|
-
# @param response [HTTP::Response]
|
65
|
-
def handle_status_code(response, verb, url, *args)
|
66
|
-
case response.status
|
67
|
-
# token validation failed
|
68
|
-
when 403
|
69
|
-
@client = @client.headers(
|
70
|
-
{
|
71
|
-
"x-csrf-token": response.headers["x-csrf-token"]
|
72
|
-
}
|
73
|
-
)
|
74
|
-
# retry the request
|
75
|
-
request(verb, url, *args)
|
76
|
-
# invalid .ROBLOSECURITY cookie
|
77
|
-
when 401
|
78
|
-
raise Errors::InvalidROBLOSECURITYError
|
79
|
-
else
|
80
|
-
raise Errors::UnhandledStatusCodeError.new(response.status, get_errors_from_response(response))
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
# @param response [HTTP::Response]
|
85
|
-
def get_errors_from_response(response)
|
86
|
-
body = JSON.parse(response.body)
|
87
|
-
rescue JSON::ParserError
|
88
|
-
"\ncould not parse errors, raw body:\n#{response.body}\n"
|
89
|
-
else
|
90
|
-
body["errors"].reduce("") do |error_message, error|
|
91
|
-
error_message + "\tCode: #{error['code']}\n\tMessage: #{error['message']}\n\n"
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "http"
|
4
|
+
require "json"
|
5
|
+
|
6
|
+
require "rublox/util/errors"
|
7
|
+
|
8
|
+
module Rublox
|
9
|
+
# @note Only use if you have an use case that the library doesn't cover (and
|
10
|
+
# create an issue and perhaps we'll implement it!).
|
11
|
+
# The {HTTPClient} is a wrapper around the http library, designed specifically
|
12
|
+
# for the Roblox API. It automatically handles the X-CSRF-TOKEN and the
|
13
|
+
# .ROBLOSECURITY cookie.
|
14
|
+
class HTTPClient
|
15
|
+
# @param roblosecurity [String]
|
16
|
+
def initialize(roblosecurity = "")
|
17
|
+
@client = HTTP.cookies(
|
18
|
+
{
|
19
|
+
".ROBLOSECURITY": roblosecurity
|
20
|
+
}
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Send a GET request to the specified URL.
|
25
|
+
# @param url [String]
|
26
|
+
# @return [Hash]
|
27
|
+
def get(url, *args)
|
28
|
+
request(:get, url, *args)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Send a POST request to the specified URL.
|
32
|
+
# @param url [String]
|
33
|
+
# @return [Hash]
|
34
|
+
def post(url, *args)
|
35
|
+
request(:post, url, *args)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Send a PATCH request to the specified URL.
|
39
|
+
# @param url [String]
|
40
|
+
# @return [Hash]
|
41
|
+
def patch(url, *args)
|
42
|
+
request(:patch, url, *args)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Send a DELETE request to the specified URL.
|
46
|
+
# @param url [String]
|
47
|
+
# @return [Hash]
|
48
|
+
def delete(url, *args)
|
49
|
+
request(:delete, url, *args)
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
# @param verb [Symbol]
|
55
|
+
# @param url [String]
|
56
|
+
# @return [Hash]
|
57
|
+
def request(verb, url, *args)
|
58
|
+
response = @client.request(verb, url, *args)
|
59
|
+
return JSON.parse(response.body) if response.status == 200
|
60
|
+
|
61
|
+
handle_status_code(response, verb, url, *args)
|
62
|
+
end
|
63
|
+
|
64
|
+
# @param response [HTTP::Response]
|
65
|
+
def handle_status_code(response, verb, url, *args)
|
66
|
+
case response.status
|
67
|
+
# token validation failed
|
68
|
+
when 403
|
69
|
+
@client = @client.headers(
|
70
|
+
{
|
71
|
+
"x-csrf-token": response.headers["x-csrf-token"]
|
72
|
+
}
|
73
|
+
)
|
74
|
+
# retry the request
|
75
|
+
request(verb, url, *args)
|
76
|
+
# invalid .ROBLOSECURITY cookie
|
77
|
+
when 401
|
78
|
+
raise Errors::InvalidROBLOSECURITYError
|
79
|
+
else
|
80
|
+
raise Errors::UnhandledStatusCodeError.new(response.status, get_errors_from_response(response))
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# @param response [HTTP::Response]
|
85
|
+
def get_errors_from_response(response)
|
86
|
+
body = JSON.parse(response.body)
|
87
|
+
rescue JSON::ParserError
|
88
|
+
"\ncould not parse errors, raw body:\n#{response.body}\n"
|
89
|
+
else
|
90
|
+
body["errors"].reduce("") do |error_message, error|
|
91
|
+
error_message + "\tCode: #{error['code']}\n\tMessage: #{error['message']}\n\n"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
data/lib/rublox/util/pages.rb
CHANGED
@@ -1,85 +1,85 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "rublox/util/url"
|
4
|
-
require "rublox/util/cache"
|
5
|
-
|
6
|
-
module Rublox
|
7
|
-
# The order to sort pages in.
|
8
|
-
module SortOrder
|
9
|
-
# Sort the pages ina ascending order.
|
10
|
-
ASCENDING = "Asc"
|
11
|
-
# Sort the pages in descending order.
|
12
|
-
DESCENDING = "Desc"
|
13
|
-
end
|
14
|
-
|
15
|
-
# The {Pages} class acts as an iterator over pages returned by the API.
|
16
|
-
# @!visibility private
|
17
|
-
# @todo Make more customizable, polish and battle-test
|
18
|
-
# @note Only use if you have an use case that the library doesn't cover (and
|
19
|
-
# create an issue and perhaps we'll implement it!).
|
20
|
-
class Pages
|
21
|
-
# How many items are returned per page
|
22
|
-
PAGE_DATA_LIMIT = 100
|
23
|
-
|
24
|
-
# @!visibility private
|
25
|
-
DEFAULT_REQUEST_PARAMETERS = {
|
26
|
-
params: {
|
27
|
-
sortOrder: SortOrder::DESCENDING,
|
28
|
-
limit: PAGE_DATA_LIMIT
|
29
|
-
}
|
30
|
-
}.freeze
|
31
|
-
|
32
|
-
# @param client [Client]
|
33
|
-
# @param initial_data [Hash]
|
34
|
-
# @param url [String]
|
35
|
-
# @param request_params [Hash]
|
36
|
-
def initialize(client, initial_data, url, request_params = {}, &data_handler)
|
37
|
-
request_params[:params] = DEFAULT_REQUEST_PARAMETERS[:params].merge(
|
38
|
-
request_params
|
39
|
-
)
|
40
|
-
|
41
|
-
@client = client
|
42
|
-
@raw_data = initial_data
|
43
|
-
@url = url
|
44
|
-
@request_parameters = request_parameters
|
45
|
-
@data_handler = data_handler
|
46
|
-
|
47
|
-
@data = []
|
48
|
-
end
|
49
|
-
|
50
|
-
# Iterate over the pages
|
51
|
-
def each
|
52
|
-
raise unless block_given?
|
53
|
-
# i = 0
|
54
|
-
|
55
|
-
# until @raw_data
|
56
|
-
# if i == @data.length
|
57
|
-
# i = 0
|
58
|
-
# data = Cache.get(Cache::PAGE, @raw_data["nextPageCursor"])
|
59
|
-
# if data
|
60
|
-
# @data = data
|
61
|
-
# else
|
62
|
-
# @raw_data, @data = next_page
|
63
|
-
# break if @raw_data.empty?
|
64
|
-
|
65
|
-
# Cache.set(Cache::PAGE, @raw_data["nextPageCursor"], @data)
|
66
|
-
# end
|
67
|
-
# end
|
68
|
-
|
69
|
-
# yield @data[i]
|
70
|
-
# i += 1
|
71
|
-
# end
|
72
|
-
end
|
73
|
-
|
74
|
-
private
|
75
|
-
|
76
|
-
# @return [Array] tuple {raw data, processed data}
|
77
|
-
def next_page
|
78
|
-
@request_parameters[:params][:cursor] = @raw_data["nextPageCursor"]
|
79
|
-
|
80
|
-
data = @client.http_client.get(@url, @request_parameters)
|
81
|
-
|
82
|
-
[data["data"], @data_handler.call(data["data"])]
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rublox/util/url"
|
4
|
+
require "rublox/util/cache"
|
5
|
+
|
6
|
+
module Rublox
|
7
|
+
# The order to sort pages in.
|
8
|
+
module SortOrder
|
9
|
+
# Sort the pages ina ascending order.
|
10
|
+
ASCENDING = "Asc"
|
11
|
+
# Sort the pages in descending order.
|
12
|
+
DESCENDING = "Desc"
|
13
|
+
end
|
14
|
+
|
15
|
+
# The {Pages} class acts as an iterator over pages returned by the API.
|
16
|
+
# @!visibility private
|
17
|
+
# @todo Make more customizable, polish and battle-test
|
18
|
+
# @note Only use if you have an use case that the library doesn't cover (and
|
19
|
+
# create an issue and perhaps we'll implement it!).
|
20
|
+
class Pages
|
21
|
+
# How many items are returned per page
|
22
|
+
PAGE_DATA_LIMIT = 100
|
23
|
+
|
24
|
+
# @!visibility private
|
25
|
+
DEFAULT_REQUEST_PARAMETERS = {
|
26
|
+
params: {
|
27
|
+
sortOrder: SortOrder::DESCENDING,
|
28
|
+
limit: PAGE_DATA_LIMIT
|
29
|
+
}
|
30
|
+
}.freeze
|
31
|
+
|
32
|
+
# @param client [Client]
|
33
|
+
# @param initial_data [Hash]
|
34
|
+
# @param url [String]
|
35
|
+
# @param request_params [Hash]
|
36
|
+
def initialize(client, initial_data, url, request_params = {}, &data_handler)
|
37
|
+
request_params[:params] = DEFAULT_REQUEST_PARAMETERS[:params].merge(
|
38
|
+
request_params
|
39
|
+
)
|
40
|
+
|
41
|
+
@client = client
|
42
|
+
@raw_data = initial_data
|
43
|
+
@url = url
|
44
|
+
@request_parameters = request_parameters
|
45
|
+
@data_handler = data_handler
|
46
|
+
|
47
|
+
@data = []
|
48
|
+
end
|
49
|
+
|
50
|
+
# Iterate over the pages
|
51
|
+
def each
|
52
|
+
raise unless block_given?
|
53
|
+
# i = 0
|
54
|
+
|
55
|
+
# until @raw_data
|
56
|
+
# if i == @data.length
|
57
|
+
# i = 0
|
58
|
+
# data = Cache.get(Cache::PAGE, @raw_data["nextPageCursor"])
|
59
|
+
# if data
|
60
|
+
# @data = data
|
61
|
+
# else
|
62
|
+
# @raw_data, @data = next_page
|
63
|
+
# break if @raw_data.empty?
|
64
|
+
|
65
|
+
# Cache.set(Cache::PAGE, @raw_data["nextPageCursor"], @data)
|
66
|
+
# end
|
67
|
+
# end
|
68
|
+
|
69
|
+
# yield @data[i]
|
70
|
+
# i += 1
|
71
|
+
# end
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
# @return [Array] tuple {raw data, processed data}
|
77
|
+
def next_page
|
78
|
+
@request_parameters[:params][:cursor] = @raw_data["nextPageCursor"]
|
79
|
+
|
80
|
+
data = @client.http_client.get(@url, @request_parameters)
|
81
|
+
|
82
|
+
[data["data"], @data_handler.call(data["data"])]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/lib/rublox/util/url.rb
CHANGED
@@ -1,25 +1,25 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Rublox
|
4
|
-
# Module for making URLs.
|
5
|
-
module URL
|
6
|
-
# The base URL to be used. If using a proxy, you can change the URL as long
|
7
|
-
# as it follows Roblox's API structure:
|
8
|
-
# https://users.roblox.com/v1/users/1
|
9
|
-
# Bad:
|
10
|
-
# https://myproxy.test/get-user/1
|
11
|
-
# https://myproxy.test/users/1
|
12
|
-
# https://users.myproxy.test/users/1
|
13
|
-
# Good:
|
14
|
-
# https://users.myproxy.test/v1/users/1
|
15
|
-
BASE_URL = "roblox.com"
|
16
|
-
|
17
|
-
# Creates an endpoint URL from the the given ApiSite and path.
|
18
|
-
# @param api_site [String] ApiSite
|
19
|
-
# @param path [String]
|
20
|
-
# @return [String] the endpoint
|
21
|
-
def self.endpoint(api_site, path)
|
22
|
-
"https://#{api_site}.#{BASE_URL}/#{path}"
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rublox
|
4
|
+
# Module for making URLs.
|
5
|
+
module URL
|
6
|
+
# The base URL to be used. If using a proxy, you can change the URL as long
|
7
|
+
# as it follows Roblox's API structure:
|
8
|
+
# https://users.roblox.com/v1/users/1
|
9
|
+
# Bad:
|
10
|
+
# https://myproxy.test/get-user/1
|
11
|
+
# https://myproxy.test/users/1
|
12
|
+
# https://users.myproxy.test/users/1
|
13
|
+
# Good:
|
14
|
+
# https://users.myproxy.test/v1/users/1
|
15
|
+
BASE_URL = "roblox.com"
|
16
|
+
|
17
|
+
# Creates an endpoint URL from the the given ApiSite and path.
|
18
|
+
# @param api_site [String] ApiSite
|
19
|
+
# @param path [String]
|
20
|
+
# @return [String] the endpoint
|
21
|
+
def self.endpoint(api_site, path)
|
22
|
+
"https://#{api_site}.#{BASE_URL}/#{path}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/rublox/version.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Rublox
|
4
|
-
# Current version of rublox
|
5
|
-
VERSION = "0.
|
6
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rublox
|
4
|
+
# Current version of rublox
|
5
|
+
VERSION = "0.2.0"
|
6
|
+
end
|