Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 138 additions & 0 deletions scripts/showdown.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import difflib
import pathlib
import typing as t

import requests
import tabulate
from bs4 import BeautifulSoup

# NOTE: Doesn't account for females, refer this and manually check them in later https://bulbapedia.bulbagarden.net/wiki/List_of_Pok%C3%A9mon_with_gender_differences

DRY_RUN = True
SHOWDOWN_DIR = pathlib.Path(__file__).parent.parent / "sprites" / "pokemon" / "other" / "showdown"
SHOWDOWN_BASE_URL = "https://play.pokemonshowdown.com/sprites/ani"


class PokemonRecord(t.TypedDict):
id: int
name: str


def list_pokemon() -> dict[str, str]:
"""Retrieve a list of all Pokémon from the PokéAPI."""
api_url = "https://pokeapi.co/api/v2/pokemon?limit=10000"
response = requests.get(api_url)

if response.status_code != 200:
raise Exception(f"Failed to retrieve Pokémon list (Status {response.status_code})")

data = response.json()
return {i["url"].split("/")[-2]: i["name"] for i in data["results"]}


def list_showdown_images(folder: pathlib.Path) -> set[str]:
"""List all Pokémon images available in the Showdown directory."""
image_files = {f.stem for f in folder.glob("*.gif") if f.is_file()}
return image_files


def _construct_showdown_url(back: bool = False, shiny: bool = False) -> str:
"""Construct the Showdown URL based on image type."""
base_url = SHOWDOWN_BASE_URL
if back:
base_url += "-back"
if shiny:
base_url += "-shiny"
return base_url


def showdown_sprite_index(back: bool = False, shiny: bool = False) -> set[str]:
"""Retrieve the index of available Pokémon sprites from Showdown."""
index = requests.get(_construct_showdown_url(back, shiny))
if index.status_code != 200:
raise Exception(f"Failed to retrieve Showdown sprite index (Status {index.status_code})")
soup = BeautifulSoup(index.text, "html.parser")
links = soup.find_all("a")
return {
str(link.get("href")).strip("./").split(".")[0] for link in links if str(link.get("href", "")).endswith(".gif")
}


def download_image(id: str, name: str, folder: pathlib.Path, pokemon_url: str) -> None:
"""Download a Pokémon image from the Showdown repository."""
response = requests.get(pokemon_url)
if response.status_code != 200:
print(f"Failed to download image for {name} (Status {response.status_code})")
return

with open(folder / f"{id}.gif", "wb") as img_file:
img_file.write(response.content)

print(f"Downloaded image for {name} to {folder / f'{id}.gif'}")


if __name__ == "__main__":
pokemon_list = list_pokemon()

showdown_folders = (
SHOWDOWN_DIR,
SHOWDOWN_DIR / "shiny",
SHOWDOWN_DIR / "back",
SHOWDOWN_DIR / "back" / "shiny",
)

for folder in showdown_folders:
showdown_images = list_showdown_images(folder)
missing_images = set(pokemon_list.keys()) - showdown_images

back = "back" in folder.parts
shiny = "shiny" in folder.parts

showdown_index = showdown_sprite_index(back=back, shiny=shiny)

print(f"\n{'=' * 40}\nMissing images in folder: {folder}\n{'=' * 40}\n")

remaining: set[str] = set()

for pid, name in pokemon_list.items():
if pid in missing_images and not DRY_RUN:
if name in showdown_index:
download_image(
pid,
name,
folder,
f"{_construct_showdown_url(back=back, shiny=shiny)}/{name}.gif",
)
else:
print(f"Exact name not found in Showdown index: {name}")
closest_matches = difflib.get_close_matches(name, showdown_index, n=3, cutoff=0.7)
if closest_matches:
print("\n".join([str(n) + ") " + m for n, m in enumerate(closest_matches, start=1)]))
print(
"Enter to skip downloading this image, or enter the number of the closest match to download that image."
)
user_input = input("Your choice: ").strip()
try:
choice = int(user_input)
if 1 <= choice <= len(closest_matches):
selected_name = closest_matches[choice - 1]
download_image(
pid,
selected_name,
folder,
f"{_construct_showdown_url(back=back, shiny=shiny)}/{selected_name}.gif",
)
else:
print("Invalid choice. Skipping download.")
remaining.add(pid)
except ValueError:
print("Skipping download.")
remaining.add(pid)

