2019-10-27 22:58:42 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
#
|
|
|
|
# Description: Automatically change episode artwork in Plex to hide spoilers.
|
|
|
|
# Author: /u/SwiftPanda16
|
|
|
|
# Requires: plexapi, requests
|
|
|
|
# Tautulli script trigger:
|
|
|
|
# * Notify on recently added
|
|
|
|
# * Notify on watched (optional - to remove the artwork after being watched)
|
|
|
|
# Tautulli script conditions:
|
|
|
|
# * Condition {1}:
|
2021-07-02 23:02:22 +00:00
|
|
|
# [Media Type | is | show or season or episode]
|
2019-10-27 22:58:42 +00:00
|
|
|
# * Condition {2} (optional):
|
|
|
|
# [ Library Name | is | DVR ]
|
|
|
|
# [ Show Namme | is | Game of Thrones ]
|
|
|
|
# Tautulli script arguments:
|
|
|
|
# * Recently Added:
|
|
|
|
# To use an image file (can be image in the same directory as this script, or full path to an image):
|
2021-07-02 23:02:22 +00:00
|
|
|
# --rating_key {rating_key} --image spoilers.png
|
2019-10-27 22:58:42 +00:00
|
|
|
# To blur the episode artwork (optional blur in pixels):
|
2021-07-02 23:02:22 +00:00
|
|
|
# --rating_key {rating_key} --blur 25
|
2021-07-29 13:14:10 +00:00
|
|
|
# To add a prefix to the summary (optional string prefix):
|
2021-07-29 01:25:54 +00:00
|
|
|
# --rating_key {rating_key} --summary_prefix "** SPOILERS **"
|
2019-10-27 22:58:42 +00:00
|
|
|
# * Watched (optional):
|
2021-07-02 23:02:22 +00:00
|
|
|
# --rating_key {rating_key} --remove
|
2021-11-23 05:38:41 +00:00
|
|
|
# Note:
|
|
|
|
# * "Use local assets" must be enabled for the library in Plex (Manage Library > Edit > Advanced > Use local assets).
|
2019-10-27 22:58:42 +00:00
|
|
|
|
|
|
|
import argparse
|
|
|
|
import os
|
|
|
|
import requests
|
|
|
|
import shutil
|
|
|
|
from plexapi.server import PlexServer
|
|
|
|
|
|
|
|
PLEX_URL = ''
|
|
|
|
PLEX_TOKEN = ''
|
|
|
|
|
|
|
|
# Environmental Variables
|
|
|
|
PLEX_URL = os.getenv('PLEX_URL', PLEX_URL)
|
|
|
|
PLEX_TOKEN = os.getenv('PLEX_TOKEN', PLEX_TOKEN)
|
|
|
|
|
|
|
|
|
2021-11-23 05:38:41 +00:00
|
|
|
def modify_episode_artwork(rating_key, image=None, blur=None, summary_prefix=None, remove=False):
|
2021-07-02 23:02:22 +00:00
|
|
|
plex = PlexServer(PLEX_URL, PLEX_TOKEN)
|
2021-11-23 05:38:41 +00:00
|
|
|
item = plex.fetchItem(rating_key)
|
2021-07-28 22:32:29 +00:00
|
|
|
|
2021-07-02 23:02:22 +00:00
|
|
|
if item.type == 'show':
|
|
|
|
episodes = item.episodes()
|
|
|
|
elif item.type == 'season':
|
|
|
|
episodes = item.episodes()
|
|
|
|
elif item.type == 'episode':
|
|
|
|
episodes = [item]
|
|
|
|
else:
|
|
|
|
print('Only media type show, season, or episode is supported: '
|
|
|
|
'{item.title} ({item.ratingKey}) is media type {item.type}.'.format(item=item))
|
2021-11-23 05:38:41 +00:00
|
|
|
return
|
2019-12-19 22:09:58 +00:00
|
|
|
|
2021-07-02 23:02:22 +00:00
|
|
|
for episode in episodes:
|
|
|
|
for part in episode.iterParts():
|
|
|
|
episode_filepath = part.file
|
|
|
|
episode_folder = os.path.dirname(episode_filepath)
|
|
|
|
episode_filename = os.path.splitext(os.path.basename(episode_filepath))[0]
|
2021-07-28 22:32:29 +00:00
|
|
|
|
2021-11-23 05:38:41 +00:00
|
|
|
if remove:
|
2021-07-02 23:02:22 +00:00
|
|
|
# Find image files with the same name as the episode
|
|
|
|
for filename in os.listdir(episode_folder):
|
|
|
|
if filename.startswith(episode_filename) and filename.endswith(('.jpg', '.png')):
|
|
|
|
# Delete the episode artwork image file
|
|
|
|
os.remove(os.path.join(episode_folder, filename))
|
2019-12-19 22:09:58 +00:00
|
|
|
|
2021-07-29 01:25:00 +00:00
|
|
|
# Unlock the summary so it will get updated on refresh
|
2021-07-28 22:32:29 +00:00
|
|
|
episode.edit(**{'summary.locked': 0})
|
|
|
|
continue
|
|
|
|
|
2021-11-23 05:38:41 +00:00
|
|
|
if image:
|
2021-07-02 23:02:22 +00:00
|
|
|
# File path to episode artwork using the same episode file name
|
2021-11-23 05:38:41 +00:00
|
|
|
episode_artwork = os.path.splitext(episode_filepath)[0] + os.path.splitext(image)[1]
|
2021-07-02 23:02:22 +00:00
|
|
|
# Copy the image to the episode artwork
|
2021-11-23 05:38:41 +00:00
|
|
|
shutil.copy2(image, episode_artwork)
|
2021-07-28 22:32:29 +00:00
|
|
|
|
2021-11-23 05:38:41 +00:00
|
|
|
elif blur:
|
2021-07-02 23:02:22 +00:00
|
|
|
# File path to episode artwork using the same episode file name
|
|
|
|
episode_artwork = os.path.splitext(episode_filepath)[0] + '.png'
|
2021-11-23 05:38:41 +00:00
|
|
|
# Get the blurred artwork
|
|
|
|
image_url = plex.transcodeImage(
|
|
|
|
episode.thumbUrl,
|
|
|
|
height=270,
|
|
|
|
width=480,
|
|
|
|
blur=blur,
|
|
|
|
imageFormat='png'
|
|
|
|
)
|
|
|
|
r = requests.get(image_url, stream=True)
|
|
|
|
if r.status_code == 200:
|
|
|
|
r.raw.decode_content = True
|
2021-07-02 23:02:22 +00:00
|
|
|
# Copy the image to the episode artwork
|
|
|
|
with open(episode_artwork, 'wb') as f:
|
2021-11-23 05:38:41 +00:00
|
|
|
shutil.copyfileobj(r.raw, f)
|
2021-07-02 23:02:22 +00:00
|
|
|
|
2021-11-23 05:38:41 +00:00
|
|
|
if summary_prefix and not episode.summary.startswith(summary_prefix):
|
2021-07-29 01:25:00 +00:00
|
|
|
# Use a zero-width space (\u200b) for blank lines
|
|
|
|
episode.edit(**{
|
2021-11-23 05:38:41 +00:00
|
|
|
'summary.value': summary_prefix + '\n\u200b\n' + episode.summary,
|
2021-07-29 01:25:00 +00:00
|
|
|
'summary.locked': 1
|
|
|
|
})
|
2021-07-28 22:32:29 +00:00
|
|
|
|
2021-07-02 23:02:22 +00:00
|
|
|
# Refresh metadata for the episode
|
|
|
|
episode.refresh()
|
2021-11-23 05:38:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
parser.add_argument('--rating_key', required=True, type=int)
|
|
|
|
parser.add_argument('--image')
|
|
|
|
parser.add_argument('--blur', type=int, default=25)
|
|
|
|
parser.add_argument('--summary_prefix', nargs='?', const='** SPOILERS **')
|
|
|
|
parser.add_argument('--remove', action='store_true')
|
|
|
|
opts = parser.parse_args()
|
|
|
|
|
|
|
|
modify_episode_artwork(**vars(opts))
|