feat(cli):improve anilist interfaces api

This commit is contained in:
Benex254
2024-08-05 09:47:00 +03:00
parent 39eca03ed7
commit 9050e5f6cf
16 changed files with 503 additions and 246 deletions

View File

@@ -30,6 +30,6 @@ def format_list_data_with_comma(data: list | None):
def extract_next_airing_episode(airing_episode: AnilistMediaNextAiringEpisode):
if airing_episode:
return f"Episode: {airing_episode['episode']} on {format_anilist_timestamp(airing_episode['airingAt'])}"
return f"{airing_episode['episode']} on {format_anilist_timestamp(airing_episode['airingAt'])}"
else:
return "Completed"

View File

@@ -7,6 +7,11 @@ from datetime import datetime
# from .kivy_markup_helper import color_text
def remove_html_tags(text):
clean = re.compile("<.*?>")
return re.sub(clean, "", text)
# utility functions
def write_crash(e: Exception):
index = datetime.today()

View File

@@ -36,6 +36,7 @@ if not APP_DATA_DIR:
USER_DATA_PATH = os.path.join(APP_DATA_DIR, "user_data.json")
USER_CONFIG_PATH = os.path.join(APP_DATA_DIR, "config.ini")
USER_WATCH_HISTORY = os.path.join(APP_DATA_DIR, "watch_history.json")
# video dir

View File

