87 lines
2.8 KiB
Python
87 lines
2.8 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 config.get("source_url"):
|
|
url = config["source_url"]
|
|
else:
|
|
slug = self.slugify(show_title)
|
|
# Ten URL structure: /v/show-name/season-YYYY or /v/show-name/season-X
|
|
url = f"https://10play.com.au/{slug}/episodes/season-{source_season}"
|
|
|
|
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(".")
|
|
|
|
return {
|
|
"show": show_clean,
|
|
"episode_id": episode_id,
|
|
"filename": filename
|
|
}
|
|
|
|
def download_episode(self, episode, entry, download_dir):
|
|
# You can reuse the logic from your iViewService here
|
|
# Just ensure --netrc is included in the final subprocess call
|
|
pass
|