package main import ( "database/sql" "io" "log" "net/http" "os" "sevenkeys/database" "sevenkeys/database/entities" "sevenkeys/database/operations" "sevenkeys/scryfall/methods" "sevenkeys/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" 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 cardsUpdatedSinceCache(db *sql.DB, updatedAtTimestamp time.Time) (bool, error) { cachedFileTimestamp, err := operations.GetCacheTimestampByType(db, entities.CacheTypeAllCardsBulkData) if err != nil { return false, err } return updatedAtTimestamp.After(cachedFileTimestamp), 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 main() { log.Println("Connecting to database...") db := database.GetDatabaseFromConfig("config.json") log.Println("Connected.") 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.") */ log.Println("Downloading bulk data entry...") allCardsBulkData, err := methods.GetBulkDataByType(types.BulkDataTypeAllCards) check(err) log.Println("Downloaded bulk data entry.") updatedAtTimestamp, err := time.Parse(types.ScryfallTimestampFormat, allCardsBulkData.UpdatedAt) check(err) updatedAtTimestamp = updatedAtTimestamp.Truncate(time.Second) // Remove the fractional seconds component from the timestamp log.Println("Checking for redownload...") updated, err := cardsUpdatedSinceCache(db, updatedAtTimestamp) check(err) if updated { log.Printf("Bulk data has been updated since last cache, redownloading.") return err = cacheAllCardsFile(db, allCardsBulkData.DownloadUri, updatedAtTimestamp) check(err) } else { log.Printf("Bulk data has not been updated. Skipping download.") } // Unmarshal cached file into Golang struct // Import cards into database }