Add code to retrieve card images
This commit is contained in:
parent
9076edb6f6
commit
f0758a2cce
|
@ -1,5 +1,16 @@
|
|||
package scryfall
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
const SCRYFALL_API_CARDS = "/cards/"
|
||||
const CARD_IMAGEURIS_KEY_PNG = "png"
|
||||
|
||||
type Card struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
|
@ -12,3 +23,38 @@ type Card struct {
|
|||
ImageUris map[string]string `json:"image_uris"`
|
||||
Language string `json:"lang"`
|
||||
}
|
||||
|
||||
func (c *ScryfallClient) GetCardById(id string) (Card, error) {
|
||||
var card Card
|
||||
|
||||
response, err := c.httpClient.Get(c.baseURL + SCRYFALL_API_CARDS + id)
|
||||
if err != nil {
|
||||
return card, err
|
||||
}
|
||||
|
||||
if response.StatusCode != http.StatusOK {
|
||||
return card, errors.New("HTTP request failed with code: " + fmt.Sprint(response.StatusCode))
|
||||
}
|
||||
|
||||
defer response.Body.Close()
|
||||
cardBytes, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return card, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(cardBytes, &card)
|
||||
if err != nil {
|
||||
return card, err
|
||||
}
|
||||
|
||||
return card, nil
|
||||
}
|
||||
|
||||
func (c *ScryfallClient) GetCardImageUrlById(id string) (string, error) {
|
||||
card, err := c.GetCardById(id)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return card.ImageUris[CARD_IMAGEURIS_KEY_PNG], nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
package scryfall
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const TEST_ID = "56ebc372-aabd-4174-a943-c7bf59e5028d"
|
||||
const TEST_ENDPOINT = "/cards/" + TEST_ID
|
||||
const TESTDATA_DIRECTORY = "testdata/"
|
||||
const TEST_GOOD_CARD_DATA_FILENAME = "card.json"
|
||||
|
||||
var (
|
||||
mux *http.ServeMux
|
||||
server *httptest.Server
|
||||
client *ScryfallClient
|
||||
)
|
||||
|
||||
func setup() func() {
|
||||
mux = http.NewServeMux()
|
||||
server = httptest.NewServer(mux)
|
||||
|
||||
client, _ = NewScryfallClient(BaseURL(server.URL))
|
||||
|
||||
return func() {
|
||||
server.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func fixture(filename string) string {
|
||||
bytes, err := ioutil.ReadFile(TESTDATA_DIRECTORY + filename)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return string(bytes)
|
||||
}
|
||||
|
||||
func Test_GetCardImageUrlById_ReturnsUrl_ForSuccessfulRequest(t *testing.T) {
|
||||
teardown := setup()
|
||||
defer teardown()
|
||||
|
||||
mux.HandleFunc(TEST_ENDPOINT, func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintf(w, fixture(TEST_GOOD_CARD_DATA_FILENAME))
|
||||
})
|
||||
|
||||
url, err := client.GetCardImageUrlById(TEST_ID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if url != "https://cards.scryfall.io/png/front/5/6/56ebc372-aabd-4174-a943-c7bf59e5028d.png?1562629953" {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package scryfall
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
const SCRYFALL_API_URL string = "https://api.scryfall.com/"
|
||||
|
||||
type ScryfallClient struct {
|
||||
baseURL string
|
||||
httpClient *http.Client
|
||||
}
|
||||
type ScryfallClientOption func(*ScryfallClient) error
|
||||
|
||||
func NewScryfallClient(options ...ScryfallClientOption) (*ScryfallClient, error) {
|
||||
client := &ScryfallClient{
|
||||
baseURL: SCRYFALL_API_URL,
|
||||
httpClient: &http.Client{
|
||||
Timeout: time.Second * 30,
|
||||
},
|
||||
}
|
||||
|
||||
if err := client.parseOptions(options...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func BaseURL(baseURL string) ScryfallClientOption {
|
||||
return func(c *ScryfallClient) error {
|
||||
c.baseURL = baseURL
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ScryfallClient) parseOptions(options ...ScryfallClientOption) error {
|
||||
for _, option := range options {
|
||||
err := option(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
|
||||
{
|
||||
"object": "card",
|
||||
"id": "56ebc372-aabd-4174-a943-c7bf59e5028d",
|
||||
"oracle_id": "e43e06fb-52b7-4f38-8fac-f31973b043f7",
|
||||
"multiverse_ids": [
|
||||
37113
|
||||
],
|
||||
"mtgo_id": 17622,
|
||||
"mtgo_foil_id": 17623,
|
||||
"tcgplayer_id": 10190,
|
||||
"cardmarket_id": 2266,
|
||||
"name": "Phantom Nishoba",
|
||||
"lang": "en",
|
||||
"released_at": "2002-05-27",
|
||||
"uri": "https://api.scryfall.com/cards/56ebc372-aabd-4174-a943-c7bf59e5028d",
|
||||
"scryfall_uri": "https://scryfall.com/card/jud/140/phantom-nishoba?utm_source=api",
|
||||
"layout": "normal",
|
||||
"highres_image": true,
|
||||
"image_status": "highres_scan",
|
||||
"image_uris": {
|
||||
"small": "https://cards.scryfall.io/small/front/5/6/56ebc372-aabd-4174-a943-c7bf59e5028d.jpg?1562629953",
|
||||
"normal": "https://cards.scryfall.io/normal/front/5/6/56ebc372-aabd-4174-a943-c7bf59e5028d.jpg?1562629953",
|
||||
"large": "https://cards.scryfall.io/large/front/5/6/56ebc372-aabd-4174-a943-c7bf59e5028d.jpg?1562629953",
|
||||
"png": "https://cards.scryfall.io/png/front/5/6/56ebc372-aabd-4174-a943-c7bf59e5028d.png?1562629953",
|
||||
"art_crop": "https://cards.scryfall.io/art_crop/front/5/6/56ebc372-aabd-4174-a943-c7bf59e5028d.jpg?1562629953",
|
||||
"border_crop": "https://cards.scryfall.io/border_crop/front/5/6/56ebc372-aabd-4174-a943-c7bf59e5028d.jpg?1562629953"
|
||||
},
|
||||
"mana_cost": "{5}{G}{W}",
|
||||
"cmc": 7,
|
||||
"type_line": "Creature — Cat Beast Spirit",
|
||||
"oracle_text": "Trample\nPhantom Nishoba enters with seven +1/+1 counters on it.\nWhenever Phantom Nishoba deals damage, you gain that much life.\nIf damage would be dealt to Phantom Nishoba, prevent that damage. Remove a +1/+1 counter from Phantom Nishoba.",
|
||||
"power": "0",
|
||||
"toughness": "0",
|
||||
"colors": [
|
||||
"G",
|
||||
"W"
|
||||
],
|
||||
"color_identity": [
|
||||
"G",
|
||||
"W"
|
||||
],
|
||||
"keywords": [
|
||||
"Trample"
|
||||
],
|
||||
"legalities": {
|
||||
"standard": "not_legal",
|
||||
"future": "not_legal",
|
||||
"historic": "not_legal",
|
||||
"timeless": "not_legal",
|
||||
"gladiator": "not_legal",
|
||||
"pioneer": "not_legal",
|
||||
"explorer": "not_legal",
|
||||
"modern": "not_legal",
|
||||
"legacy": "legal",
|
||||
"pauper": "not_legal",
|
||||
"vintage": "legal",
|
||||
"penny": "not_legal",
|
||||
"commander": "legal",
|
||||
"oathbreaker": "legal",
|
||||
"standardbrawl": "not_legal",
|
||||
"brawl": "not_legal",
|
||||
"alchemy": "not_legal",
|
||||
"paupercommander": "not_legal",
|
||||
"duel": "legal",
|
||||
"oldschool": "not_legal",
|
||||
"premodern": "legal",
|
||||
"predh": "legal"
|
||||
},
|
||||
"games": [
|
||||
"paper",
|
||||
"mtgo"
|
||||
],
|
||||
"reserved": false,
|
||||
"foil": true,
|
||||
"nonfoil": true,
|
||||
"finishes": [
|
||||
"nonfoil",
|
||||
"foil"
|
||||
],
|
||||
"oversized": false,
|
||||
"promo": false,
|
||||
"reprint": false,
|
||||
"variation": false,
|
||||
"set_id": "cd82de1a-36fd-4618-bfe8-b45532a582d9",
|
||||
"set": "jud",
|
||||
"set_name": "Judgment",
|
||||
"set_type": "expansion",
|
||||
"set_uri": "https://api.scryfall.com/sets/cd82de1a-36fd-4618-bfe8-b45532a582d9",
|
||||
"set_search_uri": "https://api.scryfall.com/cards/search?order=set&q=e%3Ajud&unique=prints",
|
||||
"scryfall_set_uri": "https://scryfall.com/sets/jud?utm_source=api",
|
||||
"rulings_uri": "https://api.scryfall.com/cards/56ebc372-aabd-4174-a943-c7bf59e5028d/rulings",
|
||||
"prints_search_uri": "https://api.scryfall.com/cards/search?order=released&q=oracleid%3Ae43e06fb-52b7-4f38-8fac-f31973b043f7&unique=prints",
|
||||
"collector_number": "140",
|
||||
"digital": false,
|
||||
"rarity": "rare",
|
||||
"card_back_id": "0aeebaf5-8c7d-4636-9e82-8c27447861f7",
|
||||
"artist": "Arnie Swekel",
|
||||
"artist_ids": [
|
||||
"af10ecf2-eb82-4100-97b2-6c236b0fa644"
|
||||
],
|
||||
"illustration_id": "2bdc53d2-1f4b-4f6d-b59d-985ff2a01268",
|
||||
"border_color": "black",
|
||||
"frame": "1997",
|
||||
"full_art": false,
|
||||
"textless": false,
|
||||
"booster": true,
|
||||
"story_spotlight": false,
|
||||
"edhrec_rank": 10936,
|
||||
"penny_rank": 4165,
|
||||
"prices": {
|
||||
"usd": "3.99",
|
||||
"usd_foil": "29.06",
|
||||
"usd_etched": null,
|
||||
"eur": "4.24",
|
||||
"eur_foil": "28.93",
|
||||
"tix": "0.53"
|
||||
},
|
||||
"related_uris": {
|
||||
"gatherer": "https://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=37113&printed=false",
|
||||
"tcgplayer_infinite_articles": "https://partner.tcgplayer.com/c/4931599/1830156/21018?subId1=api&trafcat=infinite&u=https%3A%2F%2Finfinite.tcgplayer.com%2Fsearch%3FcontentMode%3Darticle%26game%3Dmagic%26partner%3Dscryfall%26q%3DPhantom%2BNishoba",
|
||||
"tcgplayer_infinite_decks": "https://partner.tcgplayer.com/c/4931599/1830156/21018?subId1=api&trafcat=infinite&u=https%3A%2F%2Finfinite.tcgplayer.com%2Fsearch%3FcontentMode%3Ddeck%26game%3Dmagic%26partner%3Dscryfall%26q%3DPhantom%2BNishoba",
|
||||
"edhrec": "https://edhrec.com/route/?cc=Phantom+Nishoba"
|
||||
},
|
||||
"purchase_uris": {
|
||||
"tcgplayer": "https://partner.tcgplayer.com/c/4931599/1830156/21018?subId1=api&u=https%3A%2F%2Fwww.tcgplayer.com%2Fproduct%2F10190%3Fpage%3D1",
|
||||
"cardmarket": "https://www.cardmarket.com/en/Magic/Products/Singles/Judgment/Phantom-Nishoba?referrer=scryfall&utm_campaign=card_prices&utm_medium=text&utm_source=scryfall",
|
||||
"cardhoarder": "https://www.cardhoarder.com/cards/17622?affiliate_id=scryfall&ref=card-profile&utm_campaign=affiliate&utm_medium=card&utm_source=scryfall"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue