Skip to content

Instantly share code, notes, and snippets.

@JonnyWong16
Last active July 16, 2024 21:35
Show Gist options
  • Save JonnyWong16/9640557cf459896a8b7e1da8863b0485 to your computer and use it in GitHub Desktop.
Save JonnyWong16/9640557cf459896a8b7e1da8863b0485 to your computer and use it in GitHub Desktop.
Saves poster images from Plex to same folder as the media files.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
Description: Saves poster images from Plex to same folder as the media files.
Author: /u/SwiftPanda16
Requires: plexapi, tqdm (optional)
Usage:
* Save posters for an entire library:
python save_posters.py --library "Movies"
* Save posters for a specific media type in a library:
python save_posters.py --library "TV Shows" --libtype season
* Save posters for a specific item:
python save_posters.py --rating_key 1234
'''
import argparse
from pathlib import Path
from plexapi.server import PlexServer
from plexapi.utils import download
PLEX_URL = 'http://localhost:32400'
PLEX_TOKEN = 'XXXXXXXXXXXXXXXXXXXX'
# Specify the mapped docker folder paths {host: container}. Leave blank {} if non-docker.
MAPPED_FOLDERS = {
'/mnt/movies': '/movies',
'/mnt/tvshows': '/tv',
}
_MAPPED_FOLDERS = {Path(host): Path(container) for host, container in MAPPED_FOLDERS.items()}
def map_path(file_path):
for host, container in _MAPPED_FOLDERS.items():
if container in file_path.parents:
return host / file_path.relative_to(container)
return file_path
def save_posters_library(library, libtype=None):
for item in library.all(libtype=libtype, includeGuids=False):
save_posters_item(item)
def save_posters_item(item):
if hasattr(item, 'locations'):
file_path = Path(item.locations[0])
else:
file_path = Path(next(iter(item)).locations[0])
poster_path = map_path(file_path)
if poster_path.is_file():
poster_path = poster_path.parent
print(f"Downloading poster for {item.title} to {poster_path}")
try:
download(
url=item.posterUrl,
token=plex._token,
filename='poster.jpg',
savepath=poster_path,
showstatus=True # Requires `tqdm` package
)
except Exception as e:
print(f"Failed to download poster for {item.title}: {e}")
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--rating_key', type=int)
parser.add_argument('--library')
parser.add_argument('--libtype', choices=['movie', 'show', 'season', 'artist', 'album'])
opts = parser.parse_args()
plex = PlexServer(PLEX_URL, PLEX_TOKEN)
if opts.rating_key:
item = plex.fetchItem(opts.rating_key)
save_posters_item(item)
elif opts.library:
library = plex.library.section(opts.library)
save_posters_library(library, opts.libtype)
else:
print("No --rating_key or --library specified. Exiting.")
@Healzangels
Copy link

Greetings!

Came across this script and sounds like exactly what I was looking for to save some of the custom artwork I've uploaded to Plex but never saved a local copy of.

I was attempting to use the script directly through Tautulli which may be part of the problem I was running into.
After updating the script to include my docker path locations/token etc found I was running into the following error when attempting a test run. (Removed movie name)

Tautulli Notifiers :: Script returned: Downloading poster for A Movie to /mnt/user/data/media/movies/A Movie (2013)/A Movie (2013).mkv Failed to download poster for A Movie: [Errno 13] Permission denied: '/mnt/user'

For my specified mapped folders I have the following.

MAPPED_FOLDERS = { '/mnt/user/data/': '/data', }

I've also mapped this location to my Tautulli docker container as well (Not totally sure if necessary)

From the error of course seems to be permissions related but unsure which permission level it is looking for and it's it's truly on the /mnt/user/ level as not keen on changing the permissions on such a high level of the folder tree.

Again maybe trying to run through Tautuilli is adding some unneeded complexity or I've over looked something simple.

Thanks again for sharing such an awesome sound script, really excited to get it working!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment