Compare commits

...

5 Commits

Author SHA1 Message Date
Benexl
08ae8786c3 feat: sanitize " in key 2025-11-18 14:48:00 +03:00
Benexl
64093204ad feat: create temp episode preview script 2025-11-18 14:28:54 +03:00
Benexl
8440ffb5e5 feat: add a key for extra uniqueness 2025-11-18 14:20:07 +03:00
Benexl
6e287d320d feat: rewrite episode info script in python 2025-11-18 13:59:40 +03:00
Benexl
a7b0f21deb feat: rename info.py to media_info.py 2025-11-18 13:44:20 +03:00
6 changed files with 76 additions and 23 deletions

View File

@@ -0,0 +1,44 @@
import sys
from rich.console import Console
from rich.table import Table
from rich.rule import Rule
from rich.markdown import Markdown
console = Console(force_terminal=True, color_system="truecolor")
HEADER_COLOR = sys.argv[1]
SEPARATOR_COLOR = sys.argv[2]
def rule(title: str | None = None):
console.print(Rule(style=f"rgb({SEPARATOR_COLOR})"))
console.print("{TITLE}", justify="center")
left = [
("Duration", "Status"),
("Total Episodes", "Next Episode"),
("Progress", "List Status"),
("Start Date", "End Date"),
]
right = [
("{DURATION}", "{STATUS}"),
("{EPISODES}", "{NEXT_EPISODE}"),
("{USER_PROGRESS}", "{USER_STATUS}"),
("{START_DATE}", "{END_DATE}"),
]
for L_grp, R_grp in zip(left, right):
table = Table.grid(expand=True)
table.add_column(justify="left", no_wrap=True)
table.add_column(justify="right", overflow="fold")
for L, R in zip(L_grp, R_grp):
table.add_row(f"[bold rgb({HEADER_COLOR})]{L} [/]", f"{R}")
rule()
console.print(table)
rule()

View File

@@ -26,8 +26,10 @@ SCALE_UP = "{SCALE_UP}" == "True"
# fzf passes the title with quotes, so we need to trim them
TITLE = sys.argv[1]
KEY = """{KEY}"""
KEY = KEY + "-" if KEY else KEY
hash = f"{PREFIX}-{sha256(TITLE.encode('utf-8')).hexdigest()}"
hash = f"{PREFIX}-{sha256((KEY + TITLE).encode('utf-8')).hexdigest()}"
def fzf_image_preview(file_path: str):

View File

