package main import ( "database/sql" "flag" "fmt" "os" "path/filepath" "fagott.pw/grilist/grilist" "fagott.pw/grilist/models" ) var path string var sourceType string var imgUrlExportFile string var exportFile *os.File var db *sql.DB var r SeriesReader type WrappedSeries struct { Series models.Series Image string } type SeriesReader interface { Read(path string) WrappedSeries ID() int } func GetSeriesReader(rType string) SeriesReader { switch rType { case "ACDv2": return &ACDv2Reader{} } return nil } func LogErr(err error) { if err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) } } func TryGetExistingSeries(s WrappedSeries, idmap map[int]int) int { dbID, _ := idmap[s.Series.ID] return dbID } func InsertSeries(s WrappedSeries) int { var dbID int row := db.QueryRow("INSERT INTO grilist.appearances (id) VALUES (DEFAULT) RETURNING id;") row.Scan(&dbID) fmt.Printf( "Assigned %d from %s to %d\n", s.Series.ID, sourceType, dbID) _, err := db.Exec("INSERT INTO grilist.appearances_id_mappings (appearance_id, source, source_id) VALUES ($1, $2, $3);", dbID, r.ID(), s.Series.ID) LogErr(err) if s.Series.Name != "" { _, err := db.Exec("INSERT INTO grilist.appearance_names (appearance_id, name, name_type) VALUES ($1, $2, $3);", dbID, s.Series.Name, 4) LogErr(err) } if s.Series.KanjiName != "" { _, err := db.Exec("INSERT INTO grilist.appearance_names (appearance_id, name, name_type) VALUES ($1, $2, $3);", dbID, s.Series.KanjiName, 0) LogErr(err) } if s.Series.RomajiName != "" { _, err := db.Exec("INSERT INTO grilist.appearance_names (appearance_id, name, name_type) VALUES ($1, $2, $3);", dbID, s.Series.RomajiName, 1) LogErr(err) } if s.Series.FuriganaName != "" { _, err := db.Exec("INSERT INTO grilist.appearance_names (appearance_id, name, name_type) VALUES ($1, $2, $3);", dbID, s.Series.FuriganaName, 3) LogErr(err) } for _, v := range s.Series.OtherNames { _, err := db.Exec("INSERT INTO grilist.appearance_names (appearance_id, name, name_type) VALUES ($1, $2, $3);", dbID, v, 2) LogErr(err) } if exportFile != nil { if s.Image != "" { fmt.Fprintf( exportFile, "%d %s\n", dbID, s.Image) } } return dbID } func InsertTags(dbID int, s WrappedSeries, taglist map[string]int) { for _, v := range s.Series.Tags { if _, ok := taglist[v]; ok { continue } var id int row := db.QueryRow("INSERT INTO grilist.tags (name, type) VALUES ($1, $2) RETURNING id;", v, models.TagTypeSeries) row.Scan(&id) taglist[v] = id fmt.Printf("Inserted tag %s as %d\n", v, id) } rows, err := db.Query("SELECT tag_id FROM appearances_tags WHERE appearance_id = $1;", dbID) LogErr(err) existingTags := make(map[int]bool, 0) for rows.Next() { var tagID int rows.Scan(&tagID) existingTags[tagID] = true } for _, v := range s.Series.Tags { tagID := taglist[v] if _, ok := existingTags[tagID]; ok { continue } _, err := db.Exec("INSERT INTO grilist.appearances_tags (appearance_id, tag_id) VALUES ($1, $2);", dbID, tagID) existingTags[tagID] = true fmt.Printf("Assigned tag %s to %s\n", v, s.Series.Name) LogErr(err) } } func main() { flag.StringVar(&path, "path", "", "path of the source files") flag.StringVar(&sourceType, "type", "", "type of the files (ACDv2)") flag.StringVar(&imgUrlExportFile, "imageexportfile", "", "image URLs will be exported to this file, THIS WILL OVERWRITE EVERYTHING IN THE FILE!") flag.Parse() if imgUrlExportFile != "" { var err error if exportFile, err = os.Create(imgUrlExportFile); err != nil { fmt.Fprintf(os.Stderr, "%s\n", "error while accessing \"%s\"") fmt.Fprintf(os.Stderr, "%v\n", err) os.Exit(1) } } if path == "" { fmt.Fprintf(os.Stderr, "%s\n", "\"path\" must be specified!") flag.Usage() os.Exit(1) } r = GetSeriesReader(sourceType) if r == nil { fmt.Fprintf(os.Stderr, "%s\n", "\"type\" must be specified and a valid series source!") flag.Usage() os.Exit(1) } config := grilist.LoadConfig() var err error db, err = sql.Open("postgres", config.DBConnectionString()) if err == nil { err = db.Ping() } if err != nil { fmt.Fprintf(os.Stderr, "%s\n", "error with database connection") fmt.Fprintf(os.Stderr, "%v\n", err) os.Exit(1) } taglist := make(map[string]int) rows, err := db.Query("SELECT id, name FROM grilist.tags WHERE type = $1;", models.TagTypeSeries) LogErr(err) for rows.Next() { var id int var name string rows.Scan(&id, &name) taglist[name] = id } idmap := make(map[int]int) rows, err = db.Query("SELECT source_id, appearance_id FROM grilist.appearances_id_mappings WHERE source = $1;", r.ID()) LogErr(err) for rows.Next() { var sourceID int var appearanceID int rows.Scan(&sourceID, &appearanceID) idmap[sourceID] = appearanceID } filepath.Walk(path, func(path string, info os.FileInfo, err error) error { if info.IsDir() { return nil } s := r.Read(path) var dbID int if dbID = TryGetExistingSeries(s, idmap); dbID == 0 { dbID = InsertSeries(s) } InsertTags(dbID, s, taglist) return nil }) }