restiny 0.6.1 → 2.0.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d746d115f85cce78834085e5a291555b9f3a04591d6533b31c569bf8a8ddc161
4
- data.tar.gz: 2b7b6deb692271d86a6d0eb47217f239c97c7145154cb1ab7a04999939d943d0
3
+ metadata.gz: 2d5b81f9aadd44def19fb9af625b26692992457edaf57eeba97b46896f26e032
4
+ data.tar.gz: f058584408a167934ae67f9e8c160f75e542f80558446ee312fa2ce34b763ace
5
5
  SHA512:
6
- metadata.gz: 495d10b083c4fcb3b8ff6697db0e206abab20e1b0fead5549f5b4d9a7fc467343eb82dcaef07e4fdece7590d392f3144e3eb25f2c23ed27740c7118fc7f25294
7
- data.tar.gz: 64972701dd9a41ec8f835b8e4443d39020c097662ac98d7f50d08e7ae92997ea159c21a8a9d83c296fd04a330b4a7d395cb2c43651fe9bd87345cef2f5d303eb
6
+ metadata.gz: 5b737a79ec4728c34106b701db09f654c9d642cfd62b3ff311501a70afcf954f07ad92f0d1282c9a59686bffef568ef2b1fb5466e97cd267b389c1634c28b742
7
+ data.tar.gz: 99c7c3c4519a6a539a11a2970f18a38443ee4a9587b6df980cb74b03e425f1ce134e48c075af0d5b8d29339e086310eda6c44ac352e0b4daf80997923fded98b
@@ -0,0 +1,31 @@
1
+ require "faraday"
2
+ require "restiny/errors"
3
+
4
+ module Faraday
5
+ module Restiny
6
+ Faraday::Response.register_middleware(destiny_api: "Faraday::Restiny::Api")
7
+
8
+ class Api < Middleware
9
+ def on_complete(env)
10
+ return if env["response_body"].empty? || !env["response_body"].dig("ErrorCode")
11
+
12
+ if env["response_body"]["ErrorCode"] == 1
13
+ env[:body] = env["response_body"].dig("Response")
14
+ return
15
+ end
16
+
17
+ klass =
18
+ case env["status"]
19
+ when 400..499
20
+ ::Restiny::RequestError
21
+ when 500..599
22
+ ::Restiny::ResponseError
23
+ else
24
+ ::Restiny::Error
25
+ end
26
+
27
+ raise klass.new(env["response_body"]["Message"], env["response_body"]["ErrorStatus"])
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ require "faraday"
2
+ require "restiny/errors"
3
+
4
+ module Faraday
5
+ module Restiny
6
+ Faraday::Response.register_middleware(destiny_auth: "Faraday::Restiny::Auth")
7
+
8
+ class Auth < Middleware
9
+ def on_complete(env)
10
+ return if env["response_body"].empty? || env["url"].to_s !~ /oauth/
11
+
12
+ if env["response_body"]["error"]
13
+ raise ::Restiny::AuthenticationError.new(
14
+ env["response_body"]["error_description"],
15
+ env["response_body"]["error"]
16
+ )
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -40,4 +40,32 @@ module Restiny
40
40
  SUPERIOR = 5
41
41
  EXOTIC = 6
42
42
  end
43
+
44
+ module Class
45
+ TITAN = 0
46
+ HUNTER = 1
47
+ WARLOCK = 2
48
+ UNKNOWN = 3
49
+ end
50
+
51
+ module Race
52
+ HUMAN = 0
53
+ AWOKEN = 1
54
+ EXO = 2
55
+ UNKNOWN = 3
56
+ end
57
+
58
+ module Gender
59
+ MASCULINE = 0
60
+ FEMININE = 1
61
+ UNKNOWN = 2
62
+ end
63
+
64
+ module Ammunition
65
+ NONE = 0
66
+ PRIMARY = 1
67
+ SPECIAL = 2
68
+ HEAVY = 3
69
+ UNKNOWN = 4
70
+ end
43
71
  end
