1- from autohive_integrations_sdk import Integration , ExecutionContext , ActionHandler
1+ from autohive_integrations_sdk import Integration , ExecutionContext , ActionHandler , ActionResult , ActionError
22from typing import Dict , Any
33
44# Create the integration using the config.json
@@ -29,7 +29,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
2929 response = await context .fetch ("https://serpapi.com/search" , method = "GET" , params = params )
3030
3131 # Extract apps from organic results
32- organic_results = response .get ("organic_results" , [])
32+ organic_results = response .data . get ("organic_results" , [])
3333 limit = inputs .get ("num" , 10 )
3434 apps = []
3535
@@ -48,7 +48,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
4848 }
4949 apps .append (app )
5050
51- return {"apps" : apps , "total_results" : len (apps )}
51+ return ActionResult ( data = {"apps" : apps , "total_results" : len (apps )}, cost_usd = 0.0 )
5252
5353
5454@app_business_reviews .action ("get_reviews_app_store" )
@@ -61,7 +61,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
6161 app_name = inputs .get ("app_name" )
6262
6363 if not product_id and not app_name :
64- raise ValueError ( "Either product_id or app_name must be provided" )
64+ return ActionError ( message = "Either product_id or app_name must be provided" )
6565
6666 # If app_name is provided but no product_id, search for the app first
6767 if app_name and not product_id :
@@ -73,16 +73,16 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
7373
7474 search_response = await context .fetch ("https://serpapi.com/search" , method = "GET" , params = search_params )
7575
76- organic_results = search_response .get ("organic_results" , [])
76+ organic_results = search_response .data . get ("organic_results" , [])
7777 if not organic_results :
78- raise ValueError ( f"No apps found for search term: { app_name } " )
78+ return ActionError ( message = f"No apps found for search term: { app_name } " )
7979
8080 # Get the first result's product ID
8181 first_result = organic_results [0 ]
8282 product_id = str (first_result .get ("id" ))
8383
8484 if not product_id :
85- raise ValueError ( f"Could not extract product ID for app: { app_name } " )
85+ return ActionError ( message = f"Could not extract product ID for app: { app_name } " )
8686
8787 # Build SerpApi request parameters for reviews
8888 params = {"api_key" : api_key , "engine" : "apple_reviews" , "product_id" : product_id }
@@ -110,7 +110,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
110110 response = await context .fetch ("https://serpapi.com/search" , method = "GET" , params = params )
111111
112112 # Extract reviews data from current page
113- page_reviews = response .get ("reviews" , [])
113+ page_reviews = response .data . get ("reviews" , [])
114114 if not page_reviews :
115115 break
116116
@@ -139,16 +139,19 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
139139 current_page += 1
140140
141141 # Check if there are more pages using pagination info
142- pagination_info = response .get ("serpapi_pagination" , {})
142+ pagination_info = response .data . get ("serpapi_pagination" , {})
143143 if not pagination_info .get ("next" ):
144144 break
145145
146- return {
147- "reviews" : all_reviews ,
148- "total_reviews" : len (all_reviews ),
149- "app_name" : app_title ,
150- "product_id" : product_id ,
151- }
146+ return ActionResult (
147+ data = {
148+ "reviews" : all_reviews ,
149+ "total_reviews" : len (all_reviews ),
150+ "app_name" : app_title ,
151+ "product_id" : product_id ,
152+ },
153+ cost_usd = 0.0 ,
154+ )
152155
153156
154157# ---- Google Play Store Actions ----
@@ -166,7 +169,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
166169 response = await context .fetch ("https://serpapi.com/search" , method = "GET" , params = params )
167170
168171 # Extract apps from organic results
169- organic_results = response .get ("organic_results" , [])
172+ organic_results = response .data . get ("organic_results" , [])
170173 limit = inputs .get ("limit" , 10 )
171174 apps = []
172175
@@ -189,7 +192,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
189192 if len (apps ) >= limit :
190193 break
191194
192- return {"apps" : apps , "total_results" : len (apps )}
195+ return ActionResult ( data = {"apps" : apps , "total_results" : len (apps )}, cost_usd = 0.0 )
193196
194197
195198@app_business_reviews .action ("get_reviews_google_play" )
@@ -202,17 +205,17 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
202205 app_name = inputs .get ("app_name" )
203206
204207 if not product_id and not app_name :
205- raise ValueError ( "Either product_id or app_name must be provided" )
208+ return ActionError ( message = "Either product_id or app_name must be provided" )
206209
207210 # If app_name is provided but no product_id, search for the app first
208211 if app_name and not product_id :
209212 search_params = {"api_key" : api_key , "engine" : "google_play" , "store" : "apps" , "q" : app_name }
210213
211214 search_response = await context .fetch ("https://serpapi.com/search" , method = "GET" , params = search_params )
212215
213- organic_results = search_response .get ("organic_results" , [])
216+ organic_results = search_response .data . get ("organic_results" , [])
214217 if not organic_results :
215- raise ValueError ( f"No apps found for search term: { app_name } " )
218+ return ActionError ( message = f"No apps found for search term: { app_name } " )
216219
217220 # Get the first result's product ID from nested items structure
218221 product_id = None
@@ -224,7 +227,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
224227 break
225228
226229 if not product_id :
227- raise ValueError ( f"Could not extract product ID for app: { app_name } " )
230+ return ActionError ( message = f"Could not extract product ID for app: { app_name } " )
228231
229232 # Build SerpApi request parameters
230233 params = {
@@ -251,6 +254,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
251254 all_reviews = []
252255 next_page_token = None
253256 pages_fetched = 0
257+ response = None
254258
255259 # Fetch reviews with pagination
256260 while pages_fetched < max_pages :
@@ -265,7 +269,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
265269 response = await context .fetch ("https://serpapi.com/search" , method = "GET" , params = params )
266270
267271 # Extract reviews data from current page
268- page_reviews = response .get ("reviews" , [])
272+ page_reviews = response .data . get ("reviews" , [])
269273 if not page_reviews :
270274 break
271275
@@ -285,21 +289,24 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
285289 pages_fetched += 1
286290
287291 # Check if there's a next page
288- pagination_info = response .get ("serpapi_pagination" , {})
292+ pagination_info = response .data . get ("serpapi_pagination" , {})
289293 next_page_token = pagination_info .get ("next_page_token" )
290294 if not next_page_token :
291295 break
292296
293297 # Extract app information from the response
294- app_info = response .get ("product_info" , {})
298+ app_info = response .data . get ("product_info" , {}) if response is not None else {}
295299
296- return {
297- "reviews" : all_reviews ,
298- "total_reviews" : len (all_reviews ),
299- "app_name" : app_info .get ("title" , "" ),
300- "app_rating" : app_info .get ("rating" ) or 0.0 ,
301- "product_id" : product_id ,
302- }
300+ return ActionResult (
301+ data = {
302+ "reviews" : all_reviews ,
303+ "total_reviews" : len (all_reviews ),
304+ "app_name" : app_info .get ("title" , "" ),
305+ "app_rating" : app_info .get ("rating" ) or 0.0 ,
306+ "product_id" : product_id ,
307+ },
308+ cost_usd = 0.0 ,
309+ )
303310
304311
305312# ---- Google Maps Actions ----
@@ -323,7 +330,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
323330 response = await context .fetch ("https://serpapi.com/search" , method = "GET" , params = params )
324331
325332 # Extract places from local results
326- local_results = response .get ("local_results" , [])
333+ local_results = response .data . get ("local_results" , [])
327334 limit = inputs .get ("num_results" , 5 )
328335 places = []
329336
@@ -340,7 +347,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
340347 }
341348 places .append (place )
342349
343- return {"places" : places , "total_results" : len (places )}
350+ return ActionResult ( data = {"places" : places , "total_results" : len (places )}, cost_usd = 0.0 )
344351
345352
346353@app_business_reviews .action ("get_reviews_google_maps" )
@@ -355,7 +362,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
355362 local_results = [] # Initialize to store search results
356363
357364 if not place_id and not data_id and not query :
358- raise ValueError ( "Either place_id, data_id, or query (business name) must be provided" )
365+ return ActionError ( message = "Either place_id, data_id, or query (business name) must be provided" )
359366
360367 # If query is provided but no place_id/data_id, search for the place first
361368 if query and not place_id and not data_id :
@@ -369,25 +376,27 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
369376 # Search for the place to get place_id and data_id
370377 search_response = await context .fetch ("https://serpapi.com/search" , method = "GET" , params = search_params )
371378
372- local_results = search_response .get ("local_results" , [])
379+ local_results = search_response .data . get ("local_results" , [])
373380 if not local_results :
374381 # Provide helpful error message
375382 suggestion = (
376383 f"No businesses found for search query: '{ search_query } '. Use place_id instead. "
377384 "Visit: https://developers.google.com/maps/documentation/places/web-service/"
378385 "place-id to find Place ID manually."
379386 )
380- raise ValueError ( suggestion )
387+ return ActionError ( message = suggestion )
381388
382389 # Get the first result's place_id and data_id
383390 first_result = local_results [0 ]
384391 place_id = first_result .get ("place_id" )
385392 data_id = first_result .get ("data_id" )
386393
387394 if not place_id and not data_id :
388- raise ValueError (
389- f"Could not extract place_id or data_id for business: { search_query } . "
390- "The search returned results but they don't contain required identifiers."
395+ return ActionError (
396+ message = (
397+ f"Could not extract place_id or data_id for business: { search_query } . "
398+ "The search returned results but they don't contain required identifiers."
399+ )
391400 )
392401
393402 # Build SerpApi request parameters for reviews
@@ -399,7 +408,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
399408 elif data_id :
400409 params ["data_id" ] = data_id
401410 else :
402- raise ValueError ( "Could not resolve place_id or data_id from the provided query" )
411+ return ActionError ( message = "Could not resolve place_id or data_id from the provided query" )
403412
404413 # Add sort parameter if provided
405414 if inputs .get ("sort_by" ):
@@ -411,6 +420,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
411420 all_reviews = []
412421 next_page_token = None
413422 pages_fetched = 0
423+ response = None
414424
415425 # Fetch reviews with pagination
416426 while pages_fetched < max_pages :
@@ -426,7 +436,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
426436 response = await context .fetch ("https://serpapi.com/search" , method = "GET" , params = params )
427437
428438 # Extract reviews data from current page
429- page_reviews = response .get ("reviews" , [])
439+ page_reviews = response .data . get ("reviews" , [])
430440 if not page_reviews :
431441 break
432442
@@ -444,12 +454,12 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
444454 pages_fetched += 1
445455
446456 # Check if there's a next page
447- next_page_token = response .get ("serpapi_pagination" , {}).get ("next_page_token" )
457+ next_page_token = response .data . get ("serpapi_pagination" , {}).get ("next_page_token" )
448458 if not next_page_token :
449459 break
450460
451461 # Extract business information from the last response
452- place_info = response .get ("place_info" , {})
462+ place_info = response .data . get ("place_info" , {}) if response is not None else {}
453463
454464 # Use business name from search result if we searched, otherwise from place_info
455465 business_name = place_info .get ("title" , "" )
@@ -458,10 +468,13 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext):
458468 if local_results :
459469 business_name = local_results [0 ].get ("title" , business_name )
460470
461- return {
462- "reviews" : all_reviews ,
463- "total_reviews" : len (all_reviews ),
464- "average_rating" : place_info .get ("rating" ) or 0.0 ,
465- "business_name" : business_name ,
466- "place_id" : place_id or place_info .get ("place_id" , inputs .get ("place_id" , "" )),
467- }
471+ return ActionResult (
472+ data = {
473+ "reviews" : all_reviews ,
474+ "total_reviews" : len (all_reviews ),
475+ "average_rating" : place_info .get ("rating" ) or 0.0 ,
476+ "business_name" : business_name ,
477+ "place_id" : place_id or place_info .get ("place_id" , inputs .get ("place_id" , "" )),
478+ },
479+ cost_usd = 0.0 ,
480+ )
0 commit comments