mirror of
https://github.com/acedanger/shell.git
synced 2025-12-06 02:20:11 -08:00
added the ability to initiate a plex library scan from the CLI. tab completions are supported as well.
This commit is contained in:
770
plex/scan-plex-libraries.sh
Executable file
770
plex/scan-plex-libraries.sh
Executable file
@@ -0,0 +1,770 @@
|
||||
#!/bin/bash
|
||||
|
||||
################################################################################
|
||||
# Plex Library Scanner Script
|
||||
################################################################################
|
||||
#
|
||||
# Author: Peter Wood <peter@peterwood.dev>
|
||||
# Description: Command-line interface for Plex Media Scanner operations.
|
||||
# Provides library scanning, metadata refresh, and analysis
|
||||
# capabilities with styled output and error handling.
|
||||
#
|
||||
# Features:
|
||||
# - List all Plex libraries with section IDs
|
||||
# - Scan specific libraries or all libraries for new media
|
||||
# - Force refresh metadata for libraries
|
||||
# - Deep analysis of media files
|
||||
# - Generate thumbnails and preview images
|
||||
# - Interactive mode for easy library management
|
||||
# - Comprehensive error handling and validation
|
||||
#
|
||||
# Usage:
|
||||
# ./scan-plex-libraries.sh list # List all libraries
|
||||
# ./scan-plex-libraries.sh scan [section_id] # Scan library (all if no ID)
|
||||
# ./scan-plex-libraries.sh refresh [section_id] # Refresh library metadata
|
||||
# ./scan-plex-libraries.sh analyze [section_id] # Analyze library media
|
||||
# ./scan-plex-libraries.sh generate [section_id] # Generate thumbnails
|
||||
# ./scan-plex-libraries.sh # Interactive mode
|
||||
#
|
||||
# Dependencies:
|
||||
# - Plex Media Server
|
||||
# - Plex Media Scanner binary
|
||||
# - systemctl (for service management)
|
||||
#
|
||||
# Exit Codes:
|
||||
# 0 - Success
|
||||
# 1 - General error
|
||||
# 2 - Plex service not running
|
||||
# 3 - Scanner binary not found
|
||||
# 4 - Invalid section ID
|
||||
# 5 - Scanner operation failed
|
||||
#
|
||||
################################################################################
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# 🎨 Color definitions for styled output
|
||||
readonly RED='\033[0;31m'
|
||||
readonly GREEN='\033[0;32m'
|
||||
readonly YELLOW='\033[1;33m'
|
||||
readonly BLUE='\033[0;34m'
|
||||
readonly PURPLE='\033[0;35m'
|
||||
readonly CYAN='\033[0;36m'
|
||||
readonly WHITE='\033[1;37m'
|
||||
readonly BOLD='\033[1m'
|
||||
readonly DIM='\033[2m'
|
||||
readonly RESET='\033[0m'
|
||||
|
||||
# 🔧 Configuration
|
||||
readonly PLEX_SERVICE="plexmediaserver"
|
||||
readonly SCRIPT_NAME="$(basename "$0")"
|
||||
readonly SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
|
||||
readonly LOG_DIR="${SCRIPT_DIR}/../logs"
|
||||
readonly LOG_FILE="${LOG_DIR}/plex-scanner.log"
|
||||
|
||||
# Plex Media Scanner paths (common locations)
|
||||
readonly SCANNER_PATHS=(
|
||||
"/usr/lib/plexmediaserver/Plex Media Scanner"
|
||||
"/opt/plex/Plex Media Scanner"
|
||||
"/usr/local/plex/Plex Media Scanner"
|
||||
"/Applications/Plex Media Server.app/Contents/MacOS/Plex Media Scanner"
|
||||
)
|
||||
|
||||
# 🎭 ASCII symbols for compatible output
|
||||
readonly CHECKMARK="[✓]"
|
||||
readonly CROSS="[✗]"
|
||||
readonly ROCKET="[>]"
|
||||
readonly STOP_SIGN="[■]"
|
||||
readonly RECYCLE="[~]"
|
||||
readonly INFO="[i]"
|
||||
readonly HOURGLASS="[*]"
|
||||
readonly SPARKLES="[*]"
|
||||
readonly SEARCH="[?]"
|
||||
readonly LIBRARY="[📚]"
|
||||
|
||||
# Global variables
|
||||
SCANNER_PATH=""
|
||||
VERBOSE=false
|
||||
|
||||
# 🎉 Function to print completion footer
|
||||
print_footer() {
|
||||
echo -e "\n${DIM}${CYAN}--- Operation completed ${SPARKLES} ---${RESET}\n"
|
||||
}
|
||||
|
||||
# 🎯 Function to print status with style
|
||||
print_status() {
|
||||
local status="$1"
|
||||
local message="$2"
|
||||
local color="$3"
|
||||
echo -e "${color}${BOLD}[${status}]${RESET} ${message}"
|
||||
|
||||
# Log to file if log directory exists
|
||||
if [[ -d "$LOG_DIR" ]]; then
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') - [${status}] ${message}" >> "$LOG_FILE"
|
||||
fi
|
||||
}
|
||||
|
||||
# 📝 Function to log verbose output
|
||||
log_verbose() {
|
||||
local message="$1"
|
||||
if [[ "$VERBOSE" == true ]]; then
|
||||
echo -e "${DIM}${CYAN}[DEBUG]${RESET} ${message}"
|
||||
fi
|
||||
|
||||
# Always log to file if available
|
||||
if [[ -d "$LOG_DIR" ]]; then
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') - [DEBUG] ${message}" >> "$LOG_FILE"
|
||||
fi
|
||||
}
|
||||
|
||||
# 🔍 Function to find Plex Media Scanner binary
|
||||
find_scanner() {
|
||||
log_verbose "Searching for Plex Media Scanner binary..."
|
||||
|
||||
for path in "${SCANNER_PATHS[@]}"; do
|
||||
if [[ -f "$path" && -x "$path" ]]; then
|
||||
SCANNER_PATH="$path"
|
||||
log_verbose "Found scanner at: $path"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
# Try to find it in PATH
|
||||
if command -v "Plex Media Scanner" >/dev/null 2>&1; then
|
||||
SCANNER_PATH="Plex Media Scanner"
|
||||
log_verbose "Found scanner in PATH"
|
||||
return 0
|
||||
fi
|
||||
|
||||
print_status "${CROSS}" "Plex Media Scanner binary not found!" "${RED}"
|
||||
print_status "${INFO}" "Checked locations:" "${YELLOW}"
|
||||
for path in "${SCANNER_PATHS[@]}"; do
|
||||
echo -e " ${DIM}${YELLOW}• $path${RESET}"
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# 🏥 Function to check Plex service status
|
||||
check_plex_service() {
|
||||
log_verbose "Checking Plex service status..."
|
||||
|
||||
if ! systemctl is-active --quiet "$PLEX_SERVICE"; then
|
||||
print_status "${CROSS}" "Plex Media Server is not running!" "${RED}"
|
||||
print_status "${INFO}" "Start Plex with: ${BOLD}sudo systemctl start $PLEX_SERVICE${RESET}" "${YELLOW}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log_verbose "Plex service is running"
|
||||
return 0
|
||||
}
|
||||
|
||||
# 📚 Function to list all library sections
|
||||
list_libraries() {
|
||||
print_status "${LIBRARY}" "Listing all Plex library sections..." "${BLUE}"
|
||||
|
||||
if ! check_plex_service; then
|
||||
return 2
|
||||
fi
|
||||
|
||||
if ! find_scanner; then
|
||||
return 3
|
||||
fi
|
||||
|
||||
# Set library path for Linux
|
||||
export LD_LIBRARY_PATH=/usr/lib/plexmediaserver:${LD_LIBRARY_PATH:-}
|
||||
|
||||
local output
|
||||
if output=$("$SCANNER_PATH" --list 2>&1); then
|
||||
echo ""
|
||||
echo -e "${BOLD}${CYAN}Available Library Sections:${RESET}"
|
||||
echo -e "${DIM}${CYAN}=========================${RESET}"
|
||||
|
||||
# Parse and format the output
|
||||
echo "$output" | while IFS= read -r line; do
|
||||
if [[ "$line" =~ ^[[:space:]]*([0-9]+):[[:space:]]*(.+)$ ]]; then
|
||||
local section_id="${BASH_REMATCH[1]}"
|
||||
local section_name="${BASH_REMATCH[2]}"
|
||||
echo -e "${GREEN}${BOLD} ${section_id}:${RESET} ${WHITE}${section_name}${RESET}"
|
||||
elif [[ -n "$line" ]]; then
|
||||
echo -e "${DIM} $line${RESET}"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
print_status "${CHECKMARK}" "Library listing completed" "${GREEN}"
|
||||
return 0
|
||||
else
|
||||
print_status "${CROSS}" "Failed to list libraries" "${RED}"
|
||||
echo -e "${DIM}${RED}Error output: $output${RESET}"
|
||||
return 5
|
||||
fi
|
||||
}
|
||||
|
||||
# 🔍 Function to validate section ID
|
||||
validate_section_id() {
|
||||
local section_id="$1"
|
||||
|
||||
if [[ ! "$section_id" =~ ^[0-9]+$ ]]; then
|
||||
print_status "${CROSS}" "Invalid section ID: $section_id (must be a number)" "${RED}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Get list of valid section IDs
|
||||
export LD_LIBRARY_PATH=/usr/lib/plexmediaserver:${LD_LIBRARY_PATH:-}
|
||||
local valid_ids
|
||||
if valid_ids=$("$SCANNER_PATH" --list 2>/dev/null | grep -oE '^[[:space:]]*[0-9]+:' | grep -oE '[0-9]+'); then
|
||||
if echo "$valid_ids" | grep -q "^${section_id}$"; then
|
||||
return 0
|
||||
else
|
||||
print_status "${CROSS}" "Section ID $section_id not found" "${RED}"
|
||||
print_status "${INFO}" "Valid section IDs: $(echo "$valid_ids" | tr '\n' ' ')" "${YELLOW}"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
print_status "${CROSS}" "Unable to validate section ID" "${RED}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 🔄 Function to scan library for new media
|
||||
scan_library() {
|
||||
local section_id="$1"
|
||||
|
||||
if [[ -n "$section_id" ]]; then
|
||||
print_status "${ROCKET}" "Scanning library section $section_id for new media..." "${BLUE}"
|
||||
|
||||
if ! validate_section_id "$section_id"; then
|
||||
return 4
|
||||
fi
|
||||
|
||||
export LD_LIBRARY_PATH=/usr/lib/plexmediaserver:${LD_LIBRARY_PATH:-}
|
||||
|
||||
if "$SCANNER_PATH" --scan --section "$section_id" ${VERBOSE:+--verbose}; then
|
||||
print_status "${CHECKMARK}" "Library section $section_id scan completed" "${GREEN}"
|
||||
return 0
|
||||
else
|
||||
print_status "${CROSS}" "Failed to scan library section $section_id" "${RED}"
|
||||
return 5
|
||||
fi
|
||||
else
|
||||
print_status "${ROCKET}" "Scanning all libraries for new media..." "${BLUE}"
|
||||
|
||||
# Get all section IDs and scan each one
|
||||
export LD_LIBRARY_PATH=/usr/lib/plexmediaserver:${LD_LIBRARY_PATH:-}
|
||||
local section_ids
|
||||
if section_ids=$("$SCANNER_PATH" --list 2>/dev/null | grep -oE '^[[:space:]]*[0-9]+:' | grep -oE '[0-9]+'); then
|
||||
local failed_sections=()
|
||||
|
||||
while IFS= read -r id; do
|
||||
[[ -n "$id" ]] || continue
|
||||
print_status "${INFO}" "Scanning section $id..." "${YELLOW}"
|
||||
|
||||
if "$SCANNER_PATH" --scan --section "$id" ${VERBOSE:+--verbose}; then
|
||||
print_status "${CHECKMARK}" "Section $id scanned successfully" "${GREEN}"
|
||||
else
|
||||
print_status "${CROSS}" "Failed to scan section $id" "${RED}"
|
||||
failed_sections+=("$id")
|
||||
fi
|
||||
done <<< "$section_ids"
|
||||
|
||||
if [[ ${#failed_sections[@]} -eq 0 ]]; then
|
||||
print_status "${CHECKMARK}" "All libraries scanned successfully" "${GREEN}"
|
||||
return 0
|
||||
else
|
||||
print_status "${CROSS}" "Some libraries failed to scan: ${failed_sections[*]}" "${RED}"
|
||||
return 5
|
||||
fi
|
||||
else
|
||||
print_status "${CROSS}" "Unable to retrieve library list" "${RED}"
|
||||
return 5
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 🔄 Function to refresh library metadata
|
||||
refresh_library() {
|
||||
local section_id="$1"
|
||||
local force="${2:-false}"
|
||||
|
||||
local force_flag=""
|
||||
if [[ "$force" == "true" ]]; then
|
||||
force_flag="--force"
|
||||
fi
|
||||
|
||||
if [[ -n "$section_id" ]]; then
|
||||
print_status "${RECYCLE}" "Refreshing metadata for library section $section_id..." "${BLUE}"
|
||||
|
||||
if ! validate_section_id "$section_id"; then
|
||||
return 4
|
||||
fi
|
||||
|
||||
export LD_LIBRARY_PATH=/usr/lib/plexmediaserver:${LD_LIBRARY_PATH:-}
|
||||
|
||||
if "$SCANNER_PATH" --refresh $force_flag --section "$section_id" ${VERBOSE:+--verbose}; then
|
||||
print_status "${CHECKMARK}" "Library section $section_id metadata refreshed" "${GREEN}"
|
||||
return 0
|
||||
else
|
||||
print_status "${CROSS}" "Failed to refresh library section $section_id" "${RED}"
|
||||
return 5
|
||||
fi
|
||||
else
|
||||
print_status "${RECYCLE}" "Refreshing metadata for all libraries..." "${BLUE}"
|
||||
|
||||
# Get all section IDs and refresh each one
|
||||
export LD_LIBRARY_PATH=/usr/lib/plexmediaserver:${LD_LIBRARY_PATH:-}
|
||||
local section_ids
|
||||
if section_ids=$("$SCANNER_PATH" --list 2>/dev/null | grep -oE '^[[:space:]]*[0-9]+:' | grep -oE '[0-9]+'); then
|
||||
local failed_sections=()
|
||||
|
||||
while IFS= read -r id; do
|
||||
[[ -n "$id" ]] || continue
|
||||
print_status "${INFO}" "Refreshing section $id..." "${YELLOW}"
|
||||
|
||||
if "$SCANNER_PATH" --refresh $force_flag --section "$id" ${VERBOSE:+--verbose}; then
|
||||
print_status "${CHECKMARK}" "Section $id refreshed successfully" "${GREEN}"
|
||||
else
|
||||
print_status "${CROSS}" "Failed to refresh section $id" "${RED}"
|
||||
failed_sections+=("$id")
|
||||
fi
|
||||
done <<< "$section_ids"
|
||||
|
||||
if [[ ${#failed_sections[@]} -eq 0 ]]; then
|
||||
print_status "${CHECKMARK}" "All libraries refreshed successfully" "${GREEN}"
|
||||
return 0
|
||||
else
|
||||
print_status "${CROSS}" "Some libraries failed to refresh: ${failed_sections[*]}" "${RED}"
|
||||
return 5
|
||||
fi
|
||||
else
|
||||
print_status "${CROSS}" "Unable to retrieve library list" "${RED}"
|
||||
return 5
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 🔬 Function to analyze library media
|
||||
analyze_library() {
|
||||
local section_id="$1"
|
||||
local deep="${2:-false}"
|
||||
|
||||
local analyze_flag="--analyze"
|
||||
if [[ "$deep" == "true" ]]; then
|
||||
analyze_flag="--analyze-deeply"
|
||||
fi
|
||||
|
||||
if [[ -n "$section_id" ]]; then
|
||||
print_status "${SEARCH}" "Analyzing media in library section $section_id..." "${BLUE}"
|
||||
|
||||
if ! validate_section_id "$section_id"; then
|
||||
return 4
|
||||
fi
|
||||
|
||||
export LD_LIBRARY_PATH=/usr/lib/plexmediaserver:${LD_LIBRARY_PATH:-}
|
||||
|
||||
if "$SCANNER_PATH" $analyze_flag --section "$section_id" ${VERBOSE:+--verbose}; then
|
||||
print_status "${CHECKMARK}" "Library section $section_id analysis completed" "${GREEN}"
|
||||
return 0
|
||||
else
|
||||
print_status "${CROSS}" "Failed to analyze library section $section_id" "${RED}"
|
||||
return 5
|
||||
fi
|
||||
else
|
||||
print_status "${SEARCH}" "Analyzing media in all libraries..." "${BLUE}"
|
||||
|
||||
# Get all section IDs and analyze each one
|
||||
export LD_LIBRARY_PATH=/usr/lib/plexmediaserver:${LD_LIBRARY_PATH:-}
|
||||
local section_ids
|
||||
if section_ids=$("$SCANNER_PATH" --list 2>/dev/null | grep -oE '^[[:space:]]*[0-9]+:' | grep -oE '[0-9]+'); then
|
||||
local failed_sections=()
|
||||
|
||||
while IFS= read -r id; do
|
||||
[[ -n "$id" ]] || continue
|
||||
print_status "${INFO}" "Analyzing section $id..." "${YELLOW}"
|
||||
|
||||
if "$SCANNER_PATH" $analyze_flag --section "$id" ${VERBOSE:+--verbose}; then
|
||||
print_status "${CHECKMARK}" "Section $id analyzed successfully" "${GREEN}"
|
||||
else
|
||||
print_status "${CROSS}" "Failed to analyze section $id" "${RED}"
|
||||
failed_sections+=("$id")
|
||||
fi
|
||||
done <<< "$section_ids"
|
||||
|
||||
if [[ ${#failed_sections[@]} -eq 0 ]]; then
|
||||
print_status "${CHECKMARK}" "All libraries analyzed successfully" "${GREEN}"
|
||||
return 0
|
||||
else
|
||||
print_status "${CROSS}" "Some libraries failed to analyze: ${failed_sections[*]}" "${RED}"
|
||||
return 5
|
||||
fi
|
||||
else
|
||||
print_status "${CROSS}" "Unable to retrieve library list" "${RED}"
|
||||
return 5
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 🖼️ Function to generate thumbnails and fanart
|
||||
generate_thumbnails() {
|
||||
local section_id="$1"
|
||||
|
||||
if [[ -n "$section_id" ]]; then
|
||||
print_status "${SPARKLES}" "Generating thumbnails for library section $section_id..." "${BLUE}"
|
||||
|
||||
if ! validate_section_id "$section_id"; then
|
||||
return 4
|
||||
fi
|
||||
|
||||
export LD_LIBRARY_PATH=/usr/lib/plexmediaserver:${LD_LIBRARY_PATH:-}
|
||||
|
||||
if "$SCANNER_PATH" --generate --section "$section_id" ${VERBOSE:+--verbose}; then
|
||||
print_status "${CHECKMARK}" "Thumbnails generated for library section $section_id" "${GREEN}"
|
||||
return 0
|
||||
else
|
||||
print_status "${CROSS}" "Failed to generate thumbnails for library section $section_id" "${RED}"
|
||||
return 5
|
||||
fi
|
||||
else
|
||||
print_status "${SPARKLES}" "Generating thumbnails for all libraries..." "${BLUE}"
|
||||
|
||||
# Get all section IDs and generate thumbnails for each one
|
||||
export LD_LIBRARY_PATH=/usr/lib/plexmediaserver:${LD_LIBRARY_PATH:-}
|
||||
local section_ids
|
||||
if section_ids=$("$SCANNER_PATH" --list 2>/dev/null | grep -oE '^[[:space:]]*[0-9]+:' | grep -oE '[0-9]+'); then
|
||||
local failed_sections=()
|
||||
|
||||
while IFS= read -r id; do
|
||||
[[ -n "$id" ]] || continue
|
||||
print_status "${INFO}" "Generating thumbnails for section $id..." "${YELLOW}"
|
||||
|
||||
if "$SCANNER_PATH" --generate --section "$id" ${VERBOSE:+--verbose}; then
|
||||
print_status "${CHECKMARK}" "Section $id thumbnails generated successfully" "${GREEN}"
|
||||
else
|
||||
print_status "${CROSS}" "Failed to generate thumbnails for section $id" "${RED}"
|
||||
failed_sections+=("$id")
|
||||
fi
|
||||
done <<< "$section_ids"
|
||||
|
||||
if [[ ${#failed_sections[@]} -eq 0 ]]; then
|
||||
print_status "${CHECKMARK}" "Thumbnails generated for all libraries" "${GREEN}"
|
||||
return 0
|
||||
else
|
||||
print_status "${CROSS}" "Some libraries failed thumbnail generation: ${failed_sections[*]}" "${RED}"
|
||||
return 5
|
||||
fi
|
||||
else
|
||||
print_status "${CROSS}" "Unable to retrieve library list" "${RED}"
|
||||
return 5
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 🌳 Function to show library tree structure
|
||||
show_library_tree() {
|
||||
local section_id="$1"
|
||||
|
||||
if [[ -z "$section_id" ]]; then
|
||||
print_status "${CROSS}" "Section ID required for tree display" "${RED}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
print_status "${LIBRARY}" "Showing tree structure for library section $section_id..." "${BLUE}"
|
||||
|
||||
if ! validate_section_id "$section_id"; then
|
||||
return 4
|
||||
fi
|
||||
|
||||
export LD_LIBRARY_PATH=/usr/lib/plexmediaserver:${LD_LIBRARY_PATH:-}
|
||||
|
||||
if "$SCANNER_PATH" --tree --section "$section_id"; then
|
||||
print_status "${CHECKMARK}" "Tree display completed for library section $section_id" "${GREEN}"
|
||||
return 0
|
||||
else
|
||||
print_status "${CROSS}" "Failed to display tree for library section $section_id" "${RED}"
|
||||
return 5
|
||||
fi
|
||||
}
|
||||
|
||||
# ❓ Function to show help
|
||||
show_help() {
|
||||
echo -e "${BOLD}${CYAN}Plex Library Scanner${RESET}"
|
||||
echo -e "${DIM}Modern command-line interface for Plex Media Scanner${RESET}"
|
||||
echo ""
|
||||
echo -e "${BOLD}Usage:${RESET}"
|
||||
echo -e " ${SCRIPT_NAME} ${GREEN}list${RESET} ${DIM}# List all library sections${RESET}"
|
||||
echo -e " ${SCRIPT_NAME} ${GREEN}scan${RESET} [section_id] ${DIM}# Scan for new media (all if no ID)${RESET}"
|
||||
echo -e " ${SCRIPT_NAME} ${GREEN}refresh${RESET} [section_id] [force] ${DIM}# Refresh metadata (force=true for forced refresh)${RESET}"
|
||||
echo -e " ${SCRIPT_NAME} ${GREEN}analyze${RESET} [section_id] [deep] ${DIM}# Analyze media (deep=true for deep analysis)${RESET}"
|
||||
echo -e " ${SCRIPT_NAME} ${GREEN}generate${RESET} [section_id] ${DIM}# Generate thumbnails and fanart${RESET}"
|
||||
echo -e " ${SCRIPT_NAME} ${GREEN}tree${RESET} <section_id> ${DIM}# Show library tree structure${RESET}"
|
||||
echo -e " ${SCRIPT_NAME} ${GREEN}interactive${RESET} ${DIM}# Interactive mode${RESET}"
|
||||
echo ""
|
||||
echo -e "${BOLD}Options:${RESET}"
|
||||
echo -e " ${GREEN}-v, --verbose${RESET} ${DIM}# Enable verbose output${RESET}"
|
||||
echo -e " ${GREEN}-h, --help${RESET} ${DIM}# Show this help message${RESET}"
|
||||
echo ""
|
||||
echo -e "${BOLD}Examples:${RESET}"
|
||||
echo -e " ${DIM}# List all libraries${RESET}"
|
||||
echo -e " ${SCRIPT_NAME} list"
|
||||
echo ""
|
||||
echo -e " ${DIM}# Scan all libraries for new media${RESET}"
|
||||
echo -e " ${SCRIPT_NAME} scan"
|
||||
echo ""
|
||||
echo -e " ${DIM}# Scan specific library (ID 29)${RESET}"
|
||||
echo -e " ${SCRIPT_NAME} scan 29"
|
||||
echo ""
|
||||
echo -e " ${DIM}# Force refresh all libraries${RESET}"
|
||||
echo -e " ${SCRIPT_NAME} refresh \"\" true"
|
||||
echo ""
|
||||
echo -e " ${DIM}# Deep analyze specific library${RESET}"
|
||||
echo -e " ${SCRIPT_NAME} analyze 29 true"
|
||||
echo ""
|
||||
echo -e "${BOLD}Notes:${RESET}"
|
||||
echo -e " ${DIM}• Requires Plex Media Server to be running${RESET}"
|
||||
echo -e " ${DIM}• Operations may take considerable time for large libraries${RESET}"
|
||||
echo -e " ${DIM}• Use verbose mode (-v) for detailed progress information${RESET}"
|
||||
echo -e " ${DIM}• Log files are written to: ${LOG_FILE}${RESET}"
|
||||
}
|
||||
|
||||
# 🎯 Interactive mode function
|
||||
interactive_mode() {
|
||||
echo -e "${BOLD}${CYAN}🎬 Plex Library Scanner - Interactive Mode${RESET}"
|
||||
echo -e "${DIM}Select an operation to perform:${RESET}"
|
||||
echo ""
|
||||
|
||||
# First, check if Plex is running and scanner is available
|
||||
if ! check_plex_service; then
|
||||
return 2
|
||||
fi
|
||||
|
||||
if ! find_scanner; then
|
||||
return 3
|
||||
fi
|
||||
|
||||
while true; do
|
||||
echo -e "${BOLD}Available Operations:${RESET}"
|
||||
echo -e "${GREEN}1)${RESET} List all libraries"
|
||||
echo -e "${GREEN}2)${RESET} Scan libraries for new media"
|
||||
echo -e "${GREEN}3)${RESET} Refresh library metadata"
|
||||
echo -e "${GREEN}4)${RESET} Analyze library media"
|
||||
echo -e "${GREEN}5)${RESET} Generate thumbnails"
|
||||
echo -e "${GREEN}6)${RESET} Show library tree"
|
||||
echo -e "${GREEN}q)${RESET} Quit"
|
||||
echo ""
|
||||
|
||||
read -p "$(echo -e "${BOLD}Choose an option [1-6,q]:${RESET} ")" choice
|
||||
|
||||
case "$choice" in
|
||||
1)
|
||||
echo ""
|
||||
list_libraries
|
||||
;;
|
||||
2)
|
||||
echo ""
|
||||
echo -e "${BOLD}Scan Options:${RESET}"
|
||||
echo -e "${GREEN}1)${RESET} Scan all libraries"
|
||||
echo -e "${GREEN}2)${RESET} Scan specific library"
|
||||
read -p "$(echo -e "${BOLD}Choose [1-2]:${RESET} ")" scan_choice
|
||||
|
||||
case "$scan_choice" in
|
||||
1)
|
||||
scan_library ""
|
||||
;;
|
||||
2)
|
||||
read -p "$(echo -e "${BOLD}Enter section ID:${RESET} ")" section_id
|
||||
scan_library "$section_id"
|
||||
;;
|
||||
*)
|
||||
print_status "${CROSS}" "Invalid choice" "${RED}"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
3)
|
||||
echo ""
|
||||
echo -e "${BOLD}Refresh Options:${RESET}"
|
||||
echo -e "${GREEN}1)${RESET} Refresh all libraries"
|
||||
echo -e "${GREEN}2)${RESET} Refresh specific library"
|
||||
echo -e "${GREEN}3)${RESET} Force refresh all libraries"
|
||||
echo -e "${GREEN}4)${RESET} Force refresh specific library"
|
||||
read -p "$(echo -e "${BOLD}Choose [1-4]:${RESET} ")" refresh_choice
|
||||
|
||||
case "$refresh_choice" in
|
||||
1)
|
||||
refresh_library "" false
|
||||
;;
|
||||
2)
|
||||
read -p "$(echo -e "${BOLD}Enter section ID:${RESET} ")" section_id
|
||||
refresh_library "$section_id" false
|
||||
;;
|
||||
3)
|
||||
refresh_library "" true
|
||||
;;
|
||||
4)
|
||||
read -p "$(echo -e "${BOLD}Enter section ID:${RESET} ")" section_id
|
||||
refresh_library "$section_id" true
|
||||
;;
|
||||
*)
|
||||
print_status "${CROSS}" "Invalid choice" "${RED}"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
4)
|
||||
echo ""
|
||||
echo -e "${BOLD}Analysis Options:${RESET}"
|
||||
echo -e "${GREEN}1)${RESET} Analyze all libraries"
|
||||
echo -e "${GREEN}2)${RESET} Analyze specific library"
|
||||
echo -e "${GREEN}3)${RESET} Deep analyze all libraries"
|
||||
echo -e "${GREEN}4)${RESET} Deep analyze specific library"
|
||||
read -p "$(echo -e "${BOLD}Choose [1-4]:${RESET} ")" analyze_choice
|
||||
|
||||
case "$analyze_choice" in
|
||||
1)
|
||||
analyze_library "" false
|
||||
;;
|
||||
2)
|
||||
read -p "$(echo -e "${BOLD}Enter section ID:${RESET} ")" section_id
|
||||
analyze_library "$section_id" false
|
||||
;;
|
||||
3)
|
||||
analyze_library "" true
|
||||
;;
|
||||
4)
|
||||
read -p "$(echo -e "${BOLD}Enter section ID:${RESET} ")" section_id
|
||||
analyze_library "$section_id" true
|
||||
;;
|
||||
*)
|
||||
print_status "${CROSS}" "Invalid choice" "${RED}"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
5)
|
||||
echo ""
|
||||
echo -e "${BOLD}Thumbnail Generation Options:${RESET}"
|
||||
echo -e "${GREEN}1)${RESET} Generate for all libraries"
|
||||
echo -e "${GREEN}2)${RESET} Generate for specific library"
|
||||
read -p "$(echo -e "${BOLD}Choose [1-2]:${RESET} ")" gen_choice
|
||||
|
||||
case "$gen_choice" in
|
||||
1)
|
||||
generate_thumbnails ""
|
||||
;;
|
||||
2)
|
||||
read -p "$(echo -e "${BOLD}Enter section ID:${RESET} ")" section_id
|
||||
generate_thumbnails "$section_id"
|
||||
;;
|
||||
*)
|
||||
print_status "${CROSS}" "Invalid choice" "${RED}"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
6)
|
||||
echo ""
|
||||
read -p "$(echo -e "${BOLD}Enter section ID to show tree:${RESET} ")" section_id
|
||||
show_library_tree "$section_id"
|
||||
;;
|
||||
q|Q)
|
||||
print_status "${INFO}" "Goodbye!" "${CYAN}"
|
||||
break
|
||||
;;
|
||||
*)
|
||||
print_status "${CROSS}" "Invalid choice: $choice" "${RED}"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo ""
|
||||
echo -e "${DIM}Press Enter to continue...${RESET}"
|
||||
read -r
|
||||
echo ""
|
||||
done
|
||||
}
|
||||
|
||||
# 🚀 Main script logic
|
||||
main() {
|
||||
# Create log directory if it doesn't exist
|
||||
mkdir -p "$LOG_DIR"
|
||||
|
||||
# Check if running as root
|
||||
if [[ $EUID -eq 0 ]]; then
|
||||
print_status "${CROSS}" "Don't run this script as root! Use your regular user account." "${RED}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Parse command line arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-v|--verbose)
|
||||
VERBOSE=true
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Check if no arguments provided or interactive requested
|
||||
if [[ $# -eq 0 ]] || [[ "${1,,}" == "interactive" ]]; then
|
||||
interactive_mode
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Pre-flight checks
|
||||
if ! check_plex_service; then
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if ! find_scanner; then
|
||||
exit 3
|
||||
fi
|
||||
|
||||
# Handle commands
|
||||
case "${1,,}" in
|
||||
"list")
|
||||
list_libraries
|
||||
;;
|
||||
"scan")
|
||||
local section_id="${2:-}"
|
||||
scan_library "$section_id"
|
||||
;;
|
||||
"refresh")
|
||||
local section_id="${2:-}"
|
||||
local force="${3:-false}"
|
||||
refresh_library "$section_id" "$force"
|
||||
;;
|
||||
"analyze"|"analyse")
|
||||
local section_id="${2:-}"
|
||||
local deep="${3:-false}"
|
||||
analyze_library "$section_id" "$deep"
|
||||
;;
|
||||
"generate"|"thumbnails")
|
||||
local section_id="${2:-}"
|
||||
generate_thumbnails "$section_id"
|
||||
;;
|
||||
"tree")
|
||||
local section_id="$2"
|
||||
if [[ -z "$section_id" ]]; then
|
||||
print_status "${CROSS}" "Section ID required for tree command" "${RED}"
|
||||
exit 1
|
||||
fi
|
||||
show_library_tree "$section_id"
|
||||
;;
|
||||
"help"|"--help"|"-h")
|
||||
show_help
|
||||
;;
|
||||
*)
|
||||
print_status "${CROSS}" "Unknown command: ${RED}${BOLD}$1${RESET}" "${RED}"
|
||||
echo ""
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Print footer for successful operations
|
||||
print_footer
|
||||
}
|
||||
|
||||
# 🎬 Execute main function with all arguments
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user