-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgoogle_sheet_google_places.js
More file actions
144 lines (124 loc) · 5.25 KB
/
google_sheet_google_places.js
File metadata and controls
144 lines (124 loc) · 5.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/**
* Your Google Maps API Key. Renamed for uniqueness.
* IMPORTANT: For better security, consider using PropertiesService
* instead of hardcoding your key directly in the script.
* See: https://developers.google.com/apps-script/guides/properties
*/
const GMAPS_PLACES_API_KEY = 'PLACES-API-KEY';
/**
* A specific cache for Google Maps Places results. Renamed for uniqueness.
*/
const gmapsPlacesCache = CacheService.getScriptCache();
/**
* Fetches place details from Google Maps API with caching.
* This is the core function to get data.
*
* @param {string} placeName The name or description of the place.
* @param {string} field The specific field(s) to fetch (e.g., 'website', 'photos', 'formatted_phone_number').
* @return {any} The requested place detail(s) or an error message.
*/
function GMAPS_getPlaceData(placeName, field) {
if (!placeName) {
return 'Please provide a place name.';
}
const locationBias = "São Paulo, Brasil";
const input = `${placeName}, ${locationBias}`;
// Use a cache key based on input and field
const gmapsCacheKey = 'gmaps_' + input + '_' + field;
const cached = gmapsPlacesCache.get(gmapsCacheKey);
if (cached != null) {
// If cached, we need to parse it back to an object if it was one
try {
return JSON.parse(cached);
} catch(e) {
return cached; // Return as is if not JSON (e.g., simple strings)
}
}
try {
// --- Step 1: Find Place ID (Cache this separately) ---
const placeIdCacheKey = 'gmaps_placeid_' + input;
let placeId = gmapsPlacesCache.get(placeIdCacheKey);
if (placeId == null) {
const findPlaceUrl = `https://maps.googleapis.com/maps/api/place/findplacefromtext/json?input=${encodeURIComponent(input)}&inputtype=textquery&fields=place_id&key=${GMAPS_PLACES_API_KEY}`;
const findPlaceResponse = UrlFetchApp.fetch(findPlaceUrl, { 'muteHttpExceptions': true });
const findPlaceJson = JSON.parse(findPlaceResponse.getContentText());
if (findPlaceJson.status !== 'OK' || !findPlaceJson.candidates || findPlaceJson.candidates.length === 0) {
Logger.log(`GMaps Find Place Error for "${input}": ${findPlaceJson.status} - ${findPlaceJson.error_message || 'No candidates found.'}`);
return `Error: Could not find place - ${findPlaceJson.status}`;
}
placeId = findPlaceJson.candidates[0].place_id;
gmapsPlacesCache.put(placeIdCacheKey, placeId, 21600); // Cache Place ID for 6 hours
}
// --- Step 2: Get Place Details ---
const detailsUrl = `https://maps.googleapis.com/maps/api/place/details/json?place_id=${placeId}&fields=${field}&key=${GMAPS_PLACES_API_KEY}`;
const detailsResponse = UrlFetchApp.fetch(detailsUrl, { 'muteHttpExceptions': true });
const detailsJson = JSON.parse(detailsResponse.getContentText());
if (detailsJson.status !== 'OK') {
Logger.log(`GMaps Details Error for Place ID "${placeId}": ${detailsJson.status} - ${detailsJson.error_message || 'Details fetch failed.'}`);
return `Error: Could not get details - ${detailsJson.status}`;
}
const result = detailsJson.result[field];
if (result === undefined) {
return 'Not found';
}
// Cache the result. Store objects as JSON strings.
const valueToCache = (typeof result === 'object') ? JSON.stringify(result) : result;
gmapsPlacesCache.put(gmapsCacheKey, valueToCache, 21600); // Cache for 6 hours
return result;
} catch (e) {
Logger.log(`GMaps Exception for "${input}": ${e}`);
return `Error: ${e.message}`;
}
}
/**
* Gets the website for a given place.
*
* @param {string} placeName The name of the place.
* @return {string} The website URL or an error message.
* @customfunction
*/
function GMAPS_getWebsite(placeName) {
return GMAPS_getPlaceData(placeName, 'website');
}
/**
* Gets the phone number for a given place.
*
* @param {string} placeName The name of the place.
* @return {string} The phone number or an error message.
* @customfunction
*/
function GMAPS_getPhone(placeName) {
return GMAPS_getPlaceData(placeName, 'formatted_phone_number');
}
/**
* Gets the address for a given place.
*
* @param {string} placeName The name of the place.
* @return {string} The address or an error message.
* @customfunction
*/
function GMAPS_getAddress(placeName) {
return GMAPS_getPlaceData(placeName, 'formatted_address');
}
/**
* Gets the URL for the main image of a given place.
*
* @param {string} placeName The name of the place.
* @param {number} [maxWidth=400] Optional. The maximum width of the image.
* @return {string} The image URL or an error message/Not found.
* @customfunction
*/
function GMAPS_getImage(placeName, maxWidth) {
const photosData = GMAPS_getPlaceData(placeName, 'photos');
const width = maxWidth || 400; // Default to 400 if not provided
if (typeof photosData === 'string' && photosData.startsWith('Error:')) {
return photosData; // Return error messages
}
if (Array.isArray(photosData) && photosData.length > 0 && photosData[0].photo_reference) {
const photoReference = photosData[0].photo_reference;
const imageUrl = `https://maps.googleapis.com/maps/api/place/photo?maxwidth=${width}&photoreference=${photoReference}&key=${GMAPS_PLACES_API_KEY}`;
return imageUrl;
} else {
return 'No image found';
}
}