Replace CardLocation table with ProductLocation
This commit is contained in:
parent
540a1df24e
commit
9076edb6f6
|
@ -1,37 +0,0 @@
|
||||||
package database
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const CacheTypeAllCardsBulkData = "AllCardsBulkData"
|
|
||||||
|
|
||||||
func GetCacheTimestampByType(db *sql.DB, cacheType string) (string, error) {
|
|
||||||
var timestamp string
|
|
||||||
|
|
||||||
query := "SELECT Stamp FROM CacheTimestamp WHERE CacheType = ?;"
|
|
||||||
err := db.QueryRow(query, cacheType).Scan(×tamp)
|
|
||||||
|
|
||||||
return timestamp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func InsertOrUpdateCacheTimestampByType(db *sql.DB, cacheType string, stamp time.Time) error {
|
|
||||||
query := `INSERT INTO CacheTimestamp (CacheType, Stamp)
|
|
||||||
VALUES (?, ?)
|
|
||||||
ON DUPLICATE KEY
|
|
||||||
UPDATE Stamp = ?;`
|
|
||||||
|
|
||||||
insertOrUpdate, err := db.Prepare(query)
|
|
||||||
defer insertOrUpdate.Close()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = insertOrUpdate.Exec(cacheType, stamp, stamp)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
-- +goose Up
|
|
||||||
-- +goose StatementBegin
|
|
||||||
CREATE TABLE IF NOT EXISTS CacheTimestamp (
|
|
||||||
CacheType ENUM('AllCardsBulkData') PRIMARY KEY,
|
|
||||||
Stamp DATETIME NOT NULL
|
|
||||||
);
|
|
||||||
-- +goose StatementEnd
|
|
||||||
|
|
||||||
-- +goose Down
|
|
||||||
-- +goose StatementBegin
|
|
||||||
DROP TABLE IF EXISTS CacheTimestamp;
|
|
||||||
-- +goose StatementEnd
|
|
|
@ -1,13 +1,13 @@
|
||||||
-- +goose Up
|
-- +goose Up
|
||||||
-- +goose StatementBegin
|
-- +goose StatementBegin
|
||||||
CREATE TABLE IF NOT EXISTS CardtraderExpansion (
|
CREATE TABLE IF NOT EXISTS CardtraderExpansion (
|
||||||
Id INT PRIMARY KEY AUTO_INCREMENT,
|
Id INT PRIMARY KEY,
|
||||||
Code VARCHAR(20) NOT NULL,
|
Code VARCHAR(20) NOT NULL,
|
||||||
Name VARCHAR(255) NOT NULL
|
Name VARCHAR(255) NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS CardtraderBlueprint (
|
CREATE TABLE IF NOT EXISTS CardtraderBlueprint (
|
||||||
Id INT PRIMARY KEY AUTO_INCREMENT,
|
Id INT PRIMARY KEY,
|
||||||
ScryfallCardId VARCHAR(100) NULL,
|
ScryfallCardId VARCHAR(100) NULL,
|
||||||
CardtraderCategoryId INT NOT NULL,
|
CardtraderCategoryId INT NOT NULL,
|
||||||
CardtraderExpansionId INT NOT NULL,
|
CardtraderExpansionId INT NOT NULL,
|
|
@ -1,14 +0,0 @@
|
||||||
-- +goose Up
|
|
||||||
-- +goose StatementBegin
|
|
||||||
CREATE TABLE IF NOT EXISTS ScryfallSet (
|
|
||||||
SetCode VARCHAR(6) PRIMARY KEY,
|
|
||||||
Name VARCHAR(60) NOT NULL,
|
|
||||||
CardCount INT NOT NULL,
|
|
||||||
IconSvgUri VARCHAR(60) NOT NULL
|
|
||||||
);
|
|
||||||
-- +goose StatementEnd
|
|
||||||
|
|
||||||
-- +goose Down
|
|
||||||
-- +goose StatementBegin
|
|
||||||
DROP TABLE IF EXISTS ScryfallSet;
|
|
||||||
-- +goose StatementEnd
|
|
|
@ -3,7 +3,7 @@
|
||||||
CREATE TABLE IF NOT EXISTS StorageArea (
|
CREATE TABLE IF NOT EXISTS StorageArea (
|
||||||
Id INT AUTO_INCREMENT PRIMARY KEY,
|
Id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
Name VARCHAR(100) NOT NULL,
|
Name VARCHAR(100) NOT NULL,
|
||||||
StorageType ENUM('Binder', 'Box')
|
StorageType ENUM('Binder', 'Box') NOT NULL
|
||||||
);
|
);
|
||||||
-- +goose StatementEnd
|
-- +goose StatementEnd
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
-- +goose Up
|
-- +goose Up
|
||||||
-- +goose StatementBegin
|
-- +goose StatementBegin
|
||||||
CREATE TABLE IF NOT EXISTS CardLocation (
|
CREATE TABLE IF NOT EXISTS ProductLocation (
|
||||||
Id INT AUTO_INCREMENT PRIMARY KEY,
|
Id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
ScryfallCardId VARCHAR(36) NULL,
|
CardtraderBlueprintId INT NULL,
|
||||||
FOREIGN KEY (ScryfallCardId) REFERENCES ScryfallCard(Id),
|
FOREIGN KEY (CardtraderBlueprintId) REFERENCES CardtraderBlueprint(Id),
|
||||||
StorageAreaId INT NOT NULL,
|
StorageAreaId INT NOT NULL,
|
||||||
FOREIGN KEY (StorageAreaId) REFERENCES StorageArea(Id),
|
FOREIGN KEY (StorageAreaId) REFERENCES StorageArea(Id),
|
||||||
Position INT NULL,
|
Position INT NULL,
|
||||||
|
@ -13,5 +13,5 @@ CREATE TABLE IF NOT EXISTS CardLocation (
|
||||||
|
|
||||||
-- +goose Down
|
-- +goose Down
|
||||||
-- +goose StatementBegin
|
-- +goose StatementBegin
|
||||||
DROP TABLE IF EXISTS CardLocation;
|
DROP TABLE IF EXISTS ProductLocation;
|
||||||
-- +goose StatementEnd
|
-- +goose StatementEnd
|
|
@ -1,19 +0,0 @@
|
||||||
-- +goose Up
|
|
||||||
-- +goose StatementBegin
|
|
||||||
CREATE TABLE IF NOT EXISTS ScryfallCard (
|
|
||||||
Id VARCHAR(36) PRIMARY KEY,
|
|
||||||
Name VARCHAR(150) NOT NULL,
|
|
||||||
ScryfallSetCode VARCHAR(6) NOT NULL,
|
|
||||||
FOREIGN KEY (ScryfallSetCode) REFERENCES ScryfallSet(SetCode),
|
|
||||||
HasFoilPrinting BOOLEAN NOT NULL,
|
|
||||||
IsPromo BOOLEAN NOT NULL,
|
|
||||||
CollectorNumber VARCHAR(10) NOT NULL,
|
|
||||||
ImageUrl VARCHAR(100) NOT NULL,
|
|
||||||
Language VARCHAR(3) NOT NULL
|
|
||||||
);
|
|
||||||
-- +goose StatementEnd
|
|
||||||
|
|
||||||
-- +goose Down
|
|
||||||
-- +goose StatementBegin
|
|
||||||
DROP TABLE IF EXISTS ScryfallCard;
|
|
||||||
-- +goose StatementEnd
|
|
|
@ -1,78 +0,0 @@
|
||||||
package database
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ScryfallCard struct {
|
|
||||||
Id string
|
|
||||||
Name string
|
|
||||||
ScryfallSetCode string
|
|
||||||
HasFoilPrinting bool
|
|
||||||
IsPromo bool
|
|
||||||
CollectorNumber string
|
|
||||||
ImageUrl string
|
|
||||||
Language string
|
|
||||||
}
|
|
||||||
|
|
||||||
func InsertScryfallCard(db *sql.DB, scryfallCard ScryfallCard) error {
|
|
||||||
query := `INSERT INTO ScryfallCard (
|
|
||||||
Id,
|
|
||||||
Name,
|
|
||||||
ScryfallSetCode,
|
|
||||||
HasFoilPrinting,
|
|
||||||
IsPromo,
|
|
||||||
CollectorNumber,
|
|
||||||
ImageUrl,
|
|
||||||
Language)
|
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?);`
|
|
||||||
|
|
||||||
insert, err := db.Prepare(query)
|
|
||||||
defer insert.Close()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = insert.Exec(scryfallCard.Id,
|
|
||||||
scryfallCard.Name,
|
|
||||||
scryfallCard.ScryfallSetCode,
|
|
||||||
scryfallCard.HasFoilPrinting,
|
|
||||||
scryfallCard.IsPromo,
|
|
||||||
scryfallCard.CollectorNumber,
|
|
||||||
scryfallCard.ImageUrl,
|
|
||||||
scryfallCard.Language)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetAllScryfallCards(db *sql.DB) ([]ScryfallCard, error) {
|
|
||||||
var scryfallCards []ScryfallCard
|
|
||||||
|
|
||||||
query := `SELECT Id, Name, ScryfallSetCode, HasFoilPrinting, IsPromo, CollectorNumber, Language FROM CardPrinting;`
|
|
||||||
rows, err := db.Query(query)
|
|
||||||
defer rows.Close()
|
|
||||||
if err != nil {
|
|
||||||
return scryfallCards, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var scryfallCard ScryfallCard
|
|
||||||
for rows.Next() {
|
|
||||||
err := rows.Scan(&scryfallCard.Id,
|
|
||||||
&scryfallCard.Name,
|
|
||||||
&scryfallCard.ScryfallSetCode,
|
|
||||||
&scryfallCard.HasFoilPrinting,
|
|
||||||
&scryfallCard.IsPromo,
|
|
||||||
&scryfallCard.CollectorNumber,
|
|
||||||
&scryfallCard.Language)
|
|
||||||
if err != nil {
|
|
||||||
return scryfallCards, err
|
|
||||||
}
|
|
||||||
|
|
||||||
scryfallCards = append(scryfallCards, scryfallCard)
|
|
||||||
}
|
|
||||||
|
|
||||||
return scryfallCards, nil
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
package database
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql"
|
|
||||||
"sevenkeys/logic/scryfall"
|
|
||||||
)
|
|
||||||
|
|
||||||
func InsertSet(db *sql.DB, set scryfall.Set) error {
|
|
||||||
query := `INSERT INTO ScryfallSet (SetCode, Name, CardCount, IconSvgUri) VALUES (?, ?, ?, ?);`
|
|
||||||
|
|
||||||
insert, err := db.Prepare(query)
|
|
||||||
defer insert.Close()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = insert.Exec(set.Code, set.Name, set.CardCount, set.IconSvgUri)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
package logic
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sevenkeys/database"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func filterPrinting(scryfallCard database.ScryfallCard, searchCriteria SearchCriteria) bool {
|
|
||||||
if searchCriteria.SetCode != "" && !strings.Contains(scryfallCard.ScryfallSetCode, searchCriteria.SetCode) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if searchCriteria.CollectorNumber != "" && !strings.Contains(scryfallCard.CollectorNumber, searchCriteria.CollectorNumber) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if searchCriteria.Promo == False && scryfallCard.IsPromo {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if searchCriteria.Promo == True && !scryfallCard.IsPromo {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if searchCriteria.Language != "" && scryfallCard.Language != searchCriteria.Language {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
|
@ -1,426 +0,0 @@
|
||||||
package logic
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sevenkeys/database"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestFilterPrinting_ReturnsTrue_IfSetCodeDoesNotMatch(t *testing.T) {
|
|
||||||
printing := database.CardPrinting{
|
|
||||||
SetCode: "rtr",
|
|
||||||
IsFoil: false,
|
|
||||||
IsPromo: false,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
searchCriteria := SearchCriteria{
|
|
||||||
SetCode: "otj",
|
|
||||||
Foil: False,
|
|
||||||
Promo: False,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
filter := filterPrinting(printing, searchCriteria)
|
|
||||||
|
|
||||||
if filter != true {
|
|
||||||
t.Errorf("filter was false")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterPrinting_ReturnsFalse_IfSetCodeDoesMatch(t *testing.T) {
|
|
||||||
printing := database.CardPrinting{
|
|
||||||
SetCode: "rtr",
|
|
||||||
IsFoil: false,
|
|
||||||
IsPromo: false,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
searchCriteria := SearchCriteria{
|
|
||||||
SetCode: "rtr",
|
|
||||||
Foil: False,
|
|
||||||
Promo: False,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
filter := filterPrinting(printing, searchCriteria)
|
|
||||||
|
|
||||||
if filter != false {
|
|
||||||
t.Errorf("filter was true")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterPrinting_ReturnsFalse_IfSetCodeNotSet(t *testing.T) {
|
|
||||||
printing := database.CardPrinting{
|
|
||||||
SetCode: "rtr",
|
|
||||||
IsFoil: false,
|
|
||||||
IsPromo: false,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
searchCriteria := SearchCriteria{
|
|
||||||
SetCode: "",
|
|
||||||
Foil: False,
|
|
||||||
Promo: False,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
filter := filterPrinting(printing, searchCriteria)
|
|
||||||
|
|
||||||
if filter != false {
|
|
||||||
t.Errorf("filter was true")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterPrinting_ReturnsTrue_IfFoilCardInNonFoilSearch(t *testing.T) {
|
|
||||||
printing := database.CardPrinting{
|
|
||||||
SetCode: "rtr",
|
|
||||||
IsFoil: true,
|
|
||||||
IsPromo: false,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
searchCriteria := SearchCriteria{
|
|
||||||
SetCode: "rtr",
|
|
||||||
Foil: False,
|
|
||||||
Promo: False,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
filter := filterPrinting(printing, searchCriteria)
|
|
||||||
|
|
||||||
if filter != true {
|
|
||||||
t.Errorf("filter was false")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterPrinting_ReturnsTrue_IfNonFoilCardInFoilSearch(t *testing.T) {
|
|
||||||
printing := database.CardPrinting{
|
|
||||||
SetCode: "rtr",
|
|
||||||
IsFoil: false,
|
|
||||||
IsPromo: false,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
searchCriteria := SearchCriteria{
|
|
||||||
SetCode: "rtr",
|
|
||||||
Foil: True,
|
|
||||||
Promo: False,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
filter := filterPrinting(printing, searchCriteria)
|
|
||||||
|
|
||||||
if filter != true {
|
|
||||||
t.Errorf("filter was false")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterPrinting_ReturnsFalse_IfNonFoilCardInNonFoilSearch(t *testing.T) {
|
|
||||||
printing := database.CardPrinting{
|
|
||||||
SetCode: "rtr",
|
|
||||||
IsFoil: false,
|
|
||||||
IsPromo: false,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
searchCriteria := SearchCriteria{
|
|
||||||
SetCode: "rtr",
|
|
||||||
Foil: False,
|
|
||||||
Promo: False,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
filter := filterPrinting(printing, searchCriteria)
|
|
||||||
|
|
||||||
if filter != false {
|
|
||||||
t.Errorf("filter was true")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterPrinting_ReturnsFalse_IfFoilCardInFoilSearch(t *testing.T) {
|
|
||||||
printing := database.CardPrinting{
|
|
||||||
SetCode: "rtr",
|
|
||||||
IsFoil: true,
|
|
||||||
IsPromo: false,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
searchCriteria := SearchCriteria{
|
|
||||||
SetCode: "rtr",
|
|
||||||
Foil: True,
|
|
||||||
Promo: False,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
filter := filterPrinting(printing, searchCriteria)
|
|
||||||
|
|
||||||
if filter != false {
|
|
||||||
t.Errorf("filter was true")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterPrinting_ReturnsFalse_IfFoilCardInEitherFoilSearch(t *testing.T) {
|
|
||||||
printing := database.CardPrinting{
|
|
||||||
SetCode: "rtr",
|
|
||||||
IsFoil: true,
|
|
||||||
IsPromo: false,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
searchCriteria := SearchCriteria{
|
|
||||||
SetCode: "rtr",
|
|
||||||
Foil: Either,
|
|
||||||
Promo: False,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
filter := filterPrinting(printing, searchCriteria)
|
|
||||||
|
|
||||||
if filter != false {
|
|
||||||
t.Errorf("filter was true")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterPrinting_ReturnsFalse_IfNonFoilCardInEitherFoilSearch(t *testing.T) {
|
|
||||||
printing := database.CardPrinting{
|
|
||||||
SetCode: "rtr",
|
|
||||||
IsFoil: false,
|
|
||||||
IsPromo: false,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
searchCriteria := SearchCriteria{
|
|
||||||
SetCode: "rtr",
|
|
||||||
Foil: Either,
|
|
||||||
Promo: False,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
filter := filterPrinting(printing, searchCriteria)
|
|
||||||
|
|
||||||
if filter != false {
|
|
||||||
t.Errorf("filter was true")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterPrinting_ReturnsTrue_IfPromoCardInNonPromoSearch(t *testing.T) {
|
|
||||||
printing := database.CardPrinting{
|
|
||||||
SetCode: "rtr",
|
|
||||||
IsFoil: false,
|
|
||||||
IsPromo: true,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
searchCriteria := SearchCriteria{
|
|
||||||
SetCode: "rtr",
|
|
||||||
Foil: False,
|
|
||||||
Promo: False,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
filter := filterPrinting(printing, searchCriteria)
|
|
||||||
|
|
||||||
if filter != true {
|
|
||||||
t.Errorf("filter was false")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterPrinting_ReturnsTrue_IfNonPromoCardInPromoSearch(t *testing.T) {
|
|
||||||
printing := database.CardPrinting{
|
|
||||||
SetCode: "rtr",
|
|
||||||
IsFoil: false,
|
|
||||||
IsPromo: false,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
searchCriteria := SearchCriteria{
|
|
||||||
SetCode: "rtr",
|
|
||||||
Foil: False,
|
|
||||||
Promo: True,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
filter := filterPrinting(printing, searchCriteria)
|
|
||||||
|
|
||||||
if filter != true {
|
|
||||||
t.Errorf("filter was false")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterPrinting_ReturnsFalse_IfNonPromoCardInNonPromoSearch(t *testing.T) {
|
|
||||||
printing := database.CardPrinting{
|
|
||||||
SetCode: "rtr",
|
|
||||||
IsFoil: false,
|
|
||||||
IsPromo: false,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
searchCriteria := SearchCriteria{
|
|
||||||
SetCode: "rtr",
|
|
||||||
Foil: False,
|
|
||||||
Promo: False,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
filter := filterPrinting(printing, searchCriteria)
|
|
||||||
|
|
||||||
if filter != false {
|
|
||||||
t.Errorf("filter was true")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterPrinting_ReturnsFalse_IfPromoCardInPromoSearch(t *testing.T) {
|
|
||||||
printing := database.CardPrinting{
|
|
||||||
SetCode: "rtr",
|
|
||||||
IsFoil: false,
|
|
||||||
IsPromo: true,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
searchCriteria := SearchCriteria{
|
|
||||||
SetCode: "rtr",
|
|
||||||
Foil: False,
|
|
||||||
Promo: True,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
filter := filterPrinting(printing, searchCriteria)
|
|
||||||
|
|
||||||
if filter != false {
|
|
||||||
t.Errorf("filter was true")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterPrinting_ReturnsFalse_IfPromoCardInEitherPromoSearch(t *testing.T) {
|
|
||||||
printing := database.CardPrinting{
|
|
||||||
SetCode: "rtr",
|
|
||||||
IsFoil: false,
|
|
||||||
IsPromo: true,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
searchCriteria := SearchCriteria{
|
|
||||||
SetCode: "rtr",
|
|
||||||
Foil: False,
|
|
||||||
Promo: Either,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
filter := filterPrinting(printing, searchCriteria)
|
|
||||||
|
|
||||||
if filter != false {
|
|
||||||
t.Errorf("filter was true")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterPrinting_ReturnsFalse_IfNonPromoCardInEitherPromoSearch(t *testing.T) {
|
|
||||||
printing := database.CardPrinting{
|
|
||||||
SetCode: "rtr",
|
|
||||||
IsFoil: false,
|
|
||||||
IsPromo: false,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
searchCriteria := SearchCriteria{
|
|
||||||
SetCode: "rtr",
|
|
||||||
Foil: False,
|
|
||||||
Promo: Either,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
filter := filterPrinting(printing, searchCriteria)
|
|
||||||
|
|
||||||
if filter != false {
|
|
||||||
t.Errorf("filter was true")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterPrinting_ReturnsTrue_IfLanguageDoesNotMatch(t *testing.T) {
|
|
||||||
printing := database.CardPrinting{
|
|
||||||
SetCode: "rtr",
|
|
||||||
IsFoil: false,
|
|
||||||
IsPromo: false,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
searchCriteria := SearchCriteria{
|
|
||||||
SetCode: "rtr",
|
|
||||||
Foil: False,
|
|
||||||
Promo: False,
|
|
||||||
Language: "de",
|
|
||||||
}
|
|
||||||
|
|
||||||
filter := filterPrinting(printing, searchCriteria)
|
|
||||||
|
|
||||||
if filter != true {
|
|
||||||
t.Errorf("filter was false")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterPrinting_ReturnsFalse_IfLanguageDoesMatch(t *testing.T) {
|
|
||||||
printing := database.CardPrinting{
|
|
||||||
SetCode: "rtr",
|
|
||||||
IsFoil: false,
|
|
||||||
IsPromo: false,
|
|
||||||
Language: "de",
|
|
||||||
}
|
|
||||||
|
|
||||||
searchCriteria := SearchCriteria{
|
|
||||||
SetCode: "rtr",
|
|
||||||
Foil: False,
|
|
||||||
Promo: False,
|
|
||||||
Language: "de",
|
|
||||||
}
|
|
||||||
|
|
||||||
filter := filterPrinting(printing, searchCriteria)
|
|
||||||
|
|
||||||
if filter != false {
|
|
||||||
t.Errorf("filter was true")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterPrinting_ReturnsFalse_IfLanguageNotSet(t *testing.T) {
|
|
||||||
printing := database.CardPrinting{
|
|
||||||
SetCode: "rtr",
|
|
||||||
IsFoil: false,
|
|
||||||
IsPromo: false,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
searchCriteria := SearchCriteria{
|
|
||||||
SetCode: "rtr",
|
|
||||||
Foil: False,
|
|
||||||
Promo: False,
|
|
||||||
Language: "",
|
|
||||||
}
|
|
||||||
|
|
||||||
filter := filterPrinting(printing, searchCriteria)
|
|
||||||
|
|
||||||
if filter != false {
|
|
||||||
t.Errorf("filter was true")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterPrinting_ReturnsTrue_IfSetCodeMatchesButCollectorNumberDoesnt(t *testing.T) {
|
|
||||||
printing := database.CardPrinting{
|
|
||||||
SetCode: "rtr",
|
|
||||||
CollectorNumber: "301",
|
|
||||||
IsFoil: false,
|
|
||||||
IsPromo: false,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
searchCriteria := SearchCriteria{
|
|
||||||
SetCode: "rtr",
|
|
||||||
CollectorNumber: "299",
|
|
||||||
Foil: False,
|
|
||||||
Promo: False,
|
|
||||||
Language: "",
|
|
||||||
}
|
|
||||||
|
|
||||||
filter := filterPrinting(printing, searchCriteria)
|
|
||||||
|
|
||||||
if filter != true {
|
|
||||||
t.Errorf("filter was false")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -41,32 +41,6 @@ func GetCardAtLocation(db *sql.DB, cardLocationId int) (database.LocateCardResul
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func LocateCards(db *sql.DB, cardNames []string, criteria SearchCriteria) ([]database.LocateCardResult, error) {
|
|
||||||
results, err := database.GetLocateResults(db, cardNames)
|
|
||||||
if err != nil {
|
|
||||||
return results, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var filteredResults []database.LocateCardResult
|
|
||||||
|
|
||||||
for _, result := range results {
|
|
||||||
scryfallCard := database.ScryfallCard{
|
|
||||||
ScryfallSetCode: result.SetCode,
|
|
||||||
IsPromo: result.IsPromo,
|
|
||||||
Language: result.Language,
|
|
||||||
}
|
|
||||||
|
|
||||||
filter := filterPrinting(scryfallCard, criteria)
|
|
||||||
if filter {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
filteredResults = append(filteredResults, result)
|
|
||||||
}
|
|
||||||
|
|
||||||
return filteredResults, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetLocationDescription(location database.LocateCardResult) string {
|
func GetLocationDescription(location database.LocateCardResult) string {
|
||||||
var description string
|
var description string
|
||||||
|
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
package scryfall
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type BulkData struct {
|
|
||||||
Id string `json:"id"`
|
|
||||||
Uri string `json:"uri"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
DownloadUri string `json:"download_uri"`
|
|
||||||
UpdatedAt string `json:"updated_at"`
|
|
||||||
UpdatedAtTime time.Time `json:"ignore"`
|
|
||||||
Size int `json:"size"`
|
|
||||||
ContentType string `json:"content_type"`
|
|
||||||
ContentEncoding string `json:"content_encoding"`
|
|
||||||
}
|
|
||||||
|
|
||||||
const BULK_DATA_URI = "https://api.scryfall.com/bulk-data"
|
|
||||||
|
|
||||||
const BulkDataTypeOracleCards string = "oracle_cards"
|
|
||||||
const BulkDataTypeUniqueArtwork string = "unique_artwork"
|
|
||||||
const BulkDataTypeDefaultCards string = "default_cards"
|
|
||||||
const BulkDataTypeAllCards string = "all_cards"
|
|
||||||
const BulkDataTypeRulings string = "rulings"
|
|
||||||
|
|
||||||
func GetBulkDataByType(bulkDataType string) (BulkData, error) {
|
|
||||||
response, err := http.Get(BULK_DATA_URI + "/" + bulkDataType)
|
|
||||||
if err != nil {
|
|
||||||
return BulkData{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if response.StatusCode != http.StatusOK {
|
|
||||||
return BulkData{}, errors.New("HTTP request failed with code: " + string(response.StatusCode))
|
|
||||||
}
|
|
||||||
|
|
||||||
defer response.Body.Close()
|
|
||||||
bulkDataBytes, err := io.ReadAll(response.Body)
|
|
||||||
if err != nil {
|
|
||||||
return BulkData{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var bulkData BulkData
|
|
||||||
err = json.Unmarshal(bulkDataBytes, &bulkData)
|
|
||||||
if err != nil {
|
|
||||||
return BulkData{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
bulkData.UpdatedAtTime, err = time.Parse(ScryfallTimestampFormat, bulkData.UpdatedAt)
|
|
||||||
if err != nil {
|
|
||||||
return BulkData{}, err
|
|
||||||
}
|
|
||||||
// Round to the nearest second; this is so that comparison with the timestamp stored in the database works as intended
|
|
||||||
bulkData.UpdatedAtTime = bulkData.UpdatedAtTime.Truncate(time.Second)
|
|
||||||
|
|
||||||
return bulkData, nil
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
package scryfall
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SetList struct {
|
|
||||||
Object string `json:"object"`
|
|
||||||
HasMore bool `json:"has_more"`
|
|
||||||
Data []Set `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Set struct {
|
|
||||||
Code string `json:"code"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
CardCount int `json:"card_count"`
|
|
||||||
IconSvgUri string `json:"icon_svg_uri"`
|
|
||||||
Digital bool `json:"digital"`
|
|
||||||
}
|
|
||||||
|
|
||||||
const SETS_API_URL string = "https://api.scryfall.com/sets"
|
|
||||||
|
|
||||||
func GetAllSets() ([]Set, error) {
|
|
||||||
response, err := http.Get(SETS_API_URL)
|
|
||||||
if err != nil {
|
|
||||||
return []Set{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if response.StatusCode != http.StatusOK {
|
|
||||||
return []Set{}, errors.New("HTTP request failed with code: " + string(response.StatusCode))
|
|
||||||
}
|
|
||||||
|
|
||||||
defer response.Body.Close()
|
|
||||||
setsBytes, err := io.ReadAll(response.Body)
|
|
||||||
if err != nil {
|
|
||||||
return []Set{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var setList SetList
|
|
||||||
err = json.Unmarshal(setsBytes, &setList)
|
|
||||||
if err != nil {
|
|
||||||
return []Set{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return setList.Data, nil
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
package scryfall
|
|
||||||
|
|
||||||
const ScryfallTimestampFormat = "2006-01-02T15:04:05.999-07:00"
|
|
|
@ -2,7 +2,6 @@ package logic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
@ -27,38 +26,6 @@ type SearchCriteria struct {
|
||||||
|
|
||||||
type CardPrintingSearchOptions map[string]string
|
type CardPrintingSearchOptions map[string]string
|
||||||
|
|
||||||
func GetAllCardPrintingSearchOptions(db *sql.DB, searchCriteria SearchCriteria) (CardPrintingSearchOptions, error) {
|
|
||||||
var searchOptions CardPrintingSearchOptions = make(CardPrintingSearchOptions)
|
|
||||||
|
|
||||||
scryfallCards, err := database.GetAllScryfallCards(db)
|
|
||||||
if err != nil {
|
|
||||||
return searchOptions, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, scryfallCard := range scryfallCards {
|
|
||||||
// Filter based on search criteria
|
|
||||||
filter := filterPrinting(scryfallCard, searchCriteria)
|
|
||||||
if filter {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Construct search option string
|
|
||||||
searchString := fmt.Sprintf("%s (%s %s) [%s]",
|
|
||||||
scryfallCard.Name,
|
|
||||||
scryfallCard.ScryfallSetCode,
|
|
||||||
scryfallCard.CollectorNumber,
|
|
||||||
scryfallCard.Language)
|
|
||||||
|
|
||||||
if scryfallCard.IsPromo {
|
|
||||||
searchString += " PROMO"
|
|
||||||
}
|
|
||||||
|
|
||||||
searchOptions[searchString] = scryfallCard.Id
|
|
||||||
}
|
|
||||||
|
|
||||||
return searchOptions, err
|
|
||||||
}
|
|
||||||
|
|
||||||
type StorageSearchOptions map[string]int
|
type StorageSearchOptions map[string]int
|
||||||
|
|
||||||
func GetAllStorageSearchOptions(db *sql.DB) (StorageSearchOptions, error) {
|
func GetAllStorageSearchOptions(db *sql.DB) (StorageSearchOptions, error) {
|
||||||
|
|
|
@ -41,8 +41,6 @@ func main() {
|
||||||
|
|
||||||
switch flag.Args()[0] {
|
switch flag.Args()[0] {
|
||||||
case UpdateSubcommand:
|
case UpdateSubcommand:
|
||||||
update.UpdateScryfallData(db)
|
|
||||||
|
|
||||||
err := update.UpdateCardtraderData(db, config.CardtraderToken)
|
err := update.UpdateCardtraderData(db, config.CardtraderToken)
|
||||||
logic.Check(err)
|
logic.Check(err)
|
||||||
break
|
break
|
||||||
|
@ -103,38 +101,39 @@ func main() {
|
||||||
err = logic.ImportDelverLensCards(db, delverLensCards, storageAreaId)
|
err = logic.ImportDelverLensCards(db, delverLensCards, storageAreaId)
|
||||||
logic.Check(err)
|
logic.Check(err)
|
||||||
break
|
break
|
||||||
case SearchPrintingsSubcommand:
|
|
||||||
searchPrintingsCmd := flag.NewFlagSet(SearchPrintingsSubcommand, flag.ExitOnError)
|
|
||||||
|
|
||||||
setCode := searchPrintingsCmd.String("set-code", "", "The code for the set the card we're searching for belongs to.")
|
|
||||||
collectorNumber := searchPrintingsCmd.String("collector-number", "", "The collector number of the card we're searching for.")
|
|
||||||
//foil := searchPrintingsCmd.String("foil", "E", "Whether the card we're searching for is foil.")
|
|
||||||
|
|
||||||
searchPrintingsCmd.Parse(flag.Args()[1:])
|
|
||||||
|
|
||||||
searchCriteria := logic.SearchCriteria{
|
|
||||||
SetCode: *setCode,
|
|
||||||
CollectorNumber: *collectorNumber,
|
|
||||||
Promo: logic.Either,
|
|
||||||
Language: "en",
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if *foil == "Y" {
|
TODO: Rewrite this to search Blueprints
|
||||||
searchCriteria.Foil = logic.True
|
case SearchPrintingsSubcommand:
|
||||||
} else if *foil == "N" {
|
searchPrintingsCmd := flag.NewFlagSet(SearchPrintingsSubcommand, flag.ExitOnError)
|
||||||
searchCriteria.Foil = logic.False
|
|
||||||
} else {
|
|
||||||
searchCriteria.Foil = logic.Either
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
searchOptions, err := logic.GetAllCardPrintingSearchOptions(db, searchCriteria)
|
setCode := searchPrintingsCmd.String("set-code", "", "The code for the set the card we're searching for belongs to.")
|
||||||
logic.Check(err)
|
collectorNumber := searchPrintingsCmd.String("collector-number", "", "The collector number of the card we're searching for.")
|
||||||
id, _, err := logic.GenericSearch(searchOptions)
|
//foil := searchPrintingsCmd.String("foil", "E", "Whether the card we're searching for is foil.")
|
||||||
logic.Check(err)
|
|
||||||
fmt.Println(id)
|
searchPrintingsCmd.Parse(flag.Args()[1:])
|
||||||
break
|
|
||||||
|
searchCriteria := logic.SearchCriteria{
|
||||||
|
SetCode: *setCode,
|
||||||
|
CollectorNumber: *collectorNumber,
|
||||||
|
Promo: logic.Either,
|
||||||
|
Language: "en",
|
||||||
|
}
|
||||||
|
|
||||||
|
if *foil == "Y" {
|
||||||
|
searchCriteria.Foil = logic.True
|
||||||
|
} else if *foil == "N" {
|
||||||
|
searchCriteria.Foil = logic.False
|
||||||
|
} else {
|
||||||
|
searchCriteria.Foil = logic.Either
|
||||||
|
}
|
||||||
|
|
||||||
|
searchOptions, err := logic.GetAllCardPrintingSearchOptions(db, searchCriteria)
|
||||||
|
logic.Check(err)
|
||||||
|
id, _, err := logic.GenericSearch(searchOptions)
|
||||||
|
logic.Check(err)
|
||||||
|
fmt.Println(id)
|
||||||
|
break
|
||||||
|
*/
|
||||||
case SearchStorageSubcommand:
|
case SearchStorageSubcommand:
|
||||||
searchOptions, err := logic.GetAllStorageSearchOptions(db)
|
searchOptions, err := logic.GetAllStorageSearchOptions(db)
|
||||||
logic.Check(err)
|
logic.Check(err)
|
||||||
|
|
|
@ -1,218 +0,0 @@
|
||||||
package update
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql"
|
|
||||||
"encoding/json"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"sevenkeys/database"
|
|
||||||
"sevenkeys/logic"
|
|
||||||
"sevenkeys/logic/scryfall"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
sqlerr "github.com/go-mysql/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
func scryfallLog(msg string) {
|
|
||||||
log.Printf("scryfall: %s\n", msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
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 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 checkScryfallUpdates(db *sql.DB, bulkData scryfall.BulkData) (bool, error) {
|
|
||||||
cachedFileTimestampStr, err := database.GetCacheTimestampByType(db, database.CacheTypeAllCardsBulkData)
|
|
||||||
if err == sql.ErrNoRows {
|
|
||||||
return true, nil
|
|
||||||
} else if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cachedFileTimestamp, err := time.Parse("2006-01-02 15:04:05", cachedFileTimestampStr)
|
|
||||||
|
|
||||||
return bulkData.UpdatedAtTime.After(cachedFileTimestamp), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateSets(db *sql.DB) error {
|
|
||||||
sets, err := scryfall.GetAllSets()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
err := database.InsertSet(db, set)
|
|
||||||
// If we already have this set in the database, then we can just skip it
|
|
||||||
if ok, insertErr := sqlerr.Error(err); ok {
|
|
||||||
if insertErr == sqlerr.ErrDupeKey {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
response, err := http.Get(set.IconSvgUri)
|
|
||||||
defer response.Body.Close()
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
scryfallLog("Sets updated.")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func cacheBulkCardsFile(db *sql.DB, bulkData scryfall.BulkData) error {
|
|
||||||
bulkCardsResponse, err := http.Get(bulkData.DownloadUri)
|
|
||||||
defer bulkCardsResponse.Body.Close()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
cacheFile, err := os.Create(ALL_CARDS_CACHE_FILENAME)
|
|
||||||
defer cacheFile.Close()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
io.Copy(cacheFile, bulkCardsResponse.Body)
|
|
||||||
|
|
||||||
err = database.InsertOrUpdateCacheTimestampByType(db, database.CacheTypeAllCardsBulkData, bulkData.UpdatedAtTime)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func isPaper(card scryfall.Card) bool {
|
|
||||||
var paper bool = false
|
|
||||||
|
|
||||||
for _, game := range card.Games {
|
|
||||||
if game == GAME_PAPER {
|
|
||||||
paper = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return paper
|
|
||||||
}
|
|
||||||
|
|
||||||
func getScryfallCard(card scryfall.Card) database.ScryfallCard {
|
|
||||||
return database.ScryfallCard{
|
|
||||||
Id: card.Id,
|
|
||||||
Name: card.Name,
|
|
||||||
ScryfallSetCode: card.Set,
|
|
||||||
HasFoilPrinting: card.Foil,
|
|
||||||
IsPromo: card.Promo,
|
|
||||||
CollectorNumber: card.CollectorNumber,
|
|
||||||
ImageUrl: card.ImageUris["png"],
|
|
||||||
Language: card.Language,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateCards(db *sql.DB, bulkData scryfall.BulkData) error {
|
|
||||||
scryfallLog("Caching bulk cards file")
|
|
||||||
err := cacheBulkCardsFile(db, bulkData)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
scryfallLog("Cached bulk cards file")
|
|
||||||
|
|
||||||
scryfallLog("Reading cached file")
|
|
||||||
cardsBytes, err := ioutil.ReadFile(ALL_CARDS_CACHE_FILENAME)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
scryfallLog("Read cached file")
|
|
||||||
|
|
||||||
scryfallLog("Unmarshaling JSON")
|
|
||||||
var cards []scryfall.Card
|
|
||||||
err = json.Unmarshal(cardsBytes, &cards)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
scryfallLog("Unmarshaled JSON")
|
|
||||||
|
|
||||||
scryfallLog("Inserting cards")
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
scryfallCard := getScryfallCard(card)
|
|
||||||
err := database.InsertScryfallCard(db, scryfallCard)
|
|
||||||
// If we already have this card in the database, then we can just skip it
|
|
||||||
if ok, insertErr := sqlerr.Error(err); ok {
|
|
||||||
if insertErr == sqlerr.ErrDupeKey {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scryfallLog("Inserted cards")
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func UpdateScryfallData(db *sql.DB) {
|
|
||||||
bulkData, err := scryfall.GetBulkDataByType(scryfall.BulkDataTypeAllCards)
|
|
||||||
logic.Check(err)
|
|
||||||
|
|
||||||
needsUpdate, err := checkScryfallUpdates(db, bulkData)
|
|
||||||
logic.Check(err)
|
|
||||||
|
|
||||||
if !needsUpdate {
|
|
||||||
scryfallLog("No update required.")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
createCacheDirectories()
|
|
||||||
|
|
||||||
err = updateSets(db)
|
|
||||||
logic.Check(err)
|
|
||||||
|
|
||||||
err = updateCards(db, bulkData)
|
|
||||||
logic.Check(err)
|
|
||||||
|
|
||||||
scryfallLog("Update finished.")
|
|
||||||
}
|
|
Loading…
Reference in New Issue