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.
Files changed (48) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +10 -0
  3. data/LICENSE +15 -0
  4. data/README.md +157 -19
  5. data/amadeus.gemspec +26 -16
  6. data/lib/amadeus.rb +31 -4
  7. data/lib/amadeus/client.rb +120 -0
  8. data/lib/amadeus/client/access_token.rb +61 -0
  9. data/lib/amadeus/client/decorator.rb +27 -0
  10. data/lib/amadeus/client/errors.rb +76 -0
  11. data/lib/amadeus/client/http.rb +137 -0
  12. data/lib/amadeus/client/location.rb +13 -0
  13. data/lib/amadeus/client/pagination.rb +103 -0
  14. data/lib/amadeus/client/request.rb +145 -0
  15. data/lib/amadeus/client/request/hash.rb +32 -0
  16. data/lib/amadeus/client/response.rb +62 -0
  17. data/lib/amadeus/client/response/parser.rb +72 -0
  18. data/lib/amadeus/client/validator.rb +62 -0
  19. data/lib/amadeus/namespaces/core.rb +51 -0
  20. data/lib/amadeus/namespaces/reference_data.rb +41 -0
  21. data/lib/amadeus/namespaces/reference_data/location.rb +42 -0
  22. data/lib/amadeus/namespaces/reference_data/locations.rb +45 -0
  23. data/lib/amadeus/namespaces/reference_data/locations/airports.rb +38 -0
  24. data/lib/amadeus/namespaces/reference_data/urls.rb +27 -0
  25. data/lib/amadeus/namespaces/reference_data/urls/checkin_links.rb +33 -0
  26. data/lib/amadeus/namespaces/shopping.rb +66 -0
  27. data/lib/amadeus/namespaces/shopping/flight_dates.rb +33 -0
  28. data/lib/amadeus/namespaces/shopping/flight_destinations.rb +30 -0
  29. data/lib/amadeus/namespaces/shopping/flight_offers.rb +36 -0
  30. data/lib/amadeus/namespaces/shopping/hotel.rb +56 -0
  31. data/lib/amadeus/namespaces/shopping/hotel/hotel_offers.rb +44 -0
  32. data/lib/amadeus/namespaces/shopping/hotel/offer.rb +58 -0
  33. data/lib/amadeus/namespaces/shopping/hotel_offers.rb +37 -0
  34. data/lib/amadeus/namespaces/travel.rb +26 -0
  35. data/lib/amadeus/namespaces/travel/analytics.rb +37 -0
  36. data/lib/amadeus/namespaces/travel/analytics/air_traffics.rb +37 -0
  37. data/lib/amadeus/namespaces/travel/analytics/fare_searches.rb +46 -0
  38. data/lib/amadeus/version.rb +4 -1
  39. metadata +161 -23
  40. data/.gitignore +0 -12
  41. data/.rspec +0 -2
  42. data/.travis.yml +0 -5
  43. data/CODE_OF_CONDUCT.md +0 -74
  44. data/Gemfile +0 -4
  45. data/LICENSE.txt +0 -21
  46. data/Rakefile +0 -6
  47. data/bin/console +0 -14
  48. 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