forked from paymydrink/go-yelp-fusion
174 lines
4.3 KiB
Go
174 lines
4.3 KiB
Go
package yelp
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http"
|
|
"net/url"
|
|
)
|
|
|
|
const (
|
|
rootURI = "https://api.yelp.com/"
|
|
businessArea = "/v3/businesses"
|
|
searchArea = "/v3/businesses/search"
|
|
)
|
|
|
|
var (
|
|
errUnspecifiedLocation = errors.New("location must be specified")
|
|
errBusinessNotFound = errors.New("business not found")
|
|
)
|
|
|
|
// AuthOptions provide keys required for using the Yelp API. Find more
|
|
// information here: https://www.yelp.com/developers/documentation/v3/authentication
|
|
type AuthOptions struct {
|
|
APIKey string // API Key from the yelp API access site.
|
|
}
|
|
|
|
// Client manages all searches. All searches are performed from an instance of a client.
|
|
// It is the top level object used to perform a search or business query. C
|
|
type Client struct {
|
|
Options *AuthOptions
|
|
Client *http.Client
|
|
}
|
|
|
|
// DoSimpleSearch performs a simple search with a term and location.
|
|
func (client *Client) DoSimpleSearch(term, location string) (result SearchResult, err error) {
|
|
|
|
// verify the term and location are not empty
|
|
if location == "" {
|
|
return SearchResult{}, errUnspecifiedLocation
|
|
}
|
|
|
|
// set up the query options
|
|
params := map[string]string{
|
|
"term": term,
|
|
"location": location,
|
|
}
|
|
|
|
// perform the search request
|
|
_, err = client.makeRequest(searchArea, "", params, &result)
|
|
if err != nil {
|
|
return SearchResult{}, err
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
// DoSearch performs a complex search with full search options.
|
|
func (client *Client) DoSearch(options SearchOptions) (result SearchResult, err error) {
|
|
|
|
// get the options from the search provider
|
|
params, err := options.getParameters()
|
|
if err != nil {
|
|
return SearchResult{}, err
|
|
}
|
|
|
|
// perform the search request
|
|
_, err = client.makeRequest(searchArea, "", params, &result)
|
|
if err != nil {
|
|
return SearchResult{}, err
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
// GetBusiness obtains a single business by name.
|
|
func (client *Client) GetBusiness(name string) (result Business, err error) {
|
|
statusCode, err := client.makeRequest(businessArea, name, nil, &result)
|
|
if err != nil {
|
|
// At some point the Yelp API stopped reporting 404s for missing business names, and
|
|
// started reporting 400s :(
|
|
if statusCode == 400 || statusCode == 404 {
|
|
return Business{}, errBusinessNotFound
|
|
}
|
|
return Business{}, err
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
// makeRequest is an internal/private API used to make underlying requests to the Yelp API.
|
|
func (client *Client) makeRequest(area string, id string, params map[string]string, v interface{}) (statusCode int, err error) {
|
|
// get the base url
|
|
queryURI, err := url.Parse(rootURI)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
// add the type of request we're making (search|business)
|
|
queryURI.Path = area
|
|
|
|
if id != "" {
|
|
queryURI.Path += "/" + id
|
|
}
|
|
|
|
// Do request
|
|
request, err := http.NewRequest("GET", queryURI.String(), nil)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
request.Header.Add("Authorization", "Bearer "+client.Options.APIKey)
|
|
q := request.URL.Query()
|
|
if params["term"] != "" {
|
|
q.Add("term", params["term"])
|
|
}
|
|
if params["location"] != "" {
|
|
q.Add("location", params["location"])
|
|
}
|
|
if params["limit"] != "" {
|
|
q.Add("limit", params["limit"])
|
|
}
|
|
if params["offset"] != "" {
|
|
q.Add("offset", params["offset"])
|
|
}
|
|
if params["sortby"] != "" {
|
|
q.Add("sort_by", params["sortby"])
|
|
}
|
|
if params["categoryfilter"] != "" {
|
|
q.Add("category_filter", params["categoryfilter"])
|
|
}
|
|
if params["locale"] != "" {
|
|
q.Add("locale", params["locale"])
|
|
}
|
|
if params["longitude"] != "" {
|
|
q.Add("longitude", params["longitude"])
|
|
}
|
|
if params["latitude"] != "" {
|
|
q.Add("latitude", params["latitude"])
|
|
}
|
|
request.URL.RawQuery = q.Encode()
|
|
|
|
response, err := client.Client.Do(request)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
if err != nil {
|
|
if response != nil {
|
|
return response.StatusCode, err
|
|
}
|
|
return 500, err
|
|
}
|
|
|
|
// close the request when done
|
|
defer response.Body.Close()
|
|
|
|
// ensure the request returned a 200
|
|
if response.StatusCode != 200 {
|
|
return response.StatusCode, errors.New(response.Status)
|
|
}
|
|
err = json.NewDecoder(response.Body).Decode(v)
|
|
|
|
return response.StatusCode, err
|
|
}
|
|
|
|
// New will create a new yelp search client. All search operations should go through this API.
|
|
func New(options *AuthOptions, httpClient *http.Client) *Client {
|
|
if httpClient == nil {
|
|
httpClient = http.DefaultClient
|
|
}
|
|
|
|
return &Client{
|
|
Options: options,
|
|
Client: httpClient,
|
|
}
|
|
}
|