From 6c20ee4a74397da165267b6080ae9d3bf98a31a6 Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Sat, 23 Jun 2018 16:27:34 +0400 Subject: [PATCH] * Images: added localized card images download from scryfall source; --- .../sources/AltMtgOnlTokensImageSource.java | 9 +- .../card/dl/sources/CardImageSource.java | 4 +- .../card/dl/sources/CardImageUrls.java | 59 ++++++++++ .../card/dl/sources/GrabbagImageSource.java | 8 +- .../dl/sources/MagicCardsImageSource.java | 11 +- .../card/dl/sources/MagidexImageSource.java | 8 +- .../card/dl/sources/MtgImageSource.java | 10 +- .../dl/sources/MtgOnlTokensImageSource.java | 6 +- .../dl/sources/MythicspoilerComSource.java | 10 +- .../card/dl/sources/ScryfallImageSource.java | 58 +++++++--- .../card/dl/sources/TokensMtgImageSource.java | 10 +- .../dl/sources/WizardCardsImageSource.java | 15 ++- .../plugins/card/images/DownloadPictures.java | 102 ++++++++++++------ .../client/game/TokensMtgImageSourceTest.java | 13 +-- 14 files changed, 230 insertions(+), 93 deletions(-) create mode 100644 Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageUrls.java 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 6d69569614..df290687c1 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 @@ -8,7 +8,6 @@ import java.io.IOException; import java.util.HashMap; /** - * * @author spjspj */ public enum AltMtgOnlTokensImageSource implements CardImageSource { @@ -60,7 +59,7 @@ public enum AltMtgOnlTokensImageSource implements CardImageSource { } @Override - public String generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateURL(CardDownloadData card) throws Exception { return null; } @@ -122,7 +121,7 @@ public enum AltMtgOnlTokensImageSource implements CardImageSource { } @Override - public String generateTokenUrl(CardDownloadData card) throws IOException { + public CardImageUrls generateTokenUrl(CardDownloadData card) throws IOException { if (copyUrlToImage == null) { setupLinks(); } @@ -139,12 +138,12 @@ public enum AltMtgOnlTokensImageSource implements CardImageSource { } return -1; } - + @Override public boolean isTokenSource() { return true; } - + @Override public void doPause(String httpImageUrl) { } 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 e49c334a1c..f2d0fabf75 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 @@ -9,9 +9,9 @@ import org.mage.plugins.card.images.CardDownloadData; */ public interface CardImageSource { - String generateURL(CardDownloadData card) throws Exception; + CardImageUrls generateURL(CardDownloadData card) throws Exception; - String generateTokenUrl(CardDownloadData card) throws Exception; + CardImageUrls generateTokenUrl(CardDownloadData card) throws Exception; String getNextHttpImageUrl(); diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageUrls.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageUrls.java new file mode 100644 index 0000000000..1176ad3fed --- /dev/null +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageUrls.java @@ -0,0 +1,59 @@ +package org.mage.plugins.card.dl.sources; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author JayDi85 + */ +public class CardImageUrls { + + public String baseUrl; + public List alternativeUrls; + + public CardImageUrls() { + this.baseUrl = null; + this.alternativeUrls = new ArrayList<>(); + } + + public CardImageUrls(String baseUrl) { + this(baseUrl, null); + } + + public CardImageUrls(String baseUrl, String alternativeUrl) { + this(); + + this.baseUrl = baseUrl; + + if (alternativeUrl != null && !alternativeUrl.isEmpty()) { + this.alternativeUrls.add(alternativeUrl); + } + } + + public List getDownloadList() { + List downloadUrls = new ArrayList<>(); + + if (this.baseUrl != null && !this.baseUrl.isEmpty()) { + downloadUrls.add(this.baseUrl); + } + + // no needs in base url duplicate + if (this.alternativeUrls != null) { + for (String url : this.alternativeUrls) { + if (!url.equals(this.baseUrl)) { + downloadUrls.add(url); + } + } + } + + return downloadUrls; + } + + public void addAlternativeUrl(String url) { + if (url != null && !url.isEmpty()) { + this.alternativeUrls.add(url); + } else { + throw new IllegalArgumentException(); + } + } +} 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 38bb08048a..2d39d4e9d3 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 @@ -8,11 +8,11 @@ import java.util.LinkedHashSet; 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 */ public enum GrabbagImageSource implements CardImageSource { @@ -48,7 +48,7 @@ public enum GrabbagImageSource implements CardImageSource { } @Override - public String generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateURL(CardDownloadData card) throws Exception { if (singleLinks == null) { setupLinks(); } @@ -63,7 +63,7 @@ public enum GrabbagImageSource implements CardImageSource { } if (url != null) { - return getSourceName(card, url) + url; + return new CardImageUrls(getSourceName(card, url) + url); } return null; } @@ -375,7 +375,7 @@ public enum GrabbagImageSource implements CardImageSource { } @Override - public String generateTokenUrl(CardDownloadData card) throws IOException { + public CardImageUrls generateTokenUrl(CardDownloadData card) throws IOException { try { return generateURL(card); } catch (Exception ex) { diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagicCardsImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagicCardsImageSource.java index 5b72b8aa10..dfee0c9a46 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagicCardsImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagicCardsImageSource.java @@ -6,12 +6,12 @@ import java.util.LinkedHashSet; import java.util.Locale; import java.util.Map; import java.util.Set; + import mage.client.dialog.PreferencesDialog; import org.mage.plugins.card.images.CardDownloadData; import org.mage.plugins.card.utils.CardImageUtils; /** - * * @author North */ public enum MagicCardsImageSource implements CardImageSource { @@ -342,6 +342,7 @@ public enum MagicCardsImageSource implements CardImageSource { put("WWK", "worldwake"); put("ZEN", "zendikar"); } + private static final long serialVersionUID = 1L; }; @@ -361,7 +362,7 @@ public enum MagicCardsImageSource implements CardImageSource { } @Override - public String generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateURL(CardDownloadData card) throws Exception { String collectorId = card.getCollectorId(); String cardSet = card.getSet(); if (collectorId == null || cardSet == null) { @@ -389,11 +390,11 @@ public enum MagicCardsImageSource implements CardImageSource { } url.append(".jpg"); - return url.toString(); + return new CardImageUrls(url.toString()); } @Override - public String generateTokenUrl(CardDownloadData card) { + public CardImageUrls generateTokenUrl(CardDownloadData card) { String name = card.getName(); // add type to name if it's not 0 if (card.getType() > 0) { @@ -406,7 +407,7 @@ public enum MagicCardsImageSource implements CardImageSource { } else { set += '-' + card.getSet(); } - return "http://magiccards.info/extras/token/" + set + '/' + name + ".jpg"; + return new CardImageUrls("http://magiccards.info/extras/token/" + set + '/' + name + ".jpg"); } @Override 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 cb03cf6496..f8601c1043 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 @@ -8,10 +8,10 @@ import java.util.LinkedHashSet; import java.util.Locale; import java.util.Map; import java.util.Set; + import org.mage.plugins.card.images.CardDownloadData; /** - * * @author Pete Rossi */ public enum MagidexImageSource implements CardImageSource { @@ -233,7 +233,7 @@ public enum MagidexImageSource implements CardImageSource { } @Override - public String generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateURL(CardDownloadData card) throws Exception { String cardDownloadName = card.getDownloadName().toLowerCase(Locale.ENGLISH); String cardSet = card.getSet(); @@ -247,7 +247,7 @@ public enum MagidexImageSource implements CardImageSource { // This will properly escape the url URI uri = new URI("http", "magidex.com", "/extstatic/card/" + formatSetName(cardSet) + '/' + cardDownloadName + ".jpg", null, null); - return uri.toASCIIString(); + return new CardImageUrls(uri.toASCIIString()); } private String formatSetName(String setName) { @@ -264,7 +264,7 @@ public enum MagidexImageSource implements CardImageSource { }; @Override - public String generateTokenUrl(CardDownloadData card) { + public CardImageUrls generateTokenUrl(CardDownloadData card) { return null; } 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 d24ba0c499..f5104a2226 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 @@ -2,14 +2,12 @@ package org.mage.plugins.card.dl.sources; import java.util.Locale; + import org.mage.plugins.card.images.CardDownloadData; /** * Site was shutdown by wizards Feb. 2015 * - * - * - * * @author LevelX2 */ public enum MtgImageSource implements CardImageSource { @@ -32,7 +30,7 @@ public enum MtgImageSource implements CardImageSource { } @Override - public String generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateURL(CardDownloadData card) throws Exception { String collectorId = card.getCollectorId(); String cardSet = card.getSet(); if (collectorId == null || cardSet == null) { @@ -59,11 +57,11 @@ public enum MtgImageSource implements CardImageSource { } url.append(".jpg"); - return url.toString(); + return new CardImageUrls(url.toString()); } @Override - public String generateTokenUrl(CardDownloadData card) { + public CardImageUrls generateTokenUrl(CardDownloadData card) { return 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 4b2bf849db..9d82cbb425 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 @@ -3,11 +3,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; /** - * * @author spjspj */ public enum MtgOnlTokensImageSource implements CardImageSource { @@ -59,7 +59,7 @@ public enum MtgOnlTokensImageSource implements CardImageSource { } @Override - public String generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateURL(CardDownloadData card) throws Exception { return null; } @@ -324,7 +324,7 @@ public enum MtgOnlTokensImageSource implements CardImageSource { } @Override - public String generateTokenUrl(CardDownloadData card) throws IOException { + public CardImageUrls generateTokenUrl(CardDownloadData card) throws IOException { if (copyUrlToImage == null) { setupLinks(); } 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 8e3625dbbb..9a1f95093d 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 @@ -18,6 +18,7 @@ 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; @@ -28,7 +29,6 @@ import org.jsoup.select.Elements; import org.mage.plugins.card.images.CardDownloadData; /** - * * @author LevelX2 */ public enum MythicspoilerComSource implements CardImageSource { @@ -329,7 +329,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; @@ -391,7 +391,7 @@ public enum MythicspoilerComSource implements CardImageSource { } @Override - public String generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateURL(CardDownloadData card) throws Exception { String collectorId = card.getCollectorId(); String cardSet = card.getSet(); if (collectorId == null || cardSet == null) { @@ -410,11 +410,11 @@ public enum MythicspoilerComSource implements CardImageSource { .replaceAll(",", "") .replaceAll("/", ""); String link = setLinks.get(searchName); - return link; + return new CardImageUrls(link); } @Override - public String generateTokenUrl(CardDownloadData card + public CardImageUrls generateTokenUrl(CardDownloadData card ) { return 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 2cb30a5a2e..a99cf3f287 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 @@ -6,19 +6,34 @@ import java.util.LinkedHashSet; import java.util.Locale; import java.util.Map; import java.util.Set; + +import mage.client.dialog.PreferencesDialog; import org.mage.plugins.card.images.CardDownloadData; /** * @author Quercitron, JayDi85 - * */ public enum ScryfallImageSource implements CardImageSource { instance; private final Set supportedSets; + private final Map languageAliases; ScryfallImageSource() { + // https://scryfall.com/docs/api/languages + languageAliases = new HashMap<>(); + languageAliases.put("en", "en"); + languageAliases.put("es", "es"); + languageAliases.put("jp", "ja"); + languageAliases.put("it", "it"); + languageAliases.put("fr", "fr"); + languageAliases.put("cn", "zhs"); // Simplified Chinese + languageAliases.put("de", "de"); + languageAliases.put("ko", "ko"); + languageAliases.put("pt", "pt"); + languageAliases.put("ru", "ru"); + supportedSets = new LinkedHashSet<>(); // supportedSets.add("PTC"); // supportedSets.add("LEA"); @@ -214,33 +229,52 @@ public enum ScryfallImageSource implements CardImageSource { supportedSets.add("BBD"); // supportedSets.add("CM2"); supportedSets.add("M19"); - } @Override - public String generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateURL(CardDownloadData card) throws Exception { + + String preferredLanguage = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PREF_LANGUAGE, "en"); + String defaultCode = "en"; + String localizedCode = languageAliases.getOrDefault(preferredLanguage, defaultCode); + // loc example: https://api.scryfall.com/cards/xln/121/ru?format=image + + // TODO: do not use API at all? It's can help with scryfall request limits (1 request instead 2) + + String baseUrl = null; + String alternativeUrl = null; // special card number like "103a" already compatible - if (card.isCollectorIdWithStr()) { - return "https://img.scryfall.com/cards/large/en/" + formatSetName(card.getSet()) + "/" + if (baseUrl == null && card.isCollectorIdWithStr()) { + baseUrl = "https://img.scryfall.com/cards/large/" + localizedCode + "/" + formatSetName(card.getSet()) + "/" + + card.getCollectorId() + ".jpg"; + alternativeUrl = "https://img.scryfall.com/cards/large/" + defaultCode + "/" + formatSetName(card.getSet()) + "/" + card.getCollectorId() + ".jpg"; } - // double faced cards do not supporte by API (need direct link for img) + // 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 (card.isTwoFacedCard()) { - return "https://img.scryfall.com/cards/large/en/" + formatSetName(card.getSet()) + "/" + if (baseUrl == null && card.isTwoFacedCard()) { + baseUrl = "https://img.scryfall.com/cards/large/" + localizedCode + "/" + formatSetName(card.getSet()) + "/" + + card.getCollectorId() + (card.isSecondSide() ? "b" : "a") + ".jpg"; + alternativeUrl = "https://img.scryfall.com/cards/large/" + defaultCode + "/" + formatSetName(card.getSet()) + "/" + card.getCollectorId() + (card.isSecondSide() ? "b" : "a") + ".jpg"; } // basic cards by api call (redirect to img link) - // example: https://api.scryfall.com/cards/xln/121?format=image - return "https://api.scryfall.com/cards/" + formatSetName(card.getSet()) + "/" - + card.getCollectorId() + "?format=image"; + // example: https://api.scryfall.com/cards/xln/121/en?format=image + if (baseUrl == null) { + baseUrl = "https://api.scryfall.com/cards/" + formatSetName(card.getSet()) + "/" + + card.getCollectorId() + "/" + localizedCode + "?format=image"; + alternativeUrl = "https://api.scryfall.com/cards/" + formatSetName(card.getSet()) + "/" + + card.getCollectorId() + "/" + defaultCode + "?format=image"; + } + + return new CardImageUrls(baseUrl, alternativeUrl); } @Override - public String generateTokenUrl(CardDownloadData card) throws Exception { + public CardImageUrls generateTokenUrl(CardDownloadData card) throws Exception { return 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 589cc4640d..da76bfc8b6 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 @@ -16,6 +16,7 @@ import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.logging.Level; + import mage.constants.SubType; import org.apache.log4j.Logger; import org.mage.plugins.card.images.CardDownloadData; @@ -23,7 +24,6 @@ import org.mage.plugins.card.images.DownloadPictures; import org.mage.plugins.card.utils.CardImageUtils; /** - * * @author Quercitron */ public enum TokensMtgImageSource implements CardImageSource { @@ -58,7 +58,7 @@ public enum TokensMtgImageSource implements CardImageSource { } @Override - public String generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateURL(CardDownloadData card) throws Exception { return null; } @@ -80,7 +80,7 @@ public enum TokensMtgImageSource implements CardImageSource { } @Override - public String generateTokenUrl(CardDownloadData card) throws IOException { + public CardImageUrls generateTokenUrl(CardDownloadData card) throws IOException { String name = card.getName(); String set = card.getSet(); int type = card.getType(); @@ -125,7 +125,7 @@ public enum TokensMtgImageSource implements CardImageSource { String url = "http://tokens.mtg.onl/tokens/" + tokenData.getExpansionSetCode().trim() + '_' + tokenData.getNumber().trim() + '-' + tokenData.getName().trim() + ".jpg"; url = url.replace(' ', '-'); - return url; + return new CardImageUrls(url); } @Override @@ -248,7 +248,7 @@ public enum TokensMtgImageSource implements CardImageSource { List newTokensData = new ArrayList<>(); try (InputStreamReader inputReader = new InputStreamReader(inputStream, "Cp1252"); - BufferedReader reader = new BufferedReader(inputReader)) { + BufferedReader reader = new BufferedReader(inputReader)) { // we have to specify encoding to read special comma reader.readLine(); // skip header 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 2c200b624b..dff6ed8304 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 @@ -20,6 +20,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.prefs.Preferences; + import mage.cards.Sets; import mage.cards.repository.CardCriteria; import mage.cards.repository.CardInfo; @@ -462,7 +463,7 @@ public enum WizardCardsImageSource implements CardImageSource { } @Override - public String generateURL(CardDownloadData card) throws Exception { + public CardImageUrls generateURL(CardDownloadData card) throws Exception { String collectorId = card.getCollectorId(); String cardSet = card.getSet(); if (collectorId == null || cardSet == null) { @@ -495,7 +496,7 @@ public enum WizardCardsImageSource implements CardImageSource { List l = new ArrayList<>(setLinks.values()); if (l.size() >= number) { link = l.get(number - 1); - } else {; + } else { link = l.get(number - 21); if (link != null) { link = link.replace(Integer.toString(number - 20), (Integer.toString(number - 20) + 'a')); @@ -508,8 +509,12 @@ public enum WizardCardsImageSource implements CardImageSource { if (link != null && !link.startsWith("http://")) { link = "http://gatherer.wizards.com" + link; } - return link; + if (link != null) { + return new CardImageUrls(link); + } else { + return null; + } } private Map getSetLinks(String cardSet) { @@ -703,7 +708,7 @@ public enum WizardCardsImageSource implements CardImageSource { } @Override - public String generateTokenUrl(CardDownloadData card) { + public CardImageUrls generateTokenUrl(CardDownloadData card) { return null; } @@ -712,7 +717,7 @@ public enum WizardCardsImageSource implements CardImageSource { return 60.0f; } -// private final class GetImageLinkTask implements Runnable { + // private final class GetImageLinkTask implements Runnable { // // private int multiverseId; // private String cardName; diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java index 389c0be5a7..0153ff3367 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java @@ -15,6 +15,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import javax.swing.*; + import mage.cards.ExpansionSet; import mage.cards.Sets; import mage.cards.repository.CardCriteria; @@ -33,6 +34,7 @@ import org.apache.log4j.Logger; import org.mage.plugins.card.dl.sources.*; import org.mage.plugins.card.properties.SettingsManager; import org.mage.plugins.card.utils.CardImageUtils; + import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir; public class DownloadPictures extends DefaultBoundedRangeModel implements Runnable { @@ -485,7 +487,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab } try (InputStreamReader input = new InputStreamReader(in); - BufferedReader reader = new BufferedReader(input)) { + BufferedReader reader = new BufferedReader(input)) { String line = reader.readLine(); while (line != null) { @@ -597,25 +599,25 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab logger.debug("Downloading image: " + card.getName() + " (" + card.getSet() + ')'); - String url; + CardImageUrls urls; + if (ignoreUrls.contains(card.getSet()) || card.isToken()) { if (!"0".equals(card.getCollectorId())) { continue; } - url = cardImageSource.generateTokenUrl(card); + urls = cardImageSource.generateTokenUrl(card); } else { - url = cardImageSource.generateURL(card); + urls = cardImageSource.generateURL(card); } - if (url == null) { + if (urls == null) { String imageRef = cardImageSource.getNextHttpImageUrl(); String fileName = cardImageSource.getFileForHttpImage(imageRef); if (imageRef != null && fileName != null) { imageRef = cardImageSource.getSourceName() + imageRef; try { - URL imageUrl = new URL(imageRef); card.setToken(cardImageSource.isTokenSource()); - Runnable task = new DownloadTask(card, imageUrl, fileName, cardImageSource.getTotalImages()); + Runnable task = new DownloadTask(card, imageRef, fileName, cardImageSource.getTotalImages()); executor.execute(task); } catch (Exception ex) { } @@ -626,7 +628,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab } } } else { - Runnable task = new DownloadTask(card, new URL(url), cardsToDownload.size()); + Runnable task = new DownloadTask(card, urls, cardsToDownload.size()); executor.execute(task); } @@ -662,22 +664,26 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab private final class DownloadTask implements Runnable { private final CardDownloadData card; - private final URL url; + private final CardImageUrls urls; private final int count; private final String actualFilename; private final boolean useSpecifiedPaths; - DownloadTask(CardDownloadData card, URL url, int count) { + DownloadTask(CardDownloadData card, String baseUrl, int count) { + this(card, new CardImageUrls(baseUrl, null), count); + } + + DownloadTask(CardDownloadData card, CardImageUrls urls, int count) { this.card = card; - this.url = url; + this.urls = urls; this.count = count; this.actualFilename = ""; useSpecifiedPaths = false; } - DownloadTask(CardDownloadData card, URL url, String actualFilename, int count) { + DownloadTask(CardDownloadData card, String baseUrl, String actualFilename, int count) { this.card = card; - this.url = url; + this.urls = new CardImageUrls(baseUrl, null); this.count = count; this.actualFilename = actualFilename; useSpecifiedPaths = true; @@ -751,14 +757,55 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab } } - cardImageSource.doPause(url.getPath()); - URLConnection httpConn = url.openConnection(p); - httpConn.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2"); - httpConn.connect(); - int responseCode = ((HttpURLConnection) httpConn).getResponseCode(); + // can download images from many alternative urls + List downloadUrls; + if (this.urls != null) { + downloadUrls = this.urls.getDownloadList(); + } else { + downloadUrls = new ArrayList<>(); + } - if (responseCode == 200) { - // download OK + boolean isDownloadOK = false; + URLConnection httpConn = null; + List errorsList = new ArrayList<>(); + for (String currentUrl : downloadUrls) { + URL url = new URL(currentUrl); + + // on download cancel need to stop + if (cancel) { + return; + } + + // download + cardImageSource.doPause(url.getPath()); + httpConn = url.openConnection(p); + httpConn.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2"); + httpConn.connect(); + int responseCode = ((HttpURLConnection) httpConn).getResponseCode(); + + // check result + if (responseCode != 200) { + // show errors only on full fail (all urls were not work) + errorsList.add("Image download for " + card.getName() + + (!card.getDownloadName().equals(card.getName()) ? " downloadname: " + card.getDownloadName() : "") + + " (" + card.getSet() + ") failed - responseCode: " + responseCode + " url: " + url.toString()); + + if (logger.isDebugEnabled()) { + // Shows the returned html from the request to the web server + logger.debug("Returned HTML ERROR:\n" + convertStreamToString(((HttpURLConnection) httpConn).getErrorStream())); + } + + // go to next try + continue; + } else { + // all fine + isDownloadOK = true; + break; + } + } + + // can save result + if (isDownloadOK & httpConn != null) { // save data to temp OutputStream out = null; OutputStream tfileout = null; @@ -792,8 +839,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab } out.write(buf, 0, len); } - } - finally { + } finally { StreamUtils.closeQuietly(in); StreamUtils.closeQuietly(out); StreamUtils.closeQuietly(tfileout); @@ -815,15 +861,9 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab } } else { - // download ERROR - logger.warn("Image download for " + card.getName() - + (!card.getDownloadName().equals(card.getName()) ? " downloadname: " + card.getDownloadName() : "") - + " (" + card.getSet() + ") failed - responseCode: " + responseCode + " url: " + url.toString() - ); - - if (logger.isDebugEnabled()) { - // Shows the returned html from the request to the web server - logger.debug("Returned HTML ERROR:\n" + convertStreamToString(((HttpURLConnection) httpConn).getErrorStream())); + // download errors + for (String err : errorsList) { + logger.warn(err); } } diff --git a/Mage.Client/src/test/java/mage/client/game/TokensMtgImageSourceTest.java b/Mage.Client/src/test/java/mage/client/game/TokensMtgImageSourceTest.java index 8e485c801e..16f4e618f1 100644 --- a/Mage.Client/src/test/java/mage/client/game/TokensMtgImageSourceTest.java +++ b/Mage.Client/src/test/java/mage/client/game/TokensMtgImageSourceTest.java @@ -4,11 +4,11 @@ import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; import org.mage.plugins.card.dl.sources.CardImageSource; +import org.mage.plugins.card.dl.sources.CardImageUrls; import org.mage.plugins.card.dl.sources.TokensMtgImageSource; import org.mage.plugins.card.images.CardDownloadData; /** - * * @author Quercitron */ @Ignore @@ -18,15 +18,16 @@ public class TokensMtgImageSourceTest { public void generateTokenUrlTest() throws Exception { CardImageSource imageSource = TokensMtgImageSource.instance; - String url = imageSource.generateTokenUrl(new CardDownloadData("Thopter", "ORI", "0", false, 1, "ORI", "")); - Assert.assertEquals("http://tokens.mtg.onl/tokens/ORI_010-Thopter.jpg", url); + CardImageUrls url = imageSource.generateTokenUrl(new CardDownloadData("Thopter", "ORI", "0", false, 1, "ORI", "")); + Assert.assertEquals("http://tokens.mtg.onl/tokens/ORI_010-Thopter.jpg", url.baseUrl); + url = imageSource.generateTokenUrl(new CardDownloadData("Thopter", "ORI", "0", false, 2, "ORI", "")); - Assert.assertEquals("http://tokens.mtg.onl/tokens/ORI_011-Thopter.jpg", url); + Assert.assertEquals("http://tokens.mtg.onl/tokens/ORI_011-Thopter.jpg", url.baseUrl); url = imageSource.generateTokenUrl(new CardDownloadData("Ashaya, the Awoken World", "ORI", "0", false, 0, "ORI", "")); - Assert.assertEquals("http://tokens.mtg.onl/tokens/ORI_007-Ashaya,-the-Awoken-World.jpg", url); + Assert.assertEquals("http://tokens.mtg.onl/tokens/ORI_007-Ashaya,-the-Awoken-World.jpg", url.baseUrl); url = imageSource.generateTokenUrl(new CardDownloadData("Emblem Gideon, Ally of Zendikar", "BFZ", "0", false, 0, null, "")); - Assert.assertEquals("http://tokens.mtg.onl/tokens/BFZ_012-Gideon-Emblem.jpg", url); + Assert.assertEquals("http://tokens.mtg.onl/tokens/BFZ_012-Gideon-Emblem.jpg", url.baseUrl); } }