/
imdb.go
115 lines (106 loc) · 2.4 KB
/
imdb.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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package main
import (
"bytes"
"encoding/json"
"golang.org/x/text/transform"
"golang.org/x/text/unicode/norm"
"io/ioutil"
"log"
"net/http"
"net/url"
"regexp"
"strconv"
"strings"
"unicode"
)
const apiPreamble = "https://sg.media-imdb.com/suggests/"
const (
titleKey = "l"
idKey = "id"
starsKey = "s"
yearKey = "y"
coverKey = "i"
)
func isMn(r rune) bool {
return unicode.Is(unicode.Mn, r)
}
func ascii(s string) string {
t := transform.Chain(norm.NFD, transform.RemoveFunc(isMn), norm.NFC)
r, _, _ := transform.String(t, s)
return r
}
// convert converts a JSON-P string into an Entry.
func convert(cnt string) *Entry {
i := strings.Index(cnt, "(")
cnt = cnt[i+1 : len(cnt)-1]
var query map[string]interface{}
err := json.Unmarshal([]byte(cnt), &query)
if err != nil {
log.Printf("Error: %v", err)
return nil
}
if query == nil || query["d"] == nil {
return nil
}
log.Printf("Fetching JSON...\n%v", query)
entries := query["d"].([]interface{})
for i := range entries {
e := entries[i].(map[string]interface{})
title := e[titleKey].(string)
log.Printf("Title: %s", title)
if _, exists := e[yearKey]; !exists {
continue
}
year := int(e[yearKey].(float64))
log.Printf("Year: %d", year)
if e[coverKey] == nil {
continue
}
cover := e[coverKey].([]interface{})[0].(string)
log.Printf("Cover URL: %s", cover)
id := e[idKey].(string)
log.Printf("IMDb ID: %s", id)
return &Entry{title, year, cover, id, []string{}}
}
return nil
}
// Retrieve returns an Entry from IMDb's Search Suggestions API.
func Retrieve(query string) *Entry {
q := ascii(query)
if q == "" {
return nil
}
url := apiPreamble + strings.ToLower(string(q[0])) + "/" + url.PathEscape(query+".json")
r, err := http.Get(url)
if err != nil {
log.Printf("Error: %v", err)
return nil
}
defer r.Body.Close()
cnt, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Printf("Error: %v", err)
return nil
}
return convert(string(cnt))
}
func Rating(url string) float64 {
log.Printf("Fetching rating...")
r, err := http.Get(url)
if err != nil {
log.Printf("Error: %v", err)
return -1
}
defer r.Body.Close()
R := regexp.MustCompile(`"ratingValue": "(\d\.\d+)"`)
b := new(bytes.Buffer)
b.ReadFrom(r.Body)
M := R.FindStringSubmatch(b.String())
rv, err := strconv.ParseFloat(M[1], 64)
if err != nil {
log.Printf("Error: %v", err)
return -1
}
log.Printf("Rating: %.1f/10.0", rv)
return rv
}