diff --git a/viu_cli/cli/interactive/menu/media/download_episodes.py b/viu_cli/cli/interactive/menu/media/download_episodes.py index 72ebdf2..2027b14 100644 --- a/viu_cli/cli/interactive/menu/media/download_episodes.py +++ b/viu_cli/cli/interactive/menu/media/download_episodes.py @@ -6,7 +6,7 @@ from ...state import InternalDirective, State @session.menu def download_episodes(ctx: Context, state: State) -> State | InternalDirective: """Menu to select and download episodes synchronously.""" - from .....core.utils.fuzzy import fuzz + from viu_cli.cli.utils.search import find_best_match_title from .....core.utils.normalizer import normalize_title from ....service.download.service import DownloadService @@ -40,12 +40,8 @@ def download_episodes(ctx: Context, state: State) -> State | InternalDirective: return InternalDirective.BACK provider_results_map = {res.title: res for res in provider_search_results.results} - best_match_title = max( - provider_results_map.keys(), - key=lambda p_title: fuzz.ratio( - normalize_title(p_title, config.general.provider.value).lower(), - media_title.lower(), - ), + best_match_title = find_best_match_title( + provider_results_map, config.general.provider, media_item ) selected_provider_anime_ref = provider_results_map[best_match_title] diff --git a/viu_cli/cli/interactive/menu/media/provider_search.py b/viu_cli/cli/interactive/menu/media/provider_search.py index d3f0da1..f5ce13d 100644 --- a/viu_cli/cli/interactive/menu/media/provider_search.py +++ b/viu_cli/cli/interactive/menu/media/provider_search.py @@ -6,7 +6,7 @@ from ...state import InternalDirective, MenuName, ProviderState, State @session.menu def provider_search(ctx: Context, state: State) -> State | InternalDirective: - from .....core.utils.fuzzy import fuzz + from viu_cli.cli.utils.search import find_best_match_title from .....core.utils.normalizer import normalize_title, update_user_normalizer_json feedback = ctx.feedback @@ -51,12 +51,8 @@ def provider_search(ctx: Context, state: State) -> State | InternalDirective: # --- Auto-Select or Prompt --- if config.general.auto_select_anime_result: # Use fuzzy matching to find the best title - best_match_title = max( - provider_results_map.keys(), - key=lambda p_title: fuzz.ratio( - normalize_title(p_title, config.general.provider.value).lower(), - media_title.lower(), - ), + best_match_title = find_best_match_title( + provider_results_map, config.general.provider, media_item ) feedback.info(f"Auto-selecting best match: {best_match_title}") selected_provider_anime = provider_results_map[best_match_title] diff --git a/viu_cli/cli/service/download/service.py b/viu_cli/cli/service/download/service.py index dfbbe63..bff69f1 100644 --- a/viu_cli/cli/service/download/service.py +++ b/viu_cli/cli/service/download/service.py @@ -2,11 +2,12 @@ import logging from pathlib import Path from typing import TYPE_CHECKING, List +from viu_cli.cli.utils.search import find_best_match_title + from ....core.config.model import AppConfig from ....core.constants import APP_CACHE_DIR from ....core.downloader import DownloadParams, create_downloader from ....core.utils.concurrency import ManagedBackgroundWorker, thread_manager -from ....core.utils.fuzzy import fuzz from ....core.utils.normalizer import normalize_title from ....libs.media_api.types import MediaItem from ....libs.provider.anime.params import ( @@ -204,14 +205,8 @@ class DownloadService: provider_results_map = { result.title: result for result in provider_search_results.results } - best_match_title = max( - provider_results_map.keys(), - key=lambda p_title: fuzz.ratio( - normalize_title( - p_title, self.app_config.general.provider.value - ).lower(), - media_title.lower(), - ), + best_match_title = find_best_match_title( + provider_results_map, self.app_config.general.provider, media_item ) provider_anime_ref = provider_results_map[best_match_title] diff --git a/viu_cli/cli/utils/search.py b/viu_cli/cli/utils/search.py new file mode 100644 index 0000000..c32c506 --- /dev/null +++ b/viu_cli/cli/utils/search.py @@ -0,0 +1,36 @@ +"""Search functionality.""" + +from viu_cli.core.utils.fuzzy import fuzz +from viu_cli.core.utils.normalizer import normalize_title +from viu_cli.libs.provider.anime.types import SearchResult, ProviderName +from viu_cli.libs.media_api.types import MediaItem + + +def find_best_match_title( + provider_results_map: dict[str, SearchResult], + provider: ProviderName, + media_item: MediaItem, +) -> str: + """Find the best match title using fuzzy matching for both the english AND romaji title. + + Parameters: + provider_results_map (dict[str, SearchResult]): The map of provider results. + provider (ProviderName): The provider name from the config. + media_item (MediaItem): The media item to match. + + Returns: + str: The best match title. + """ + return max( + provider_results_map.keys(), + key=lambda p_title: max( + fuzz.ratio( + normalize_title(p_title, provider.value).lower(), + (media_item.title.romaji or "").lower(), + ), + fuzz.ratio( + normalize_title(p_title, provider.value).lower(), + (media_item.title.english or "").lower(), + ), + ), + )