@@ -17,6 +17,9 @@ module Restiny
17
17
  class RateLimitedError < RequestError
18
18
  end
19
19
 
20
+ class AuthenticationError < RequestError
21
+ end
22
+
20
23
  class ResponseError < Error
21
24
  end
22
25
  end
@@ -79,15 +79,15 @@ module Restiny
79
79
  single_method_name, plural_method_name = method_names
80
80
 
81
81
  define_method single_method_name do |id|
82
- fetch_item(full_table_name, id)
82
+ fetch_item(table_name: full_table_name, id: id)
83
83
  end
84
84
 
85
- define_method plural_method_name do |limit = nil|
86
- fetch_items(full_table_name, limit)
85
+ define_method plural_method_name do |limit: nil|
86
+ fetch_items(table_name: full_table_name, limit: limit)
87
87
  end
88
88
  end
89
89
 
90
- def self.download(url)
90
+ def self.download_by_url(url)
91
91
  zipped_file = Down.download(url)
92
92
  manifest_path = zipped_file.path + ".db"
93
93
 
@@ -116,7 +116,7 @@ module Restiny
116
116
  @database.execute(query).map { |row| row["name"].gsub(/(Destiny|Definition)/, "") }
117
117
  end
118
118
 
119
- def fetch_item(table_name, id)
119
+ def fetch_item(table_name:, id:)
120
120
  query = "SELECT json FROM #{table_name} WHERE json_extract(json, '$.hash')=?"
121
121
  result = @database.execute(query, id)
122
122
 
@@ -127,7 +127,7 @@ module Restiny
127
127
  raise Restiny::RequestError.new("Error while fetching item (#{e})")
128
128
  end
129
129
 
130
- def fetch_items(table_name, limit = nil)
130
+ def fetch_items(table_name:, limit: nil)
131
131
  bindings = []
132
132
 
133
133
  query = "SELECT json FROM #{table_name} ORDER BY json_extract(json, '$.index')"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Restiny
4
- VERSION = "0.6.1"
4
+ VERSION = "2.0.1"
5
5
  end
data/lib/restiny.rb CHANGED
@@ -9,6 +9,8 @@ require "restiny/manifest"
9
9
 
10
10
  require "faraday"
11
11
  require "faraday/follow_redirects"
12
+ require "faraday/destiny/api"
13
+ require "faraday/destiny/auth"
12
14
  require "securerandom"
13
15
 
14
16
  module Restiny
@@ -21,7 +23,7 @@ module Restiny
21
23
 
22
24
  # OAuth methods
23
25
 
24
- def authorise_url(redirect_url = nil, state = nil)
26
+ def get_authorise_url(redirect_url: nil, state: nil)
25
27
  check_oauth_client_id
26
28
 
27
29
  @oauth_state = state || SecureRandom.hex(15)
@@ -29,129 +31,142 @@ module Restiny
29
31
  params = { response_type: "code", client_id: @oauth_client_id, state: @oauth_state }
30
32
  params[:redirect_url] = redirect_url unless redirect_url.nil?
31
33
 
32
- connection.build_url(BUNGIE_URL + "/en/oauth/authorize", params).to_s
34
+ auth_connection.build_url(BUNGIE_URL + "/en/oauth/authorize/", params).to_s
33
35
  end
34
36
 
35
- def request_access_token(code, redirect_url = nil)
37
+ def request_access_token(code:, redirect_url: nil)
36
38
  check_oauth_client_id
37
39
 
38
40
  params = { code: code, grant_type: "authorization_code", client_id: @oauth_client_id }
39
41
  params[:redirect_url] = redirect_url unless redirect_url.nil?
40
42
 
41
- make_api_request(
42
- :post,
43
- "app/oauth/token/",
44
- params,
45
- "Content-Type" => "application/x-www-form-urlencoded"
46
- )
43
+ auth_post("app/oauth/token/", params)
47
44
  end
48
45
 
49
46
  # Manifest methods
50
47
 
