/ gmaps / gmaps.go
gmaps.go
 1  // SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
 2  //
 3  // SPDX-License-Identifier: AGPL-3.0-or-later
 4  
 5  package gmaps
 6  
 7  import (
 8  	"encoding/json"
 9  	"fmt"
10  	"io"
11  	"net/http"
12  	"strings"
13  )
14  
15  type GMapsResp struct {
16  	Places []Place `json:"places"`
17  }
18  
19  type Place struct {
20  	FormattedAddress string      `json:"formattedAddress"`
21  	PlusCode         PlusCode    `json:"plusCode"`
22  	DisplayName      DisplayName `json:"displayName"`
23  	Location         Location    `json:"location"`
24  }
25  
26  type PlusCode struct {
27  	GlobalCode   string `json:"globalCode"`
28  	CompoundCode string `json:"compoundCode"`
29  }
30  
31  type Location struct {
32  	Latitude  float64 `json:"latitude"`
33  	Longitude float64 `json:"longitude"`
34  }
35  
36  type DisplayName struct {
37  	Text         string `json:"text"`
38  	LanguageCode string `json:"languageCode"`
39  }
40  
41  // Search queries the Google Maps API using the Text Search (New) endpoint
42  func Search(query, gMapsKey string) ([]Place, error) {
43  	reqBody := map[string]string{
44  		"textQuery":    query,
45  		"languageCode": "en",
46  	}
47  
48  	jsonBody, err := json.Marshal(reqBody)
49  	if err != nil {
50  		return nil, fmt.Errorf("failed to marshal request body: %w", err)
51  	}
52  
53  	client := http.Client{}
54  	req, err := http.NewRequest("POST", "https://places.googleapis.com/v1/places:searchText", strings.NewReader(string(jsonBody)))
55  	if err != nil {
56  		return nil, fmt.Errorf("failed to create HTTP request: %w", err)
57  	}
58  
59  	req.Header = http.Header{}
60  	req.Header.Add("Content-Type", "application/json")
61  	req.Header.Add("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:131.0) Gecko/20100101 Firefox/131.0")
62  	req.Header.Add("X-Goog-Api-Key", gMapsKey)
63  	req.Header.Add("X-Goog-FieldMask", "places.formattedAddress,places.displayName,places.plusCode,places.location")
64  
65  	res, err := client.Do(req)
66  	if err != nil {
67  		return nil, fmt.Errorf("failed to execute HTTP request: %w", err)
68  	}
69  
70  	body, err := io.ReadAll(res.Body)
71  	if err != nil {
72  		return nil, fmt.Errorf("failed to read response body: %w", err)
73  	}
74  	if err := res.Body.Close(); err != nil {
75  		return nil, fmt.Errorf("failed to close response body: %w", err)
76  	}
77  
78  	var gMapsResp GMapsResp
79  	err = json.Unmarshal(body, &gMapsResp)
80  	if err != nil {
81  		return nil, fmt.Errorf("failed to unmarshal response body: %w", err)
82  	}
83  
84  	return gMapsResp.Places, nil
85  }