Fix broken --download switch

This commit is contained in:
2026-05-14 21:24:46 +09:30
parent 6e938857d4
commit ac103339b2
+56 -202
View File
@@ -1,23 +1,10 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import argparse import argparse
import sys import sys
from pathlib import Path from pathlib import Path
from services.iview import iViewService from services.iview import iViewService
# -------------------------
# Metadata paths
# -------------------------
DOWNLOAD_META = Path("./.config")
HISTORY_FILE = DOWNLOAD_META / "history"
SERIES_FILE = DOWNLOAD_META / "series"
# ------------------------- # -------------------------
# Service registry # Service registry
# ------------------------- # -------------------------
@@ -25,284 +12,151 @@ SERVICES = {
"IVIEW": iViewService(), "IVIEW": iViewService(),
} }
# -------------------------
# Core Autograbber
# -------------------------
class AutoGrabber: class AutoGrabber:
def __init__(self, download_dir, config_dir, dry_run=False, mark_existing=False):
def __init__( # The main media output directory (Required)
self,
download_dir,
dry_run=False,
mark_existing=False
):
self.download_dir = Path(download_dir) self.download_dir = Path(download_dir)
# The config directory (Defaults to PWD/.tvgrabber or CLI override)
self.config_dir = Path(config_dir)
self.history_file = self.config_dir / "history"
self.series_file = self.config_dir / "series"
self.dry_run = dry_run self.dry_run = dry_run
self.mark_existing = mark_existing self.mark_existing = mark_existing
# Initialize
self.history = self.load_history() self.history = self.load_history()
self.series_list = self.load_series() self.series_list = self.load_series()
# -------------------------
# History handling
# -------------------------
def load_history(self): def load_history(self):
history = {} history = {}
# Ensure .tvgrabber exists before we try to handle the history file
if not self.config_dir.exists():
self.config_dir.mkdir(parents=True, exist_ok=True)
if not HISTORY_FILE.exists(): if not self.history_file.exists():
HISTORY_FILE.touch() self.history_file.touch()
with open(HISTORY_FILE, "r") as f:
with open(self.history_file, "r") as f:
for line in f: for line in f:
line = line.strip() line = line.strip()
if not line or "|" not in line:
if not line: if line: history[line] = None
continue continue
if "|" in line:
ep_id, filename = line.split("|", 1) ep_id, filename = line.split("|", 1)
history[ep_id.strip()] = filename.strip() history[ep_id.strip()] = filename.strip()
else:
history[line.strip()] = None
return history return history
def save_history(self): def save_history(self):
with open(self.history_file, "w") as f:
with open(HISTORY_FILE, "w") as f:
for ep_id in sorted(self.history.keys()): for ep_id in sorted(self.history.keys()):
filename = self.history[ep_id] filename = self.history[ep_id]
f.write(f"{ep_id} | {filename}\n" if filename else f"{ep_id}\n")
if filename:
f.write(f"{ep_id} | {filename}\n")
else:
f.write(f"{ep_id}\n")
# -------------------------
# Series loading
# -------------------------
def load_series(self): def load_series(self):
if not self.series_file.exists():
if not SERIES_FILE.exists(): print(f"❌ Error: Series file not found at {self.series_file}")
print(f"Please ensure your series list is in {self.config_dir}/series")
print(
"❌ Missing required file: "
f"{SERIES_FILE}"
)
sys.exit(1) sys.exit(1)
series = [] series = []
with open(self.series_file, "r") as f:
with open(SERIES_FILE, "r") as f:
for line in f: for line in f:
line = line.strip() line = line.strip()
if not line or "/" not in line: continue
if not line:
continue
if "/" not in line:
continue
service_name, remainder = line.split("/", 1) service_name, remainder = line.split("/", 1)
if "|" in remainder: if "|" in remainder:
source_title, output_title = remainder.split("|", 1) source_title, output_title = remainder.split("|", 1)
else: else:
source_title = remainder source_title = output_title = remainder
output_title = remainder
series.append((
service_name.strip(),
source_title.strip(),
output_title.strip()
))
series.append((service_name.strip(), source_title.strip(), output_title.strip()))
return series return series
# ------------------------- def process_show(self, service_name, source_title, output_title):
# Process a single show
# -------------------------
def process_show(
self,
service_name,
source_title,
output_title
):
service = SERVICES.get(service_name.upper()) service = SERVICES.get(service_name.upper())
if not service: if not service:
print(f"❌ Unknown service: {service_name}") print(f"❌ Unknown service: {service_name}")
return return
print("\n==============================") print(f"\n📺 Show: {output_title} ({service_name})")
print(f"📺 Show: {output_title}")
print(f"📡 Service: {service_name}")
print("==============================")
seasons = service.discover_seasons(source_title) seasons = service.discover_seasons(source_title)
if not seasons: if not seasons:
print("⚠️ No seasons found") print("⚠️ No seasons found")
return return
for season_data in seasons: for season_data in seasons:
season_num = season_data["season"] season_num = season_data["season"]
data = season_data["data"] print(f"📦 Season {season_num}")
print(f"\n📦 Processing Season {season_num}")
for entry in data["entries"]:
episode = service.normalize_episode(
output_title,
entry
)
for entry in season_data["data"]["entries"]:
episode = service.normalize_episode(output_title, entry)
ep_id = episode["episode_id"] ep_id = episode["episode_id"]
if not ep_id:
continue
filename = episode["filename"] filename = episode["filename"]
# already downloaded
if ep_id in self.history: if ep_id in self.history:
print(f"{filename} (Skipped)")
print(
f""
f"{self.history[ep_id]} "
f"(already downloaded)"
)
continue continue
# dry-run mode
if self.dry_run: if self.dry_run:
print(f" 🧪 {filename} (Dry Run)")
print(
f"🧪 "
f"{filename} "
f"(would download)"
)
continue continue
# mark-existing mode
if self.mark_existing: if self.mark_existing:
print(f" 📝 {filename} (Marked)")
print(
f"📝 "
f"{filename} "
f"(added to history)"
)
self.history[ep_id] = filename self.history[ep_id] = filename
self.save_history() self.save_history()
continue continue
print(f"{filename} (Downloading...)")
# normal download mode if service.download_episode(episode, entry, self.download_dir):
print(f"{filename} → downloading")
success = service.download_episode(
episode,
entry,
self.download_dir
)
if success:
self.history[ep_id] = filename self.history[ep_id] = filename
self.save_history() self.save_history()
# -------------------------
# Main execution
# -------------------------
def run(self): def run(self):
for service, source, output in self.series_list:
if not self.series_list: self.process_show(service, source, output)
print("\n✅ Done.")
print("⚠️ No shows found in .series")
return
for (
service_name,
source_title,
output_title
) in self.series_list:
self.process_show(
service_name,
source_title,
output_title
)
print("\n✅ Autograbber run complete")
# ------------------------- # -------------------------
# CLI # CLI
# ------------------------- # -------------------------
def parse_args(): def parse_args():
parser = argparse.ArgumentParser(description="Australian FTA TV AutoGrabber")
parser = argparse.ArgumentParser() # Required positional argument for the download directory
parser.add_argument( parser.add_argument(
"--dry-run", "download_dir",
action="store_true", help="REQUIRED: Path to the directory where media will be saved"
help="Do not download anything"
) )
# Optional config directory override
parser.add_argument( parser.add_argument(
"-d", "--downloads", "-c", "--config",
dest="downloads", default="~/.tvgrabber",
default="./downloads", help="Path to the config folder containing 'series' and 'history' (default: ~/.tvgrabber)"
help="Directory where videos will be saved."
) )
parser.add_argument( parser.add_argument("--dry-run", action="store_true")
"--mark-existing", parser.add_argument("--mark-existing", action="store_true")
action="store_true",
help="Add all available episodes to history without downloading"
)
return parser.parse_args() return parser.parse_args()
# -------------------------
# Entry point
# -------------------------
if __name__ == "__main__": if __name__ == "__main__":
args = parse_args() args = parse_args()
# Convert to Path object and ensure it exists # Ensure the download directory exists
download_path = Path(args.downloads).resolve() out_path = Path(args.download_dir).resolve()
if not out_path.exists() and not args.dry_run:
if not args.dry_run and not download_path.exists(): out_path.mkdir(parents=True, exist_ok=True)
print(f"📂 Creating download directory: {download_path}")
download_path.mkdir(parents=True, exist_ok=True)
AutoGrabber( AutoGrabber(
download_dir=download_path, download_dir=out_path,
config_dir=Path(args.config).resolve(),
dry_run=args.dry_run, dry_run=args.dry_run,
mark_existing=args.mark_existing mark_existing=args.mark_existing
).run() ).run()