51
- def download_manifest(locale = "en")
52
- response = get("Destiny2/Manifest/")
48
+ def get_manifest_url(locale: "en")
49
+ result = api_get("Destiny2/Manifest/").dig("mobileWorldContentPaths", locale)
50
+ BUNGIE_URL + result
51
+ end
53
52
 
54
- manifest_path = response.dig("mobileWorldContentPaths", locale)
55
- raise Restiny::ResponseError.new("Unable to determine manifest URL") if manifest_path.nil?
53
+ def download_manifest(locale: "en")
54
+ manifest_url = get_manifest_url
55
+ raise Restiny::ResponseError.new("Unable to determine manifest URL") if manifest_url.nil?
56
56
 
57
- Manifest.download(BUNGIE_URL + manifest_path)
57
+ Manifest.download_by_url(BUNGIE_URL + manifest_url)
58
58
  end
59
59
 
60
- # Profile methods
60
+ # Profile and related methods
61
61
 
62
- def get_profile(membership_id, membership_type, components = [])
63
- if components.empty?
62
+ def get_profile(membership_id:, membership_type:, components:, type_url: nil)
63
+ if !components.is_a?(Array) || components.empty?
64
64
  raise Restiny::InvalidParamsError.new("Please provide at least one component")
65
65
  end
66
66
 
67
- get("Destiny2/#{membership_type}/Profile/#{membership_id}?components=#{components.join(",")}")
67
+ url = "Destiny2/#{membership_type}/Profile/#{membership_id}/"
68
+ url += type_url if type_url
69
+ url += "?components=#{components.join(",")}"
70
+
71
+ api_get(url)
72
+ end
73
+
74
+ def get_character_profile(character_id:, membership_id:, membership_type:, components:)
75
+ get_profile(
76
+ membership_id: membership_id,
77
+ membership_type: membership_type,
78
+ components: components,
79
+ type_url: "Character/#{character_id}/"
80
+ )
68
81
  end
69
82
 
70
- # Account methods
83
+ def get_instanced_item_profile(item_id:, membership_id:, membership_type:, components:)
84
+ get_profile(
85
+ membership_id: membership_id,
86
+ membership_type: membership_type,
87
+ components: components,
88
+ type_url: "Item/#{item_id}/"
89
+ )
90
+ end
71
91
 
72
- def get_user_by_membership_id(membership_id, membership_type = Platform::ALL)
73
- raise Restiny::InvalidParamsError.new("Please provide a membership ID") if membership_id.nil?
92
+ # User methods.
74
93
 
75
- get("User/GetMembershipsById/#{membership_id}/#{membership_type}/")
94
+ def get_user_memberships_by_id(membership_id, membership_type: Platform::ALL)
95
+ raise Restiny::InvalidParamsError.new("Please provide a membership ID") if membership_id.nil?
96
+ api_get("User/GetMembershipsById/#{membership_id}/#{membership_type}/")
76
97
  end
77
98
 
78
- def get_user_by_bungie_name(full_display_name, membership_type = Platform::ALL)
79
- display_name, display_name_code = full_display_name.split("#")
99
+ def search_player_by_bungie_name(name, membership_type: Platform::ALL)
100
+ display_name, display_name_code = name.split("#")
80
101
  if display_name.nil? || display_name_code.nil?
81
102
  raise Restiny::InvalidParamsError.new("You must provide a valid Bungie name")
82
103
  end
83
104
 
