google_flights_agent.rb 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. module Agents
  2. class GoogleFlightsAgent < Agent
  3. include FormConfigurable
  4. cannot_receive_events!
  5. default_schedule "every_12h"
  6. description <<-MD
  7. The GoogleFlightsAgent will tell you the minimum airline prices between a pair of cities.
  8. Follow the documentation [here](https://developers.google.com/qpx-express/v1/prereqs#get-a-google-account) to retrieve an api key.
  9. After you get to the google developer console, created a project, enabled qpx express api then you can choose `api key` credential to be created.
  10. Note that at present you're limited to 50 queries per day free and after that are billed $0.035 per query.
  11. The `origin` and `destination` options require an [airport code](http://www.expedia.com/daily/airports/AirportCodes.asp).
  12. All the default options must exist. For `infantInSeatCount`, `infantInLapCount`, `seniorCount`, and `childCount`, leave them to the default value of `0` if you do not need them.
  13. Make sure `date` and `return_date` is in this date format: `YYYY-MM-DAY`. You can use liquid formatting to dynamically assign a date in the future. For example to set the departure date 21 days from today, you'd use `{% assign current_date = 'now' | date: '%s' %}{{current_date | plus: 1814000 | date: '%Y-%m-%d'}}`
  14. You can choose one way tickets only by setting `roundtrip` to `false`.
  15. You can limit to specific airlines using the `permittedCarrier` option and the two-letter IATA airline codes of choice. [https://en.wikipedia.org/wiki/List_of_airline_codes](https://en.wikipedia.org/wiki/List_of_airline_codes). Multiple airlines can be chosen, separated by commas.
  16. You can alternately limit your search to a specific set of airlines with the `alliance` option, to choose among the three Google-recognized ones, ONEWORLD, STAR and SKYTEAM.
  17. You can limit the number of `solutions` returned. The first solution will be the lowest priced ticket.
  18. MD
  19. event_description <<-MD
  20. The event payload will have objects that contains valuable data like this
  21. "carrier": [
  22. {
  23. "code": "B6",
  24. "name": "Jetblue Airways Corporation"
  25. }
  26. ]
  27. "tripOption": [
  28. "saleTotal": "USD49.10"
  29. "slice": [
  30. ...
  31. ...
  32. "flight": {
  33. "carrier": "B6",
  34. "number": "833"
  35. }
  36. ]
  37. ]
  38. MD
  39. def default_options
  40. {
  41. 'qpx_api_key' => '',
  42. 'adultCount'=> 1,
  43. 'origin' => 'BOS',
  44. 'destination' => 'SFO',
  45. 'date' => '2016-04-11',
  46. 'childCount' => 0,
  47. 'infantInSeatCount' => 0,
  48. 'infantInLapCount'=> 0,
  49. 'seniorCount'=> 0,
  50. 'return_date' => '2016-04-18',
  51. 'roundtrip' => true,
  52. 'preferredCabin' => 'COACH',
  53. 'solutions'=> 3,
  54. 'permittedCarrier' => '',
  55. 'alliance' => ''
  56. }
  57. end
  58. form_configurable :qpx_api_key, type: :string
  59. form_configurable :adultCount
  60. form_configurable :origin, type: :string
  61. form_configurable :destination, type: :string
  62. form_configurable :date, type: :string
  63. form_configurable :preferredCabin, type: :array, values: %w(COACH PREMIUM_COACH BUSINESS FIRST)
  64. form_configurable :permittedCarrier, type: :string
  65. form_configurable :alliance, type: :array, values: %w(ONEWORLD SKYTEAM STAR)
  66. form_configurable :childCount
  67. form_configurable :infantInSeatCount
  68. form_configurable :infantInLapCount
  69. form_configurable :seniorCount
  70. form_configurable :roundtrip, type: :boolean
  71. form_configurable :return_date, type: :string
  72. form_configurable :solutions
  73. def validate_options
  74. errors.add(:base, "You need a qpx api key") unless options['qpx_api_key'].present?
  75. errors.add(:base, "Adult Count must exist") unless options['adultCount'].present?
  76. errors.add(:base, "Origin must exist") unless options['origin'].present?
  77. errors.add(:base, "Destination must exist") unless options['destination'].present?
  78. errors.add(:base, "Date must exist") unless options['date'].present?
  79. errors.add(:base, "Child Count") unless options['childCount'].present?
  80. errors.add(:base, "Infant In Seat Count must exist") unless options['infantInSeatCount'].present?
  81. errors.add(:base, "Infant In Lap Count") unless options['infantInLapCount'].present?
  82. errors.add(:base, "Senior Count must exist") unless options['seniorCount'].present?
  83. errors.add(:base, "Solutions must exist") unless options['solutions'].present?
  84. errors.add(:base, "Return Date must exist") if options["return_date"].blank? && boolify(options['roundtrip'])
  85. end
  86. def working?
  87. !recent_error_logs?
  88. end
  89. def round_trip?
  90. boolify(interpolated['roundtrip'])
  91. end
  92. def post_params
  93. if round_trip?
  94. post_params = {:request=>{:passengers=>{:kind=>"qpxexpress#passengerCounts", :adultCount=> interpolated["adultCount"], :childCount=> interpolated["childCount"], :infantInLapCount=>interpolated["infantInLapCount"], :infantInSeatCount=>interpolated['infantInSeatCount'], :seniorCount=>interpolated["seniorCount"]}, :slice=>[ {:origin=> interpolated["origin"].to_s , :destination=> interpolated["destination"].to_s , :date=> interpolated["date"].to_s , :preferredCabin=> interpolated["preferredCabin"].to_s , :permittedCarrier=> interpolated["permittedCarrier"].to_s , :alliance=> interpolated["alliance"].to_s }, {:origin=>interpolated["destination"].to_s , :destination=> interpolated["origin"].to_s , :date=> interpolated["return_date"].to_s , :preferredCabin=> interpolated["preferredCabin"].to_s , :permittedCarrier=> interpolated["permittedCarrier"].to_s , :alliance=>interpolated["alliance"].to_s } ], :solutions=> interpolated["solutions"]}}
  95. else
  96. post_params = {:request=>{:passengers=>{:kind=>"qpxexpress#passengerCounts", :adultCount=> interpolated["adultCount"], :childCount=> interpolated["childCount"], :infantInLapCount=>interpolated["infantInLapCount"], :infantInSeatCount=>interpolated['infantInSeatCount'], :seniorCount=>interpolated["seniorCount"]}, :slice=>[{:kind=>"qpxexpress#sliceInput", :origin=> interpolated["origin"].to_s , :destination=> interpolated["destination"].to_s , :date=> interpolated["date"].to_s , :preferredCabin=> interpolated["preferredCabin"].to_s , :permittedCarrier=> interpolated["permittedCarrier"].to_s , :alliance=>interpolated["alliance"].to_s }], :solutions=> interpolated["solutions"]}}
  97. end
  98. end
  99. def check
  100. body = JSON.generate(post_params)
  101. request = HTTParty.post(event_url, :body => body, :headers => {"Content-Type" => "application/json"})
  102. events = JSON.parse request.body
  103. create_event :payload => events
  104. end
  105. def event_url
  106. endpoint = 'https://www.googleapis.com/qpxExpress/v1/trips/search?key=' + "#{URI.encode(interpolated[:qpx_api_key].to_s)}"
  107. end
  108. end
  109. end