aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/series/series.go11
-rw-r--r--modules/tags/tag.go8
-rw-r--r--tools/animeimporter/ACDv2Reader.go59
-rw-r--r--tools/animeimporter/main.go202
4 files changed, 280 insertions, 0 deletions
diff --git a/modules/series/series.go b/modules/series/series.go
new file mode 100644
index 0000000..1f50903
--- /dev/null
+++ b/modules/series/series.go
@@ -0,0 +1,11 @@
1package series
2
3type Series struct {
4 ID int
5 Name string
6 KanjiName string
7 RomajiName string
8 FuriganaName string
9 OtherNames []string
10 Tags []string
11}
diff --git a/modules/tags/tag.go b/modules/tags/tag.go
new file mode 100644
index 0000000..026df0f
--- /dev/null
+++ b/modules/tags/tag.go
@@ -0,0 +1,8 @@
1package tags
2
3type TagType int
4
5const (
6 TagTypeGril TagType = iota
7 TagTypeSeries
8)
diff --git a/tools/animeimporter/ACDv2Reader.go b/tools/animeimporter/ACDv2Reader.go
new file mode 100644
index 0000000..36564e4
--- /dev/null
+++ b/tools/animeimporter/ACDv2Reader.go
@@ -0,0 +1,59 @@
1package main
2
3import (
4 "encoding/json"
5 "io/ioutil"
6 "path/filepath"
7 "strconv"
8 "strings"
9
10 "fagott.pw/grilist/modules/grils"
11)
12
13func ifErrExit(err error) {
14 if err != nil {
15 panic(err)
16 }
17}
18
19func toInt(s string) int {
20 i, err := strconv.ParseInt(s, 10, 32)
21 ifErrExit(err)
22 return int(i)
23}
24
25type ACDv2Reader struct{}
26
27type ACDv2Series struct {
28 Name struct {
29 English string `json:"english"`
30 Romaji string `json:"romaji"`
31 Japanese string `json:"japanese"`
32 Furigana string `json:"furigana"`
33 Aliases []string `json:"aliases"`
34 } `json:"name"`
35 Tags []string `json:"tags"`
36 Image string `json:"image"`
37}
38
39func (r *ACDv2Reader) Read(path string) WrappedSeries {
40 s := WrappedSeries{}
41 data, err := ioutil.ReadFile(path)
42 ifErrExit(err)
43 var jObj ACDv2Series
44 err = json.Unmarshal(data, &jObj)
45 ifErrExit(err)
46 s.Image = jObj.Image
47 s.Series.ID = toInt(strings.TrimSuffix(filepath.Base(path), ".json"))
48 s.Series.Name = jObj.Name.English
49 s.Series.KanjiName = jObj.Name.Japanese
50 s.Series.RomajiName = jObj.Name.Romaji
51 s.Series.FuriganaName = jObj.Name.Furigana
52 s.Series.OtherNames = jObj.Name.Aliases
53 s.Series.Tags = jObj.Tags
54 return s
55}
56
57func (r *ACDv2Reader) ID() int {
58 return int(grils.DataSourceACD)
59}
diff --git a/tools/animeimporter/main.go b/tools/animeimporter/main.go
new file mode 100644
index 0000000..7d95b8e
--- /dev/null
+++ b/tools/animeimporter/main.go
@@ -0,0 +1,202 @@
1package main
2
3import (
4 "database/sql"
5 "flag"
6 "fmt"
7 "os"
8 "path/filepath"
9
10 "fagott.pw/grilist/grilist"
11 "fagott.pw/grilist/modules/series"
12 "fagott.pw/grilist/modules/tags"
13)
14
15var path string
16var sourceType string
17var imgUrlExportFile string
18var exportFile *os.File
19var db *sql.DB
20var r SeriesReader
21
22type WrappedSeries struct {
23 Series series.Series
24 Image string
25}
26
27type SeriesReader interface {
28 Read(path string) WrappedSeries
29 ID() int
30}
31
32func GetSeriesReader(rType string) SeriesReader {
33 switch rType {
34 case "ACDv2":
35 return &ACDv2Reader{}
36 }
37 return nil
38}
39
40func LogErr(err error) {
41 if err != nil {
42 fmt.Fprintf(os.Stderr, "%s\n", err)
43 }
44}
45
46func TryGetExistingSeries(s WrappedSeries, idmap map[int]int) int {
47 dbID, _ := idmap[s.Series.ID]
48 return dbID
49}
50
51func InsertSeries(s WrappedSeries) int {
52 var dbID int
53 row := db.QueryRow("INSERT INTO grilist.appearances (id) VALUES (DEFAULT) RETURNING id;")
54 row.Scan(&dbID)
55 fmt.Printf(
56 "Assigned %d from %s to %d\n",
57 s.Series.ID,
58 sourceType,
59 dbID)
60 _, err := db.Exec("INSERT INTO grilist.appearances_id_mappings (appearance_id, source, source_id) VALUES ($1, $2, $3);",
61 dbID, r.ID(), s.Series.ID)
62 LogErr(err)
63 if s.Series.Name != "" {
64 _, err := db.Exec("INSERT INTO grilist.appearance_names (appearance_id, name, name_type) VALUES ($1, $2, $3);",
65 dbID, s.Series.Name, 4)
66 LogErr(err)
67 }
68 if s.Series.KanjiName != "" {
69 _, err := db.Exec("INSERT INTO grilist.appearance_names (appearance_id, name, name_type) VALUES ($1, $2, $3);",
70 dbID, s.Series.Name, 0)
71 LogErr(err)
72 }
73 if s.Series.RomajiName != "" {
74 _, err := db.Exec("INSERT INTO grilist.appearance_names (appearance_id, name, name_type) VALUES ($1, $2, $3);",
75 dbID, s.Series.Name, 1)
76 LogErr(err)
77 }
78 if s.Series.FuriganaName != "" {
79 _, err := db.Exec("INSERT INTO grilist.appearance_names (appearance_id, name, name_type) VALUES ($1, $2, $3);",
80 dbID, s.Series.Name, 3)
81 LogErr(err)
82 }
83 for _, v := range s.Series.OtherNames {
84 _, err := db.Exec("INSERT INTO grilist.appearance_names (appearance_id, name, name_type) VALUES ($1, $2, $3);",
85 dbID, v, 2)
86 LogErr(err)
87 }
88 if exportFile != nil {
89 if s.Image != "" {
90 fmt.Fprintf(
91 exportFile,
92 "%d %s\n",
93 dbID,
94 s.Image)
95 }
96 }
97 return dbID
98}
99
100func InsertTags(dbID int, s WrappedSeries, taglist map[string]int) {
101 for _, v := range s.Series.Tags {
102 if _, ok := taglist[v]; ok {
103 continue
104 }
105 var id int
106 row := db.QueryRow("INSERT INTO grilist.tags (name, type) VALUES ($1, $2) RETURNING id;",
107 v, tags.TagTypeSeries)
108 row.Scan(&id)
109 taglist[v] = id
110 fmt.Printf("Inserted tag %s as %d\n", v, id)
111 }
112 rows, err := db.Query("SELECT tag_id FROM appearances_tags WHERE appearance_id = $1;", dbID)
113 LogErr(err)
114 existingTags := make(map[int]bool, 0)
115 for rows.Next() {
116 var tagID int
117 rows.Scan(&tagID)
118 existingTags[tagID] = true
119 }
120 for _, v := range s.Series.Tags {
121 tagID := taglist[v]
122 if _, ok := existingTags[tagID]; ok {
123 continue
124 }
125 _, err := db.Exec("INSERT INTO grilist.appearances_tags (appearance_id, tag_id) VALUES ($1, $2);",
126 dbID, tagID)
127 existingTags[tagID] = true
128 fmt.Printf("Assigned tag %s to %s\n", v, s.Series.Name)
129 LogErr(err)
130 }
131}
132
133func main() {
134 flag.StringVar(&path, "path", "", "path of the source files")
135 flag.StringVar(&sourceType, "type", "", "type of the files (ACDv2)")
136 flag.StringVar(&imgUrlExportFile, "imageexportfile", "", "image URLs will be exported to this file, THIS WILL OVERWRITE EVERYTHING IN THE FILE!")
137 flag.Parse()
138 if imgUrlExportFile != "" {
139 var err error
140 if exportFile, err = os.Create(imgUrlExportFile); err != nil {
141 fmt.Fprintf(os.Stderr, "%s\n", "error while accessing \"%s\"")
142 fmt.Fprintf(os.Stderr, "%v\n", err)
143 os.Exit(1)
144 }
145 }
146 if path == "" {
147 fmt.Fprintf(os.Stderr, "%s\n", "\"path\" must be specified!")
148 flag.Usage()
149 os.Exit(1)
150 }
151 r = GetSeriesReader(sourceType)
152 if r == nil {
153 fmt.Fprintf(os.Stderr, "%s\n", "\"type\" must be specified and a valid series source!")
154 flag.Usage()
155 os.Exit(1)
156 }
157 config := grilist.LoadConfig()
158 var err error
159 db, err = sql.Open("postgres", config.DBConnectionString())
160 if err == nil {
161 err = db.Ping()
162 }
163 if err != nil {
164 fmt.Fprintf(os.Stderr, "%s\n", "error with database connection")
165 fmt.Fprintf(os.Stderr, "%v\n", err)
166 os.Exit(1)
167 }
168
169 taglist := make(map[string]int)
170 rows, err := db.Query("SELECT id, name FROM grilist.tags WHERE type = $1;", tags.TagTypeSeries)
171 LogErr(err)
172 for rows.Next() {
173 var id int
174 var name string
175 rows.Scan(&id, &name)
176 taglist[name] = id
177 }
178 idmap := make(map[int]int)
179 rows, err = db.Query("SELECT source_id, appearance_id FROM grilist.appearances_id_mappings WHERE source = $1;", r.ID())
180 LogErr(err)
181 for rows.Next() {
182 var sourceID int
183 var appearanceID int
184 rows.Scan(&sourceID, &appearanceID)
185 idmap[sourceID] = appearanceID
186 }
187
188 filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
189 if info.IsDir() {
190 return nil
191 }
192 s := r.Read(path)
193
194 var dbID int
195 if dbID = TryGetExistingSeries(s, idmap); dbID == 0 {
196 dbID = InsertSeries(s)
197 }
198 InsertTags(dbID, s, taglist)
199
200 return nil
201 })
202}