Skip to content

Commit

Permalink
Merge pull request #3 from Nekidev/Animechan
Browse files Browse the repository at this point in the history
  • Loading branch information
Nekidev authored Sep 22, 2022
2 parents 1566d93 + bee0ea5 commit f39f0a5
Show file tree
Hide file tree
Showing 9 changed files with 190 additions and 10 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
__pycache__/
__pycache__/
.pytest_cache/
12 changes: 9 additions & 3 deletions anime_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
"""
from anime_api.apis.anime_facts_rest_api import AnimeFactsRestAPI
from anime_api.apis.trace_moe import TraceMoeAPI
from anime_api.apis.animechan import AnimechanAPI


# List of tuples (api_name, api_class, api_docs_url, is_available)
apis = [
api_list = [
(
"Anime Facts Rest API",
AnimeFactsRestAPI,
Expand All @@ -19,7 +20,7 @@
"https://soruly.github.io/trace.moe-api/",
True,
),
("Animechan", None, "https://animechan.vercel.app/guide", False),
("Animechan", AnimechanAPI, "https://animechan.vercel.app/guide", True),
("Jikan", None, "https://jikan.docs.apiary.io/#", False),
("Waifu Pics", None, "https://waifu.pics/docs", False),
("Studio Ghibli API", None, "https://ghibliapi.herokuapp.com/", False),
Expand All @@ -45,7 +46,12 @@
("Shikimori", None, "https://shikimori.one/api/doc", False),
("Mangadex", None, "https://api.mangadex.org/docs.html", False),
("Danbooru", None, "https://danbooru.donmai.us/wiki_pages/help:api", False),
("Yandere", None, "https://yande.re/help/api", False), # Yandere and Konachan are forks of the same github repo. That's why they have almost-identical apis.
(
"Yandere",
None,
"https://yande.re/help/api",
False,
), # Yandere and Konachan are forks of the same github repo. That's why they have almost-identical apis.
("Konachan", None, "https://konachan.com/help/api", False),
("Waifu.im", None, "https://waifu.im/", False),
("Catboys", None, "https://catboys.com/api", False),
Expand Down
3 changes: 1 addition & 2 deletions anime_api/apis/anime_facts_rest_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ class AnimeFactsRestAPI:
endpoint = "https://anime-facts-rest-api.herokuapp.com/api/v1"

def __init__(self, endpoint: typing.Optional[str] = None):
if endpoint:
self.endpoint = endpoint
self.endpoint = endpoint or self.endpoint

def get_animes(self) -> typing.List[Anime]:
"""
Expand Down
90 changes: 90 additions & 0 deletions anime_api/apis/animechan/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
"""
Base module for the Animechan API. The documentation is available at
https://animechan.vercel.app/guide
"""
import typing
import requests

from anime_api import exceptions
from anime_api.apis.animechan.objects import Quote


class AnimechanAPI:
"""
Docs: https://animechan.vercel.app/guide
"""

endpoint = "https://animechan.vercel.app/api"

def __init__(self, endpoint: typing.Optional[str] = None):
self.endpoint = endpoint or self.endpoint

def get_random_quote(self) -> Quote:
"""
Get a random quote from the API.
"""
response = requests.get(f"{self.endpoint}/random")

if response.status_code != 200:
raise exceptions.ServerError(
status_code=response.status_code,
)

return Quote(**response.json())

def get_10_random_quotes(self) -> typing.List[Quote]:
"""
Get 10 random quotes from the API.
"""
response = requests.get(f"{self.endpoint}/quotes")

if response.status_code != 200:
raise exceptions.ServerError(
status_code=response.status_code,
)

return [Quote(**quote) for quote in response.json()]

def search_by_anime_title(self, anime_title: str, page: int = 1) -> Quote:
"""
Return a list of quotes from the given anime.
"""
response = requests.get(
f"{self.endpoint}/quotes/anime", params={"title": anime_title, "page": page}
)

