rublox 0.1.0 → 0.3.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/LICENSE +21 -21
- data/{README.MD → README.md} +58 -68
- data/lib/rublox/bases/base_group.rb +19 -0
- data/lib/rublox/bases/base_user.rb +19 -0
- data/lib/rublox/derive/group.rb +33 -50
- data/lib/rublox/derive/model.rb +17 -0
- data/lib/rublox/derive/user.rb +43 -89
- data/lib/rublox/models/full_group.rb +55 -60
- data/lib/rublox/models/full_user.rb +40 -49
- data/lib/rublox/models/group_shout.rb +26 -62
- data/lib/rublox/models/presence.rb +59 -98
- data/lib/rublox/models/skinny_user.rb +28 -0
- data/lib/rublox/util/api_helper.rb +69 -0
- data/lib/rublox/util/errors.rb +44 -109
- data/lib/rublox.rb +89 -136
- data/rublox.gemspec +30 -32
- metadata +31 -49
- data/CHANGELOG.MD +0 -4
- data/Gemfile +0 -6
- data/Rakefile +0 -33
- data/lib/rublox/models/group_member.rb +0 -54
- data/lib/rublox/models/group_role.rb +0 -70
- data/lib/rublox/models/limited_user.rb +0 -34
- data/lib/rublox/util/cache.rb +0 -39
- data/lib/rublox/util/http_client.rb +0 -95
- data/lib/rublox/util/pages.rb +0 -85
- data/lib/rublox/util/url.rb +0 -25
- data/lib/rublox/version.rb +0 -6
@@ -1,49 +1,40 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
@display_name = data["displayName"]
|
42
|
-
@description = data["description"]
|
43
|
-
@banned = data["banned"]
|
44
|
-
@join_date = Time.iso8601(data["created"])
|
45
|
-
|
46
|
-
@client = client
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rublox/derive/user"
|
4
|
+
|
5
|
+
module Rublox
|
6
|
+
module Models
|
7
|
+
class FullUser
|
8
|
+
include Derive::User
|
9
|
+
|
10
|
+
# @return [String]
|
11
|
+
attr_reader :description
|
12
|
+
# @return [Time]
|
13
|
+
attr_reader :created
|
14
|
+
# @return [Boolean]
|
15
|
+
attr_reader :is_banned
|
16
|
+
# @return [String?]
|
17
|
+
attr_reader :external_app_display_name
|
18
|
+
# @return [Boolean]
|
19
|
+
attr_reader :has_verified_badge
|
20
|
+
# @return [Integer]
|
21
|
+
attr_reader :id
|
22
|
+
# @return [String]
|
23
|
+
attr_reader :name
|
24
|
+
# @return [String]
|
25
|
+
attr_reader :display_name
|
26
|
+
|
27
|
+
# @!visibility private
|
28
|
+
def initialize(data)
|
29
|
+
@description = data["description"]
|
30
|
+
@created = Time.iso8601(data["created"])
|
31
|
+
@is_banned = data["isBanned"]
|
32
|
+
@external_app_display_name = data["externalAppDisplayName"]
|
33
|
+
@has_verified_badge = data["hasVerifiedBadge"]
|
34
|
+
@id = data["id"]
|
35
|
+
@name = data["name"]
|
36
|
+
@display_name = data["displayName"]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -1,62 +1,26 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "rublox/models/
|
4
|
-
|
5
|
-
module Rublox
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
# Sends a new shout.
|
30
|
-
# @example
|
31
|
-
# client = Rublox::Client.new
|
32
|
-
# group = client.group_from_id(1)
|
33
|
-
# group.shout.send_shout("new shout")
|
34
|
-
# @param new_shout [String] the body of the new shout
|
35
|
-
# @return [void]
|
36
|
-
def send_shout(new_shout)
|
37
|
-
@client.http_client.patch(
|
38
|
-
URL.endpoint("groups", "v1/groups/#{@group_id}/status"),
|
39
|
-
json: {
|
40
|
-
message: new_shout
|
41
|
-
}
|
42
|
-
)
|
43
|
-
end
|
44
|
-
|
45
|
-
# Clears the group shout. Same as calling {#send_shout} with an empty string.
|
46
|
-
# @example
|
47
|
-
# client = Rublox::Client.new
|
48
|
-
# group = client.group_from_id(1)
|
49
|
-
# group.shout.clear
|
50
|
-
# # same as
|
51
|
-
# group.shout.send_shout("")
|
52
|
-
# @return [void]
|
53
|
-
def clear
|
54
|
-
send_shout("")
|
55
|
-
end
|
56
|
-
|
57
|
-
# @return [GroupShout] A new group shout object with updated information.
|
58
|
-
def refresh
|
59
|
-
@client.group_from_id(@group_id).shout
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rublox/models/skinny_user"
|
4
|
+
|
5
|
+
module Rublox
|
6
|
+
module Models
|
7
|
+
class GroupShout
|
8
|
+
# @return [String]
|
9
|
+
attr_reader :body
|
10
|
+
# @return [SkinnyUser]
|
11
|
+
attr_reader :poster
|
12
|
+
# @return [Time]
|
13
|
+
attr_reader :created
|
14
|
+
# @return [Time]
|
15
|
+
attr_reader :updated
|
16
|
+
|
17
|
+
# @!visibility private
|
18
|
+
def initialize(data)
|
19
|
+
@body = data["body"]
|
20
|
+
@poster = SkinnyUser.new(data["poster"])
|
21
|
+
@created = Time.iso8601(data["created"])
|
22
|
+
@updated = Time.iso8601(data["updated"])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -1,98 +1,59 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
@presence_type = PresenceType.enum_to_presence_type(data["userPresenceType"])
|
61
|
-
@last_location = data["lastLocation"]
|
62
|
-
@place_id = data["placeId"]
|
63
|
-
@root_place_id = data["rootPlaceId"]
|
64
|
-
@game_job_id = data["gameId"]
|
65
|
-
@universe_id = data["universeId"]
|
66
|
-
@user_id = data["userId"]
|
67
|
-
@last_online_date = Time.iso8601(data["lastOnline"])
|
68
|
-
|
69
|
-
@client = client
|
70
|
-
end
|
71
|
-
|
72
|
-
# @todo add Place class
|
73
|
-
# @return [Place, nil] the place last visited by the user, can be nil if the
|
74
|
-
# user has never played a game
|
75
|
-
def place
|
76
|
-
return unless @place_id
|
77
|
-
end
|
78
|
-
|
79
|
-
# @todo add Place class
|
80
|
-
# @return [Place, nil] the root of the place last visited by the user, can
|
81
|
-
# be nil if the user has never played a game
|
82
|
-
def root_place
|
83
|
-
return unless @root_place_id
|
84
|
-
end
|
85
|
-
|
86
|
-
# @todo add Universe class
|
87
|
-
# @return [Universe, nil] the universe of the place last visited by the user,
|
88
|
-
# can be nil if the user has never played a game
|
89
|
-
def universe
|
90
|
-
return unless @universe_id
|
91
|
-
end
|
92
|
-
|
93
|
-
# @return [FullUser] the user tied to the presence
|
94
|
-
def user
|
95
|
-
@client.user_from_id(@user_id)
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rublox/derive/model"
|
4
|
+
require "rublox/bases/base_user"
|
5
|
+
|
6
|
+
module Rublox
|
7
|
+
module Models
|
8
|
+
module PresenceType
|
9
|
+
OFFLINE = :offline
|
10
|
+
ONLINE = :online
|
11
|
+
IN_GAME = :in_game
|
12
|
+
IN_STUDIO = :in_studio
|
13
|
+
|
14
|
+
PRESENCE_MAP = [
|
15
|
+
OFFLINE,
|
16
|
+
ONLINE,
|
17
|
+
IN_GAME,
|
18
|
+
IN_STUDIO
|
19
|
+
].freeze
|
20
|
+
private_constant :PRESENCE_MAP
|
21
|
+
|
22
|
+
# @!visibility private
|
23
|
+
def self.get(enum)
|
24
|
+
PRESENCE_MAP[enum]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class Presence
|
29
|
+
include Derive::Model
|
30
|
+
|
31
|
+
# @return [PresenceType]
|
32
|
+
attr_reader :user_presence_type
|
33
|
+
# @return [String]
|
34
|
+
attr_reader :last_location
|
35
|
+
# attr_reader :place_id
|
36
|
+
# attr_reader :root_place_id
|
37
|
+
# attr_reader :game_id
|
38
|
+
# attr_reader :universe_id
|
39
|
+
# @return [Bases::BaseUser]
|
40
|
+
attr_reader :user
|
41
|
+
# @return [Time]
|
42
|
+
attr_reader :last_online
|
43
|
+
|
44
|
+
# @!visibility private
|
45
|
+
def initialize(data)
|
46
|
+
@user_presence_type = PresenceType.get(data["userPresenceType"])
|
47
|
+
@last_location = data["lastLocation"]
|
48
|
+
# @place_id = data["placeId"]
|
49
|
+
# @root_place_id = data["rootPlaceId"]
|
50
|
+
# @game_id = data["gameId"]
|
51
|
+
# @universe_id = data["universeId"]
|
52
|
+
@user = Bases::BaseUser.new(data["userId"])
|
53
|
+
@last_online = Time.iso8601(data["lastOnline"])
|
54
|
+
|
55
|
+
@id = @user_id
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rublox/derive/user"
|
4
|
+
|
5
|
+
module Rublox
|
6
|
+
module Models
|
7
|
+
class SkinnyUser
|
8
|
+
include Derive::User
|
9
|
+
|
10
|
+
# @return [Integer]
|
11
|
+
attr_reader :id
|
12
|
+
# @return [String]
|
13
|
+
attr_reader :name
|
14
|
+
# @return [String]
|
15
|
+
attr_reader :display_name
|
16
|
+
# @return [Boolean]
|
17
|
+
attr_reader :has_verified_badge
|
18
|
+
|
19
|
+
# @!visibility private
|
20
|
+
def initialize(data)
|
21
|
+
@id = data["id"] || data["userId"]
|
22
|
+
@name = data["name"] || data["username"]
|
23
|
+
@display_name = data["displayName"]
|
24
|
+
@has_verified_badge = data["hasVerifiedBadge"]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "http"
|
4
|
+
require "json"
|
5
|
+
|
6
|
+
require "rublox/util/errors"
|
7
|
+
|
8
|
+
module Rublox
|
9
|
+
module APIHelper
|
10
|
+
@client = HTTP::Client.new
|
11
|
+
|
12
|
+
# @!visibility private
|
13
|
+
def self.roblosecurity=(roblosecurity)
|
14
|
+
@client = @client.cookies(
|
15
|
+
{
|
16
|
+
".ROBLOSECURITY" => roblosecurity
|
17
|
+
}
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.get(url, *args)
|
22
|
+
request(:get, url, *args)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.post(url, *args)
|
26
|
+
request(:post, url, *args)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.patch(url, *args)
|
30
|
+
request(:patch, url, *args)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.delete(url, *args)
|
34
|
+
request(:delete, url, *args)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.request(method, url, *args)
|
38
|
+
response = @client.request(method, url, *args)
|
39
|
+
case response.status
|
40
|
+
when 200
|
41
|
+
JSON.parse(response.body)
|
42
|
+
when 403
|
43
|
+
if JSON.parse(response.body).any? { |error| error.code.zero? }
|
44
|
+
@client = @client.headers(
|
45
|
+
{
|
46
|
+
"x-csrf-token" => response.headers
|
47
|
+
}
|
48
|
+
)
|
49
|
+
end
|
50
|
+
when 401
|
51
|
+
raise Errors::InvalidROBLOSECURITYError
|
52
|
+
else
|
53
|
+
raise Errors::UnhandledStatusCodeError.new(response, get_errors_from_response(response))
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.get_errors_from_response(response)
|
58
|
+
body = JSON.parse(response.body)
|
59
|
+
rescue JSON::ParserError
|
60
|
+
"\ncould not parse errors, raw body:\n#{response.body}\n"
|
61
|
+
else
|
62
|
+
body["errors"].reduce("") do |error_message, error|
|
63
|
+
error_message + "\tCode: #{error['code']}\n\tMessage: #{error['message']}\n\n"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
private_class_method :request, :get_errors_from_response
|
68
|
+
end
|
69
|
+
end
|
data/lib/rublox/util/errors.rb
CHANGED
@@ -1,109 +1,44 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Rublox
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
@user_id = user_id
|
46
|
-
super("The presence of the user with ID #{user_id} could not be found.")
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
# Exception raised when a user is not part of a group.
|
51
|
-
class MemberNotFoundError < StandardError
|
52
|
-
# @return [Integer] the given user's ID
|
53
|
-
attr_reader :user_id
|
54
|
-
|
55
|
-
# @return [Integer] the given group's ID
|
56
|
-
attr_reader :group_id
|
57
|
-
|
58
|
-
# @param id [Integer]
|
59
|
-
# @param group_id [Integer]
|
60
|
-
def initialize(id, group_id)
|
61
|
-
@user_id = id
|
62
|
-
@group_id = group_id
|
63
|
-
super("The user of ID #{id} is not part of this group of ID #{group_id}")
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
# Exception raised when a role doesn't exist.
|
68
|
-
class RoleNotFoundError < StandardError
|
69
|
-
# @return [Integer] the given role's ID
|
70
|
-
attr_reader :role_id
|
71
|
-
|
72
|
-
# @return [Integer] the given group's ID
|
73
|
-
attr_reader :group_id
|
74
|
-
|
75
|
-
# @param role_id [Integer]
|
76
|
-
# @param group_id [Integer]
|
77
|
-
def initialize(role_id, group_id)
|
78
|
-
@role_id = role_id
|
79
|
-
@group_id = group_id
|
80
|
-
super("The role of ID #{role_id} does not exist in group of ID #{group_id}.")
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
# Exception raised when an unhandled status code is returned.
|
85
|
-
class UnhandledStatusCodeError < StandardError
|
86
|
-
# @return [HTTP::Response::Status] the unhandled status code
|
87
|
-
attr_reader :status_code
|
88
|
-
|
89
|
-
# @return [String] a string containing all the errors returned by the API
|
90
|
-
# neatly formatted
|
91
|
-
attr_reader :errors
|
92
|
-
|
93
|
-
# @param status_code [Integer]
|
94
|
-
# @param errors [String, nil]
|
95
|
-
def initialize(status_code, errors = "")
|
96
|
-
super("Unhandled status code #{status_code}.\nRoblox errors:\n#{errors}")
|
97
|
-
@status_code = status_code
|
98
|
-
@errors = errors
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
# Exception raised when an invalid .ROBLOSECURITY cookie is used.
|
103
|
-
class InvalidROBLOSECURITYError < StandardError
|
104
|
-
def initialize
|
105
|
-
super("A valid .ROBLOSECURITY cookie needs to be passed to Rublox's constructor for this action.")
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rublox
|
4
|
+
module Errors
|
5
|
+
# This error is raised when a user couldn't be found
|
6
|
+
class UserNotFoundError < StandardError
|
7
|
+
end
|
8
|
+
|
9
|
+
# This error is raised when a group couldn't be found
|
10
|
+
class GroupNotFoundError < StandardError
|
11
|
+
end
|
12
|
+
|
13
|
+
# This error is raised when one of the provided user IDs are invalid, or if a user ID is repeated
|
14
|
+
class PresenceRequestError < StandardError
|
15
|
+
# @!visibility private
|
16
|
+
def initialize
|
17
|
+
super("An invalid or repeated user ID was provided")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# This error is raised when an error returned by the Roblox API should be dealt by the user
|
22
|
+
class UnhandledStatusCodeError < StandardError
|
23
|
+
# @return [HTTP::Response] the response object
|
24
|
+
attr_reader :response
|
25
|
+
# @return [String] a formatted string of errors returned by the Roblox API
|
26
|
+
attr_reader :errors
|
27
|
+
|
28
|
+
# @!visibility private
|
29
|
+
def initialize(response, errors)
|
30
|
+
super("Unhandled status code #{response.status}.\nRoblox errors:\n#{errors}")
|
31
|
+
@response = response
|
32
|
+
@errors = errors
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# This error is raised when a method that requires authenticated is called without a valid .ROBLOSECURITY cookie set
|
37
|
+
class InvalidROBLOSECURITYError < StandardError
|
38
|
+
# @!visibility private
|
39
|
+
def initialize
|
40
|
+
super("A valid .ROBLOSECURITY cookie needs to be passed to Rublox for this action.")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|