Merge pull request #5818 from rafaeldamasceno/scryfall-improvements

Scryfall improvements
This commit is contained in:
Oleg Agafonov 2019-05-28 23:06:21 +02:00 committed by GitHub
commit 50e5a3e050
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 212 additions and 103 deletions

View file

@ -1,11 +1,22 @@
package org.mage.plugins.card.dl.sources; package org.mage.plugins.card.dl.sources;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import mage.cards.ExpansionSet;
import mage.cards.Sets;
import mage.client.util.CardLanguage; import mage.client.util.CardLanguage;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.mage.plugins.card.dl.DownloadServiceInfo; import org.mage.plugins.card.dl.DownloadServiceInfo;
import org.mage.plugins.card.images.CardDownloadData; import org.mage.plugins.card.images.CardDownloadData;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Proxy; import java.net.Proxy;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.*; import java.util.*;
/** /**
@ -70,29 +81,34 @@ public enum ScryfallImageSource implements CardImageSource {
alternativeUrl = null; alternativeUrl = null;
} }
// special card number like "103a" and "U123" already compatible // art variation cards
if (baseUrl == null && card.isCollectorIdWithStr()) { // ARN and POR use notation
// WARNING, after 2018 it's not compatible and some new sets have GUID files instead card numbers // PLS uses notation
// TODO: replace card number links to API calls (need test with lands, alternative images and double faces), replace not working images by direct links if (baseUrl == null && card.getUsesVariousArt() && card.getSet().matches("ARN|POR|PLS")) {
String scryfallCollectorId = card.getCollectorIdAsInt().toString();
if (card.getCollectorId().startsWith("U") || card.getCollectorIdAsInt() == -1) { if (card.getCollectorId().endsWith("b")) {
// fix for Ultimate Box Topper (PUMA) and Mythic Edition (MED) -- need to use API if (card.getSet().matches("ARN|POR")) {
// ignored and go to API call at the end scryfallCollectorId += "";
} else { } else if (card.getSet().matches("PLS")) {
baseUrl = "https://img.scryfall.com/cards/large/" + localizedCode + "/" + formatSetName(card.getSet(), isToken) + "/" scryfallCollectorId += "";
+ card.getCollectorId() + ".jpg"; }
alternativeUrl = "https://img.scryfall.com/cards/large/" + defaultCode + "/" + formatSetName(card.getSet(), isToken) + "/"
+ card.getCollectorId() + ".jpg";
} }
baseUrl = "https://api.scryfall.com/cards/" + formatSetName(card.getSet(), isToken) + "/"
+ scryfallCollectorId + "/" + localizedCode + "?format=image";
alternativeUrl = "https://api.scryfall.com/cards/" + formatSetName(card.getSet(), isToken) + "/"
+ scryfallCollectorId + "/" + defaultCode + "?format=image";
} }
// double faced cards do not supports by API (need direct link for img) // double faced card
// example: https://img.scryfall.com/cards/large/en/xln/173b.jpg // the front face can be downloaded normally
if (baseUrl == null && card.isTwoFacedCard()) { // the back face is prepared beforehand
baseUrl = "https://img.scryfall.com/cards/large/" + localizedCode + "/" + formatSetName(card.getSet(), isToken) + "/" if (baseUrl == null && card.isTwoFacedCard() && !card.isSecondSide()) {
+ card.getCollectorId() + (card.isSecondSide() ? "b" : "a") + ".jpg"; baseUrl = "https://api.scryfall.com/cards/" + formatSetName(card.getSet(), isToken) + "/"
alternativeUrl = "https://img.scryfall.com/cards/large/" + defaultCode + "/" + formatSetName(card.getSet(), isToken) + "/" + card.getCollectorIdAsInt() + "/" + localizedCode + "?format=image";
+ card.getCollectorId() + (card.isSecondSide() ? "b" : "a") + ".jpg"; alternativeUrl = "https://api.scryfall.com/cards/" + formatSetName(card.getSet(), isToken) + "/"
+ card.getCollectorIdAsInt() + "/" + defaultCode + "?format=image";
} }
// basic cards by api call (redirect to img link) // basic cards by api call (redirect to img link)
@ -107,21 +123,92 @@ public enum ScryfallImageSource implements CardImageSource {
return new CardImageUrls(baseUrl, alternativeUrl); return new CardImageUrls(baseUrl, alternativeUrl);
} }
private String getFaceImageUrl(Proxy proxy, CardDownloadData card, boolean isToken, String localizationCode) throws Exception {
// connect to Scryfall API
final URL cardUrl = new URL("https://api.scryfall.com/cards/" + formatSetName(card.getSet(), isToken) + "/"
+ (card.getCollectorIdAsInt() % 1000) + "/" + localizationCode);
URLConnection request = proxy == null ? cardUrl.openConnection() : cardUrl.openConnection(proxy);
request.connect();
// parse the response and return the image URI from the correct card face
JsonParser jp = new JsonParser();
JsonElement root = jp.parse(new InputStreamReader((InputStream) request.getContent()));
JsonObject jsonCard = root.getAsJsonObject();
if (!jsonCard.has("card_faces")) {
throw new Exception("Couldn't find card_faces in Card JSON.");
}
JsonArray jsonCardFaces = jsonCard.getAsJsonArray("card_faces");
JsonObject jsonCardFace = jsonCardFaces.get(card.isSecondSide() ? 1 : 0).getAsJsonObject();
JsonObject jsonImageUris = jsonCardFace.getAsJsonObject("image_uris");
return jsonImageUris.get("large").getAsString();
}
@Override @Override
public boolean prepareDownloadList(DownloadServiceInfo downloadServiceInfo, List<CardDownloadData> downloadList) { public boolean prepareDownloadList(DownloadServiceInfo downloadServiceInfo, List<CardDownloadData> downloadList) {
// prepare download list example ( // prepare download list example (
Proxy proxy = downloadServiceInfo.getProxy(); Proxy proxy = downloadServiceInfo.getProxy();
preparedUrls.clear(); preparedUrls.clear();
final List<ExpansionSet.SetCardInfo> sixthEditionCards = Sets.findSet("6ED").getSetCardInfo();
for (CardDownloadData card : downloadList) { for (CardDownloadData card : downloadList) {
// need cancel // need cancel
if (downloadServiceInfo.isNeedCancel()) { if (downloadServiceInfo.isNeedCancel()) {
return false; return false;
} }
// TODO: download faces info here // prepare the back face URL
if (card.isTwoFacedCard()) { if (card.isTwoFacedCard() && card.isSecondSide()) {
final String defaultCode = CardLanguage.ENGLISH.getCode();
final String localizedCode = languageAliases.getOrDefault(this.getCurrentLanguage(), defaultCode);
String url = null; String url = null;
try {
url = getFaceImageUrl(proxy, card, card.isToken(), localizedCode);
} catch (Exception e) {
logger.warn("Failed to prepare image URL for " + card.getName() + " (" + card.getSet() + ") #" + card.getCollectorId());
downloadServiceInfo.incErrorCount();
continue;
}
preparedUrls.put(card, url);
}
// if a S00 card is in 6ED, it's actually a 6ED card
if (card.getSet().equals("S00") && sixthEditionCards.stream().anyMatch(sixthEditionCard -> sixthEditionCard.getName().equals(card.getName()))) {
// we have direct links for the lands because there are multiple search results
if (card.getUsesVariousArt()) { // lands are the only defined multiple art cards in S00 in XMage
continue;
}
String url = null;
try {
url = searchCard(proxy, "6ED", card.getName());
} catch (Exception e) {
logger.warn("Failed to prepare image URL for " + card.getName() + " (" + card.getSet() + ") #" + card.getCollectorId());
downloadServiceInfo.incErrorCount();
continue;
}
preparedUrls.put(card, url);
}
// if an E01 card number is above 106, it's actually an AKH card
if (card.getSet().equals("E01") && card.getCollectorIdAsInt() > 106) {
String url = null;
try {
url = searchCard(proxy, "AKH", card.getName());
} catch (Exception e) {
logger.warn("Failed to prepare image URL for " + card.getName() + " (" + card.getSet() + ") #" + card.getCollectorId());
downloadServiceInfo.incErrorCount();
continue;
}
preparedUrls.put(card, url); preparedUrls.put(card, url);
} }
@ -132,6 +219,24 @@ public enum ScryfallImageSource implements CardImageSource {
return true; return true;
} }
private String searchCard(Proxy proxy, String set, String name) throws Exception {
final URL searchUrl = new URL("https://api.scryfall.com/cards/search?q=s:" + URLEncoder.encode(set + " " + name, "UTF-8"));
URLConnection request = proxy == null ? searchUrl.openConnection() : searchUrl.openConnection(proxy);
request.connect();
// parse the response and return the image URI from the correct card face
JsonParser jp = new JsonParser();
JsonElement root = jp.parse(new InputStreamReader((InputStream) request.getContent()));
JsonObject searchResult = root.getAsJsonObject();
if (searchResult.get("total_cards").getAsInt() != 1) {
throw new Exception("Card not found in Scryfall.");
}
JsonObject jsonCard = searchResult.getAsJsonArray("data").get(0).getAsJsonObject();
JsonObject jsonImageUris = jsonCard.getAsJsonObject("image_uris");
return jsonImageUris.get("large").getAsString();
}
@Override @Override
public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception {
return innerGenerateURL(card, false); return innerGenerateURL(card, false);

View file

@ -267,104 +267,109 @@ public class ScryfallImageSupportCards {
// Duels of the Planeswalkers Promos -- xmage uses one set (DPAP), but scryfall store it by years // Duels of the Planeswalkers Promos -- xmage uses one set (DPAP), but scryfall store it by years
// 2009 - https://scryfall.com/sets/pdtp // 2009 - https://scryfall.com/sets/pdtp
put("DPAP/Garruk Wildspeaker", "https://img.scryfall.com/cards/large/en/pdtp/1.jpg"); put("DPAP/Garruk Wildspeaker", "https://api.scryfall.com/cards/pdtp/1/en?format=image");
// 2010 - https://scryfall.com/sets/pdp10 // 2010 - https://scryfall.com/sets/pdp10
put("DPAP/Liliana Vess", "https://img.scryfall.com/cards/large/en/pdp10/1.jpg"); put("DPAP/Liliana Vess", "https://api.scryfall.com/cards/pdp10/1/en?format=image");
put("DPAP/Nissa Revane", "https://img.scryfall.com/cards/large/en/pdp10/2.jpg"); put("DPAP/Nissa Revane", "https://api.scryfall.com/cards/pdp10/2/en?format=image");
// 2011 - https://scryfall.com/sets/pdp11 // 2011 - https://scryfall.com/sets/pdp11
put("DPAP/Frost Titan", "https://img.scryfall.com/cards/large/en/pdp11/1.jpg"); put("DPAP/Frost Titan", "https://api.scryfall.com/cards/pdp11/1/en?format=image");
put("DPAP/Grave Titan", "https://img.scryfall.com/cards/large/en/pdp11/2.jpg"); put("DPAP/Grave Titan", "https://api.scryfall.com/cards/pdp11/2/en?format=image");
put("DPAP/Inferno Titan", "https://img.scryfall.com/cards/large/en/pdp11/3.jpg"); put("DPAP/Inferno Titan", "https://api.scryfall.com/cards/pdp11/3/en?format=image");
// 2012 - https://scryfall.com/sets/pdp12 // 2012 - https://scryfall.com/sets/pdp12
put("DPAP/Primordial Hydra", "https://img.scryfall.com/cards/large/en/pdp12/1.jpg"); put("DPAP/Primordial Hydra", "https://api.scryfall.com/cards/pdp12/1/en?format=image");
put("DPAP/Serra Avatar", "https://img.scryfall.com/cards/large/en/pdp12/2.jpg"); put("DPAP/Serra Avatar", "https://api.scryfall.com/cards/pdp12/2/en?format=image");
put("DPAP/Vampire Nocturnus", "https://img.scryfall.com/cards/large/en/pdp12/3.jpg"); put("DPAP/Vampire Nocturnus", "https://api.scryfall.com/cards/pdp12/3/en?format=image");
// 2013 - https://scryfall.com/sets/pdp13 // 2013 - https://scryfall.com/sets/pdp13
put("DPAP/Bonescythe Sliver", "https://img.scryfall.com/cards/large/en/pdp13/1.jpg"); put("DPAP/Bonescythe Sliver", "https://api.scryfall.com/cards/pdp13/1/en?format=image");
put("DPAP/Ogre Battledriver", "https://img.scryfall.com/cards/large/en/pdp13/2.jpg"); put("DPAP/Ogre Battledriver", "https://api.scryfall.com/cards/pdp13/2/en?format=image");
put("DPAP/Scavenging Ooze", "https://img.scryfall.com/cards/large/en/pdp13/3.jpg"); put("DPAP/Scavenging Ooze", "https://api.scryfall.com/cards/pdp13/3/en?format=image");
// 2014 - https://scryfall.com/sets/pdp14 // 2014 - https://scryfall.com/sets/pdp14
put("DPAP/Soul of Ravnica", "https://img.scryfall.com/cards/large/en/pdp14/1.jpg"); put("DPAP/Soul of Ravnica", "https://api.scryfall.com/cards/pdp14/1/en?format=image");
put("DPAP/Soul of Zendikar", "https://img.scryfall.com/cards/large/en/pdp14/2.jpg"); put("DPAP/Soul of Zendikar", "https://api.scryfall.com/cards/pdp14/2/en?format=image");
// Gateway Promos -- xmage uses one set (GRC), but scryfall store it by years // Gateway Promos -- xmage uses one set (GRC), but scryfall store it by years
// 2006 - https://scryfall.com/sets/pgtw // 2006 - https://scryfall.com/sets/pgtw
put("GRC/Fiery Temper", "https://img.scryfall.com/cards/large/en/pgtw/3.jpg"); put("GRC/Fiery Temper", "https://api.scryfall.com/cards/pgtw/3/en?format=image");
put("GRC/Icatian Javelineers", "https://img.scryfall.com/cards/large/en/pgtw/2.jpg"); put("GRC/Icatian Javelineers", "https://api.scryfall.com/cards/pgtw/2/en?format=image");
put("GRC/Wood Elves", "https://img.scryfall.com/cards/large/en/pgtw/1.jpg"); put("GRC/Wood Elves", "https://api.scryfall.com/cards/pgtw/1/en?format=image");
// 2007 - https://scryfall.com/sets/pg07 // 2007 - https://scryfall.com/sets/pg07
put("GRC/Boomerang", "https://img.scryfall.com/cards/large/en/pg07/4.jpg"); put("GRC/Boomerang", "https://api.scryfall.com/cards/pg07/4/en?format=image");
put("GRC/Calciderm", "https://img.scryfall.com/cards/large/en/pg07/5.jpg"); put("GRC/Calciderm", "https://api.scryfall.com/cards/pg07/5/en?format=image");
put("GRC/Dauntless Dourbark", "https://img.scryfall.com/cards/large/en/pg07/12.jpg"); put("GRC/Dauntless Dourbark", "https://api.scryfall.com/cards/pg07/12/en?format=image");
put("GRC/Llanowar Elves", "https://img.scryfall.com/cards/large/en/pg07/9.jpg"); put("GRC/Llanowar Elves", "https://api.scryfall.com/cards/pg07/9/en?format=image");
put("GRC/Mind Stone", "https://img.scryfall.com/cards/large/en/pg07/11.jpg"); put("GRC/Mind Stone", "https://api.scryfall.com/cards/pg07/11/en?format=image");
put("GRC/Mogg Fanatic", "https://img.scryfall.com/cards/large/en/pg07/10.jpg"); put("GRC/Mogg Fanatic", "https://api.scryfall.com/cards/pg07/10/en?format=image");
put("GRC/Reckless Wurm", "https://img.scryfall.com/cards/large/en/pg07/6.jpg"); put("GRC/Reckless Wurm", "https://api.scryfall.com/cards/pg07/6/en?format=image");
put("GRC/Yixlid Jailer", "https://img.scryfall.com/cards/large/en/pg07/7.jpg"); put("GRC/Yixlid Jailer", "https://api.scryfall.com/cards/pg07/7/en?format=image");
put("GRC/Zoetic Cavern", "https://img.scryfall.com/cards/large/en/pg07/8.jpg"); put("GRC/Zoetic Cavern", "https://api.scryfall.com/cards/pg07/8/en?format=image");
// 2008a - https://scryfall.com/sets/pg08 // 2008a - https://scryfall.com/sets/pg08
put("GRC/Boggart Ram-Gang", "https://img.scryfall.com/cards/large/en/pg08/17.jpg"); put("GRC/Boggart Ram-Gang", "https://api.scryfall.com/cards/pg08/17/en?format=image");
put("GRC/Cenn's Tactician", "https://img.scryfall.com/cards/large/en/pg08/14.jpg"); put("GRC/Cenn's Tactician", "https://api.scryfall.com/cards/pg08/14/en?format=image");
put("GRC/Duergar Hedge-Mage", "https://img.scryfall.com/cards/large/en/pg08/19.jpg"); put("GRC/Duergar Hedge-Mage", "https://api.scryfall.com/cards/pg08/19/en?format=image");
put("GRC/Gravedigger", "https://img.scryfall.com/cards/large/en/pg08/16.jpg"); put("GRC/Gravedigger", "https://api.scryfall.com/cards/pg08/16/en?format=image");
put("GRC/Lava Axe", "https://img.scryfall.com/cards/large/en/pg08/13.jpg"); put("GRC/Lava Axe", "https://api.scryfall.com/cards/pg08/13/en?format=image");
put("GRC/Oona's Blackguard", "https://img.scryfall.com/cards/large/en/pg08/15.jpg"); put("GRC/Oona's Blackguard", "https://api.scryfall.com/cards/pg08/15/en?format=image");
put("GRC/Selkie Hedge-Mage", "https://img.scryfall.com/cards/large/en/pg08/20.jpg"); put("GRC/Selkie Hedge-Mage", "https://api.scryfall.com/cards/pg08/20/en?format=image");
put("GRC/Wilt-Leaf Cavaliers", "https://img.scryfall.com/cards/large/en/pg08/18.jpg"); put("GRC/Wilt-Leaf Cavaliers", "https://api.scryfall.com/cards/pg08/18/en?format=image");
// Wizards Play Network Promos -- xmage uses one set (GRC), but scryfall store it by years // Wizards Play Network Promos -- xmage uses one set (GRC), but scryfall store it by years
// 2008b - https://scryfall.com/sets/pwpn // 2008b - https://scryfall.com/sets/pwpn
put("GRC/Sprouting Thrinax", "https://img.scryfall.com/cards/large/en/pwpn/21.jpg"); put("GRC/Sprouting Thrinax", "https://api.scryfall.com/cards/pwpn/21/en?format=image");
put("GRC/Woolly Thoctar", "https://img.scryfall.com/cards/large/en/pwpn/22.jpg"); put("GRC/Woolly Thoctar", "https://api.scryfall.com/cards/pwpn/22/en?format=image");
// 2009 - https://scryfall.com/sets/pwp09 // 2009 - https://scryfall.com/sets/pwp09
put("GRC/Hellspark Elemental", "https://img.scryfall.com/cards/large/en/pwp09/25.jpg"); put("GRC/Hellspark Elemental", "https://api.scryfall.com/cards/pwp09/25/en?format=image");
put("GRC/Kor Duelist", "https://img.scryfall.com/cards/large/en/pwp09/32.jpg"); put("GRC/Kor Duelist", "https://api.scryfall.com/cards/pwp09/32/en?format=image");
put("GRC/Marisi's Twinclaws", "https://img.scryfall.com/cards/large/en/pwp09/26.jpg"); put("GRC/Marisi's Twinclaws", "https://api.scryfall.com/cards/pwp09/26/en?format=image");
put("GRC/Mind Control", "https://img.scryfall.com/cards/large/en/pwp09/30.jpg"); put("GRC/Mind Control", "https://api.scryfall.com/cards/pwp09/30/en?format=image");
put("GRC/Path to Exile", "https://img.scryfall.com/cards/large/en/pwp09/24.jpg"); put("GRC/Path to Exile", "https://api.scryfall.com/cards/pwp09/24/en?format=image");
put("GRC/Rise from the Grave", "https://img.scryfall.com/cards/large/en/pwp09/31.jpg"); put("GRC/Rise from the Grave", "https://api.scryfall.com/cards/pwp09/31/en?format=image");
put("GRC/Slave of Bolas", "https://img.scryfall.com/cards/large/en/pwp09/27.jpg"); put("GRC/Slave of Bolas", "https://api.scryfall.com/cards/pwp09/27/en?format=image");
put("GRC/Vampire Nighthawk", "https://img.scryfall.com/cards/large/en/pwp09/33.jpg"); put("GRC/Vampire Nighthawk", "https://api.scryfall.com/cards/pwp09/33/en?format=image");
// 2010 - https://scryfall.com/sets/pwp10 // 2010 - https://scryfall.com/sets/pwp10
put("GRC/Kor Firewalker", "https://img.scryfall.com/cards/large/en/pwp10/36.jpg"); put("GRC/Kor Firewalker", "https://api.scryfall.com/cards/pwp10/36/en?format=image");
put("GRC/Leatherback Baloth", "https://img.scryfall.com/cards/large/en/pwp10/37.jpg"); put("GRC/Leatherback Baloth", "https://api.scryfall.com/cards/pwp10/37/en?format=image");
put("GRC/Syphon Mind", "https://img.scryfall.com/cards/large/en/pwp10/40.jpg"); put("GRC/Syphon Mind", "https://api.scryfall.com/cards/pwp10/40/en?format=image");
put("GRC/Pathrazer of Ulamog", "https://img.scryfall.com/cards/large/en/pwp10/46.jpg"); put("GRC/Pathrazer of Ulamog", "https://api.scryfall.com/cards/pwp10/46/en?format=image");
put("GRC/Curse of Wizardry", "https://img.scryfall.com/cards/large/en/pwp10/47.jpg"); put("GRC/Curse of Wizardry", "https://api.scryfall.com/cards/pwp10/47/en?format=image");
put("GRC/Fling/50", "https://img.scryfall.com/cards/large/en/pwp10/50.jpg"); // same card but different year put("GRC/Fling/50", "https://api.scryfall.com/cards/pwp10/50/en?format=image"); // same card but different year
put("GRC/Sylvan Ranger/51", "https://img.scryfall.com/cards/large/en/pwp10/51.jpg"); // same card but different year put("GRC/Sylvan Ranger/51", "https://api.scryfall.com/cards/pwp10/51/en?format=image"); // same card but different year
put("GRC/Plague Stinger", "https://img.scryfall.com/cards/large/en/pwp10/59.jpg"); put("GRC/Plague Stinger", "https://api.scryfall.com/cards/pwp10/59/en?format=image");
put("GRC/Golem's Heart", "https://img.scryfall.com/cards/large/en/pwp10/60.jpg"); put("GRC/Golem's Heart", "https://api.scryfall.com/cards/pwp10/60/en?format=image");
put("GRC/Skinrender", "https://img.scryfall.com/cards/large/en/pwp10/63.jpg"); put("GRC/Skinrender", "https://api.scryfall.com/cards/pwp10/63/en?format=image");
// 2011 - https://scryfall.com/sets/pwp11 // 2011 - https://scryfall.com/sets/pwp11
put("GRC/Auramancer", "https://img.scryfall.com/cards/large/en/pwp11/77.jpg"); put("GRC/Auramancer", "https://api.scryfall.com/cards/pwp11/77/en?format=image");
put("GRC/Bloodcrazed Neonate", "https://img.scryfall.com/cards/large/en/pwp11/83.jpg"); put("GRC/Bloodcrazed Neonate", "https://api.scryfall.com/cards/pwp11/83/en?format=image");
put("GRC/Boneyard Wurm", "https://img.scryfall.com/cards/large/en/pwp11/84.jpg"); put("GRC/Boneyard Wurm", "https://api.scryfall.com/cards/pwp11/84/en?format=image");
put("GRC/Circle of Flame", "https://img.scryfall.com/cards/large/en/pwp11/78.jpg"); put("GRC/Circle of Flame", "https://api.scryfall.com/cards/pwp11/78/en?format=image");
put("GRC/Curse of the Bloody Tome", "https://img.scryfall.com/cards/large/en/pwp11/80.jpg"); put("GRC/Curse of the Bloody Tome", "https://api.scryfall.com/cards/pwp11/80/en?format=image");
put("GRC/Fling/69", "https://img.scryfall.com/cards/large/en/pwp11/69.jpg"); // same card but different year put("GRC/Fling/69", "https://api.scryfall.com/cards/pwp11/69/en?format=image"); // same card but different year
put("GRC/Master's Call", "https://img.scryfall.com/cards/large/en/pwp11/64.jpg"); put("GRC/Master's Call", "https://api.scryfall.com/cards/pwp11/64/en?format=image");
put("GRC/Maul Splicer", "https://img.scryfall.com/cards/large/en/pwp11/72.jpg"); put("GRC/Maul Splicer", "https://api.scryfall.com/cards/pwp11/72/en?format=image");
put("GRC/Plague Myr", "https://img.scryfall.com/cards/large/en/pwp11/65.jpg"); put("GRC/Plague Myr", "https://api.scryfall.com/cards/pwp11/65/en?format=image");
put("GRC/Shrine of Burning Rage", "https://img.scryfall.com/cards/large/en/pwp11/73.jpg"); put("GRC/Shrine of Burning Rage", "https://api.scryfall.com/cards/pwp11/73/en?format=image");
put("GRC/Signal Pest", "https://img.scryfall.com/cards/large/en/pwp11/66.jpg"); put("GRC/Signal Pest", "https://api.scryfall.com/cards/pwp11/66/en?format=image");
put("GRC/Sylvan Ranger/70", "https://img.scryfall.com/cards/large/en/pwp11/70.jpg"); // same card but different year put("GRC/Sylvan Ranger/70", "https://api.scryfall.com/cards/pwp11/70/en?format=image"); // same card but different year
put("GRC/Tormented Soul", "https://img.scryfall.com/cards/large/en/pwp11/76.jpg"); put("GRC/Tormented Soul", "https://api.scryfall.com/cards/pwp11/76/en?format=image");
put("GRC/Vault Skirge", "https://img.scryfall.com/cards/large/en/pwp11/71.jpg"); put("GRC/Vault Skirge", "https://api.scryfall.com/cards/pwp11/71/en?format=image");
// 2012 - https://scryfall.com/sets/pwp12 // 2012 - https://scryfall.com/sets/pwp12
put("GRC/Curse of Thirst", "https://img.scryfall.com/cards/large/en/pwp12/81.jpg"); put("GRC/Curse of Thirst", "https://api.scryfall.com/cards/pwp12/81/en?format=image");
put("GRC/Gather the Townsfolk", "https://img.scryfall.com/cards/large/en/pwp12/79.jpg"); put("GRC/Gather the Townsfolk", "https://api.scryfall.com/cards/pwp12/79/en?format=image");
put("GRC/Nearheath Stalker", "https://img.scryfall.com/cards/large/en/pwp12/82.jpg"); put("GRC/Nearheath Stalker", "https://api.scryfall.com/cards/pwp12/82/en?format=image");
// TODO: remove Grand Prix fix after scryfall fix image's link (that's link must be work: https://img.scryfall.com/cards/large/en/pgpx/2016b.jpg ) // Spined Wurm print in Starter 2000 is actually from Magazine Inserts
put("GPX/Sword of Feast and Famine", "https://img.scryfall.com/cards/large/en/pgpx/1%E2%98%85.jpg"); put("S00/Spined Wurm", "https://api.scryfall.com/cards/pmei/11/en?format=image");
// Most of the other S00 cards are from 6ED
// TODO: remove after scryfall add lands to RNA (that's link must works: https://api.scryfall.com/cards/rna/262/en?format=image) // We'll download lands manually because we have multiple arts and XMage has totally different ID's
put("RNA/Plains", "https://api.scryfall.com/cards/grn/260/en?format=image"); put("S00/Forest/49", "https://api.scryfall.com/cards/6ed/347/en?format=image");
put("RNA/Island", "https://api.scryfall.com/cards/grn/261/en?format=image"); put("S00/Forest/50", "https://api.scryfall.com/cards/6ed/348/en?format=image");
put("RNA/Swamp", "https://api.scryfall.com/cards/grn/262/en?format=image"); put("S00/Island/51", "https://api.scryfall.com/cards/6ed/335/en?format=image");
put("RNA/Mountain", "https://api.scryfall.com/cards/grn/263/en?format=image"); put("S00/Island/52", "https://api.scryfall.com/cards/6ed/336/en?format=image");
put("RNA/Forest", "https://api.scryfall.com/cards/grn/264/en?format=image"); put("S00/Mountain/53", "https://api.scryfall.com/cards/6ed/343/en?format=image");
put("S00/Mountain/54", "https://api.scryfall.com/cards/6ed/344/en?format=image");
put("S00/Plains/55", "https://api.scryfall.com/cards/6ed/331/en?format=image");
put("S00/Plains/56", "https://api.scryfall.com/cards/6ed/332/en?format=image");
put("S00/Swamp/57", "https://api.scryfall.com/cards/6ed/339/en?format=image");
put("S00/Swamp/58", "https://api.scryfall.com/cards/6ed/340/en?format=image");
} }
}; };

View file

@ -30,7 +30,6 @@ public final class FromTheVaultTransform extends ExpansionSet {
cards.add(new SetCardInfo("Lord of Lineage", "4b", Rarity.MYTHIC, mage.cards.l.LordOfLineage.class)); cards.add(new SetCardInfo("Lord of Lineage", "4b", Rarity.MYTHIC, mage.cards.l.LordOfLineage.class));
cards.add(new SetCardInfo("Bruna, the Fading Light", "5a", Rarity.MYTHIC, mage.cards.b.BrunaTheFadingLight.class)); cards.add(new SetCardInfo("Bruna, the Fading Light", "5a", Rarity.MYTHIC, mage.cards.b.BrunaTheFadingLight.class));
cards.add(new SetCardInfo("Brisela, Voice of Nightmares", "5b", Rarity.MYTHIC, mage.cards.b.BriselaVoiceOfNightmares.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Brisela, Voice of Nightmares", "5b", Rarity.MYTHIC, mage.cards.b.BriselaVoiceOfNightmares.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Brisela, Voice of Nightmares", "5c", Rarity.MYTHIC, mage.cards.b.BriselaVoiceOfNightmares.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Chandra, Fire of Kaladesh", "6a", Rarity.MYTHIC, mage.cards.c.ChandraFireOfKaladesh.class)); cards.add(new SetCardInfo("Chandra, Fire of Kaladesh", "6a", Rarity.MYTHIC, mage.cards.c.ChandraFireOfKaladesh.class));
cards.add(new SetCardInfo("Chandra, Roaring Flame", "6b", Rarity.MYTHIC, mage.cards.c.ChandraRoaringFlame.class)); cards.add(new SetCardInfo("Chandra, Roaring Flame", "6b", Rarity.MYTHIC, mage.cards.c.ChandraRoaringFlame.class));
cards.add(new SetCardInfo("Delver of Secrets", "7a", Rarity.MYTHIC, mage.cards.d.DelverOfSecrets.class)); cards.add(new SetCardInfo("Delver of Secrets", "7a", Rarity.MYTHIC, mage.cards.d.DelverOfSecrets.class));
@ -39,7 +38,7 @@ public final class FromTheVaultTransform extends ExpansionSet {
cards.add(new SetCardInfo("Withengar Unbound", "8b", Rarity.MYTHIC, mage.cards.w.WithengarUnbound.class)); cards.add(new SetCardInfo("Withengar Unbound", "8b", Rarity.MYTHIC, mage.cards.w.WithengarUnbound.class));
cards.add(new SetCardInfo("Garruk Relentless", "9a", Rarity.MYTHIC, mage.cards.g.GarrukRelentless.class)); cards.add(new SetCardInfo("Garruk Relentless", "9a", Rarity.MYTHIC, mage.cards.g.GarrukRelentless.class));
cards.add(new SetCardInfo("Garruk, the Veil-Cursed", "9b", Rarity.MYTHIC, mage.cards.g.GarrukTheVeilCursed.class)); cards.add(new SetCardInfo("Garruk, the Veil-Cursed", "9b", Rarity.MYTHIC, mage.cards.g.GarrukTheVeilCursed.class));
cards.add(new SetCardInfo("Gisela, the Broken Blade", 10, Rarity.MYTHIC, mage.cards.g.GiselaTheBrokenBlade.class)); cards.add(new SetCardInfo("Gisela, the Broken Blade", "10a", Rarity.MYTHIC, mage.cards.g.GiselaTheBrokenBlade.class));
cards.add(new SetCardInfo("Huntmaster of the Fells", "11a", Rarity.MYTHIC, mage.cards.h.HuntmasterOfTheFells.class)); cards.add(new SetCardInfo("Huntmaster of the Fells", "11a", Rarity.MYTHIC, mage.cards.h.HuntmasterOfTheFells.class));
cards.add(new SetCardInfo("Ravager of the Fells", "11b", Rarity.MYTHIC, mage.cards.r.RavagerOfTheFells.class)); cards.add(new SetCardInfo("Ravager of the Fells", "11b", Rarity.MYTHIC, mage.cards.r.RavagerOfTheFells.class));
cards.add(new SetCardInfo("Jace, Vryn's Prodigy", "12a", Rarity.MYTHIC, mage.cards.j.JaceVrynsProdigy.class)); cards.add(new SetCardInfo("Jace, Vryn's Prodigy", "12a", Rarity.MYTHIC, mage.cards.j.JaceVrynsProdigy.class));