@@ -6,6 +6,8 @@ from typing import Dict, List, Optional
import httpx
from viu_media.core.utils import formatter
from ...core.config import AppConfig
from ...core.constants import APP_CACHE_DIR, PLATFORM, SCRIPTS_DIR
from ...core.utils.file import AtomicWriter
@@ -299,18 +301,19 @@ def get_anime_preview(
# Color codes
"HEADER_COLOR": ",".join(HEADER_COLOR),
"SEPARATOR_COLOR": ",".join(SEPARATOR_COLOR),
"PREFIX": "search-results",
"PREFIX": "search-result",
"KEY": "",
"SCALE_UP": str(config.general.preview_scale_up),
}
for key, value in replacements.items():
preview_script = preview_script.replace(f"{{{key}}}", value)
(PREVIEWS_CACHE_DIR / "search-results-preview-script.py").write_text(
(PREVIEWS_CACHE_DIR / "search-result-preview-script.py").write_text(
preview_script, encoding="utf-8"
)
preview_script_final = f"{sys.executable} {PREVIEWS_CACHE_DIR / 'search-results-preview-script.py'} {{}}"
preview_script_final = f"{sys.executable} {PREVIEWS_CACHE_DIR / 'search-result-preview-script.py'} {{}}"
return preview_script_final
@@ -348,30 +351,30 @@ def get_episode_preview(
logger.error(f"Failed to start episode background caching: {e}")
# Continue with script generation even if caching fails
# Prepare values to inject into the template
path_sep = "\\" if PLATFORM == "win32" else "/"
# Format the template with the dynamic values
replacements = {
"PREVIEW_MODE": config.general.preview,
"IMAGE_CACHE_PATH": str(IMAGES_CACHE_DIR),
"INFO_CACHE_PATH": str(INFO_CACHE_DIR),
"PATH_SEP": path_sep,
"IMAGE_CACHE_DIR": str(IMAGES_CACHE_DIR),
"INFO_CACHE_DIR": str(INFO_CACHE_DIR),
"IMAGE_RENDERER": config.general.image_renderer,
# Color codes
"C_TITLE": ansi.get_true_fg(HEADER_COLOR, bold=True),
"C_KEY": ansi.get_true_fg(HEADER_COLOR, bold=True),
"C_VALUE": ansi.get_true_fg(HEADER_COLOR, bold=True),
"C_RULE": ansi.get_true_fg(SEPARATOR_COLOR, bold=True),
"RESET": ansi.RESET,
"PREFIX": f"{media_item.title.english}_Episode_",
"SCALE_UP": " --scale-up" if config.general.preview_scale_up else "",
"HEADER_COLOR": ",".join(HEADER_COLOR),
"SEPARATOR_COLOR": ",".join(SEPARATOR_COLOR),
"PREFIX": "episode",
"KEY": f"{media_item.title.english.replace(formatter.DOUBLE_QUOTE, formatter.SINGLE_QUOTE)}",
"SCALE_UP": str(config.general.preview_scale_up),
}
for key, value in replacements.items():
preview_script = preview_script.replace(f"{{{key}}}", value)
return preview_script
(PREVIEWS_CACHE_DIR / "episode-preview-script.py").write_text(
preview_script, encoding="utf-8"
)
preview_script_final = (
f"{sys.executable} {PREVIEWS_CACHE_DIR / 'episode-preview-script.py'} {{}}"
)
return preview_script_final
def get_dynamic_anime_preview(config: AppConfig) -> str:

View File

@@ -31,7 +31,9 @@ logger = logging.getLogger(__name__)
FZF_SCRIPTS_DIR = SCRIPTS_DIR / "fzf"
TEMPLATE_INFO_SCRIPT = (FZF_SCRIPTS_DIR / "info.py").read_text(encoding="utf-8")
TEMPLATE_MEDIA_INFO_SCRIPT = (FZF_SCRIPTS_DIR / "media_info.py").read_text(
encoding="utf-8"
)
TEMPLATE_EPISODE_INFO_SCRIPT = (FZF_SCRIPTS_DIR / "episode_info.py").read_text(
encoding="utf-8"
)
@@ -142,7 +144,7 @@ class PreviewCacheWorker(ManagedBackgroundWorker):
def _generate_info_text(self, media_item: MediaItem, config: AppConfig) -> str:
"""Generate formatted info text for a media item."""
# Import here to avoid circular imports
info_script = TEMPLATE_INFO_SCRIPT
info_script = TEMPLATE_MEDIA_INFO_SCRIPT
description = formatter.clean_html(
media_item.description or "No description available."
)
@@ -236,7 +238,7 @@ class PreviewCacheWorker(ManagedBackgroundWorker):
"""Generate a cache hash for the given text."""
from hashlib import sha256
return f"search-results-{sha256(text.encode('utf-8')).hexdigest()}"
return f"search-result-{sha256(text.encode('utf-8')).hexdigest()}"
def _on_task_completed(self, task: WorkerTask, future) -> None:
"""Handle task completion with enhanced logging."""
@@ -306,7 +308,7 @@ class EpisodeCacheWorker(ManagedBackgroundWorker):
for episode_str in episodes:
hash_id = self._get_cache_hash(
f"{media_item.title.english}_Episode_{episode_str}"
f"{media_item.title.english.replace(formatter.DOUBLE_QUOTE, formatter.SINGLE_QUOTE)}-{episode_str}"
)
# Find episode data
@@ -402,7 +404,7 @@ class EpisodeCacheWorker(ManagedBackgroundWorker):
"""Generate a cache hash for the given text."""
from hashlib import sha256
return sha256(text.encode("utf-8")).hexdigest()
return "episode-" + sha256(text.encode("utf-8")).hexdigest()
def _on_task_completed(self, task: WorkerTask, future) -> None:
"""Handle task completion with enhanced logging."""

View File

@@ -5,6 +5,8 @@ from typing import Dict, List, Optional, Union
from ...libs.media_api.types import AiringSchedule
COMMA_REGEX = re.compile(r"([0-9]{3})(?=\d)")
SINGLE_QUOTE = "'"
DOUBLE_QUOTE = '"'
def format_media_duration(total_minutes: Optional[int]) -> str: