expedia_api 0.1.3 → 0.1.4

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
  SHA1:
3
- metadata.gz: 2087ea6d06f80910b08422290767099664c7025e
4
- data.tar.gz: a16cde4dc03bf5dfbc040cc51682edbd8e4a4156
3
+ metadata.gz: b1fe7e96bee4a14c1f2667b22eb9da9f5445e5b8
4
+ data.tar.gz: 2d5f8165948ef02e8de35ce24698b2c4126829fa
5
5
  SHA512:
6
- metadata.gz: ebb4d56de697d4dd04579880706b959a30e99737f5b23a6085475a003a0a6eb4ec97319c71ed68f187e41fad347834b8b34d3f1339cb1824db11175b6727793a
7
- data.tar.gz: 8a559770123d2617f5d70518c41920ce16e4137c2b860b57ffa2f999cdea16fcc43b081d0caa972fbea7ca95d0a55dd9b0ca9ba78b448b7faced03bde316d9ba
6
+ metadata.gz: d04cde9d1f73bbadc2d939339a4393eccf50ce33fca9504b0b129588ad2ef6691878339e70e83ad918234e27bdea3231f867ea44bdb2497fc44ec87fadd8d458
7
+ data.tar.gz: d1d264980a237298402a4901d1dc2b2089396887338fbcac11a0b490c2c0b2d51f69cffe5dcb4f005ce3f25f881cc8fc41f2ba67ae15ab031bb7294ec5f03cba
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Expedia Api
2
2
 