if response.status_code != 200:
raise exceptions.ServerError(
status_code=response.status_code,
)

return [Quote(**quote) for quote in response.json()]

def search_by_character_name(self, character_name: str, page: int = 1) -> Quote:
"""
Return a list of quotes from the given character.
"""
response = requests.get(
f"{self.endpoint}/quotes/character",
params={"name": character_name, "page": page},
)

if response.status_code != 200:
raise exceptions.ServerError(
status_code=response.status_code,
)

return [Quote(**quote) for quote in response.json()]

def get_animes(self, page: int = 1):
"""
Return a list of animes.
"""
response = requests.get(f"{self.endpoint}/available/anime", params={"page": page})

if response.status_code != 200:
raise exceptions.ServerError(
status_code=response.status_code,
)

return response.json()
13 changes: 13 additions & 0 deletions anime_api/apis/animechan/objects.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from dataclasses import dataclass


@dataclass
class Quote:
"""
Object representing a quote. Anime and character are not objects because the API returns a
title (for the anime) or a name (for the character).
"""

anime: str
character: str
quote: str
3 changes: 1 addition & 2 deletions anime_api/apis/trace_moe/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ def __init__(
endpoint: typing.Optional[str] = None,
x_trace_key: typing.Optional[str] = None,
):
if endpoint:
self.endpoint = endpoint
self.endpoint = endpoint or self.endpoint
self.x_trace_key = x_trace_key

def search(
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "anime-api"
version = "0.2.0"
version = "0.3.0"
description = "A collection of wrappers for anime-related APIs"
authors = ["Neki <84998222+Nekidev@users.noreply.github.com>"]
readme = "README.md"
Expand Down
2 changes: 1 addition & 1 deletion tests/anime_facts_rest_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Usage:
cd tests
poetry run python -m pytest
poetry run python -m pytest anime_facts_rest_api.py
"""

import typing
Expand Down
72 changes: 72 additions & 0 deletions tests/animechan.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
"""
Run tests for the AnimechanAPI class.
Usage:
cd tests
poetry run python -m pytest animechan.py
"""
from anime_api.apis.animechan import AnimechanAPI
from anime_api.apis.animechan.objects import Quote


def test_get_quote():
"""
Test the get_quote method. Should return a single quote.
"""
quote = AnimechanAPI().get_random_quote()

assert isinstance(quote, Quote), "The return type of get_quote() is not a Quote."


def test_get_10_random_quotes():
"""
Test the get_10_random_quotes method. Should return a list of quotes.
"""
quotes = AnimechanAPI().get_10_random_quotes()

assert isinstance(
quotes, list
), "The return type of get_10_random_quotes() is not a list."
assert len(quotes) > 0, "The list of quotes is empty."
for quote in quotes:
assert isinstance(
quote, Quote
), "The list of quotes does not contain Quote objects."


def test_search_quote_by_anime_title():
"""
Test the search_quote_by_anime_title method. Should return a list of quotes.
"""
quotes = AnimechanAPI().search_by_anime_title("Naruto")

assert isinstance(
quotes, list
), "The return type of search_quote_by_anime_title() is not a list."
assert len(quotes) > 0, "The list of quotes is empty."
for quote in quotes:
assert isinstance(
quote, Quote
), "The list of quotes does not contain Quote objects."


def test_search_quote_by_character_name():
"""
Test the search_quote_by_character_name method. Should return a list of quotes.
"""
quotes = AnimechanAPI().search_by_character_name("Naruto")

assert isinstance(
quotes, list
), "The return type of search_quote_by_character_name() is not a list."
assert len(quotes) > 0, "The list of quotes is empty."


def test_get_animes():
"""
Test the get_animes method. Should return a list of anime titles.
"""
animes = AnimechanAPI().get_animes()

assert isinstance(animes, list), "The return type of get_animes() is not a list."
assert len(animes) > 0, "The list of animes is empty."

0 comments on commit f39f0a5

Please sign in to comment.