|
1 | 1 | package org.magic.api.decksniffer.impl; |
2 | 2 |
|
3 | | -import static org.magic.services.tools.MTG.getEnabledPlugin; |
4 | | - |
5 | 3 | import java.io.IOException; |
6 | 4 | import java.net.URI; |
7 | | -import java.net.URISyntaxException; |
8 | 5 | import java.util.ArrayList; |
| 6 | +import java.util.Arrays; |
9 | 7 | import java.util.List; |
10 | 8 | import java.util.Map; |
| 9 | +import java.util.stream.Collectors; |
11 | 10 |
|
12 | | -import org.jsoup.nodes.Document; |
13 | | -import org.jsoup.nodes.Element; |
14 | 11 | import org.magic.api.beans.MTGCard; |
15 | 12 | import org.magic.api.beans.MTGDeck; |
16 | | -import org.magic.api.beans.technical.MTGProperty; |
17 | 13 | import org.magic.api.beans.technical.RetrievableDeck; |
18 | 14 | import org.magic.api.interfaces.MTGCardsProvider; |
19 | 15 | import org.magic.api.interfaces.abstracts.AbstractDeckSniffer; |
20 | | -import org.magic.services.MTGConstants; |
21 | | -import org.magic.services.network.URLTools; |
| 16 | +import org.magic.services.network.RequestBuilder; |
| 17 | +import org.magic.services.tools.MTG; |
22 | 18 |
|
23 | | -public class TCGPlayerDeckSniffer extends AbstractDeckSniffer { |
24 | | - private static final String MAX_PAGE = "MAX_PAGE"; |
25 | | - private static final String SUBDECK_GROUP_CARD_QTY = "subdeck-group__card-qty"; |
| 19 | +import com.google.gson.JsonObject; |
26 | 20 |
|
| 21 | +public class TCGPlayerDeckSniffer extends AbstractDeckSniffer { |
| 22 | + |
27 | 23 | @Override |
28 | 24 | public String[] listFilter() { |
29 | | - return new String[]{"standard", "modern", "legacy", "vintage", "commander", "pioneer", "pauper", "historic", |
30 | | - "brawl"}; |
| 25 | + return new String[]{"standard", "modern", "legacy", "vintage", "commander", "pioneer", "pauper", "historic", "brawl"}; |
31 | 26 | } |
32 | 27 |
|
33 | 28 | @Override |
34 | 29 | public MTGDeck getDeck(RetrievableDeck info) throws IOException { |
35 | 30 | logger.debug("get deck at {}", info.getUrl()); |
36 | 31 | MTGDeck deck = info.toBaseDeck(); |
37 | | - Document d = URLTools.extractAsHtml(info.getUrl().toString()); |
38 | | - for (Element e : d.select("span.singleTag")) { |
39 | | - deck.getTags().add(e.text()); |
40 | | - } |
41 | | - |
42 | | - var main = d.getElementsByClass("subdeck"); |
43 | | - |
44 | | - int taille = main.get(0).getElementsByClass(SUBDECK_GROUP_CARD_QTY).size(); |
45 | | - for (var i = 0; i < taille; i++) { |
46 | | - var qte = Integer.parseInt(main.get(0).getElementsByClass(SUBDECK_GROUP_CARD_QTY).get(i).text()); |
47 | | - String cardName = main.get(0).getElementsByClass("subdeck-group__card-name").get(i).text(); |
48 | | - |
49 | | - if (cardName.contains("//")) |
50 | | - cardName = cardName.substring(0, cardName.indexOf("//")).trim(); |
51 | | - |
52 | | - MTGCard mc; |
53 | | - try { |
54 | | - mc = getEnabledPlugin(MTGCardsProvider.class).searchCardByName(cardName, null, true).get(0); |
55 | | - deck.getMain().put(mc, qte); |
56 | | - notify(mc); |
57 | | - } catch (IndexOutOfBoundsException e1) { |
58 | | - logger.error("{} is not found", cardName, e1); |
59 | | - } |
60 | | - |
61 | | - } |
62 | | - |
63 | | - if (main.size() > 1) { |
64 | | - int tailleSide = main.get(1).getElementsByClass(SUBDECK_GROUP_CARD_QTY).size(); |
65 | | - for (var i = 0; i < tailleSide; i++) { |
66 | | - var qte = Integer.parseInt(main.get(1).getElementsByClass(SUBDECK_GROUP_CARD_QTY).get(i).text()); |
67 | | - String cardName = main.get(1).getElementsByClass("subdeck-group__card-name").get(i).text(); |
68 | | - |
69 | | - if (cardName.contains("//")) |
70 | | - cardName = cardName.substring(0, cardName.indexOf("//")).trim(); |
71 | | - try { |
72 | | - MTGCard mc = getEnabledPlugin(MTGCardsProvider.class).searchCardByName(cardName, null, true).get(0); |
73 | | - deck.getSideBoard().put(mc, qte); |
74 | | - |
75 | | - } catch (IndexOutOfBoundsException e1) { |
76 | | - logger.error("{} is not found", cardName, e1); |
77 | | - } |
78 | | - |
79 | | - } |
80 | | - } |
81 | | - |
| 32 | + |
| 33 | + var obj = RequestBuilder.build().newClient().get().url(info.getUrl()) |
| 34 | + .addContent("source", "infinite-content") |
| 35 | + .addContent("subDecks", "true") |
| 36 | + .addContent("cards", "true") |
| 37 | + .addContent("stats", "false") |
| 38 | + .toJson().getAsJsonObject().get("result").getAsJsonObject(); |
| 39 | + |
| 40 | + |
| 41 | + fillData(obj, "maindeck", deck.getMain()); |
| 42 | + fillData(obj, "sideboard", deck.getSideBoard()); |
| 43 | + |
82 | 44 | return deck; |
83 | 45 |
|
84 | 46 | } |
| 47 | + |
| 48 | + private void fillData(JsonObject obj, String side, Map<MTGCard,Integer> data) |
| 49 | + { |
| 50 | + obj.get("deck").getAsJsonObject().get("subDecks").getAsJsonObject().get(side).getAsJsonArray().forEach(je->{ |
| 51 | + |
| 52 | + var id= je.getAsJsonObject().get("cardID").getAsString(); |
| 53 | + var cardData = obj.get("cards").getAsJsonObject().get(id).getAsJsonObject(); |
| 54 | + var qty = je.getAsJsonObject().get("quantity").getAsInt(); |
| 55 | + data.put(parseCard(cardData), qty); |
| 56 | + }); |
| 57 | + } |
| 58 | + |
| 59 | + |
| 60 | + private MTGCard parseCard(JsonObject obj) { |
| 61 | + |
| 62 | + var name = obj.get("name").getAsString(); |
| 63 | + var set = obj.get("set").getAsString(); |
| 64 | + try { |
| 65 | + var edition = MTG.getEnabledPlugin(MTGCardsProvider.class).getSetById(set); |
| 66 | + var mc = MTG.getEnabledPlugin(MTGCardsProvider.class).searchCardByName(obj.get("name").getAsString(), edition, true).getFirst(); |
| 67 | + notify(mc); |
| 68 | + return mc; |
| 69 | + |
| 70 | + } catch (Exception e) { |
| 71 | + logger.error("can't find card for {}/{}",name,set); |
| 72 | + } |
| 73 | + |
| 74 | + return null; |
| 75 | + } |
85 | 76 |
|
86 | 77 | @Override |
87 | 78 | public List<RetrievableDeck> getDeckList(String filter, MTGCard mc) throws IOException { |
88 | 79 |
|
89 | | - var baseUrl = "https://decks.tcgplayer.com"; |
90 | | - |
91 | | - String url = baseUrl + "/magic/deck/search?format=" + filter; |
92 | | - logger.debug("get List deck at {}", url); |
93 | | - var list = new ArrayList<RetrievableDeck>(); |
94 | | - |
95 | | - for (var i = 1; i <= getInt(MAX_PAGE); i++) { |
96 | | - url = baseUrl + "/magic/deck/search?format=" + filter + "&page=" + i; |
97 | | - Document d = URLTools.extractAsHtml(url); |
98 | | - |
99 | | - for (Element tr : d.getElementsByClass("gradeA")) { |
100 | | - var deck = new RetrievableDeck(); |
101 | | - |
102 | | - var mana = ""; |
103 | | - |
104 | | - Element manaEl = tr.getElementsByTag(MTGConstants.HTML_TAG_TD).get(0); |
105 | | - if (manaEl.toString().contains("white-mana")) |
106 | | - mana += "{W}"; |
107 | | - if (manaEl.toString().contains("blue-mana")) |
108 | | - mana += "{U}"; |
109 | | - if (manaEl.toString().contains("black-mana")) |
110 | | - mana += "{B}"; |
111 | | - if (manaEl.toString().contains("red-mana")) |
112 | | - mana += "{R}"; |
113 | | - if (manaEl.toString().contains("green-mana")) |
114 | | - mana += "{G}"; |
115 | | - |
116 | | - String deckName = tr.getElementsByTag(MTGConstants.HTML_TAG_TD).get(1).text(); |
117 | | - String link = baseUrl |
118 | | - + tr.getElementsByTag(MTGConstants.HTML_TAG_TD).get(1).getElementsByTag("a").attr("href"); |
119 | | - String deckPlayer = tr.getElementsByTag(MTGConstants.HTML_TAG_TD).get(2).text(); |
120 | | - String deckDesc = tr.getElementsByTag(MTGConstants.HTML_TAG_TD).get(3).text(); |
121 | | - |
122 | | - deck.setColor(mana); |
123 | | - deck.setAuthor(deckPlayer); |
124 | | - deck.setName(deckName); |
125 | | - deck.setDescription(deckDesc); |
126 | | - |
127 | | - try { |
128 | | - deck.setUrl(new URI(link)); |
129 | | - } catch (URISyntaxException _) { |
130 | | - deck.setUrl(null); |
131 | | - } |
132 | | - |
133 | | - list.add(deck); |
134 | | - |
135 | | - } |
136 | | - |
137 | | - } |
138 | | - |
139 | | - return list; |
140 | | - |
| 80 | + var list = new ArrayList<RetrievableDeck>(); |
| 81 | + |
| 82 | + var obj = RequestBuilder.build().newClient().get().url("https://infinite-api.tcgplayer.com/content/decks/magic") |
| 83 | + .addContent("source", "infinite-content") |
| 84 | + .addContent("rows", "128") |
| 85 | + .addContent("format", filter) |
| 86 | + .addContent("isAdmin", "false") |
| 87 | + .addContent("td", "false") |
| 88 | + .addContent("sort", "latest") |
| 89 | + .addContent("offset", "0") |
| 90 | + .addContent("order", "desc").toJson().getAsJsonObject(); |
| 91 | + |
| 92 | + |
| 93 | + for(var d : obj.get("result").getAsJsonArray()) |
| 94 | + { |
| 95 | + var deck = new RetrievableDeck(); |
| 96 | + |
| 97 | + deck.setAuthor(d.getAsJsonObject().get("deckData").getAsJsonObject().get("playerName").getAsString()); |
| 98 | + deck.setDescription(d.getAsJsonObject().get("date").getAsString()); |
| 99 | + deck.setName(d.getAsJsonObject().get("deckData").getAsJsonObject().get("deckName").getAsString()); |
| 100 | + deck.setUrl(URI.create("https://infinite-api.tcgplayer.com/deck/magic/"+d.getAsJsonObject().get("deckID").getAsString())); |
| 101 | + |
| 102 | + if(d.getAsJsonObject().get("deckData").getAsJsonObject().get("colors")!=null) |
| 103 | + deck.setColor(Arrays.stream(d.getAsJsonObject().get("deckData").getAsJsonObject().get("colors").getAsString().split(",")).map(s -> "{" + s + "}").collect(Collectors.joining())); |
| 104 | + |
| 105 | + list.add(deck); |
| 106 | + } |
| 107 | + return list; |
141 | 108 | } |
142 | 109 |
|
143 | 110 | @Override |
144 | 111 | public String getName() { |
145 | 112 | return "TCGPlayer"; |
146 | 113 | } |
147 | 114 |
|
148 | | - @Override |
149 | | - public Map<String, MTGProperty> getDefaultAttributes() { |
150 | | - |
151 | | - var m = super.getDefaultAttributes(); |
152 | | - m.put(MAX_PAGE, MTGProperty.newIntegerProperty("1", "number of page to query", 1, 10)); |
153 | | - return m; |
154 | | - } |
155 | | - |
156 | 115 | } |
0 commit comments