Skip to content

Instantly share code, notes, and snippets.

@xenago
Forked from JonnyWong16/select_tmdb_poster.py
Last active September 15, 2024 22:40
Show Gist options
  • Save xenago/f24a5a2d82a0f0060f1794c6c1b76266 to your computer and use it in GitHub Desktop.
Save xenago/f24a5a2d82a0f0060f1794c6c1b76266 to your computer and use it in GitHub Desktop.

Revisions

  1. xenago revised this gist Mar 15, 2024. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion plex_poster_fix.py
    Original file line number Diff line number Diff line change
    @@ -9,7 +9,7 @@

    # Usage Instructions
    #
    # Note: usage of a Python venv is recommended to avoid installing packages system-wide. See e.g. https://realpython.com/python-virtual-environments-a-primer/
    # Note: usage of a Python venv is optional, but recommended to avoid installing PlexAPI system-wide. See e.g. https://realpython.com/python-virtual-environments-a-primer/
    #
    # 1. Install Python (method depends on OS)
    # * Tested with Python 3.10+
  2. xenago revised this gist Mar 15, 2024. 1 changed file with 5 additions and 5 deletions.
    10 changes: 5 additions & 5 deletions plex_poster_fix.py
    Original file line number Diff line number Diff line change
    @@ -32,19 +32,19 @@
    Requires: plexapi
    Usage:
    * Provide the Plex server URL, if not using the PLEX_URL environment variable:
    python select_tmdb_poster.py --plex_url "https://my-plex-url"
    python plex_poster_fix.py --plex_url "https://my-plex-url"
    * Provide a Plex API key, if not using the PLEX_TOKEN environment variable:
    python select_tmdb_poster.py --plex_token "my-token-here"
    python plex_poster_fix.py --plex_token "my-token-here"
    * Change the posters for an entire library:
    python select_tmdb_poster.py --library "Movies"
    python plex_poster_fix.py --library "Movies"
    * Change the poster for a specific item:
    python select_tmdb_poster.py --rating_key 1234
    python plex_poster_fix.py --rating_key 1234
    * By default locked posters are skipped. To update locked posters:
    python select_tmdb_poster.py --library "Movies" --include_locked
    python plex_poster_fix.py --library "Movies" --include_locked
    Tautulli script trigger:
    * Notify on recently added
  3. xenago revised this gist Mar 15, 2024. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions plex_poster_fix.py
    Original file line number Diff line number Diff line change
    @@ -9,6 +9,8 @@

    # Usage Instructions
    #
    # Note: usage of a Python venv is recommended to avoid installing packages system-wide. See e.g. https://realpython.com/python-virtual-environments-a-primer/
    #
    # 1. Install Python (method depends on OS)
    # * Tested with Python 3.10+
    # 2. Download script (example, can use any method to download the file)
  4. xenago revised this gist Mar 15, 2024. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion plex_poster_fix.py
    Original file line number Diff line number Diff line change
    @@ -7,7 +7,7 @@
    # Adapted from JonnyWong16's [`select_tmdb_poster.py`](https://gist.github.com/JonnyWong16/b0e6b2761f8649d811f51866e682464b).
    # With large libraries, it may take a few seconds up to a minute for the script to start producing output.

    # Installation
    # Usage Instructions
    #
    # 1. Install Python (method depends on OS)
    # * Tested with Python 3.10+
    @@ -21,6 +21,8 @@
    # * To increase security, can optionally use the `PLEX_TOKEN` environment variable instead of the `--plex_token` argument
    # * Depending on OS, `python3` may need to be used as the command instead of `python`

    ################################

    """
    Description: Selects the default TMDB poster if no poster is selected
    or the current poster is from Gracenote.
  5. xenago revised this gist Mar 15, 2024. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion plex_poster_fix.py
    Original file line number Diff line number Diff line change
    @@ -12,7 +12,7 @@
    # 1. Install Python (method depends on OS)
    # * Tested with Python 3.10+
    # 2. Download script (example, can use any method to download the file)
    # * `wget https://gist.github.com/xenago/f24a5a2d82a0f0060f1794c6c1b76266/raw/select_tmdb_poster.py`
    # * `wget https://gist.github.com/xenago/f24a5a2d82a0f0060f1794c6c1b76266/raw`
    # 3. Install PlexAPI library:
    # * `pip install PlexAPI==4.15.10`
    # * Depending on OS, `pip3` may need to be used as the command instead of `pip`
  6. xenago revised this gist Mar 15, 2024. 1 changed file with 5 additions and 4 deletions.
    9 changes: 5 additions & 4 deletions plex_poster_fix.py
    Original file line number Diff line number Diff line change
    @@ -4,20 +4,21 @@
    # plex_poster_fix.py
    #
    # Swaps out posters provided by Gracenote with ones from TMDB.
    # Adapted from [`select_tmdb_poster.py`](https://gist.github.com/JonnyWong16/b0e6b2761f8649d811f51866e682464b).
    # Adapted from JonnyWong16's [`select_tmdb_poster.py`](https://gist.github.com/JonnyWong16/b0e6b2761f8649d811f51866e682464b).
    # With large libraries, it may take a few seconds up to a minute for the script to start producing output.

    # Installation
    #
    # 1. Install Python (system-dependent)
    # 1. Install Python (method depends on OS)
    # * Tested with Python 3.10+
    # 2. Download script (example, can use any method)
    # 2. Download script (example, can use any method to download the file)
    # * `wget https://gist.github.com/xenago/f24a5a2d82a0f0060f1794c6c1b76266/raw/select_tmdb_poster.py`
    # 3. Install PlexAPI library:
    # * `pip install PlexAPI==4.15.10`
    # * Depending on OS, `pip3` may need to be used as the command instead of `pip`
    # 4. Run script:
    # * `python plex_poster_fix.py --library "Library Name Here" --plex_url "https://plex-server-ip-here:32400" --plex_token "contents of myPlexAccessToken browser cookie go here"`
    # * To increase security, set the `PLEX_TOKEN` environment variable rather than passing `--plex_token`
    # * To increase security, can optionally use the `PLEX_TOKEN` environment variable instead of the `--plex_token` argument
    # * Depending on OS, `python3` may need to be used as the command instead of `python`

    """
  7. xenago revised this gist Mar 15, 2024. No changes.
  8. xenago revised this gist Mar 15, 2024. 2 changed files with 127 additions and 92 deletions.
    127 changes: 127 additions & 0 deletions plex_poster_fix.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,127 @@
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-

    # plex_poster_fix.py
    #
    # Swaps out posters provided by Gracenote with ones from TMDB.
    # Adapted from [`select_tmdb_poster.py`](https://gist.github.com/JonnyWong16/b0e6b2761f8649d811f51866e682464b).
    # With large libraries, it may take a few seconds up to a minute for the script to start producing output.

    # Installation
    #
    # 1. Install Python (system-dependent)
    # * Tested with Python 3.10+
    # 2. Download script (example, can use any method)
    # * `wget https://gist.github.com/xenago/f24a5a2d82a0f0060f1794c6c1b76266/raw/select_tmdb_poster.py`
    # 3. Install PlexAPI library:
    # * `pip install PlexAPI==4.15.10`
    # 4. Run script:
    # * `python plex_poster_fix.py --library "Library Name Here" --plex_url "https://plex-server-ip-here:32400" --plex_token "contents of myPlexAccessToken browser cookie go here"`
    # * To increase security, set the `PLEX_TOKEN` environment variable rather than passing `--plex_token`
    # * Depending on OS, `python3` may need to be used as the command instead of `python`

    """
    Description: Selects the default TMDB poster if no poster is selected
    or the current poster is from Gracenote.
    Author: /u/SwiftPanda16
    Requires: plexapi
    Usage:
    * Provide the Plex server URL, if not using the PLEX_URL environment variable:
    python select_tmdb_poster.py --plex_url "https://my-plex-url"
    * Provide a Plex API key, if not using the PLEX_TOKEN environment variable:
    python select_tmdb_poster.py --plex_token "my-token-here"
    * Change the posters for an entire library:
    python select_tmdb_poster.py --library "Movies"
    * Change the poster for a specific item:
    python select_tmdb_poster.py --rating_key 1234
    * By default locked posters are skipped. To update locked posters:
    python select_tmdb_poster.py --library "Movies" --include_locked
    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}
    """

    import argparse
    import os
    import plexapi.base
    from plexapi.server import PlexServer

    plexapi.base.USER_DONT_RELOAD_FOR_KEYS.add("fields")


    def select_tmdb_poster_library(library, include_locked=False):
    for item in library.all(includeGuids=False):
    # Only reload for fields
    item.reload(**{k: 0 for k, v in item._INCLUDES.items()})
    select_tmdb_poster_item(item, include_locked=include_locked)


    def select_tmdb_poster_item(item, include_locked=False):
    if next((f.locked for f in item.fields if f.name == "thumb"), False) and not include_locked:
    print(f"Poster is locked for `{item.title}`. Skipping.")
    return

    posters = item.posters()
    selected_poster = next((p for p in posters if p.selected), None)

    item_slug = f"{item.title} ({item.year})"

    if selected_poster is None:
    print(f"WARNING: No poster selected for `{item_slug}`.")
    elif selected_poster.provider == "gracenote":
    print(f"WARNING: Poster provider is `gracenote` for `{item_slug}`.")
    else:
    print(f"Poster provider is `{selected_poster.provider}` for `{item_slug}`. Skipping.")
    if selected_poster is None or selected_poster.provider == "gracenote":
    # Fallback to first poster if no TMDB posters are available
    tmdb_poster = next((p for p in posters if p.provider == "tmdb"), posters[0])
    # Selecting the poster automatically locks it
    tmdb_poster.select()
    print(f"Selected `{tmdb_poster.provider}` poster for `{item_slug}`.")


    if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--plex_url", type=str)
    parser.add_argument("--plex_token", type=str)
    parser.add_argument("--rating_key", type=int)
    parser.add_argument("--library")
    parser.add_argument("--include_locked", action="store_true")
    opts = parser.parse_args()
    # If a token is not provided as a CLI argument, try the environment variable
    if opts.plex_url:
    PLEX_URL = opts.plex_url
    else:
    PLEX_URL = os.getenv("PLEX_URL")
    if PLEX_URL is None:
    print("No Plex URL provided via `--plex_url` argument or `PLEX_URL` environment variable. Exiting.")
    exit(1)
    if opts.plex_token:
    PLEX_TOKEN = opts.plex_token
    else:
    PLEX_TOKEN = os.getenv("PLEX_TOKEN")
    if PLEX_TOKEN is None:
    print("No Plex API key provided via `--plex_token` argument or `PLEX_TOKEN` environment variable. Exiting.")
    exit(1)
    # Attempt to authenticate with the Plex server
    plex = PlexServer(PLEX_URL, PLEX_TOKEN)
    # Actually perform the poster replacement
    if opts.rating_key:
    selected_item = plex.fetchItem(opts.rating_key)
    select_tmdb_poster_item(selected_item, opts.include_locked)
    elif opts.library:
    selected_library = plex.library.section(opts.library)
    select_tmdb_poster_library(selected_library, opts.include_locked)
    else:
    print("No `--rating_key` or `--library` specified. Exiting.")
    exit(1)
    92 changes: 0 additions & 92 deletions select_tmdb_poster.py
    Original file line number Diff line number Diff line change
    @@ -1,92 +0,0 @@
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-

    '''
    Description: Selects the default TMDB poster if no poster is selected
    or the current poster is from Gracenote.
    Author: /u/SwiftPanda16
    Requires: plexapi
    Usage:
    * Change the posters for an entire library:
    python select_tmdb_poster.py --library "Movies"
    * Change the poster for a specific item:
    python select_tmdb_poster.py --rating_key 1234
    * By default locked posters are skipped. To update locked posters:
    python select_tmdb_poster.py --library "Movies" --include_locked
    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}
    '''

    import argparse
    import os
    import plexapi.base
    from plexapi.server import PlexServer
    plexapi.base.USER_DONT_RELOAD_FOR_KEYS.add('fields')


    # ## 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_tmdb_poster_library(library, include_locked=False):
    for item in library.all(includeGuids=False):
    # Only reload for fields
    item.reload(**{k: 0 for k, v in item._INCLUDES.items()})
    select_tmdb_poster_item(item, include_locked=include_locked)


    def select_tmdb_poster_item(item, include_locked=False):
    # if item.isLocked('thumb') and not include_locked: # PlexAPI 4.5.10
    if next((f.locked for f in item.fields if f.name == 'thumb'), False) and not include_locked:
    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:
    skipping = ' Skipping.' if selected_poster.provider != 'gracenote' else ''
    print(f"Poster provider is '{selected_poster.provider}' for {item.title}.{skipping}")

    if selected_poster is None or selected_poster.provider == 'gracenote':
    # Fallback to first poster if no TMDB posters are available
    tmdb_poster = next((p for p in posters if p.provider == 'tmdb'), posters[0])
    # Selecting the poster automatically locks it
    tmdb_poster.select()
    print(f"Selected {tmdb_poster.provider} poster 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')
    opts = parser.parse_args()

    plex = PlexServer(PLEX_URL, PLEX_TOKEN)

    if opts.rating_key:
    item = plex.fetchItem(opts.rating_key)
    select_tmdb_poster_item(item, opts.include_locked)
    elif opts.library:
    library = plex.library.section(opts.library)
    select_tmdb_poster_library(library, opts.include_locked)
    else:
    print("No --rating_key or --library specified. Exiting.")
  9. @JonnyWong16 JonnyWong16 revised this gist Mar 8, 2024. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion select_tmdb_poster.py
    Original file line number Diff line number Diff line change
    @@ -51,7 +51,8 @@ def select_tmdb_poster_library(library, include_locked=False):


    def select_tmdb_poster_item(item, include_locked=False):
    if item.isLocked('thumb') and not include_locked:
    # if item.isLocked('thumb') and not include_locked: # PlexAPI 4.5.10
    if next((f.locked for f in item.fields if f.name == 'thumb'), False) and not include_locked:
    print(f"Locked poster for {item.title}. Skipping.")
    return

  10. @JonnyWong16 JonnyWong16 revised this gist Mar 4, 2024. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion select_tmdb_poster.py
    Original file line number Diff line number Diff line change
    @@ -46,7 +46,7 @@
    def select_tmdb_poster_library(library, include_locked=False):
    for item in library.all(includeGuids=False):
    # Only reload for fields
    item.reload(**{k: 0 for k, v in item._INDLUCES.items()})
    item.reload(**{k: 0 for k, v in item._INCLUDES.items()})
    select_tmdb_poster_item(item, include_locked=include_locked)


  11. @JonnyWong16 JonnyWong16 revised this gist Mar 1, 2024. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion select_tmdb_poster.py
    Original file line number Diff line number Diff line change
    @@ -46,7 +46,7 @@
    def select_tmdb_poster_library(library, include_locked=False):
    for item in library.all(includeGuids=False):
    # Only reload for fields
    item.reload(**{k: 0 for k, v in movie._INDLUCES.items()})
    item.reload(**{k: 0 for k, v in item._INDLUCES.items()})
    select_tmdb_poster_item(item, include_locked=include_locked)


  12. @JonnyWong16 JonnyWong16 revised this gist Feb 29, 2024. 1 changed file with 1 addition and 21 deletions.
    22 changes: 1 addition & 21 deletions select_tmdb_poster.py
    Original file line number Diff line number Diff line change
    @@ -46,27 +46,7 @@
    def select_tmdb_poster_library(library, include_locked=False):
    for item in library.all(includeGuids=False):
    # Only reload for fields
    item.reload(
    checkFiles=0,
    includeAllConcerts=0,
    includeBandwidths=0,
    includeChapters=0,
    includeChildren=0,
    includeConcerts=0,
    includeExternalMedia=0,
    includeExtras=0,
    includeFields=1,
    includeGeolocation=0,
    includeLoudnessRamps=0,
    includeMarkers=0,
    includeOnDeck=0,
    includePopularLeaves=0,
    includePreferences=0,
    includeRelated=0,
    includeRelatedCount=0,
    includeReviews=0,
    includeStations=0
    )
    item.reload(**{k: 0 for k, v in movie._INDLUCES.items()})
    select_tmdb_poster_item(item, include_locked=include_locked)


  13. @JonnyWong16 JonnyWong16 revised this gist Feb 21, 2024. 1 changed file with 6 additions and 3 deletions.
    9 changes: 6 additions & 3 deletions select_tmdb_poster.py
    Original file line number Diff line number Diff line change
    @@ -72,21 +72,24 @@ def select_tmdb_poster_library(library, include_locked=False):

    def select_tmdb_poster_item(item, include_locked=False):
    if item.isLocked('thumb') and not include_locked:
    print(f"Skipping locked poster for {item.title}.")
    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}")
    print(f"WARNING: No poster selected for {item.title}.")
    else:
    skipping = ' Skipping.' if selected_poster.provider != 'gracenote' else ''
    print(f"Poster provider is '{selected_poster.provider}' for {item.title}.{skipping}")

    if selected_poster is None or selected_poster.provider == 'gracenote':
    # Fallback to first poster if no TMDB posters are available
    tmdb_poster = next((p for p in posters if p.provider == 'tmdb'), posters[0])
    # Selecting the poster automatically locks it
    tmdb_poster.select()
    print(f"Selected {tmdb_poster.provider} poster for {item.title}")
    print(f"Selected {tmdb_poster.provider} poster for {item.title}.")


    if __name__ == '__main__':
  14. @JonnyWong16 JonnyWong16 revised this gist Feb 20, 2024. 1 changed file with 12 additions and 14 deletions.
    26 changes: 12 additions & 14 deletions select_tmdb_poster.py
    Original file line number Diff line number Diff line change
    @@ -71,24 +71,22 @@ def select_tmdb_poster_library(library, include_locked=False):


    def select_tmdb_poster_item(item, include_locked=False):
    if item.isLocked('thumb') and not include_locked:
    print(f"Skipping locked poster for {item.title}.")
    return

    posters = item.posters()
    selected_poster = next((p for p in posters if p.selected), None)

    if selected_poster is None or not item.isLocked('thumb'):
    if selected_poster is None:
    print(f"WARNING: No poster selected for {item.title}")
    select_tmdb_poster(item, posters)
    elif not include_locked and item.isLocked('thumb'):
    print(f"Poster is locked for {item.title}. Skipping.")
    elif selected_poster.provider == 'gracenote':
    select_tmdb_poster(item, posters)


    def select_tmdb_poster(item, posters):
    # Fallback to first poster if no TMDB posters are available
    tmdb_poster = next((p for p in posters if p.provider == 'tmdb'), posters[0])
    # Selecting the poster automatically locks it
    tmdb_poster.select()
    print(f"Selected {tmdb_poster.provider} poster for {item.title}")

    if selected_poster is None or selected_poster.provider == 'gracenote':
    # Fallback to first poster if no TMDB posters are available
    tmdb_poster = next((p for p in posters if p.provider == 'tmdb'), posters[0])
    # Selecting the poster automatically locks it
    tmdb_poster.select()
    print(f"Selected {tmdb_poster.provider} poster for {item.title}")


    if __name__ == '__main__':
  15. @JonnyWong16 JonnyWong16 revised this gist Feb 20, 2024. 1 changed file with 9 additions and 9 deletions.
    18 changes: 9 additions & 9 deletions select_tmdb_poster.py
    Original file line number Diff line number Diff line change
    @@ -13,8 +13,8 @@
    * Change the poster for a specific item:
    python select_tmdb_poster.py --rating_key 1234
    * Ignore locked posters:
    python select_tmdb_poster.py --library "Movies" --ignore_locked
    * By default locked posters are skipped. To update locked posters:
    python select_tmdb_poster.py --library "Movies" --include_locked
    Tautulli script trigger:
    * Notify on recently added
    @@ -43,7 +43,7 @@
    PLEX_TOKEN = PLEX_TOKEN or os.getenv('PLEX_TOKEN', PLEX_TOKEN)


    def select_tmdb_poster_library(library, ignore_locked=False):
    def select_tmdb_poster_library(library, include_locked=False):
    for item in library.all(includeGuids=False):
    # Only reload for fields
    item.reload(
    @@ -67,17 +67,17 @@ def select_tmdb_poster_library(library, ignore_locked=False):
    includeReviews=0,
    includeStations=0
    )
    select_tmdb_poster_item(item, ignore_locked=ignore_locked)
    select_tmdb_poster_item(item, include_locked=include_locked)


    def select_tmdb_poster_item(item, ignore_locked=False):
    def select_tmdb_poster_item(item, include_locked=False):
    posters = item.posters()
    selected_poster = next((p for p in posters if p.selected), None)

    if selected_poster is None or not item.isLocked('thumb'):
    print(f"WARNING: No poster selected for {item.title}")
    select_tmdb_poster(item, posters)
    elif not ignore_locked and item.isLocked('thumb'):
    elif not include_locked and item.isLocked('thumb'):
    print(f"Poster is locked for {item.title}. Skipping.")
    elif selected_poster.provider == 'gracenote':
    select_tmdb_poster(item, posters)
    @@ -95,16 +95,16 @@ def select_tmdb_poster(item, posters):
    parser = argparse.ArgumentParser()
    parser.add_argument('--rating_key', type=int)
    parser.add_argument('--library')
    parser.add_argument('--ignore_locked', action='store_true')
    parser.add_argument('--include_locked', action='store_true')
    opts = parser.parse_args()

    plex = PlexServer(PLEX_URL, PLEX_TOKEN)

    if opts.rating_key:
    item = plex.fetchItem(opts.rating_key)
    select_tmdb_poster_item(item, opts.ignore_locked)
    select_tmdb_poster_item(item, opts.include_locked)
    elif opts.library:
    library = plex.library.section(opts.library)
    select_tmdb_poster_library(library, opts.ignore_locked)
    select_tmdb_poster_library(library, opts.include_locked)
    else:
    print("No --rating_key or --library specified. Exiting.")
  16. @JonnyWong16 JonnyWong16 revised this gist Feb 18, 2024. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion select_tmdb_poster.py
    Original file line number Diff line number Diff line change
    @@ -19,7 +19,7 @@
    Tautulli script trigger:
    * Notify on recently added
    Tautulli script conditions:
    * Filter which media to add labels to using conditions. Examples:
    * Filter which media to select the poster. Examples:
    [ Media Type | is | movie ]
    Tautulli script arguments:
    * Recently Added:
  17. @JonnyWong16 JonnyWong16 revised this gist Feb 18, 2024. 1 changed file with 24 additions and 13 deletions.
    37 changes: 24 additions & 13 deletions select_tmdb_poster.py
    Original file line number Diff line number Diff line change
    @@ -13,6 +13,9 @@
    * Change the poster for a specific item:
    python select_tmdb_poster.py --rating_key 1234
    * Ignore locked posters:
    python select_tmdb_poster.py --library "Movies" --ignore_locked
    Tautulli script trigger:
    * Notify on recently added
    Tautulli script conditions:
    @@ -40,7 +43,7 @@
    PLEX_TOKEN = PLEX_TOKEN or os.getenv('PLEX_TOKEN', PLEX_TOKEN)


    def select_tmdb_poster_library(library):
    def select_tmdb_poster_library(library, ignore_locked=False):
    for item in library.all(includeGuids=False):
    # Only reload for fields
    item.reload(
    @@ -64,36 +67,44 @@ def select_tmdb_poster_library(library):
    includeReviews=0,
    includeStations=0
    )
    select_tmdb_poster_item(item)
    select_tmdb_poster_item(item, ignore_locked=ignore_locked)


    def select_tmdb_poster_item(item):
    def select_tmdb_poster_item(item, ignore_locked=False):
    posters = item.posters()
    selected_poster = next((p for p in posters if p.selected), None)

    if selected_poster is None or not item.isLocked('thumb') and selected_poster.provider == 'gracenote':
    if selected_poster is None:
    print(f"WARNING: No poster selected for {item.title}")
    # Fallback to first poster if no TMDB posters are available
    tmdb_poster = next((p for p in posters if p.provider == 'tmdb'), posters[0])
    # Selecting the poster automatically locks it
    tmdb_poster.select()
    print(f"Selected {tmdb_poster.provider} poster for {item.title}")
    if selected_poster is None or not item.isLocked('thumb'):
    print(f"WARNING: No poster selected for {item.title}")
    select_tmdb_poster(item, posters)
    elif not ignore_locked and item.isLocked('thumb'):
    print(f"Poster is locked for {item.title}. Skipping.")
    elif selected_poster.provider == 'gracenote':
    select_tmdb_poster(item, posters)


    def select_tmdb_poster(item, posters):
    # Fallback to first poster if no TMDB posters are available
    tmdb_poster = next((p for p in posters if p.provider == 'tmdb'), posters[0])
    # Selecting the poster automatically locks it
    tmdb_poster.select()
    print(f"Selected {tmdb_poster.provider} poster for {item.title}")


    if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--rating_key', type=int)
    parser.add_argument('--library')
    parser.add_argument('--ignore_locked', action='store_true')
    opts = parser.parse_args()

    plex = PlexServer(PLEX_URL, PLEX_TOKEN)

    if opts.rating_key:
    item = plex.fetchItem(opts.rating_key)
    select_tmdb_poster_item(item)
    select_tmdb_poster_item(item, opts.ignore_locked)
    elif opts.library:
    library = plex.library.section(opts.library)
    select_tmdb_poster_library(library)
    select_tmdb_poster_library(library, opts.ignore_locked)
    else:
    print("No --rating_key or --library specified. Exiting.")
  18. @JonnyWong16 JonnyWong16 revised this gist Feb 18, 2024. 1 changed file with 52 additions and 22 deletions.
    74 changes: 52 additions & 22 deletions select_tmdb_poster.py
    Original file line number Diff line number Diff line change
    @@ -2,28 +2,45 @@
    # -*- coding: utf-8 -*-

    '''
    Description: Selects the default TMDB poster for all movies in a Plex library
    if the current poster is from Gracenote.
    Description: Selects the default TMDB poster if no poster is selected
    or the current poster is from Gracenote.
    Author: /u/SwiftPanda16
    Requires: plexapi
    Usage:
    * Change the posters for an entire library:
    python select_tmdb_poster.py --library "Movies"
    * Change the poster for a specific item:
    python select_tmdb_poster.py --rating_key 1234
    Tautulli script trigger:
    * Notify on recently added
    Tautulli script conditions:
    * Filter which media to add labels to using conditions. Examples:
    [ Media Type | is | movie ]
    Tautulli script arguments:
    * Recently Added:
    --rating_key {rating_key}
    '''

    import argparse
    import os
    import plexapi.base
    from plexapi.server import PlexServer
    plexapi.base.USER_DONT_RELOAD_FOR_KEYS.add('fields')


    # ## EDIT SETTINGS ##

    PLEX_URL = 'http://localhost:32400'
    PLEX_TOKEN = 'XXXXXXXXXXXXXXXXXXXXXX'
    # ## OVERRIDES - ONLY EDIT IF RUNNING SCRIPT WITHOUT TAUTULLI ##

    LIBRARY_NAME = 'Movies'
    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)

    # ## CODE BELOW ##

    def select_tmdb_poster(library):
    def select_tmdb_poster_library(library):
    for item in library.all(includeGuids=False):
    # Only reload for fields
    item.reload(
    @@ -47,23 +64,36 @@ def select_tmdb_poster(library):
    includeReviews=0,
    includeStations=0
    )
    select_tmdb_poster_item(item)

    # Skip item if the poster is locked
    if item.isLocked('thumb'):
    continue

    posters = item.posters()
    def select_tmdb_poster_item(item):
    posters = item.posters()
    selected_poster = next((p for p in posters if p.selected), None)

    selected_poster = next((p for p in posters if p.selected), None)
    if selected_poster and selected_poster.provider == 'gracenote':
    # Fallback to first poster if no TMDB posters are available
    tmdb_poster = next((p for p in posters if p.provider == 'tmdb'), posters[0])
    # Selecting the poster automatically locks it
    tmdb_poster.select()
    print(f"Selected {tmdb_poster.provider} poster for {item.title}")
    if selected_poster is None or not item.isLocked('thumb') and selected_poster.provider == 'gracenote':
    if selected_poster is None:
    print(f"WARNING: No poster selected for {item.title}")
    # Fallback to first poster if no TMDB posters are available
    tmdb_poster = next((p for p in posters if p.provider == 'tmdb'), posters[0])
    # Selecting the poster automatically locks it
    tmdb_poster.select()
    print(f"Selected {tmdb_poster.provider} poster for {item.title}")


    if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--rating_key', type=int)
    parser.add_argument('--library')
    opts = parser.parse_args()

    plex = PlexServer(PLEX_URL, PLEX_TOKEN)
    library = plex.library.section(LIBRARY_NAME)
    select_tmdb_poster(library)

    if opts.rating_key:
    item = plex.fetchItem(opts.rating_key)
    select_tmdb_poster_item(item)
    elif opts.library:
    library = plex.library.section(opts.library)
    select_tmdb_poster_library(library)
    else:
    print("No --rating_key or --library specified. Exiting.")
  19. @JonnyWong16 JonnyWong16 revised this gist Feb 6, 2024. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions select_tmdb_poster.py
    Original file line number Diff line number Diff line change
    @@ -58,6 +58,7 @@ def select_tmdb_poster(library):
    if selected_poster and selected_poster.provider == 'gracenote':
    # Fallback to first poster if no TMDB posters are available
    tmdb_poster = next((p for p in posters if p.provider == 'tmdb'), posters[0])
    # Selecting the poster automatically locks it
    tmdb_poster.select()
    print(f"Selected {tmdb_poster.provider} poster for {item.title}")

  20. @JonnyWong16 JonnyWong16 revised this gist Feb 6, 2024. 1 changed file with 6 additions and 3 deletions.
    9 changes: 6 additions & 3 deletions select_tmdb_poster.py
    Original file line number Diff line number Diff line change
    @@ -2,29 +2,32 @@
    # -*- coding: utf-8 -*-

    '''
    Description: Selects the default TMDB poster for movies in a Plex library
    Description: Selects the default TMDB poster for all movies in a Plex library
    if the current poster is from Gracenote.
    Author: /u/SwiftPanda16
    Requires: plexapi
    '''

    import plexapi.base
    from plexapi.server import PlexServer

    plexapi.base.USER_DONT_RELOAD_FOR_KEYS.add('fields')


    # ## EDIT SETTINGS ##

    PLEX_URL = 'http://localhost:32400'
    PLEX_TOKEN = 'XXXXXXXXXXXXXXXXXXXXXX'

    LIBRARY_NAME = 'Movies'


    # ## CODE BELOW ##

    def select_tmdb_poster(library):
    for item in library.all(includeGuids=False):
    # Only reload for fields
    item.reload(
    checkFiles=False,
    checkFiles=0,
    includeAllConcerts=0,
    includeBandwidths=0,
    includeChapters=0,
  21. @JonnyWong16 JonnyWong16 revised this gist Feb 6, 2024. 1 changed file with 28 additions and 1 deletion.
    29 changes: 28 additions & 1 deletion select_tmdb_poster.py
    Original file line number Diff line number Diff line change
    @@ -8,16 +8,43 @@
    Requires: plexapi
    '''

    import plexapi.base
    from plexapi.server import PlexServer

    plexapi.base.USER_DONT_RELOAD_FOR_KEYS.add('fields')


    PLEX_URL = 'http://localhost:32400'
    PLEX_TOKEN = 'XXXXXXXXXXXXXXXXXXXXXX'

    LIBRARY_NAME = 'Movies'


    def select_tmdb_poster(library):
    for item in library.all():
    for item in library.all(includeGuids=False):
    # Only reload for fields
    item.reload(
    checkFiles=False,
    includeAllConcerts=0,
    includeBandwidths=0,
    includeChapters=0,
    includeChildren=0,
    includeConcerts=0,
    includeExternalMedia=0,
    includeExtras=0,
    includeFields=1,
    includeGeolocation=0,
    includeLoudnessRamps=0,
    includeMarkers=0,
    includeOnDeck=0,
    includePopularLeaves=0,
    includePreferences=0,
    includeRelated=0,
    includeRelatedCount=0,
    includeReviews=0,
    includeStations=0
    )

    # Skip item if the poster is locked
    if item.isLocked('thumb'):
    continue
  22. @JonnyWong16 JonnyWong16 created this gist Feb 5, 2024.
    38 changes: 38 additions & 0 deletions select_tmdb_poster.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,38 @@
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-

    '''
    Description: Selects the default TMDB poster for movies in a Plex library
    if the current poster is from Gracenote.
    Author: /u/SwiftPanda16
    Requires: plexapi
    '''

    from plexapi.server import PlexServer

    PLEX_URL = 'http://localhost:32400'
    PLEX_TOKEN = 'XXXXXXXXXXXXXXXXXXXXXX'

    LIBRARY_NAME = 'Movies'


    def select_tmdb_poster(library):
    for item in library.all():
    # Skip item if the poster is locked
    if item.isLocked('thumb'):
    continue

    posters = item.posters()

    selected_poster = next((p for p in posters if p.selected), None)
    if selected_poster and selected_poster.provider == 'gracenote':
    # Fallback to first poster if no TMDB posters are available
    tmdb_poster = next((p for p in posters if p.provider == 'tmdb'), posters[0])
    tmdb_poster.select()
    print(f"Selected {tmdb_poster.provider} poster for {item.title}")


    if __name__ == '__main__':
    plex = PlexServer(PLEX_URL, PLEX_TOKEN)
    library = plex.library.section(LIBRARY_NAME)
    select_tmdb_poster(library)