3
+ [![Build Status](https://travis-ci.org/hendricius/expedia_api.svg?branch=master)](https://travis-ci.org/hendricius/expedia_api)
4
+
3
5
  This is a ruby wrapper for the official Expedia.com API. Please note that the Expedia.com API is a different than the one provided by the Expedia Affiliate Network. They are different companies. If you want to use the EAN Api please use [expedia gem](https://github.com/zaidakram/expedia).
4
6
 
5
7
 
@@ -39,9 +41,17 @@ Then when using the API create a new client object:
39
41
 
40
42
  ```
41
43
  client = ExpediaApi::Client.new
44
+ ```
45
+
46
+ Search Hotels:
47
+ ```
42
48
  client.get_list({})
49
+ ```
43
50
 
51
+ Search Packages:
44
52
 
53
+ ```
54
+ client.search_packages({})
45
55
  ```
46
56
 
47
57
  The parameters you can pass to `get_list` are the following:
data/expedia_api.gemspec CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
11
11
 
12
12
  spec.description = "Expediacom is a lightweight flexible Ruby SDK for the official Expedia.com API"
13
13
  spec.summary = "Wrapper for the Expedia.com API"
14
- spec.homepage = "https://github.com/hendricius/expediacom"
14
+ spec.homepage = "https://github.com/hendricius/expedia_api"
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
17
  spec.bindir = "exe"
@@ -26,5 +26,6 @@ Gem::Specification.new do |spec|
26
26
  spec.add_runtime_dependency(%q<faraday>, ["~> 0.8"])
27
27
  spec.add_runtime_dependency "faraday_middleware"
28
28
  spec.add_runtime_dependency "activesupport"
29
+ spec.add_runtime_dependency "money", '~> 6'
29
30
 
30
31
  end
data/lib/expedia_api.rb CHANGED
@@ -2,13 +2,20 @@ require 'json'
2
2
  require 'faraday'
3
3
  require 'faraday_middleware'
4
4
  require 'active_support/core_ext/hash/indifferent_access'
5
+ require 'money'
5
6
 
6
7
  require "expedia_api/version"
7
8
  require "expedia_api/http_service"
8
9
  require "expedia_api/client"
9
- require "expedia_api/hotel_response_list"
10
10
  require "expedia_api/entities"
11
11
  require "expedia_api/entities/search_entity"
12
+ require "expedia_api/entities/package"
13
+ require "expedia_api/entities/package_flight"
14
+ require "expedia_api/entities/package_hotel"
15
+ require "expedia_api/response_lists"
16
+ require "expedia_api/response_lists/base_response_list"
17
+ require "expedia_api/response_lists/packages"
18
+ require "expedia_api/response_lists/hotels"
12
19
 
13
20
  module ExpediaApi
14
21
  class << self
@@ -81,19 +81,48 @@ module ExpediaApi
81
81
  # true
82
82
  # description:
83
83
  # return available hotels only. default: true
84
- def get_list(parameters = {})
85
- data = request(parameters: parameters)
86
- ExpediaApi::HotelResponseList.new(response: data)
84
+ def search_hotels(parameters = {})
85
+ data = request(parameters: parameters, uri: 'wsapi/rest/hotel/v1/search')
86
+ ExpediaApi::ResponseLists::Hotels.new(response: data)
87
87
  rescue Faraday::ParsingError => e
88
- ExpediaApi::HotelResponseList.new(exception: e)
88
+ ExpediaApi::ResponseLists::Hotels.new(exception: e)
89
89
  rescue Faraday::ConnectionFailed => e
90
- ExpediaApi::HotelResponseList.new(exception: e)
90
+ ExpediaApi::ResponseLists::Hotels.new(exception: e)
91
+ end
92
+
93
+ def search_packages(hotel_ids: [], region_ids: [], from_date:, to_date:, from_airport:, to_airport:, other_options: {})
94
+ validate_package_arguments({hotel_ids: hotel_ids, region_ids: region_ids})
95
+ parameters = {}
96
+ parameters[:hotelids] = hotel_ids if hotel_ids.length
97
+ parameters[:regionids] = region_ids if region_ids.length
98
+ path_uri = build_package_search_request_path(from_airport: from_airport, to_airport: to_airport, from_date: from_date, to_date: to_date)
99
+ base_uri = "/wsapi/rest/package/v1/search"
100
+ full_uri = "#{base_uri}/#{path_uri}"
101
+ data = request(parameters: parameters, uri: full_uri)
102
+ ExpediaApi::ResponseLists::Packages.new(response: data)
103
+ rescue Faraday::ParsingError => e
104
+ ExpediaApi::PackageResponseList.new(exception: e)
105
+ rescue Faraday::ConnectionFailed => e
106
+ ExpediaApi::PackageResponseList.new(exception: e)
91
107
  end
92
108
 
93
109
  private
94
110
 
95
- def request(request_options: {}, parameters: {})
96
- HTTPService.perform_request(request_options: request_options, parameters: parameters)
111
+ def request(request_options: {}, parameters: {}, uri:)
112
+ HTTPService.perform_request(request_options: request_options, parameters: parameters, uri: uri)
113
+ end
114
+
115
+ def validate_package_arguments(args)
116
+ if args[:hotel_ids].empty? && args[:region_ids].empty?
117
+ raise ArgumentError
118
+ end
119
+ true
120
+ end
121
+
122
+ def build_package_search_request_path(from_airport:, to_airport:, from_date:, to_date:)
123
+ from_date = from_date.strftime("%F")
124
+ to_date = to_date.strftime("%F")
125
+ "#{from_date}/#{from_airport}/#{to_airport}/#{to_date}/#{to_airport}/#{from_airport}"
97
126
  end
98
127
 
99
128
  end
@@ -0,0 +1,38 @@
1
+ module ExpediaApi
2
+ module Entities
3
+ class Package
4
+ attr_accessor :flight, :hotel
5
+ attr_reader :raw_data
6
+
7
+ def initialize(raw_data)
8
+ @raw_data = raw_data || {}
9
+ end
10
+
11
+ def flight_index
12
+ raw_data[:FlightReferenceIndex].to_i
13
+ end
14
+
15
+ def hotel_index
16
+ raw_data[:HotelReferenceIndex].to_i
17
+ end
18
+
19
+ # returns a money object including the price. returns nil if there is no price
20
+ def price
21
+ if raw_data[:PackagePrice] && raw_data[:PackagePrice][:TotalPrice]
22
+ Money.new(raw_data[:PackagePrice][:TotalPrice][:Value].to_f * 100, raw_data[:PackagePrice][:TotalPrice][:Currency])
23
+ else
24
+ nil
25
+ end
26
+ end
27
+
28
+ # returns a money object with the savings, nil if there are no savings.
29
+ def savings
30
+ if raw_data[:PackagePrice] && raw_data[:PackagePrice][:TotalSavings]
31
+ Money.new(raw_data[:PackagePrice][:TotalSavings][:Value].to_f * 100, raw_data[:PackagePrice][:TotalSavings][:Currency])
32
+ else
33
+ nil
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,47 @@
1
+ module ExpediaApi
2
+ module Entities
3
+ class PackageFlight
4
+ attr_reader :raw_data
5
+
6
+ def initialize(raw_data)
7
+ @raw_data = raw_data || {}
8
+ end
9
+
10
+ def index
11
+ raw_data[:FlightIndex].to_i
12
+ end
13
+
14
+ def flight_legs
15
+ extract_flightlegs.map do |leg|
16
+ FlightLeg.new(leg)
17
+ end
18
+ end
19
+
20
+ def extract_flightlegs
21
+ raw_data.fetch(:FlightItinerary, {}).fetch(:FlightLeg, {})
22
+ end
23
+
24
+ class FlightLeg
25
+ def initialize(raw_data)
26
+ @raw_data = raw_data || {}
27
+ end
28
+
29
+ def segments
30
+ extract_segments.map do |segment|
31
+ FlightLegSegment.new(segment)
32
+ end
33
+ end
34
+
35
+ def extract_segments
36
+ @raw_data[:FlightSegment] || []
37
+ end
38
+ end
39
+
40
+ class FlightLegSegment
41
+ def initialize(raw_data)
42
+ @raw_data = raw_data || {}
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,15 @@
1
+ module ExpediaApi
2
+ module Entities
3
+ class PackageHotel
4
+ attr_reader :raw_data
5
+
6
+ def initialize(raw_data)
7
+ @raw_data = raw_data || {}
8
+ end
9
+
10
+ def index
11
+ raw_data[:HotelIndex].to_i
12
+ end
13
+ end
14
+ end
15
+ end
@@ -2,7 +2,6 @@ module ExpediaApi
2
2
  module HTTPService
3
3
 
4
4
  API_SERVER = 'ews.expedia.com'
5
- API_PATH = 'wsapi/rest/hotel/v1/search'
6
5
 
7
6
  class << self
8
7
 
@@ -24,14 +23,14 @@ module ExpediaApi
24
23
  options
25
24
  end
26
25
 
27
- def perform_request(request_options: {}, parameters: {})
26
+ def perform_request(request_options: {}, parameters: {}, uri:)
28
27
  args = common_parameters.merge(parameters)
29
28
  # figure out our options for this request
30
29
  # set up our Faraday connection
31
30
  connection = Faraday.new(faraday_options) do |faraday|
32
31
  faraday.adapter Faraday.default_adapter
33
32
  end
34
- connection.get(API_PATH, args)
33
+ connection.get(uri, args)
35
34
  end
36
35
 
37
36
  def use_proxy?
@@ -0,0 +1,4 @@
1
+ module ExpediaApi
2
+ module ResponseLists
3
+ end
4
+ end
@@ -0,0 +1,75 @@
1
+ module ExpediaApi
2
+ module ResponseLists
3
+ class BaseResponseList
4
+ include Enumerable
5
+ attr_reader :response, :exception
6
+
7
+ def initialize(entries: [], response: nil, exception: nil)
8
+ @response = response
9
+ @exception = exception
10
+ end
11
+
12
+ def each(&block)
13
+ entries.each(&:block)
14
+ end
15
+
16
+ def map(&block)
17
+ entries.map(&:block)
18
+ end
19
+
20
+ def first
21
+ entries.first
22
+ end
23
+
24
+ def last
25
+ entries.last
26
+ end
27
+
28
+ def entries
29
+ @entries ||= begin
30
+ self.entries = extract_entries_from_response(@response)
31
+ self.entries
32
+ end
33
+ end
34
+
35
+ def entries=(entries)
36
+ raise ArgumentError, "implement me"
37
+ end
38
+
39
+ def success?
40
+ exception.nil?
41
+ end
42
+
43
+ def error?
44
+ !!exception
45
+ end
46
+
47
+ def extract_entries_from_response(response)
48
+ raise ArgumentError, "implement me"
49
+ end
50
+
51
+ private
52
+
53
+ # extracts an array of data from the response
54
+ #
55
+ # returns an array.
56
+ def extract_data_from_response(response)
57
+ if response.nil?
58
+ return []
59
+ end
60
+ body = nil
61
+ begin
62
+ body = JSON.parse(response.body)
63
+ rescue JSON::ParserError => e
64
+ @exception = e
65
+ return []
66
+ end
67
+ if !body.is_a?(Hash) || body.nil?
68
+ return []
69
+ end
70
+ body
71
+ end
72
+
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,28 @@
1
+ module ExpediaApi
2
+ module ResponseLists
3
+ class Hotels < BaseResponseList
4
+
5
+ def entries=(entries)
6
+ if entries
7
+ @entries = entries.map {|e| ExpediaApi::Entities::SearchEntity.new(e.with_indifferent_access) }
8
+ else
9
+ @entries = []
10
+ end
11
+ end
12
+
13
+ def extract_entries_from_response(response)
14
+ body = extract_data_from_response(response)
15
+ return [] if body.empty?
16
+ hotel_count = body["HotelCount"].to_i
17
+ if hotel_count == 1
18
+ [body["HotelInfoList"]["HotelInfo"]]
19
+ elsif hotel_count > 1
20
+ body["HotelInfoList"]["HotelInfo"]
21
+ else
22
+ []
23
+ end
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,46 @@
1
+ module ExpediaApi
2
+ module ResponseLists
3
+ class Packages < BaseResponseList
4
+
5
+ def entries=(entries)
6
+ @entries = entries
7
+ end
8
+
9
+ def extract_entries_from_response(response)
10
+ json = extract_data_from_response(response).with_indifferent_access
11
+ return [] if json.empty?
12
+ json = json.with_indifferent_access
13
+ flights = extract_flights(json[:FlightList][:Flight])
14
+ hotels = extract_hotels(json[:HotelList][:Hotel])
15
+ packages = extract_packages(json["PackageSearchResultList"]["PackageSearchResult"], hotels: hotels, flights: flights)
16
+ packages
17
+ end
18
+
19
+ # returns flights for each of the entries
20
+ def extract_flights(flights_json)
21
+ # right now only 1 flight
22
+ [ExpediaApi::Entities::PackageFlight.new(flights_json)]
23
+ end
24
+
25
+ # returns hotels for each hotel in the json
26
+ def extract_hotels(hotels_json)
27
+ hotels_json.map do |hotel|
28
+ ExpediaApi::Entities::PackageHotel.new(hotel)
29
+ end
30
+ end
31
+
32
+ # returns packages for each of the json data
33
+ def extract_packages(json, flights:, hotels:)
34
+ flights_by_index = flights.map {|flight| [flight.index, flight]}.to_h
35
+ hotels_by_index = hotels.map {|hotel| [hotel.index, hotel]}.to_h
36
+ json.map do |package|
37
+ entity = ExpediaApi::Entities::Package.new(package)
38
+ entity.flight = flights_by_index[entity.flight_index]
39
+ entity.hotel = hotels_by_index[entity.hotel_index]
40
+ entity
41
+ end
42
+ end
43
+ end
44
+
45
+ end
46
+ end
@@ -1,3 +1,3 @@
1
1
  module ExpediaApi
2
- VERSION = "0.1.3"
2
+ VERSION = "0.1.4"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: expedia_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hendrik Kleinwaechter
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-04-11 00:00:00.000000000 Z
11
+ date: 2016-04-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: money
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '6'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '6'
125
139
  description: Expediacom is a lightweight flexible Ruby SDK for the official Expedia.com
126
140
  API
127
141
  email:
@@ -142,11 +156,17 @@ files:
142
156
  - lib/expedia_api.rb
143
157
  - lib/expedia_api/client.rb
144
158
  - lib/expedia_api/entities.rb
159
+ - lib/expedia_api/entities/package.rb
160
+ - lib/expedia_api/entities/package_flight.rb
161
+ - lib/expedia_api/entities/package_hotel.rb
145
162
  - lib/expedia_api/entities/search_entity.rb
146
- - lib/expedia_api/hotel_response_list.rb
147
163
  - lib/expedia_api/http_service.rb
164
+ - lib/expedia_api/response_lists.rb
165
+ - lib/expedia_api/response_lists/base_response_list.rb
166
+ - lib/expedia_api/response_lists/hotels.rb
167
+ - lib/expedia_api/response_lists/packages.rb
148
168
  - lib/expedia_api/version.rb
149
- homepage: https://github.com/hendricius/expediacom
169
+ homepage: https://github.com/hendricius/expedia_api
150
170
  licenses: []
151
171
  metadata: {}
152
172
  post_install_message:
@@ -1,73 +0,0 @@
1
- module ExpediaApi
2
- class HotelResponseList
3
- include Enumerable
4
- attr_reader :response, :exception
5
-
6
- def initialize(entries: [], response: nil, exception: nil)
7
- @response = response
8
- self.entries = extract_entries_from_response(response)
9
- @exception = exception
10
- end
11
-
12
- def each(&block)
13
- @entries.each(&:block)
14
- end
15
-
16
- def map(&block)
17
- @entries.map(&:block)
18
- end
19
-
20
- def first
21
- @entries.first
22
- end
23
-
24
- def last
25
- @entries.last
26
- end
27
-
28
- def entries
29
- @entries
30
- end
31
-
32
- def entries=(entries)
33
- @entries = entries.map {|e| ExpediaApi::Entities::SearchEntity.new(e.with_indifferent_access) }
34
- end
35
-
36
- def success?
37
- exception.nil?
38
- end
39
-
40
- def error?
41
- !!exception
42
- end
43
-
44
- def response_body
45
- end
46
-
47
- def extract_entries_from_response(response)
48
- # probably an error ocurred connecting
49
- if response.nil?
50
- return []
51
- end
52
- body = nil
53
- begin
54
- body = JSON.parse(response.body)
55
- rescue JSON::ParserError => e
56
- @exception = e
57
- return []
58
- end
59
- if !body.is_a?(Hash) || body.nil?
60
- return []
61
- end
62
- hotel_count = body["HotelCount"].to_i
63
- if hotel_count == 1
64
- [body["HotelInfoList"]["HotelInfo"]]
65
- elsif hotel_count > 1
66
- body["HotelInfoList"]["HotelInfo"]
67
- else
68
- []
69
- end
70
- end
71
-
72
- end
73
- end