Add watchlist episode offset naming
This commit is contained in:
+31
-1
@@ -20,7 +20,7 @@ from uuid import uuid4
|
||||
PROJECT_ROOT = Path(__file__).resolve().parent
|
||||
ANI_CLI = os.environ.get("ANI_CLI_BIN") or shutil.which("ani-cli") or "ani-cli"
|
||||
APP_NAME = "ani-cli-web"
|
||||
VERSION = "0.44.1"
|
||||
VERSION = "0.45.0"
|
||||
ALLANIME_BASE = "allanime.day"
|
||||
ALLANIME_API = f"https://api.{ALLANIME_BASE}"
|
||||
ALLANIME_REFERER = "https://allmanga.to"
|
||||
@@ -709,6 +709,18 @@ def normalize_season(value):
|
||||
return str(number)
|
||||
|
||||
|
||||
def normalize_episode_offset(value):
|
||||
text = str(value or "").strip()
|
||||
if not text:
|
||||
return None
|
||||
if not re.match(r"^[0-9]+$", text):
|
||||
raise ValueError("Episode offset must be a positive number")
|
||||
number = int(text, 10)
|
||||
if number < 1:
|
||||
raise ValueError("Episode offset must be a positive number")
|
||||
return str(number)
|
||||
|
||||
|
||||
def normalize_media_type(value, default="tv"):
|
||||
media_type = str(value or default).strip().lower()
|
||||
return media_type if media_type in MEDIA_TYPE_CHOICES else default
|
||||
@@ -741,6 +753,21 @@ def episode_label(value):
|
||||
return re.sub(r"[^0-9A-Za-z.]+", "-", text).strip("-") or "00"
|
||||
|
||||
|
||||
def apply_episode_offset(value, offset):
|
||||
normalized_offset = normalize_episode_offset(offset)
|
||||
text = str(value or "").strip()
|
||||
if not normalized_offset or not text:
|
||||
return text
|
||||
match = re.match(r"^0*([0-9]+)(.*)$", text)
|
||||
if not match:
|
||||
return text
|
||||
number = int(match.group(1) or "0", 10)
|
||||
if number < 1:
|
||||
return text
|
||||
suffix = match.group(2) or ""
|
||||
return f"{int(normalized_offset, 10) + number - 1}{suffix}"
|
||||
|
||||
|
||||
def extract_episode_from_filename(path):
|
||||
match = re.search(r"\bEpisode\s+([0-9][0-9A-Za-z.\-]*)\s*$", path.stem)
|
||||
return match.group(1) if match else None
|
||||
@@ -763,6 +790,7 @@ def finalize_library_files(job):
|
||||
library_name = sanitize_path_component(job.get("anime_name") or job.get("title"))
|
||||
media_type = normalize_media_type(job.get("media_type"))
|
||||
season = season_label(job)
|
||||
episode_offset = normalize_episode_offset(job.get("episode_offset"))
|
||||
target_dir.mkdir(parents=True, exist_ok=True)
|
||||
files = sorted(
|
||||
[path for path in staging_dir.iterdir() if path.is_file()],
|
||||
@@ -781,6 +809,7 @@ def finalize_library_files(job):
|
||||
if ep is None:
|
||||
ep = str(fallback_episode)
|
||||
fallback_episode += 1
|
||||
ep = apply_episode_offset(ep, episode_offset)
|
||||
final_name = f"{library_name} - S{season}E{episode_label(ep)}{source.suffix}"
|
||||
destination = unique_destination(target_dir / final_name)
|
||||
shutil.move(str(source), str(destination))
|
||||
@@ -824,6 +853,7 @@ def build_job(payload, config):
|
||||
"anime_name": anime_name,
|
||||
"media_type": media_type,
|
||||
"season": normalize_season(payload.get("season")),
|
||||
"episode_offset": normalize_episode_offset(payload.get("episode_offset")),
|
||||
"query": query,
|
||||
"result_index": index,
|
||||
"mode": mode,
|
||||
|
||||
Reference in New Issue
Block a user