-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
163 lines (144 loc) · 3.78 KB
/
main.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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
package main
import (
"bytes"
"encoding/csv"
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"strings"
"time"
"github.com/tidwall/gjson"
)
const version = "0.1.0"
var (
dataDir = flag.String("dataDir", ".", "Location of the data directory. It contains CSV files with IMDb IDs and a \"metas\" subdirectory will be used for writing metas as JSON files.")
versionFlag = flag.Bool("version", false, "Prints the version of stremio-metafetcher")
)
func init() {
// Timeout for global default HTTP client (for when using `http.Get()`)
http.DefaultClient.Timeout = 5 * time.Second
}
func main() {
flag.Parse()
if *versionFlag {
fmt.Println("stremio-metafetcher v" + version)
}
// Clean input
if strings.HasSuffix(*dataDir, "/") {
*dataDir = strings.TrimRight(*dataDir, "/")
}
files, err := ioutil.ReadDir(*dataDir)
if err != nil {
log.Fatal("Couldn't read directory:", err)
}
for _, file := range files {
// Skip non-CSV files
if !strings.HasSuffix(file.Name(), ".csv") {
continue
}
records := read(*dataDir + "/" + file.Name())
missingMetas := determineMissingMetas(records, *dataDir+"/metas")
metas := fetchMetas(missingMetas)
writeMetas(metas, *dataDir+"/metas")
}
}
func read(filePath string) [][]string {
fileBytes, err := ioutil.ReadFile(filePath)
if err != nil {
log.Fatal("Couldn't read file:", err)
}
csvReader := csv.NewReader(bytes.NewReader(fileBytes))
records, err := csvReader.ReadAll()
if err != nil {
log.Fatal("Couldn't read CSV:", err)
}
return records
}
func determineMissingMetas(records [][]string, metasDir string) []string {
headRecord := records[0]
imdbIndex := 0
found := false
for ; imdbIndex < len(headRecord); imdbIndex++ {
if headRecord[imdbIndex] == "IMDb ID" {
found = true
break
}
}
if !found {
log.Fatal("Couldn't find \"IMDb ID\" in CSV header:", headRecord)
}
var imdbIDs []string
for _, record := range records[1:] {
imdbIDs = append(imdbIDs, record[imdbIndex])
}
// Now we have *all* IMDb IDs. But we only want to know the missing ones.
fileInfos, err := ioutil.ReadDir(metasDir)
if err != nil {
log.Fatal("Couldn't read metas directory:", err)
}
var fileNames []string
for _, fileInfo := range fileInfos {
fileName := strings.TrimSuffix(fileInfo.Name(), ".json")
fileNames = append(fileNames, fileName)
}
var result []string
for _, imdbID := range imdbIDs {
found = false
for _, fileName := range fileNames {
if fileName == imdbID {
found = true
break
}
}
if !found {
result = append(result, imdbID)
}
}
return result
}
type meta struct {
imdbID string
meta string
}
func fetchMetas(imdbIDs []string) []meta {
var result []meta
for _, imdbID := range imdbIDs {
log.Println("Fetching meta for", imdbID)
// Note: Add "?sda" to invalidate the server's cache
url := "https://v3-cinemeta.strem.io/meta/movie/" + imdbID + ".json"
res, err := http.Get(url)
if err != nil {
log.Printf("Couldn't GET %v: %v", url, err)
continue
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
log.Println("Bad GET response:", res.StatusCode)
continue
}
resBody, err := ioutil.ReadAll(res.Body)
if err != nil {
log.Println("Couldn't read response body:", err)
continue
}
metaJSON := gjson.GetBytes(resBody, "meta").Raw
if metaJSON == "" {
log.Println("Response body is empty or at least doesn't contain a \"meta\" element")
continue
}
result = append(result, meta{imdbID, metaJSON})
// Don't DoS the server
time.Sleep(100 * time.Millisecond)
}
return result
}
func writeMetas(metas []meta, metaDir string) {
for _, meta := range metas {
log.Println("Write meta file for", meta.imdbID)
if err := ioutil.WriteFile(metaDir+"/"+meta.imdbID+".json", []byte(meta.meta), 0600); err != nil {
log.Fatal("Couldn't write file:", err)
}
}
}