From 2a21d9ccd01fbd2fb1f23edf1003990e8acea9d8 Mon Sep 17 00:00:00 2001 From: Neki <84998222+Nekidev@users.noreply.github.com> Date: Sun, 30 Apr 2023 16:46:04 -0300 Subject: [PATCH] Added Catboys API --- README.md | 304 +++++++++++++-------------- anime_api/__init__.py | 2 +- anime_api/apis/__init__.py | 1 + anime_api/apis/catboys/__init__.py | 85 ++++++++ anime_api/apis/catboys/objects.py | 39 ++++ anime_api/apis/nekos_api/__init__.py | 4 +- pyproject.toml | 2 +- tests/test_catboys_api.py | 58 +++++ 8 files changed, 332 insertions(+), 163 deletions(-) create mode 100644 anime_api/apis/catboys/__init__.py create mode 100644 anime_api/apis/catboys/objects.py create mode 100644 tests/test_catboys_api.py diff --git a/README.md b/README.md index 137db30..38be828 100644 --- a/README.md +++ b/README.md @@ -4,25 +4,26 @@ The Anime API is a collection of wrappers for different types of free anime-related APIs. [Join our Discord server](https://discord.gg/PgQnuM3YnM). - ## Why anime-api (and not others)? There are several reasons why would you prefer using anime-api: -- **Intuitive**: anime-api is designed to be intuitive. Supports autocompletion everywhere. -- **Complete**: Every actively supported API has no feature left apart. -- **Simple**: Get all the anime information you want with a single line of code. -- **Legal**: I shouldn't need to say this, but all the APIs are legal. (no free streaming services/others) -- **Actively supported**: Get new releases (with new API wrappers) every now and then. +- **Intuitive**: anime-api is designed to be intuitive. Supports autocompletion everywhere. +- **Complete**: Every actively supported API has no feature left apart. +- **Simple**: Get all the anime information you want with a single line of code. +- **Legal**: I shouldn't need to say this, but all the APIs are legal. (no free streaming services/others) +- **Actively supported**: Get new releases (with new API wrappers) every now and then. ## Installation Using Poetry: + ``` poetry add anime-api ``` Using pip: + ``` pip install anime-api ``` @@ -31,13 +32,12 @@ pip install anime-api The full documentation can be found [here](docs/). - ## APIs These are the currently supported and planned to add support for APIs: | Name | API Documentation | Available | -|-----------------------------|-------------------------------------------------------------------------------------|-----------| +| --------------------------- | ----------------------------------------------------------------------------------- | --------- | | Anime Facts Rest API | [Documentation](https://chandan-02.github.io/anime-facts-rest-api/) | ✅ | | Trace.moe | [Documentation](https://soruly.github.io/trace.moe-api/) | ✅ | | Animechan | [Documentation](https://animechan.vercel.app/docs) | ✅ | @@ -48,7 +48,7 @@ These are the currently supported and planned to add support for APIs: | AniList | [Documentation](https://anilist.gitbook.io/anilist-apiv2-docs/) | ❌ | | AniDB | [Documentation](https://wiki.anidb.net/w/API) | ❌ | | Kyoko | [Documentation](https://github.com/Elliottophellia/kyoko) | ✅ | -| Animu | [Documentation](https://docs.animu.ml/) | ✅ | +| Animu | [Documentation](https://docs.animu.ml/) | ✅ (down) | | Anisearch | [Documentation](https://anisearch.com/developers) | ❌ | | Anime News Network | [Documentation](https://www.animenewsnetwork.com/encyclopedia/api.php) | ❌ | | Notify.moe (Anime Notifier) | [Documentation](https://notify.moe/api) | ❌ | @@ -64,207 +64,193 @@ These are the currently supported and planned to add support for APIs: | Yandere | [Documentation](https://yande.re/help/api) | ❌ | | Konachan | [Documentation](https://konachan.com/help/api) | ❌ | | Waifu.im | [Documentation](https://waifu.im/) | ✅ | -| Catboys | [Documentation](https://catboys.com/api) | ❌ | +| Catboys | [Documentation](https://catboys.com/api) | ✅ | | Anime Character Database | [Documentation](http://wiki.animecharactersdatabase.com/index.php?title=API_Access) | ❌ | -| AniBase | Not released | ❌ | -| Nekos API | [Documentation](https://nekos.nekidev.com/docs/rest-api/endpoints) | ✅ | - +| Nekos API | [Documentation](https://v1.nekosapi.com/docs/rest-api/endpoints) | ✅ | ### APIs by feature You know what you want to do, but have no idea of what API will work for you? This list orders the APIs by features. See which fits you best! - #### Images -- Nekos API: - - Thousands of anime images - - Lots of image metadata - - Actively developed (frequent new features, images, categories, and more) - - 100% open-source - - `v2.0.0` in its way - - Official Python wrapper (this!) - - Completely free -- Animu: - - Tons of anime gifs and images - - Get reaction gifs from +60 different categories - - Completely free -- Hmtai: - - Tons of anime gifs and images - - SFW and NSFW images - - Get random images from +70 different categories - - Completely free -- Nekos.life - - Lots of different neko pics - - Get random neko images from +20 different categories - - Completely free -- Waifu.pics - - Lots of different waifu images - - Get random images from +30 categories - - SFW and NSFW images - - Get 30 different images with a single API call - - Get a different image every time - - Completely free -- NekoBot - - Lots of different neko images - - Image generation (memes, ships, etc.) - - Get random images from 30 different categories - - SFW and NSFW images - - Completely free -- Nekos.moe - - Lots of different neko images - - Advanced image search - - Upload images - - Like and favorite images - - SFW and NSFW images - - Get any amount of random images - - Completely free -- Nekos.best - - Lots of different neko images - - Get random images from +35 different categories - - Get many random images with a single API call - - Search for images by category, format and more - - Fully SFW - - 99.9% uptime - - Fast response times - - Get all image's source - - Completely free - +- Nekos API: + - Thousands of anime images + - Lots of image metadata + - Actively developed (frequent new features, images, categories, and more) + - 100% open-source + - `v2.0.0` in its way + - Official Python wrapper (this!) + - Completely free +- Animu: + - Tons of anime gifs and images + - Get reaction gifs from +60 different categories + - Completely free +- Hmtai: + - Tons of anime gifs and images + - SFW and NSFW images + - Get random images from +70 different categories + - Completely free +- Nekos.life + - Lots of different neko pics + - Get random neko images from +20 different categories + - Completely free +- Waifu.pics + - Lots of different waifu images + - Get random images from +30 categories + - SFW and NSFW images + - Get 30 different images with a single API call + - Get a different image every time + - Completely free +- NekoBot + - Lots of different neko images + - Image generation (memes, ships, etc.) + - Get random images from 30 different categories + - SFW and NSFW images + - Completely free +- Nekos.moe + - Lots of different neko images + - Advanced image search + - Upload images + - Like and favorite images + - SFW and NSFW images + - Get any amount of random images + - Completely free +- Nekos.best + - Lots of different neko images + - Get random images from +35 different categories + - Get many random images with a single API call + - Search for images by category, format and more + - Fully SFW + - 99.9% uptime + - Fast response times + - Get all image's source + - Completely free #### Facts -- Anime Facts Rest API: - - Lots of different anime facts - - Get random fact from an anime - - Save fact ID and refetch the fact later - - Get a list of all available animes - - Completely free -- Animu: - - Lots of anime facts - - Get random anime facts - - Completely free -- Kyoko: - - Lots of different anime facts - - Get random reaction gifs from 3 different categories - - Completely free -- Nekos.life - - Lots of different anime facts - - Get random anime facts - - Completely free - +- Anime Facts Rest API: + - Lots of different anime facts + - Get random fact from an anime + - Save fact ID and refetch the fact later + - Get a list of all available animes + - Completely free +- Animu: + - Lots of anime facts + - Get random anime facts + - Completely free +- Kyoko: + - Lots of different anime facts + - Get random reaction gifs from 3 different categories + - Completely free +- Nekos.life + - Lots of different anime facts + - Get random anime facts + - Completely free #### Quotes -- Animechan: - - Lots of different quotes from a large list of characters and animes - - Get random anime quotes - - Get 10 random anime quotes with a single api call - - Search quotes by character name or anime title - - Get a list of all available animes - - Completely free -- Animu: - - Lots of different anime quotes with information about who said them and where - - Get random anime quotes - - Completely free. -- Kyoko: - - Lots of different anime quotes - - Get random quotes with information about who said them and where - - Completely free - +- Animechan: + - Lots of different quotes from a large list of characters and animes + - Get random anime quotes + - Get 10 random anime quotes with a single api call + - Search quotes by character name or anime title + - Get a list of all available animes + - Completely free +- Animu: + - Lots of different anime quotes with information about who said them and where + - Get random anime quotes + - Completely free. +- Kyoko: + - Lots of different anime quotes + - Get random quotes with information about who said them and where + - Completely free #### Waifus -- Animu: - - Lots of different waifus from Video Games, Animes, Movies and more. - - Get random waifus with their statistics, source, many images and more. - - Completely free - +- Animu: + - Lots of different waifus from Video Games, Animes, Movies and more. + - Get random waifus with their statistics, source, many images and more. + - Completely free #### Animes -- Anime Facts Rest API: - - Get a list of lots of snake-case anime titles with their images and facts about them - - Completely free -- Animechan: - - Get a list of lots of anime titles with random quotes from them - - Completely free -- Studio Ghibli API - - Get Studio Ghibli animes with information such as director, producer, etc. - - Dynamic loading support - - Get super specific anime details such as veichles, locations, people, and species. - - Completely free - +- Anime Facts Rest API: + - Get a list of lots of snake-case anime titles with their images and facts about them + - Completely free +- Animechan: + - Get a list of lots of anime titles with random quotes from them + - Completely free +- Studio Ghibli API + - Get Studio Ghibli animes with information such as director, producer, etc. + - Dynamic loading support + - Get super specific anime details such as veichles, locations, people, and species. + - Completely free #### Entertainment -- Nekos.life - - Get an answer from an 8ball with an aditional image of an 8ball showing the answer. - - Get a random "why?" question - - Completely free - +- Nekos.life + - Get an answer from an 8ball with an aditional image of an 8ball showing the answer. + - Get a random "why?" question + - Completely free #### Utilities -- Trace.moe - - Find an anime from a screenshot with information about the specific anime, episode and time of the screenshot. - - Completely free -- Nekos.life - - Get a random cat text emoji - - Generate random names - - Owoify text (`hello` => `hewwo`) - - Mark text as spoiler (`hello` => `||hello||`) (API endpoint is currently bugged) - - Completely free -- Animu: - - Generate a secure password - - Completely free - +- Trace.moe + - Find an anime from a screenshot with information about the specific anime, episode and time of the screenshot. + - Completely free +- Nekos.life + - Get a random cat text emoji + - Generate random names + - Owoify text (`hello` => `hewwo`) + - Mark text as spoiler (`hello` => `||hello||`) (API endpoint is currently bugged) + - Completely free +- Animu: + - Generate a secure password + - Completely free ### APIs that will not be supported -- Illegal anime streaming services -- Non anime-related APIs -- APIs that are not APIs (i.e. web scrapping) +- Illegal anime streaming services +- Non anime-related APIs +- APIs that are not APIs (i.e. web scrapping) ## Contributing Read the following before contributing: - ### Adding an API If you want to add an API to the list, please make sure that: -- The API is free to use -- The API is anime-related (or manga-related) -- You follow the same architecture as the other API wrappers -- Document the code you write -- Add all the necessary tests to the `tests` folder - +- The API is free to use +- The API is anime-related (or manga-related) +- You follow the same architecture as the other API wrappers +- Document the code you write +- Add all the necessary tests to the `tests` folder ### Fixing an API wrapper Before fixing an API wrapper, please make sure that: -- The bug is not being fixed in another PR -- The bug is actually a bug and not a feature (xd) -- The bug is not a bug from the API itself -- You have created an issue. If you have not created an issue, please create one before fixing the bug. - +- The bug is not being fixed in another PR +- The bug is actually a bug and not a feature (xd) +- The bug is not a bug from the API itself +- You have created an issue. If you have not created an issue, please create one before fixing the bug. ### Requesting a new API If you want to request a new API, please make sure that: -- The API is free to use -- The API is anime-related (or manga-related) -- It is not already in the list (wether available or not) +- The API is free to use +- The API is anime-related (or manga-related) +- It is not already in the list (wether available or not) Once you have checked this, please create an issue with the following information: -- The name of the API -- The API docs link -- List of all the features the API has - +- The name of the API +- The API docs link +- List of all the features the API has ## Mantainers diff --git a/anime_api/__init__.py b/anime_api/__init__.py index 6561da5..b136b1a 100644 --- a/anime_api/__init__.py +++ b/anime_api/__init__.py @@ -52,7 +52,7 @@ ), # 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", apis.WaifuImAPI, "https://waifu.im/", True), - ("Catboys", None, "https://catboys.com/api", False), + ("Catboys", apis.CatboysAPI, "https://catboys.com/api", True), ( "Anime Character Database", None, diff --git a/anime_api/apis/__init__.py b/anime_api/apis/__init__.py index f0f7a71..3628831 100644 --- a/anime_api/apis/__init__.py +++ b/anime_api/apis/__init__.py @@ -16,3 +16,4 @@ from .nekos_best import NekosBest from .waifu_im import WaifuImAPI from .nekos_api import NekosAPI +from .catboys import CatboysAPI diff --git a/anime_api/apis/catboys/__init__.py b/anime_api/apis/catboys/__init__.py new file mode 100644 index 0000000..83de8ac --- /dev/null +++ b/anime_api/apis/catboys/__init__.py @@ -0,0 +1,85 @@ +""" +Base module for the Catboys API. Endpoints can be found at https://catboys.com/api +""" +import typing +import requests + +from anime_api import exceptions + +from anime_api.apis.catboys.objects import Image, EightBall, DiceRoll + + +class CatboysAPI: + """ + Endpoints: https://api.catboys.com/endpoints + """ + + endpoint: str = "https://api.catboys.com" + + def __init__(self, endpoint: typing.Optional[str] = None): + self.endpoint = endpoint or self.endpoint + + def get_random_image(self) -> Image: + """ + Returns a random image. + """ + + response = requests.get(self.endpoint + "/img") + CatboysAPI._check_response_code(response) + + return Image.from_json(response.json()) + + def get_random_baka_gif(self) -> str: + """ + Returns a random baka gif. + """ + + response = requests.get(self.endpoint + "/baka") + CatboysAPI._check_response_code(response) + + return response.json()["url"] + + def get_eight_ball(self) -> EightBall: + """ + Returns an 8ball prediction. + """ + + response = requests.get(self.endpoint + "/8ball") + CatboysAPI._check_response_code(response) + + return EightBall.from_json(response.json()) + + def get_dice_roll(self) -> DiceRoll: + """ + Returns a random number and image from a virtual 6-sided dice. + """ + + response = requests.get(self.endpoint + "/dice") + CatboysAPI._check_response_code(response) + + return DiceRoll.from_json(response.json()) + + def get_catboy_saying(self) -> str: + """ + Returns a random saying from a virtual catboy. + """ + + response = requests.get(self.endpoint + "/catboy") + CatboysAPI._check_response_code(response) + + return response.json()["response"] + + @staticmethod + def _check_response_code(res) -> None: + """ + Check if the request was successful. + """ + data = res.json() + if ( + res.status_code not in range(200, 300) + or data.get("error", "none") != "none" + ): + raise exceptions.ServerError( + res.status_code, + f"An error occurred while fetching the data from the server{'. ' + data['error'] if data.get('error', 'none') != 'none' else ''}", + ) diff --git a/anime_api/apis/catboys/objects.py b/anime_api/apis/catboys/objects.py new file mode 100644 index 0000000..70b34d3 --- /dev/null +++ b/anime_api/apis/catboys/objects.py @@ -0,0 +1,39 @@ +from dataclasses import dataclass + + +@dataclass +class _Artist: + name: str + url: str + + +@dataclass +class Image: + url: str + artist: _Artist + source_url: str + + def from_json(data: dict): + return Image( + url=data["url"], + artist=_Artist(data["artist"], data["artist_url"]), + source_url=data["source_url"], + ) + + +@dataclass +class EightBall: + answer: str + image: str + + def from_json(data: dict): + return EightBall(answer=data["response"], image=data["url"]) + + +@dataclass +class DiceRoll: + number: int + image: str + + def from_json(data: dict): + return DiceRoll(number=data["response"], image=data["url"]) diff --git a/anime_api/apis/nekos_api/__init__.py b/anime_api/apis/nekos_api/__init__.py index a94752e..423be2c 100644 --- a/anime_api/apis/nekos_api/__init__.py +++ b/anime_api/apis/nekos_api/__init__.py @@ -52,10 +52,10 @@ def decorator(*args, **kwargs): class NekosAPI: """ - Docs: https://nekos.nekidev.com/docs/rest-api/endpoints + Docs: https://v1.nekosapi.com/docs/rest-api/endpoints """ - endpoint: str = "https://nekos.nekidev.com/api" + endpoint: str = "https://api.nekosapi.com/v1" token: typing.Optional[str] = None def __init__( diff --git a/pyproject.toml b/pyproject.toml index 7ee7cdb..dfd46cb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "anime-api" -version = "0.15.4" +version = "1.0.0" description = "A collection of wrappers for anime-related APIs" authors = ["Neki <84998222+Nekidev@users.noreply.github.com>"] readme = "README.md" diff --git a/tests/test_catboys_api.py b/tests/test_catboys_api.py new file mode 100644 index 0000000..d8cd350 --- /dev/null +++ b/tests/test_catboys_api.py @@ -0,0 +1,58 @@ +""" +Run tests for the AnimuAPI class + +Usage: + Replace the api_token variable with your API token. + + cd tests + poetry run python -m pytest test_catboys_api.py +""" +from anime_api.apis import CatboysAPI +from anime_api.apis.catboys import objects + + +def test_get_random_image(): + """ + Test the get_random_image method + """ + api = CatboysAPI() + image = api.get_random_image() + assert isinstance(image, objects.Image) + + +def test_get_random_baka_gif(): + """ + Test the get_random_baka_gif method + """ + api = CatboysAPI() + gif = api.get_random_baka_gif() + assert isinstance(gif, str) + + +def test_get_eight_ball(): + """ + Test the get_eight_ball method + """ + api = CatboysAPI() + eight_ball = api.get_eight_ball() + assert isinstance(eight_ball, objects.EightBall) + + +def test_get_dice_roll(): + """ + Test the get_dice_roll method + """ + + api = CatboysAPI() + dice_roll = api.get_dice_roll() + assert isinstance(dice_roll, objects.DiceRoll) + + +def test_get_catboy_saying(): + """ + Test the get_catboy_saying method + """ + + api = CatboysAPI() + catboy_saying = api.get_catboy_saying() + assert isinstance(catboy_saying, str)