expedia_api 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
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