searchapi 1.0.0

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 (51) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +175 -0
  3. data/bin/test +14 -0
  4. data/lib/searchapi/error_result.rb +50 -0
  5. data/lib/searchapi/google_finance_options.rb +40 -0
  6. data/lib/searchapi/google_finance_request.rb +26 -0
  7. data/lib/searchapi/google_finance_result.rb +262 -0
  8. data/lib/searchapi/google_flights_options.rb +85 -0
  9. data/lib/searchapi/google_flights_request.rb +25 -0
  10. data/lib/searchapi/google_flights_result.rb +275 -0
  11. data/lib/searchapi/google_images_options.rb +64 -0
  12. data/lib/searchapi/google_images_request.rb +26 -0
  13. data/lib/searchapi/google_images_result.rb +133 -0
  14. data/lib/searchapi/google_light_options.rb +43 -0
  15. data/lib/searchapi/google_light_request.rb +26 -0
  16. data/lib/searchapi/google_light_result.rb +198 -0
  17. data/lib/searchapi/google_local_options.rb +40 -0
  18. data/lib/searchapi/google_local_request.rb +26 -0
  19. data/lib/searchapi/google_local_result.rb +85 -0
  20. data/lib/searchapi/google_news_light_options.rb +47 -0
  21. data/lib/searchapi/google_news_light_request.rb +26 -0
  22. data/lib/searchapi/google_news_light_result.rb +94 -0
  23. data/lib/searchapi/google_news_options.rb +53 -0
  24. data/lib/searchapi/google_news_portal_options.rb +40 -0
  25. data/lib/searchapi/google_news_portal_request.rb +89 -0
  26. data/lib/searchapi/google_news_portal_result.rb +137 -0
  27. data/lib/searchapi/google_news_request.rb +26 -0
  28. data/lib/searchapi/google_news_result.rb +129 -0
  29. data/lib/searchapi/google_scholar_options.rb +48 -0
  30. data/lib/searchapi/google_scholar_request.rb +26 -0
  31. data/lib/searchapi/google_scholar_result.rb +195 -0
  32. data/lib/searchapi/google_search_options.rb +67 -0
  33. data/lib/searchapi/google_search_request.rb +26 -0
  34. data/lib/searchapi/google_search_result.rb +301 -0
  35. data/lib/searchapi/helpers.rb +10 -0
  36. data/lib/searchapi/instagram_profile_options.rb +31 -0
  37. data/lib/searchapi/instagram_profile_request.rb +26 -0
  38. data/lib/searchapi/instagram_profile_result.rb +117 -0
  39. data/lib/searchapi/module_methods.rb +80 -0
  40. data/lib/searchapi/request.rb +25 -0
  41. data/lib/searchapi/response_methods.rb +14 -0
  42. data/lib/searchapi/tiktok_profile_options.rb +31 -0
  43. data/lib/searchapi/tiktok_profile_request.rb +26 -0
  44. data/lib/searchapi/tiktok_profile_result.rb +71 -0
  45. data/lib/searchapi/version.rb +3 -0
  46. data/lib/searchapi/youtube_search_options.rb +62 -0
  47. data/lib/searchapi/youtube_search_request.rb +26 -0
  48. data/lib/searchapi/youtube_search_result.rb +411 -0
  49. data/lib/searchapi.rb +70 -0
  50. data/searchapi.gemspec +37 -0
  51. metadata +164 -0
