Files
tvgrabber/services/ten.py
T
2026-05-15 00:00:57 +09:30

90 lines
2.9 KiB
Python

import subprocess
import json
from pathlib import Path
from services.base import BaseService
class TenService(BaseService):
def name(self):
return "Ten"
def slugify(self, text):
# Ten slugs are usually just lowercase with hyphens
import re
text = text.lower().replace("&", "and")
text = re.sub(r"[^a-z0-t0-9\s]", "", text)
return re.sub(r"\s+", "-", text).strip("-")
def run_ytdlp_json(self, url):
result = subprocess.run([
"yt-dlp",
"-J",
"--netrc", # Using .netrc for headless auth
"--no-flat-playlist",
url
], capture_output=True, text=True)
try:
return json.loads(result.stdout)
except:
return None
def discover_seasons(self, show_title, source_season=None, source_url=None):
# 1. Enforce source_season requirement for Ten
if not source_season:
print(f"❌ Error: Ten requires 'source_season' in series.json for '{show_title}'")
return None
if source_url:
url = source_url
else:
slug = self.slugify(show_title)
# Ten URL structure: /v/show-name/episodes/YYYY or /v/show-name/episodes/season-X
s_str = str(source_season)
if len(s_str) == 4:
season_path = s_str
else:
season_path = f"season-{s_str}"
url = f"https://10play.com.au/{slug}/episodes/{season_path}"
print(f"🔎 Querying Ten: {url}")
data = self.run_ytdlp_json(url)
if not data or "entries" not in data:
print(f"⚠️ Could not find episodes for {show_title} Season {source_season}")
return None
return [{
"season": source_season,
"data": data
}]
def normalize_episode(self, output_title, entry, season_num=None):
# Ten uses 'episode_number' in its JSON
episode_idx = entry.get("episode_number") or 0
episode_id = entry.get("id")
# Clean title (Ten often includes show name in the episode title)
raw_title = entry.get("title") or ""
clean_title = raw_title.replace(output_title, "").strip(": ").strip()
# Use the provided season_num (which we resolved in autograbber.py)
# Convert to int to handle potential string inputs from JSON for formatting
try:
s_val = int(season_num)
except (ValueError, TypeError):
s_val = 1
show_clean = output_title.replace(" ", ".")
title_clean = clean_title.replace(" ", ".")
# filename = f"{show_clean}.S{s_val:02d}E{episode_idx:02d}.{title_clean}".strip(".") # With episode title
filename = f"{show_clean}.S{s_val:02d}E{episode_idx:02d}".strip(".") # Without episode title
return {
"show": show_clean,
"episode_id": episode_id,
"filename": filename
}