Last active
April 15, 2025 21:48
-
-
Save JonnyWong16/b0e6b2761f8649d811f51866e682464b to your computer and use it in GitHub Desktop.
Selects the default TMDB poster and art for items in a Plex library if no poster/art is selected or the current poster/art is from Gracenote.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
''' | |
Description: Selects the default TMDB poster and art for items in a Plex library | |
if no poster/art is selected or the current poster/art is from Gracenote. | |
Author: /u/SwiftPanda16 | |
Requires: plexapi | |
Usage: | |
* Change the posters for an entire library: | |
python select_tmdb_poster.py --library "Movies" --poster | |
* Change the art for an entire library: | |
python select_tmdb_poster.py --library "Movies" --art | |
* Change the posters and art for an entire library: | |
python select_tmdb_poster.py --library "Movies" --poster --art | |
* Change the poster for a specific item: | |
python select_tmdb_poster.py --rating_key 1234 --poster | |
* Change the art for a specific item: | |
python select_tmdb_poster.py --rating_key 1234 --art | |
* Change the poster and art for a specific item: | |
python select_tmdb_poster.py --rating_key 1234 --poster --art | |
* By default locked posters are skipped. To update locked posters: | |
python select_tmdb_poster.py --library "Movies" --include_locked --poster --art | |
* To override the preferred provider: | |
python select_tmdb_poster.py --library "Movies" --art --art_provider "fanarttv" | |
Tautulli script trigger: | |
* Notify on recently added | |
Tautulli script conditions: | |
* Filter which media to select the poster. Examples: | |
[ Media Type | is | movie ] | |
Tautulli script arguments: | |
* Recently Added: | |
--rating_key {rating_key} --poster --art | |
''' | |
import argparse | |
import os | |
import plexapi.base | |
from plexapi.server import PlexServer | |
plexapi.base.USER_DONT_RELOAD_FOR_KEYS.add('fields') | |
# Poster and art providers to replace | |
REPLACE_PROVIDERS = ['gracenote', 'plex', None] | |
# Preferred poster and art provider to use (Note not all providers are availble for all items) | |
# Possible options: tmdb, tvdb, imdb, fanarttv, gracenote, plex | |
PREFERRED_POSTER_PROVIDER = 'tmdb' | |
PREFERRED_ART_PROVIDER = 'tmdb' | |
# ## OVERRIDES - ONLY EDIT IF RUNNING SCRIPT WITHOUT TAUTULLI ## | |
PLEX_URL = '' | |
PLEX_TOKEN = '' | |
# Environmental Variables | |
PLEX_URL = PLEX_URL or os.getenv('PLEX_URL', PLEX_URL) | |
PLEX_TOKEN = PLEX_TOKEN or os.getenv('PLEX_TOKEN', PLEX_TOKEN) | |
def select_library( | |
library, | |
include_locked=False, | |
poster=False, | |
poster_provider=PREFERRED_POSTER_PROVIDER, | |
art=False, | |
art_provider=PREFERRED_ART_PROVIDER | |
): | |
for item in library.all(includeGuids=False): | |
# Only reload for fields | |
item.reload(**{k: 0 for k, v in item._INCLUDES.items()}) | |
select_item( | |
item, | |
include_locked=include_locked, | |
poster=poster, | |
poster_provider=poster_provider, | |
art=art, | |
art_provider=art_provider | |
) | |
def select_item( | |
item, | |
include_locked=False, | |
poster=False, | |
poster_provider=PREFERRED_POSTER_PROVIDER, | |
art=False, | |
art_provider=PREFERRED_ART_PROVIDER | |
): | |
print(f"{item.title} ({item.year})") | |
if poster: | |
select_poster(item, include_locked, poster_provider) | |
if art: | |
select_art(item, include_locked, art_provider) | |
def select_poster(item, include_locked=False, provider=PREFERRED_POSTER_PROVIDER): | |
print(" Checking poster...") | |
if item.isLocked('thumb') and not include_locked: # PlexAPI 4.5.10 | |
print(f" - Locked poster for {item.title}. Skipping.") | |
return | |
posters = item.posters() | |
selected_poster = next((p for p in posters if p.selected), None) | |
if selected_poster is None: | |
print(f" - WARNING: No poster selected for {item.title}.") | |
else: | |
skip_poster = selected_poster.provider not in REPLACE_PROVIDERS | |
print(f" - Poster provider is '{selected_poster.provider}' for {item.title}.") | |
if posters and (selected_poster is None or selected_poster.provider in REPLACE_PROVIDERS): | |
# Fallback to first poster if no preferred provider posters are available | |
provider_poster = next((p for p in posters if p.provider == provider), posters[0]) | |
# Selecting the poster automatically locks it | |
provider_poster.select() | |
print(f" - Selected and locked {provider_poster.provider} poster for {item.title}.") | |
elif skip_poster and selected_poster: | |
item.lockPoster() | |
print(f" - Locked {selected_poster.provider} poster for {item.title}.") | |
def select_art(item, include_locked=False, provider=PREFERRED_ART_PROVIDER): | |
print(" Checking art...") | |
if item.isLocked('art') and not include_locked: # PlexAPI 4.5.10 | |
print(f" - Locked art for {item.title}. Skipping.") | |
return | |
arts = item.arts() | |
selected_art = next((p for p in arts if p.selected), None) | |
if selected_art is None: | |
print(f" - WARNING: No art selected for {item.title}.") | |
else: | |
skip_art = selected_art.provider not in REPLACE_PROVIDERS | |
print(f" - Art provider is '{selected_art.provider}' for {item.title}.") | |
if arts and (selected_art is None or selected_art.provider in REPLACE_PROVIDERS): | |
# Fallback to first art if no preferred provider arts are available | |
provider_art = next((p for p in arts if p.provider == provider), arts[0]) | |
# Selecting the art automatically locks it | |
provider_art.select() | |
print(f" - Selected and locked {provider_art.provider} art for {item.title}.") | |
elif skip_art and selected_art: | |
item.lockArt() | |
print(f" - Locked {selected_art.provider} art for {item.title}.") | |
if __name__ == '__main__': | |
parser = argparse.ArgumentParser() | |
parser.add_argument('--rating_key', type=int) | |
parser.add_argument('--library') | |
parser.add_argument('--include_locked', action='store_true') | |
parser.add_argument('--poster', action='store_true') | |
parser.add_argument('--poster_provider', default=PREFERRED_POSTER_PROVIDER) | |
parser.add_argument('--art', action='store_true') | |
parser.add_argument('--art_provider', default=PREFERRED_ART_PROVIDER) | |
opts = parser.parse_args() | |
plex = PlexServer(PLEX_URL, PLEX_TOKEN) | |
if opts.rating_key: | |
item = plex.fetchItem(opts.rating_key) | |
select_item(item, opts.include_locked, opts.poster, opts.poster_provider, opts.art, opts.art_provider) | |
elif opts.library: | |
library = plex.library.section(opts.library) | |
select_library(library, opts.include_locked, opts.poster, opts.poster_provider, opts.art, opts.art_provider) | |
else: | |
print("No --rating_key or --library specified. Exiting.") |
TIA
I am getting this in my log. How do i fix it? thanks
Tautulli Notifiers :: Script returned:
No --rating_key or --library specified. Exiting.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Am I right in thinking that this updates my Plex library with the set poster on https://www.themoviedb.org/ ?
If yes, how the hell do I get it working.