From 915518fdec7efd759c3516156f1f2a4452400056 Mon Sep 17 00:00:00 2001 From: meisnate12 Date: Mon, 29 Aug 2022 15:07:01 -0400 Subject: [PATCH] [8] add imdb_watchlist builder --- VERSION | 2 +- docs/index.md | 10 +++++--- docs/metadata/builders/imdb.md | 43 +++++++++++++++++++++++++++++---- docs/metadata/builders/smart.md | 2 +- docs/metadata/overlay.md | 4 +-- modules/builder.py | 5 +++- modules/imdb.py | 27 +++++++++++++++++++-- 7 files changed, 77 insertions(+), 16 deletions(-) diff --git a/VERSION b/VERSION index 1fc8b02b..ecfc8aaf 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.17.3-develop7 +1.17.3-develop8 diff --git a/docs/index.md b/docs/index.md index f29a7ae4..3b269ad8 100644 --- a/docs/index.md +++ b/docs/index.md @@ -6,10 +6,12 @@ [![Develop GitHub commits since latest stable release (by SemVer)](https://img.shields.io/github/commits-since/meisnate12/plex-meta-manager/latest/develop?label=Commits%20in%20Develop&style=plastic)](https://github.com/meisnate12/Plex-Meta-Manager/tree/develop) [![Nightly GitHub commits since latest stable release (by SemVer)](https://img.shields.io/github/commits-since/meisnate12/plex-meta-manager/latest/nightly?label=Commits%20in%20Nightly&style=plastic)](https://github.com/meisnate12/Plex-Meta-Manager/tree/nightly) -[![Discord](https://img.shields.io/discord/822460010649878528?label=Discord&style=plastic)](https://discord.gg/NfH6mGFuAB) -[![Docker Cloud Build Status](https://img.shields.io/docker/cloud/build/meisnate12/plex-meta-manager?style=plastic)](https://hub.docker.com/r/meisnate12/plex-meta-manager) -[![Wiki](https://img.shields.io/readthedocs/plex-meta-manager?style=plastic)](https://metamanager.wiki) -[![Sponsor or Donate](https://img.shields.io/badge/-Sponsor_or_Donate-blueviolet?style=plastic)](https://github.com/sponsors/meisnate12) +[![Discord](https://img.shields.io/discord/822460010649878528?color=%2300bc8c&label=Discord&style=plastic)](https://discord.gg/NfH6mGFuAB) +[![Reddit](https://img.shields.io/reddit/subreddit-subscribers/PlexMetaManager?color=%2300bc8c&label=r%2FPlexMetaManager&style=plastic)](https://www.reddit.com/r/PlexMetaManager/) +[![Docker Cloud Build Status](https://img.shields.io/docker/cloud/build/meisnate12/plex-meta-manager?color=%2300bc8c&style=plastic)](https://hub.docker.com/r/meisnate12/plex-meta-manager) +[![Wiki](https://img.shields.io/readthedocs/plex-meta-manager?color=%2300bc8c&style=plastic)](https://metamanager.wiki) +[![GitHub Sponsors](https://img.shields.io/github/sponsors/meisnate12?color=%238a2be2&style=plastic)](https://github.com/sponsors/meisnate12) +[![Sponsor or Donate](https://img.shields.io/badge/-Sponsor%2FDonate-blueviolet?style=plastic)](https://github.com/sponsors/meisnate12) Plex Meta Manager is an open source Python 3 project that has been designed to ease the creation and maintenance of metadata, collections, and playlists within a Plex Media Server. The script is designed to be run continuously and be able to update information based on sources outside your plex environment. Plex Meta Manager supports Movie/TV/Music libraries and Playlists. diff --git a/docs/metadata/builders/imdb.md b/docs/metadata/builders/imdb.md index ce377075..1e3ec1b3 100644 --- a/docs/metadata/builders/imdb.md +++ b/docs/metadata/builders/imdb.md @@ -2,11 +2,12 @@ You can find items using the features of [IMDb.com](https://www.imdb.com/) (IMDb). -| Attribute | Description | Works with Movies | Works with Shows | Works with Playlists and Custom Sort | -|:----------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------:|:----------------:|:------------------------------------:| -| [`imdb_id`](#imdb-id) | Gets the movie/show specified. | ✅ | ✅ | ❌ | -| [`imdb_chart`](#imdb-chart) | Gets every movie/show in an IMDb Chart like [IMDb Top 250 Movies](https://www.imdb.com/chart/top). | ✅ | ✅ | ✅ | -| [`imdb_list`](#imdb-list) | Gets every movie/show in an IMDb List, [IMDb Keyword Search](https://www.imdb.com/search/keyword/), or [IMDb Search](https://www.imdb.com/search/title/). | ✅ | ✅ | ✅ | +| Attribute | Description | Works with Movies | Works with Shows | Works with Playlists and Custom Sort | +|:------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------:|:----------------:|:------------------------------------:| +| [`imdb_id`](#imdb-id) | Gets the movie/show specified. | ✅ | ✅ | ❌ | +| [`imdb_chart`](#imdb-chart) | Gets every movie/show in an IMDb Chart like [IMDb Top 250 Movies](https://www.imdb.com/chart/top). | ✅ | ✅ | ✅ | +| [`imdb_list`](#imdb-list) | Gets every movie/show in an IMDb List, [IMDb Keyword Search](https://www.imdb.com/search/keyword/), or [IMDb Search](https://www.imdb.com/search/title/). | ✅ | ✅ | ✅ | +| [`imdb_watchlist`](#imdb-watchlist) | Gets every movie/show in an IMDb User's Watchlist. | ✅ | ✅ | ✅ | ## IMDb ID @@ -118,4 +119,36 @@ collections: url: https://www.imdb.com/search/title/?series=tt0096697&sort=user_rating,desc limit: 100 summary: The top 100 Simpsons episodes by IMDb user rating +``` + +## IMDb Watchlist + +Finds every item in an IMDb User's Watchlist. + +The expected input is an IMDb User ID (example: `ur12345678`). Multiple values are supported as a list or as a comma-separated string. + +The `sync_mode: sync` and `collection_order: custom` Details are recommended since the lists are continuously updated and in a specific order. + +```yaml +collections: + My Watch Watchlist: + imdb_warchlist: ur64054558 + collection_order: custom + sync_mode: sync +``` +```yaml +collections: + My Friends Watchlists: + imdb_warchlist: ur64054558, ur12345678 + collection_order: custom + sync_mode: sync +``` +```yaml +collections: + My Friends Watchlists: + imdb_warchlist: + - ur64054558 + - ur12345678 + collection_order: custom + sync_mode: sync ``` \ No newline at end of file diff --git a/docs/metadata/builders/smart.md b/docs/metadata/builders/smart.md index d28a7b0b..40e71ad2 100644 --- a/docs/metadata/builders/smart.md +++ b/docs/metadata/builders/smart.md @@ -27,7 +27,7 @@ To make a collection a Smart Label Collection, the `smart_label` attribute must sort_by: release.desc all: label: <> - unplayed: True + unplayed: true ``` This is extremely useful because smart collections don't follow normal show/hide rules and can eliminate the need to have [Plex Collectionless](plex.md#plex-collectionless) when used correctly. To fix the issue described in [Plex Collectionless](plex.md#plex-collectionless) you would make `Marvel Cinematic Universe` a Smart Label Collection and all other Marvel collection just normal collections, and they will show/hide all the movie properly. diff --git a/docs/metadata/overlay.md b/docs/metadata/overlay.md index d726f437..d325231c 100644 --- a/docs/metadata/overlay.md +++ b/docs/metadata/overlay.md @@ -244,8 +244,8 @@ These are some commonly-used examples of Special Text overlays: | `name: text(Season <> Episode <>)` | Season 1 Episode 1 | | `name: text(Season <>)` | Season 1 | | `name: text(Episode <>)` | Episode 1 | -| `name: text(Runtime: <>m)` | Runtime: 90m | -| `name: text(Runtime: <>h <>m)` | Runtime: 1h 30m | +| `name: "text(Runtime: <>m)"` | Runtime: 90m | +| `name: "text(Runtime: <>h <>m)"` | Runtime: 1h 30m | #### Text Addon Images diff --git a/modules/builder.py b/modules/builder.py index b9f88f7f..dd796d89 100644 --- a/modules/builder.py +++ b/modules/builder.py @@ -143,7 +143,7 @@ smart_url_invalid = ["filters", "run_again", "sync_mode", "show_filtered", "show custom_sort_builders = [ "plex_search", "plex_pilots", "tmdb_list", "tmdb_popular", "tmdb_now_playing", "tmdb_top_rated", "tmdb_trending_daily", "tmdb_trending_weekly", "tmdb_discover", "reciperr_list", "trakt_chart", "trakt_userlist", - "tvdb_list", "imdb_chart", "imdb_list", "stevenlu_popular", "anidb_popular", "tmdb_upcoming", "tmdb_airing_today", + "tvdb_list", "imdb_chart", "imdb_list", "imdb_watchlist", "stevenlu_popular", "anidb_popular", "tmdb_upcoming", "tmdb_airing_today", "tmdb_on_the_air", "trakt_list", "trakt_watchlist", "trakt_collection", "trakt_trending", "trakt_popular", "trakt_boxoffice", "trakt_collected_daily", "trakt_collected_weekly", "trakt_collected_monthly", "trakt_collected_yearly", "trakt_collected_all", "flixpatrol_url", "flixpatrol_demographics", "flixpatrol_popular", "flixpatrol_top", "trakt_recommendations", @@ -1144,6 +1144,9 @@ class CollectionBuilder: self.builders.append((method_name, value)) else: raise Failed(f"{self.Type} Error: chart: {value} is invalid options are {[i for i in imdb.charts]}") + elif method_name == "imdb_watchlist": + for imdb_user in self.config.IMDb.validate_imdb_watchlists(self.Type, method_data, self.language): + self.builders.append((method_name, imdb_user)) def _letterboxd(self, method_name, method_data): if method_name.startswith("letterboxd_list"): diff --git a/modules/imdb.py b/modules/imdb.py index 36dbf236..bcc282c5 100644 --- a/modules/imdb.py +++ b/modules/imdb.py @@ -1,11 +1,11 @@ -import csv, gzip, math, os, re, requests, shutil, time +import csv, gzip, json, math, os, re, requests, shutil, time from modules import util from modules.util import Failed from urllib.parse import urlparse, parse_qs logger = util.logger -builders = ["imdb_list", "imdb_id", "imdb_chart"] +builders = ["imdb_list", "imdb_id", "imdb_chart", "imdb_watchlist"] movie_charts = ["box_office", "popular_movies", "top_movies", "top_english", "top_indian", "lowest_rated"] show_charts = ["popular_shows", "top_shows"] charts = { @@ -68,6 +68,26 @@ class IMDb: valid_lists.append({"url": imdb_url, "limit": list_count}) return valid_lists + def validate_imdb_watchlists(self, err_type, users, language): + valid_users = [] + for user in util.get_list(users): + user_id = None + if not user.startswith("ur"): + try: + user_id = int(user[2:]) + except ValueError: + pass + if not user_id: + raise Failed(f"{err_type} Error: User {user} not in the format of 'ur########'") + if self._watchlist(user, language): + valid_users.append(user) + return valid_users + + def _watchlist(self, user, language): + response = self.config.get_html(f"{base_url}/user/{user}/watchlist", headers=util.header(language)) + group = response.xpath("//span[@class='ab_widget']/script[@type='text/javascript']/text()") + return [k for k in json.loads(str(group[0]).split("\n")[5][35:-2])["titles"]] + def _total(self, imdb_url, language): if imdb_url.startswith(urls["lists"]): xpath_total = "//div[@class='desc lister-total-num-results']/text()" @@ -186,6 +206,9 @@ class IMDb: elif method == "imdb_chart": logger.info(f"Processing IMDb Chart: {charts[data]}") return [(_i, "imdb") for _i in self._ids_from_chart(data)] + elif method == "imdb_watchlist": + logger.info(f"Processing IMDb Watchlist: {data}") + return [(_i, "imdb") for _i in self._watchlist(data, language)] else: raise Failed(f"IMDb Error: Method {method} not supported")