157 lines
4.8 KiB
C#
157 lines
4.8 KiB
C#
![]() |
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Linq;
|
|||
|
using System.Net.Http;
|
|||
|
using System.Text.Json;
|
|||
|
using System.Text.Json.Serialization;
|
|||
|
using System.Threading.Tasks;
|
|||
|
using Microsoft.Extensions.Configuration;
|
|||
|
using RestaurantAPI.Models;
|
|||
|
|
|||
|
public class GooglePlacesService
|
|||
|
{
|
|||
|
private readonly HttpClient _httpClient;
|
|||
|
private readonly string _apiKey;
|
|||
|
|
|||
|
public GooglePlacesService(HttpClient httpClient, IConfiguration configuration)
|
|||
|
{
|
|||
|
_httpClient = httpClient;
|
|||
|
_apiKey = configuration["GooglePlaces:ApiKey"];
|
|||
|
}
|
|||
|
|
|||
|
public async Task<List<Restaurant>> GetRestaurantsAsync(
|
|||
|
double latitude,
|
|||
|
double longitude,
|
|||
|
int radius = 5000,
|
|||
|
int? minPrice = null,
|
|||
|
int? maxPrice = null)
|
|||
|
{
|
|||
|
// Build the Nearby Search URL
|
|||
|
string url = $"https://maps.googleapis.com/maps/api/place/nearbysearch/json" +
|
|||
|
$"?location={latitude},{longitude}" +
|
|||
|
$"&radius={radius}" +
|
|||
|
$"&type=restaurant" +
|
|||
|
$"&key={_apiKey}";
|
|||
|
|
|||
|
// Append optional minPrice/maxPrice
|
|||
|
if (minPrice.HasValue) url += $"&minprice={minPrice.Value}";
|
|||
|
if (maxPrice.HasValue) url += $"&maxprice={maxPrice.Value}";
|
|||
|
|
|||
|
// Call Google Places Nearby Search
|
|||
|
HttpResponseMessage response = await _httpClient.GetAsync(url);
|
|||
|
string json = await response.Content.ReadAsStringAsync();
|
|||
|
|
|||
|
Console.WriteLine("Google API Response: " + json);
|
|||
|
|
|||
|
// Return empty list if the request failed
|
|||
|
if (!response.IsSuccessStatusCode)
|
|||
|
{
|
|||
|
Console.WriteLine("Error: " + response.StatusCode);
|
|||
|
return new List<Restaurant>();
|
|||
|
}
|
|||
|
|
|||
|
// Deserialize the JSON into our GooglePlacesResponse model
|
|||
|
var data = JsonSerializer.Deserialize<GooglePlacesResponse>(
|
|||
|
json,
|
|||
|
new JsonSerializerOptions { PropertyNameCaseInsensitive = true }
|
|||
|
);
|
|||
|
|
|||
|
var restaurants = new List<Restaurant>();
|
|||
|
|
|||
|
if (data?.Results != null)
|
|||
|
{
|
|||
|
foreach (var place in data.Results)
|
|||
|
{
|
|||
|
// Skip places missing a name or location
|
|||
|
if (string.IsNullOrEmpty(place.Name) || place.Geometry?.Location == null)
|
|||
|
{
|
|||
|
Console.WriteLine($"Skipping a place due to missing name or location. Name: {place.Name}");
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// Use Google's Place ID for unique identification
|
|||
|
string placeId = place.PlaceId ?? Guid.NewGuid().ToString();
|
|||
|
|
|||
|
// Extract the first photo reference if available
|
|||
|
string firstPhotoReference = place.Photos?.FirstOrDefault()?.PhotoReference;
|
|||
|
|
|||
|
// Generate the Google Maps URL
|
|||
|
string googleMapsUrl = $"https://www.google.com/maps/place/?q=place_id:{placeId}";
|
|||
|
|
|||
|
|
|||
|
// Create a Restaurant object with all necessary data
|
|||
|
restaurants.Add(new Restaurant
|
|||
|
{
|
|||
|
Id = placeId,
|
|||
|
PlaceId = placeId,
|
|||
|
Name = place.Name,
|
|||
|
Type = place.PriceLevel switch
|
|||
|
{
|
|||
|
1 => "Fast Food",
|
|||
|
2 => "Casual Dining",
|
|||
|
3 => "Fine Dining",
|
|||
|
4 => "Luxury Dining",
|
|||
|
_ => "Unknown"
|
|||
|
},
|
|||
|
Latitude = place.Geometry.Location.Lat,
|
|||
|
Longitude = place.Geometry.Location.Lng,
|
|||
|
Rating = place.Rating,
|
|||
|
PriceLevel = place.PriceLevel,
|
|||
|
PhotoReference = firstPhotoReference,
|
|||
|
GoogleMapsUrl = googleMapsUrl
|
|||
|
});
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return restaurants;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// -------------------- Google Places Response Models --------------------
|
|||
|
|
|||
|
public class GooglePlacesResponse
|
|||
|
{
|
|||
|
[JsonPropertyName("results")]
|
|||
|
public List<GooglePlace> Results { get; set; }
|
|||
|
}
|
|||
|
|
|||
|
public class GooglePlace
|
|||
|
{
|
|||
|
[JsonPropertyName("place_id")]
|
|||
|
public string PlaceId { get; set; }
|
|||
|
|
|||
|
[JsonPropertyName("name")]
|
|||
|
public string Name { get; set; }
|
|||
|
|
|||
|
public GoogleGeometry Geometry { get; set; }
|
|||
|
|
|||
|
[JsonPropertyName("rating")]
|
|||
|
public double Rating { get; set; }
|
|||
|
|
|||
|
[JsonPropertyName("price_level")]
|
|||
|
public int? PriceLevel { get; set; }
|
|||
|
|
|||
|
[JsonPropertyName("photos")]
|
|||
|
public List<GooglePhoto> Photos { get; set; }
|
|||
|
}
|
|||
|
|
|||
|
public class GoogleGeometry
|
|||
|
{
|
|||
|
public GoogleLocation Location { get; set; }
|
|||
|
}
|
|||
|
|
|||
|
public class GoogleLocation
|
|||
|
{
|
|||
|
[JsonPropertyName("lat")]
|
|||
|
public double Lat { get; set; }
|
|||
|
|
|||
|
[JsonPropertyName("lng")]
|
|||
|
public double Lng { get; set; }
|
|||
|
}
|
|||
|
|
|||
|
public class GooglePhoto
|
|||
|
{
|
|||
|
[JsonPropertyName("photo_reference")]
|
|||
|
public string PhotoReference { get; set; }
|
|||
|
}
|