230 lines
6.2 KiB
Python
Executable File
230 lines
6.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Create a new movie post from an IMDB ID.
|
|
|
|
Usage:
|
|
python scripts/new_movie.py tt1234567
|
|
python scripts/new_movie.py tt1234567 --title "Custom Title"
|
|
python scripts/new_movie.py https://www.imdb.com/title/tt1234567/
|
|
|
|
This fetches all metadata (title, year, runtime, director, poster) and creates
|
|
a ready-to-edit draft post.
|
|
"""
|
|
|
|
import argparse
|
|
import re
|
|
import subprocess
|
|
import sys
|
|
from datetime import datetime, timezone
|
|
from pathlib import Path
|
|
|
|
import requests
|
|
|
|
# Configuration
|
|
TMDB_API_KEY = "9e36fdcf70a4918e0dce327acc437dff"
|
|
|
|
# Paths
|
|
SCRIPT_DIR = Path(__file__).parent
|
|
PROJECT_ROOT = SCRIPT_DIR.parent
|
|
CONTENT_DIR = PROJECT_ROOT / "content" / "posts"
|
|
IMAGES_DIR = PROJECT_ROOT / "static" / "images" / "posters"
|
|
|
|
|
|
def extract_imdb_id(input_str):
|
|
"""Extract IMDB ID from URL or raw ID."""
|
|
match = re.search(r'(tt\d+)', input_str)
|
|
if match:
|
|
return match.group(1)
|
|
return None
|
|
|
|
|
|
def find_movie_by_imdb(imdb_id):
|
|
"""Find TMDB movie by IMDB ID."""
|
|
url = f"https://api.themoviedb.org/3/find/{imdb_id}"
|
|
params = {
|
|
"api_key": TMDB_API_KEY,
|
|
"external_source": "imdb_id"
|
|
}
|
|
resp = requests.get(url, params=params, timeout=10)
|
|
resp.raise_for_status()
|
|
data = resp.json()
|
|
|
|
results = data.get("movie_results", [])
|
|
if results:
|
|
return results[0]
|
|
return None
|
|
|
|
|
|
def get_movie_details(tmdb_id):
|
|
"""Get full movie details from TMDB."""
|
|
url = f"https://api.themoviedb.org/3/movie/{tmdb_id}"
|
|
params = {
|
|
"api_key": TMDB_API_KEY,
|
|
"append_to_response": "credits"
|
|
}
|
|
resp = requests.get(url, params=params, timeout=10)
|
|
resp.raise_for_status()
|
|
return resp.json()
|
|
|
|
|
|
def get_directors(credits):
|
|
"""Extract director names from credits."""
|
|
crew = credits.get("crew", [])
|
|
directors = [p["name"] for p in crew if p.get("job") == "Director"]
|
|
return directors
|
|
|
|
|
|
def slugify(title):
|
|
"""Convert title to URL-friendly slug."""
|
|
slug = title.lower()
|
|
slug = re.sub(r"[^a-z0-9\s-]", "", slug)
|
|
slug = re.sub(r"[\s_]+", "-", slug)
|
|
slug = re.sub(r"-+", "-", slug)
|
|
return slug.strip("-")
|
|
|
|
|
|
def download_poster(poster_path, filename):
|
|
"""Download and save poster. Returns local path."""
|
|
if not poster_path:
|
|
return ""
|
|
|
|
# w500 = 500px wide, good for 200px display on retina
|
|
url = f"https://image.tmdb.org/t/p/w500{poster_path}"
|
|
resp = requests.get(url, timeout=10)
|
|
resp.raise_for_status()
|
|
|
|
IMAGES_DIR.mkdir(parents=True, exist_ok=True)
|
|
filepath = IMAGES_DIR / filename
|
|
filepath.write_bytes(resp.content)
|
|
|
|
return f"/images/posters/{filename}"
|
|
|
|
|
|
def create_post(imdb_id, details, poster_path, custom_title=None):
|
|
"""Create the Hugo post with all metadata."""
|
|
title = custom_title or details.get("title", "Untitled")
|
|
slug = slugify(title)
|
|
filename = f"{slug}.md"
|
|
filepath = CONTENT_DIR / filename
|
|
|
|
if filepath.exists():
|
|
print(f"Post already exists: {filepath}")
|
|
return None
|
|
|
|
# Download poster
|
|
poster_url = ""
|
|
if details.get("poster_path"):
|
|
poster_filename = f"{slug}.jpg"
|
|
print(f"Downloading poster...")
|
|
poster_url = download_poster(details["poster_path"], poster_filename)
|
|
|
|
# Extract metadata
|
|
release_date = details.get("release_date", "")
|
|
year = int(release_date.split("-")[0]) if release_date else ""
|
|
runtime = details.get("runtime", "")
|
|
|
|
credits = details.get("credits", {})
|
|
directors = get_directors(credits)
|
|
director_str = directors[0] if len(directors) == 1 else directors if directors else ""
|
|
|
|
genres = [g["name"] for g in details.get("genres", [])]
|
|
|
|
now = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
|
|
# Build frontmatter
|
|
# Using manual formatting to control output
|
|
genres_yaml = "\n".join(f" - {g}" for g in genres) if genres else "[]"
|
|
if isinstance(director_str, list):
|
|
director_yaml = "\n".join(f" - {d}" for d in director_str)
|
|
director_yaml = f"\n{director_yaml}"
|
|
else:
|
|
director_yaml = f' "{director_str}"' if director_str else ' ""'
|
|
|
|
content = f'''---
|
|
title: '{title}'
|
|
date: {now}
|
|
draft: true
|
|
series: "Frank's Couch"
|
|
summary: ""
|
|
imdb: "{imdb_id}"
|
|
poster: "{poster_url}"
|
|
year: {year}
|
|
runtime: {runtime}
|
|
director:{director_yaml}
|
|
genres:
|
|
{genres_yaml}
|
|
tags:
|
|
- gucci
|
|
- ghost theater
|
|
- marcel
|
|
- amc-south
|
|
- amc-lakeline
|
|
- anticipated
|
|
- no-expectations
|
|
- had pizza
|
|
---
|
|
{{{{< imdbposter >}}}}
|
|
|
|
| Date watched | |
|
|
|---------------------|-------------------|
|
|
| Show Time | |
|
|
| Theater | |
|
|
| Theater Number | |
|
|
| Pizza | |
|
|
| Tickets | |
|
|
| Letterboxd Rating | |
|
|
| Crew | |
|
|
|
|
{{{{< /imdbposter >}}}}
|
|
|
|
Write your review here...
|
|
|
|
'''
|
|
|
|
filepath.write_text(content)
|
|
return filepath
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description="Create a new movie post from IMDB ID",
|
|
epilog="Example: python scripts/new_movie.py tt1234567"
|
|
)
|
|
parser.add_argument("imdb", help="IMDB ID or URL (e.g., tt1234567)")
|
|
parser.add_argument("--title", help="Custom title (default: from TMDB)")
|
|
args = parser.parse_args()
|
|
|
|
# Extract IMDB ID
|
|
imdb_id = extract_imdb_id(args.imdb)
|
|
if not imdb_id:
|
|
print(f"Invalid IMDB ID: {args.imdb}")
|
|
print("Expected format: tt1234567 or https://www.imdb.com/title/tt1234567/")
|
|
sys.exit(1)
|
|
|
|
print(f"Looking up {imdb_id}...")
|
|
|
|
# Find on TMDB
|
|
movie = find_movie_by_imdb(imdb_id)
|
|
if not movie:
|
|
print(f"Movie not found for IMDB ID: {imdb_id}")
|
|
sys.exit(1)
|
|
|
|
tmdb_id = movie["id"]
|
|
print(f"Found: {movie.get('title')} ({movie.get('release_date', '')[:4]})")
|
|
|
|
# Get full details
|
|
print("Fetching details...")
|
|
details = get_movie_details(tmdb_id)
|
|
|
|
# Create post
|
|
filepath = create_post(imdb_id, details, details.get("poster_path"), args.title)
|
|
|
|
if filepath:
|
|
print(f"\nCreated: {filepath.relative_to(PROJECT_ROOT)}")
|
|
print(f"IMDB: https://www.imdb.com/title/{imdb_id}/")
|
|
print(f"\nEdit your post, then run: ./scripts/build.sh")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|