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.
@@ -1,49 +1,40 @@
1
- # frozen_string_literal: true
2
-
3
- require "time"
4
-
5
- require "rublox/derive/user"
6
-
7
- module Rublox
8
- # @note This class is handled internally by the public interface such as
9
- # {Client#user_from_id}. You should not be creating it yourself.
10
- # The {FullUser} class corresponds to a full user response you can get via
11
- # https://users.roblox.com/v1/users/userId. You can use it to get information
12
- # about users.
13
- #
14
- # See {User} for methods you can call on users!
15
- class FullUser
16
- include User
17
-
18
- # @return [Integer] the user's ID
19
- attr_reader :id
20
-
21
- # @return [String] the user's username
22
- attr_reader :username
23
-
24
- # @return [String] the user's display name
25
- attr_reader :display_name
26
-
27
- # @return [String] the user's profile description
28
- attr_reader :description
29
-
30
- # @return [true, false] is the user banned?
31
- attr_reader :banned
32
-
33
- # @return [Time] the user's join date
34
- attr_reader :join_date
35
-
36
- # @param data [Hash]
37
- # @param client [Client]
38
- def initialize(data, client)
39
- @id = data["id"]
40
- @username = data["name"]
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/limited_user"
4
-
5
- module Rublox
6
- # @note This class is handled internally by the public interface such as
7
- # {FullGroup#shout}. You should not be creating it yourself.
8
- # The {GroupShout} class corresponds to a shout response. You can use it to get
9
- # and set information about group shouts.
10
- class GroupShout
11
- # @return [String] the shout's body
12
- attr_reader :body
13
-
14
- # @return [LimitedUser, nil] the user that made the shout, can be nil if the
15
- # shout has no poster
16
- attr_reader :poster
17
-
18
- # @param data [Hash]
19
- # @param client [Client]
20
- # @param group_id [Integer]
21
- def initialize(data, client, group_id)
22
- @body = data["body"]
23
- @poster = LimitedUser.new(data["poster"], client) if data["poster"]
24
-
25
- @group_id = group_id
26
- @client = client
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 "time"
4
-
5
- module Rublox
6
- # The state of the presence.
7
- #
8
- # Can be offline, online/on the website, playing a game, developing on studio.
9
- module PresenceType
10
- # The user is/was offline.
11
- OFFLINE = :Offline
12
- # The user is/was online (this also applies to the website).
13
- ONLINE = :Online
14
- # The user is/was playing a game.
15
- GAME = :"In game"
16
- # The user is/was developing on studio.
17
- STUDIO = :"In Studio"
18
-
19
- # @!visibility private
20
- PRESENCE_MAP = [
21
- OFFLINE,
22
- ONLINE,
23
- GAME,
24
- STUDIO
25
- ].freeze
26
-
27
- # Convert the Roblox PresenceType enum response to rublox's PresenceType
28
- # equivalent.
29
- # @!visibility private
30
- # @param enum [Integer]
31
- # @return [Symbol]
32
- def self.enum_to_presence_type(enum)
33
- PRESENCE_MAP[enum]
34
- end
35
- end
36
-
37
- # @note This class is handled internally by the public interface such as
38
- # {Client#user_presence_from_id}. You should not be creating it yourself.
39
- # The {Presence} class corresponds to a response you can get via
40
- # https://presence.roblox.com/v1/presence/users. You can use it to get information
41
- # about the presence states of users.
42
- class Presence
43
- # @return [PresenceType] the current presence type
44
- attr_reader :presence_type
45
-
46
- # @return [PresenceType] the last presence type of the user
47
- attr_reader :last_presence_type
48
-
49
- # @note Unlike it sounds, this is not a numerical ID like of a user. It's a
50
- # randomly generated string with hexadecimal numbers containing the server's
51
- # job ID (which looks like "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"), it can be
52
- # also accessed in-game via the game.JobId property.
53
- # @return [String, nil] the job ID of the game last played by the user.
54
- attr_reader :game_job_id
55
-
56
- # @return [Time] the date at which the user was last online
57
- attr_reader :last_online_date
58
-
59
- def initialize(data, client)
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
@@ -1,109 +1,44 @@
1
- # frozen_string_literal: true
2
-
3
- module Rublox
4
- # This module contains errors that can be raised by rublox methods.
5
- module Errors
6
- # Exception raised when a user cannot be found.
7
- class UserNotFoundError < StandardError
8
- # @return [Integer, "(no ID information provided)"] the given user's ID
9
- attr_reader :user_id
10
-
11
- # @return [String, "(no username information provided)"] the given user's
12
- # username
13
- attr_reader :user_username
14
-
15
- # @param user_id [Integer]
16
- # @param username [String, nil]
17
- def initialize(
18
- user_id = "(no ID information provided)",
19
- username = "(no username information provided)"
20
- )
21
- @user_id = user_id
22
- @user_username = username
23
- super("The user of ID #{user_id} and username #{username} could not be found.")
24
- end
25
- end
26
-
27
- # Exception raised when a group cannot be found.
28
- class GroupNotFoundError < StandardError
29
- # @return [Integer] the given group's ID
30
- attr_reader :group_id
31
-
32
- # @param group_id [Integer]
33
- def initialize(group_id)
34
- @group_id = group_id
35
- super("The group of ID #{group_id} could not be found.")
36
- end
37
- end
38
-
39
- # Exception raised when a user's presence cannot be found.
40
- class PresenceNotFoundError < StandardError
41
- # @return [Integer] the presence user's ID
42
- attr_reader :user_id
43
-
44
- def initialize(user_id)
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