mirror of
https://github.com/Benexl/FastAnime.git
synced 2026-01-27 07:14:33 -08:00
feat: show episodes count in ui and get progress from server if dont exist locally
This commit is contained in:
@@ -373,16 +373,28 @@ def fetch_episode(config: Config, anilist_config: QueryDict):
|
||||
# internal config
|
||||
anime: Anime = anilist_config.anime
|
||||
_anime: SearchResult = anilist_config._anime
|
||||
|
||||
selected_anime_anilist: AnilistBaseMediaDataSchema = (
|
||||
anilist_config.selected_anime_anilist
|
||||
)
|
||||
# prompt for episode number
|
||||
episodes = anime["availableEpisodesDetail"][translation_type]
|
||||
if (
|
||||
continue_from_history
|
||||
and user_watch_history.get(str(anime_id), {}).get("episode") in episodes
|
||||
):
|
||||
episode_number = user_watch_history[str(anime_id)]["episode"]
|
||||
print(f"[bold cyan]Continuing from Episode:[/] [bold]{episode_number}[/]")
|
||||
else:
|
||||
episode_number = ""
|
||||
if continue_from_history:
|
||||
if user_watch_history.get(str(anime_id), {}).get("episode") in episodes:
|
||||
episode_number = user_watch_history[str(anime_id)]["episode"]
|
||||
print(f"[bold cyan]Continuing from Episode:[/] [bold]{episode_number}[/]")
|
||||
elif selected_anime_anilist["mediaListEntry"]:
|
||||
episode_number = str(
|
||||
selected_anime_anilist.get("mediaListEntry", {}).get(
|
||||
"progress"
|
||||
) # type:ignore
|
||||
)
|
||||
episode_number = episode_number if episode_number in episodes else ""
|
||||
print(f"[bold cyan]Continuing from Episode:[/] [bold]{episode_number}[/]")
|
||||
else:
|
||||
episode_number = ""
|
||||
|
||||
if not episode_number:
|
||||
choices = [*episodes, "Back"]
|
||||
if config.use_fzf:
|
||||
episode_number = fzf.run(
|
||||
@@ -501,6 +513,8 @@ def provide_anime(config: Config, anilist_config: QueryDict):
|
||||
def anilist_options(config, anilist_config: QueryDict):
|
||||
selected_anime: AnilistBaseMediaDataSchema = anilist_config.selected_anime_anilist
|
||||
selected_anime_title: str = anilist_config.selected_anime_title
|
||||
progress = (selected_anime["mediaListEntry"] or {"progress": 0}).get("progress", 0)
|
||||
episodes_total = selected_anime["episodes"] or "Inf"
|
||||
|
||||
def _watch_trailer(config: Config, anilist_config: QueryDict):
|
||||
if trailer := selected_anime.get("trailer"):
|
||||
@@ -678,7 +692,7 @@ def anilist_options(config, anilist_config: QueryDict):
|
||||
|
||||
icons = config.icons
|
||||
options = {
|
||||
f"{'📽️ ' if icons else ''}Stream": provide_anime,
|
||||
f"{'📽️ ' if icons else ''}Stream ({progress}/{episodes_total})": provide_anime,
|
||||
f"{'📼 ' if icons else ''}Watch Trailer": _watch_trailer,
|
||||
f"{'✨ ' if icons else ''}Score Anime": _score_anime,
|
||||
f"{'📥 ' if icons else ''}Add to List": _add_to_list,
|
||||
@@ -703,19 +717,24 @@ def anilist_options(config, anilist_config: QueryDict):
|
||||
|
||||
def select_anime(config: Config, anilist_config: QueryDict):
|
||||
search_results = anilist_config.data["data"]["Page"]["media"]
|
||||
anime_data = {
|
||||
sanitize_filename(
|
||||
str(anime["title"][config.preferred_language] or anime["title"]["romaji"])
|
||||
): anime
|
||||
for anime in search_results
|
||||
}
|
||||
|
||||
anime_data = {}
|
||||
for anime in search_results:
|
||||
anime: AnilistBaseMediaDataSchema
|
||||
progress = (anime["mediaListEntry"] or {"progress": 0}).get("progress", 0)
|
||||
episodes_total = anime["episodes"] or "Inf"
|
||||
title = str(
|
||||
anime["title"][config.preferred_language] or anime["title"]["romaji"]
|
||||
)
|
||||
title = sanitize_filename(f"{title} ({progress} of {episodes_total})")
|
||||
anime_data[title] = anime
|
||||
|
||||
choices = [*anime_data.keys(), "Back"]
|
||||
if config.use_fzf:
|
||||
if config.preview:
|
||||
from .utils import get_preview
|
||||
|
||||
preview = get_preview(search_results, config)
|
||||
preview = get_preview(search_results, anime_data.keys())
|
||||
selected_anime_title = fzf.run(
|
||||
choices,
|
||||
prompt="Select Anime: ",
|
||||
@@ -733,15 +752,9 @@ def select_anime(config: Config, anilist_config: QueryDict):
|
||||
if config.preview:
|
||||
from .utils import IMAGES_DIR, get_icons
|
||||
|
||||
get_icons(search_results, config)
|
||||
get_icons(search_results, anime_data.keys())
|
||||
choices = []
|
||||
for anime in search_results:
|
||||
title = sanitize_filename(
|
||||
str(
|
||||
anime["title"][config.preferred_language]
|
||||
or anime["title"]["romaji"]
|
||||
)
|
||||
)
|
||||
for title in anime_data.keys():
|
||||
icon_path = os.path.join(IMAGES_DIR, title)
|
||||
choices.append(f"{title}\0icon\x1f{icon_path}")
|
||||
choices.append("Back")
|
||||
|
||||
@@ -11,8 +11,7 @@ import requests
|
||||
from ...constants import APP_CACHE_DIR
|
||||
from ...libs.anilist.anilist_data_schema import AnilistBaseMediaDataSchema
|
||||
from ...Utility import anilist_data_helper
|
||||
from ...Utility.utils import remove_html_tags, sanitize_filename
|
||||
from ..config import Config
|
||||
from ...Utility.utils import remove_html_tags
|
||||
from ..utils.utils import get_true_fg
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -133,22 +132,20 @@ def save_info_from_str(info: str, file_name: str):
|
||||
|
||||
|
||||
def write_search_results(
|
||||
search_results: list[AnilistBaseMediaDataSchema], config: Config, workers=None
|
||||
search_results: list[AnilistBaseMediaDataSchema],
|
||||
titles,
|
||||
workers=None,
|
||||
):
|
||||
H_COLOR = 215, 0, 95
|
||||
S_COLOR = 208, 208, 208
|
||||
S_WIDTH = 45
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=workers) as executor:
|
||||
future_to_task = {}
|
||||
for anime in search_results:
|
||||
anime_title = (
|
||||
anime["title"][config.preferred_language] or anime["title"]["romaji"]
|
||||
)
|
||||
anime_title = sanitize_filename(anime_title)
|
||||
for anime, title in zip(search_results, titles):
|
||||
image_url = anime["coverImage"]["large"]
|
||||
future_to_task[
|
||||
executor.submit(save_image_from_url, image_url, anime_title)
|
||||
] = image_url
|
||||
future_to_task[executor.submit(save_image_from_url, image_url, title)] = (
|
||||
image_url
|
||||
)
|
||||
|
||||
# handle the text data
|
||||
template = f"""
|
||||
@@ -172,9 +169,7 @@ def write_search_results(
|
||||
{textwrap.fill(remove_html_tags(
|
||||
str(anime['description'])), width=45)}
|
||||
"""
|
||||
future_to_task[
|
||||
executor.submit(save_info_from_str, template, anime_title)
|
||||
] = anime_title
|
||||
future_to_task[executor.submit(save_info_from_str, template, title)] = title
|
||||
|
||||
# execute the jobs
|
||||
for future in concurrent.futures.as_completed(future_to_task):
|
||||
@@ -186,19 +181,15 @@ def write_search_results(
|
||||
|
||||
|
||||
# get rofi icons
|
||||
def get_icons(search_results: list[AnilistBaseMediaDataSchema], config, workers=None):
|
||||
def get_icons(search_results: list[AnilistBaseMediaDataSchema], titles, workers=None):
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=workers) as executor:
|
||||
# load the jobs
|
||||
future_to_url = {}
|
||||
for anime in search_results:
|
||||
anime_title = (
|
||||
anime["title"][config.preferred_language] or anime["title"]["romaji"]
|
||||
)
|
||||
anime_title = sanitize_filename(anime_title)
|
||||
for anime, title in zip(search_results, titles):
|
||||
image_url = anime["coverImage"]["large"]
|
||||
future_to_url[
|
||||
executor.submit(save_image_from_url, image_url, anime_title)
|
||||
] = image_url
|
||||
future_to_url[executor.submit(save_image_from_url, image_url, title)] = (
|
||||
image_url
|
||||
)
|
||||
|
||||
# execute the jobs
|
||||
for future in concurrent.futures.as_completed(future_to_url):
|
||||
@@ -209,12 +200,10 @@ def get_icons(search_results: list[AnilistBaseMediaDataSchema], config, workers=
|
||||
logger.error("%r generated an exception: %s" % (url, exc))
|
||||
|
||||
|
||||
def get_preview(
|
||||
search_results: list[AnilistBaseMediaDataSchema], config: Config, wait=False
|
||||
):
|
||||
def get_preview(search_results: list[AnilistBaseMediaDataSchema], titles, wait=False):
|
||||
# ensure images and info exists
|
||||
background_worker = Thread(
|
||||
target=write_search_results, args=(search_results, config)
|
||||
target=write_search_results, args=(search_results, titles)
|
||||
)
|
||||
background_worker.daemon = True
|
||||
background_worker.start()
|
||||
|
||||
Reference in New Issue
Block a user