MasterDraco 6dc2df3cee Fix code consistency and reliability issues
This commit addresses multiple code consistency and reliability issues across the codebase:

1. Version consistency - use package.json version (2.0.9) throughout
2. Improved module loading with better error handling and consistent symlinks
3. Enhanced data directory handling with better error checking
4. Fixed redundant code in main-installer.sh
5. Improved error handling in transmission-client.js
6. Added extensive module symlink creation
7. Better file path handling and permission checks
8. Enhanced API response handling

💡 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-03-07 11:38:14 +00:00

308 lines
9.3 KiB
Bash

#!/bin/bash
# Utilities module for Transmission RSS Manager Installation
# Function to log a message with timestamp
function log() {
local level=$1
local message=$2
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
case $level in
"INFO")
echo -e "${timestamp} ${GREEN}[INFO]${NC} $message"
;;
"WARN")
echo -e "${timestamp} ${YELLOW}[WARN]${NC} $message"
;;
"ERROR")
echo -e "${timestamp} ${RED}[ERROR]${NC} $message"
;;
"DEBUG")
if [ "${DEBUG_ENABLED}" = "true" ]; then
echo -e "${timestamp} ${BOLD}[DEBUG]${NC} $message"
fi
;;
*)
echo -e "${timestamp} [LOG] $message"
;;
esac
# If log file is specified, also write to log file
if [ -n "${LOG_FILE}" ]; then
echo "${timestamp} [${level}] ${message}" >> "${LOG_FILE}"
fi
}
# Function to check if a command exists
function command_exists() {
command -v "$1" &> /dev/null
}
# Function to backup a file before modifying it
function backup_file() {
local file=$1
if [ -f "$file" ]; then
local backup="${file}.bak.$(date +%Y%m%d%H%M%S)"
cp "$file" "$backup"
log "INFO" "Created backup of $file at $backup"
echo "$backup"
fi
}
# Function to manage config file updates
function update_config_file() {
local config_file=$1
local is_update=$2
if [ "$is_update" = true ] && [ -f "$config_file" ]; then
# Backup the existing config file
local backup_file=$(backup_file "$config_file")
log "INFO" "Existing configuration backed up to $backup_file"
# We'll let the server.js handle merging the config
log "INFO" "Existing configuration will be preserved"
# Update the config version if needed
local current_version=$(grep -o '"version": "[^"]*"' "$config_file" | cut -d'"' -f4)
if [ -n "$current_version" ]; then
local new_version="2.0.0"
if [ "$current_version" != "$new_version" ]; then
log "INFO" "Updating config version from $current_version to $new_version"
sed -i "s/\"version\": \"$current_version\"/\"version\": \"$new_version\"/" "$config_file"
fi
fi
return 0
else
# New installation, config file will be created by finalize_setup
log "INFO" "New configuration will be created"
return 1
fi
}
# Function to create a directory if it doesn't exist
function create_dir_if_not_exists() {
local dir=$1
local owner=$2
if [ ! -d "$dir" ]; then
mkdir -p "$dir"
log "INFO" "Created directory: $dir"
if [ -n "$owner" ]; then
chown -R "$owner" "$dir"
log "INFO" "Set ownership of $dir to $owner"
fi
fi
}
# Function to finalize the setup (permissions, etc.)
# Function to ensure NPM packages are properly installed
function ensure_npm_packages() {
local install_dir=$1
# First ensure the installation directory exists
if [ ! -d "$install_dir" ]; then
log "INFO" "Creating installation directory: $install_dir"
mkdir -p "$install_dir" || {
log "ERROR" "Failed to create installation directory: $install_dir"
return 1
}
}
# Ensure data directory exists
if [ ! -d "$install_dir/data" ]; then
log "INFO" "Creating data directory: $install_dir/data"
mkdir -p "$install_dir/data" || {
log "ERROR" "Failed to create data directory: $install_dir/data"
return 1
}
# Initialize empty data files
echo "[]" > "$install_dir/data/rss-feeds.json"
echo "[]" > "$install_dir/data/rss-items.json"
log "INFO" "Initialized empty data files"
fi
# Ensure package.json exists in the installation directory
if [ ! -f "$install_dir/package.json" ]; then
log "INFO" "Copying package.json to installation directory..."
cp "$SCRIPT_DIR/package.json" "$install_dir/package.json" || {
log "ERROR" "Failed to copy package.json to installation directory"
return 1
}
}
# Install NPM packages if not already installed or if it's an update
if [ ! -d "$install_dir/node_modules" ] || [ "$IS_UPDATE" = "true" ]; then
log "INFO" "Installing NPM packages in $install_dir..."
# Save current directory
local current_dir=$(pwd)
# Change to install directory and install packages
cd "$install_dir" || {
log "ERROR" "Failed to change to installation directory: $install_dir"
return 1
}
npm install || {
log "ERROR" "NPM installation failed in $install_dir"
cd "$current_dir" # Return to original directory
return 1
}
# Return to original directory
cd "$current_dir"
log "INFO" "NPM packages successfully installed in $install_dir"
else
log "INFO" "NPM packages appear to be already installed in $install_dir, skipping"
fi
return 0
}
function finalize_setup() {
log "INFO" "Setting up final permissions and configurations..."
# Ensure logs directory exists
mkdir -p "$INSTALL_DIR/logs"
log "INFO" "Created logs directory: $INSTALL_DIR/logs"
# Ensure CONFIG_DIR exists
if [ ! -d "$CONFIG_DIR" ]; then
mkdir -p "$CONFIG_DIR"
log "INFO" "Created configuration directory: $CONFIG_DIR"
chown -R "$USER:$USER" "$CONFIG_DIR"
fi
# Check if the config symlink exists, create it if not
if [ ! -L "$INSTALL_DIR/config.json" ] || [ ! -e "$INSTALL_DIR/config.json" ]; then
# If there's a real file at INSTALL_DIR/config.json (not a symlink), move it to CONFIG_DIR
if [ -f "$INSTALL_DIR/config.json" ] && [ ! -L "$INSTALL_DIR/config.json" ]; then
log "INFO" "Moving existing config.json to $CONFIG_DIR"
mv "$INSTALL_DIR/config.json" "$CONFIG_DIR/config.json"
fi
# Create the symlink
ln -sf "$CONFIG_DIR/config.json" "$INSTALL_DIR/config.json"
log "INFO" "Created symlink from $INSTALL_DIR/config.json to $CONFIG_DIR/config.json"
fi
# Set proper ownership for the installation directory
chown -R $USER:$USER $INSTALL_DIR
# Create media directories with correct permissions
create_dir_if_not_exists "$MEDIA_DIR/movies" "$USER:$USER"
create_dir_if_not_exists "$MEDIA_DIR/tvshows" "$USER:$USER"
create_dir_if_not_exists "$MEDIA_DIR/music" "$USER:$USER"
create_dir_if_not_exists "$MEDIA_DIR/software" "$USER:$USER"
# Create book/magazine directories if enabled
if [ "$ENABLE_BOOK_SORTING" = true ]; then
create_dir_if_not_exists "$MEDIA_DIR/books" "$USER:$USER"
create_dir_if_not_exists "$MEDIA_DIR/magazines" "$USER:$USER"
fi
# Install npm packages
ensure_npm_packages "$INSTALL_DIR" || {
log "ERROR" "Failed to install NPM packages"
}
# Handle configuration file
if ! update_config_file "$CONFIG_DIR/config.json" "$IS_UPDATE"; then
log "INFO" "Creating default configuration file..."
# Create the users array content for JSON
USER_JSON=""
if [ "${AUTH_ENABLED}" = "true" ] && [ -n "${ADMIN_USERNAME}" ]; then
USER_JSON="{ \"username\": \"${ADMIN_USERNAME}\", \"password\": \"${ADMIN_PASSWORD}\", \"role\": \"admin\" }"
fi
# Make sure CONFIG_DIR exists
mkdir -p "$CONFIG_DIR"
# Get version from package.json dynamically
VERSION=$(grep -oP '"version": "\K[^"]+' "${SCRIPT_DIR}/package.json" 2>/dev/null || echo "2.0.9")
cat > $CONFIG_DIR/config.json << EOF
{
"version": "$VERSION",
"transmissionConfig": {
"host": "${TRANSMISSION_HOST}",
"port": ${TRANSMISSION_PORT},
"username": "${TRANSMISSION_USER}",
"password": "${TRANSMISSION_PASS}",
"path": "${TRANSMISSION_RPC_PATH}"
},
"remoteConfig": {
"isRemote": ${TRANSMISSION_REMOTE},
"directoryMapping": ${TRANSMISSION_DIR_MAPPING}
},
"destinationPaths": {
"movies": "${MEDIA_DIR}/movies",
"tvShows": "${MEDIA_DIR}/tvshows",
"music": "${MEDIA_DIR}/music",
"books": "${MEDIA_DIR}/books",
"magazines": "${MEDIA_DIR}/magazines",
"software": "${MEDIA_DIR}/software"
},
"seedingRequirements": {
"minRatio": 1.0,
"minTimeMinutes": 60,
"checkIntervalSeconds": 300
},
"processingOptions": {
"enableBookSorting": ${ENABLE_BOOK_SORTING},
"extractArchives": true,
"deleteArchives": true,
"createCategoryFolders": true,
"ignoreSample": true,
"ignoreExtras": true,
"renameFiles": true,
"autoReplaceUpgrades": true,
"removeDuplicates": true,
"keepOnlyBestVersion": true
},
"securitySettings": {
"authEnabled": ${AUTH_ENABLED:-false},
"httpsEnabled": ${HTTPS_ENABLED:-false},
"sslCertPath": "${SSL_CERT_PATH:-""}",
"sslKeyPath": "${SSL_KEY_PATH:-""}",
"users": [
${USER_JSON}
]
},
"rssFeeds": [],
"rssUpdateIntervalMinutes": 60,
"autoProcessing": false,
"port": ${PORT},
"logLevel": "info"
}
EOF
# Set ownership for the config file
chown $USER:$USER $CONFIG_DIR/config.json
# Ensure symlink exists from INSTALL_DIR to CONFIG_DIR
ln -sf "$CONFIG_DIR/config.json" "$INSTALL_DIR/config.json"
log "INFO" "Created symlink from $INSTALL_DIR/config.json to $CONFIG_DIR/config.json"
log "INFO" "Default configuration created successfully"
fi
# Start the service
log "INFO" "Starting the service..."
systemctl daemon-reload
systemctl enable $SERVICE_NAME
systemctl start $SERVICE_NAME
# Check if service started successfully
sleep 2
if systemctl is-active --quiet $SERVICE_NAME; then
log "INFO" "Service started successfully!"
else
log "ERROR" "Service failed to start. Check logs with: journalctl -u $SERVICE_NAME"
fi
log "INFO" "Setup finalized!"
}