165 lines
6.0 KiB
Python
165 lines
6.0 KiB
Python
"""
|
|
Setup wizard for Social Media Collection Downloader.
|
|
Run this first to configure your collections, cookies, and options.
|
|
"""
|
|
|
|
import json
|
|
import sys
|
|
import os
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
CONFIG_DIR = Path(__file__).parent / "config"
|
|
CONFIG_PATH = CONFIG_DIR / "config.json"
|
|
CONFIG_DIR.mkdir(exist_ok=True)
|
|
|
|
|
|
def check_dependency(cmd: str, name: str, install_hint: str) -> bool:
|
|
try:
|
|
subprocess.run([cmd, "--version"], capture_output=True, check=True)
|
|
print(f" ✓ {name} found")
|
|
return True
|
|
except (FileNotFoundError, subprocess.CalledProcessError):
|
|
print(f" ✗ {name} not found — {install_hint}")
|
|
return False
|
|
|
|
|
|
def check_dependencies():
|
|
print("\n── Checking dependencies ──────────────────────────────────")
|
|
ok = True
|
|
ok &= check_dependency("yt-dlp", "yt-dlp", "pip install yt-dlp")
|
|
try:
|
|
from playwright.sync_api import sync_playwright
|
|
print(" ✓ Playwright found")
|
|
except ImportError:
|
|
print(" ✗ Playwright not found — pip install playwright && playwright install chromium")
|
|
ok = False
|
|
return ok
|
|
|
|
|
|
def prompt(question: str, default: str = "") -> str:
|
|
if default:
|
|
val = input(f" {question} [{default}]: ").strip()
|
|
return val if val else default
|
|
else:
|
|
return input(f" {question}: ").strip()
|
|
|
|
|
|
def prompt_bool(question: str, default: bool = True) -> bool:
|
|
d = "Y/n" if default else "y/N"
|
|
val = input(f" {question} [{d}]: ").strip().lower()
|
|
if not val:
|
|
return default
|
|
return val in ("y", "yes", "1", "true")
|
|
|
|
|
|
def setup_platform(platform: str) -> dict:
|
|
print(f"\n── {platform} Setup ─────────────────────────────────────────")
|
|
cfg: dict = {}
|
|
|
|
enabled = prompt_bool(f"Enable {platform}?", True)
|
|
cfg["enabled"] = enabled
|
|
if not enabled:
|
|
return cfg
|
|
|
|
print(f"""
|
|
How to get your cookies:
|
|
1. Install "Get cookies.txt LOCALLY" browser extension
|
|
2. Log into {platform.lower()}.com
|
|
3. Click the extension and export cookies as JSON (or Netscape .txt)
|
|
4. Save the file anywhere and enter the path below
|
|
|
|
OR: let yt-dlp read cookies directly from your browser (Chrome/Firefox)
|
|
(your browser must be closed or the profile must be accessible)
|
|
""")
|
|
|
|
method = prompt("Cookie method — (1) cookies file (2) browser auto-read", "1")
|
|
|
|
if method == "2":
|
|
browser = prompt("Browser name (chrome / firefox / edge / safari)", "chrome")
|
|
cfg["cookies_from_browser"] = browser
|
|
cfg["cookies_file"] = None
|
|
else:
|
|
cookies_path = prompt("Path to cookies file (JSON or Netscape txt)", "")
|
|
cfg["cookies_file"] = cookies_path if cookies_path else None
|
|
cfg["cookies_from_browser"] = None
|
|
|
|
print(f"\n Enter your {platform} collection/saved URLs.")
|
|
print(" TikTok: Go to your profile → Collections → open a collection → copy URL")
|
|
print(" Instagram: Go to profile → Saved → open a collection → copy URL")
|
|
print(" (Enter one per line, blank line when done)\n")
|
|
|
|
collections = []
|
|
while True:
|
|
url = input(" Collection URL (or press Enter to finish): ").strip()
|
|
if not url:
|
|
break
|
|
if url.startswith("http"):
|
|
collections.append(url)
|
|
print(f" Added: {url}")
|
|
else:
|
|
print(" ⚠ That doesn't look like a URL, skipping.")
|
|
|
|
cfg["collections"] = collections
|
|
|
|
cfg["unsave_after_download"] = prompt_bool("Unsave/remove posts after downloading?", True)
|
|
cfg["headless"] = prompt_bool("Run browser in headless mode (invisible) for unsaving?", False)
|
|
|
|
delay_dl = prompt("Seconds to wait between downloads (avoid rate limits)", "2")
|
|
cfg["delay_between_downloads"] = int(delay_dl) if delay_dl.isdigit() else 2
|
|
|
|
delay_un = prompt("Seconds to wait between unsaves", "3")
|
|
cfg["delay_between_unsaves"] = int(delay_un) if delay_un.isdigit() else 3
|
|
|
|
return cfg
|
|
|
|
|
|
def save_config(config: dict):
|
|
with open(CONFIG_PATH, "w") as f:
|
|
json.dump(config, f, indent=2)
|
|
print(f"\n ✓ Config saved to {CONFIG_PATH}")
|
|
|
|
|
|
def print_banner():
|
|
print("""
|
|
╔══════════════════════════════════════════════════════════╗
|
|
║ Social Media Collection Downloader — Setup ║
|
|
║ TikTok & Instagram → Download → Auto-unsave ║
|
|
╚══════════════════════════════════════════════════════════╝
|
|
""")
|
|
|
|
|
|
def main():
|
|
print_banner()
|
|
deps_ok = check_dependencies()
|
|
if not deps_ok:
|
|
print("\n Please install missing dependencies first, then re-run setup.py")
|
|
print("\n Quick install:")
|
|
print(" pip install yt-dlp playwright")
|
|
print(" playwright install chromium\n")
|
|
sys.exit(1)
|
|
|
|
config = {}
|
|
config["tiktok"] = setup_platform("TikTok")
|
|
config["instagram"] = setup_platform("Instagram")
|
|
|
|
print("\n── Summary ─────────────────────────────────────────────────")
|
|
for platform in ["tiktok", "instagram"]:
|
|
p = config[platform]
|
|
status = "✓ Enabled" if p.get("enabled") else "✗ Disabled"
|
|
n = len(p.get("collections", []))
|
|
print(f" {platform.capitalize()}: {status} | {n} collection(s)")
|
|
|
|
if prompt_bool("\n Save this config and run now?", True):
|
|
save_config(config)
|
|
print("\n Running downloader...\n")
|
|
subprocess.run([sys.executable, str(Path(__file__).parent / "downloader.py")])
|
|
else:
|
|
save_config(config)
|
|
print("\n Config saved. Run later with:")
|
|
print(" python downloader.py\n")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|