This commit is contained in:
@@ -81,18 +81,19 @@ defmodule CobblemonUi.EvolutionApi do
|
|||||||
end
|
end
|
||||||
|
|
||||||
defp fetch_species_chain_url(species) do
|
defp fetch_species_chain_url(species) do
|
||||||
url = "https://pokeapi.co/api/v2/pokemon-species/#{species}"
|
api_name = CobblemonUi.PokeApiNames.normalize(species)
|
||||||
|
url = "https://pokeapi.co/api/v2/pokemon-species/#{api_name}"
|
||||||
|
|
||||||
case Req.get(url) do
|
case Req.get(url) do
|
||||||
{:ok, %Req.Response{status: 200, body: %{"evolution_chain" => %{"url" => url}}}} ->
|
{:ok, %Req.Response{status: 200, body: %{"evolution_chain" => %{"url" => url}}}} ->
|
||||||
{:ok, url}
|
{:ok, url}
|
||||||
|
|
||||||
{:ok, %Req.Response{status: status}} ->
|
{:ok, %Req.Response{status: status}} ->
|
||||||
Logger.warning("[EvolutionApi] Species lookup failed for #{species}: HTTP #{status}")
|
Logger.warning("[EvolutionApi] Species lookup failed for #{api_name}: HTTP #{status}")
|
||||||
{:error, :not_found}
|
{:error, :not_found}
|
||||||
|
|
||||||
{:error, reason} ->
|
{:error, reason} ->
|
||||||
Logger.warning("[EvolutionApi] Species lookup failed for #{species}: #{inspect(reason)}")
|
Logger.warning("[EvolutionApi] Species lookup failed for #{api_name}: #{inspect(reason)}")
|
||||||
{:error, reason}
|
{:error, reason}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -68,21 +68,67 @@ defmodule CobblemonUi.PokeApi do
|
|||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
defp fetch_types(species) do
|
defp fetch_types(species) do
|
||||||
url = "https://pokeapi.co/api/v2/pokemon/#{species}"
|
api_name = CobblemonUi.PokeApiNames.normalize(species)
|
||||||
|
|
||||||
|
case fetch_types_direct(api_name) do
|
||||||
|
{:ok, types} ->
|
||||||
|
types
|
||||||
|
|
||||||
|
:not_found ->
|
||||||
|
# The /pokemon/ endpoint requires the specific form name (e.g.
|
||||||
|
# "aegislash-shield"). Fall back through the /pokemon-species/
|
||||||
|
# endpoint to resolve the default variety.
|
||||||
|
fetch_types_via_species(api_name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp fetch_types_direct(api_name) do
|
||||||
|
url = "https://pokeapi.co/api/v2/pokemon/#{api_name}"
|
||||||
|
|
||||||
case Req.get(url) do
|
case Req.get(url) do
|
||||||
{:ok, %Req.Response{status: 200, body: %{"types" => types}}} ->
|
{:ok, %Req.Response{status: 200, body: %{"types" => types}}} ->
|
||||||
types
|
parsed =
|
||||||
|> Enum.sort_by(fn t -> t["slot"] end)
|
types
|
||||||
|> Enum.map(fn t -> get_in(t, ["type", "name"]) end)
|
|> Enum.sort_by(fn t -> t["slot"] end)
|
||||||
|> Enum.reject(&is_nil/1)
|
|> Enum.map(fn t -> get_in(t, ["type", "name"]) end)
|
||||||
|
|> Enum.reject(&is_nil/1)
|
||||||
|
|
||||||
|
{:ok, parsed}
|
||||||
|
|
||||||
|
{:ok, %Req.Response{status: 404}} ->
|
||||||
|
:not_found
|
||||||
|
|
||||||
{:ok, %Req.Response{status: status}} ->
|
{:ok, %Req.Response{status: status}} ->
|
||||||
Logger.warning("[PokeApi] Type lookup failed for #{species}: HTTP #{status}")
|
Logger.warning("[PokeApi] Type lookup failed for #{api_name}: HTTP #{status}")
|
||||||
[]
|
{:ok, []}
|
||||||
|
|
||||||
{:error, reason} ->
|
{:error, reason} ->
|
||||||
Logger.warning("[PokeApi] Type lookup failed for #{species}: #{inspect(reason)}")
|
Logger.warning("[PokeApi] Type lookup failed for #{api_name}: #{inspect(reason)}")
|
||||||
|
{:ok, []}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp fetch_types_via_species(api_name) do
|
||||||
|
url = "https://pokeapi.co/api/v2/pokemon-species/#{api_name}"
|
||||||
|
|
||||||
|
with {:ok, %Req.Response{status: 200, body: body}} <- Req.get(url),
|
||||||
|
%{"varieties" => varieties} <- body,
|
||||||
|
%{"pokemon" => %{"url" => pokemon_url}} <-
|
||||||
|
Enum.find(varieties, fn v -> v["is_default"] end) do
|
||||||
|
case Req.get(pokemon_url) do
|
||||||
|
{:ok, %Req.Response{status: 200, body: %{"types" => types}}} ->
|
||||||
|
types
|
||||||
|
|> Enum.sort_by(fn t -> t["slot"] end)
|
||||||
|
|> Enum.map(fn t -> get_in(t, ["type", "name"]) end)
|
||||||
|
|> Enum.reject(&is_nil/1)
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
Logger.warning("[PokeApi] Fallback type lookup failed for #{api_name}")
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
else
|
||||||
|
_ ->
|
||||||
|
Logger.warning("[PokeApi] Species fallback failed for #{api_name}")
|
||||||
[]
|
[]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
78
lib/cobblemon_ui/poke_api_names.ex
Normal file
78
lib/cobblemon_ui/poke_api_names.ex
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
defmodule CobblemonUi.PokeApiNames do
|
||||||
|
@moduledoc """
|
||||||
|
Maps Cobblemon species names to PokeAPI-compatible names.
|
||||||
|
|
||||||
|
Cobblemon stores species names as single lowercase words (e.g. `ironthorns`),
|
||||||
|
while PokeAPI expects hyphenated forms (e.g. `iron-thorns`). This module
|
||||||
|
provides the translation layer.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Static map of Cobblemon names that differ from PokeAPI names.
|
||||||
|
# Only entries where the name doesn't match need to be listed.
|
||||||
|
@name_map %{
|
||||||
|
# Paradox Pokémon (Scarlet)
|
||||||
|
"greattusk" => "great-tusk",
|
||||||
|
"screamtail" => "scream-tail",
|
||||||
|
"brutebonnet" => "brute-bonnet",
|
||||||
|
"fluttermane" => "flutter-mane",
|
||||||
|
"sandyshocks" => "sandy-shocks",
|
||||||
|
"slitherwing" => "slither-wing",
|
||||||
|
"roaringmoon" => "roaring-moon",
|
||||||
|
"walkingwake" => "walking-wake",
|
||||||
|
"gougingfire" => "gouging-fire",
|
||||||
|
"ragingbolt" => "raging-bolt",
|
||||||
|
# Paradox Pokémon (Violet)
|
||||||
|
"irontreads" => "iron-treads",
|
||||||
|
"ironbundle" => "iron-bundle",
|
||||||
|
"ironhands" => "iron-hands",
|
||||||
|
"ironjugulis" => "iron-jugulis",
|
||||||
|
"ironmoth" => "iron-moth",
|
||||||
|
"ironvaliant" => "iron-valiant",
|
||||||
|
"ironthorns" => "iron-thorns",
|
||||||
|
"ironleaves" => "iron-leaves",
|
||||||
|
"ironcrown" => "iron-crown",
|
||||||
|
"ironboulder" => "iron-boulder",
|
||||||
|
# Tapu guardians
|
||||||
|
"tapukoko" => "tapu-koko",
|
||||||
|
"tapulele" => "tapu-lele",
|
||||||
|
"tapubulu" => "tapu-bulu",
|
||||||
|
"tapufini" => "tapu-fini",
|
||||||
|
# Hyphenated / special names
|
||||||
|
"hooh" => "ho-oh",
|
||||||
|
"porygonz" => "porygon-z",
|
||||||
|
"typenull" => "type-null",
|
||||||
|
"mrmime" => "mr-mime",
|
||||||
|
"mrrime" => "mr-rime",
|
||||||
|
"mimejr" => "mime-jr",
|
||||||
|
"jangmoo" => "jangmo-o",
|
||||||
|
"hakamoo" => "hakamo-o",
|
||||||
|
"kommoo" => "kommo-o",
|
||||||
|
"chiyu" => "chi-yu",
|
||||||
|
"chienpao" => "chien-pao",
|
||||||
|
"tinglu" => "ting-lu",
|
||||||
|
"wochien" => "wo-chien",
|
||||||
|
"nidoranf" => "nidoran-f",
|
||||||
|
"nidoranm" => "nidoran-m",
|
||||||
|
"farfetchd" => "farfetchd",
|
||||||
|
"sirfetchd" => "sirfetchd",
|
||||||
|
# Flabébé line
|
||||||
|
"flabebe" => "flabebe"
|
||||||
|
}
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Converts a Cobblemon species name to the PokeAPI-compatible name.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
iex> CobblemonUi.PokeApiNames.normalize("ironthorns")
|
||||||
|
"iron-thorns"
|
||||||
|
|
||||||
|
iex> CobblemonUi.PokeApiNames.normalize("bulbasaur")
|
||||||
|
"bulbasaur"
|
||||||
|
"""
|
||||||
|
@spec normalize(String.t()) :: String.t()
|
||||||
|
def normalize(species) when is_binary(species) do
|
||||||
|
key = species |> String.downcase() |> String.trim()
|
||||||
|
Map.get(@name_map, key, key)
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user