amadeus 0.1.0 → 1.0.0.beta1
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 +5 -5
- data/CHANGELOG.md +10 -0
- data/LICENSE +15 -0
- data/README.md +157 -19
- data/amadeus.gemspec +26 -16
- data/lib/amadeus.rb +31 -4
- data/lib/amadeus/client.rb +120 -0
- data/lib/amadeus/client/access_token.rb +61 -0
- data/lib/amadeus/client/decorator.rb +27 -0
- data/lib/amadeus/client/errors.rb +76 -0
- data/lib/amadeus/client/http.rb +137 -0
- data/lib/amadeus/client/location.rb +13 -0
- data/lib/amadeus/client/pagination.rb +103 -0
- data/lib/amadeus/client/request.rb +145 -0
- data/lib/amadeus/client/request/hash.rb +32 -0
- data/lib/amadeus/client/response.rb +62 -0
- data/lib/amadeus/client/response/parser.rb +72 -0
- data/lib/amadeus/client/validator.rb +62 -0
- data/lib/amadeus/namespaces/core.rb +51 -0
- data/lib/amadeus/namespaces/reference_data.rb +41 -0
- data/lib/amadeus/namespaces/reference_data/location.rb +42 -0
- data/lib/amadeus/namespaces/reference_data/locations.rb +45 -0
- data/lib/amadeus/namespaces/reference_data/locations/airports.rb +38 -0
- data/lib/amadeus/namespaces/reference_data/urls.rb +27 -0
- data/lib/amadeus/namespaces/reference_data/urls/checkin_links.rb +33 -0
- data/lib/amadeus/namespaces/shopping.rb +66 -0
- data/lib/amadeus/namespaces/shopping/flight_dates.rb +33 -0
- data/lib/amadeus/namespaces/shopping/flight_destinations.rb +30 -0
- data/lib/amadeus/namespaces/shopping/flight_offers.rb +36 -0
- data/lib/amadeus/namespaces/shopping/hotel.rb +56 -0
- data/lib/amadeus/namespaces/shopping/hotel/hotel_offers.rb +44 -0
- data/lib/amadeus/namespaces/shopping/hotel/offer.rb +58 -0
- data/lib/amadeus/namespaces/shopping/hotel_offers.rb +37 -0
- data/lib/amadeus/namespaces/travel.rb +26 -0
- data/lib/amadeus/namespaces/travel/analytics.rb +37 -0
- data/lib/amadeus/namespaces/travel/analytics/air_traffics.rb +37 -0
- data/lib/amadeus/namespaces/travel/analytics/fare_searches.rb +46 -0
- data/lib/amadeus/version.rb +4 -1
- metadata +161 -23
- data/.gitignore +0 -12
- data/.rspec +0 -2
- data/.travis.yml +0 -5
- data/CODE_OF_CONDUCT.md +0 -74
- data/Gemfile +0 -4
- data/LICENSE.txt +0 -21
- data/Rakefile +0 -6
- data/bin/console +0 -14
- data/bin/setup +0 -8
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Amadeus
|
4
|
+
class Request
|
5
|
+
# Helper methods to for the {Amadeus::Request} object to help it
|
6
|
+
# flatten hash keys
|
7
|
+
# @!visibility private
|
8
|
+
module Hash
|
9
|
+
private
|
10
|
+
|
11
|
+
# Flattens the hash keys, so page: { offset: 1 } becomes
|
12
|
+
# 'page[offset] => 1'
|
13
|
+
def flatten_keys(value, key = nil, out_hash = {})
|
14
|
+
case value
|
15
|
+
when nil then return ''
|
16
|
+
when ::Hash
|
17
|
+
value.each { |k, v| flatten_keys(v, append_key(key, k), out_hash) }
|
18
|
+
when Array
|
19
|
+
value.each { |v| flatten_keys(v, :"#{key}[]", out_hash) }
|
20
|
+
else
|
21
|
+
out_hash[key] = value
|
22
|
+
end
|
23
|
+
out_hash
|
24
|
+
end
|
25
|
+
|
26
|
+
# Used by .flatten_keys to add a sub key to a key
|
27
|
+
def append_key(root_key, key)
|
28
|
+
root_key.nil? ? :"#{key}" : :"#{root_key}[#{key.to_s}]"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'amadeus/client/response/parser'
|
4
|
+
|
5
|
+
module Amadeus
|
6
|
+
# The response object returned for every API call.
|
7
|
+
class Response
|
8
|
+
include Parser
|
9
|
+
|
10
|
+
# The actual HTTPResponse object returned from the Net::HTTP request
|
11
|
+
# @return [Net::HTTPResponse]
|
12
|
+
attr_reader :http_response
|
13
|
+
|
14
|
+
# The actual Amadeus::Request object used to make this API call
|
15
|
+
# @return [Amadeus::Request]
|
16
|
+
attr_reader :request
|
17
|
+
|
18
|
+
# The parsed JSON received from the API, if the result was JSON
|
19
|
+
# @return [Hash]
|
20
|
+
attr_reader :result
|
21
|
+
|
22
|
+
# The data extracted from the JSON data - if the body contained JSON
|
23
|
+
# @return [Hash]
|
24
|
+
attr_reader :data
|
25
|
+
|
26
|
+
# The raw body received from the API
|
27
|
+
# @return [String]
|
28
|
+
attr_reader :body
|
29
|
+
|
30
|
+
# Wether the raw body has been parsed into JSON
|
31
|
+
# @return [Boolean]
|
32
|
+
attr_reader :parsed
|
33
|
+
|
34
|
+
# The HTTP status code for the response, if any
|
35
|
+
# @return [Number]
|
36
|
+
attr_reader :status_code
|
37
|
+
|
38
|
+
# Initialize the Response object with the
|
39
|
+
# HTTPResponse object to parse, the client that made the request
|
40
|
+
# and the original request made
|
41
|
+
#
|
42
|
+
# @param [Net:::HTTPResponse] http_response the HTTPResponse returned
|
43
|
+
# @param [Amadeus::Request] request the request object used to
|
44
|
+
# make the API call
|
45
|
+
# @!visibility private
|
46
|
+
def initialize(http_response, request)
|
47
|
+
@http_response = http_response
|
48
|
+
@request = request
|
49
|
+
end
|
50
|
+
|
51
|
+
# Parses the response, using the client to log any errors
|
52
|
+
#
|
53
|
+
# @param [Amadeus::Client] client the client used to output any errors
|
54
|
+
# @return [Amadeus::Response] returns itself
|
55
|
+
# @!visibility private
|
56
|
+
def parse(client)
|
57
|
+
parse_status_code
|
58
|
+
parse_data(client)
|
59
|
+
self
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Amadeus
|
6
|
+
class Response
|
7
|
+
# Helper methods to for the {Amadeus::Response} object to help it
|
8
|
+
# parse the response received from the API
|
9
|
+
# @!visibility private
|
10
|
+
module Parser
|
11
|
+
# Tries to parse the HTTPResponse, parsing the JSON and raising the
|
12
|
+
# appropriate errors
|
13
|
+
def detect_error(client)
|
14
|
+
raise_error(Amadeus::ServerError, client) if @status_code >= 500
|
15
|
+
raise_error(Amadeus::AuthenticationError, client) if @status_code == 401
|
16
|
+
raise_error(Amadeus::NotFoundError, client) if @status_code == 404
|
17
|
+
raise_error(Amadeus::ClientError, client) if @status_code >= 400
|
18
|
+
raise_error(Amadeus::ParserError, client) unless @parsed
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
# Tries to parse the received data from raw string to parsed data and into
|
24
|
+
# a data object
|
25
|
+
def parse_data(client)
|
26
|
+
@parsed = false
|
27
|
+
@result = parse_json(http_response, client)
|
28
|
+
@data = @result.fetch('data', nil) if @result
|
29
|
+
end
|
30
|
+
|
31
|
+
# Logs and raises the error
|
32
|
+
def raise_error(error_class, client)
|
33
|
+
error = error_class.new(self)
|
34
|
+
error.log(client)
|
35
|
+
raise error
|
36
|
+
end
|
37
|
+
|
38
|
+
# Tries to parse the JSON, if there is any
|
39
|
+
def parse_json(http_response, client)
|
40
|
+
@body = http_response.body
|
41
|
+
return unless json?(http_response)
|
42
|
+
json = JSON.parse(@body)
|
43
|
+
@parsed = true
|
44
|
+
return json
|
45
|
+
rescue JSON::ParserError
|
46
|
+
raise_error(Amadeus::ParserError, client)
|
47
|
+
end
|
48
|
+
|
49
|
+
def parse_status_code
|
50
|
+
@status_code = http_response.code
|
51
|
+
@status_code = @status_code.to_i if @status_code
|
52
|
+
end
|
53
|
+
|
54
|
+
# checks if the HTTPResponse included JSON
|
55
|
+
def json?(http_response)
|
56
|
+
json_header?(http_response) && body?(http_response)
|
57
|
+
end
|
58
|
+
|
59
|
+
# checks if the HTTPResponse has a non-empty body
|
60
|
+
def body?(http_response)
|
61
|
+
http_response.body && !http_response.body.empty?
|
62
|
+
end
|
63
|
+
|
64
|
+
# checks if the HTTPResponse has a JSON header
|
65
|
+
def json_header?(http_response)
|
66
|
+
content_type = http_response['Content-Type']
|
67
|
+
content_types = ['application/json', 'application/vnd.amadeus+json']
|
68
|
+
content_type && content_types.include?(content_type.split(';').first)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Amadeus
|
4
|
+
class Client
|
5
|
+
# A set of helper methods to allow the validating of
|
6
|
+
# arguments past into the {Amadeus::Client}
|
7
|
+
# @!visibility private
|
8
|
+
module Validator
|
9
|
+
private
|
10
|
+
|
11
|
+
# Uses {init_optional} to find an entry, and it that returns
|
12
|
+
# nil it raises an ArgumentError
|
13
|
+
#
|
14
|
+
# @param [String or Symbol] key the key to find the entry
|
15
|
+
# @param [Hash] options the arguments were passed to the {Amadeus::Client}
|
16
|
+
# @raise [ArgumentError] when no entry can be found
|
17
|
+
#
|
18
|
+
def init_required(key, options)
|
19
|
+
init_optional(key, options).tap do |val|
|
20
|
+
raise(ArgumentError, "Missing required argument: #{key}") if val.nil?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Tries to find an option by string or symbol in the options hash and
|
25
|
+
# in the environment variables.When it can not find it anywhere it
|
26
|
+
# defaults to the provided default option.
|
27
|
+
#
|
28
|
+
# @param [String or Symbol] key the key to find the entry
|
29
|
+
# @param [Hash] options the arguments were passed to the {Amadeus::Client}
|
30
|
+
# @param [Object] default an optional default value to return
|
31
|
+
#
|
32
|
+
def init_optional(key, options, default = nil)
|
33
|
+
value = options[key]
|
34
|
+
value = options[key.to_s] if value.nil?
|
35
|
+
value = ENV["AMADEUS_#{key.to_s.upcase}"] if value.nil?
|
36
|
+
value = default if value.nil?
|
37
|
+
value
|
38
|
+
end
|
39
|
+
|
40
|
+
# Checks a list of options for unrecognized keys and warns the user.
|
41
|
+
# This is mainly used to provide a nice experience when users make a typo
|
42
|
+
# in their arguments.
|
43
|
+
#
|
44
|
+
# @param [Hash] options the arguments were passed to the {Amadeus::Client}
|
45
|
+
# @param [Logger] logger the logger used to send warnings to
|
46
|
+
# @param [Hash] recognized_options a whitelist of recognized options
|
47
|
+
# @return [nil]
|
48
|
+
|
49
|
+
def warn_on_unrecognized_options(options, logger, recognized_options)
|
50
|
+
options.each_key do |key|
|
51
|
+
next if recognized_options.include?(key.to_sym)
|
52
|
+
logger.warn('Amadeus::Client::Validator') do
|
53
|
+
# :nocov:
|
54
|
+
"Unrecognized option: #{key}"
|
55
|
+
# :nocov:
|
56
|
+
end
|
57
|
+
end
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Amadeus
|
4
|
+
# The namespaces that allow this API to map the paths
|
5
|
+
# of the API to similar calls on the SDK
|
6
|
+
#
|
7
|
+
# Access via the +Amadeus::Client+ object
|
8
|
+
#
|
9
|
+
# amadeus = Amadeus::Client.new
|
10
|
+
# amadeus.reference_data
|
11
|
+
# amadeus.shopping
|
12
|
+
# amadeus.travel
|
13
|
+
#
|
14
|
+
module Namespaces
|
15
|
+
# The namespace for the checkin links and locations APIs:
|
16
|
+
#
|
17
|
+
# @return [Amadeus::Namespaces::ReferenceData]
|
18
|
+
# @example Some of the further namespaces available
|
19
|
+
# amadeus.reference_data.urls.checkin_links
|
20
|
+
# amadeus.reference_data.locations
|
21
|
+
#
|
22
|
+
def reference_data
|
23
|
+
ReferenceData.new(self)
|
24
|
+
end
|
25
|
+
|
26
|
+
# The namespace for the shopping APIs:
|
27
|
+
#
|
28
|
+
# @return [Amadeus::Namespaces::Shopping]
|
29
|
+
# @example Some of the further namespaces available
|
30
|
+
# amadeus.shopping.flight_destinations
|
31
|
+
# amadeus.shopping.flight_offers
|
32
|
+
# amadeus.shopping.flight_dates
|
33
|
+
# amadeus.shopping.hotel_offers
|
34
|
+
# amadeus.shopping.hotels
|
35
|
+
#
|
36
|
+
def shopping
|
37
|
+
Shopping.new(self)
|
38
|
+
end
|
39
|
+
|
40
|
+
# The namespace for the travel analytics APIs:
|
41
|
+
#
|
42
|
+
# @return [Amadeus::Namespaces::Travel]
|
43
|
+
# @example Some of the further namespaces available
|
44
|
+
# amadeus.travel.analytics.air_traffics
|
45
|
+
# amadeus.travel.analytics.fare_searches
|
46
|
+
#
|
47
|
+
def travel
|
48
|
+
Travel.new(self)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Amadeus
|
4
|
+
module Namespaces
|
5
|
+
# A namespaced client for the
|
6
|
+
# +/v2/reference_data+ endpoints
|
7
|
+
#
|
8
|
+
# Access via the +Amadeus::Client+ object
|
9
|
+
#
|
10
|
+
# amadeus = Amadeus::Client.new
|
11
|
+
# amadeus.reference_data
|
12
|
+
#
|
13
|
+
class ReferenceData < Amadeus::Client::Decorator
|
14
|
+
# The namespace for the Urls APIs.
|
15
|
+
#
|
16
|
+
# @return [Amadeus::Namespaces::ReferenceData::Urls]
|
17
|
+
# @example
|
18
|
+
# amadeus.reference_data.urls.checkin_links
|
19
|
+
#
|
20
|
+
def urls
|
21
|
+
Amadeus::Namespaces::ReferenceData::Urls.new(client)
|
22
|
+
end
|
23
|
+
|
24
|
+
# The namespace for the Locations APIs:
|
25
|
+
#
|
26
|
+
# @param [Number] location_id The optional ID for the location
|
27
|
+
# @return [Amadeus::Namespaces::ReferenceData::Locations]
|
28
|
+
# @example
|
29
|
+
# amadeus.reference_data.locations
|
30
|
+
# amadeus.reference_data.locations.airports
|
31
|
+
#
|
32
|
+
def locations(location_id = nil)
|
33
|
+
if location_id
|
34
|
+
Amadeus::Namespaces::ReferenceData::Location.new(client, location_id)
|
35
|
+
else
|
36
|
+
Amadeus::Namespaces::ReferenceData::Locations.new(client)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Amadeus
|
4
|
+
module Namespaces
|
5
|
+
class ReferenceData
|
6
|
+
# A namespaced client for the
|
7
|
+
# +/v2/reference-data/locations/:location_id+ endpoints
|
8
|
+
#
|
9
|
+
# Access via the +Amadeus::Client+ object
|
10
|
+
#
|
11
|
+
# amadeus = Amadeus::Client.new
|
12
|
+
# amadeus.reference_data.locations('ALHR')
|
13
|
+
#
|
14
|
+
class Location < Amadeus::Client::Decorator
|
15
|
+
# the Location ID
|
16
|
+
attr_reader :location_id
|
17
|
+
|
18
|
+
# Initialize this namespaced client with an
|
19
|
+
# {Amadeus::Client} instance and an optional Location ID
|
20
|
+
#
|
21
|
+
# @param [Amadeus::Client] client
|
22
|
+
# @param [Number] location_id
|
23
|
+
#
|
24
|
+
def initialize(client, location_id = nil)
|
25
|
+
super(client)
|
26
|
+
@location_id = location_id
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns details for a specific airport
|
30
|
+
#
|
31
|
+
# @return [Amadeus::Response] a parsed response
|
32
|
+
# @raise [Amadeus::Base] an exception if the call failed
|
33
|
+
# @example Find details for London Heathrow
|
34
|
+
# amadeus.reference_data.locations('ALHR').get
|
35
|
+
#
|
36
|
+
def get(params = {})
|
37
|
+
client.get("/v1/reference-data/locations/#{@location_id}", params)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Amadeus
|
4
|
+
module Namespaces
|
5
|
+
class ReferenceData
|
6
|
+
# A namespaced client for the
|
7
|
+
# +/v2/reference-data/locations+ endpoints
|
8
|
+
#
|
9
|
+
# Access via the +Amadeus::Client+ object
|
10
|
+
#
|
11
|
+
# amadeus = Amadeus::Client.new
|
12
|
+
# amadeus.reference_data.locations
|
13
|
+
#
|
14
|
+
class Locations < Amadeus::Client::Decorator
|
15
|
+
# The namespace for the Airports API:
|
16
|
+
#
|
17
|
+
# @return [Amadeus::Namespaces::ReferenceData::Locations::Airports]
|
18
|
+
# @example
|
19
|
+
# amadeus.reference_data.locations.airports
|
20
|
+
#
|
21
|
+
def airports
|
22
|
+
Amadeus::Namespaces::ReferenceData::Locations::Airports.new(client)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns a list of airports and cities matching a given keyword.
|
26
|
+
#
|
27
|
+
# @option params [String] :keyword keyword that should represent the
|
28
|
+
# start of a word in a city or airport name or code
|
29
|
+
# @option params [String] :subType the {Amadeus::Location} to
|
30
|
+
# search for
|
31
|
+
# @return [Amadeus::Response] a parsed response
|
32
|
+
# @raise [Amadeus::Base] an exception if the call failed
|
33
|
+
# @example Find any location starting with 'lon'
|
34
|
+
# amadeus.reference_data.locations.get(
|
35
|
+
# keyword: 'lon',
|
36
|
+
# subType: Amadeus::Location::ANY
|
37
|
+
# )
|
38
|
+
#
|
39
|
+
def get(params = {})
|
40
|
+
client.get('/v1/reference-data/locations', params)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Amadeus
|
4
|
+
module Namespaces
|
5
|
+
class ReferenceData
|
6
|
+
class Locations
|
7
|
+
# A namespaced client for the
|
8
|
+
# +/v2/reference-data/locations/airports+ endpoints
|
9
|
+
#
|
10
|
+
# Access via the +Amadeus::Client+ object
|
11
|
+
#
|
12
|
+
# amadeus = Amadeus::Client.new
|
13
|
+
# amadeus.reference_data.locations.airports
|
14
|
+
#
|
15
|
+
class Airports < Amadeus::Client::Decorator
|
16
|
+
# Returns a list of relevant airports near to a given point.
|
17
|
+
#
|
18
|
+
# @option params [Double] :latitude latitude location to be at the
|
19
|
+
# center of the search circle - required
|
20
|
+
# @option params [Double] :longitude longitude location to be at the
|
21
|
+
# center of the search circle - required
|
22
|
+
# @return [Amadeus::Response] a parsed response
|
23
|
+
# @raise [Amadeus::Base] an exception if the call
|
24
|
+
# failed
|
25
|
+
# @example Find the nearest airport to the 49.0000,2.55 lat/long
|
26
|
+
# amadeus.reference_data.locations.airports.get(
|
27
|
+
# longitude: 49.0000,
|
28
|
+
# latitude: 2.55
|
29
|
+
# )
|
30
|
+
#
|
31
|
+
def get(params = {})
|
32
|
+
client.get('/v1/reference-data/locations/airports', params)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|