gillbus 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.ruby-version +1 -0
  4. data/Gemfile +10 -0
  5. data/Guardfile +29 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +140 -0
  8. data/Rakefile +9 -0
  9. data/gillbus.gemspec +31 -0
  10. data/lib/gillbus/base_request.rb +99 -0
  11. data/lib/gillbus/base_response.rb +43 -0
  12. data/lib/gillbus/buy_booking.rb +74 -0
  13. data/lib/gillbus/buy_tickets.rb +36 -0
  14. data/lib/gillbus/cancel_order.rb +55 -0
  15. data/lib/gillbus/drivers/faraday_response_file_logger.rb +19 -0
  16. data/lib/gillbus/find_order.rb +37 -0
  17. data/lib/gillbus/get_all_cities.rb +24 -0
  18. data/lib/gillbus/get_cities.rb +34 -0
  19. data/lib/gillbus/get_countries.rb +24 -0
  20. data/lib/gillbus/get_dates_new.rb +35 -0
  21. data/lib/gillbus/get_order_status.rb +28 -0
  22. data/lib/gillbus/get_order_ticket.rb +62 -0
  23. data/lib/gillbus/get_required_fields.rb +32 -0
  24. data/lib/gillbus/get_time_table.rb +33 -0
  25. data/lib/gillbus/get_trip_seats.rb +61 -0
  26. data/lib/gillbus/get_trips.rb +13 -0
  27. data/lib/gillbus/helpers/fields.rb +47 -0
  28. data/lib/gillbus/helpers/parser.rb +100 -0
  29. data/lib/gillbus/helpers/update_attrs.rb +15 -0
  30. data/lib/gillbus/lock_seats.rb +82 -0
  31. data/lib/gillbus/logout.rb +19 -0
  32. data/lib/gillbus/parse_error.rb +11 -0
  33. data/lib/gillbus/reserve_tickets.rb +13 -0
  34. data/lib/gillbus/search_trips.rb +96 -0
  35. data/lib/gillbus/session_login.rb +32 -0
  36. data/lib/gillbus/structs/commission.rb +54 -0
  37. data/lib/gillbus/structs/item.rb +14 -0
  38. data/lib/gillbus/structs/passenger_discount.rb +37 -0
  39. data/lib/gillbus/structs/point.rb +38 -0
  40. data/lib/gillbus/structs/return_cause.rb +23 -0
  41. data/lib/gillbus/structs/seat.rb +38 -0
  42. data/lib/gillbus/structs/segment.rb +161 -0
  43. data/lib/gillbus/structs/tariff.rb +59 -0
  44. data/lib/gillbus/structs/ticket.rb +285 -0
  45. data/lib/gillbus/structs/timetable_segment.rb +51 -0
  46. data/lib/gillbus/structs/timetable_trip.rb +77 -0
  47. data/lib/gillbus/structs/trip.rb +164 -0
  48. data/lib/gillbus/tickets_booking.rb +182 -0
  49. data/lib/gillbus/unlock_seats.rb +15 -0
  50. data/lib/gillbus/version.rb +3 -0
  51. data/lib/gillbus.rb +86 -0
  52. data/script/example_booking.rb +82 -0
  53. data/script/example_booking_with_segments.rb +90 -0
  54. data/script/example_canceling_booking.rb +67 -0
  55. data/script/example_canceling_reservation.rb +69 -0
  56. data/script/example_reservation.rb +88 -0
  57. data/test/buy_booking_test.rb +32 -0
  58. data/test/buy_tickets_test.rb +12 -0
  59. data/test/cancel_order_test.rb +12 -0
  60. data/test/error_test.rb +31 -0
  61. data/test/find_order_test.rb +24 -0
  62. data/test/get_cities_test.rb +12 -0
  63. data/test/get_countries_test.rb +12 -0
  64. data/test/get_dates_new_test.rb +12 -0
  65. data/test/get_order_ticket_test.rb +12 -0
  66. data/test/get_time_table_test.rb +21 -0
  67. data/test/get_trip_seats_test.rb +40 -0
  68. data/test/lock_seats_test.rb +70 -0
  69. data/test/reserve_tickets_test.rb +22 -0
  70. data/test/responses/buyBooking.xml +9 -0
  71. data/test/responses/buyTickets.xml +7 -0
  72. data/test/responses/cancelOrder.xml +8 -0
  73. data/test/responses/error.xml +1 -0
  74. data/test/responses/findOrder.xml +296 -0
  75. data/test/responses/getCities.xml +266 -0
  76. data/test/responses/getCountries.xml +90 -0
  77. data/test/responses/getOrderTicket.xml +3 -0
  78. data/test/responses/getTimeTable.xml +81 -0
  79. data/test/responses/getTripSeats-one-empty-segment.xml +562 -0
  80. data/test/responses/getTripSeats-segments.xml +1052 -0
  81. data/test/responses/getTripSeats.xml +492 -0
  82. data/test/responses/lockSeats.xml +23 -0
  83. data/test/responses/reserveTickets.xml +76 -0
  84. data/test/responses/searchTrips-empty.xml +3 -0
  85. data/test/responses/searchTrips-prod.xml +193 -0
  86. data/test/responses/searchTrips-segments-roundtrip.xml +15812 -0
  87. data/test/responses/searchTrips-segments.xml +808 -0
  88. data/test/responses/sessionLogin.xml +3 -0
  89. data/test/responses/ticketsBooking.xml +75 -0
  90. data/test/responses/very_empty.xml +1 -0
  91. data/test/search_trips_test.rb +71 -0
  92. data/test/session_login_test.rb +12 -0
  93. data/test/test_helper.rb +3 -0
  94. data/test/tickets_booking_test.rb +16 -0
  95. metadata +303 -0
