-
Notifications
You must be signed in to change notification settings - Fork 0
fix: migrate Foursquare API to new Places API endpoints (#1474) #40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -32,29 +32,41 @@ exports.getApi = (req, res) => { | |||||||||
| */ | ||||||||||
| exports.getFoursquare = async (req, res, next) => { | ||||||||||
| try { | ||||||||||
| const headers = { | ||||||||||
| Authorization: `${process.env.FOURSQUARE_APIKEY}`, | ||||||||||
| const options = { | ||||||||||
| method: 'GET', | ||||||||||
| headers: { | ||||||||||
| accept: 'application/json', | ||||||||||
| 'X-Places-Api-Version': '2025-06-17', | ||||||||||
| authorization: `Bearer ${process.env.FOURSQUARE_APIKEY}`, | ||||||||||
|
Comment on lines
+39
to
+40
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Foursquare Places API (v3) uses the
Suggested change
|
||||||||||
| }, | ||||||||||
| }; | ||||||||||
|
|
||||||||||
| const fetchJson = async (url, fetchOptions, label) => { | ||||||||||
| const res = await fetch(url, fetchOptions); | ||||||||||
| if (!res.ok) { | ||||||||||
| const text = await res.text().catch(() => '<unable to read body>'); | ||||||||||
| throw new Error(`${label} failed: ${res.status} ${res.statusText} - ${text}`); | ||||||||||
| } | ||||||||||
| return res.json(); | ||||||||||
| }; | ||||||||||
|
|
||||||||||
| const [trendingVenuesRes, venueDetailRes, venuePhotosRes] = await Promise.all([ | ||||||||||
| fetch('https://api.foursquare.com/v3/places/search?ll=47.609657,-122.342148&limit=10', { | ||||||||||
| headers, | ||||||||||
| }).then((res) => res.json()), | ||||||||||
| fetch('https://api.foursquare.com/v3/places/427ea800f964a520b1211fe3', { | ||||||||||
| headers, | ||||||||||
| }).then((res) => res.json()), | ||||||||||
| fetch('https://api.foursquare.com/v3/places/427ea800f964a520b1211fe3/photos', { | ||||||||||
| headers, | ||||||||||
| }).then((res) => res.json()), | ||||||||||
| const [trendingVenuesRes, venueDetailRes] = await Promise.all([ | ||||||||||
| fetchJson('https://places-api.foursquare.com/places/search?ll=47.609657,-122.342148&limit=10', options, 'Foursquare search'), | ||||||||||
| fetchJson('https://places-api.foursquare.com/places/427ea800f964a520b1211fe3', options, 'Foursquare venue detail'), | ||||||||||
|
Comment on lines
+54
to
+55
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The standard Foursquare Places API v3 endpoints use the
Suggested change
|
||||||||||
| ]); | ||||||||||
| res.render('api/foursquare', { | ||||||||||
| title: 'Foursquare API (v3)', | ||||||||||
| trendingVenues: trendingVenuesRes.results, | ||||||||||
| title: 'Foursquare Places API', | ||||||||||
| trendingVenues: trendingVenuesRes.results || [], | ||||||||||
| venueDetail: venueDetailRes, | ||||||||||
| venuePhotos: venuePhotosRes.slice(0, 9), // Limit the photos to 9 | ||||||||||
| }); | ||||||||||
| } catch (error) { | ||||||||||
| next(error); | ||||||||||
| console.error('Foursquare API Error:', error); | ||||||||||
| return res.status(500).render('api/foursquare', { | ||||||||||
| title: 'Foursquare Places API', | ||||||||||
| trendingVenues: [], | ||||||||||
| venueDetail: null, | ||||||||||
| error: 'Failed to fetch Foursquare data', | ||||||||||
| }); | ||||||||||
| } | ||||||||||
| }; | ||||||||||
|
|
||||||||||
|
|
||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,56 +7,48 @@ block content | |
| | Foursquare API | ||
|
|
||
| .btn-group.mb-4.d-flex(role='group') | ||
| a.btn.btn-primary.w-100(href='https://location.foursquare.com/developer', target='_blank') | ||
| a.btn.btn-primary.w-100(href='https://foursquare.com/developer', target='_blank') | ||
| i.far.fa-check-square.fa-sm.me-2 | ||
| | Developer Info | ||
| a.btn.btn-primary.w-100(href='https://docs.foursquare.com/', target='_blank') | ||
| i.fas.fa-code-branch.fa-sm.me-2 | ||
| | API Docs | ||
| h3.text-primary Trending Venues | ||
| p Near longitude: -122.342148, latitude: 47.609657 | ||
| table.table.table-striped.table-bordered | ||
| thead | ||
| tr | ||
| th.d-xs | ||
| th Name | ||
| th.d-xs.d-sm Category | ||
| th.d-xs Address | ||
| th.d-xs Distance (meters) | ||
| th.d-xs Open Now ? | ||
| tbody | ||
| each venue in trendingVenues | ||
| if error | ||
| .alert.alert-danger.mt-3 #{ error } | ||
| else | ||
| h3.text-primary Trending Venues | ||
| p Near longitude: -122.342148, latitude: 47.609657 | ||
| table.table.table-striped.table-bordered | ||
| thead | ||
| tr | ||
| td.d-xs | ||
| if venue.categories && venue.categories.length > 0 | ||
| img(src=venue.categories[0].icon.prefix + '32' + venue.categories[0].icon.suffix, alt=venue.categories[0].name, width='32', height='32') | ||
| else | ||
| | N/A | ||
| td= venue.name | ||
| td.d-xs.d-sm= venue.categories && venue.categories.length > 0 ? venue.categories[0].name : 'N/A' | ||
| td.d-xs= venue.location.formatted_address || 'N/A' | ||
| td.d-xs= venue.distance | ||
| td.d-xs= venue.closed_bucket || 'Unknown' | ||
| br | ||
| h3.text-primary Venue Details | ||
| p | ||
| i | ||
| u #{ venueDetail.name } | ||
| if venueDetail.categories && venueDetail.categories.length > 0 | ||
| th.d-xs | ||
| th Name | ||
| th.d-xs.d-sm Category | ||
| th.d-xs Address | ||
| th.d-xs Distance (meters) | ||
| tbody | ||
| each venue in trendingVenues | ||
| tr | ||
| td.d-xs | ||
| if venue.categories && venue.categories.length > 0 | ||
| img(src=venue.categories[0].icon.prefix + '32' + venue.categories[0].icon.suffix, alt=venue.categories[0].name, width='32', height='32') | ||
| else | ||
| | N/A | ||
| td= venue.name | ||
| td.d-xs.d-sm= venue.categories && venue.categories.length > 0 ? venue.categories[0].name : 'N/A' | ||
| td.d-xs= venue.location.formatted_address || 'N/A' | ||
| td.d-xs= venue.distance | ||
| br | ||
| h3.text-primary Venue Details | ||
| p | ||
| i | ||
| u #{ venueDetail.name } | ||
| if venueDetail.categories && venueDetail.categories.length > 0 | ||
| | | ||
| | is a #{ venueDetail.categories[0].name } | ||
| | | ||
| | is a #{ venueDetail.categories[0].name } | ||
| | | ||
| | located at #{ venueDetail.location.address || 'N/A' }, #{ venueDetail.location.locality || 'N/A' }, #{ venueDetail.location.region || 'N/A' }. (longitude: #{ venueDetail.geocodes.main.longitude }, latitude: #{ venueDetail.geocodes.main.latitude }) | ||
| if venueDetail.related_places | ||
| if venueDetail.related_places.children && venueDetail.related_places.children.length > 0 | ||
| p Related venues or businesses to #{ venueDetail.name }, which are mostly in the same building or the immediate area are: | ||
| p(style='margin-left: 20px; white-space: pre-wrap') #{ venueDetail.related_places.children.map(place => place.name).join(', ') } | ||
| if venuePhotos && venuePhotos.length > 0 | ||
| h4.text-secondary Photo Gallery | ||
| | #{ venueDetail.name } | ||
| .row | ||
| each photo in venuePhotos | ||
| .col-md-4 | ||
| img.img-thumbnail(src=photo.prefix + '400x400' + photo.suffix, alt=venueDetail.name, width='100%') | ||
| else | ||
| p No photos available. | ||
| | located at #{ venueDetail.location.address || 'N/A' }, #{ venueDetail.location.locality || 'N/A' }, #{ venueDetail.location.region || 'N/A' }. (longitude: #{ venueDetail.longitude }, latitude: #{ venueDetail.latitude }) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Foursquare Places API response structure nests geographic coordinates under |
||
| if venueDetail.related_places | ||
| if venueDetail.related_places.children && venueDetail.related_places.children.length > 0 | ||
| p Related venues or businesses to #{ venueDetail.name }, which are mostly in the same building or the immediate area are: | ||
| p(style='margin-left: 20px; white-space: pre-wrap') #{ venueDetail.related_places.children.map(place => place.name).join(', ') } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the next should be removed