From 1727882fb576c2bcc44a6eb338bfee65e24487e2 Mon Sep 17 00:00:00 2001 From: Hamcha Date: Fri, 22 Nov 2019 15:58:55 +0100 Subject: [PATCH] Add scryfall DB for links and images --- README.md | 3 +- cmd/convert.ts | 53 ++++++++++++++++------ lib/types.ts | 110 +++++++++++++++++++++++++++++++++++++++++++++ lib/utils.ts | 5 ++- package.json | 2 +- templates/cube.ejs | 69 ++++++++++++++++++++++++++-- 6 files changed, 222 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index a182af5..e8542fc 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,8 @@ export ACCESS_SECRET= To use the rare finder, you'll need to build the rare db 1. Download this: https://www.mtgjson.com/files/AllPrintings.json -2. Run `yarn import-db` +2. Also download this: https://archive.scryfall.com/json/scryfall-default-cards.json +3. Run `yarn build-db` It will create a file called `mcmCards.json` diff --git a/cmd/convert.ts b/cmd/convert.ts index 8f61511..e1f00e2 100644 --- a/cmd/convert.ts +++ b/cmd/convert.ts @@ -1,31 +1,56 @@ import { existsSync } from "fs"; -import { asyncLoadJSON, asyncSaveJSON } from "../lib"; - -interface JSONCard { - mcmId: number; - set: string; -} +import { asyncLoadJSON, asyncSaveJSON, MCMCard, MCMDB, ScryfallCard, ScryfallDB } from "../lib"; interface JSONSet { - cards: JSONCard[]; + cards: MCMCard[]; } type JSONDB = Record; +const mtgjsonFile = "AllPrintings.json"; +const scryfallJSONFile = "scryfall-default-cards.json"; + async function run() { - if (!existsSync("AllPrintings.json")) { + if (!existsSync(mtgjsonFile)) { console.error( - "AllPrintings.json not found. Download from: https://www.mtgjson.com/files/AllPrintings.json" + mtgjsonFile + + " not found. Download from: https://www.mtgjson.com/files/AllPrintings.json" ); process.exit(1); } - console.info("Loading AllPrintings.json"); - const db = await asyncLoadJSON("AllPrintings.json"); - let acc = {}; - for (const set in db) { - db[set].cards.forEach(c => { + if (!existsSync(scryfallJSONFile)) { + console.error( + scryfallJSONFile + + " not found. Download from: https://archive.scryfall.com/json/scryfall-default-cards.json" + ); + process.exit(1); + } + console.info("Loading " + mtgjsonFile); + const mtgdb = await asyncLoadJSON(mtgjsonFile); + console.info("Loading " + scryfallJSONFile); + const scrydb = await asyncLoadJSON(scryfallJSONFile); + let scrycards: Record = {}; + scrydb.forEach(c => (scrycards[c.id] = c)); + let acc: MCMDB = {}; + for (const set in mtgdb) { + mtgdb[set].cards.forEach(c => { c.set = set; + if (c.scryfallId in scrycards) { + c.scryfallUrl = scrycards[c.scryfallId].scryfall_uri; + if ("image_uris" in scrycards[c.scryfallId]) { + c.scryfallImageUrl = scrycards[c.scryfallId].image_uris.normal; + } else if ( + "card_faces" in scrycards[c.scryfallId] && + "image_uris" in scrycards[c.scryfallId].card_faces[0] + ) { + c.scryfallImageUrl = + scrycards[c.scryfallId].card_faces[0].image_uris.normal; + } else { + console.log(scrycards[c.scryfallId]); + } + } + // Search for scryfall card acc[c.mcmId] = c; }); } diff --git a/lib/types.ts b/lib/types.ts index 9b96faa..5d2acf7 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -62,6 +62,8 @@ export interface MCMCard { scryfallId: string; scryfallIllustrationId: string; scryfallOracleId: string; + scryfallImageUrl: string; + scryfallUrl: string; subtypes: string[]; supertypes: any[]; tcgplayerProductId: number; @@ -86,12 +88,15 @@ export interface LeanMCMCard { name: string; rarity: string; scryfallId: string; + scryfallImageUrl: string; + scryfallUrl: string; subtypes: string[]; supertypes: any[]; text: string; type: string; types: string[]; set: string; + number: string; } export interface Language { @@ -133,3 +138,108 @@ export interface LeanArticle { } export type CardItem = LeanMCMCard & LeanArticle; + +export interface ImageUris { + small: string; + normal: string; + large: string; + png: string; + art_crop: string; + border_crop: string; +} + +export interface Legalities { + standard: string; + future: string; + historic: string; + pioneer: string; + modern: string; + legacy: string; + pauper: string; + vintage: string; + penny: string; + commander: string; + brawl: string; + duel: string; + oldschool: string; +} + +export interface RelatedUris { + tcgplayer_decks: string; + edhrec: string; + mtgtop8: string; +} + +export interface CardFace { + object: string; + name: string; + mana_cost: string; + type_line: string; + oracle_text: string; + colors: string[]; + power: string; + toughness: string; + artist: string; + artist_id: string; + illustration_id: string; + image_uris: ImageUris; + color_indicator: string[]; + loyalty: string; +} + +export interface ScryfallCard { + object: string; + id: string; + oracle_id: string; + multiverse_ids: any[]; + tcgplayer_id: number; + name: string; + lang: string; + released_at: string; + uri: string; + scryfall_uri: string; + layout: string; + highres_image: boolean; + image_uris: ImageUris; + card_faces?: CardFace[]; + mana_cost: string; + cmc: number; + type_line: string; + oracle_text: string; + colors: any[]; + color_identity: string[]; + legalities: Legalities; + games: string[]; + reserved: boolean; + foil: boolean; + nonfoil: boolean; + oversized: boolean; + promo: boolean; + reprint: boolean; + variation: boolean; + set: string; + set_name: string; + set_type: string; + set_uri: string; + set_search_uri: string; + scryfall_set_uri: string; + rulings_uri: string; + prints_search_uri: string; + collector_number: string; + digital: boolean; + rarity: string; + card_back_id: string; + artist: string; + artist_ids: string[]; + illustration_id: string; + border_color: string; + frame: string; + full_art: boolean; + textless: boolean; + booster: boolean; + story_spotlight: boolean; + edhrec_rank: number; + related_uris: RelatedUris; +} + +export type ScryfallDB = ScryfallCard[]; diff --git a/lib/utils.ts b/lib/utils.ts index 0290b57..9b8e75f 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -36,6 +36,7 @@ export function leanCard(card: MCMCard): LeanMCMCard { manaCost: card.manaCost, mcmId: card.mcmId, name: card.name, + number: card.number, rarity: card.rarity, scryfallId: card.scryfallId, subtypes: card.subtypes, @@ -43,7 +44,9 @@ export function leanCard(card: MCMCard): LeanMCMCard { text: card.text, type: card.type, types: card.types, - set: card.set + set: card.set, + scryfallImageUrl: card.scryfallImageUrl, + scryfallUrl: card.scryfallUrl }; } diff --git a/package.json b/package.json index 588d2d8..a837b96 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "license": "MIT", "scripts": { "fetch": "ts-node cmd/fetch.ts", - "init-db": "ts-node cmd/convert.ts", + "build-db": "ts-node cmd/convert.ts", "find": "ts-node cmd/find.ts", "cube": "ts-node cmd/cube.ts", "cube-watch": "ts-node cmd/cube-dev.ts" diff --git a/templates/cube.ejs b/templates/cube.ejs index c8bdecc..1187b1a 100644 --- a/templates/cube.ejs +++ b/templates/cube.ejs @@ -33,11 +33,11 @@ .color-section { flex: 1; - margin: 5px; } .color-section header { text-align: center; + padding: 5px; } .color-W header.color-header { @@ -77,7 +77,7 @@ border: 1px solid #aaa; border-radius: 5px; font-size: 10pt; - margin: 5px 0; + margin: 10px 5px; } .type-section header.type-header { @@ -87,6 +87,17 @@ padding: 5px; } + .cards { + position: relative; + } + + .cmc-index { + position: absolute; + opacity: 0.1; + right: 5px; + font-size: 15pt; + } + ul { margin: 0; padding: 0; @@ -95,12 +106,35 @@ } ul li { + display: flex; + } + + ul li a { padding: 5px; + flex: 1; + color: inherit; + text-decoration: none; + } + + ul li a:hover { + background-color: #eee; } ul:last-child { border-bottom: none; } + + .img-overlay { + position: fixed; + top: 0; + left: 0; + pointer-events: none; + } + + .img-overlay img { + width: auto; + height: 300px; + } @@ -123,9 +157,15 @@ (<%=utils.deepSum(typecards)%>)
<% Object.entries(typecards).forEach(([cmc, finalcards]) => { %> +
<%=cmc%>
<% }); %> @@ -136,6 +176,29 @@ <% }); %>
+ + \ No newline at end of file