[8] add imdb_watchlist builder

pull/1020/head
meisnate12 2 years ago
parent e1f23f0d3e
commit 915518fdec

@ -1 +1 @@
1.17.3-develop7 1.17.3-develop8

@ -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) [![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) [![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) [![Discord](https://img.shields.io/discord/822460010649878528?color=%2300bc8c&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) [![Reddit](https://img.shields.io/reddit/subreddit-subscribers/PlexMetaManager?color=%2300bc8c&label=r%2FPlexMetaManager&style=plastic)](https://www.reddit.com/r/PlexMetaManager/)
[![Wiki](https://img.shields.io/readthedocs/plex-meta-manager?style=plastic)](https://metamanager.wiki) [![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)
[![Sponsor or Donate](https://img.shields.io/badge/-Sponsor_or_Donate-blueviolet?style=plastic)](https://github.com/sponsors/meisnate12) [![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. 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.

@ -2,11 +2,12 @@
You can find items using the features of [IMDb.com](https://www.imdb.com/) (IMDb). 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 | | Attribute | Description | Works with Movies | Works with Shows | Works with Playlists and Custom Sort |
|:----------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------:|:----------------:|:------------------------------------:| |:------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------:|:----------------:|:------------------------------------:|
| [`imdb_id`](#imdb-id) | Gets the movie/show specified. | ✅ | ✅ | ❌ | | [`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_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_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 ## IMDb ID
@ -119,3 +120,35 @@ collections:
limit: 100 limit: 100
summary: The top 100 Simpsons episodes by IMDb user rating 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
```

@ -27,7 +27,7 @@ To make a collection a Smart Label Collection, the `smart_label` attribute must
sort_by: release.desc sort_by: release.desc
all: all:
label: <<smart_label>> label: <<smart_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. 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.

@ -244,8 +244,8 @@ These are some commonly-used examples of Special Text overlays:
| `name: text(Season <<season_number>> Episode <<episode_number>>)` | Season 1 Episode 1 | | `name: text(Season <<season_number>> Episode <<episode_number>>)` | Season 1 Episode 1 |
| `name: text(Season <<season_number>>)` | Season 1 | | `name: text(Season <<season_number>>)` | Season 1 |
| `name: text(Episode <<episode_number>>)` | Episode 1 | | `name: text(Episode <<episode_number>>)` | Episode 1 |
| `name: text(Runtime: <<runtime>>m)` | Runtime: 90m | | `name: "text(Runtime: <<runtime>>m)"` | Runtime: 90m |
| `name: text(Runtime: <<runtimeH>>h <<runtimeM>>m)` | Runtime: 1h 30m | | `name: "text(Runtime: <<runtimeH>>h <<runtimeM>>m)"` | Runtime: 1h 30m |
#### Text Addon Images #### Text Addon Images

@ -143,7 +143,7 @@ smart_url_invalid = ["filters", "run_again", "sync_mode", "show_filtered", "show
custom_sort_builders = [ custom_sort_builders = [
"plex_search", "plex_pilots", "tmdb_list", "tmdb_popular", "tmdb_now_playing", "tmdb_top_rated", "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", "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", "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", "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", "flixpatrol_url", "flixpatrol_demographics", "flixpatrol_popular", "flixpatrol_top", "trakt_recommendations",
@ -1144,6 +1144,9 @@ class CollectionBuilder:
self.builders.append((method_name, value)) self.builders.append((method_name, value))
else: else:
raise Failed(f"{self.Type} Error: chart: {value} is invalid options are {[i for i in imdb.charts]}") 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): def _letterboxd(self, method_name, method_data):
if method_name.startswith("letterboxd_list"): if method_name.startswith("letterboxd_list"):

@ -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 import util
from modules.util import Failed from modules.util import Failed
from urllib.parse import urlparse, parse_qs from urllib.parse import urlparse, parse_qs
logger = util.logger 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"] movie_charts = ["box_office", "popular_movies", "top_movies", "top_english", "top_indian", "lowest_rated"]
show_charts = ["popular_shows", "top_shows"] show_charts = ["popular_shows", "top_shows"]
charts = { charts = {
@ -68,6 +68,26 @@ class IMDb:
valid_lists.append({"url": imdb_url, "limit": list_count}) valid_lists.append({"url": imdb_url, "limit": list_count})
return valid_lists 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): def _total(self, imdb_url, language):
if imdb_url.startswith(urls["lists"]): if imdb_url.startswith(urls["lists"]):
xpath_total = "//div[@class='desc lister-total-num-results']/text()" xpath_total = "//div[@class='desc lister-total-num-results']/text()"
@ -186,6 +206,9 @@ class IMDb:
elif method == "imdb_chart": elif method == "imdb_chart":
logger.info(f"Processing IMDb Chart: {charts[data]}") logger.info(f"Processing IMDb Chart: {charts[data]}")
return [(_i, "imdb") for _i in self._ids_from_chart(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: else:
raise Failed(f"IMDb Error: Method {method} not supported") raise Failed(f"IMDb Error: Method {method} not supported")

Loading…
Cancel
Save