mirror of
https://github.com/Benexl/FastAnime.git
synced 2025-12-29 06:03:29 -08:00
feat(cli): add auto-select provider results
This commit is contained in:
@@ -4,6 +4,12 @@ import shutil
|
||||
from datetime import datetime
|
||||
from functools import lru_cache
|
||||
|
||||
from fuzzywuzzy import fuzz
|
||||
|
||||
from fastanime.libs.anilist.anilist_data_schema import AnilistBaseMediaDataSchema
|
||||
|
||||
from .data import anime_normalizer
|
||||
|
||||
# TODO: make it use color_text instead of fixed vals
|
||||
# from .kivy_markup_helper import color_text
|
||||
|
||||
@@ -98,6 +104,32 @@ def sanitize_filename(filename: str):
|
||||
return sanitized
|
||||
|
||||
|
||||
def anime_title_percentage_match(
|
||||
possible_user_requested_anime_title: str, anime: AnilistBaseMediaDataSchema
|
||||
) -> float:
|
||||
"""Returns the percentage match between the possible title and user title
|
||||
|
||||
Args:
|
||||
possible_user_requested_anime_title (str): an Animdl search result title
|
||||
title (str): the anime title the user wants
|
||||
|
||||
Returns:
|
||||
int: the percentage match
|
||||
"""
|
||||
if normalized_anime_title := anime_normalizer.get(
|
||||
possible_user_requested_anime_title
|
||||
):
|
||||
possible_user_requested_anime_title = normalized_anime_title
|
||||
# compares both the romaji and english names and gets highest Score
|
||||
title_a = str(anime["title"]["romaji"])
|
||||
title_b = str(anime["title"]["english"])
|
||||
percentage_ratio = max(
|
||||
fuzz.ratio(title_a.lower(), possible_user_requested_anime_title.lower()),
|
||||
fuzz.ratio(title_b.lower(), possible_user_requested_anime_title.lower()),
|
||||
)
|
||||
return percentage_ratio
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Example usage
|
||||
unsafe_filename = "CON:example?file*name.txt"
|
||||
|
||||
@@ -48,7 +48,8 @@ signal.signal(signal.SIGINT, handle_exit)
|
||||
@click.option("-c/-no-c", "--continue/--no-continue", "continue_", type=bool)
|
||||
@click.option("-q", "--quality", type=int)
|
||||
@click.option("-t", "--translation_type")
|
||||
@click.option("-a", "--auto-next", type=bool)
|
||||
@click.option("-A/-no-A", "--auto-next/--no-auto-next", type=bool)
|
||||
@click.option("-a/-no-a", "--auto-select/--no-auto-select", type=bool)
|
||||
@click.option(
|
||||
"-S",
|
||||
"--sort-by",
|
||||
@@ -63,6 +64,7 @@ def run_cli(
|
||||
translation_type,
|
||||
quality,
|
||||
auto_next,
|
||||
auto_select,
|
||||
sort_by,
|
||||
downloads_dir,
|
||||
):
|
||||
@@ -75,6 +77,8 @@ def run_cli(
|
||||
ctx.obj.quality = quality
|
||||
if auto_next:
|
||||
ctx.obj.auto_next = auto_next
|
||||
if auto_select:
|
||||
ctx.obj.auto_select = auto_select
|
||||
if sort_by:
|
||||
ctx.obj.sort_by = sort_by
|
||||
if downloads_dir:
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import click
|
||||
from fuzzywuzzy import fuzz
|
||||
from rich import print
|
||||
|
||||
from ...libs.anime_provider.allanime.api import anime_provider
|
||||
from ...libs.anime_provider.types import Anime
|
||||
@@ -35,9 +37,15 @@ def download(config: Config, anime_title, episode_range):
|
||||
search_result["title"]: search_result for search_result in search_results
|
||||
}
|
||||
|
||||
search_result = fzf.run(
|
||||
list(search_results_.keys()), "Please Select title: ", "FastAnime"
|
||||
)
|
||||
if config.auto_select:
|
||||
search_result = max(
|
||||
search_results_.keys(), key=lambda title: fuzz.ratio(title, anime_title)
|
||||
)
|
||||
print("[cyan]Auto selecting:[/] ", search_result)
|
||||
else:
|
||||
search_result = fzf.run(
|
||||
list(search_results_.keys()), "Please Select title: ", "FastAnime"
|
||||
)
|
||||
|
||||
anime: Anime = anime_provider.get_anime(search_results_[search_result]["id"])
|
||||
|
||||
@@ -51,7 +59,7 @@ def download(config: Config, anime_title, episode_range):
|
||||
try:
|
||||
episode = str(episode)
|
||||
if episode not in episodes:
|
||||
print("Episode not found skipping")
|
||||
print(f"[cyan]Warning[/]: Episode {episode} not found, skipping")
|
||||
continue
|
||||
streams = anime_provider.get_episode_streams(
|
||||
anime, episode, config.translation_type
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import click
|
||||
from fuzzywuzzy import fuzz
|
||||
from rich import print
|
||||
|
||||
from ...cli.config import Config
|
||||
from ...libs.anime_provider.allanime.api import anime_provider
|
||||
@@ -24,16 +26,23 @@ def search(
|
||||
search_results_ = {
|
||||
search_result["title"]: search_result for search_result in search_results
|
||||
}
|
||||
if config.auto_select:
|
||||
search_result = max(
|
||||
search_results_.keys(), key=lambda title: fuzz.ratio(title, anime_title)
|
||||
)
|
||||
print("[cyan]Auto Selecting:[/] ", search_result)
|
||||
|
||||
search_result = fzf.run(
|
||||
list(search_results_.keys()), "Please Select title: ", "FastAnime"
|
||||
)
|
||||
else:
|
||||
search_result = fzf.run(
|
||||
list(search_results_.keys()), "Please Select title: ", "FastAnime"
|
||||
)
|
||||
|
||||
anime: Anime = anime_provider.get_anime(search_results_[search_result]["id"])
|
||||
|
||||
def stream_anime():
|
||||
episodes = anime["availableEpisodesDetail"][config.translation_type]
|
||||
episode = fzf.run(episodes, "Select an episode: ", header="Episodes")
|
||||
|
||||
episode = fzf.run(episodes, "Select an episode: ", header=search_result)
|
||||
streams = anime_provider.get_episode_streams(
|
||||
anime, episode, config.translation_type
|
||||
)
|
||||
|
||||
@@ -21,6 +21,7 @@ class Config(object):
|
||||
"continue_from_history": "False",
|
||||
"quality": "0",
|
||||
"auto_next": "True",
|
||||
"auto_select": "True",
|
||||
"sort_by": "search match",
|
||||
"downloads_dir": USER_VIDEOS_DIR,
|
||||
"translation_type": "sub",
|
||||
@@ -41,6 +42,7 @@ class Config(object):
|
||||
self.sort_by = self.get_sort_by()
|
||||
self.continue_from_history = self.get_continue_from_history()
|
||||
self.auto_next = self.get_auto_next()
|
||||
self.auto_select = self.get_auto_select()
|
||||
self.quality = self.get_quality()
|
||||
self.server = self.get_server()
|
||||
self.preferred_language = self.get_preferred_language()
|
||||
@@ -84,6 +86,9 @@ class Config(object):
|
||||
def get_auto_next(self):
|
||||
return self.configparser.getboolean("stream", "auto_next")
|
||||
|
||||
def get_auto_select(self):
|
||||
return self.configparser.getboolean("stream", "auto_select")
|
||||
|
||||
def get_quality(self):
|
||||
return self.configparser.getint("stream", "quality")
|
||||
|
||||
|
||||
@@ -14,7 +14,11 @@ from ...libs.anime_provider.types import Anime, SearchResult, Server
|
||||
from ...libs.fzf import fzf
|
||||
from ...Utility import anilist_data_helper
|
||||
from ...Utility.data import anime_normalizer
|
||||
from ...Utility.utils import remove_html_tags, sanitize_filename
|
||||
from ...Utility.utils import (
|
||||
anime_title_percentage_match,
|
||||
remove_html_tags,
|
||||
sanitize_filename,
|
||||
)
|
||||
from ..config import Config
|
||||
from ..utils.mpv import mpv
|
||||
from ..utils.tools import QueryDict, exit_app
|
||||
@@ -303,6 +307,7 @@ def fetch_episode(config: Config, anilist_config: QueryDict):
|
||||
continue_from_history: bool = config.continue_from_history
|
||||
user_watch_history: dict = config.watch_history
|
||||
anime_id: int = anilist_config.anime_id
|
||||
anime_title: str = anilist_config.anime_title
|
||||
|
||||
# internal config
|
||||
anime: Anime = anilist_config.anime
|
||||
@@ -317,7 +322,7 @@ def fetch_episode(config: Config, anilist_config: QueryDict):
|
||||
episode_number = fzf.run(
|
||||
[*episodes, "Back"],
|
||||
prompt="Select Episode:",
|
||||
header="Episodes",
|
||||
header=anime_title,
|
||||
)
|
||||
|
||||
if episode_number == "Back":
|
||||
@@ -354,6 +359,8 @@ def provide_anime(config: Config, anilist_config: QueryDict):
|
||||
# internal config
|
||||
selected_anime_title = anilist_config.selected_anime_title
|
||||
|
||||
anime_data: AnilistBaseMediaDataSchema = anilist_config.selected_anime_anilist
|
||||
|
||||
# search and get the requested title from provider
|
||||
search_results = anime_provider.search_for_anime(
|
||||
selected_anime_title, translation_type
|
||||
@@ -371,15 +378,22 @@ def provide_anime(config: Config, anilist_config: QueryDict):
|
||||
):
|
||||
_title = _title
|
||||
|
||||
anime_title = fzf.run(
|
||||
[*search_results.keys(), "Back"],
|
||||
prompt="Select Search Result:",
|
||||
header="Anime Search Results",
|
||||
)
|
||||
if config.auto_select:
|
||||
anime_title = max(
|
||||
search_results.keys(),
|
||||
key=lambda title: anime_title_percentage_match(title, anime_data),
|
||||
)
|
||||
print(f"[cyan]Auto selecting[/]: {anime_title}")
|
||||
else:
|
||||
anime_title = fzf.run(
|
||||
[*search_results.keys(), "Back"],
|
||||
prompt="Select Search Result:",
|
||||
header="Anime Search Results",
|
||||
)
|
||||
|
||||
if anime_title == "Back":
|
||||
anilist_options(config, anilist_config)
|
||||
return
|
||||
if anime_title == "Back":
|
||||
anilist_options(config, anilist_config)
|
||||
return
|
||||
anilist_config.anime_title = anime_normalizer.get(anime_title) or anime_title
|
||||
anilist_config._anime = search_results[anime_title]
|
||||
fetch_anime_episode(config, anilist_config)
|
||||
|
||||
@@ -151,7 +151,7 @@ class AllAnimeAPI:
|
||||
yield {
|
||||
"server": "gogoanime",
|
||||
"episode_title": allanime_episode["notes"]
|
||||
or f"{anime["title"]} Episode:{episode_number}",
|
||||
or f"{anime["title"]}: Episode {episode_number}",
|
||||
"links": resp.json()["links"],
|
||||
} # pyright:ignore
|
||||
case "Kir":
|
||||
@@ -160,7 +160,7 @@ class AllAnimeAPI:
|
||||
yield {
|
||||
"server": "wetransfer",
|
||||
"episode_title": allanime_episode["notes"]
|
||||
or f"{anime["title"]} Episode:{episode_number}",
|
||||
or f"{anime["title"]}: Episode {episode_number}",
|
||||
"links": resp.json()["links"],
|
||||
} # pyright:ignore
|
||||
case "S-mp4":
|
||||
@@ -169,7 +169,7 @@ class AllAnimeAPI:
|
||||
yield {
|
||||
"server": "sharepoint",
|
||||
"episode_title": allanime_episode["notes"]
|
||||
or f"{anime["title"]} Episode:{episode_number}",
|
||||
or f"{anime["title"]}: Episode {episode_number}",
|
||||
"links": resp.json()["links"],
|
||||
} # pyright:ignore
|
||||
case "Sak":
|
||||
@@ -178,7 +178,7 @@ class AllAnimeAPI:
|
||||
yield {
|
||||
"server": "dropbox",
|
||||
"episode_title": allanime_episode["notes"]
|
||||
or f"{anime["title"]} Episode:{episode_number}",
|
||||
or f"{anime["title"]}: Episode {episode_number}",
|
||||
"links": resp.json()["links"],
|
||||
} # pyright:ignore
|
||||
except Timeout:
|
||||
|
||||
Reference in New Issue
Block a user