Add content CLI
This commit is contained in:
1 parent
3da32a4a90
commit
661ee019e5
10 files changed
+387
No files matched your search
@@ -0,0 +1,115 @@
|
||||
import imdb
|
||||
import jsonfile
|
||||
|
||||
ABOUT_FILE = "about.json"
|
||||
MEDIA_KINDS = {
|
||||
"show": {"key": "shows", "label": "TV show", "omdb_type": "series"},
|
||||
"movie": {"key": "movies", "label": "movie", "omdb_type": "movie"}
|
||||
}
|
||||
|
||||
|
||||
def load_items(kind: str) -> tuple[dict, list[dict]]:
|
||||
data = jsonfile.load(ABOUT_FILE)
|
||||
return data, data.setdefault(MEDIA_KINDS[kind]["key"], [])
|
||||
|
||||
|
||||
def find_index(items: list[dict], text: str) -> int | None:
|
||||
identifier = imdb.imdb_id(text)
|
||||
for index, item in enumerate(items):
|
||||
if identifier and imdb.imdb_id(item.get("url", "")) == identifier:
|
||||
return index
|
||||
if item.get("name", "").lower() == text.lower():
|
||||
return index
|
||||
return None
|
||||
|
||||
|
||||
def valid_rating(value: str) -> int:
|
||||
rating = int(value)
|
||||
if not 0 <= rating <= 10:
|
||||
raise ValueError("Rating must be between 0 and 10")
|
||||
return rating
|
||||
|
||||
|
||||
def list_items(arguments) -> None:
|
||||
_, items = load_items(arguments.kind)
|
||||
if not items:
|
||||
print(f"No {MEDIA_KINDS[arguments.kind]['label']}s yet.")
|
||||
return
|
||||
for item in sorted(items, key=lambda entry: -entry.get("rating", 0)):
|
||||
print(f"{item.get('rating', '?'):>3}/10 {item.get('name')} {item.get('url')}")
|
||||
|
||||
|
||||
def resolve_name(arguments, identifier: str) -> str | None:
|
||||
if arguments.name:
|
||||
return arguments.name
|
||||
details = imdb.lookup(identifier)
|
||||
if not details:
|
||||
print("Could not look up the title. Pass --name, or set OMDB_API_KEY in .env.")
|
||||
return None
|
||||
expected_type = MEDIA_KINDS[arguments.kind]["omdb_type"]
|
||||
if details.get("Type") != expected_type:
|
||||
print(f"Warning: OMDb lists {details.get('Title')} as a {details.get('Type')}, not a {expected_type}.")
|
||||
return details.get("Title")
|
||||
|
||||
|
||||
def add_item(arguments) -> None:
|
||||
identifier = imdb.imdb_id(arguments.title)
|
||||
if not identifier:
|
||||
print(f"{arguments.title} is not an IMDb link or ID.")
|
||||
return
|
||||
data, items = load_items(arguments.kind)
|
||||
if find_index(items, identifier) is not None:
|
||||
print(f"{identifier} is already listed. Use rate to change its rating.")
|
||||
return
|
||||
name = resolve_name(arguments, identifier)
|
||||
if not name:
|
||||
return
|
||||
items.append({"name": name, "rating": arguments.rating, "url": imdb.title_url(identifier)})
|
||||
jsonfile.save(ABOUT_FILE, data)
|
||||
print(f"Added {name} ({arguments.rating}/10)")
|
||||
|
||||
|
||||
def remove_item(arguments) -> None:
|
||||
data, items = load_items(arguments.kind)
|
||||
index = find_index(items, arguments.title)
|
||||
if index is None:
|
||||
print(f"{arguments.title} is not listed.")
|
||||
return
|
||||
removed = items.pop(index)
|
||||
jsonfile.save(ABOUT_FILE, data)
|
||||
print(f"Removed {removed.get('name')}")
|
||||
|
||||
|
||||
def rate_item(arguments) -> None:
|
||||
data, items = load_items(arguments.kind)
|
||||
index = find_index(items, arguments.title)
|
||||
if index is None:
|
||||
print(f"{arguments.title} is not listed.")
|
||||
return
|
||||
items[index]["rating"] = arguments.rating
|
||||
jsonfile.save(ABOUT_FILE, data)
|
||||
print(f"Rated {items[index].get('name')} {arguments.rating}/10")
|
||||
|
||||
|
||||
def register(subparsers) -> None:
|
||||
for kind, settings in MEDIA_KINDS.items():
|
||||
parser = subparsers.add_parser(kind, help=f"Manage the {settings['label']}s on the about page")
|
||||
parser.set_defaults(kind=kind)
|
||||
actions = parser.add_subparsers(dest="action", required=True)
|
||||
|
||||
actions.add_parser("list", help=f"List {settings['label']}s").set_defaults(handler=list_items)
|
||||
|
||||
add_parser = actions.add_parser("add", help=f"Add a {settings['label']} by IMDb link or ID")
|
||||
add_parser.add_argument("title", help="IMDb link or ID, like tt0816692")
|
||||
add_parser.add_argument("--rating", type=valid_rating, required=True, help="Your rating from 0 to 10")
|
||||
add_parser.add_argument("--name", help="Display name, looked up on OMDb when left out")
|
||||
add_parser.set_defaults(handler=add_item)
|
||||
|
||||
remove_parser = actions.add_parser("remove", help=f"Remove a {settings['label']}")
|
||||
remove_parser.add_argument("title", help="IMDb link, ID or name")
|
||||
remove_parser.set_defaults(handler=remove_item)
|
||||
|
||||
rate_parser = actions.add_parser("rate", help=f"Change a {settings['label']}'s rating")
|
||||
rate_parser.add_argument("title", help="IMDb link, ID or name")
|
||||
rate_parser.add_argument("rating", type=valid_rating, help="New rating from 0 to 10")
|
||||
rate_parser.set_defaults(handler=rate_item)
|
||||
Reference in new issue
Block a user