@@ -0,0 +1,34 @@
1
+ class Gillbus
2
+ module GetCities
3
+
4
+ Gillbus.register self, :get_cities
5
+
6
+ class Request < BaseRequest
7
+
8
+ def path; '/online2/getCities' end
9
+
10
+ attr_accessor :start_city_id
11
+
12
+ def params
13
+ {
14
+ startCityId: start_city_id,
15
+ }
16
+ end
17
+
18
+ end
19
+
20
+ class City
21
+ extend Fields
22
+ include UpdateAttrs
23
+ field :id
24
+ field :name
25
+ field :country_id
26
+ field :country_name
27
+ end
28
+
29
+ class Response < BaseResponse
30
+ field :cities, [City], key: 'CITY'
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,24 @@
1
+ class Gillbus
2
+ module GetCountries
3
+
4
+ Gillbus.register self, :get_countries
5
+
6
+ class Request < BaseRequest
7
+
8
+ def path; '/online2/getCountries' end
9
+
10
+ end
11
+
12
+ class Country
13
+ extend Fields
14
+ include UpdateAttrs
15
+ field :id
16
+ field :name
17
+ end
18
+
19
+ class Response < BaseResponse
20
+ field :countries, [Country], key: 'COUNTRY'
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,35 @@
1
+ class Gillbus
2
+ module GetDatesNew
3
+
4
+ Gillbus.register self, :get_dates_new
5
+
6
+ class Request < BaseRequest
7
+
8
+ def path; '/online2/getDatesNew' end
9
+
10
+ attr_accessor :start_city_id
11
+ attr_accessor :end_city_id
12
+ attr_accessor :start_date_search
13
+ attr_accessor :end_date_search
14
+ attr_accessor :oneway_trip_date
15
+ attr_accessor :selected_modes
16
+
17
+ def params
18
+ compact(
19
+ startCityId: start_city_id,
20
+ endCityId: end_city_id,
21
+ startDateSearch: date(start_date_search),
22
+ endDateSearch: date(end_date_search),
23
+ onewayTripDate: date(oneway_trip_date),
24
+ selectedModes: modes(selected_modes),
25
+ )
26
+ end
27
+
28
+ end
29
+
30
+ class Response < BaseResponse
31
+ field :items, [Item], key: 'ITEM'
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,28 @@
1
+ class Gillbus
2
+ module GetOrderStatus
3
+
4
+ Gillbus.register self, :get_order_status
5
+
6
+ class Request < BaseRequest
7
+
8
+ def path; '/online2/getOrderStatus' end
9
+
10
+ # orderNumber
11
+ # Номер заказа или массив заказов, полученных при создании отложенной продажи.
12
+ attr_accessor :order_number
13
+
14
+ def params
15
+ compact(
16
+ orderNumber: order_number.is_a?(Array) ? order_number.join(";") : order_number,
17
+ )
18
+ end
19
+
20
+ end
21
+
22
+ class Response < BaseResponse
23
+ field :tickets, [Ticket], key: 'TICKET'
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,62 @@
1
+ require 'base64'
2
+ class Gillbus
3
+ module GetOrderTicket
4
+
5
+ Gillbus.register self, :get_order_ticket
6
+
7
+ class Request < BaseRequest
8
+
9
+ def path; '/online2/getOrderTicket' end
10
+
11
+ # orderId
12
+ # Уникальный ИД заказа, переданный при отложенной продаже.
13
+ attr_accessor :order_id
14
+
15
+ # removeAd
16
+ # Признак удаления логотипа Gillbus из билета. true – удалить логотип.
17
+ # По умолчанию false.
18
+ attr_accessor :remove_ad
19
+
20
+ # orderNumber
21
+ # Номер заказа полученный при создании отложенной продажи.
22
+ attr_accessor :order_number
23
+
24
+ # base64 (не обязательный)
25
+ # Признак получения билета заказа в виде строки Base64. true – билет заказа будет возвращен как строка Base64. По умолчанию false.
26
+ # Важно: надо передать true, парсер ответа ожидает этого.
27
+ # Иначе можно получить невалидный xml
28
+ attr_accessor :base64
29
+
30
+ # Тип возвращаемого документа. Например, "ticket"
31
+ attr_accessor :as
32
+
33
+ # locale (не обязательный)
34
+ # Язык формирования данных.
35
+ attr_accessor :locale
36
+
37
+ def params
38
+ compact(
39
+ orderId: order_id,
40
+ removeAd: remove_ad,
41
+ orderNumber: order_number,
42
+ base64: base64,
43
+ as: as,
44
+ locale: translated_locale(locale)
45
+ )
46
+ end
47
+ end
48
+
49
+ class Response < BaseResponse
50
+
51
+ field :ticket, :ticket
52
+
53
+ parser do
54
+ def ticket(val)
55
+ Base64.decode64(val)
56
+ end
57
+ end
58
+
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,32 @@
1
+ class Gillbus
2
+ module GetRequiredFields
3
+ Gillbus.register self, :get_required_fields
4
+
5
+ class Request < BaseRequest
6
+ def path; '/online2/getRequiredFields' end
7
+
8
+ attr_accessor :trip_id
9
+
10
+ def params
11
+ compact(
12
+ tripId: trip_id,
13
+ )
14
+ end
15
+ end
16
+
17
+ class Response < BaseResponse
18
+ field :dictionary, :bool_dict
19
+
20
+ parser do
21
+ def bool_dict(val)
22
+ return unless val
23
+ result = {}
24
+ val.each do |k, v|
25
+ result[k.downcase.to_sym] = bool(v)
26
+ end
27
+ result
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,33 @@
1
+ class Gillbus
2
+ module GetTimeTable
3
+
4
+ Gillbus.register self, :get_time_table
5
+
6
+ class Request < BaseRequest
7
+
8
+ def path; '/online2/getTimeTable' end
9
+
10
+ attr_accessor :locale
11
+ attr_accessor :start_city_id
12
+ attr_accessor :end_city_id
13
+ attr_accessor :start_date_search
14
+ attr_accessor :end_date_search
15
+
16
+ def params
17
+ compact(
18
+ locale: translated_locale(locale),
19
+ startCityId: start_city_id,
20
+ endCityId: end_city_id,
21
+ startDateSearch: date(start_date_search),
22
+ endDateSearch: date(end_date_search),
23
+ )
24
+ end
25
+
26
+ end
27
+
28
+ class Response < BaseResponse
29
+ field :trips, [TimetableTrip], key: 'TRIP'
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,61 @@
1
+ class Gillbus
2
+ module GetTripSeats
3
+
4
+ Gillbus.register self, :get_trip_seats
5
+
6
+ class Request < BaseRequest
7
+
8
+ def path; '/online2/getTripSeats' end
9
+
10
+ # tripId
11
+ # ИД рейса, для которого нужно получить карту мест
12
+ attr_accessor :trip_id
13
+
14
+ # carriageId (не обязательный)
15
+ # ИД вагона, для которого нужно получить карту мест. По- умолчанию первый попавшийся. Только для железнодорожных рейсов.
16
+ attr_accessor :carriage_id
17
+
18
+ # backCarriageId (не обязательный)
19
+ # ИД вагона обратного рейса, для которого нужно получить карту мест. По-умолчанию первый попавшийся. Только для железнодорожных рейсов.
20
+ attr_accessor :back_carriage_id
21
+
22
+ # segment0carriageId...segmentNcarriageId (не обязательный)
23
+ # ИД вагона сегмента рейса с порядковым нормеом 0...N, для которого нужно получить карту мест.
24
+ # По-умолчанию первый попавшийся. Только для железнодорожных рейсов.
25
+
26
+ def params
27
+ compact(
28
+ tripId: trip_id,
29
+ carriageId: carriage_id,
30
+ backCarriageId: back_carriage_id
31
+ )
32
+ end
33
+
34
+ end
35
+
36
+ class Response < BaseResponse
37
+
38
+ SEGMENT_REGEX = /SEGMENT_(?<number>\d+)_SEAT/
39
+
40
+ field :seats, [Seat], key: 'SEAT'
41
+
42
+ field :segments, :segments, key: SEGMENT_REGEX
43
+
44
+ parser do
45
+ def segments(val)
46
+ return {} unless val.present?
47
+
48
+ max_segment_number = val.keys.max.match(SEGMENT_REGEX)[:number].to_i
49
+
50
+ [*0..max_segment_number].inject({}) do |hash, segment|
51
+ seats = val["SEGMENT_#{segment}_SEAT"].to_a
52
+ hash[segment] = seats.map { |seat| Seat.parse(seat) }.presence || []
53
+ hash
54
+ end
55
+ end
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,13 @@
1
+ class Gillbus
2
+ module GetTrips
3
+
4
+ Gillbus.register self, :get_trips
5
+
6
+ class Request < BaseRequest
7
+ def path; '/online2/getTrips' end
8
+ end
9
+
10
+ Response = Gillbus::SearchTrips::Response
11
+
12
+ end
13
+ end
@@ -0,0 +1,47 @@
1
+ class Gillbus
2
+ # Gives a bunch of class methods
3
+ # to parse gillbus responses hash and define accessors
4
+ #
5
+ # Warning:
6
+ # resulting definitions won't work properly in subclass
7
+ #
8
+ # Usage:
9
+ # class MyClass
10
+ # extend Gillbus::Fields
11
+ # field :foo, :date
12
+ # end
13
+ #
14
+ # MyClass.parse(hash)
15
+ module Fields
16
+
17
+ def parser_class
18
+ @parser_class || Gillbus::Parser
19
+ end
20
+
21
+ def parse(doc, instance=new)
22
+ parser_class.new(
23
+ doc: doc,
24
+ instance: instance,
25
+ fields: field_definitions
26
+ ).parse
27
+ instance
28
+ end
29
+
30
+ def parser(&definition)
31
+ @parser_class = Class.new(parser_class, &definition)
32
+ end
33
+
34
+ private
35
+
36
+ def field_definitions
37
+ @fields ||= []
38
+ end
39
+
40
+ def field(name, type=:string, key: name.to_s.upcase)
41
+ field_definitions << {name: name, key: key, type: type}
42
+ attr_accessor name
43
+ end
44
+
45
+
46
+ end
47
+ end
@@ -0,0 +1,100 @@
1
+ require 'bigdecimal'
2
+ require 'active_support/time'
3
+
4
+ class Gillbus
5
+ class Parser
6
+
7
+ attr_accessor :doc
8
+ attr_accessor :instance
9
+ attr_accessor :fields
10
+
11
+ def initialize(instance:, doc:, fields:)
12
+ @instance = instance
13
+ @doc = doc
14
+ @fields = fields
15
+ end
16
+
17
+ def parse
18
+ fields.each do |name:, key:, type:|
19
+ raw_value =
20
+ if key.is_a?(Regexp)
21
+ doc.select { |k| k =~ key }
22
+ else
23
+ doc[key]
24
+ end
25
+ value = make_one_or_many(type, raw_value)
26
+ instance.send "#{name}=", value unless value.nil?
27
+ end
28
+ instance
29
+ end
30
+
31
+ private
32
+
33
+ def make_one_or_many(type, val)
34
+ # [:type]
35
+ if type.is_a? Array
36
+ array(val).map {|v| make_one type.first, v }
37
+ # :type
38
+ else
39
+ make_one type, val
40
+ end
41
+ end
42
+
43
+ def make_one(type, val)
44
+ return if val.nil?
45
+ if type.is_a? Class
46
+ type.parse(val)
47
+ else
48
+ send type, val
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ # nil => []
55
+ # [] => []
56
+ # {} => [{}]
57
+ def array(arg)
58
+ return [arg] if arg.is_a? Hash
59
+ Array(arg)
60
+ end
61
+
62
+ def string(val)
63
+ return if val == "null"
64
+ val
65
+ end
66
+
67
+ def bool(val)
68
+ val == "true"
69
+ end
70
+
71
+ def yesno_bool(val)
72
+ val == 'Y'
73
+ end
74
+
75
+ def int(val)
76
+ val.to_i
77
+ end
78
+
79
+ def date(val)
80
+ Date.strptime(val, '%d.%m.%Y')
81
+ end
82
+
83
+ def time(val)
84
+ if val =~ /^ ( \d\d:\d\d ) (?: :\d\d )? $/x
85
+ $1
86
+ else
87
+ nil
88
+ end
89
+ end
90
+
91
+ def datetime(val)
92
+ ActiveSupport::TimeZone["Europe/Kiev"].parse(val)
93
+ end
94
+
95
+ def decimal(val)
96
+ BigDecimal.new(val)
97
+ end
98
+
99
+ end
100
+ end
@@ -0,0 +1,15 @@
1
+ class Gillbus
2
+ module UpdateAttrs
3
+
4
+ def initialize(attrs={})
5
+ update_attrs attrs if attrs
6
+ end
7
+
8
+ def update_attrs(attrs={})
9
+ attrs.each do |k, v|
10
+ public_send "#{k}=", v
11
+ end
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,82 @@
1
+ class Gillbus
2
+ module LockSeats
3
+
4
+ Gillbus.register self, :lock_seats
5
+
6
+ class Request < BaseRequest
7
+
8
+ def path; '/online2/lockSeats' end
9
+
10
+ # tripId
11
+ # ИД рейса, для которого нужно получить карту мест
12
+ attr_accessor :trip_id
13
+
14
+ # carriageId (не обязательный)
15
+ # ИД вагона, для которого нужно получить карту мест. По- умолчанию первый попавшийся. Только для железнодорожных рейсов.
16
+ attr_accessor :carriage_id
17
+
18
+ # backCarriageId (не обязательный)
19
+ # ИД вагона обратного рейса, для которого нужно получить карту мест. По-умолчанию первый попавшийся. Только для железнодорожных рейсов.
20
+ attr_accessor :back_carriage_id
21
+
22
+ # segment0carriageId...segmentNcarriageId (не обязательный)
23
+ # ИД вагона сегмента рейса с порядковым нормеом 0...N, для которого нужно получить карту мест.
24
+ # По-умолчанию первый попавшийся. Только для железнодорожных рейсов.
25
+
26
+ # seatId0...seatIdN (не обязательный)
27
+ # ИД места с порядковым номером 0...N, которое нужно заблокировать.
28
+ attr_accessor :seat_ids
29
+
30
+ # backSeatId0...backSeatIdN (не обязательный)
31
+ # ИД места с порядковым номером 0...N, которое нужно заблокировать на обратный рейс.
32
+ attr_accessor :back_seat_ids
33
+
34
+ # segment0seatId0... segmentMseatIdN (не обязательный)
35
+ # ИД места с порядковым номером 0...N, которое нужно заблокировать на сегмент рейса с порядковым номером 0...M.
36
+ attr_accessor :segments_seat_ids
37
+
38
+ def params
39
+ seats = Array(seat_ids).map.with_index {|id, n| [:"seatId#{n}", id] }.to_h
40
+ back_seats = Array(back_seat_ids).map.with_index {|id, n| [:"backSeatId#{n}", id] }.to_h
41
+ segments_seats = Hash(segments_seat_ids).map do |segment, seat_ids|
42
+ Array(seat_ids).map.with_index {|id, n| [:"segment#{segment}seatId#{n}", id] }.to_h
43
+ end.reduce(&:merge).to_h
44
+
45
+ compact(
46
+ tripId: trip_id,
47
+ carriageId: carriage_id,
48
+ backCarriageId: back_carriage_id,
49
+ **seats,
50
+ **back_seats,
51
+ **segments_seats,
52
+ )
53
+ end
54
+ end
55
+
56
+ class Response < BaseResponse
57
+
58
+ # seat lock, time limit, in seconds
59
+ field :time_limit, :milliseconds
60
+ # [{Symbol => Boolean}] необходимые для ввода типы документов?
61
+ field :dictionary, :bool_dict
62
+
63
+ parser do
64
+ def milliseconds(val)
65
+ return unless val
66
+ val.to_i / 1000
67
+ end
68
+
69
+ def bool_dict(val)
70
+ return unless val
71
+ result = {}
72
+ val.each do |k, v|
73
+ result[k.downcase.to_sym] = bool(v)
74
+ end
75
+ result
76
+ end
77
+ end
78
+
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,19 @@
1
+ class Gillbus
2
+ module Logout
3
+
4
+ Gillbus.register self, :logout
5
+
6
+ class Request < BaseRequest
7
+
8
+ def path; '/online2/logout' end
9
+
10
+ end
11
+
12
+ class Response < BaseResponse
13
+
14
+ field :logout, :bool
15
+
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ # I want it not to be an exception, for now
2
+ class Gillbus::ParseError
3
+ def initialize(response_string)
4
+ @response = response_string
5
+ end
6
+ attr_reader :response
7
+ attr_accessor :session_id
8
+ def error?; true; end
9
+ def error_code; 0; end
10
+ def error_message; "Malformed response"; end
11
+ end
@@ -0,0 +1,13 @@
1
+ class Gillbus
2
+ module ReserveTickets
3
+
4
+ Gillbus.register self, :reserve_tickets
5
+
6
+ class Request < Gillbus::TicketsBooking::Request
7
+ def path; '/online2/reserveTickets' end
8
+ end
9
+
10
+ Response = Gillbus::TicketsBooking::Response
11
+
12
+ end
13
+ end