-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathgooglemaps.go
90 lines (86 loc) · 2.67 KB
/
googlemaps.go
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
package unfurlist
import (
"context"
"net/http"
"net/url"
"regexp"
"strings"
)
// GoogleMapsFetcher returns FetchFunc that recognizes some Google Maps urls and
// constructs metadata for them containing preview image from Google Static Maps
// API. The only argument is the API key to create image links with.
func GoogleMapsFetcher(key string) FetchFunc {
if key == "" {
return func(context.Context, *http.Client, *url.URL) (*Metadata, bool) { return nil, false }
}
return func(_ context.Context, _ *http.Client, u *url.URL) (*Metadata, bool) {
if u == nil {
return nil, false
}
if idx := strings.LastIndexByte(u.Host, '.'); idx == -1 ||
!(strings.HasSuffix(u.Host[:idx], ".google") &&
strings.HasPrefix(u.Path, "/maps")) {
return nil, false
}
if u.Path == "/maps/api/staticmap" {
return &Metadata{Image: u.String(), Type: "image"}, true
}
g := &url.URL{
Scheme: "https",
Host: "maps.googleapis.com",
Path: "/maps/api/staticmap",
}
vals := make(url.Values)
vals.Set("key", key)
vals.Set("zoom", "16")
vals.Set("size", "640x480")
vals.Set("scale", "2")
if q := u.Query().Get("q"); u.Path == "/maps" && q != "" {
if zoom := u.Query().Get("z"); zoom != "" {
vals.Set("zoom", zoom)
}
vals.Set("markers", "color:red|"+q)
g.RawQuery = vals.Encode()
return &Metadata{
Type: "website",
Image: g.String(),
ImageWidth: 640 * 2,
ImageHeight: 480 * 2,
}, true
}
name, coords, zoom, ok := coordsFromPath(u.Path)
if !ok {
return &Metadata{Title: "Google Maps", Type: "website"}, true
}
vals.Set("zoom", zoom)
vals.Set("markers", "color:red|"+coords)
g.RawQuery = vals.Encode()
return &Metadata{
Title: name,
Type: "website",
Image: g.String(),
ImageWidth: 640 * 2,
ImageHeight: 480 * 2,
}, true
}
}
var googlePlace = regexp.MustCompile(`^/maps/place/(?P<name>[^/]+)/@(?P<coords>[0-9.-]+,[0-9.-]+),(?P<zoom>[0-9.]+)z`)
// coordsFromPath extracts name, coordinates and zoom level from urls of the
// following format:
// https://www.google.com/maps/place/Passeig+de+Gràcia,+Barcelona,+Spain/@41.3931702,2.1617715,17z
func coordsFromPath(p string) (name, coords, zoom string, ok bool) {
ix := googlePlace.FindStringSubmatchIndex(p)
// 4*2 is len(googlePlace.SubexpNames())*2
if ix == nil || len(ix) != 4*2 {
return "", "", "", false
}
name = p[ix[1*2]:ix[1*2+1]]
coords = p[ix[2*2]:ix[2*2+1]]
zoom = p[ix[3*2]:ix[3*2+1]]
// normally p is already unescaped URL.Path, but it still has spaces
// presented as +, this unescapes them
if name, err := url.QueryUnescape(name); err == nil {
return name, coords, zoom, true
}
return name, coords, zoom, true
}