mirror of
https://github.com/Benexl/FastAnime.git
synced 2025-12-12 15:50:01 -08:00
feat: airing schedule previews in python
This commit is contained in:
@@ -0,0 +1,41 @@
|
|||||||
|
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("{ANIME_TITLE}", justify="center")
|
||||||
|
|
||||||
|
left = [
|
||||||
|
("Total Episodes",),
|
||||||
|
("Upcoming Episodes",),
|
||||||
|
]
|
||||||
|
right = [
|
||||||
|
("{TOTAL_EPISODES}",),
|
||||||
|
("{UPCOMING_EPISODES}",),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
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()
|
||||||
|
console.print(Markdown("""{SCHEDULE_TABLE}"""))
|
||||||
|
|||||||
@@ -124,11 +124,9 @@ logger = logging.getLogger(__name__)
|
|||||||
PREVIEWS_CACHE_DIR = APP_CACHE_DIR / "previews"
|
PREVIEWS_CACHE_DIR = APP_CACHE_DIR / "previews"
|
||||||
IMAGES_CACHE_DIR = PREVIEWS_CACHE_DIR / "images"
|
IMAGES_CACHE_DIR = PREVIEWS_CACHE_DIR / "images"
|
||||||
INFO_CACHE_DIR = PREVIEWS_CACHE_DIR / "info"
|
INFO_CACHE_DIR = PREVIEWS_CACHE_DIR / "info"
|
||||||
AIRING_SCHEDULE_CACHE_DIR = PREVIEWS_CACHE_DIR / "airing_schedule"
|
|
||||||
|
|
||||||
FZF_SCRIPTS_DIR = SCRIPTS_DIR / "fzf"
|
FZF_SCRIPTS_DIR = SCRIPTS_DIR / "fzf"
|
||||||
TEMPLATE_PREVIEW_SCRIPT = (FZF_SCRIPTS_DIR / "preview.py").read_text(encoding="utf-8")
|
TEMPLATE_PREVIEW_SCRIPT = (FZF_SCRIPTS_DIR / "preview.py").read_text(encoding="utf-8")
|
||||||
TEMPLATE_AIRING_SCHEDULE_PREVIEW_SCRIPT = ""
|
|
||||||
DYNAMIC_PREVIEW_SCRIPT = ""
|
DYNAMIC_PREVIEW_SCRIPT = ""
|
||||||
|
|
||||||
EPISODE_PATTERN = re.compile(r"^Episode\s+(\d+)\s-\s.*")
|
EPISODE_PATTERN = re.compile(r"^Episode\s+(\d+)\s-\s.*")
|
||||||
@@ -457,6 +455,50 @@ def get_review_preview(choice_map: Dict[str, MediaReview], config: AppConfig) ->
|
|||||||
return preview_script
|
return preview_script
|
||||||
|
|
||||||
|
|
||||||
|
def get_airing_schedule_preview(
|
||||||
|
schedule_result: AiringScheduleResult, config: AppConfig, anime_title: str = "Anime"
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
Generate the generic loader script for airing schedule previews and start background caching.
|
||||||
|
"""
|
||||||
|
|
||||||
|
IMAGES_CACHE_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
|
INFO_CACHE_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
HEADER_COLOR = config.fzf.preview_header_color.split(",")
|
||||||
|
SEPARATOR_COLOR = config.fzf.preview_separator_color.split(",")
|
||||||
|
|
||||||
|
# Start managed background caching for episodes
|
||||||
|
try:
|
||||||
|
preview_manager = _get_preview_manager()
|
||||||
|
worker = preview_manager.get_airing_schedule_worker()
|
||||||
|
worker.cache_airing_schedule_preview(anime_title, schedule_result, config)
|
||||||
|
logger.debug("Started background caching for airing schedule previews")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to start episode background caching: {e}")
|
||||||
|
|
||||||
|
# Use the generic loader script
|
||||||
|
preview_script = TEMPLATE_PREVIEW_SCRIPT
|
||||||
|
|
||||||
|
replacements = {
|
||||||
|
"PREVIEW_MODE": config.general.preview,
|
||||||
|
"IMAGE_CACHE_DIR": str(IMAGES_CACHE_DIR),
|
||||||
|
"INFO_CACHE_DIR": str(INFO_CACHE_DIR),
|
||||||
|
"IMAGE_RENDERER": config.general.image_renderer,
|
||||||
|
# Color codes
|
||||||
|
"HEADER_COLOR": ",".join(HEADER_COLOR),
|
||||||
|
"SEPARATOR_COLOR": ",".join(SEPARATOR_COLOR),
|
||||||
|
"PREFIX": "airing-schedule",
|
||||||
|
"KEY": "",
|
||||||
|
"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
|
||||||
|
|
||||||
|
|
||||||
def get_dynamic_anime_preview(config: AppConfig) -> str:
|
def get_dynamic_anime_preview(config: AppConfig) -> str:
|
||||||
"""
|
"""
|
||||||
Generate dynamic anime preview script for search functionality.
|
Generate dynamic anime preview script for search functionality.
|
||||||
@@ -539,40 +581,3 @@ def get_preview_worker_status() -> dict:
|
|||||||
if _preview_manager:
|
if _preview_manager:
|
||||||
return _preview_manager.get_status()
|
return _preview_manager.get_status()
|
||||||
return {"preview_worker": None, "episode_worker": None}
|
return {"preview_worker": None, "episode_worker": None}
|
||||||
|
|
||||||
|
|
||||||
def get_airing_schedule_preview(
|
|
||||||
schedule_result: AiringScheduleResult, config: AppConfig, anime_title: str = "Anime"
|
|
||||||
) -> str:
|
|
||||||
"""
|
|
||||||
Generate the generic loader script for airing schedule previews and start background caching.
|
|
||||||
"""
|
|
||||||
|
|
||||||
INFO_CACHE_DIR.mkdir(parents=True, exist_ok=True)
|
|
||||||
preview_manager = _get_preview_manager()
|
|
||||||
worker = preview_manager.get_airing_schedule_worker()
|
|
||||||
worker.cache_airing_schedule_preview(anime_title, schedule_result, config)
|
|
||||||
logger.debug("Started background caching for airing schedule previews")
|
|
||||||
|
|
||||||
# Use the generic loader script
|
|
||||||
preview_script = TEMPLATE_AIRING_SCHEDULE_PREVIEW_SCRIPT
|
|
||||||
path_sep = "\\" if PLATFORM == "win32" else "/"
|
|
||||||
|
|
||||||
# Inject the correct cache path and color codes
|
|
||||||
replacements = {
|
|
||||||
"PREVIEW_MODE": config.general.preview,
|
|
||||||
"INFO_CACHE_DIR": str(INFO_CACHE_DIR),
|
|
||||||
"PATH_SEP": path_sep,
|
|
||||||
"C_TITLE": ansi.get_true_fg(config.fzf.header_color.split(","), bold=True),
|
|
||||||
"C_KEY": ansi.get_true_fg(config.fzf.header_color.split(","), bold=True),
|
|
||||||
"C_VALUE": ansi.get_true_fg(config.fzf.header_color.split(","), bold=True),
|
|
||||||
"C_RULE": ansi.get_true_fg(
|
|
||||||
config.fzf.preview_separator_color.split(","), bold=True
|
|
||||||
),
|
|
||||||
"RESET": ansi.RESET,
|
|
||||||
}
|
|
||||||
|
|
||||||
for key, value in replacements.items():
|
|
||||||
preview_script = preview_script.replace(f"{{{key}}}", value)
|
|
||||||
|
|
||||||
return preview_script
|
|
||||||
|
|||||||
@@ -745,7 +745,7 @@ class AiringScheduleCacheWorker(ManagedBackgroundWorker):
|
|||||||
def _get_cache_hash(self, text: str) -> str:
|
def _get_cache_hash(self, text: str) -> str:
|
||||||
from hashlib import sha256
|
from hashlib import sha256
|
||||||
|
|
||||||
return sha256(text.encode("utf-8")).hexdigest()
|
return "airing-schedule-" + sha256(text.encode("utf-8")).hexdigest() + ".py"
|
||||||
|
|
||||||
def _on_task_completed(self, task: WorkerTask, future) -> None:
|
def _on_task_completed(self, task: WorkerTask, future) -> None:
|
||||||
super()._on_task_completed(task, future)
|
super()._on_task_completed(task, future)
|
||||||
|
|||||||
Reference in New Issue
Block a user