feat: show episodes count in ui and get progress from server if dont exist locally

This commit is contained in:
Benex254
2024-08-05 09:47:06 +03:00
parent a15a2b1e6d
commit 2ff580cbd2
5 changed files with 112 additions and 53 deletions

View File

@@ -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")

View File

@@ -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()