@@ -0,0 +1,275 @@
1
+ require 'forwardable'
2
+
3
+ module SearchAPI
4
+
5
+ # Google Flights Search metadata
6
+ GoogleFlightsMetadataSchema = DynamicSchema::Struct.define do
7
+ id String
8
+ status String
9
+ created_at String, as: :created_at
10
+ request_time_taken Float, as: :request_time_taken
11
+ parsing_time_taken Float, as: :parsing_time_taken
12
+ total_time_taken Float, as: :total_time_taken
13
+ request_url String, as: :request_url
14
+ html_url String, as: :html_url
15
+ json_url String, as: :json_url
16
+ end
17
+
18
+ class GoogleFlightsMetadata < GoogleFlightsMetadataSchema
19
+ end
20
+
21
+ # Google Flights Search parameters
22
+ GoogleFlightsParametersSchema = DynamicSchema::Struct.define do
23
+ engine String
24
+ departure_id String, as: :departure_id
25
+ arrival_id String, as: :arrival_id
26
+ currency String
27
+ hl String
28
+ gl String
29
+ outbound_date String, as: :outbound_date
30
+ return_date String, as: :return_date
31
+ flight_type String, as: :flight_type
32
+ travel_class String, as: :travel_class
33
+ stops String
34
+ sort_by String, as: :sort_by
35
+ adults Integer
36
+ children Integer
37
+ infants_in_seat Integer, as: :infants_in_seat
38
+ infants_on_lap Integer, as: :infants_on_lap
39
+ end
40
+
41
+ class GoogleFlightsParameters < GoogleFlightsParametersSchema
42
+ end
43
+
44
+ # Airport details
45
+ GoogleFlightsAirportSchema = DynamicSchema::Struct.define do
46
+ name String
47
+ id String
48
+ date String
49
+ time String
50
+ end
51
+
52
+ class GoogleFlightsAirport < GoogleFlightsAirportSchema
53
+ end
54
+
55
+ # Detected extensions (amenities)
56
+ GoogleFlightsExtensionsSchema = DynamicSchema::Struct.define do
57
+ has_power_and_usb_outlets [ TrueClass, FalseClass ], as: :has_power_and_usb_outlets
58
+ has_personal_video_screen [ TrueClass, FalseClass ], as: :has_personal_video_screen
59
+ has_live_tv [ TrueClass, FalseClass ], as: :has_live_tv
60
+ has_on_demand_video [ TrueClass, FalseClass ], as: :has_on_demand_video
61
+ has_stream_video_to_own_device [ TrueClass, FalseClass ], as: :has_stream_video_to_own_device
62
+ wifi String
63
+ seat_type String, as: :seat_type
64
+ legroom_short String, as: :legroom_short
65
+ legroom_long String, as: :legroom_long
66
+ carbon_emission Float, as: :carbon_emission
67
+ end
68
+
69
+ class GoogleFlightsExtensions < GoogleFlightsExtensionsSchema
70
+ end
71
+
72
+ # Flight segment
73
+ GoogleFlightsSegmentSchema = DynamicSchema::Struct.define do
74
+ departure_airport GoogleFlightsAirport, as: :departure_airport
75
+ arrival_airport GoogleFlightsAirport, as: :arrival_airport
76
+ duration Integer
77
+ airplane String
78
+ airline String
79
+ airline_logo String, as: :airline_logo
80
+ travel_class String, as: :travel_class
81
+ flight_number String, as: :flight_number
82
+ ticket_also_sold_by String, array: true, as: :ticket_also_sold_by
83
+ is_overnight [ TrueClass, FalseClass ], as: :is_overnight
84
+ is_often_delayed [ TrueClass, FalseClass ], as: :is_often_delayed
85
+ extensions String, array: true
86
+ detected_extensions GoogleFlightsExtensions, as: :detected_extensions
87
+ end
88
+
89
+ class GoogleFlightsSegment < GoogleFlightsSegmentSchema
90
+ end
91
+
92
+ # Layover
93
+ GoogleFlightsLayoverSchema = DynamicSchema::Struct.define do
94
+ duration Integer
95
+ name String
96
+ id String
97
+ is_overnight [ TrueClass, FalseClass ], as: :is_overnight
98
+ end
99
+
100
+ class GoogleFlightsLayover < GoogleFlightsLayoverSchema
101
+ end
102
+
103
+ # Carbon emissions
104
+ GoogleFlightsCarbonEmissionsSchema = DynamicSchema::Struct.define do
105
+ this_flight Integer, as: :this_flight
106
+ typical_for_this_route Integer, as: :typical_for_this_route
107
+ difference_percent Integer, as: :difference_percent
108
+ lowest_route Integer, as: :lowest_route
109
+ end
110
+
111
+ class GoogleFlightsCarbonEmissions < GoogleFlightsCarbonEmissionsSchema
112
+ end
113
+
114
+ # Flight option
115
+ GoogleFlightsFlightSchema = DynamicSchema::Struct.define do
116
+ flights GoogleFlightsSegment, array: true
117
+ layovers GoogleFlightsLayover, array: true
118
+ total_duration Integer, as: :total_duration
119
+ carbon_emissions GoogleFlightsCarbonEmissions, as: :carbon_emissions
120
+ price Integer
121
+ type String
122
+ extensions String, array: true
123
+ airline_logo String, as: :airline_logo
124
+ booking_token String, as: :booking_token
125
+ departure_token String, as: :departure_token
126
+ end
127
+
128
+ class GoogleFlightsFlight < GoogleFlightsFlightSchema
129
+ end
130
+
131
+ # Price range
132
+ GoogleFlightsPriceRangeSchema = DynamicSchema::Struct.define do
133
+ low_price Integer, as: :low_price
134
+ high_price Integer, as: :high_price
135
+ end
136
+
137
+ class GoogleFlightsPriceRange < GoogleFlightsPriceRangeSchema
138
+ end
139
+
140
+ # Price history point
141
+ GoogleFlightsPriceHistorySchema = DynamicSchema::Struct.define do
142
+ price Integer
143
+ iso_date String, as: :iso_date
144
+ end
145
+
146
+ class GoogleFlightsPriceHistory < GoogleFlightsPriceHistorySchema
147
+ end
148
+
149
+ # Price insights
150
+ GoogleFlightsPriceInsightsSchema = DynamicSchema::Struct.define do
151
+ lowest_price Integer, as: :lowest_price
152
+ price_level String, as: :price_level
153
+ typical_price_range GoogleFlightsPriceRange, as: :typical_price_range
154
+ price_history GoogleFlightsPriceHistory, array: true, as: :price_history
155
+ end
156
+
157
+ class GoogleFlightsPriceInsights < GoogleFlightsPriceInsightsSchema
158
+ end
159
+
160
+ # Airport data
161
+ GoogleFlightsAirportDataInnerSchema = DynamicSchema::Struct.define do
162
+ id String
163
+ name String
164
+ end
165
+
166
+ class GoogleFlightsAirportDataInner < GoogleFlightsAirportDataInnerSchema
167
+ end
168
+
169
+ GoogleFlightsAirportDataSchema = DynamicSchema::Struct.define do
170
+ airport GoogleFlightsAirportDataInner
171
+ city String
172
+ country String
173
+ country_code String, as: :country_code
174
+ image String
175
+ thumbnail String
176
+ end
177
+
178
+ class GoogleFlightsAirportData < GoogleFlightsAirportDataSchema
179
+ end
180
+
181
+ # Airport info
182
+ GoogleFlightsAirportInfoSchema = DynamicSchema::Struct.define do
183
+ departure GoogleFlightsAirportData, array: true
184
+ arrival GoogleFlightsAirportData, array: true
185
+ end
186
+
187
+ class GoogleFlightsAirportInfo < GoogleFlightsAirportInfoSchema
188
+ end
189
+
190
+ # Booking request
191
+ GoogleFlightsBookingRequestSchema = DynamicSchema::Struct.define do
192
+ url String
193
+ post_data String, as: :post_data
194
+ end
195
+
196
+ class GoogleFlightsBookingRequest < GoogleFlightsBookingRequestSchema
197
+ end
198
+
199
+ # Local price
200
+ GoogleFlightsLocalPriceSchema = DynamicSchema::Struct.define do
201
+ currency String
202
+ price Integer
203
+ end
204
+
205
+ class GoogleFlightsLocalPrice < GoogleFlightsLocalPriceSchema
206
+ end
207
+
208
+ # Booking option
209
+ GoogleFlightsBookingOptionSchema = DynamicSchema::Struct.define do
210
+ book_with String, as: :book_with
211
+ airline_logos String, array: true, as: :airline_logos
212
+ flight_numbers String, array: true, as: :flight_numbers
213
+ price Integer
214
+ local_prices GoogleFlightsLocalPrice, array: true, as: :local_prices
215
+ option_title String, as: :option_title
216
+ extensions String, array: true
217
+ baggage_prices String, array: true, as: :baggage_prices
218
+ booking_phone String, as: :booking_phone
219
+ booking_request GoogleFlightsBookingRequest, as: :booking_request
220
+ is_split_booking [ TrueClass, FalseClass ], as: :is_split_booking
221
+ end
222
+
223
+ class GoogleFlightsBookingOption < GoogleFlightsBookingOptionSchema
224
+ end
225
+
226
+ # Selected flight
227
+ GoogleFlightsSelectedFlightSchema = DynamicSchema::Struct.define do
228
+ flights GoogleFlightsSegment, array: true
229
+ layovers GoogleFlightsLayover, array: true
230
+ total_duration Integer, as: :total_duration
231
+ carbon_emissions GoogleFlightsCarbonEmissions, as: :carbon_emissions
232
+ type String
233
+ airline_logo String, as: :airline_logo
234
+ end
235
+
236
+ class GoogleFlightsSelectedFlight < GoogleFlightsSelectedFlightSchema
237
+ end
238
+
239
+ # Main Google Flights result
240
+ GoogleFlightsResultSchema = DynamicSchema::Struct.define do
241
+ search_metadata GoogleFlightsMetadata, as: :search_metadata
242
+ search_parameters GoogleFlightsParameters, as: :search_parameters
243
+ best_flights GoogleFlightsFlight, array: true, as: :best_flights
244
+ other_flights GoogleFlightsFlight, array: true, as: :other_flights
245
+ price_insights GoogleFlightsPriceInsights, as: :price_insights
246
+ airports GoogleFlightsAirportInfo, array: true
247
+ selected_flights GoogleFlightsSelectedFlight, array: true, as: :selected_flights
248
+ booking_options GoogleFlightsBookingOption, array: true, as: :booking_options
249
+ error String
250
+ end
251
+
252
+ class GoogleFlightsResult < GoogleFlightsResultSchema
253
+ extend Forwardable
254
+ include Enumerable
255
+
256
+ def_delegators :best_flights, :each, :[], :count, :size, :length, :first, :last, :empty?
257
+
258
+ def success?
259
+ self.error.nil?
260
+ end
261
+
262
+ def all_flights
263
+ ( best_flights || [] ) + ( other_flights || [] )
264
+ end
265
+
266
+ def cheapest
267
+ all_flights.min_by { | f | f.price || Float::INFINITY }
268
+ end
269
+
270
+ def fastest
271
+ all_flights.min_by { | f | f.total_duration || Float::INFINITY }
272
+ end
273
+ end
274
+
275
+ end
@@ -0,0 +1,64 @@
1
+ module SearchAPI
2
+ class GoogleImagesOptions
3
+ include DynamicSchema::Definable
4
+ include Helpers
5
+
6
+ DEVICES = %w[ desktop mobile tablet ]
7
+ SAFE_SEARCH = %w[ active off ]
8
+ SIZES = %w[ large medium icon larger_than_400x300 larger_than_640x480 larger_than_800x600
9
+ larger_than_1024x768 larger_than_2mp larger_than_4mp larger_than_6mp
10
+ larger_than_8mp larger_than_12mp larger_than_15mp larger_than_20mp
11
+ larger_than_40mp larger_than_70mp ]
12
+ COLORS = %w[ black_and_white color transparent red orange yellow green teal blue
13
+ purple pink white gray black brown ]
14
+ IMAGE_TYPES = %w[ clipart line_drawing gif face photo ]
15
+ TIME_PERIODS = %w[ last_hour last_day last_week last_month last_year ]
16
+ USAGE_RIGHTS = %w[ creative_commons_licenses commercial_or_other_licenses ]
17
+ ASPECT_RATIOS = %w[ square tall wide panoramic ]
18
+
19
+ NORMALIZE_DOWNCASE = ->(v) { v.to_s.downcase }
20
+
21
+ schema do
22
+ q String
23
+ device String, in: DEVICES, normalize: NORMALIZE_DOWNCASE
24
+ location String
25
+ uule String
26
+ google_domain String
27
+ gl String
28
+ hl String
29
+ lr String
30
+ cr String
31
+ nfpr Integer
32
+ filter Integer
33
+ safe String, in: SAFE_SEARCH, normalize: NORMALIZE_DOWNCASE
34
+ tbs String
35
+ size String, in: SIZES, normalize: NORMALIZE_DOWNCASE
36
+ color String, in: COLORS, normalize: NORMALIZE_DOWNCASE
37
+ image_type String, in: IMAGE_TYPES, normalize: NORMALIZE_DOWNCASE
38
+ time_period String, in: TIME_PERIODS, normalize: NORMALIZE_DOWNCASE
39
+ usage_rights String, in: USAGE_RIGHTS, normalize: NORMALIZE_DOWNCASE
40
+ aspect_ratio String, in: ASPECT_RATIOS, normalize: NORMALIZE_DOWNCASE
41
+ page Integer
42
+ end
43
+
44
+ def self.build( options = nil, &block )
45
+ new( api_options: builder.build( options, &block ) )
46
+ end
47
+
48
+ def self.build!( options = nil, &block )
49
+ new( api_options: builder.build!( options, &block ) )
50
+ end
51
+
52
+ def initialize( options = {}, api_options: nil )
53
+ @options = self.class.builder.build( options || {} )
54
+ @options = api_options.merge( @options ) if api_options
55
+ end
56
+
57
+ def to_h
58
+ result = @options.to_h
59
+ result[ :engine ] = 'google_images'
60
+ result
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,26 @@
1
+ module SearchAPI
2
+ class GoogleImagesRequest < Request
3
+
4
+ def search( query, options = nil, &block )
5
+ if options
6
+ options = options.is_a?( GoogleImagesOptions ) ? options : GoogleImagesOptions.build!( options.to_h )
7
+ options = options.to_h
8
+ else
9
+ options = { engine: 'google_images' }
10
+ end
11
+ options[ :q ] = query.to_s
12
+
13
+ response = get( "#{ BASE_URI }/search", options, &block )
14
+ attributes = ( JSON.parse( response.body, symbolize_names: true ) rescue nil )
15
+
16
+ result = if response.success?
17
+ GoogleImagesResult.new( attributes || {} )
18
+ else
19
+ ErrorResult.new( response.status, attributes )
20
+ end
21
+
22
+ ResponseMethods.install( response, result )
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,133 @@
1
+ require 'forwardable'
2
+
3
+ module SearchAPI
4
+
5
+ GoogleImagesMetadataSchema = DynamicSchema::Struct.define do
6
+ id String
7
+ status String
8
+ created_at String, as: :created_at
9
+ request_time_taken Float, as: :request_time_taken
10
+ parsing_time_taken Float, as: :parsing_time_taken
11
+ total_time_taken Float, as: :total_time_taken
12
+ request_url String, as: :request_url
13
+ html_url String, as: :html_url
14
+ json_url String, as: :json_url
15
+ end
16
+
17
+ class GoogleImagesMetadata < GoogleImagesMetadataSchema
18
+ end
19
+
20
+ GoogleImagesParametersSchema = DynamicSchema::Struct.define do
21
+ engine String
22
+ q String
23
+ device String
24
+ uule String
25
+ location String
26
+ location_used String, as: :location_used
27
+ cr String
28
+ google_domain String, as: :google_domain
29
+ hl String
30
+ gl String
31
+ lr String
32
+ nfpr Integer
33
+ filter Integer
34
+ safe String
35
+ page Integer
36
+ tbs String
37
+ chips String
38
+ size String
39
+ color String
40
+ image_type String, as: :image_type
41
+ time_period String, as: :time_period
42
+ usage_rights String, as: :usage_rights
43
+ aspect_ratio String, as: :aspect_ratio
44
+ next_page_token String, as: :next_page_token
45
+ end
46
+
47
+ class GoogleImagesParameters < GoogleImagesParametersSchema
48
+ end
49
+
50
+ GoogleImagesSearchInformationSchema = DynamicSchema::Struct.define do
51
+ query_displayed String, as: :query_displayed
52
+ total_results Integer, as: :total_results
53
+ page Integer
54
+ time_taken_displayed Float, as: :time_taken_displayed
55
+ detected_location String, as: :detected_location
56
+ did_you_mean String, as: :did_you_mean
57
+ has_no_results_for [ TrueClass, FalseClass ], as: :has_no_results_for
58
+ showing_results_for String, as: :showing_results_for
59
+ end
60
+
61
+ class GoogleImagesSearchInformation < GoogleImagesSearchInformationSchema
62
+ end
63
+
64
+ GoogleImagesSuggestionSchema = DynamicSchema::Struct.define do
65
+ title String
66
+ link String
67
+ thumbnail String
68
+ end
69
+
70
+ class GoogleImagesSuggestion < GoogleImagesSuggestionSchema
71
+ end
72
+
73
+ GoogleImagesSourceSchema = DynamicSchema::Struct.define do
74
+ name String
75
+ link String
76
+ end
77
+
78
+ class GoogleImagesSource < GoogleImagesSourceSchema
79
+ end
80
+
81
+ GoogleImagesOriginalSchema = DynamicSchema::Struct.define do
82
+ link String
83
+ width Integer
84
+ height Integer
85
+ end
86
+
87
+ class GoogleImagesOriginal < GoogleImagesOriginalSchema
88
+ end
89
+
90
+ GoogleImageSchema = DynamicSchema::Struct.define do
91
+ position Integer
92
+ title String
93
+ source GoogleImagesSource
94
+ original GoogleImagesOriginal
95
+ thumbnail String
96
+ tag String
97
+ end
98
+
99
+ class GoogleImage < GoogleImageSchema
100
+ end
101
+
102
+ GoogleImagesRelatedSearchSchema = DynamicSchema::Struct.define do
103
+ link String
104
+ query String
105
+ highlighted String, array: true
106
+ thumbnail String
107
+ end
108
+
109
+ class GoogleImagesRelatedSearch < GoogleImagesRelatedSearchSchema
110
+ end
111
+
112
+ GoogleImagesResultSchema = DynamicSchema::Struct.define do
113
+ search_metadata GoogleImagesMetadata, as: :search_metadata
114
+ search_parameters GoogleImagesParameters, as: :search_parameters
115
+ search_information GoogleImagesSearchInformation, as: :search_information
116
+ suggestions GoogleImagesSuggestion, array: true
117
+ images GoogleImage, array: true
118
+ related_searches GoogleImagesRelatedSearch, array: true, as: :related_searches
119
+ error String
120
+ end
121
+
122
+ class GoogleImagesResult < GoogleImagesResultSchema
123
+ extend Forwardable
124
+ include Enumerable
125
+
126
+ def_delegators :images, :each, :[], :count, :size, :length, :first, :last, :empty?
127
+
128
+ def success?
129
+ self.error.nil?
130
+ end
131
+ end
132
+
133
+ end
@@ -0,0 +1,43 @@
1
+ module SearchAPI
2
+ class GoogleLightOptions
3
+ include DynamicSchema::Definable
4
+ include Helpers
5
+
6
+ SAFE_SEARCH = %w[ active off ]
7
+ NORMALIZE_DOWNCASE = ->(v) { v.to_s.downcase }
8
+
9
+ schema do
10
+ q String
11
+ location String
12
+ uule String
13
+ google_domain String
14
+ hl String
15
+ gl String
16
+ lr String
17
+ nfpr String
18
+ filter String
19
+ safe String, in: SAFE_SEARCH, normalize: NORMALIZE_DOWNCASE
20
+ page Integer
21
+ end
22
+
23
+ def self.build( options = nil, &block )
24
+ new( api_options: builder.build( options, &block ) )
25
+ end
26
+
27
+ def self.build!( options = nil, &block )
28
+ new( api_options: builder.build!( options, &block ) )
29
+ end
30
+
31
+ def initialize( options = {}, api_options: nil )
32
+ @options = self.class.builder.build( options || {} )
33
+ @options = api_options.merge( @options ) if api_options
34
+ end
35
+
36
+ def to_h
37
+ result = @options.to_h
38
+ result[ :engine ] = 'google_light'
39
+ result
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,26 @@
1
+ module SearchAPI
2
+ class GoogleLightRequest < Request
3
+
4
+ def search( query, options = nil, &block )
5
+ if options
6
+ options = options.is_a?( GoogleLightOptions ) ? options : GoogleLightOptions.build!( options.to_h )
7
+ options = options.to_h
8
+ else
9
+ options = { engine: 'google_light' }
10
+ end
11
+ options[ :q ] = query.to_s
12
+
13
+ response = get( "#{ BASE_URI }/search", options, &block )
14
+ attributes = ( JSON.parse( response.body, symbolize_names: true ) rescue nil )
15
+
16
+ result = if response.success?
17
+ GoogleLightResult.new( attributes || {} )
18
+ else
19
+ ErrorResult.new( response.status, attributes )
20
+ end
21
+
22
+ ResponseMethods.install( response, result )
23
+ end
24
+
25
+ end
26
+ end