diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/AltMtgOnlTokensImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/AltMtgOnlTokensImageSource.java index df290687c1..f8216028ba 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/AltMtgOnlTokensImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/AltMtgOnlTokensImageSource.java @@ -1,4 +1,3 @@ - package org.mage.plugins.card.dl.sources; import org.apache.log4j.Logger; @@ -59,7 +58,7 @@ public enum AltMtgOnlTokensImageSource implements CardImageSource { } @Override - public CardImageUrls generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { return null; } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageSource.java index 8fb85388bf..758f38881e 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageSource.java @@ -6,11 +6,11 @@ import org.mage.plugins.card.images.CardDownloadData; import java.util.ArrayList; /** - * @author North + * @author North, JayDi85 */ public interface CardImageSource { - CardImageUrls generateURL(CardDownloadData card) throws Exception; + CardImageUrls generateCardUrl(CardDownloadData card) throws Exception; CardImageUrls generateTokenUrl(CardDownloadData card) throws Exception; @@ -53,7 +53,11 @@ public interface CardImageSource { return true; } - default boolean isImageProvided(String setCode, String cardName) { + default boolean isCardImageProvided(String setCode, String cardName) { + return false; + } + + default boolean isTokenImageProvided(String setCode, String cardName, Integer tokenNumber) { return false; } } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSource.java index 0fc6561b97..766208bdf1 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CopyPasteImageSource.java @@ -1,6 +1,10 @@ package org.mage.plugins.card.dl.sources; -import java.awt.Toolkit; +import mage.cards.Sets; +import org.mage.plugins.card.images.CardDownloadData; + +import javax.swing.*; +import java.awt.*; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.StringSelection; import java.io.IOException; @@ -10,12 +14,8 @@ import java.util.LinkedHashSet; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.swing.JOptionPane; -import mage.cards.Sets; -import org.mage.plugins.card.images.CardDownloadData; /** - * * @author spjspj */ public enum CopyPasteImageSource implements CardImageSource { @@ -74,7 +74,7 @@ public enum CopyPasteImageSource implements CardImageSource { } @Override - public CardImageUrls generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { if (singleLinks == null) { setupLinks(); } @@ -198,7 +198,7 @@ public enum CopyPasteImageSource implements CardImageSource { @Override public CardImageUrls generateTokenUrl(CardDownloadData card) throws IOException { try { - return generateURL(card); + return generateCardUrl(card); } catch (Exception ex) { } return null; @@ -239,7 +239,7 @@ public enum CopyPasteImageSource implements CardImageSource { } @Override - public boolean isImageProvided(String setCode, String cardName) { + public boolean isCardImageProvided(String setCode, String cardName) { missingCards.add(setCode + "/" + cardName); if (singleLinks != null) { @@ -248,6 +248,11 @@ public enum CopyPasteImageSource implements CardImageSource { return false; } + @Override + public boolean isTokenImageProvided(String setCode, String cardName, Integer tokenNumber) { + return false; + } + @Override public boolean isSetSupportedComplete(String setCode) { return false; diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GrabbagImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GrabbagImageSource.java index 8d3e12236c..e38898760f 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GrabbagImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GrabbagImageSource.java @@ -1,6 +1,8 @@ - package org.mage.plugins.card.dl.sources; +import org.apache.log4j.Logger; +import org.mage.plugins.card.images.CardDownloadData; + import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; @@ -9,9 +11,6 @@ import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.logging.Level; -import org.apache.log4j.Logger; -import org.mage.plugins.card.images.CardDownloadData; - /** * @author spjspj */ @@ -48,7 +47,7 @@ public enum GrabbagImageSource implements CardImageSource { } @Override - public CardImageUrls generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { if (singleLinks == null) { setupLinks(); } @@ -450,7 +449,7 @@ public enum GrabbagImageSource implements CardImageSource { @Override public CardImageUrls generateTokenUrl(CardDownloadData card) throws IOException { try { - return generateURL(card); + return generateCardUrl(card); } catch (Exception ex) { java.util.logging.Logger.getLogger(GrabbagImageSource.class.getName()).log(Level.SEVERE, null, ex); } @@ -501,7 +500,7 @@ public enum GrabbagImageSource implements CardImageSource { } @Override - public boolean isImageProvided(String setCode, String cardName) { + public boolean isCardImageProvided(String setCode, String cardName) { if (singleLinks == null) { setupLinks(); } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagidexImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagidexImageSource.java index c2ddfcc987..4bd2c49433 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagidexImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagidexImageSource.java @@ -1,16 +1,10 @@ - package org.mage.plugins.card.dl.sources; -import java.net.URI; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.Locale; -import java.util.Map; -import java.util.Set; - import org.mage.plugins.card.images.CardDownloadData; +import java.net.URI; +import java.util.*; + /** * @author Pete Rossi */ @@ -234,7 +228,7 @@ public enum MagidexImageSource implements CardImageSource { } @Override - public CardImageUrls generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { String cardDownloadName = card.getDownloadName().toLowerCase(Locale.ENGLISH); String cardSet = card.getSet(); diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MtgImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MtgImageSource.java index f5104a2226..7c8a368579 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MtgImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MtgImageSource.java @@ -1,10 +1,9 @@ - package org.mage.plugins.card.dl.sources; -import java.util.Locale; - import org.mage.plugins.card.images.CardDownloadData; +import java.util.Locale; + /** * Site was shutdown by wizards Feb. 2015 * @@ -30,7 +29,7 @@ public enum MtgImageSource implements CardImageSource { } @Override - public CardImageUrls generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { String collectorId = card.getCollectorId(); String cardSet = card.getSet(); if (collectorId == null || cardSet == null) { diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MtgOnlTokensImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MtgOnlTokensImageSource.java index 9d82cbb425..f43baec92c 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MtgOnlTokensImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MtgOnlTokensImageSource.java @@ -1,12 +1,11 @@ - package org.mage.plugins.card.dl.sources; -import java.io.IOException; -import java.util.HashMap; - import org.apache.log4j.Logger; import org.mage.plugins.card.images.CardDownloadData; +import java.io.IOException; +import java.util.HashMap; + /** * @author spjspj */ @@ -59,7 +58,7 @@ public enum MtgOnlTokensImageSource implements CardImageSource { } @Override - public CardImageUrls generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { return null; } @@ -352,8 +351,12 @@ public enum MtgOnlTokensImageSource implements CardImageSource { } @Override - public boolean isImageProvided(String setCode, String cardName) { - return true; + public boolean isCardImageProvided(String setCode, String cardName) { + return false; } + @Override + public boolean isTokenImageProvided(String setCode, String cardName, Integer tokenNumber) { + return true; + } } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java index 86f80a6fea..1c0ecaf857 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java @@ -1,22 +1,5 @@ package org.mage.plugins.card.dl.sources; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.HttpURLConnection; -import java.net.InetSocketAddress; -import java.net.Proxy; -import java.net.URL; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.prefs.Preferences; import mage.client.MageFrame; import mage.remote.Connection; import mage.remote.Connection.ProxyType; @@ -26,6 +9,13 @@ import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import org.mage.plugins.card.images.CardDownloadData; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.*; +import java.util.*; +import java.util.prefs.Preferences; + /** * @author LevelX2 */ @@ -330,7 +320,7 @@ public enum MythicspoilerComSource implements CardImageSource { } private Map getSetLinksFromPage(String cardSet, Set aliasesStart, Preferences prefs, - ProxyType proxyType, String baseUrl, String pageUrl) throws IOException { + ProxyType proxyType, String baseUrl, String pageUrl) throws IOException { Map pageLinks = new HashMap<>(); String urlDocument; @@ -392,7 +382,7 @@ public enum MythicspoilerComSource implements CardImageSource { } @Override - public CardImageUrls generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { String collectorId = card.getCollectorId(); String cardSet = card.getSet(); if (collectorId == null || cardSet == null) { diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSource.java index f176324825..6d1f873c1b 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSource.java @@ -3,20 +3,23 @@ package org.mage.plugins.card.dl.sources; import mage.client.util.CardLanguage; import org.mage.plugins.card.images.CardDownloadData; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; /** - * @author Quercitron, JayDi85 + * @author JayDi85 */ public enum ScryfallImageSource implements CardImageSource { instance; - private final Set supportedSets; private final Map languageAliases; private CardLanguage currentLanguage = CardLanguage.ENGLISH; // working language ScryfallImageSource() { + // LANGUAGES // https://scryfall.com/docs/api/languages languageAliases = new HashMap<>(); languageAliases.put(CardLanguage.ENGLISH, "en"); @@ -30,225 +33,9 @@ public enum ScryfallImageSource implements CardImageSource { languageAliases.put(CardLanguage.RUSSIAN, "ru"); languageAliases.put(CardLanguage.CHINES_SIMPLE, "zhs"); languageAliases.put(CardLanguage.CHINES_TRADITION, "zht"); - - supportedSets = new LinkedHashSet<>(); - // supportedSets.add("PTC"); // - supportedSets.add("LEA"); - supportedSets.add("LEB"); - supportedSets.add("2ED"); - supportedSets.add("ARN"); - supportedSets.add("ATQ"); - supportedSets.add("3ED"); - supportedSets.add("LEG"); - supportedSets.add("DRK"); - supportedSets.add("FEM"); - supportedSets.add("4ED"); - supportedSets.add("ICE"); - supportedSets.add("CHR"); - supportedSets.add("HML"); - supportedSets.add("ALL"); - supportedSets.add("MIR"); - supportedSets.add("VIS"); - supportedSets.add("5ED"); - supportedSets.add("POR"); - supportedSets.add("WTH"); - supportedSets.add("TMP"); - supportedSets.add("STH"); - supportedSets.add("EXO"); - supportedSets.add("P02"); - supportedSets.add("UGL"); - supportedSets.add("USG"); - supportedSets.add("DD3DVD"); - supportedSets.add("DD3EVG"); - supportedSets.add("DD3GVL"); - supportedSets.add("DD3JVC"); - - supportedSets.add("ULG"); - supportedSets.add("6ED"); - supportedSets.add("UDS"); - supportedSets.add("PTK"); - supportedSets.add("S99"); - supportedSets.add("MMQ"); - // supportedSets.add("BRB");Battle Royale Box Set - supportedSets.add("NEM"); - supportedSets.add("S00"); - supportedSets.add("PCY"); - supportedSets.add("INV"); - // supportedSets.add("BTD"); // Beatdown Boxset - supportedSets.add("PLS"); - supportedSets.add("7ED"); - supportedSets.add("APC"); - supportedSets.add("ODY"); - // supportedSets.add("DKM"); // Deckmasters 2001 - supportedSets.add("TOR"); - supportedSets.add("JUD"); - supportedSets.add("ONS"); - supportedSets.add("LGN"); - supportedSets.add("SCG"); - supportedSets.add("8ED"); - supportedSets.add("MRD"); - supportedSets.add("DST"); - supportedSets.add("5DN"); - supportedSets.add("CHK"); - supportedSets.add("UNH"); - supportedSets.add("BOK"); - supportedSets.add("SOK"); - supportedSets.add("9ED"); - supportedSets.add("RAV"); - supportedSets.add("GPT"); - supportedSets.add("DIS"); - supportedSets.add("CSP"); - supportedSets.add("TSP"); - supportedSets.add("TSB"); - supportedSets.add("PLC"); - supportedSets.add("FUT"); - supportedSets.add("10E"); - supportedSets.add("MED"); - supportedSets.add("LRW"); - supportedSets.add("EVG"); - supportedSets.add("MOR"); - supportedSets.add("SHM"); - supportedSets.add("EVE"); - supportedSets.add("DRB"); - supportedSets.add("ME2"); - supportedSets.add("ALA"); - supportedSets.add("DD2"); - supportedSets.add("CON"); - supportedSets.add("DDC"); - supportedSets.add("ARB"); - supportedSets.add("M10"); - // supportedSets.add("TD0"); // Magic Online Deck Series - supportedSets.add("V09"); - supportedSets.add("HOP"); - supportedSets.add("ME3"); - supportedSets.add("ZEN"); - supportedSets.add("DDD"); - supportedSets.add("H09"); - supportedSets.add("WWK"); - supportedSets.add("DDE"); - supportedSets.add("ROE"); - // duels of the planewalkers: - supportedSets.add("DPA"); - supportedSets.add("DPAP"); - // - supportedSets.add("ARC"); - supportedSets.add("M11"); - supportedSets.add("V10"); - supportedSets.add("DDF"); - supportedSets.add("SOM"); - // supportedSets.add("TD0"); // Commander Theme Decks - supportedSets.add("PD2"); - supportedSets.add("ME4"); - supportedSets.add("MBS"); - supportedSets.add("DDG"); - supportedSets.add("NPH"); - supportedSets.add("CMD"); - supportedSets.add("M12"); - supportedSets.add("V11"); - supportedSets.add("DDH"); - supportedSets.add("ISD"); - supportedSets.add("PD3"); - supportedSets.add("DKA"); - supportedSets.add("DDI"); - supportedSets.add("AVR"); - supportedSets.add("PC2"); - supportedSets.add("M13"); - supportedSets.add("V12"); - supportedSets.add("DDJ"); - supportedSets.add("RTR"); - supportedSets.add("CM1"); - // supportedSets.add("TD2"); // Duel Decks: Mirrodin Pure vs. New Phyrexia - supportedSets.add("GTC"); - supportedSets.add("DDK"); - supportedSets.add("DGM"); - supportedSets.add("MMA"); - supportedSets.add("M14"); - supportedSets.add("V13"); - supportedSets.add("DDL"); - supportedSets.add("THS"); - supportedSets.add("C13"); - supportedSets.add("BNG"); - supportedSets.add("DDM"); - supportedSets.add("JOU"); - // supportedSets.add("MD1"); // Modern Event Deck - supportedSets.add("CNS"); - supportedSets.add("VMA"); - supportedSets.add("M15"); - supportedSets.add("V14"); - supportedSets.add("DDN"); - supportedSets.add("KTK"); - supportedSets.add("C14"); - // supportedSets.add("DD3"); // Duel Decks Anthology - supportedSets.add("FRF"); - supportedSets.add("DDO"); - supportedSets.add("DTK"); - supportedSets.add("TPR"); - supportedSets.add("MM2"); - supportedSets.add("ORI"); - supportedSets.add("V15"); - supportedSets.add("DDP"); - supportedSets.add("BFZ"); - supportedSets.add("EXP"); - supportedSets.add("C15"); - // supportedSets.add("PZ1"); // Legendary Cube - supportedSets.add("OGW"); - supportedSets.add("DDQ"); - supportedSets.add("W16"); - supportedSets.add("SOI"); - supportedSets.add("EMA"); - supportedSets.add("EMN"); - supportedSets.add("V16"); - supportedSets.add("CN2"); - supportedSets.add("DDR"); - supportedSets.add("KLD"); - supportedSets.add("MPS"); - // supportedSets.add("PZ2"); - supportedSets.add("C16"); - supportedSets.add("PCA"); - supportedSets.add("AER"); - supportedSets.add("MM3"); - supportedSets.add("DDS"); - supportedSets.add("W17"); - supportedSets.add("AKH"); - supportedSets.add("CMA"); - supportedSets.add("E01"); - supportedSets.add("HOU"); - supportedSets.add("C17"); - supportedSets.add("XLN"); - supportedSets.add("DDT"); - supportedSets.add("IMA"); - supportedSets.add("E02"); - supportedSets.add("V17"); - supportedSets.add("UST"); - supportedSets.add("DDU"); - supportedSets.add("RIX"); - supportedSets.add("WMCQ"); - supportedSets.add("PPRO"); - supportedSets.add("A25"); - supportedSets.add("DOM"); - supportedSets.add("BBD"); - supportedSets.add("C18"); - supportedSets.add("CM2"); - supportedSets.add("M19"); - supportedSets.add("GS1"); - supportedSets.add("GRN"); - supportedSets.add("GK1"); - supportedSets.add("GNT"); - supportedSets.add("UMA"); - supportedSets.add("PUMA"); - supportedSets.add("RNA"); - // - supportedSets.add("EURO"); - supportedSets.add("GPX"); - supportedSets.add("ATH"); - supportedSets.add("GRC"); - supportedSets.add("ANA"); } - @Override - public CardImageUrls generateURL(CardDownloadData card) throws Exception { - - String preferredCode = this.getCurrentLanguage().getCode(); + private CardImageUrls innerGenerateURL(CardDownloadData card, boolean isToken) { String defaultCode = CardLanguage.ENGLISH.getCode(); String localizedCode = languageAliases.getOrDefault(this.getCurrentLanguage(), defaultCode); // loc example: https://api.scryfall.com/cards/xln/121/ru?format=image @@ -259,22 +46,20 @@ public enum ScryfallImageSource implements CardImageSource { String baseUrl = null; String alternativeUrl = null; + // TOKENS TRY + + // tokens support only direct links + if (baseUrl == null && isToken) { + baseUrl = ScryfallImageSupportTokens.findTokenLink(card.getSet(), card.getName(), card.getType()); + alternativeUrl = null; + } + + // CARDS TRY + // direct links to images (non localization) if (baseUrl == null) { - - // set/card/number - String linkCode1 = card.getSet() + "/" + card.getName() + "/" + card.getCollectorId(); - if (directDownloadLinks.containsKey(linkCode1)) { - baseUrl = directDownloadLinks.get(linkCode1); - alternativeUrl = null; - } - - // set/card - String linkCode2 = card.getSet() + "/" + card.getName(); - if (directDownloadLinks.containsKey(linkCode2)) { - baseUrl = directDownloadLinks.get(linkCode2); - alternativeUrl = null; - } + baseUrl = ScryfallImageSupportCards.findDirectDownloadLink(card.getSet(), card.getName(), card.getCollectorId()); + alternativeUrl = null; } // special card number like "103a" and "U123" already compatible @@ -285,9 +70,9 @@ public enum ScryfallImageSource implements CardImageSource { // fix for Ultimate Box Topper (PUMA) -- need to use API // ignored and go to API call at the end } else { - baseUrl = "https://img.scryfall.com/cards/large/" + localizedCode + "/" + formatSetName(card.getSet()) + "/" + baseUrl = "https://img.scryfall.com/cards/large/" + localizedCode + "/" + formatSetName(card.getSet(), isToken) + "/" + card.getCollectorId() + ".jpg"; - alternativeUrl = "https://img.scryfall.com/cards/large/" + defaultCode + "/" + formatSetName(card.getSet()) + "/" + alternativeUrl = "https://img.scryfall.com/cards/large/" + defaultCode + "/" + formatSetName(card.getSet(), isToken) + "/" + card.getCollectorId() + ".jpg"; } } @@ -295,27 +80,33 @@ public enum ScryfallImageSource implements CardImageSource { // double faced cards do not supports by API (need direct link for img) // example: https://img.scryfall.com/cards/large/en/xln/173b.jpg if (baseUrl == null && card.isTwoFacedCard()) { - baseUrl = "https://img.scryfall.com/cards/large/" + localizedCode + "/" + formatSetName(card.getSet()) + "/" + baseUrl = "https://img.scryfall.com/cards/large/" + localizedCode + "/" + formatSetName(card.getSet(), isToken) + "/" + card.getCollectorId() + (card.isSecondSide() ? "b" : "a") + ".jpg"; - alternativeUrl = "https://img.scryfall.com/cards/large/" + defaultCode + "/" + formatSetName(card.getSet()) + "/" + alternativeUrl = "https://img.scryfall.com/cards/large/" + defaultCode + "/" + formatSetName(card.getSet(), isToken) + "/" + card.getCollectorId() + (card.isSecondSide() ? "b" : "a") + ".jpg"; } // basic cards by api call (redirect to img link) // example: https://api.scryfall.com/cards/xln/121/en?format=image if (baseUrl == null) { - baseUrl = "https://api.scryfall.com/cards/" + formatSetName(card.getSet()) + "/" + baseUrl = "https://api.scryfall.com/cards/" + formatSetName(card.getSet(), isToken) + "/" + card.getCollectorId() + "/" + localizedCode + "?format=image"; - alternativeUrl = "https://api.scryfall.com/cards/" + formatSetName(card.getSet()) + "/" + alternativeUrl = "https://api.scryfall.com/cards/" + formatSetName(card.getSet(), isToken) + "/" + card.getCollectorId() + "/" + defaultCode + "?format=image"; } return new CardImageUrls(baseUrl, alternativeUrl); } + @Override + public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { + return innerGenerateURL(card, false); + + } + @Override public CardImageUrls generateTokenUrl(CardDownloadData card) throws Exception { - return null; + return innerGenerateURL(card, true); } @Override @@ -345,7 +136,7 @@ public enum ScryfallImageSource implements CardImageSource { @Override public boolean isTokenSource() { - return false; + return true; } @Override @@ -368,132 +159,41 @@ public enum ScryfallImageSource implements CardImageSource { } - private String formatSetName(String setName) { - if (setNameReplacement.containsKey(setName)) { - setName = setNameReplacement.get(setName); + private String formatSetName(String setName, boolean isToken) { + if (isToken) { + // token uses direct link download, not set + return setName.toLowerCase(Locale.ENGLISH); + } else { + return ScryfallImageSupportCards.findScryfallSetCode(setName); } - return setName.toLowerCase(Locale.ENGLISH); } - private static final Map setNameReplacement = new HashMap() { - { - put("DD3GVL", "gvl"); - put("DD3JVC", "jvc"); - put("DD3DVD", "dvd"); - put("DD3EVG", "evg"); - put("MPS-AKH", "mp2"); - put("MBP", "pmei"); - put("WMCQ", "pwcq"); - put("EURO", "pelp"); - put("GPX", "pgpx"); - put("MED", "me1"); - } - }; - - private static final Map directDownloadLinks = new HashMap() { - { - // direct links to download images for special cards - - // Duels of the Planeswalkers Promos -- xmage uses one set (DPAP), but scryfall store it by years - // 2009 - https://scryfall.com/sets/pdtp - put("DPAP/Garruk Wildspeaker", "https://img.scryfall.com/cards/large/en/pdtp/1.jpg"); - // 2010 - https://scryfall.com/sets/pdp10 - put("DPAP/Liliana Vess", "https://img.scryfall.com/cards/large/en/pdp10/1.jpg"); - put("DPAP/Nissa Revane", "https://img.scryfall.com/cards/large/en/pdp10/2.jpg"); - // 2011 - https://scryfall.com/sets/pdp11 - put("DPAP/Frost Titan", "https://img.scryfall.com/cards/large/en/pdp11/1.jpg"); - put("DPAP/Grave Titan", "https://img.scryfall.com/cards/large/en/pdp11/2.jpg"); - put("DPAP/Inferno Titan", "https://img.scryfall.com/cards/large/en/pdp11/3.jpg"); - // 2012 - https://scryfall.com/sets/pdp12 - put("DPAP/Primordial Hydra", "https://img.scryfall.com/cards/large/en/pdp12/1.jpg"); - put("DPAP/Serra Avatar", "https://img.scryfall.com/cards/large/en/pdp12/2.jpg"); - put("DPAP/Vampire Nocturnus", "https://img.scryfall.com/cards/large/en/pdp12/3.jpg"); - // 2013 - https://scryfall.com/sets/pdp13 - put("DPAP/Bonescythe Sliver", "https://img.scryfall.com/cards/large/en/pdp13/1.jpg"); - put("DPAP/Ogre Battledriver", "https://img.scryfall.com/cards/large/en/pdp13/2.jpg"); - put("DPAP/Scavenging Ooze", "https://img.scryfall.com/cards/large/en/pdp13/3.jpg"); - // 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 Zendikar", "https://img.scryfall.com/cards/large/en/pdp14/2.jpg"); - - // Gateway Promos -- xmage uses one set (GRC), but scryfall store it by years - // 2006 - https://scryfall.com/sets/pgtw - put("GRC/Fiery Temper", "https://img.scryfall.com/cards/large/en/pgtw/3.jpg"); - put("GRC/Icatian Javelineers", "https://img.scryfall.com/cards/large/en/pgtw/2.jpg"); - put("GRC/Wood Elves", "https://img.scryfall.com/cards/large/en/pgtw/1.jpg"); - // 2007 - https://scryfall.com/sets/pg07 - put("GRC/Boomerang", "https://img.scryfall.com/cards/large/en/pg07/4.jpg"); - put("GRC/Calciderm", "https://img.scryfall.com/cards/large/en/pg07/5.jpg"); - put("GRC/Dauntless Dourbark", "https://img.scryfall.com/cards/large/en/pg07/12.jpg"); - put("GRC/Llanowar Elves", "https://img.scryfall.com/cards/large/en/pg07/9.jpg"); - put("GRC/Mind Stone", "https://img.scryfall.com/cards/large/en/pg07/11.jpg"); - put("GRC/Mogg Fanatic", "https://img.scryfall.com/cards/large/en/pg07/10.jpg"); - put("GRC/Reckless Wurm", "https://img.scryfall.com/cards/large/en/pg07/6.jpg"); - put("GRC/Yixlid Jailer", "https://img.scryfall.com/cards/large/en/pg07/7.jpg"); - put("GRC/Zoetic Cavern", "https://img.scryfall.com/cards/large/en/pg07/8.jpg"); - // 2008a - https://scryfall.com/sets/pg08 - put("GRC/Boggart Ram-Gang", "https://img.scryfall.com/cards/large/en/pg08/17.jpg"); - put("GRC/Cenn's Tactician", "https://img.scryfall.com/cards/large/en/pg08/14.jpg"); - put("GRC/Duergar Hedge-Mage", "https://img.scryfall.com/cards/large/en/pg08/19.jpg"); - put("GRC/Gravedigger", "https://img.scryfall.com/cards/large/en/pg08/16.jpg"); - put("GRC/Lava Axe", "https://img.scryfall.com/cards/large/en/pg08/13.jpg"); - put("GRC/Oona's Blackguard", "https://img.scryfall.com/cards/large/en/pg08/15.jpg"); - put("GRC/Selkie Hedge-Mage", "https://img.scryfall.com/cards/large/en/pg08/20.jpg"); - put("GRC/Wilt-Leaf Cavaliers", "https://img.scryfall.com/cards/large/en/pg08/18.jpg"); - - // Wizards Play Network Promos -- xmage uses one set (GRC), but scryfall store it by years - // 2008b - https://scryfall.com/sets/pwpn - put("GRC/Sprouting Thrinax", "https://img.scryfall.com/cards/large/en/pwpn/21.jpg"); - put("GRC/Woolly Thoctar", "https://img.scryfall.com/cards/large/en/pwpn/22.jpg"); - // 2009 - https://scryfall.com/sets/pwp09 - put("GRC/Hellspark Elemental", "https://img.scryfall.com/cards/large/en/pwp09/25.jpg"); - put("GRC/Kor Duelist", "https://img.scryfall.com/cards/large/en/pwp09/32.jpg"); - put("GRC/Marisi's Twinclaws", "https://img.scryfall.com/cards/large/en/pwp09/26.jpg"); - put("GRC/Mind Control", "https://img.scryfall.com/cards/large/en/pwp09/30.jpg"); - put("GRC/Path to Exile", "https://img.scryfall.com/cards/large/en/pwp09/24.jpg"); - put("GRC/Rise from the Grave", "https://img.scryfall.com/cards/large/en/pwp09/31.jpg"); - put("GRC/Slave of Bolas", "https://img.scryfall.com/cards/large/en/pwp09/27.jpg"); - put("GRC/Vampire Nighthawk", "https://img.scryfall.com/cards/large/en/pwp09/33.jpg"); - // 2010 - https://scryfall.com/sets/pwp10 - put("GRC/Kor Firewalker", "https://img.scryfall.com/cards/large/en/pwp10/36.jpg"); - put("GRC/Leatherback Baloth", "https://img.scryfall.com/cards/large/en/pwp10/37.jpg"); - put("GRC/Syphon Mind", "https://img.scryfall.com/cards/large/en/pwp10/40.jpg"); - put("GRC/Pathrazer of Ulamog", "https://img.scryfall.com/cards/large/en/pwp10/46.jpg"); - put("GRC/Curse of Wizardry", "https://img.scryfall.com/cards/large/en/pwp10/47.jpg"); - put("GRC/Fling/50", "https://img.scryfall.com/cards/large/en/pwp10/50.jpg"); // 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/Plague Stinger", "https://img.scryfall.com/cards/large/en/pwp10/59.jpg"); - put("GRC/Golem's Heart", "https://img.scryfall.com/cards/large/en/pwp10/60.jpg"); - put("GRC/Skinrender", "https://img.scryfall.com/cards/large/en/pwp10/63.jpg"); - // 2011 - https://scryfall.com/sets/pwp11 - put("GRC/Auramancer", "https://img.scryfall.com/cards/large/en/pwp11/77.jpg"); - put("GRC/Bloodcrazed Neonate", "https://img.scryfall.com/cards/large/en/pwp11/83.jpg"); - put("GRC/Boneyard Wurm", "https://img.scryfall.com/cards/large/en/pwp11/84.jpg"); - put("GRC/Circle of Flame", "https://img.scryfall.com/cards/large/en/pwp11/78.jpg"); - put("GRC/Curse of the Bloody Tome", "https://img.scryfall.com/cards/large/en/pwp11/80.jpg"); - put("GRC/Fling/69", "https://img.scryfall.com/cards/large/en/pwp11/69.jpg"); // same card but different year - put("GRC/Master's Call", "https://img.scryfall.com/cards/large/en/pwp11/64.jpg"); - put("GRC/Maul Splicer", "https://img.scryfall.com/cards/large/en/pwp11/72.jpg"); - put("GRC/Plague Myr", "https://img.scryfall.com/cards/large/en/pwp11/65.jpg"); - put("GRC/Shrine of Burning Rage", "https://img.scryfall.com/cards/large/en/pwp11/73.jpg"); - put("GRC/Signal Pest", "https://img.scryfall.com/cards/large/en/pwp11/66.jpg"); - put("GRC/Sylvan Ranger/70", "https://img.scryfall.com/cards/large/en/pwp11/70.jpg"); // same card but different year - put("GRC/Tormented Soul", "https://img.scryfall.com/cards/large/en/pwp11/76.jpg"); - put("GRC/Vault Skirge", "https://img.scryfall.com/cards/large/en/pwp11/71.jpg"); - // 2012 - https://scryfall.com/sets/pwp12 - put("GRC/Curse of Thirst", "https://img.scryfall.com/cards/large/en/pwp12/81.jpg"); - put("GRC/Gather the Townsfolk", "https://img.scryfall.com/cards/large/en/pwp12/79.jpg"); - put("GRC/Nearheath Stalker", "https://img.scryfall.com/cards/large/en/pwp12/82.jpg"); - - // 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 ) - put("GPX/Sword of Feast and Famine", "https://img.scryfall.com/cards/large/en/pgpx/1%E2%98%85.jpg"); - } - }; - @Override public ArrayList getSupportedSets() { ArrayList supportedSetsCopy = new ArrayList<>(); - supportedSetsCopy.addAll(supportedSets); + + // cards + supportedSetsCopy.addAll(ScryfallImageSupportCards.getSupportedSets()); + + // tokens + for (String code : ScryfallImageSupportTokens.getSupportedSets().keySet()) { + if (!supportedSetsCopy.contains(code)) { + supportedSetsCopy.add(code); + } + } + return supportedSetsCopy; } + + @Override + public boolean isCardImageProvided(String setCode, String cardName) { + // all cards from set + return ScryfallImageSupportCards.getSupportedSets().contains(setCode); + } + + @Override + public boolean isTokenImageProvided(String setCode, String cardName, Integer tokenNumber) { + // only direct tokens from set + return ScryfallImageSupportTokens.findTokenLink(setCode, cardName, tokenNumber) != null; + } } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java new file mode 100644 index 0000000000..08424c69ac --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java @@ -0,0 +1,385 @@ +package org.mage.plugins.card.dl.sources; + +import org.tritonus.share.ArraySet; + +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +/** + * @author JayDi85 + */ +public class ScryfallImageSupportCards { + + private static final Map xmageSetsToScryfall = new HashMap() { + { + // xmage -> scryfall + put("DD3GVL", "gvl"); + put("DD3JVC", "jvc"); + put("DD3DVD", "dvd"); + put("DD3EVG", "evg"); + put("MPS-AKH", "mp2"); + put("MBP", "pmei"); + put("WMCQ", "pwcq"); + put("EURO", "pelp"); + put("GPX", "pgpx"); + put("MED", "me1"); + } + }; + + private static final Set supportedSets = new ArraySet() { + { + // xmage set codes + // add("PTC"); // + add("LEA"); + add("LEB"); + add("2ED"); + add("ARN"); + add("ATQ"); + add("3ED"); + add("LEG"); + add("DRK"); + add("FEM"); + add("4ED"); + add("ICE"); + add("CHR"); + add("HML"); + add("ALL"); + add("MIR"); + add("VIS"); + add("5ED"); + add("POR"); + add("WTH"); + add("TMP"); + add("STH"); + add("EXO"); + add("P02"); + add("UGL"); + add("USG"); + add("DD3DVD"); + add("DD3EVG"); + add("DD3GVL"); + add("DD3JVC"); + + add("ULG"); + add("6ED"); + add("UDS"); + add("PTK"); + add("S99"); + add("MMQ"); + // add("BRB");Battle Royale Box Set + add("NEM"); + add("S00"); + add("PCY"); + add("INV"); + // add("BTD"); // Beatdown Boxset + add("PLS"); + add("7ED"); + add("APC"); + add("ODY"); + // add("DKM"); // Deckmasters 2001 + add("TOR"); + add("JUD"); + add("ONS"); + add("LGN"); + add("SCG"); + add("8ED"); + add("MRD"); + add("DST"); + add("5DN"); + add("CHK"); + add("UNH"); + add("BOK"); + add("SOK"); + add("9ED"); + add("RAV"); + add("GPT"); + add("DIS"); + add("CSP"); + add("TSP"); + add("TSB"); + add("PLC"); + add("FUT"); + add("10E"); + add("MED"); + add("LRW"); + add("EVG"); + add("MOR"); + add("SHM"); + add("EVE"); + add("DRB"); + add("ME2"); + add("ALA"); + add("DD2"); + add("CON"); + add("DDC"); + add("ARB"); + add("M10"); + // add("TD0"); // Magic Online Deck Series + add("V09"); + add("HOP"); + add("ME3"); + add("ZEN"); + add("DDD"); + add("H09"); + add("WWK"); + add("DDE"); + add("ROE"); + // duels of the planewalkers: + add("DPA"); + add("DPAP"); + // + add("ARC"); + add("M11"); + add("V10"); + add("DDF"); + add("SOM"); + // add("TD0"); // Commander Theme Decks + add("PD2"); + add("ME4"); + add("MBS"); + add("DDG"); + add("NPH"); + add("CMD"); + add("M12"); + add("V11"); + add("DDH"); + add("ISD"); + add("PD3"); + add("DKA"); + add("DDI"); + add("AVR"); + add("PC2"); + add("M13"); + add("V12"); + add("DDJ"); + add("RTR"); + add("CM1"); + // add("TD2"); // Duel Decks: Mirrodin Pure vs. New Phyrexia + add("GTC"); + add("DDK"); + add("DGM"); + add("MMA"); + add("M14"); + add("V13"); + add("DDL"); + add("THS"); + add("C13"); + add("BNG"); + add("DDM"); + add("JOU"); + // add("MD1"); // Modern Event Deck + add("CNS"); + add("VMA"); + add("M15"); + add("V14"); + add("DDN"); + add("KTK"); + add("C14"); + // add("DD3"); // Duel Decks Anthology + add("FRF"); + add("DDO"); + add("DTK"); + add("TPR"); + add("MM2"); + add("ORI"); + add("V15"); + add("DDP"); + add("BFZ"); + add("EXP"); + add("C15"); + // add("PZ1"); // Legendary Cube + add("OGW"); + add("DDQ"); + add("W16"); + add("SOI"); + add("EMA"); + add("EMN"); + add("V16"); + add("CN2"); + add("DDR"); + add("KLD"); + add("MPS"); + // add("PZ2"); + add("C16"); + add("PCA"); + add("AER"); + add("MM3"); + add("DDS"); + add("W17"); + add("AKH"); + add("CMA"); + add("E01"); + add("HOU"); + add("C17"); + add("XLN"); + add("DDT"); + add("IMA"); + add("E02"); + add("V17"); + add("UST"); + add("DDU"); + add("RIX"); + add("WMCQ"); + add("PPRO"); + add("A25"); + add("DOM"); + add("BBD"); + add("C18"); + add("CM2"); + add("M19"); + add("GS1"); + add("GRN"); + add("GK1"); + add("GNT"); + add("UMA"); + add("PUMA"); + add("RNA"); + // + add("EURO"); + add("GPX"); + add("ATH"); + add("GRC"); + add("ANA"); + } + }; + + private static final Map directDownloadLinks = new HashMap() { + { + // xmage card -> direct or api link: + // examples: + // direct example: https://img.scryfall.com/cards/large/en/trix/6.jpg + // api example: https://api.scryfall.com/cards/trix/6/en?format=image + // api example: https://api.scryfall.com/cards/trix/6?format=image + // api format is primary + // + // code form for one card: + // set/card_name + // + // code form for same name cards (alternative images): + // set/card_name/card_number + // set/card_name/card_number + + // Duels of the Planeswalkers Promos -- xmage uses one set (DPAP), but scryfall store it by years + // 2009 - https://scryfall.com/sets/pdtp + put("DPAP/Garruk Wildspeaker", "https://img.scryfall.com/cards/large/en/pdtp/1.jpg"); + // 2010 - https://scryfall.com/sets/pdp10 + put("DPAP/Liliana Vess", "https://img.scryfall.com/cards/large/en/pdp10/1.jpg"); + put("DPAP/Nissa Revane", "https://img.scryfall.com/cards/large/en/pdp10/2.jpg"); + // 2011 - https://scryfall.com/sets/pdp11 + put("DPAP/Frost Titan", "https://img.scryfall.com/cards/large/en/pdp11/1.jpg"); + put("DPAP/Grave Titan", "https://img.scryfall.com/cards/large/en/pdp11/2.jpg"); + put("DPAP/Inferno Titan", "https://img.scryfall.com/cards/large/en/pdp11/3.jpg"); + // 2012 - https://scryfall.com/sets/pdp12 + put("DPAP/Primordial Hydra", "https://img.scryfall.com/cards/large/en/pdp12/1.jpg"); + put("DPAP/Serra Avatar", "https://img.scryfall.com/cards/large/en/pdp12/2.jpg"); + put("DPAP/Vampire Nocturnus", "https://img.scryfall.com/cards/large/en/pdp12/3.jpg"); + // 2013 - https://scryfall.com/sets/pdp13 + put("DPAP/Bonescythe Sliver", "https://img.scryfall.com/cards/large/en/pdp13/1.jpg"); + put("DPAP/Ogre Battledriver", "https://img.scryfall.com/cards/large/en/pdp13/2.jpg"); + put("DPAP/Scavenging Ooze", "https://img.scryfall.com/cards/large/en/pdp13/3.jpg"); + // 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 Zendikar", "https://img.scryfall.com/cards/large/en/pdp14/2.jpg"); + + // Gateway Promos -- xmage uses one set (GRC), but scryfall store it by years + // 2006 - https://scryfall.com/sets/pgtw + put("GRC/Fiery Temper", "https://img.scryfall.com/cards/large/en/pgtw/3.jpg"); + put("GRC/Icatian Javelineers", "https://img.scryfall.com/cards/large/en/pgtw/2.jpg"); + put("GRC/Wood Elves", "https://img.scryfall.com/cards/large/en/pgtw/1.jpg"); + // 2007 - https://scryfall.com/sets/pg07 + put("GRC/Boomerang", "https://img.scryfall.com/cards/large/en/pg07/4.jpg"); + put("GRC/Calciderm", "https://img.scryfall.com/cards/large/en/pg07/5.jpg"); + put("GRC/Dauntless Dourbark", "https://img.scryfall.com/cards/large/en/pg07/12.jpg"); + put("GRC/Llanowar Elves", "https://img.scryfall.com/cards/large/en/pg07/9.jpg"); + put("GRC/Mind Stone", "https://img.scryfall.com/cards/large/en/pg07/11.jpg"); + put("GRC/Mogg Fanatic", "https://img.scryfall.com/cards/large/en/pg07/10.jpg"); + put("GRC/Reckless Wurm", "https://img.scryfall.com/cards/large/en/pg07/6.jpg"); + put("GRC/Yixlid Jailer", "https://img.scryfall.com/cards/large/en/pg07/7.jpg"); + put("GRC/Zoetic Cavern", "https://img.scryfall.com/cards/large/en/pg07/8.jpg"); + // 2008a - https://scryfall.com/sets/pg08 + put("GRC/Boggart Ram-Gang", "https://img.scryfall.com/cards/large/en/pg08/17.jpg"); + put("GRC/Cenn's Tactician", "https://img.scryfall.com/cards/large/en/pg08/14.jpg"); + put("GRC/Duergar Hedge-Mage", "https://img.scryfall.com/cards/large/en/pg08/19.jpg"); + put("GRC/Gravedigger", "https://img.scryfall.com/cards/large/en/pg08/16.jpg"); + put("GRC/Lava Axe", "https://img.scryfall.com/cards/large/en/pg08/13.jpg"); + put("GRC/Oona's Blackguard", "https://img.scryfall.com/cards/large/en/pg08/15.jpg"); + put("GRC/Selkie Hedge-Mage", "https://img.scryfall.com/cards/large/en/pg08/20.jpg"); + put("GRC/Wilt-Leaf Cavaliers", "https://img.scryfall.com/cards/large/en/pg08/18.jpg"); + + // Wizards Play Network Promos -- xmage uses one set (GRC), but scryfall store it by years + // 2008b - https://scryfall.com/sets/pwpn + put("GRC/Sprouting Thrinax", "https://img.scryfall.com/cards/large/en/pwpn/21.jpg"); + put("GRC/Woolly Thoctar", "https://img.scryfall.com/cards/large/en/pwpn/22.jpg"); + // 2009 - https://scryfall.com/sets/pwp09 + put("GRC/Hellspark Elemental", "https://img.scryfall.com/cards/large/en/pwp09/25.jpg"); + put("GRC/Kor Duelist", "https://img.scryfall.com/cards/large/en/pwp09/32.jpg"); + put("GRC/Marisi's Twinclaws", "https://img.scryfall.com/cards/large/en/pwp09/26.jpg"); + put("GRC/Mind Control", "https://img.scryfall.com/cards/large/en/pwp09/30.jpg"); + put("GRC/Path to Exile", "https://img.scryfall.com/cards/large/en/pwp09/24.jpg"); + put("GRC/Rise from the Grave", "https://img.scryfall.com/cards/large/en/pwp09/31.jpg"); + put("GRC/Slave of Bolas", "https://img.scryfall.com/cards/large/en/pwp09/27.jpg"); + put("GRC/Vampire Nighthawk", "https://img.scryfall.com/cards/large/en/pwp09/33.jpg"); + // 2010 - https://scryfall.com/sets/pwp10 + put("GRC/Kor Firewalker", "https://img.scryfall.com/cards/large/en/pwp10/36.jpg"); + put("GRC/Leatherback Baloth", "https://img.scryfall.com/cards/large/en/pwp10/37.jpg"); + put("GRC/Syphon Mind", "https://img.scryfall.com/cards/large/en/pwp10/40.jpg"); + put("GRC/Pathrazer of Ulamog", "https://img.scryfall.com/cards/large/en/pwp10/46.jpg"); + put("GRC/Curse of Wizardry", "https://img.scryfall.com/cards/large/en/pwp10/47.jpg"); + put("GRC/Fling/50", "https://img.scryfall.com/cards/large/en/pwp10/50.jpg"); // 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/Plague Stinger", "https://img.scryfall.com/cards/large/en/pwp10/59.jpg"); + put("GRC/Golem's Heart", "https://img.scryfall.com/cards/large/en/pwp10/60.jpg"); + put("GRC/Skinrender", "https://img.scryfall.com/cards/large/en/pwp10/63.jpg"); + // 2011 - https://scryfall.com/sets/pwp11 + put("GRC/Auramancer", "https://img.scryfall.com/cards/large/en/pwp11/77.jpg"); + put("GRC/Bloodcrazed Neonate", "https://img.scryfall.com/cards/large/en/pwp11/83.jpg"); + put("GRC/Boneyard Wurm", "https://img.scryfall.com/cards/large/en/pwp11/84.jpg"); + put("GRC/Circle of Flame", "https://img.scryfall.com/cards/large/en/pwp11/78.jpg"); + put("GRC/Curse of the Bloody Tome", "https://img.scryfall.com/cards/large/en/pwp11/80.jpg"); + put("GRC/Fling/69", "https://img.scryfall.com/cards/large/en/pwp11/69.jpg"); // same card but different year + put("GRC/Master's Call", "https://img.scryfall.com/cards/large/en/pwp11/64.jpg"); + put("GRC/Maul Splicer", "https://img.scryfall.com/cards/large/en/pwp11/72.jpg"); + put("GRC/Plague Myr", "https://img.scryfall.com/cards/large/en/pwp11/65.jpg"); + put("GRC/Shrine of Burning Rage", "https://img.scryfall.com/cards/large/en/pwp11/73.jpg"); + put("GRC/Signal Pest", "https://img.scryfall.com/cards/large/en/pwp11/66.jpg"); + put("GRC/Sylvan Ranger/70", "https://img.scryfall.com/cards/large/en/pwp11/70.jpg"); // same card but different year + put("GRC/Tormented Soul", "https://img.scryfall.com/cards/large/en/pwp11/76.jpg"); + put("GRC/Vault Skirge", "https://img.scryfall.com/cards/large/en/pwp11/71.jpg"); + // 2012 - https://scryfall.com/sets/pwp12 + put("GRC/Curse of Thirst", "https://img.scryfall.com/cards/large/en/pwp12/81.jpg"); + put("GRC/Gather the Townsfolk", "https://img.scryfall.com/cards/large/en/pwp12/79.jpg"); + put("GRC/Nearheath Stalker", "https://img.scryfall.com/cards/large/en/pwp12/82.jpg"); + + // 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 ) + put("GPX/Sword of Feast and Famine", "https://img.scryfall.com/cards/large/en/pgpx/1%E2%98%85.jpg"); + } + }; + + public static String findScryfallSetCode(String xmageCode) { + return xmageSetsToScryfall.getOrDefault(xmageCode, xmageCode).toLowerCase(Locale.ENGLISH); + } + + public static Set getSupportedSets() { + return supportedSets; + } + + public static String findDirectDownloadLink(String setCode, String cardName, String cardNumber) { + + // set/card/number + String linkCode1 = setCode + "/" + cardName + "/" + cardNumber; + if (directDownloadLinks.containsKey(linkCode1)) { + return directDownloadLinks.get(linkCode1); + } + + // set/card + String linkCode2 = setCode + "/" + cardName; + if (directDownloadLinks.containsKey(linkCode2)) { + return directDownloadLinks.get(linkCode2); + } + + // default + return null; + } +} diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportTokens.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportTokens.java new file mode 100644 index 0000000000..db48a3ad5e --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportTokens.java @@ -0,0 +1,56 @@ +package org.mage.plugins.card.dl.sources; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author JayDi85 + */ +public class ScryfallImageSupportTokens { + + private static final Map supportedSets = new HashMap<>(); + + private static final Map supportedCards = new HashMap() { + { + // xmage token -> direct or api link: + // examples: + // direct example: https://img.scryfall.com/cards/large/en/trix/6.jpg + // api example: https://api.scryfall.com/cards/trix/6/en?format=image + // api example: https://api.scryfall.com/cards/trix/6?format=image + // api format is primary + // + // code form for one token: + // set/token_name + // + // code form for same name tokens (alternative images): + // set/token_name/1 + // set/token_name/2 + + // RIX + put("RIX/City's Blessing", "https://api.scryfall.com/cards/trix/6/en?format=image"); // TODO: missing from tokens data + put("RIX/Elemental/1", "https://api.scryfall.com/cards/trix/1/en?format=image"); + put("RIX/Elemental/2", "https://api.scryfall.com/cards/trix/2/en?format=image"); + put("RIX/Golem", "https://api.scryfall.com/cards/trix/4/en?format=image"); + put("RIX/Emblem Huatli, Radiant Champion", "https://api.scryfall.com/cards/trix/5/en?format=image"); + put("RIX/Saproling", "https://api.scryfall.com/cards/trix/3/en?format=image"); + + // generate supported sets + supportedSets.clear(); + for (String cardName : this.keySet()) { + String[] s = cardName.split("\\/"); + if (s.length > 1) { + supportedSets.putIfAbsent(s[0], s[0]); + } + } + } + }; + + public static Map getSupportedSets() { + return supportedSets; + } + + public static String findTokenLink(String setCode, String tokenName, Integer tokenNumber) { + String search = setCode + "/" + tokenName + (!tokenNumber.equals(0) ? "/" + tokenNumber : ""); + return supportedCards.getOrDefault(search, null); + } +} diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/TokensMtgImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/TokensMtgImageSource.java index ae000f70da..d501e30ffe 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/TokensMtgImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/TokensMtgImageSource.java @@ -1,6 +1,11 @@ - package org.mage.plugins.card.dl.sources; +import mage.constants.SubType; +import org.apache.log4j.Logger; +import org.mage.plugins.card.images.CardDownloadData; +import org.mage.plugins.card.images.DownloadPicturesService; +import org.mage.plugins.card.utils.CardImageUtils; + import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; @@ -8,21 +13,9 @@ import java.io.InputStreamReader; import java.net.Proxy; import java.net.URL; import java.net.URLConnection; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.logging.Level; -import mage.constants.SubType; -import org.apache.log4j.Logger; -import org.mage.plugins.card.images.CardDownloadData; -import org.mage.plugins.card.images.DownloadPicturesService; -import org.mage.plugins.card.utils.CardImageUtils; - /** * @author Quercitron */ @@ -58,7 +51,7 @@ public enum TokensMtgImageSource implements CardImageSource { } @Override - public CardImageUrls generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { return null; } @@ -160,7 +153,12 @@ public enum TokensMtgImageSource implements CardImageSource { } @Override - public boolean isImageProvided(String setCode, String cardName) { + public boolean isCardImageProvided(String setCode, String cardName) { + return false; + } + + @Override + public boolean isTokenImageProvided(String setCode, String cardName, Integer tokenNumber) { String searchName = cardName; if (cardName.toLowerCase(Locale.ENGLISH).contains("emblem")) { searchName = getEmblemName(cardName); diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/WizardCardsImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/WizardCardsImageSource.java index d0555b8242..0f335d7e9e 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/WizardCardsImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/WizardCardsImageSource.java @@ -452,7 +452,7 @@ public enum WizardCardsImageSource implements CardImageSource { } @Override - public CardImageUrls generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateCardUrl(CardDownloadData card) throws Exception { String collectorId = card.getCollectorId(); String cardSet = card.getSet(); if (collectorId == null || cardSet == null) { diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPicturesService.java b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPicturesService.java index 5ebcf5e176..ddec9bd3b4 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPicturesService.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPicturesService.java @@ -66,9 +66,9 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements private Proxy p = Proxy.NO_PROXY; enum DownloadSources { - WIZARDS("1. wizards.com - low quality CARDS, multi-language, can be SLOW", WizardCardsImageSource.instance), + WIZARDS("1. wizards.com - low quality CARDS, multi-language, slow download", WizardCardsImageSource.instance), TOKENS("2. tokens.mtg.onl - high quality TOKENS", TokensMtgImageSource.instance), - SCRYFALL("3. scryfall.com - high quality CARDS, multi-language", ScryfallImageSource.instance), + SCRYFALL("3. scryfall.com - high quality CARDS and TOKENS, multi-language", ScryfallImageSource.instance), MAGIDEX("4. magidex.com - high quality CARDS", MagidexImageSource.instance), GRAB_BAG("5. GrabBag - STAR WARS cards and tokens", GrabbagImageSource.instance), MYTHICSPOILER("6. mythicspoiler.com", MythicspoilerComSource.instance), @@ -332,7 +332,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements int numberCardImagesAvailable = 0; for (CardDownloadData data : cardsMissing) { if (data.isToken()) { - if (selectedSource.isTokenSource() && selectedSource.isImageProvided(data.getSet(), data.getName())) { + if (selectedSource.isTokenSource() && selectedSource.isTokenImageProvided(data.getSet(), data.getName(), data.getType())) { numberTokenImagesAvailable++; cardsDownloadQueue.add(data); } else { @@ -340,7 +340,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements } } else { if (selectedSets != null && selectedSets.contains(data.getSet())) { - if (selectedSource.isSetSupportedComplete(data.getSet()) || selectedSource.isImageProvided(data.getSet(), data.getName())) { + if (selectedSource.isSetSupportedComplete(data.getSet()) || selectedSource.isCardImageProvided(data.getSet(), data.getName())) { numberCardImagesAvailable++; cardsDownloadQueue.add(data); } @@ -495,7 +495,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements if (params.length >= 5) { int type = 0; if (params[4] != null && !params[4].isEmpty()) { - type = Integer.parseInt(params[4].trim()); + type = Integer.parseInt(params[4].trim()); // token number for same names } String fileName = ""; if (params.length > 5 && params[5] != null && !params[5].isEmpty()) { @@ -544,6 +544,16 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements logger.error(ex); throw new RuntimeException("DownloadPicturesService : readFile() error"); } + + // TODO: delete and move to copy-pate images download mode + /* + for (CardDownloadData card : list) { + if (card.isToken()) { + System.out.println(card.getSet() + "/" + card.getName() + (!card.getType().equals(0) ? "/" + card.getType() : "")); + } + } + */ + return list; } @@ -603,7 +613,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements } urls = selectedSource.generateTokenUrl(card); } else { - urls = selectedSource.generateURL(card); + urls = selectedSource.generateCardUrl(card); } if (urls == null) { @@ -924,7 +934,7 @@ class LoadMissingCardDataNew implements Runnable { private static DownloadPicturesService downloadPicturesService; public LoadMissingCardDataNew(DownloadPicturesService downloadPicturesService) { - this.downloadPicturesService = downloadPicturesService; + LoadMissingCardDataNew.downloadPicturesService = downloadPicturesService; } @Override @@ -935,5 +945,4 @@ class LoadMissingCardDataNew implements Runnable { public static void main() { (new Thread(new LoadMissingCardDataNew(downloadPicturesService))).start(); } - } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java b/Mage.Client/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java index 27e8c98f31..9d0d5730cc 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java @@ -175,7 +175,7 @@ public final class CardImageUtils { String prefixType = ""; if (card.getType() != 0) { - prefixType = " " + Integer.toString(card.getType()); + prefixType = " " + card.getType(); } String cardName = card.getFileName(); @@ -192,6 +192,7 @@ public final class CardImageUtils { finalFileName = cardName + prefixType + ".full.jpg"; } + /* 2019-01-12: no needs in name corrections, all files must be same and auto-downloaded // if image file exists, correct name (for case sensitive systems) // use TFile for zips TFile dirFile = new TFile(setPath); @@ -210,6 +211,7 @@ public final class CardImageUtils { } catch (Exception ex) { log.error("Can't read card name from file, may be it broken: " + setPath); } + */ return setPath + finalFileName; }