table = tabulate.tabulate(
[(pid, pname) for pid, pname in pokemon_list.items() if pid in (missing_images if DRY_RUN else remaining)],
headers=["Pokémon ID", "Pokémon Name"],
tablefmt="github",
)

print(table)
Binary file added sprites/pokemon/other/showdown/1000.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/1007.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/1009.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/1011.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/1012.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/1013.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/1018.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/1019.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/1020.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/1021.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/10250.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/10251.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/10252.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/10253.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/10255.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/10258.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/10259.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/10260.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/10261.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/10262.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/10263.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/10272.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/10278.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/10279.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/10280.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sprites/pokemon/other/showdown/10281.gif
Binary file added sprites/pokemon/other/showdown/10282.gif
Binary file added sprites/pokemon/other/showdown/10283.gif
Binary file added sprites/pokemon/other/showdown/10284.gif
Binary file added sprites/pokemon/other/showdown/10285.gif
Binary file added sprites/pokemon/other/showdown/10286.gif
Binary file added sprites/pokemon/other/showdown/926.gif
Binary file added sprites/pokemon/other/showdown/927.gif
Binary file added sprites/pokemon/other/showdown/932.gif
Binary file added sprites/pokemon/other/showdown/933.gif
Binary file added sprites/pokemon/other/showdown/934.gif
Binary file added sprites/pokemon/other/showdown/935.gif
Binary file added sprites/pokemon/other/showdown/936.gif
Binary file added sprites/pokemon/other/showdown/937.gif
Binary file added sprites/pokemon/other/showdown/940.gif
Binary file added sprites/pokemon/other/showdown/941.gif
Binary file added sprites/pokemon/other/showdown/942.gif
Binary file added sprites/pokemon/other/showdown/943.gif
Binary file added sprites/pokemon/other/showdown/944.gif
Binary file added sprites/pokemon/other/showdown/945.gif
Binary file added sprites/pokemon/other/showdown/946.gif
Binary file added sprites/pokemon/other/showdown/947.gif
Binary file added sprites/pokemon/other/showdown/948.gif
Binary file added sprites/pokemon/other/showdown/949.gif
Binary file added sprites/pokemon/other/showdown/950.gif
Binary file added sprites/pokemon/other/showdown/962.gif
Binary file added sprites/pokemon/other/showdown/969.gif
Binary file added sprites/pokemon/other/showdown/970.gif
Binary file added sprites/pokemon/other/showdown/983.gif
Binary file added sprites/pokemon/other/showdown/984.gif
Binary file added sprites/pokemon/other/showdown/985.gif
Binary file added sprites/pokemon/other/showdown/986.gif
Binary file added sprites/pokemon/other/showdown/987.gif
Binary file added sprites/pokemon/other/showdown/988.gif
Binary file added sprites/pokemon/other/showdown/989.gif
Binary file added sprites/pokemon/other/showdown/996.gif
Binary file added sprites/pokemon/other/showdown/997.gif
Binary file added sprites/pokemon/other/showdown/998.gif
Binary file added sprites/pokemon/other/showdown/999.gif
Binary file added sprites/pokemon/other/showdown/back/1000.gif
Binary file added sprites/pokemon/other/showdown/back/1007.gif
Binary file added sprites/pokemon/other/showdown/back/1009.gif
Binary file added sprites/pokemon/other/showdown/back/1011.gif
Binary file added sprites/pokemon/other/showdown/back/1012.gif
Binary file added sprites/pokemon/other/showdown/back/1013.gif
Binary file added sprites/pokemon/other/showdown/back/1018.gif
Binary file added sprites/pokemon/other/showdown/back/1019.gif
Binary file added sprites/pokemon/other/showdown/back/1020.gif
Binary file added sprites/pokemon/other/showdown/back/1021.gif
Binary file added sprites/pokemon/other/showdown/back/10250.gif
Binary file added sprites/pokemon/other/showdown/back/10251.gif
Binary file added sprites/pokemon/other/showdown/back/10252.gif
Binary file added sprites/pokemon/other/showdown/back/10253.gif
Binary file added sprites/pokemon/other/showdown/back/10255.gif
Binary file added sprites/pokemon/other/showdown/back/10258.gif
Binary file added sprites/pokemon/other/showdown/back/10259.gif
Binary file added sprites/pokemon/other/showdown/back/10260.gif
Binary file added sprites/pokemon/other/showdown/back/10261.gif
Binary file added sprites/pokemon/other/showdown/back/10262.gif
Binary file added sprites/pokemon/other/showdown/back/10263.gif
Binary file added sprites/pokemon/other/showdown/back/10272.gif
Binary file added sprites/pokemon/other/showdown/back/10278.gif
Binary file added sprites/pokemon/other/showdown/back/10279.gif
Binary file added sprites/pokemon/other/showdown/back/10280.gif
Binary file added sprites/pokemon/other/showdown/back/10281.gif
Binary file added sprites/pokemon/other/showdown/back/10282.gif
Binary file added sprites/pokemon/other/showdown/back/10283.gif
Binary file added sprites/pokemon/other/showdown/back/10284.gif
Binary file added sprites/pokemon/other/showdown/back/10285.gif
Binary file added sprites/pokemon/other/showdown/back/10286.gif
Binary file added sprites/pokemon/other/showdown/back/926.gif
Binary file added sprites/pokemon/other/showdown/back/927.gif
Binary file added sprites/pokemon/other/showdown/back/932.gif
Binary file added sprites/pokemon/other/showdown/back/933.gif
Binary file added sprites/pokemon/other/showdown/back/934.gif
Binary file added sprites/pokemon/other/showdown/back/935.gif
Binary file added sprites/pokemon/other/showdown/back/936.gif
Binary file added sprites/pokemon/other/showdown/back/937.gif
Binary file added sprites/pokemon/other/showdown/back/940.gif
Binary file added sprites/pokemon/other/showdown/back/941.gif
Binary file added sprites/pokemon/other/showdown/back/942.gif
Binary file added sprites/pokemon/other/showdown/back/943.gif
Binary file added sprites/pokemon/other/showdown/back/944.gif
Binary file added sprites/pokemon/other/showdown/back/945.gif
Binary file added sprites/pokemon/other/showdown/back/946.gif
Binary file added sprites/pokemon/other/showdown/back/947.gif
Binary file added sprites/pokemon/other/showdown/back/948.gif
Binary file added sprites/pokemon/other/showdown/back/949.gif
Binary file added sprites/pokemon/other/showdown/back/950.gif
Binary file added sprites/pokemon/other/showdown/back/962.gif
Binary file added sprites/pokemon/other/showdown/back/969.gif
Binary file added sprites/pokemon/other/showdown/back/970.gif
Binary file added sprites/pokemon/other/showdown/back/983.gif
Binary file added sprites/pokemon/other/showdown/back/984.gif
Binary file added sprites/pokemon/other/showdown/back/985.gif
Binary file added sprites/pokemon/other/showdown/back/986.gif
Binary file added sprites/pokemon/other/showdown/back/987.gif
Binary file added sprites/pokemon/other/showdown/back/988.gif
Binary file added sprites/pokemon/other/showdown/back/989.gif
Binary file added sprites/pokemon/other/showdown/back/996.gif
Binary file added sprites/pokemon/other/showdown/back/997.gif
Binary file added sprites/pokemon/other/showdown/back/998.gif
Binary file added sprites/pokemon/other/showdown/back/999.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/926.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/927.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/932.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/933.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/935.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/936.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/937.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/940.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/941.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/942.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/943.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/944.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/945.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/948.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/949.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/950.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/962.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/969.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/970.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/985.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/986.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/987.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/996.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/997.gif
Binary file added sprites/pokemon/other/showdown/back/shiny/999.gif
Binary file added sprites/pokemon/other/showdown/shiny/1000.gif
Binary file added sprites/pokemon/other/showdown/shiny/1007.gif
Binary file added sprites/pokemon/other/showdown/shiny/1009.gif
Binary file added sprites/pokemon/other/showdown/shiny/1011.gif
Binary file added sprites/pokemon/other/showdown/shiny/1012.gif
Binary file added sprites/pokemon/other/showdown/shiny/1013.gif
Binary file added sprites/pokemon/other/showdown/shiny/1018.gif
Binary file added sprites/pokemon/other/showdown/shiny/1019.gif
Binary file added sprites/pokemon/other/showdown/shiny/1020.gif
Binary file added sprites/pokemon/other/showdown/shiny/1021.gif
Binary file added sprites/pokemon/other/showdown/shiny/10250.gif
Binary file added sprites/pokemon/other/showdown/shiny/10251.gif
Binary file added sprites/pokemon/other/showdown/shiny/10252.gif
Binary file added sprites/pokemon/other/showdown/shiny/10253.gif
Binary file added sprites/pokemon/other/showdown/shiny/10255.gif
Binary file added sprites/pokemon/other/showdown/shiny/10258.gif
Binary file added sprites/pokemon/other/showdown/shiny/10259.gif
Binary file added sprites/pokemon/other/showdown/shiny/10260.gif
Binary file added sprites/pokemon/other/showdown/shiny/10261.gif
Binary file added sprites/pokemon/other/showdown/shiny/10262.gif
Binary file added sprites/pokemon/other/showdown/shiny/10263.gif
Binary file added sprites/pokemon/other/showdown/shiny/10272.gif
Binary file added sprites/pokemon/other/showdown/shiny/10278.gif
Binary file added sprites/pokemon/other/showdown/shiny/10279.gif
Binary file added sprites/pokemon/other/showdown/shiny/10280.gif
Binary file added sprites/pokemon/other/showdown/shiny/10281.gif
Binary file added sprites/pokemon/other/showdown/shiny/10282.gif
Binary file added sprites/pokemon/other/showdown/shiny/10283.gif
Binary file added sprites/pokemon/other/showdown/shiny/10284.gif
Binary file added sprites/pokemon/other/showdown/shiny/10285.gif
Binary file added sprites/pokemon/other/showdown/shiny/10286.gif
Binary file added sprites/pokemon/other/showdown/shiny/926.gif
Binary file added sprites/pokemon/other/showdown/shiny/927.gif
Binary file added sprites/pokemon/other/showdown/shiny/932.gif
Binary file added sprites/pokemon/other/showdown/shiny/933.gif
Binary file added sprites/pokemon/other/showdown/shiny/934.gif
Binary file added sprites/pokemon/other/showdown/shiny/935.gif
Binary file added sprites/pokemon/other/showdown/shiny/936.gif
Binary file added sprites/pokemon/other/showdown/shiny/937.gif
Binary file added sprites/pokemon/other/showdown/shiny/940.gif
Binary file added sprites/pokemon/other/showdown/shiny/941.gif
Binary file added sprites/pokemon/other/showdown/shiny/942.gif
Binary file added sprites/pokemon/other/showdown/shiny/943.gif
Binary file added sprites/pokemon/other/showdown/shiny/944.gif
Binary file added sprites/pokemon/other/showdown/shiny/945.gif
Binary file added sprites/pokemon/other/showdown/shiny/946.gif
Binary file added sprites/pokemon/other/showdown/shiny/947.gif
Binary file added sprites/pokemon/other/showdown/shiny/948.gif
Binary file added sprites/pokemon/other/showdown/shiny/949.gif
Binary file added sprites/pokemon/other/showdown/shiny/950.gif
Binary file added sprites/pokemon/other/showdown/shiny/962.gif
Binary file added sprites/pokemon/other/showdown/shiny/969.gif
Binary file added sprites/pokemon/other/showdown/shiny/970.gif
Binary file added sprites/pokemon/other/showdown/shiny/983.gif
Binary file added sprites/pokemon/other/showdown/shiny/984.gif
Binary file added sprites/pokemon/other/showdown/shiny/985.gif
Binary file added sprites/pokemon/other/showdown/shiny/986.gif
Binary file added sprites/pokemon/other/showdown/shiny/987.gif
Binary file added sprites/pokemon/other/showdown/shiny/988.gif
Binary file added sprites/pokemon/other/showdown/shiny/989.gif
Binary file added sprites/pokemon/other/showdown/shiny/996.gif
Binary file added sprites/pokemon/other/showdown/shiny/997.gif
Binary file added sprites/pokemon/other/showdown/shiny/998.gif
Binary file added sprites/pokemon/other/showdown/shiny/999.gif