Rework Scryfall Image Downloads (#11926)

* Rework Scryfall Image Downloads

Now autoconverts collector numbers ending in "*" or "+" or "Ph" so not as many direct links required.
Uses a third attempt with &variation=true which is needed for the 79 cards that are marked as variations.
Fully tested image downloads with language set to russian to ensure fallbacks work correctly.

Restored comments to match scryfall names instead of the .java file names
Added check for api link ending in "/"
Added workaround comments.
Created prepareCardNumber in ScryfallImageSupportCards.java to use for the shared code.

A couple of comments of scryfall set names:
Commander Legends: Battle for Baldur's Gate
Game Night: Free-for-All

Comment for Viscera Seer re issue 11157
This commit is contained in:
tiera3 2024-05-26 08:33:23 +10:00 committed by GitHub
parent 8d574eaba1
commit e3e5f3fa28
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 85 additions and 479 deletions

View file

@ -33,6 +33,24 @@ public class CardImageUrls {
}
}
public CardImageUrls(String baseUrl, String alternativeUrl , String nextaltUrl) {
this();
this.baseUrl = baseUrl;
if (alternativeUrl != null
&& !alternativeUrl.isEmpty()
&& !Objects.equals(baseUrl, alternativeUrl)) {
this.alternativeUrls.add(alternativeUrl);
}
if (nextaltUrl != null
&& !nextaltUrl.isEmpty()
&& !Objects.equals(baseUrl, nextaltUrl)) {
this.alternativeUrls.add(nextaltUrl);
}
}
public List<String> getDownloadList() {
List<String> downloadUrls = new ArrayList<>();

View file

@ -83,14 +83,18 @@ public enum ScryfallImageSource implements CardImageSource {
if (ScryfallImageSupportCards.isApiLink(link)) {
// api link - must prepare direct link
baseUrl = link + localizedCode + "?format=image";
alternativeUrl = link + defaultCode + "?format=image";
// workaround to use cards without english images (some promos or special cards)
if (Objects.equals(baseUrl, alternativeUrl) && baseUrl.endsWith("/en?format=image")) {
alternativeUrl = alternativeUrl.replace("/en?format=image", "?format=image");
if (link.endsWith("/")) {
alternativeUrl = link.substring(0,link.length()-1) + "?format=image";
}
} else {
// direct link to image
baseUrl = link;
// workaround to use localization in direct links
if (link.contains("/?format=image")){
baseUrl = link.replaceFirst("\\?format=image" , localizedCode + "?format=image");
alternativeUrl = link.replaceFirst("/\\?format=image" , "?format=image");
}
}
}
}
@ -109,26 +113,25 @@ public enum ScryfallImageSource implements CardImageSource {
// basic cards by api call (redirect to img link)
// example: https://api.scryfall.com/cards/xln/121/en?format=image
if (baseUrl == null) {
String cn = ScryfallImageSupportCards.prepareCardNumber(card.getCollectorId()) ;
baseUrl = String.format("https://api.scryfall.com/cards/%s/%s/%s?format=image",
formatSetName(card.getSet(), isToken),
card.getCollectorId(),
cn,
localizedCode);
alternativeUrl = String.format("https://api.scryfall.com/cards/%s/%s/%s?format=image",
alternativeUrl = String.format("https://api.scryfall.com/cards/%s/%s?format=image",
formatSetName(card.getSet(), isToken),
card.getCollectorId(),
defaultCode);
cn);
// with no localisation code, scryfall defaults to first available image - usually english, but may not be for some special cards
// workaround to use cards without english images (some promos or special cards)
// bug: https://github.com/magefree/mage/issues/6829
// example: Mysterious Egg from IKO https://api.scryfall.com/cards/iko/385/?format=image
if (Objects.equals(baseUrl, alternativeUrl)) {
// without loc code scryfall must return first available image
alternativeUrl = String.format("https://api.scryfall.com/cards/%s/%s/?format=image",
formatSetName(card.getSet(), isToken),
card.getCollectorId());
}
}
return new CardImageUrls(baseUrl, alternativeUrl);
// workaround to deal with the cards that scryfall has marked as variations that seem to sometimes fail
// eg https://api.scryfall.com/cards/4ed/134?format=image fails
// eg https://api.scryfall.com/cards/4ed/134?format=image&variation=true succeeds
return new CardImageUrls(baseUrl, alternativeUrl , alternativeUrl + "&variation=true");
}
private String getFaceImageUrl(Proxy proxy, CardDownloadData card, boolean isToken) throws Exception {
@ -140,6 +143,13 @@ public enum ScryfallImageSource implements CardImageSource {
String apiUrl = ScryfallImageSupportCards.findDirectDownloadLink(card.getSet(), card.getName(), card.getCollectorId());
if (apiUrl != null) {
if (apiUrl.endsWith("*/")) {
apiUrl = apiUrl.substring(0 , apiUrl.length() -2) + "★/" ;
} else if (apiUrl.endsWith("+/")) {
apiUrl = apiUrl.substring(0 , apiUrl.length() -2) + "†/" ;
} else if (apiUrl.endsWith("Ph/")) {
apiUrl = apiUrl.substring(0 , apiUrl.length() -3) + "Φ/" ;
}
// BY DIRECT URL
// direct links via hardcoded API path. Used for cards with non-ASCII collector numbers
if (localizedCode.equals(defaultCode)) {
@ -154,15 +164,15 @@ public enum ScryfallImageSource implements CardImageSource {
} else {
// BY CARD NUMBER
// localized and default
String cn = ScryfallImageSupportCards.prepareCardNumber (card.getCollectorId()) ;
needUrls.add(String.format("https://api.scryfall.com/cards/%s/%s/%s",
formatSetName(card.getSet(), isToken),
card.getCollectorId(),
cn,
localizedCode));
if (!localizedCode.equals(defaultCode)) {
needUrls.add(String.format("https://api.scryfall.com/cards/%s/%s/%s",
needUrls.add(String.format("https://api.scryfall.com/cards/%s/%s",
formatSetName(card.getSet(), isToken),
card.getCollectorId(),
defaultCode));
cn));
}
}

View file

@ -371,7 +371,7 @@ public class ScryfallImageSupportCards {
add("C17"); // Commander 2017
add("WMC"); // World Magic Cup Qualifiers
add("H17"); // HasCon 2017
add("HTR16"); // 2016 Heroes of the Realm
add("PHTR"); // 2016 Heroes of the Realm
add("PXLN"); // Ixalan Promos
add("XLN"); // Ixalan
add("PSS2"); // XLN Standard Showdown
@ -438,7 +438,7 @@ public class ScryfallImageSupportCards {
add("PELD"); // Throne of Eldraine Promos
add("ELD"); // Throne of Eldraine
//add("PTG"); // Ponies: The Galloping
add("CMB1"); // Mystery Booster Playtest Cards
add("CMB1"); // Mystery Booster Playtest Cards 2019
//add("MB1"); // Mystery Booster
add("GN2"); // Game Night 2019
add("HA1"); // Historic Anthology 1
@ -490,6 +490,7 @@ public class ScryfallImageSupportCards {
add("C21"); // Commander 2021 Edition
add("MH2"); // Modern Horizons 2
add("H1R"); // Modern Horizons 1 Timeshifts
add("PLG21"); // Love Your LGS 2021
add("AFR"); // Adventures in the Forgotten Realms
add("AFC"); // Forgotten Realms Commander
add("J21"); // Jumpstart: Historic Horizons
@ -513,7 +514,7 @@ public class ScryfallImageSupportCards {
add("YDMU"); // Alchemy: Dominaria
add("40K"); // Warhammer 40,000
add("UNF"); // Unfinity
add("GN3"); // Game Night 2022
add("GN3"); // Game Night: Free-for-All
add("BRO"); // The Brothers' War
add("BRC"); // The Brothers' War Commander
add("BRR"); // The Brothers' War Retro Artifacts
@ -538,8 +539,8 @@ public class ScryfallImageSupportCards {
add("WOE"); // Wilds of Eldraine
add("WOT"); // Wilds of Eldraine: Enchanting Tales
add("WOC"); // Wilds of Eldraine Commander
add("LCI"); // Lost Caverns of Ixalan
add("LCC"); // Lost Caverns of Ixalan Commander
add("LCI"); // The Lost Caverns of Ixalan
add("LCC"); // The Lost Caverns of Ixalan Commander
add("REX"); // Jurassic World Collection
add("SPG"); // Special Guests
add("RVR"); // Ravnica Remastered
@ -569,6 +570,7 @@ public class ScryfallImageSupportCards {
// example:
// api link: https://api.scryfall.com/cards/trix/6/
// api direct link: https://api.scryfall.com/cards/rex/26/en?format=image&face=back
// api loc link: https://api.scryfall.com/cards/rex/26/?format=image - loc code will be inserted between "/?"
// image link: https://c1.scryfall.com/file/scryfall-cards/large/back/d/5/d5dfd236-b1da-4552-b94f-ebf6bb9dafdf.jpg
//
// key for one card:
@ -579,478 +581,47 @@ public class ScryfallImageSupportCards {
// set/card_name/card_number_2
//
// double faced cards:
// front face image: format=image&face=front
// front face image: format=image&face=front or simply format=image
// back face image: format=image&face=back
// example: https://api.scryfall.com/cards/rex/26/en?format=image&face=back
//
// Cards with non-ASCII collector numbers must use direct download (cause xmage uses different card number)
// Cards with non-ASCII collector numbers
// - ending in "*" will replace with "" for scryfall
// - ending in "+" will replace with "" for scryfall
// - ending in "Ph" will replace with "Φ" for scryfall
// - anything else must use direct download (cause xmage uses different card number)
// Verify checks must check and show missing data from that list,
// see test_checkMissingScryfallSettingsAndCardNumbers
// 10E
put("10E/Air Elemental/64*", "https://api.scryfall.com/cards/10e/64★/");
put("10E/Anaba Bodyguard/187*", "https://api.scryfall.com/cards/10e/187★/");
put("10E/Ancestor's Chosen/1*", "https://api.scryfall.com/cards/10e/1★/");
put("10E/Angel of Mercy/2*", "https://api.scryfall.com/cards/10e/2★/");
put("10E/Angelic Blessing/3*", "https://api.scryfall.com/cards/10e/3★/");
put("10E/Angelic Wall/5*", "https://api.scryfall.com/cards/10e/5★/");
put("10E/Arcane Teachings/188*", "https://api.scryfall.com/cards/10e/188★/");
put("10E/Ascendant Evincar/127*", "https://api.scryfall.com/cards/10e/127★/");
put("10E/Avatar of Might/251*", "https://api.scryfall.com/cards/10e/251★/");
put("10E/Aven Cloudchaser/7*", "https://api.scryfall.com/cards/10e/7★/");
put("10E/Aven Fisher/68*", "https://api.scryfall.com/cards/10e/68★/");
put("10E/Aven Windreader/69*", "https://api.scryfall.com/cards/10e/69★/");
put("10E/Benalish Knight/11*", "https://api.scryfall.com/cards/10e/11★/");
put("10E/Birds of Paradise/252*", "https://api.scryfall.com/cards/10e/252★/");
put("10E/Blanchwood Armor/253*", "https://api.scryfall.com/cards/10e/253★/");
put("10E/Bog Wraith/130*", "https://api.scryfall.com/cards/10e/130★/");
put("10E/Canopy Spider/254*", "https://api.scryfall.com/cards/10e/254★/");
put("10E/Cloud Elemental/74*", "https://api.scryfall.com/cards/10e/74★/");
put("10E/Cloud Sprite/75*", "https://api.scryfall.com/cards/10e/75★/");
put("10E/Coat of Arms/316*", "https://api.scryfall.com/cards/10e/316★/");
put("10E/Colossus of Sardia/317*", "https://api.scryfall.com/cards/10e/317★/");
put("10E/Contaminated Bond/132*", "https://api.scryfall.com/cards/10e/132★/");
put("10E/Dehydration/78*", "https://api.scryfall.com/cards/10e/78★/");
put("10E/Dragon Roost/197*", "https://api.scryfall.com/cards/10e/197★/");
put("10E/Drudge Skeletons/139*", "https://api.scryfall.com/cards/10e/139★/");
put("10E/Dusk Imp/140*", "https://api.scryfall.com/cards/10e/140★/");
put("10E/Elvish Champion/261*", "https://api.scryfall.com/cards/10e/261★/");
put("10E/Faerie Conclave/351*", "https://api.scryfall.com/cards/10e/351★/");
put("10E/Fear/142*", "https://api.scryfall.com/cards/10e/142★/");
put("10E/Field Marshal/15*", "https://api.scryfall.com/cards/10e/15★/");
put("10E/Firebreathing/200*", "https://api.scryfall.com/cards/10e/200★/");
put("10E/Fog Elemental/85*", "https://api.scryfall.com/cards/10e/85★/");
put("10E/Furnace Whelp/205*", "https://api.scryfall.com/cards/10e/205★/");
put("10E/Ghitu Encampment/353*", "https://api.scryfall.com/cards/10e/353★/");
put("10E/Giant Spider/267*", "https://api.scryfall.com/cards/10e/267★/");
put("10E/Goblin King/207*", "https://api.scryfall.com/cards/10e/207★/");
put("10E/Goblin Sky Raider/210*", "https://api.scryfall.com/cards/10e/210★/");
put("10E/Heart of Light/19*", "https://api.scryfall.com/cards/10e/19★/");
put("10E/Holy Strength/22*", "https://api.scryfall.com/cards/10e/22★/");
put("10E/Hypnotic Specter/151*", "https://api.scryfall.com/cards/10e/151★/");
put("10E/Kamahl, Pit Fighter/214*", "https://api.scryfall.com/cards/10e/214★/");
put("10E/Leonin Scimitar/331*", "https://api.scryfall.com/cards/10e/331★/");
put("10E/Lightning Elemental/217*", "https://api.scryfall.com/cards/10e/217★/");
put("10E/Lord of the Pit/154*", "https://api.scryfall.com/cards/10e/154★/");
put("10E/Loxodon Warhammer/332*", "https://api.scryfall.com/cards/10e/332★/");
put("10E/Lure/276*", "https://api.scryfall.com/cards/10e/276★/");
put("10E/Mahamoti Djinn/90*", "https://api.scryfall.com/cards/10e/90★/");
put("10E/Mantis Engine/333*", "https://api.scryfall.com/cards/10e/333★/");
put("10E/March of the Machines/91*", "https://api.scryfall.com/cards/10e/91★/");
put("10E/Might Weaver/278*", "https://api.scryfall.com/cards/10e/278★/");
//put("10E/Mind Bend/93*", "https://api.scryfall.com/cards/10e/93★/"); // not implemented
put("10E/Mirri, Cat Warrior/279*", "https://api.scryfall.com/cards/10e/279★/");
put("10E/Mobilization/29*", "https://api.scryfall.com/cards/10e/29★/");
put("10E/Molimo, Maro-Sorcerer/280*", "https://api.scryfall.com/cards/10e/280★/");
put("10E/Mortivore/161*", "https://api.scryfall.com/cards/10e/161★/");
put("10E/Nekrataal/163*", "https://api.scryfall.com/cards/10e/163★/");
put("10E/Nightmare/164*", "https://api.scryfall.com/cards/10e/164★/");
put("10E/Nomad Mythmaker/30*", "https://api.scryfall.com/cards/10e/30★/");
put("10E/Ornithopter/336*", "https://api.scryfall.com/cards/10e/336★/");
put("10E/Overgrowth/283*", "https://api.scryfall.com/cards/10e/283★/");
put("10E/Overrun/284*", "https://api.scryfall.com/cards/10e/284★/");
put("10E/Pacifism/31*", "https://api.scryfall.com/cards/10e/31★/");
put("10E/Paladin en-Vec/32*", "https://api.scryfall.com/cards/10e/32★/");
put("10E/Pariah/33*", "https://api.scryfall.com/cards/10e/33★/");
put("10E/Persuasion/95*", "https://api.scryfall.com/cards/10e/95★/");
put("10E/Pincher Beetles/285*", "https://api.scryfall.com/cards/10e/285★/");
put("10E/Plague Beetle/168*", "https://api.scryfall.com/cards/10e/168★/");
put("10E/Platinum Angel/339*", "https://api.scryfall.com/cards/10e/339★/");
put("10E/Primal Rage/286*", "https://api.scryfall.com/cards/10e/286★/");
put("10E/Rage Weaver/223*", "https://api.scryfall.com/cards/10e/223★/");
put("10E/Raging Goblin/224*", "https://api.scryfall.com/cards/10e/224★/");
put("10E/Razormane Masticore/340*", "https://api.scryfall.com/cards/10e/340★/");
put("10E/Regeneration/290*", "https://api.scryfall.com/cards/10e/290★/");
put("10E/Reya Dawnbringer/35*", "https://api.scryfall.com/cards/10e/35★/");
put("10E/Rhox/291*", "https://api.scryfall.com/cards/10e/291★/");
put("10E/Robe of Mirrors/101*", "https://api.scryfall.com/cards/10e/101★/");
put("10E/Rock Badger/226*", "https://api.scryfall.com/cards/10e/226★/");
put("10E/Rootwater Commando/102*", "https://api.scryfall.com/cards/10e/102★/");
put("10E/Rushwood Dryad/294*", "https://api.scryfall.com/cards/10e/294★/");
put("10E/Sage Owl/104*", "https://api.scryfall.com/cards/10e/104★/");
put("10E/Scalpelexis/105*", "https://api.scryfall.com/cards/10e/105★/");
put("10E/Sengir Vampire/176*", "https://api.scryfall.com/cards/10e/176★/");
put("10E/Serra Angel/39*", "https://api.scryfall.com/cards/10e/39★/");
put("10E/Serra's Embrace/40*", "https://api.scryfall.com/cards/10e/40★/");
put("10E/Severed Legion/177*", "https://api.scryfall.com/cards/10e/177★/");
put("10E/Shimmering Wings/107*", "https://api.scryfall.com/cards/10e/107★/");
put("10E/Shivan Dragon/230*", "https://api.scryfall.com/cards/10e/230★/");
put("10E/Shivan Hellkite/231*", "https://api.scryfall.com/cards/10e/231★/");
put("10E/Sky Weaver/109*", "https://api.scryfall.com/cards/10e/109★/");
put("10E/Skyhunter Patrol/41*", "https://api.scryfall.com/cards/10e/41★/");
put("10E/Skyhunter Prowler/42*", "https://api.scryfall.com/cards/10e/42★/");
put("10E/Skyhunter Skirmisher/43*", "https://api.scryfall.com/cards/10e/43★/");
put("10E/Snapping Drake/110*", "https://api.scryfall.com/cards/10e/110★/");
put("10E/Spark Elemental/237*", "https://api.scryfall.com/cards/10e/237★/");
put("10E/Spawning Pool/358*", "https://api.scryfall.com/cards/10e/358★/");
put("10E/Spiketail Hatchling/111*", "https://api.scryfall.com/cards/10e/111★/");
put("10E/Spirit Link/45*", "https://api.scryfall.com/cards/10e/45★/");
put("10E/Stampeding Wildebeests/300*", "https://api.scryfall.com/cards/10e/300★/");
put("10E/Steadfast Guard/48*", "https://api.scryfall.com/cards/10e/48★/");
put("10E/Suntail Hawk/50*", "https://api.scryfall.com/cards/10e/50★/");
put("10E/Tangle Spider/303*", "https://api.scryfall.com/cards/10e/303★/");
put("10E/The Hive/324*", "https://api.scryfall.com/cards/10e/324★/");
put("10E/Thieving Magpie/115*", "https://api.scryfall.com/cards/10e/115★/");
put("10E/Threaten/242*", "https://api.scryfall.com/cards/10e/242★/");
put("10E/Thundering Giant/243*", "https://api.scryfall.com/cards/10e/243★/");
put("10E/Time Stop/117*", "https://api.scryfall.com/cards/10e/117★/");
put("10E/Treetop Bracers/304*", "https://api.scryfall.com/cards/10e/304★/");
put("10E/Treetop Village/361*", "https://api.scryfall.com/cards/10e/361★/");
put("10E/Troll Ascetic/305*", "https://api.scryfall.com/cards/10e/305★/");
put("10E/True Believer/53*", "https://api.scryfall.com/cards/10e/53★/");
put("10E/Tundra Wolves/54*", "https://api.scryfall.com/cards/10e/54★/");
put("10E/Uncontrollable Anger/244*", "https://api.scryfall.com/cards/10e/244★/");
put("10E/Unholy Strength/185*", "https://api.scryfall.com/cards/10e/185★/");
put("10E/Upwelling/306*", "https://api.scryfall.com/cards/10e/306★/");
put("10E/Vampire Bats/186*", "https://api.scryfall.com/cards/10e/186★/");
put("10E/Viashino Sandscout/246*", "https://api.scryfall.com/cards/10e/246★/");
put("10E/Voice of All/56*", "https://api.scryfall.com/cards/10e/56★/");
put("10E/Wall of Air/124*", "https://api.scryfall.com/cards/10e/124★/");
put("10E/Wall of Fire/247*", "https://api.scryfall.com/cards/10e/247★/");
put("10E/Wall of Swords/57*", "https://api.scryfall.com/cards/10e/57★/");
put("10E/Wall of Wood/309*", "https://api.scryfall.com/cards/10e/309★/");
put("10E/Whispersilk Cloak/345*", "https://api.scryfall.com/cards/10e/345★/");
put("10E/Wild Griffin/59*", "https://api.scryfall.com/cards/10e/59★/");
put("10E/Windborn Muse/60*", "https://api.scryfall.com/cards/10e/60★/");
put("10E/Youthful Knight/62*", "https://api.scryfall.com/cards/10e/62★/");
// 4ED
put("4ED/El-Hajjaj/134+", "https://api.scryfall.com/cards/4ed/134†/");
// 5ED
put("5ED/Game of Chaos/232+", "https://api.scryfall.com/cards/5ed/232†/");
put("5ED/Inferno/243+", "https://api.scryfall.com/cards/5ed/243†/");
put("5ED/Ironclaw Curse/244+", "https://api.scryfall.com/cards/5ed/244†/");
put("5ED/Manabarbs/250+", "https://api.scryfall.com/cards/5ed/250†/");
put("5ED/Shivan Dragon/267+", "https://api.scryfall.com/cards/5ed/267†/");
// AER
put("AER/Alley Strangler/52+", "https://api.scryfall.com/cards/aer/52†/");
put("AER/Dawnfeather Eagle/14+", "https://api.scryfall.com/cards/aer/14†/");
put("AER/Wrangle/101+", "https://api.scryfall.com/cards/aer/101†/");
// ARN
put("ARN/Army of Allah/2+", "https://api.scryfall.com/cards/arn/2†/");
put("ARN/Bird Maiden/37+", "https://api.scryfall.com/cards/arn/37†/");
put("ARN/Erg Raiders/25+", "https://api.scryfall.com/cards/arn/25†/");
put("ARN/Fishliver Oil/13+", "https://api.scryfall.com/cards/arn/13†/");
put("ARN/Giant Tortoise/15+", "https://api.scryfall.com/cards/arn/15†/");
put("ARN/Hasran Ogress/27+", "https://api.scryfall.com/cards/arn/27†/");
put("ARN/Moorish Cavalry/7+", "https://api.scryfall.com/cards/arn/7†/");
put("ARN/Nafs Asp/52+", "https://api.scryfall.com/cards/arn/52†/");
put("ARN/Oubliette/31+", "https://api.scryfall.com/cards/arn/31†/");
put("ARN/Piety/8+", "https://api.scryfall.com/cards/arn/8†/");
put("ARN/Rukh Egg/43+", "https://api.scryfall.com/cards/arn/43†/");
put("ARN/Stone-Throwing Devils/33+", "https://api.scryfall.com/cards/arn/33†/");
put("ARN/War Elephant/11+", "https://api.scryfall.com/cards/arn/11†/");
put("ARN/Wyluli Wolf/55+", "https://api.scryfall.com/cards/arn/55†/");
// ATQ
put("ATQ/Tawnos's Weaponry/70+", "https://api.scryfall.com/cards/atq/70†/");
// DD2
put("DD2/Chandra Nalaar/34*", "https://api.scryfall.com/cards/dd2/34★/");
put("DD2/Jace Beleren/1*", "https://api.scryfall.com/cards/dd2/1★/");
// DKM
put("DKM/Icy Manipulator/36*", "https://api.scryfall.com/cards/dkm/36★/");
put("DKM/Incinerate/14*", "https://api.scryfall.com/cards/dkm/14★/");
// DRK
put("DRK/Fountain of Youth/103+", "https://api.scryfall.com/cards/drk/103†/");
put("DRK/Gaea's Touch/77+", "https://api.scryfall.com/cards/drk/77†/");
put("DRK/Runesword/107+", "https://api.scryfall.com/cards/drk/107†/");
// J14
put("J14/Plains/1*", "https://api.scryfall.com/cards/j14/1★/");
put("J14/Island/2*", "https://api.scryfall.com/cards/j14/2★/");
put("J14/Swamp/3*", "https://api.scryfall.com/cards/j14/3★/");
put("J14/Mountain/4*", "https://api.scryfall.com/cards/j14/4★/");
put("J14/Forest/5*", "https://api.scryfall.com/cards/j14/5★/");
// KLD
put("KLD/Arborback Stomper/142+", "https://api.scryfall.com/cards/kld/142†/");
put("KLD/Brazen Scourge/107+", "https://api.scryfall.com/cards/kld/107†/");
put("KLD/Terrain Elemental/272+", "https://api.scryfall.com/cards/kld/272†/");
put("KLD/Wind Drake/70+", "https://api.scryfall.com/cards/kld/70†/");
// M20
put("M20/Corpse Knight/206+", "https://api.scryfall.com/cards/m20/206†/");
// MIR
put("MIR/Reality Ripple/87+", "https://api.scryfall.com/cards/mir/87†/");
// OGW
put("OGW/Captain's Claws/162+", "https://api.scryfall.com/cards/ogw/162†/");
// ODY
put("ODY/Cephalid Looter/72+", "https://api.scryfall.com/cards/ody/72†/");
put("ODY/Seafloor Debris/325+", "https://api.scryfall.com/cards/ody/325†/");
// PAL99
put("PAL99/Island/3+", "https://api.scryfall.com/cards/pal99/3†/");
// PALA
put("PALA/Ajani Vengeant/154*", "https://api.scryfall.com/cards/pala/154★/");
// PAVR
put("PAVR/Moonsilver Spear/217*", "https://api.scryfall.com/cards/pavr/217★/");
put("PAVR/Restoration Angel/32*", "https://api.scryfall.com/cards/pavr/32★/");
// PBNG
put("PBNG/Arbiter of the Ideal/31*", "https://api.scryfall.com/cards/pbng/31★/");
put("PBNG/Eater of Hope/66*", "https://api.scryfall.com/cards/pbng/66★/");
put("PBNG/Forgestoker Dragon/98*", "https://api.scryfall.com/cards/pbng/98★/");
put("PBNG/Nessian Wilds Ravager/129*", "https://api.scryfall.com/cards/pbng/129★/");
put("PBNG/Silent Sentinel/26*", "https://api.scryfall.com/cards/pbng/26★/");
put("PBNG/Tromokratis/55*", "https://api.scryfall.com/cards/pbng/55★/");
// PDGM
put("PDGM/Breaking // Entering/124*", "https://api.scryfall.com/cards/pdgm/124★/");
put("PDGM/Maze's End/152*", "https://api.scryfall.com/cards/pdgm/152★/");
put("PDGM/Plains/157*", "https://api.scryfall.com/cards/pdgm/157★/");
// PDKA
put("PDKA/Archdemon of Greed/71*", "https://api.scryfall.com/cards/pdka/71★/");
put("PDKA/Mondronen Shaman/98*", "https://api.scryfall.com/cards/pdka/98★/");
put("PDKA/Ravenous Demon/71*", "https://api.scryfall.com/cards/pdka/71★/");
put("PDKA/Tovolar's Magehunter/98*", "https://api.scryfall.com/cards/pdka/98★/");
// PGTC
put("PGTC/Consuming Aberration/152*", "https://api.scryfall.com/cards/pgtc/152★/");
put("PGTC/Fathom Mage/162*", "https://api.scryfall.com/cards/pgtc/162★/");
put("PGTC/Foundry Champion/165*", "https://api.scryfall.com/cards/pgtc/165★/");
put("PGTC/Rubblehulk/191*", "https://api.scryfall.com/cards/pgtc/191★/");
put("PGTC/Skarrg Goliath/133*", "https://api.scryfall.com/cards/pgtc/133★/");
put("PGTC/Treasury Thrull/201*", "https://api.scryfall.com/cards/pgtc/201★/");
// PLS
put("PLS/Ertai, the Corrupted/107*", "https://api.scryfall.com/cards/pls/107★/");
put("PLS/Skyship Weatherlight/133*", "https://api.scryfall.com/cards/pls/133★/");
put("PLS/Tahngarth, Talruum Hero/74*", "https://api.scryfall.com/cards/pls/74★/");
// POR
put("POR/Anaconda/158+", "https://api.scryfall.com/cards/por/158†/");
put("POR/Blaze/118+", "https://api.scryfall.com/cards/por/118†/");
put("POR/Elite Cat Warrior/163+", "https://api.scryfall.com/cards/por/163†/");
put("POR/Hand of Death/96+", "https://api.scryfall.com/cards/por/96†/");
put("POR/Monstrous Growth/173+", "https://api.scryfall.com/cards/por/173†/");
put("POR/Raging Goblin/145+", "https://api.scryfall.com/cards/por/145†/");
put("POR/Warrior's Charge/38+", "https://api.scryfall.com/cards/por/38†/");
// PISD
put("PISD/Howlpack Alpha/193*", "https://api.scryfall.com/cards/pisd/193★/");
put("PISD/Ludevic's Abomination/64*", "https://api.scryfall.com/cards/pisd/64★/");
put("PISD/Ludevic's Test Subject/64*", "https://api.scryfall.com/cards/pisd/64★/");
put("PISD/Mayor of Avabruck/193*", "https://api.scryfall.com/cards/pisd/193★/");
// PJOU
put("PJOU/Dawnbringer Charioteers/6*", "https://api.scryfall.com/cards/pjou/6★/");
put("PJOU/Dictate of the Twin Gods/93*", "https://api.scryfall.com/cards/pjou/93★/");
put("PJOU/Doomwake Giant/66*", "https://api.scryfall.com/cards/pjou/66★/");
put("PJOU/Heroes' Bane/126*", "https://api.scryfall.com/cards/pjou/126★/");
put("PJOU/Scourge of Fleets/51*", "https://api.scryfall.com/cards/pjou/51★/");
put("PJOU/Spawn of Thraxes/112*", "https://api.scryfall.com/cards/pjou/112★/");
// PL21
put("PL21/Sethron, Hurloon General/1*", "https://api.scryfall.com/cards/pl21/1★/");
// PM10
put("PM10/Ant Queen/166*", "https://api.scryfall.com/cards/pm10/166★/");
put("PM10/Honor of the Pure/16*", "https://api.scryfall.com/cards/pm10/16★/");
put("PM10/Vampire Nocturnus/118*", "https://api.scryfall.com/cards/pm10/118★/");
// PM11
put("PM11/Ancient Hellkite/122*", "https://api.scryfall.com/cards/pm11/122★/");
put("PM11/Birds of Paradise/165*", "https://api.scryfall.com/cards/pm11/165★/");
put("PM11/Sun Titan/35*", "https://api.scryfall.com/cards/pm11/35★/");
// PM12
put("PM12/Bloodlord of Vaasgoth/82*", "https://api.scryfall.com/cards/pm12/82★/");
put("PM12/Chandra's Phoenix/126*", "https://api.scryfall.com/cards/pm12/126★/");
put("PM12/Garruk's Horde/176*", "https://api.scryfall.com/cards/pm12/176★/");
// PM13
put("PM13/Cathedral of War/221*", "https://api.scryfall.com/cards/pm13/221★/");
put("PM13/Magmaquake/140*", "https://api.scryfall.com/cards/pm13/140★/");
put("PM13/Mwonvuli Beast Tracker/177*", "https://api.scryfall.com/cards/pm13/177★/");
put("PM13/Staff of Nin/217*", "https://api.scryfall.com/cards/pm13/217★/");
put("PM13/Xathrid Gorgon/118*", "https://api.scryfall.com/cards/pm13/118★/");
// PM14
put("PM14/Colossal Whale/48*", "https://api.scryfall.com/cards/pm14/48★/");
put("PM14/Goblin Diplomats/141*", "https://api.scryfall.com/cards/pm14/141★/");
put("PM14/Hive Stirrings/21*", "https://api.scryfall.com/cards/pm14/21★/");
put("PM14/Megantic Sliver/185*", "https://api.scryfall.com/cards/pm14/185★/");
put("PM14/Ratchet Bomb/215*", "https://api.scryfall.com/cards/pm14/215★/");
// PMBS
put("PMBS/Glissa, the Traitor/96*", "https://api.scryfall.com/cards/pmbs/96★/");
put("PMBS/Hero of Bladehold/8*", "https://api.scryfall.com/cards/pmbs/8★/");
put("PMBS/Thopter Assembly/140*", "https://api.scryfall.com/cards/pmbs/140★/");
// PMEI
put("PMEI/Jamuraan Lion/10*", "https://api.scryfall.com/cards/pmei/10★/");
// PNPH
put("PNPH/Phyrexian Metamorph/42*", "https://api.scryfall.com/cards/pnph/42★/");
put("PNPH/Sheoldred, Whispering One/73*", "https://api.scryfall.com/cards/pnph/73★/");
// PRES
put("PRES/Goblin Chieftain/141*", "https://api.scryfall.com/cards/pres/141★/");
put("PRES/Lathliss, Dragon Queen/149*", "https://api.scryfall.com/cards/pres/149★/");
put("PRES/Loam Lion/13*", "https://api.scryfall.com/cards/pres/13★/");
put("PRES/Oran-Rief, the Vastwood/221*", "https://api.scryfall.com/cards/pres/221★/");
// PROE
put("PROE/Emrakul, the Aeons Torn/4*", "https://api.scryfall.com/cards/proe/4★/");
put("PROE/Lord of Shatterskull Pass/156*", "https://api.scryfall.com/cards/proe/156★/");
// PRTR
put("PRTR/Archon of the Triumvirate/142*", "https://api.scryfall.com/cards/prtr/142★/");
put("PRTR/Carnival Hellsteed/147*", "https://api.scryfall.com/cards/prtr/147★/");
put("PRTR/Corpsejack Menace/152*", "https://api.scryfall.com/cards/prtr/152★/");
put("PRTR/Deadbridge Goliath/120*", "https://api.scryfall.com/cards/prtr/120★/");
put("PRTR/Grove of the Guardian/240*", "https://api.scryfall.com/cards/prtr/240★/");
put("PRTR/Hypersonic Dragon/170*", "https://api.scryfall.com/cards/prtr/170★/");
// PSDC
put("PSDC/Ajani, Caller of the Pride/1*", "https://api.scryfall.com/cards/psdc/1★/");
put("PSDC/Chandra, Pyromaster/132*", "https://api.scryfall.com/cards/psdc/132★/");
put("PSDC/Garruk, Caller of Beasts/172*", "https://api.scryfall.com/cards/psdc/172★/");
put("PSDC/Jace, Memory Adept/60*", "https://api.scryfall.com/cards/psdc/60★/");
put("PSDC/Liliana of the Dark Realms/102*", "https://api.scryfall.com/cards/psdc/102★/");
// PSOI
put("PSOI/Tamiyo's Journal/265s+", "https://api.scryfall.com/cards/psoi/265s†/");
// PSOM
put("PSOM/Steel Hellkite/205*", "https://api.scryfall.com/cards/psom/205★/");
put("PSOM/Wurmcoil Engine/223*", "https://api.scryfall.com/cards/psom/223★/");
// PTHS
put("PTHS/Abhorrent Overlord/75*", "https://api.scryfall.com/cards/pths/75★/");
put("PTHS/Anthousa, Setessan Hero/149*", "https://api.scryfall.com/cards/pths/149★/");
put("PTHS/Bident of Thassa/42*", "https://api.scryfall.com/cards/pths/42★/");
put("PTHS/Celestial Archon/3*", "https://api.scryfall.com/cards/pths/3★/");
put("PTHS/Ember Swallower/120*", "https://api.scryfall.com/cards/pths/120★/");
put("PTHS/Shipbreaker Kraken/63*", "https://api.scryfall.com/cards/pths/63★/");
// PWAR
put("PWAR/Ajani, the Greathearted/184s*", "https://api.scryfall.com/cards/pwar/184s★/");
put("PWAR/Angrath, Captain of Chaos/227s*", "https://api.scryfall.com/cards/pwar/227s★/");
put("PWAR/Arlinn, Voice of the Pack/150s*", "https://api.scryfall.com/cards/pwar/150s★/");
put("PWAR/Ashiok, Dream Render/228s*", "https://api.scryfall.com/cards/pwar/228s★/");
put("PWAR/Chandra, Fire Artisan/119s*", "https://api.scryfall.com/cards/pwar/119s★/");
put("PWAR/Davriel, Rogue Shadowmage/83s*", "https://api.scryfall.com/cards/pwar/83s★/");
put("PWAR/Domri, Anarch of Bolas/191s*", "https://api.scryfall.com/cards/pwar/191s★/");
put("PWAR/Dovin, Hand of Control/229s*", "https://api.scryfall.com/cards/pwar/229s★/");
put("PWAR/Gideon Blackblade/13s*", "https://api.scryfall.com/cards/pwar/13s★/");
put("PWAR/Huatli, the Sun's Heart/230s*", "https://api.scryfall.com/cards/pwar/230s★/");
put("PWAR/Jace, Wielder of Mysteries/54s*", "https://api.scryfall.com/cards/pwar/54s★/");
put("PWAR/Jaya, Venerated Firemage/135s*", "https://api.scryfall.com/cards/pwar/135s★/");
put("PWAR/Jiang Yanggu, Wildcrafter/164s*", "https://api.scryfall.com/cards/pwar/164s★/");
put("PWAR/Karn, the Great Creator/1s*", "https://api.scryfall.com/cards/pwar/1s★/");
put("PWAR/Kasmina, Enigmatic Mentor/56s*", "https://api.scryfall.com/cards/pwar/56s★/");
put("PWAR/Kaya, Bane of the Dead/231s*", "https://api.scryfall.com/cards/pwar/231s★/");
put("PWAR/Kiora, Behemoth Beckoner/232s*", "https://api.scryfall.com/cards/pwar/232s★/");
put("PWAR/Liliana, Dreadhorde General/97s*", "https://api.scryfall.com/cards/pwar/97s★/");
put("PWAR/Nahiri, Storm of Stone/233s*", "https://api.scryfall.com/cards/pwar/233s★/");
put("PWAR/Narset, Parter of Veils/61s*", "https://api.scryfall.com/cards/pwar/61s★/");
put("PWAR/Nicol Bolas, Dragon-God/207s*", "https://api.scryfall.com/cards/pwar/207s★/");
put("PWAR/Nissa, Who Shakes the World/169s*", "https://api.scryfall.com/cards/pwar/169s★/");
put("PWAR/Ob Nixilis, the Hate-Twisted/100s*", "https://api.scryfall.com/cards/pwar/100s★/");
put("PWAR/Ral, Storm Conduit/211s*", "https://api.scryfall.com/cards/pwar/211s★/");
put("PWAR/Saheeli, Sublime Artificer/234s*", "https://api.scryfall.com/cards/pwar/234s★/");
put("PWAR/Samut, Tyrant Smasher/235s*", "https://api.scryfall.com/cards/pwar/235s★/");
put("PWAR/Sarkhan the Masterless/143s*", "https://api.scryfall.com/cards/pwar/143s★/");
put("PWAR/Sorin, Vengeful Bloodlord/217s*", "https://api.scryfall.com/cards/pwar/217s★/");
put("PWAR/Tamiyo, Collector of Tales/220s*", "https://api.scryfall.com/cards/pwar/220s★/");
put("PWAR/Teferi, Time Raveler/221s*", "https://api.scryfall.com/cards/pwar/221s★/");
put("PWAR/Teyo, the Shieldmage/32s*", "https://api.scryfall.com/cards/pwar/32s★/");
put("PWAR/The Wanderer/37s*", "https://api.scryfall.com/cards/pwar/37s★/");
put("PWAR/Tibalt, Rakish Instigator/146s*", "https://api.scryfall.com/cards/pwar/146s★/");
put("PWAR/Ugin, the Ineffable/2s*", "https://api.scryfall.com/cards/pwar/2s★/");
put("PWAR/Vivien, Champion of the Wilds/180s*", "https://api.scryfall.com/cards/pwar/180s★/");
put("PWAR/Vraska, Swarm's Eminence/236s*", "https://api.scryfall.com/cards/pwar/236s★/");
// PWWK
put("PWWK/Comet Storm/76*", "https://api.scryfall.com/cards/pwwk/76★/");
put("PWWK/Joraga Warcaller/106*", "https://api.scryfall.com/cards/pwwk/106★/");
put("PWWK/Ruthless Cullblade/65*", "https://api.scryfall.com/cards/pwwk/65★/");
// PZEN
put("PZEN/Rampaging Baloths/178*", "https://api.scryfall.com/cards/pzen/178★/");
put("PZEN/Valakut, the Molten Pinnacle/228*", "https://api.scryfall.com/cards/pzen/228★/");
// SHM
put("SHM/Reflecting Pool/278*", "https://api.scryfall.com/cards/shm/278★/");
// SOI
put("SOI/Tamiyo's Journal/265+a", "https://api.scryfall.com/cards/soi/265†a/");
put("SOI/Tamiyo's Journal/265+b", "https://api.scryfall.com/cards/soi/265†b/");
put("SOI/Tamiyo's Journal/265+c", "https://api.scryfall.com/cards/soi/265†c/");
put("SOI/Tamiyo's Journal/265+d", "https://api.scryfall.com/cards/soi/265†d/");
put("SOI/Tamiyo's Journal/265+e", "https://api.scryfall.com/cards/soi/265†e/");
// THB
put("THB/Temple of Abandon/347*", "https://api.scryfall.com/cards/thb/347★/");
// UNH
put("UNH/Aesthetic Consultation/48*", "https://api.scryfall.com/cards/unh/48★/");
put("UNH/AWOL/2*", "https://api.scryfall.com/cards/unh/2★/");
put("UNH/Bad Ass/49*", "https://api.scryfall.com/cards/unh/49★/");
put("UNH/Blast from the Past/72*", "https://api.scryfall.com/cards/unh/72★/");
put("UNH/Cardpecker/4*", "https://api.scryfall.com/cards/unh/4★/");
put("UNH/Emcee/9*", "https://api.scryfall.com/cards/unh/9★/");
put("UNH/Farewell to Arms/56*", "https://api.scryfall.com/cards/unh/56★/");
put("UNH/Frazzled Editor/77*", "https://api.scryfall.com/cards/unh/77★/");
put("UNH/Gleemax/121*", "https://api.scryfall.com/cards/unh/121★/");
put("UNH/Goblin Mime/78*", "https://api.scryfall.com/cards/unh/78★/");
put("UNH/Greater Morphling/34*", "https://api.scryfall.com/cards/unh/34★/");
put("UNH/Keeper of the Sacred Word/101*", "https://api.scryfall.com/cards/unh/101★/");
put("UNH/Laughing Hyena/103*", "https://api.scryfall.com/cards/unh/103★/");
put("UNH/Letter Bomb/122*", "https://api.scryfall.com/cards/unh/122★/");
put("UNH/Mana Screw/123*", "https://api.scryfall.com/cards/unh/123★/");
put("UNH/Monkey Monkey Monkey/104*", "https://api.scryfall.com/cards/unh/104★/");
put("UNH/Mons's Goblin Waiters/82*", "https://api.scryfall.com/cards/unh/82★/");
put("UNH/Mox Lotus/124*", "https://api.scryfall.com/cards/unh/124★/");
put("UNH/My First Tome/125*", "https://api.scryfall.com/cards/unh/125★/");
put("UNH/Old Fogey/106*", "https://api.scryfall.com/cards/unh/106★/");
put("UNH/Question Elemental?/43*", "https://api.scryfall.com/cards/unh/43★/");
put("UNH/Richard Garfield, Ph.D./44*", "https://api.scryfall.com/cards/unh/44★/");
put("UNH/Shoe Tree/109*", "https://api.scryfall.com/cards/unh/109★/");
put("UNH/Standing Army/20*", "https://api.scryfall.com/cards/unh/20★/");
put("UNH/Time Machine/128*", "https://api.scryfall.com/cards/unh/128★/");
put("UNH/Touch and Go/90*", "https://api.scryfall.com/cards/unh/90★/");
put("UNH/When Fluffy Bunnies Attack/67*", "https://api.scryfall.com/cards/unh/67★/");
// WAR
put("WAR/Ajani, the Greathearted/184*", "https://api.scryfall.com/cards/war/184★/");
put("WAR/Angrath, Captain of Chaos/227*", "https://api.scryfall.com/cards/war/227★/");
put("WAR/Arlinn, Voice of the Pack/150*", "https://api.scryfall.com/cards/war/150★/");
put("WAR/Ashiok, Dream Render/228*", "https://api.scryfall.com/cards/war/228★/");
put("WAR/Chandra, Fire Artisan/119*", "https://api.scryfall.com/cards/war/119★/");
put("WAR/Davriel, Rogue Shadowmage/83*", "https://api.scryfall.com/cards/war/83★/");
put("WAR/Domri, Anarch of Bolas/191*", "https://api.scryfall.com/cards/war/191★/");
put("WAR/Dovin, Hand of Control/229*", "https://api.scryfall.com/cards/war/229★/");
put("WAR/Gideon Blackblade/13*", "https://api.scryfall.com/cards/war/13★/");
put("WAR/Huatli, the Sun's Heart/230*", "https://api.scryfall.com/cards/war/230★/");
put("WAR/Jace, Wielder of Mysteries/54*", "https://api.scryfall.com/cards/war/54★/");
put("WAR/Jaya, Venerated Firemage/135*", "https://api.scryfall.com/cards/war/135★/");
put("WAR/Jiang Yanggu, Wildcrafter/164*", "https://api.scryfall.com/cards/war/164★/");
put("WAR/Karn, the Great Creator/1*", "https://api.scryfall.com/cards/war/1★/");
put("WAR/Kasmina, Enigmatic Mentor/56*", "https://api.scryfall.com/cards/war/56★/");
put("WAR/Kaya, Bane of the Dead/231*", "https://api.scryfall.com/cards/war/231★/");
put("WAR/Kiora, Behemoth Beckoner/232*", "https://api.scryfall.com/cards/war/232★/");
put("WAR/Liliana, Dreadhorde General/97*", "https://api.scryfall.com/cards/war/97★/");
put("WAR/Nahiri, Storm of Stone/233*", "https://api.scryfall.com/cards/war/233★/");
put("WAR/Narset, Parter of Veils/61*", "https://api.scryfall.com/cards/war/61★/");
put("WAR/Nicol Bolas, Dragon-God/207*", "https://api.scryfall.com/cards/war/207★/");
put("WAR/Nissa, Who Shakes the World/169*", "https://api.scryfall.com/cards/war/169★/");
put("WAR/Ob Nixilis, the Hate-Twisted/100*", "https://api.scryfall.com/cards/war/100★/");
put("WAR/Ral, Storm Conduit/211*", "https://api.scryfall.com/cards/war/211★/");
put("WAR/Saheeli, Sublime Artificer/234*", "https://api.scryfall.com/cards/war/234★/");
put("WAR/Samut, Tyrant Smasher/235*", "https://api.scryfall.com/cards/war/235★/");
put("WAR/Sarkhan the Masterless/143*", "https://api.scryfall.com/cards/war/143★/");
put("WAR/Sorin, Vengeful Bloodlord/217*", "https://api.scryfall.com/cards/war/217★/");
put("WAR/Tamiyo, Collector of Tales/220*", "https://api.scryfall.com/cards/war/220★/");
put("WAR/Teferi, Time Raveler/221*", "https://api.scryfall.com/cards/war/221★/");
put("WAR/Teyo, the Shieldmage/32*", "https://api.scryfall.com/cards/war/32★/");
put("WAR/The Wanderer/37*", "https://api.scryfall.com/cards/war/37★/");
put("WAR/Tibalt, Rakish Instigator/146*", "https://api.scryfall.com/cards/war/146★/");
put("WAR/Ugin, the Ineffable/2*", "https://api.scryfall.com/cards/war/2★/");
put("WAR/Vivien, Champion of the Wilds/180*", "https://api.scryfall.com/cards/war/180★/");
put("WAR/Vraska, Swarm's Eminence/236*", "https://api.scryfall.com/cards/war/236★/");
// SLD
// fake double faced cards
put("SLD/Blightsteel Colossus/1079b", "https://api.scryfall.com/cards/sld/1079/en?format=image&face=back");
put("SLD/Doubling Cube/1080b", "https://api.scryfall.com/cards/sld/1080/en?format=image&face=back");
put("SLD/Darksteel Colossus/1081b", "https://api.scryfall.com/cards/sld/1081/en?format=image&face=back");
put("SLD/Ulamog, the Ceaseless Hunger/1122b", "https://api.scryfall.com/cards/sld/1122/en?format=image&face=back");
put("SLD/Etali, Primal Storm/1123b", "https://api.scryfall.com/cards/sld/1123/en?format=image&face=back");
put("SLD/Ghalta, Primal Hunger/1124b", "https://api.scryfall.com/cards/sld/1124/en?format=image&face=back");
put("SLD/Zndrsplt, Eye of Wisdom/379b", "https://api.scryfall.com/cards/sld/379/en?format=image&face=back");
put("SLD/Zndrsplt, Eye of Wisdom/379*", "https://api.scryfall.com/cards/sld/379★/");
put("SLD/Zndrsplt, Eye of Wisdom/379b*", "https://api.scryfall.com/cards/sld/379★/en?format=image&face=back");
put("SLD/Ajani Goldmane/1453b", "https://api.scryfall.com/cards/sld/1453/en?format=image&face=back");
put("SLD/Jace Beleren/1454b", "https://api.scryfall.com/cards/sld/1454/en?format=image&face=back");
put("SLD/Liliana Vess/1455b", "https://api.scryfall.com/cards/sld/1455/en?format=image&face=back");
put("SLD/Blightsteel Colossus/1079b", "https://api.scryfall.com/cards/sld/1079/en?format=image&face=back");
put("SLD/Chandra Nalaar/1456b", "https://api.scryfall.com/cards/sld/1456/en?format=image&face=back");
put("SLD/Darksteel Colossus/1081b", "https://api.scryfall.com/cards/sld/1081/en?format=image&face=back");
put("SLD/Doubling Cube/1080b", "https://api.scryfall.com/cards/sld/1080/en?format=image&face=back");
put("SLD/Etali, Primal Storm/1123b", "https://api.scryfall.com/cards/sld/1123/en?format=image&face=back");
put("SLD/Garruk Wildspeaker/1457b", "https://api.scryfall.com/cards/sld/1457/en?format=image&face=back");
put("SLD/Ghalta, Primal Hunger/1124b", "https://api.scryfall.com/cards/sld/1124/en?format=image&face=back");
put("SLD/Jace Beleren/1454b", "https://api.scryfall.com/cards/sld/1454/en?format=image&face=back");
put("SLD/Krark's Thumb/383b", "https://api.scryfall.com/cards/sld/383/en?format=image&face=back");
put("SLD/Liliana Vess/1455b", "https://api.scryfall.com/cards/sld/1455/en?format=image&face=back");
put("SLD/Okaun, Eye of Chaos/380b", "https://api.scryfall.com/cards/sld/380/en?format=image&face=back");
put("SLD/Okaun, Eye of Chaos/380*", "https://api.scryfall.com/cards/sld/380★/");
put("SLD/Okaun, Eye of Chaos/380b*", "https://api.scryfall.com/cards/sld/380★/en?format=image&face=back");
put("SLD/Propaganda/381b", "https://api.scryfall.com/cards/sld/381/en?format=image&face=back");
put("SLD/Stitch in Time/382b", "https://api.scryfall.com/cards/sld/382/en?format=image&face=back");
put("SLD/Krark's Thumb/383b", "https://api.scryfall.com/cards/sld/383/en?format=image&face=back");
put("SLD/Ulamog, the Ceaseless Hunger/1122b", "https://api.scryfall.com/cards/sld/1122/en?format=image&face=back");
put("SLD/Zndrsplt, Eye of Wisdom/379b", "https://api.scryfall.com/cards/sld/379/en?format=image&face=back");
put("SLD/Zndrsplt, Eye of Wisdom/379b*", "https://api.scryfall.com/cards/sld/379★/en?format=image&face=back");
// normal cards
put("SLD/Demonlord Belzenlok/159*", "https://api.scryfall.com/cards/sld/159★/");
put("SLD/Griselbrand/160*", "https://api.scryfall.com/cards/sld/160★/");
put("SLD/Kothophed, Soul Hoarder/162*", "https://api.scryfall.com/cards/sld/162★/");
put("SLD/Liliana's Contract/161*", "https://api.scryfall.com/cards/sld/161★/");
put("SLD/Razaketh, the Foulblooded/163*", "https://api.scryfall.com/cards/sld/163★/");
put("SLD/Goblin Lackey/1311*", "https://api.scryfall.com/cards/sld/1311★/");
put("SLD/Goblin Matron/1312*", "https://api.scryfall.com/cards/sld/1312★/");
put("SLD/Muxus, Goblin Grandee/1314*", "https://api.scryfall.com/cards/sld/1314★/");
put("SLD/Goblin Recruiter/1313*", "https://api.scryfall.com/cards/sld/1313★/");
put("SLD/Plague Sliver/633Ph", "https://api.scryfall.com/cards/sld/633Φ/");
put("SLD/Shadowborn Apostle/681Ph", "https://api.scryfall.com/cards/sld/681Φ/");
put("SLD/Toxin Sliver/635Ph", "https://api.scryfall.com/cards/sld/635Φ/");
put("SLD/Shattergang Brothers/1315*", "https://api.scryfall.com/cards/sld/1315★/");
put("SLD/Virulent Sliver/659Ph", "https://api.scryfall.com/cards/sld/659Φ/");
put("SLD/Viscera Seer/99999VS", "https://api.scryfall.com/cards/sld/VS/"); // see issue 11157
// CALC - custom alchemy version of cards.
put("CALC/C-Pillar of the Paruns", "https://api.scryfall.com/cards/dis/176/");
@ -1058,17 +629,11 @@ public class ScryfallImageSupportCards {
put("LTR/The One Ring/001", "https://api.scryfall.com/cards/ltr/0/");
// REX - double faced lands (xmage uses two diff lands for it)
put("REX/Command Tower/26", "https://api.scryfall.com/cards/rex/26/en?format=image");
put("REX/Command Tower/26b", "https://api.scryfall.com/cards/rex/26/en?format=image&face=back");
put("REX/Forest/25", "https://api.scryfall.com/cards/rex/25/en?format=image");
put("REX/Forest/25b", "https://api.scryfall.com/cards/rex/25/en?format=image&face=back");
put("REX/Island/22", "https://api.scryfall.com/cards/rex/22/en?format=image");
put("REX/Island/22b", "https://api.scryfall.com/cards/rex/22/en?format=image&face=back");
put("REX/Mountain/24", "https://api.scryfall.com/cards/rex/24/en?format=image");
put("REX/Mountain/24b", "https://api.scryfall.com/cards/rex/24/en?format=image&face=back");
put("REX/Plains/21", "https://api.scryfall.com/cards/rex/21/en?format=image");
put("REX/Plains/21b", "https://api.scryfall.com/cards/rex/21/en?format=image&face=back");
put("REX/Swamp/23", "https://api.scryfall.com/cards/rex/23/en?format=image");
put("REX/Swamp/23b", "https://api.scryfall.com/cards/rex/23/en?format=image&face=back");
}
};
@ -1098,6 +663,19 @@ public class ScryfallImageSupportCards {
return null;
}
public static String prepareCardNumber(String xmageCardNumber) {
if (xmageCardNumber.endsWith("*")) {
return xmageCardNumber.substring(0 , xmageCardNumber.length() -1) + "" ;
}
if (xmageCardNumber.endsWith("+")) {
return xmageCardNumber.substring(0 , xmageCardNumber.length() -1) + "" ;
}
if (xmageCardNumber.endsWith("Ph")) {
return xmageCardNumber.substring(0 , xmageCardNumber.length() -2) + "Φ" ;
}
return xmageCardNumber;
}
public static String findDirectDownloadLink(String setCode, String cardName, String cardNumber) {
String key = findDirectDownloadKey(setCode, cardName, cardNumber);
return directDownloadLinks.get(key);