JBOPS/utility/plex_dance.py
2020-07-04 13:31:02 -07:00

174 lines
5.7 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Description: Do the Plex Dance!
Author: Blacktwin, SwiftPanda16
Requires: plexapi, requests
Original Dance moves
1. Move all files for the media item out of the directory your Library is looking at,
so Plex will not “see” it anymore
2. Scan the library (to detect changes)
3. Empty trash
4. Clean bundles
5. Double check naming schema and move files back
6. Scan the library
https://forums.plex.tv/t/the-plex-dance/197064
Script Dance moves
1. Create .plexignore file in affected items library root
.plexignore will contain:
# Ignoring below file for Plex Dance
*Item_Root/*
- if .plexignore file already exists in library root, append contents
2. Scan the library
3. Empty trash
4. Clean bundles
5. Remove or restore .plexignore
6. Scan the library
7. Optimize DB
Example:
Dance with rating key 110645
plex_dance.py --ratingKey 110645
From Unraid host OS
plex_dance.py --ratingKey 110645 --path /mnt/user
*Dancing only works with Show or Movie rating keys
**After Dancing, if you use Tautulli the rating key of the dancing item will have changed.
Please use this script to update your Tautulli database with the new rating key
https://gist.github.com/JonnyWong16/f554f407832076919dc6864a78432db2
"""
from __future__ import print_function
from __future__ import unicode_literals
from plexapi.server import PlexServer
from plexapi.server import CONFIG
import requests
import argparse
import time
import os
# Using CONFIG file
PLEX_URL = ''
PLEX_TOKEN = ''
IGNORE_FILE = "# Ignoring below file for Plex Dance\n{}"
if not PLEX_TOKEN:
PLEX_TOKEN = CONFIG.data['auth'].get('server_token')
if not PLEX_URL:
PLEX_URL = CONFIG.data['auth'].get('server_baseurl')
session = requests.Session()
# Ignore verifying the SSL certificate
session.verify = False # '/path/to/certfile'
# If verify is set to a path to a directory,
# the directory must have been processed using the c_rehash utility supplied
# with OpenSSL.
if session.verify is False:
# Disable the warning that the request is insecure, we know that...
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
plex = PlexServer(PLEX_URL, PLEX_TOKEN, session=session)
def section_path(section, filepath):
for location in section.locations:
if filepath.startswith(location):
return location
def refresh_section(sectionID):
plex = PlexServer(PLEX_URL, PLEX_TOKEN, session=session)
section = plex.library.sectionByID(sectionID)
section.update()
time.sleep(10)
plex = PlexServer(PLEX_URL, PLEX_TOKEN, session=session)
section = plex.library.sectionByID(sectionID)
while section.refreshing is True:
time.sleep(10)
print("Waiting for library to finish refreshing to continue dance.")
plex = PlexServer(PLEX_URL, PLEX_TOKEN, session=session)
section = plex.library.sectionByID(sectionID)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Do the Plex Dance!",
formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument('--ratingKey', nargs="?", type=int, required=True,
help='Rating key of item that needs to dance.')
parser.add_argument('--path', nargs="?", type=str,
help='Prefix path for libraries behind mount points.\n'
'Example: /mnt/user Resolves: /mnt/user/library_root')
opts = parser.parse_args()
item = plex.fetchItem(opts.ratingKey)
item.reload()
sectionID = item.librarySectionID
section = plex.library.sectionByID(sectionID)
old_plexignore = ''
if item.type == 'movie':
item_file = item.media[0].parts[0].file
locations = os.path.split(item.locations[0])
item_root = os.path.split(locations[0])[1]
library_root = section_path(section, locations[0])
elif item.type == 'show':
locations = os.path.split(item.locations[0])
item_root = locations[1]
library_root = section_path(section, locations[0])
else:
print("Media type not supported.")
exit()
library_root = opts.path + library_root if opts.path else library_root
plexignore = IGNORE_FILE.format('*' + item_root + '/*')
item_ignore = os.path.join(library_root, '.plexignore')
# Check for existing .plexignore file in library root
if os.path.exists(item_ignore):
# If file exists append new ignore params and store old params
with open(item_ignore, 'a+') as old_file:
old_plexignore = old_file.readlines()
old_file.write('\n' + plexignore)
# 1. Create .plexignore file
print("Creating .plexignore file for dancing.")
with open(item_ignore, 'w') as f:
f.write(plexignore)
# 2. Scan library
print("Refreshing library of dancing item.")
refresh_section(sectionID)
# 3. Empty library trash
print("Emptying Trash from library.")
section.emptyTrash()
time.sleep(5)
# 4. Clean library bundles
print("Cleaning Bundles from library.")
plex.library.cleanBundles()
time.sleep(5)
# 5. Remove or restore .plexignore
if old_plexignore:
print("Replacing new .plexignore with old .plexignore.")
with open(item_ignore, 'w') as new_file:
new_file.writelines(old_plexignore)
else:
print("Removing .plexignore file from dancing directory.")
os.remove(item_ignore)
# 6. Scan library
print("Refreshing library of dancing item.")
refresh_section(sectionID)
# 7. Optimize DB
print("Optimizing library database.")
plex.library.optimize()