checkpoint: get pokemon info from server

This commit is contained in:
Dan Anglin 2024-09-20 02:16:41 +01:00
parent 578c781907
commit 90bbddf56d
Signed by: dananglin
GPG key ID: 0C1D44CFBEE68638
4 changed files with 159 additions and 14 deletions

View file

@ -45,15 +45,3 @@ type Encounter struct {
Chance int `json:"chance"` Chance int `json:"chance"`
Method NamedAPIResource `json:"method"` Method NamedAPIResource `json:"method"`
} }
type NamedAPIResourceList struct {
Count int `json:"count"`
Next *string `json:"next"`
Previous *string `json:"previous"`
Results []NamedAPIResource `json:"results"`
}
type NamedAPIResource struct {
Name string `json:"name"`
URL string `json:"url"`
}

View file

@ -0,0 +1,13 @@
package pokeapi
type NamedAPIResourceList struct {
Count int `json:"count"`
Next *string `json:"next"`
Previous *string `json:"previous"`
Results []NamedAPIResource `json:"results"`
}
type NamedAPIResource struct {
Name string `json:"name"`
URL string `json:"url"`
}

View file

@ -0,0 +1,87 @@
package pokeapi
type Pokemon struct {
ID int `json:"id"`
Name string `json:"name"`
BaseExperience int `json:"base_experience"`
Height int `json:"height"`
IsDefault bool `json:"is_default"`
Order int `json:"order"`
Weight int `json:"weight"`
Abilities []PokemonAbility `json:"abilities"`
Forms []NamedAPIResource `json:"forms"`
GameIndices []VersionGameIndex `json:"game_indices"`
HeldItems []PokemonHeldItems `json:"held_items"`
LocationAreaEncounters string `json:"location_area_encounters"`
Moves []PokemonMoves `json:"moves"`
PastTypes []PokemonTypePast `json:"past_types"`
Sprites PokemonSprites `json:"sprites"`
Cries PokemonCries `json:"cries"`
Species NamedAPIResource `json:"species"`
Stats []PokemonStat `json:"stats"`
Types []PokemonType `json:"types"`
}
type PokemonAbility struct {
IsHidden bool `json:"is_hidden"`
Slot int `json:"slot"`
Ability NamedAPIResource `json:"ability"`
}
type VersionGameIndex struct {
GameIndex int `json:"game_index"`
Version NamedAPIResource `json:"version"`
}
type PokemonHeldItems struct {
Item NamedAPIResource `json:"item"`
VersionDetails []PokemonHeldItemVersion `json:"version_details"`
}
type PokemonHeldItemVersion struct {
Version NamedAPIResource `json:"version"`
Rarity int `json:"rarity"`
}
type PokemonMoves struct {
Move NamedAPIResource `json:"move"`
VersionGroupDetails []PokemonMoveVersion `json:"version_group_details"`
}
type PokemonMoveVersion struct {
MoveLearnMethod NamedAPIResource `json:"move_learn_method"`
VersionGroup NamedAPIResource `json:"version_group"`
LevelLearnedAt int
}
type PokemonTypePast struct {
Generation NamedAPIResource `json:"generation"`
Types PokemonType `json:"types"`
}
type PokemonSprites struct {
FrontDefault string `json:"front_default"`
FrontShiny string `json:"front_shiny"`
FrontFemale string `json:"front_female"`
FrontShinyFemale string `json:"front_shiny_female"`
BackDefault string `json:"back_default"`
BackShiny string `json:"back_shiny"`
BackFemale string `json:"back_female"`
BackShinyFemale string `json:"back_shiny_female"`
}
type PokemonCries struct {
Latest string `json:"latest"`
Legacy string `json:"legacy"`
}
type PokemonStat struct {
Stat NamedAPIResource `json:"stat"`
Effort int `json:"effort"`
BaseStat int `json:"base_stat"`
}
type PokemonType struct {
Slot int `json:"slot"`
Type NamedAPIResource `json:"type"`
}

View file

@ -15,7 +15,8 @@ import (
const ( const (
baseURL string = "https://pokeapi.co/api/v2" baseURL string = "https://pokeapi.co/api/v2"
LocationAreaEndpoint = baseURL + "/location-area" LocationAreaPath = baseURL + "/location-area"
PokemonPath = baseURL + "/pokemon"
) )
type Client struct { type Client struct {
@ -93,7 +94,7 @@ func (c *Client) GetNamedAPIResourceList(url string) (pokeapi.NamedAPIResourceLi
func (c *Client) GetLocationArea(location string) (pokeapi.LocationArea, error) { func (c *Client) GetLocationArea(location string) (pokeapi.LocationArea, error) {
var locationArea pokeapi.LocationArea var locationArea pokeapi.LocationArea
url := LocationAreaEndpoint + "/" + location + "/" url := LocationAreaPath + "/" + location + "/"
dataFromCache, exists := c.cache.Get(url) dataFromCache, exists := c.cache.Get(url)
if exists { if exists {
@ -146,6 +147,62 @@ func (c *Client) GetLocationArea(location string) (pokeapi.LocationArea, error)
return locationArea, nil return locationArea, nil
} }
func (c *Client) GetPokemon(pokemonName string) (pokeapi.Pokemon, error) {
var pokemon pokeapi.Pokemon
url := PokemonPath + "/" + pokemonName + "/"
dataFromCache, exists := c.cache.Get(url)
if exists {
fmt.Println("Using data from cache.")
if err := decodeJSON(dataFromCache, &pokemon); err != nil {
return pokeapi.Pokemon{}, fmt.Errorf("unable to decode the data from the cache: %w", err)
}
return pokemon, nil
}
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
defer cancel()
request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return pokeapi.Pokemon{}, fmt.Errorf("error creating the HTTP request: %w", err)
}
resp, err := c.httpClient.Do(request)
if err != nil {
return pokeapi.Pokemon{}, fmt.Errorf("error getting the response from the server: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode >= 400 {
return pokeapi.Pokemon{}, fmt.Errorf(
"received a bad status from %s: (%d) %s",
url,
resp.StatusCode,
resp.Status,
)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return pokeapi.Pokemon{}, fmt.Errorf(
"unable to read the response from the server: %w",
err,
)
}
if err := decodeJSON(body, &pokemon); err != nil {
return pokeapi.Pokemon{}, fmt.Errorf("unable to decode the data from the server: %w", err)
}
c.cache.Add(url, body)
return pokemon, nil
}
func decodeJSON(data []byte, value any) error { func decodeJSON(data []byte, value any) error {
if err := json.Unmarshal(data, value); err != nil { if err := json.Unmarshal(data, value); err != nil {
return fmt.Errorf("unable to decode the JSON data: %w", err) return fmt.Errorf("unable to decode the JSON data: %w", err)