84
- post(
105
+ api_post(
85
106
  "Destiny2/SearchDestinyPlayerByBungieName/#{membership_type}/",
86
- { displayName: display_name, displayNameCode: display_name_code }
107
+ params: {
108
+ displayName: display_name,
109
+ displayNameCode: display_name_code
110
+ }
87
111
  )
88
112
  end
89
113
 
90
- def search_users(name, page = 0)
91
- post("User/Search/GlobalName/#{page}", displayNamePrefix: name)
114
+ def search_users_by_global_name(name:, page: 0)
115
+ api_post("User/Search/GlobalName/#{page}/", params: { displayNamePrefix: name })
92
116
  end
93
117
 
94
- def get(endpoint_url, params = {}, headers = {})
95
- make_api_request(:get, endpoint_url, params, headers).dig("Response")
96
- end
118
+ # General request methods
97
119
 
98
- def post(endpoint_url, body, headers = {})
99
- make_api_request(:post, endpoint_url, body, headers).dig("Response")
120
+ def api_get(url, params: {})
121
+ api_connection.get(url, params, token_header).body
100
122
  end
101
123
 
102
- private
103
-
104
- def make_api_request(type, url, params, headers = {})
105
- raise Restiny::InvalidParamsError.new("You need to set an API key") unless @api_key
106
-
107
- headers[:authorization] = "Bearer #{@oauth_token}" if @oauth_token
108
-
109
- response =
110
- case type
111
- when :get
112
- connection.get(url, params, headers)
113
- when :post
114
- connection.post(url, params, headers)
115
- end
116
-
117
- response.body
118
- rescue Faraday::Error => error
119
- begin
120
- error_body = JSON.parse(error.response_body)
121
- status, message = error_body["ErrorStatus"], error_body["Message"]
122
- rescue JSON::ParserError
123
- status, message = error.response_status, error.message
124
- end
125
-
126
- klass =
127
- case error
128
- when Faraday::ClientError
129
- Restiny::RequestError
130
- when Faraday::ServerError
131
- Restiny::ResponseError
132
- else
133
- Restiny::Error
134
- end
124
+ def api_post(url, params: {})
125
+ api_connection.post(url, params, token_header).body
126
+ end
135
127
 
136
- raise klass.new(message, status)
128
+ def auth_post(url, params)
129
+ auth_connection.post(url, params, "Content-Type" => "application/x-www-form-urlencoded").body
137
130
  end
138
131
 
132
+ private
133
+
139
134
  def check_oauth_client_id
140
135
  raise Restiny::RequestError.new("You need to set an OAuth client ID") unless @oauth_client_id
141
136
  end
142
137
 
143
138
  def default_headers
144
- { "User-Agent": "restiny v#{Restiny::VERSION}", "X-API-KEY": @api_key }
139
+ { "User-Agent": "restiny v#{Restiny::VERSION}" }
145
140
  end
146
141
 
147
- def connection
142
+ def api_connection
143
+ raise Restiny::InvalidParamsError.new("You need to set an API key") unless @api_key
144
+
148
145
  @connection ||=
149
- Faraday.new(url: API_BASE_URL, headers: default_headers) do |faraday|
150
- faraday.request :json
146
+ Faraday.new(
147
+ url: API_BASE_URL,
148
+ headers: default_headers.merge("X-API-KEY": @api_key)
149
+ ) do |faraday|
151
150
  faraday.request :url_encoded
151
+ faraday.request :json
152
+ faraday.response :follow_redirects
153
+ faraday.response :destiny_api
152
154
  faraday.response :json
155
+ end
156
+ end
157
+
158
+ def auth_connection
159
+ @auth_connection ||=
160
+ Faraday.new(url: API_BASE_URL, headers: default_headers) do |faraday|
161
+ faraday.request :url_encoded
162
+ faraday.request :json
153
163
  faraday.response :follow_redirects
154
- faraday.response :raise_error
164
+ faraday.response :destiny_auth
165
+ faraday.response :json
155
166
  end
156
167
  end
168
+
169
+ def token_header
170
+ {}.tap { |headers| headers["authorization"] = "Bearer #{@oauth_token}" if @oauth_token }
171
+ end
157
172
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: restiny
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Bogan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-11 00:00:00.000000000 Z
11
+ date: 2023-07-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -157,6 +157,8 @@ executables: []
157
157
  extensions: []
158
158
  extra_rdoc_files: []
159
159
  files:
160
+ - lib/faraday/destiny/api.rb
161
+ - lib/faraday/destiny/auth.rb
160
162
  - lib/restiny.rb
161
163
  - lib/restiny/constants.rb
162
164
  - lib/restiny/errors.rb