-
Notifications
You must be signed in to change notification settings - Fork 0
/
finder.go
76 lines (61 loc) · 1.55 KB
/
finder.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
package macfinder
import (
"encoding/json"
"github.com/PuerkitoBio/goquery"
"github.com/pkg/errors"
"net/http"
"strings"
)
const (
apiEndpoint = "https://www.apple.com/fr/shop/refurbished/mac/macbook-pro"
scriptPrefix = "window.REFURB_GRID_BOOTSTRAP = "
scriptSuffix = ";"
)
var (
ErrInvalidRawData = errors.New("invalid data found in the script tag")
)
type response struct {
Tiles []struct {
Filters struct {
Dimensions Specs `json:"dimensions"`
} `json:"filters"`
ProductDetailsUrl string `json:"productDetailsUrl"`
} `json:"tiles"`
}
func FetchAvailable() ([]*Model, error) {
resp, err := http.Get(apiEndpoint)
if err != nil {
return nil, err
}
doc, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
return nil, err
}
scriptRawText := strings.TrimSpace(doc.Find("div[role=main] script").Text())
if !strings.HasPrefix(scriptRawText, scriptPrefix) || !strings.HasSuffix(scriptRawText, scriptSuffix) {
return nil, ErrInvalidRawData
}
jsonData := scriptRawText[len(scriptPrefix) : len(scriptRawText)-len(scriptSuffix)]
var data response
err = json.Unmarshal([]byte(jsonData), &data)
if err != nil {
return nil, err
}
available := make([]*Model, len(data.Tiles))
for i, t := range data.Tiles {
available[i] = &Model{t.Filters.Dimensions, t.ProductDetailsUrl}
}
return available, nil
}
func FindModel(specs Specs) (*Model, error) {
available, err := FetchAvailable()
if err != nil {
return nil, err
}
for _, m := range available {
if m.Specs.match(specs) {
return m, nil
}
}
return nil, nil
}