@@ -24,7 +24,7 @@ commands = {
"--server",
type=click.Choice(SERVERS_AVAILABLE, case_sensitive=False),
)
@click.option("-h", "--hist", type=bool)
@click.option("-c-h/-no-h", "--continue_h/--no-continue_h", type=bool)
@click.option("-q", "--quality", type=int)
@click.option("-t-t", "--translation_type")
@click.option("-a-n", "--auto-next", type=bool)
@@ -38,7 +38,7 @@ commands = {
def run_cli(
ctx: click.Context,
server,
hist,
continue_h,
translation_type,
quality,
auto_next,
@@ -48,8 +48,8 @@ def run_cli(
ctx.obj = Config()
if server:
ctx.obj.server = server
if hist:
ctx.obj.continue_from_history = hist
if continue_h:
ctx.obj.continue_from_history = continue_h
if quality:
ctx.obj.quality = quality
if auto_next:

View File

@@ -1,6 +1,7 @@
import click
from ...interfaces import anilist as anilist_interface
from ...interfaces.anilist_interfaces import anilist as anilist_interface
from ...utils.tools import QueryDict
from .favourites import favourites
from .popular import popular
from .recent import recent
@@ -19,6 +20,8 @@ commands = {
@click.group(commands=commands, invoke_without_command=True)
@click.pass_obj
def anilist(config):
anilist_interface(config=config)
@click.pass_context
def anilist(ctx: click.Context):
if ctx.invoked_subcommand is None:
anilist_config = QueryDict()
anilist_interface(ctx.obj, anilist_config)

View File

@@ -1,6 +1,15 @@
import click
from ....libs.anilist.anilist import AniList
from ...interfaces.anilist_interfaces import select_anime
from ...utils.tools import QueryDict
@click.command()
def favourites():
print("favourites")
@click.pass_obj
def favourites(config):
anime_data = AniList.get_most_favourite()
if anime_data[0]:
anilist_config = QueryDict()
anilist_config.data = anime_data[1]
select_anime(config, anilist_config)

View File

@@ -1,7 +1,5 @@
import click
from ..interfaces import anime_provider_
@click.command()
@click.pass_obj
@@ -9,7 +7,4 @@ def search(
config,
anime_title,
):
anime_provider_(
config,
anime_title,
)
pass

View File

@@ -1,7 +1,8 @@
import json
import os
from configparser import ConfigParser
from .. import USER_CONFIG_PATH, USER_DOWNLOADS_DIR
from .. import USER_CONFIG_PATH, USER_DOWNLOADS_DIR, USER_WATCH_HISTORY
class Config(object):
@@ -15,6 +16,7 @@ class Config(object):
"sort_by": "search match",
"downloads_dir": USER_DOWNLOADS_DIR,
"translation_type": "sub",
"preferred_language": "romaji",
}
)
self.configparser.add_section("stream")
@@ -33,10 +35,26 @@ class Config(object):
self.auto_next = self.get_auto_next()
self.quality = self.get_quality()
self.server = self.get_server()
self.preferred_language = self.get_preferred_language()
# ---- setup history ------
if not os.path.exists(USER_WATCH_HISTORY):
self.watch_history = {}
else:
with open(USER_WATCH_HISTORY, "r") as history:
self.watch_history = json.load(history)
def update_watch_history(self, title, episode):
with open(USER_WATCH_HISTORY, "w") as history:
self.watch_history[title] = episode
json.dump(self.watch_history, history)
def get_downloads_dir(self):
return self.configparser.get("general", "downloads_dir")
def get_preferred_language(self):
return self.configparser.get("general", "preferred_language")
def get_sort_by(self):
return self.configparser.get("anilist", "sort_by")

View File

@@ -1,215 +0,0 @@
from __future__ import annotations
from InquirerPy import inquirer
from rich import print
from ..libs.anilist.anilist import AniList
from ..libs.anilist.anilist_data_schema import AnilistDataSchema
from ..libs.anime_provider.allanime.api import anime_provider
from .config import Config
from .utils.mpv import mpv
from .utils.utils import clear, fuzzy_inquirer, get_selected_anime, get_selected_server
def fetch_episode(config: Config, anime, translation_type, selected_anime):
# fetch episode
episode_number = fuzzy_inquirer(
"Select Episode:",
[*anime["show"]["availableEpisodesDetail"][translation_type], "back"],
)
if episode_number == "back":
anime_provider_(
config,
selected_anime[0]["name"],
)
return
episode = anime_provider.get_anime_episode(
selected_anime[0]["_id"], episode_number, config.translation_type
)
fetch_streams(config, episode, anime, translation_type, selected_anime)
def fetch_streams(config: Config, episode, *args):
episode_streams = list(anime_provider.get_episode_streams(episode))
server = fuzzy_inquirer(
"Select Server:", [episode_stream[0] for episode_stream in episode_streams]
)
selected_server = get_selected_server(server, episode_streams)
quality = config.quality
links = selected_server[1]["links"]
if quality > len(links) - 1:
quality = config.quality = len(links) - 1
elif quality < 0:
quality = config.quality = 0
stream_link = links[quality]["link"]
print(
"[bold magenta]Now playing:[/]",
args[-1][0]["name"],
"[bold magenta] Episode: [/]",
episode["episode"]["episodeString"],
)
mpv(stream_link)
clear()
player_controls(config, episode, links, *args)
def player_controls(config: Config, episode, links: list, *args):
anime = args[0]
selected_anime = args[-1]
episodes = [*anime["show"]["availableEpisodesDetail"][config.translation_type]]
episodes = sorted(episodes, key=int)
current_episode = episode["episode"]["episodeString"]
def _back():
fetch_streams(config, episode, *args)
def _replay():
stream_link = links[config.quality]["link"]
print(
"[bold magenta]Now playing:[/]",
args[-1][0]["name"],
"[bold magenta] Episode: [/]",
episode["episode"]["episodeString"],
)
mpv(stream_link)
clear()
player_controls(config, episode, links, *args)
def _next_episode():
next_episode = episodes.index(current_episode) + 1
if next_episode >= len(episodes):
next_episode = len(episodes) - 1
episode = anime_provider.get_anime_episode(
selected_anime[0]["_id"], episodes[next_episode], config.translation_type
)
fetch_streams(config, episode, *args)
def _episodes():
fetch_episode(config, *args)
def _previous_episode():
prev_episode = episodes.index(current_episode) - 1
if prev_episode <= 0:
prev_episode = 0
episode = anime_provider.get_anime_episode(
selected_anime[0]["_id"], episodes[prev_episode], config.translation_type
)
fetch_streams(config, episode, *args)
def _change_quality():
options = [link["link"] for link in links]
quality = fuzzy_inquirer("Select Quality:", options)
config.quality = options.index(quality) # set quality
player_controls(config, episode, links, *args)
def _change_translation_type():
options = ["sub", "dub"]
translation_type = fuzzy_inquirer("Select Translation Type:", options)
config.translation_type = translation_type # set trannslation type
player_controls(config, episode, links, *args)
options = {
"Replay": _replay,
"Next Episode": _next_episode,
"Episodes": _episodes,
"Previous Episode": _previous_episode,
"Change Quality": _change_quality,
"Change Translation Type": _change_translation_type,
"Back": _back,
}
action = fuzzy_inquirer("Select Action:", options.keys())
options[action]()
def anime_provider_(config: Config, anime_title, **kwargs):
translation_type = config.translation_type
search_results = anime_provider.search_for_anime(anime_title, translation_type)
search_results_anime_titles = [
anime["name"] for anime in search_results["shows"]["edges"]
]
selected_anime_title = fuzzy_inquirer(
"Select Search Result:",
[*search_results_anime_titles, "back"],
default=kwargs.get("default_anime_title", ""),
)
if selected_anime_title == "back":
anilist(config)
return
fetch_anime_epiosode(
config,
selected_anime_title,
search_results,
)
def fetch_anime_epiosode(config, selected_anime_title, search_results):
translation_type = config.translation_type
selected_anime = get_selected_anime(selected_anime_title, search_results)
anime = anime_provider.get_anime(selected_anime[0]["_id"])
fetch_episode(config, anime, translation_type, selected_anime)
def _stream(config, anilist_data: AnilistDataSchema, preferred_lang="romaji"):
anime_titles = [
str(anime["title"][preferred_lang])
for anime in anilist_data["data"]["Page"]["media"]
]
selected_anime_title = fuzzy_inquirer("Select Anime:", anime_titles)
anime_provider_(
config, selected_anime_title, default_anime_title=selected_anime_title
)
def anilist_options(config, anilist_data: AnilistDataSchema):
def _watch_trailer():
pass
def _add_to_list():
pass
def _remove_from_list():
pass
def _view_info():
pass
options = {
"stream": _stream,
"watch trailer": _watch_trailer,
"add to list": _add_to_list,
"remove from list": _remove_from_list,
"view info": _view_info,
"back": anilist,
}
action = fuzzy_inquirer("Select Action:", options.keys())
options[action](config, anilist_data)
def anilist(config, *args, **kwargs):
def _anilist_search():
search_term = inquirer.text(
"Search:", instruction="Enter anime to search for"
).execute()
return AniList.search(query=search_term)
options = {
"trending": AniList.get_trending,
"search": _anilist_search,
"most popular anime": AniList.get_most_popular,
"most favourite anime": AniList.get_most_favourite,
"most scored anime": AniList.get_most_scored,
"upcoming anime": AniList.get_most_favourite,
"recently updated anime": AniList.get_most_recently_updated,
}
action = fuzzy_inquirer("Select Action:", options.keys())
anilist_data = options[action]()
if anilist_data[0]:
anilist_options(config, anilist_data[1])

View File

@@ -0,0 +1,404 @@
from __future__ import annotations
import sys
from InquirerPy import inquirer
from rich import print
from ...libs.anilist.anilist import AniList
from ...libs.anilist.anilist_data_schema import AnilistBaseMediaDataSchema
from ...libs.anime_provider.allanime.api import anime_provider
from ...libs.anime_provider.allanime.data_types import AllAnimeEpisode, AllAnimeShow
from ..config import Config
from ..utils.mpv import mpv
from ..utils.tools import QueryDict
from ..utils.utils import clear, fuzzy_inquirer
# FIXME: BACK brocken
def player_controls(config: Config, anilist_config: QueryDict):
# user config
translation_type: str = config.translation_type
# internal config
_anime: AllAnimeShow = anilist_config._anime
current_episode: str = anilist_config.episode_number
episodes: list = anilist_config.episodes
links: list = anilist_config.current_stream_links
current_link: str = anilist_config.current_stream_link
anime_title: str = anilist_config.anime_title
def _back():
fetch_streams(config, anilist_config)
def _replay():
print(
"[bold magenta]Now Replaying:[/]",
anime_title,
"[bold magenta] Episode: [/]",
current_episode,
)
config.update_watch_history(anime_title, current_episode)
mpv(current_link)
clear()
player_controls(config, anilist_config)
def _next_episode():
next_episode = episodes.index(current_episode) + 1
if next_episode >= len(episodes):
next_episode = len(episodes) - 1
episode = anime_provider.get_anime_episode(
_anime["_id"], episodes[next_episode], translation_type
)
# update internal config
anilist_config.episode = episode
anilist_config.episode_number = episodes[next_episode]
# update user config
config.update_watch_history(anime_title, episodes[next_episode])
# call interface
fetch_streams(config, anilist_config)
def _episodes():
# reset watch_history
config.update_watch_history(anime_title, None)
# call interface
fetch_episode(config, anilist_config)
def _previous_episode():
prev_episode = episodes.index(current_episode) - 1
if prev_episode <= 0:
prev_episode = 0
episode = anime_provider.get_anime_episode(
_anime["_id"], episodes[prev_episode], config.translation_type
)
# update internal config
anilist_config.episode = episode
# anilist_config.episode_title = episode["title"]
anilist_config.episode_number = episodes[prev_episode]
# update user config
config.update_watch_history(anime_title, episodes[prev_episode])
# call interface
fetch_streams(config, anilist_config)
def _change_quality():
# extract the actual link urls
options = [link["link"] for link in links]
# prompt for new quality
quality = fuzzy_inquirer("Select Quality:", options)
config.quality = options.index(quality) # set quality
player_controls(config, anilist_config)
def _change_translation_type():
# prompt for new translation type
options = ["sub", "dub"]
translation_type = fuzzy_inquirer("Select Translation Type:", options)
# update internal config
config.translation_type = translation_type
# reload to controls
player_controls(config, anilist_config)
options = {
"Replay": _replay,
"Next Episode": _next_episode,
"Episodes": _episodes,
"Previous Episode": _previous_episode,
"Change Quality": _change_quality,
"Change Translation Type": _change_translation_type,
"Back to servers": _back,
"Go to Main Menu": lambda: anilist(config, anilist_config),
"Go to Anime Options Menu": lambda: anilist_options(config, anilist_config),
"Go to Search Results": lambda: select_anime(config, anilist_config),
"exit": sys.exit,
}
action = fuzzy_inquirer("Select Action:", options.keys())
# update_watch_history
config.update_watch_history(anime_title, current_episode)
options[action]()
def fetch_streams(config: Config, anilist_config: QueryDict):
# user config
quality: int = config.quality
# internal config
episode: AllAnimeEpisode = anilist_config.episode
episode_number: str = anilist_config.episode_number
anime_title: str = anilist_config.anime_title
# get streams for episode from provider
episode_streams = anime_provider.get_episode_streams(episode)
episode_streams = {
episode_stream[0]: episode_stream[1] for episode_stream in episode_streams
}
# prompt for preferred server
server = fuzzy_inquirer("Select Server:", [*episode_streams.keys(), "back"])
if server == "back":
# reset watch_history
config.update_watch_history(anime_title, None)
fetch_episode(config, anilist_config)
return
selected_server = episode_streams[server]
links = selected_server["links"]
if quality > len(links) - 1:
quality = config.quality = len(links) - 1
elif quality < 0:
quality = config.quality = 0
stream_link = links[quality]["link"]
# update internal config
anilist_config.current_stream_links = links
anilist_config.current_stream_link = stream_link
anilist_config.current_server = selected_server
anilist_config.current_server_name = server
# play video
print(
"[bold magenta]Now playing:[/]",
anime_title,
"[bold magenta] Episode: [/]",
episode_number,
)
mpv(stream_link)
# switch to controls
clear()
player_controls(config, anilist_config)
def fetch_episode(config: Config, anilist_config: QueryDict):
# user config
translation_type: str = config.translation_type
continue_from_history: bool = config.continue_from_history
user_watch_history = config.watch_history
anime_title = anilist_config.anime_title
# internal config
anime = anilist_config.anime
_anime: AllAnimeShow = anilist_config._anime
# prompt for episode number
# TODO: Load episode number from cache
episodes = anime["show"]["availableEpisodesDetail"][translation_type]
if continue_from_history and user_watch_history.get(anime_title) in episodes:
episode_number = user_watch_history[anime_title]
print(f"[bold cyan]Continuing from Episode:[/] [bold]{episode_number}[/]")
else:
episode_number = fuzzy_inquirer(
"Select Episode:",
[*episodes, "back"],
)
if episode_number == "back":
provide_anime(config, anilist_config)
return
config.update_watch_history(anime_title, episode_number)
# get the episode info from provider
episode = anime_provider.get_anime_episode(
_anime["_id"], episode_number, translation_type
)
# update internal config
anilist_config.episodes = episodes
anilist_config.episode = episode
# anilist_config.episode_title = episode["title"]
anilist_config.episode_number = episode_number
# next interface
fetch_streams(config, anilist_config)
def fetch_anime_epiosode(config, anilist_config: QueryDict):
selected_anime: AllAnimeShow = anilist_config._anime
anilist_config.anime = anime_provider.get_anime(selected_anime["_id"])
fetch_episode(config, anilist_config)
def provide_anime(config: Config, anilist_config: QueryDict):
# user config
translation_type = config.translation_type
# internal config
selected_anime_title = anilist_config.selected_anime_title
# search and get the requested title from provider
search_results = anime_provider.search_for_anime(
selected_anime_title, translation_type
)
search_results = {
anime["name"]: anime for anime in search_results["shows"]["edges"]
}
anime_title = fuzzy_inquirer(
"Select Search Result:",
[*search_results.keys(), "back"],
default=selected_anime_title,
)
if anime_title == "back":
anilist_options(config, anilist_config)
return
anilist_config.anime_title = anime_title
anilist_config._anime = search_results[anime_title]
fetch_anime_epiosode(config, anilist_config)
def anilist_options(config, anilist_config: QueryDict):
selected_anime: AnilistBaseMediaDataSchema = anilist_config.selected_anime_anilist
selected_anime_title: str = anilist_config.selected_anime_title
def _watch_trailer(config, anilist_config):
if trailer := selected_anime.get("trailer"):
trailer_url = "https://youtube.com/watch?v=" + trailer["id"]
print("[bold magenta]Watching Trailer of:[/]", selected_anime_title)
mpv(trailer_url)
anilist_options(config, anilist_config)
def _add_to_list(config, anilist_config):
pass
def _remove_from_list():
pass
def _change_translation_type(config, anilist_config):
# prompt for new translation type
options = ["sub", "dub"]
translation_type = fuzzy_inquirer("Select Translation Type:", options)
# update internal config
config.translation_type = translation_type
anilist_options(config, anilist_config)
def _view_info(config, anilist_config):
from InquirerPy import inquirer
from rich.console import Console
from ...Utility import anilist_data_helper
from ...Utility.utils import remove_html_tags
from ..utils.print_img import print_img
clear()
console = Console()
print_img(selected_anime["coverImage"]["medium"])
console.print("[bold cyan]Title(jp): ", selected_anime["title"]["romaji"])
console.print("[bold cyan]Title(eng): ", selected_anime["title"]["english"])
console.print("[bold cyan]Popularity: ", selected_anime["popularity"])
console.print("[bold cyan]Favourites: ", selected_anime["favourites"])
console.print("[bold cyan]Status: ", selected_anime["status"])
console.print(
"[bold cyan]Start Date: ",
anilist_data_helper.format_anilist_date_object(selected_anime["startDate"]),
)
console.print(
"[bold cyan]End Date: ",
anilist_data_helper.format_anilist_date_object(selected_anime["endDate"]),
)
# console.print("[bold cyan]Season: ", selected_anime["season"])
console.print("[bold cyan]Episodes: ", selected_anime["episodes"])
console.print(
"[bold cyan]Tags: ",
anilist_data_helper.format_list_data_with_comma(
[tag["name"] for tag in selected_anime["tags"]]
),
)
console.print(
"[bold cyan]Genres: ",
anilist_data_helper.format_list_data_with_comma(selected_anime["genres"]),
)
# console.print("[bold cyan]Type: ", selected_anime["st"])
if selected_anime["nextAiringEpisode"]:
console.print(
"[bold cyan]Next Episode: ",
anilist_data_helper.extract_next_airing_episode(
selected_anime["nextAiringEpisode"]
),
)
console.print(
"[bold underline cyan]Description\n[/]",
remove_html_tags(str(selected_anime["description"])),
)
if inquirer.confirm("Enter to continue", default=True).execute():
anilist_options(config, anilist_config)
return
options = {
"stream": provide_anime,
"watch trailer": _watch_trailer,
"add to list": _add_to_list,
"remove from list": _remove_from_list,
"view info": _view_info,
"Change Translation Type": _change_translation_type,
"back": select_anime,
}
action = fuzzy_inquirer("Select Action:", options.keys())
options[action](config, anilist_config)
def select_anime(config: Config, anilist_config: QueryDict):
anime_data = {
str(
anime["title"][config.preferred_language] or anime["title"]["romaji"]
): anime
for anime in anilist_config.data["data"]["Page"]["media"]
}
selected_anime_title = fuzzy_inquirer(
"Select Anime:",
[
*anime_data.keys(),
"back",
],
)
if selected_anime_title == "back":
anilist(config, anilist_config)
return
selected_anime = anime_data[selected_anime_title]
anilist_config.selected_anime_anilist = selected_anime
anilist_config.selected_anime_title = selected_anime_title
anilist_options(config, anilist_config)
def anilist(config: Config, anilist_config: QueryDict):
def _anilist_search():
search_term = inquirer.text(
"Search:", instruction="Enter anime to search for"
).execute()
return AniList.search(query=search_term)
options = {
"trending": AniList.get_trending,
"search": _anilist_search,
"most popular anime": AniList.get_most_popular,
"most favourite anime": AniList.get_most_favourite,
"most scored anime": AniList.get_most_scored,
"upcoming anime": AniList.get_upcoming_anime,
"recently updated anime": AniList.get_most_recently_updated,
}
action = fuzzy_inquirer("Select Action:", options.keys())
anilist_data = options[action]()
if anilist_data[0]:
anilist_config.data = anilist_data[1]
select_anime(config, anilist_config)

View File

@@ -0,0 +1,24 @@
import shutil
import subprocess
import requests
def print_img(url: str):
executable = shutil.which("chafa")
curl = shutil.which("curl")
# curl -sL "$1" | chafa /dev/stdin
if executable is None or curl is None:
print("chafa or curl not found")
return
res = requests.get(url)
if res.status_code != 200:
print("Error fetching image")
return
img_bytes = res.content
if not img_bytes:
print("No image found")
img_bytes = subprocess.check_output([curl, "-sL", url])
subprocess.run([executable, url, "--size=15x15"], input=img_bytes)

View File

@@ -0,0 +1,13 @@
class QueryDict(dict):
"""dot.notation access to dictionary attributes"""
def __getattr__(self, attr):
try:
return self.__getitem__(attr)
except KeyError:
raise AttributeError(
"%r object has no attribute %r" % (self.__class__.__name__, attr)
)
def __setattr__(self, attr, value):
self.__setitem__(attr, value)

View File

@@ -20,7 +20,12 @@ def clear():
def fuzzy_inquirer(prompt: str, choices, **kwargs):
clear()
action = inquirer.fuzzy(
prompt, choices, height="100%", border=True, **kwargs
prompt,
choices,
height="100%",
border=True,
validate=lambda result: result in choices,
**kwargs,
).execute()
return action

View File

@@ -175,7 +175,7 @@ class AniList:
return airing_schedule
@classmethod
def get_upcoming_anime(cls, page: int, *_, **kwargs):
def get_upcoming_anime(cls, page: int = 1, *_, **kwargs):
"""
Gets upcoming anime from anilist
"""

View File

@@ -11,7 +11,6 @@ from .constants import (
ALLANIME_REFERER,
USER_AGENT,
)
from .data_types import AllAnimeEpisode, AllAnimeSearchResults
from .gql_queries import ALLANIME_EPISODES_GQL, ALLANIME_SEARCH_GQL, ALLANIME_SHOW_GQL
from .utils import decode_hex_string
@@ -27,7 +26,7 @@ class AllAnimeAPI:
api_endpoint = ALLANIME_API_ENDPOINT
def _fetch_gql(self, query: str, variables: dict) -> dict:
def _fetch_gql(self, query: str, variables: dict):
try:
response = requests.get(
self.api_endpoint,
@@ -38,16 +37,12 @@ class AllAnimeAPI:
headers={"Referer": ALLANIME_REFERER, "User-Agent": USER_AGENT},
timeout=10,
)
if response.status_code != 200:
return {}
return response.json().get("data", {})
return response.json()["data"]
except Exception as e:
Logger.error(f"allanime:Error: {e}")
return {}
def search_for_anime(
self, user_query: str, translation_type: str = "sub"
) -> AllAnimeSearchResults | dict:
def search_for_anime(self, user_query: str, translation_type: str = "sub"):
search = {"allowAdult": False, "allowUnknown": False, "query": user_query}
limit = 40
translationtype = translation_type
@@ -75,7 +70,7 @@ class AllAnimeAPI:
def get_anime_episode(
self, allanime_show_id: str, episode_string: str, translation_type: str = "sub"
) -> AllAnimeEpisode | dict:
):
variables = {
"showId": allanime_show_id,
"translationType": translation_type,

View File

@@ -15,7 +15,7 @@ fuzzywuzzy = "^0.18.0"
rich = "^13.7.1"
click = "^8.1.7"
python-levenshtein = "^0.25.1"
kivymd = [{url = "https://github.com/kivymd/KivyMD/archive/master.zip"}]
kivymd = [{ url = "https://github.com/kivymd/KivyMD/archive/master.zip" }]
pyshortcuts = "^1.9.0"
inquirerpy = "^0.3.4"
@@ -40,4 +40,4 @@ fastanime = 'fastanime:FastAnime'
[tool.bandit]
#exclude = tests,path/to/file
#tests = B201,B301
skips = ["B311","B603","B607","B404"]
skips = ["B311", "B603", "B607", "B404"]