package main import ( "database/sql" "encoding/json" "io" "io/ioutil" "log" "net/http" "os" "sevenkeys/database/entities" "sevenkeys/database/operations" "sevenkeys/logic/scryfall/types" "time" ) const CACHE_DIR string = "cache" const SET_ICON_CACHE_DIR string = CACHE_DIR + "/seticons/" const SET_ICON_FILE_EXTENSION string = ".svg" const ALL_CARDS_CACHE_FILENAME = CACHE_DIR + "/all-cards.json" const GAME_PAPER = "paper" func check(err error) { if err != nil { log.Fatal(err) } } func createCacheDirectories() error { err := os.Mkdir(CACHE_DIR, os.ModePerm) if err != nil && !os.IsExist(err) { return err } err = os.Mkdir(SET_ICON_CACHE_DIR, os.ModePerm) if err != nil && !os.IsExist(err) { return err } return nil } func importSets(db *sql.DB, sets []types.Set) error { for _, set := range sets { // We're only interested in paper cards, so skip importing // any sets that were only released in a video game if set.Digital { continue } log.Println("Importing " + set.Code) err := operations.InsertOrUpdateSet(db, set) if err != nil { return err } log.Println("Downloading logo for " + set.Code) response, err := http.Get(set.IconSvgUri) defer response.Body.Close() if err != nil { return err } iconFilename := SET_ICON_CACHE_DIR + set.Code + SET_ICON_FILE_EXTENSION iconFile, err := os.Create(iconFilename) if err != nil { return err } io.Copy(iconFile, response.Body) log.Println("Finished importing " + set.Code) } return nil } func cacheAllCardsFile(db *sql.DB, uri string, updatedAtTimestamp time.Time) error { log.Printf("Downloading bulk card data...") bulkCardsResponse, err := http.Get(uri) if err != nil { return err } log.Printf("Downloaded bulk card data.") log.Printf("Writing card data to cache file...") cacheFile, err := os.Create(ALL_CARDS_CACHE_FILENAME) if err != nil { return err } defer bulkCardsResponse.Body.Close() defer cacheFile.Close() io.Copy(cacheFile, bulkCardsResponse.Body) log.Printf("Cache file written.") log.Printf("Recording timestamp...") err = operations.InsertOrUpdateCacheTimestampByType(db, entities.CacheTypeAllCardsBulkData, updatedAtTimestamp) if err != nil { return err } log.Printf("Timestamp recorded.") return nil } func importCards(db *sql.DB, cards []types.Card) error { for _, card := range cards { // We're only interested in paper cards, so skip cards or printings of a card which // aren't available in paper if !isPaper(card) { continue } err := operations.InsertCard(db, card) if err != nil { return err } } return nil } func isPaper(card types.Card) bool { var paper bool = false for _, game := range card.Games { if game == GAME_PAPER { paper = true } } return paper } func main() { log.Println("Creating cache directories...") err := createCacheDirectories() check(err) log.Println("Created cache directories.") log.Println("Downloading set data from Scryfall...") sets, err := methods.GetSets() check(err) log.Println("Downloaded set data.") log.Println("Importing set data...") err = importSets(db, sets) check(err) log.Println("Imported sets.") if updated { log.Printf("Bulk data has been updated since last cache, redownloading.") err = cacheAllCardsFile(db, allCardsBulkData.DownloadUri, updatedAtTimestamp) check(err) } else { log.Printf("Bulk data has not been updated. Skipping download.") } log.Printf("Unmarsaling file into slice...") allCardsBytes, err := ioutil.ReadFile(ALL_CARDS_CACHE_FILENAME) check(err) var allCards []types.Card err = json.Unmarshal(allCardsBytes, &allCards) check(err) log.Printf("Unmarshaled file.") log.Printf("Importing card data into database...") err = importCards(db, allCards) check(err) log.Printf("Imported card data.") }