diff --git a/untested scripts/plex-analyze-cli.py b/untested scripts/plex-analyze-cli.py new file mode 100644 index 0000000..6ab2d4f --- /dev/null +++ b/untested scripts/plex-analyze-cli.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +# Plex analayze all files that are missing analyzation info +# OS: Ubunti 16.04 ( in case of other OS's make sure to change paths ) + +from subprocess import call +import os +import requests +import sqlite3 +import sys + +conn = sqlite3.connect('/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-in Support/Databases/com.plexapp.plugins.library.db') + +c = conn.cursor() +c.execute('Select media_items.metadata_item_id As id, metadata_items.title As title From media_items Inner Join metadata_items On media_items.metadata_item_id = metadata_items.id Where media_items.bitrate Is Null And Not metadata_items.metadata_type = "12"') +items = c.fetchall() +conn.close() + +print("To analyze: " + str( len(items) )) + +for row in items: + os.system('LD_LIBRARY_PATH=/usr/lib/plexmediaserver PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR=/var/lib/plexmediaserver/Library/Application\ Support /usr/lib/plexmediaserver/Plex\ Media\ Scanner -a -o ' + str(row[0])) + os.system('sleep 1') + print(str(row[0])) diff --git a/untested scripts/plex-analyze-curl.py b/untested scripts/plex-analyze-curl.py new file mode 100644 index 0000000..69851f0 --- /dev/null +++ b/untested scripts/plex-analyze-curl.py @@ -0,0 +1,21 @@ +# Plex analayze all files that are missing analyzation info using CURL calls +# OS: Ubunti 16.04 ( in case of other OS's make sure to change paths ) +# Replace xxx with your plex token, you can get it by: +# grep -E -o "PlexOnlineToken=.{0,22}" /var/lib/plexmediaserver/Library/Application\ Support/Plex\ Media\ Server/Preferences.xml + +#!/usr/bin/env python3 +import requests +import sqlite3 + +conn = sqlite3.connect('/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-in Support/Databases/com.plexapp.plugins.library.db') + +c = conn.cursor() +c.execute('select metadata_item_id from media_items where bitrate is null') +items = c.fetchall() +conn.close() + +print("To analyze: " + str( len(items) )) +for row in items: + requests.put(url='http://127.0.0.1:32400/library/metadata/' + str(row[0]) + '/analyze?X-Plex-Token=xxx') + requests.get(url='http://127.0.0.1:32400/library/metadata/' + str(row[0]) + '/refresh?X-Plex-Token=xxx') + print(str(row[0])) diff --git a/untested scripts/plex-analyzedeeply-cli.py b/untested scripts/plex-analyzedeeply-cli.py new file mode 100644 index 0000000..35bd369 --- /dev/null +++ b/untested scripts/plex-analyzedeeply-cli.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +# analyzedeeply.cli will preform deep analyzation only on files that were not processed yet +from subprocess import call +import os +import requests +import sqlite3 +import sys +import time + +conn = sqlite3.connect('/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-in Support/Databases/com.plexapp.plugins.library.db') + +c = conn.cursor() +c.execute('select meta.id from metadata_items meta \ +join media_items media on media.metadata_item_id = meta.id \ +join media_parts part on part.media_item_id = media.id \ +where part.extra_data not like "%deepAnalysisVersion=2%" \ +and meta.metadata_type in (1, 4, 12) and part.file != "";') + +items = c.fetchall() +conn.close() + +print("ANALYZE DEEPLY START") +print("Number of video files to process: " + str( len(items) )) +start_time = time.time() + +for row in items: + print ("Processing video id: " + str(row[0])) + start_row = time.time() + os.system('LD_LIBRARY_PATH=/usr/lib/plexmediaserver \ + PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR=/var/lib/plexmediaserver/Library/Application\ Support \ + /usr/lib/plexmediaserver/Plex\ Media\ Scanner --analyze-deeply -o ' + str(row[0])) + end_row = time.time() + print ("Video id:" + str(row[0]) + " took {:.2f} seconds to process".format(end_row - start_row)) +end_time = time.time() +print ("Files proccessed:" + str(row[0]) + " in {:.2f} seconds".format(end_row - start_row)) diff --git a/untested scripts/plex-folder-scan-sh b/untested scripts/plex-folder-scan-sh new file mode 100644 index 0000000..2fc1bab --- /dev/null +++ b/untested scripts/plex-folder-scan-sh @@ -0,0 +1,26 @@ +#!/bin/bash +## PLEX FOLDER SCAN +## UPDATE PATHS AND PLEX SECTION +MOVIELIBRARY="/mnt/cloud/movies/" +MOVIESECTION=2 +TVLIBRARY="/mnt/cloud/series/" +TVSECTION=1 + +export LD_LIBRARY_PATH=/usr/lib/plexmediaserver +export PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR=/var/lib/plexmediaserver/Library/Application\ Support + +if [[ -z "$1" ]]; then + echo "Usage /path to script/plex-scan-folder.sh /full path/to media/" + echo "CURRENT SCRIPT SETTINGS" + echo "Movie path: $MOVIELIBRARY | Section: $MOVIESECTION" + echo "TV path : $TVLIBRARY | Section: $TVSECTION" + echo "List of Plex Library Sections" + $LD_LIBRARY_PATH/Plex\ Media\ Scanner --list +elif [[ $1 == "$MOVIELIBRARY"* ]]; then + $LD_LIBRARY_PATH/Plex\ Media\ Scanner --scan --refresh --section $MOVIESECTION --directory "$1" +elif [[ $1 == "$TVLIBRARY"* ]]; then + $LD_LIBRARY_PATH/Plex\ Media\ Scanner --scan --refresh --section $TVSECTION --directory "$1" +else + echo "$1 does not contain movie or tv path" +fi +exit diff --git a/untested scripts/plex-list-matched-wrong.sh b/untested scripts/plex-list-matched-wrong.sh new file mode 100644 index 0000000..724b474 --- /dev/null +++ b/untested scripts/plex-list-matched-wrong.sh @@ -0,0 +1,136 @@ +#!/bin/bash +## The function of this script is to show you possible wrongly maateched movies in Plex Media Server +## Copy paste URL result in broser and use Plex feature: Fix Matched +## +## Setup +## 1. chmod a+x plex-matched-wrong.sh +## 2. Set correct paths in variables +## +## More scripts at: https://github.com/ajkis/scripts +## If you find script useful feel free to buy me a beer at https://paypal.me/ajki + +if pidof -o %PPID -x "$0"; then + exit 1 +fi +LOGFILE="/home/plex/logs/pmsmatchwrong.log" +DB="/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-in Support/Databases/com.plexapp.plugins.library.db" +PLEXURL="http://XXX:32400/web/index.html#!/server/XXX/details?key=%2Flibrary%2Fmetadata%2F" +export LD_LIBRARY_PATH=/usr/lib/plexmediaserver +export PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR=/var/lib/plexmediaserver/Library/Application\ Support +MOVIESSECTION=1 # SET PLEX SECTION FOR MOVIES + +echo "Plex Libraries" +$LD_LIBRARY_PATH/Plex\ Media\ Scanner --list + +echo "Script movie section setting: $MOVIESSECTION" +read -n1 -r -p "Press space/enter to continue or any other key to exit..." key +if [ "$key" != '' ]; then + echo " " + echo "EXIT: Aborted" + exit +fi + +if [[ -f $LOGFILE ]]; then + rm -f $LOGFILE +fi + +qcase1=" \ +with \ + movies_only as ( \ + select * \ + from metadata_items \ + where library_section_id = $MOVIESSECTION \ + and title <> '' \ + ), \ + duplicates as ( \ + select * \ + from movies_only \ + where title || year in ( \ + select t_y \ + from ( \ + select title || year as t_y, count(*) N \ + from movies_only \ + group by title || year \ + ) as x \ + where N >= 2 \ + ) \ + ) \ +select \ + duplicates.id as metadata_items_id, \ + duplicates.title as metadata_items_title, \ + media_parts.file as media_parts_file \ +from duplicates \ +join media_items \ + on media_items.metadata_item_id = duplicates.id \ +join media_parts \ + on media_parts.media_item_id = media_items.id \ +order by duplicates.title \ +" + +qcase2="with \ + movies_only as ( \ + select * \ + from metadata_items \ + where library_section_id = $MOVIESSECTION \ + and title <> '' \ + ), \ + duplicates as ( \ + select * \ + from movies_only \ + where title || year in ( \ + select t_y \ + from ( \ + select title || year as t_y, count(*) N \ + from movies_only \ + group by title || year \ + ) as x \ + where N >= 1 \ + ) \ + ), \ + merged as ( \ + select \ + duplicates.id as metadata_items_id, \ + duplicates.title as metadata_items_title, \ + media_parts.file as media_parts_file \ + from duplicates \ + join media_items \ + on media_items.metadata_item_id = duplicates.id \ + join media_parts \ + on media_parts.media_item_id = media_items.id \ + ) \ +select * \ +from merged \ +where media_parts_file not like '%' || replace(replace(replace(replace(metadata_items_title, ':', ''), '...', ''), '?', ''), ' ', ' ') || '%' \ +order by metadata_items_title \ +" + +readarray -t case1 < <(sqlite3 "$DB" "$qcase1") +readarray -t case2 < <(sqlite3 "$DB" "$qcase2") + +echo "POSSIBLY WRONLGY MATCHED MOVIES WHERE TITLE IS NOT UNIQUE" | tee -a $LOGFILE +echo "One of the results is correct, check based on file name and manually fix second one" +echo "Copy paste URL in browser and use Fix Match" +sqlite3 "$DB" "$query1" | + +for result in "${case1[@]}" +do + echo "$result" | tee -a $LOGFILE + result=$(echo $result | cut -d "|" -f1) + echo "URL: ${PLEXURL}$result" | tee -a $LOGFILE + echo " " | tee -a $LOGFILE +done +echo " " | tee -a $LOGFILE + +echo "POSSIBLY WRONLGY MATCHED MOVIES WHERE PLEX TITLE IS NOT PRESENT IN FOLDER OR FILE NAME" | tee -a $LOGFILE +echo "Copy paste URL in browser and use Fix Match" | tee -a $LOGFILE +for result in "${case2[@]}" +do + echo "$result" | tee -a $LOGFILE + result=$(echo $result | cut -d "|" -f1) + echo "URL: ${PLEXURL}$result" | tee -a $LOGFILE + echo " " | tee -a $LOGFILE +done + +echo "Finished, all results are logged in: $LOGFILE" + +exit diff --git a/untested scripts/plex-scan-new.sh b/untested scripts/plex-scan-new.sh new file mode 100644 index 0000000..1b64d44 --- /dev/null +++ b/untested scripts/plex-scan-new.sh @@ -0,0 +1,79 @@ +#!/bin/bash +## PLEX SCAN ONLY NEW/MODIFED FOLDERS SINCE LAST RUN +## OS: Linux Ubuntu 16.04 +## Make script executable by chmod a+x plex-scan-new.sh +## Add script to crontab -e ( paste the line bellow without ## ) +## */30 * * * * /path to script/plex-scan-new.sh >/dev/null 2>&1 +## Make sure you disable all Plex automatic & scheduled library scans. +if pidof -o %PPID -x "$0"; then + echo "$(date "+%d.%m.%Y %T") Exit, already running." + exit 1 +fi + +#SETTINGS +MOVIELIBRARY="/mnt/cloud/movies/" +MOVIESECTION=2 +TVLIBRARY="/mnt/cloud/series/" +TVSECTION=1 +LOGFILE="/home/plex/logs/plex-scan-new.log" +FOLDERLISTFILE="/home/plex/.cache/folderlistfile" +LASTRUNFILE="/home/plex/.cache/lastrunfile" + + +export LD_LIBRARY_PATH=/usr/lib/plexmediaserver +export PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR=/var/lib/plexmediaserver/Library/Application\ Support + +if [[ ! -f "$LASTRUNFILE" ]]; then + touch $LASTRUNFILE +fi +echo "$(date "+%d.%m.%Y %T") PLEX SCAN FOR NEW/MODIFIED FILES AFTER: $(date -r $LASTRUNFILE)" + +if [[ -f "$FOLDERLISTFILE" ]]; then + echo "Removing previous folder list" + rm $FOLDERLISTFILE +fi + +start=$(date +'%s') +startmovies=$(date +'%s') +echo "Scaning for new files: $MOVIELIBRARY" +find "$MOVIELIBRARY" -mindepth 1 -type f -cnewer $LASTRUNFILE | +while read mfile; do + echo "$(date "+%d.%m.%Y %T") New file detected: $mfile" | tee -a "$LOGFILE" + MFOLDER=$(dirname "${mfile}") + echo "$MFOLDER" | tee -a "$FOLDERLISTFILE" +done +echo "$(date "+%d.%m.%Y %T") Movie files scanned in $(($(date +'%s') - $startmovies)) seconds" | tee -a "$LOGFILE" + +startseries=$(date +'%s') +echo "Scaning for new files: $TVLIBRARY" +find "$TVLIBRARY" -mindepth 2 -type f -cnewer $LASTRUNFILE | +while read tvfile; do + echo "$(date "+%d.%m.%Y %T") New file detected: $tvfile" | tee -a "$LOGFILE" + TVFOLDER=$(dirname "${tvfile}") + echo "$TVFOLDER" | tee -a "$FOLDERLISTFILE" +done +echo "$(date "+%d.%m.%Y %T") TV folders scanned in $(($(date +'%s') - $startseries)) seconds" | tee -a "$LOGFILE" + +echo "$(date "+%d.%m.%Y %T") Move & TV folders scanned in $(($(date +'%s') - $start)) seconds" | tee -a "$LOGFILE" +echo "$(date "+%d.%m.%Y %T") Setting lastrun for next folder scans" | tee -a "$LOGFILE" +touch $LASTRUNFILE +echo "$(date "+%d.%m.%Y %T") Remove duplicates" | tee -a "$LOGFILE" +sort "$FOLDERLISTFILE" | uniq | tee "$FOLDERLISTFILE" + +startplexscan=$(date +'%s') +echo "$(date "+%d.%m.%Y %T") Plex scan started" | tee -a "$LOGFILE" +readarray -t FOLDERS < "$FOLDERLISTFILE" +for FOLDER in "${FOLDERS[@]}" +do + if [[ $FOLDER == "$MOVIELIBRARY"* ]]; then + echo "$(date "+%d.%m.%Y %T") Plex scan movie folder:: $FOLDER" | tee -a "$LOGFILE" + $LD_LIBRARY_PATH/Plex\ Media\ Scanner --scan --refresh --section "$MOVIESECTION" --directory "$FOLDER" | tee -a "$LOGFILE" + elif [[ $FOLDER == "$TVLIBRARY"* ]]; then + echo "$(date "+%d.%m.%Y %T") Plex scan TV folder: $FOLDER" | tee -a "$LOGFILE" + $LD_LIBRARY_PATH/Plex\ Media\ Scanner --scan --refresh --section "$TVSECTION" --directory "$FOLDER" | tee -a "$LOGFILE" + fi +done +echo "$(date "+%d.%m.%Y %T") Plex scan finished in $(($(date +'%s') - $startplexscan)) seconds" | tee -a "$LOGFILE" + +echo "$(date "+%d.%m.%Y %T") Scan completed in $(($(date +'%s') - $start)) seconds" | tee -a "$LOGFILE" +exit diff --git a/untested scripts/plexgeneratefolderlist.sh b/untested scripts/plexgeneratefolderlist.sh new file mode 100644 index 0000000..684d6a0 --- /dev/null +++ b/untested scripts/plexgeneratefolderlist.sh @@ -0,0 +1,55 @@ +#!/bin/bash +## THIS SCRIPT WILL GENERATE FOLDER LIST BEFORE UPLOADING WITH RCLONE. +## THE SECOND SCRIPT PLEXREFRESHFOLDERS WILL RUN PLEX SCANNER ONLY ON GENERATED FOLDERS. +## FOLDER LIST WILL HAVE LOCAL PATH REPLACED WITH UNIONFS ONES + +# EXIT IF SCRIPT IF ALREADY RUNNING +if pidof -o %PPID -x "$0"; then + echo "$(date "+%d.%m.%Y %T") Already running, exiting." + exit 1 +fi + +TIMESTAMP=`date +%Y-%m-%d_%H-%M-%S` +LOGFILE="/home/plex/logs/local2acdcrypt.cron.log" +MOVIES="/storage/local/movies" +SERIES="/storage/local/series" +LOCALPATH="/storage/local/" +UNIONFSPATH="/mnt/unionfs/" +RCLONEREMOTE="acdcrypt:" +MINFOLDERAGE="15" # MINIMUM FOLDER AGE IN MINUTES. SCRIPT WILL ONLY STARTED WHEN THERE IS A MATCH + + +readarray -t MOVIEFOLDERS < <(find "$MOVIES" -mindepth 1 -type d -mmin +$MINFOLDERAGE -not -iname '*.partial*') +readarray -t SERIESFOLDERS < <(find "$SERIES" -mindepth 2 -type d -mmin +$MINFOLDERAGE -not -iname '*.partial*') +readarray -t UPLOAD < <(find "$LOCALPATH" -mindepth 1 -type f -mmin +$MINFOLDERAGE -not -path '*/\.*' -not -iname '*.partial*') + +if [[ -n $UPLOAD ]]; then + start=$(date +'%s') + echo "$(date "+%d.%m.%Y %T") START" | tee -a "$LOGFILE" + # RCLONE MOVE FILES ( CHANGE TO YOUR PATHS ) + /usr/bin/rclone move $LOCALPATH $RCLONEREMOTE -v --no-traverse --transfers=20 --checkers=20 --delete-after --min-age ${MINFOLDERAGE}m --stats 30s --log-file=$LOGFILE + + #GENERATE AND UPLOAD PLEX.LIST + for mfolder in "${MOVIEFOLDERS[@]}" + do + if [[ $mfolder == *"/movies/"* ]] ; then # Change /movies/ to match your path + MREFRESHFOLDER="${mfolder/$LOCALPATH/$UNIONFSPATH}" # Change path from /storage/local/ to /mnt/unionfs + echo "Adding to plex.list: $MREFRESHFOLDER" | tee -a "$LOGFILE" + echo "$MREFRESHFOLDER" >>/home/plex/.cache/$TIMESTAMP-plex.list + fi + done + for sfolder in "${SERIESFOLDERS[@]}" + do + if [[ $sfolder == *"/series/"* ]] ; then # Change /series/ to match your path + SREFRESHFOLDER="${sfolder/$LOCALPATH/$UNIONFSPATH}" # Change path from /storage/local/ to /mnt/unionfs + echo "Adding to plex.list: $SREFRESHFOLDER" | tee -a "$LOGFILE" + echo "$SREFRESHFOLDER" >>/home/plex/.cache/$TIMESTAMP-plex.list + fi + done + if [[ -f /home/plex/.cache/$TIMESTAMP-plex.list ]]; then + echo "Uploading: $TIMESTAMP-plex.list" | tee -a "$LOGFILE" + /usr/bin/rclone move /home/plex/.cache/$TIMESTAMP-plex.list $RCLONEREMOTE/tmp/ -v --no-traverse --log-file=$LOGFILE #Change acdcrypt: to match your remote + fi + echo "$(date "+%d.%m.%Y %T") ENDED in $(($(date +'%s') - $start)) seconds" | tee -a "$LOGFILE" +fi +exit diff --git a/untested scripts/plexrefreshfolderlist.sh b/untested scripts/plexrefreshfolderlist.sh new file mode 100644 index 0000000..fbe1b48 --- /dev/null +++ b/untested scripts/plexrefreshfolderlist.sh @@ -0,0 +1,52 @@ +#!/bin/bash +## THIS SCRIPT WILL RUN PLEX SCANNER ONLY ON FOLDERS PREVIOUSLY GENERATED BY plexgeneratefolderlist.sh + +if pidof -o %PPID -x "$0"; then + echo "$(date "+%d.%m.%Y %T") Exit, already running." + exit 1 +fi +TIMESTAMP=`date +%Y-%m-%d_%H-%M-%S` +LOGFILE="/home/plex/logs/plexrefresh.cron.log" +UNIONFSPATH="/mnt/unionfs" +RCLONEREMOTE="acdcrypt:" +PLEXLIST="${UNIONFSPATH}/tmp/ " +CACHE="/home/plex/.cache/" +TVSECTION=1 +MOVIESECTION=2 + +export LD_LIBRARY_PATH=/usr/lib/plexmediaserver +export PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR=/var/lib/plexmediaserver/Library/Application\ Support + +# EXIT IF THERE ARE NO PLEX LIST FILES +if [[ -z $(find $PLEXLISTPATH -type f -iname "*.list" -mmin +1) ]];then + echo "Exit: No list available" + exit +fi +# FIND LISTS, MERGE INTO ONE FILE AND DELETE RLONE REMOTE +find $PLEXLISTPATH -type f -iname "*.list" -mmin +1 | +while read FILEPATH; do + cat $FILEPATH >> ${CACHE}$TIMESTAMP-plex.list + FILE=$(basename "${FILEPATH}") + /usr/bin/rclone delete ${RCLONEPATH2LIST}{$FILE} +done + +# REMOVE DUPLICATE FOLDERS +sort $CACHE/$TIMESTAMP-plex.list | uniq | tee $CACHE/$TIMESTAMP-plex.list > /dev/null + +# PLEX SCAN NEW FOLDERS +readarray -t FOLDERS < ${CACHE}$TIMESTAMP-plex.list +for FOLDER in "${FOLDERS[@]}" +do + if [[ $FOLDER == *"/movies/"* ]] ; then + echo "$(date "+%d.%m.%Y %T") Refreshing movie folder: $FOLDER" | tee -a "$LOGFILE" + ${LD_LIBRARY_PATH}/Plex\ Media\ Scanner --scan --refresh --section $MOVIESECTION --directory "${FOLDER}" | tee -a "$LOGFILE" + fi + if [[ $FOLDER == *"/series/"* ]] ; then + echo "$(date "+%d.%m.%Y %T") Refreshing serie folder: $FOLDER" | tee -a "$LOGFILE" + ${LD_LIBRARY_PATH}/Plex\ Media\ Scanner --scan --refresh --section $TVSECTION --directory "${FOLDER}" | tee -a "$LOGFILE" + fi +done +# ADD SUFFIX DONE TO THE FINISHED LIST +echo "$TIMESTAMP-plex.list.done" | tee -a "$LOGFILE" +mv ${CACHE}$TIMESTAMP-plex.list ${CACHE}$TIMESTAMP-plex.list.done +exit