#!/bin/bash # Configuration module for Transmission RSS Manager Installation # Configuration variables with defaults INSTALL_DIR="/opt/transmission-rss-manager" SERVICE_NAME="transmission-rss-manager" PORT=3000 # Get default user safely - avoid using root get_default_user() { local default_user # Try logname first to get the user who invoked sudo if command -v logname &> /dev/null; then default_user=$(logname 2>/dev/null) fi # If logname failed, try SUDO_USER if [ -z "$default_user" ] && [ -n "$SUDO_USER" ]; then default_user="$SUDO_USER" fi # Fallback to current user if both methods failed if [ -z "$default_user" ]; then default_user="$(whoami)" fi # Ensure the user is not root if [ "$default_user" = "root" ]; then echo "nobody" else echo "$default_user" fi } # Initialize default user USER=$(get_default_user) # Transmission configuration variables TRANSMISSION_REMOTE=false TRANSMISSION_HOST="localhost" TRANSMISSION_PORT=9091 TRANSMISSION_USER="" TRANSMISSION_PASS="" TRANSMISSION_RPC_PATH="/transmission/rpc" TRANSMISSION_DOWNLOAD_DIR="/var/lib/transmission-daemon/downloads" TRANSMISSION_DIR_MAPPING="{}" # Media path defaults MEDIA_DIR="/mnt/media" ENABLE_BOOK_SORTING=true # Helper function to validate port number validate_port() { local port="$1" if [[ "$port" =~ ^[0-9]+$ ]] && [ "$port" -ge 1 ] && [ "$port" -le 65535 ]; then return 0 else return 1 fi } # Helper function to validate URL hostname validate_hostname() { local hostname="$1" if [[ "$hostname" =~ ^[a-zA-Z0-9]([a-zA-Z0-9\-\.]+[a-zA-Z0-9])?$ ]]; then return 0 elif [[ "$hostname" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then return 0 else return 1 fi } function gather_configuration() { log "INFO" "Starting configuration gathering" echo -e "${BOLD}Installation Configuration:${NC}" echo -e "Please provide the following configuration parameters:" echo read -p "Installation directory [$INSTALL_DIR]: " input_install_dir if [ -n "$input_install_dir" ]; then # Validate installation directory if [[ ! "$input_install_dir" =~ ^/ ]]; then log "WARN" "Installation directory must be an absolute path. Using default." else INSTALL_DIR="$input_install_dir" fi fi # Using fixed port 3000 to avoid permission issues with ports below 1024 log "INFO" "Using port 3000 for the web interface" log "INFO" "This is to avoid permission issues with ports below 1024 (like port 80)" PORT=3000 # Get user read -p "Run as user [$USER]: " input_user if [ -n "$input_user" ]; then # Check if user exists if id "$input_user" &>/dev/null; then USER="$input_user" else log "WARN" "User $input_user does not exist. Using $USER instead." fi fi echo echo -e "${BOLD}Transmission Configuration:${NC}" echo -e "Configure connection to your Transmission client:" echo # Ask if Transmission is remote read -p "Is Transmission running on a remote server? (y/n) [n]: " input_remote if [[ $input_remote =~ ^[Yy]$ ]]; then TRANSMISSION_REMOTE=true # Get and validate hostname while true; do read -p "Remote Transmission host [localhost]: " input_trans_host if [ -z "$input_trans_host" ]; then break elif validate_hostname "$input_trans_host"; then TRANSMISSION_HOST="$input_trans_host" break else log "WARN" "Invalid hostname format." fi done # Get and validate port while true; do read -p "Remote Transmission port [9091]: " input_trans_port if [ -z "$input_trans_port" ]; then break elif validate_port "$input_trans_port"; then TRANSMISSION_PORT="$input_trans_port" break else log "WARN" "Invalid port number. Port must be between 1 and 65535." fi done # Get credentials read -p "Remote Transmission username []: " input_trans_user TRANSMISSION_USER=${input_trans_user:-$TRANSMISSION_USER} # Use read -s for password to avoid showing it on screen read -s -p "Remote Transmission password []: " input_trans_pass echo # Add a newline after the password input if [ -n "$input_trans_pass" ]; then # TODO: In a production environment, consider encrypting this password TRANSMISSION_PASS="$input_trans_pass" fi read -p "Remote Transmission RPC path [/transmission/rpc]: " input_trans_path if [ -n "$input_trans_path" ]; then # Ensure path starts with / for consistency if [[ ! "$input_trans_path" =~ ^/ ]]; then input_trans_path="/$input_trans_path" fi TRANSMISSION_RPC_PATH="$input_trans_path" fi # Configure directory mapping for remote setup echo echo -e "${YELLOW}Directory Mapping Configuration${NC}" echo -e "When using a remote Transmission server, you need to map paths between servers." echo -e "For each directory on the remote server, specify the corresponding local directory." echo # Get remote download directory read -p "Remote Transmission download directory: " REMOTE_DOWNLOAD_DIR REMOTE_DOWNLOAD_DIR=${REMOTE_DOWNLOAD_DIR:-"/var/lib/transmission-daemon/downloads"} # Get local directory that corresponds to remote download directory read -p "Local directory that corresponds to the remote download directory: " LOCAL_DOWNLOAD_DIR LOCAL_DOWNLOAD_DIR=${LOCAL_DOWNLOAD_DIR:-"/mnt/transmission-downloads"} # Create mapping JSON - use proper JSON escaping for directory paths REMOTE_DOWNLOAD_DIR_ESCAPED=$(echo "$REMOTE_DOWNLOAD_DIR" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g') LOCAL_DOWNLOAD_DIR_ESCAPED=$(echo "$LOCAL_DOWNLOAD_DIR" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g') TRANSMISSION_DIR_MAPPING="{\"$REMOTE_DOWNLOAD_DIR_ESCAPED\": \"$LOCAL_DOWNLOAD_DIR_ESCAPED\"}" # Create the local directory if ! mkdir -p "$LOCAL_DOWNLOAD_DIR"; then log "ERROR" "Failed to create local download directory: $LOCAL_DOWNLOAD_DIR" else if ! chown -R "$USER:$USER" "$LOCAL_DOWNLOAD_DIR"; then log "ERROR" "Failed to set permissions on local download directory: $LOCAL_DOWNLOAD_DIR" fi fi # Ask if want to add more mappings while true; do read -p "Add another directory mapping? (y/n) [n]: " add_another if [[ ! $add_another =~ ^[Yy]$ ]]; then break fi read -p "Remote directory path: " remote_dir read -p "Corresponding local directory path: " local_dir if [ -n "$remote_dir" ] && [ -n "$local_dir" ]; then # Escape directory paths for JSON remote_dir_escaped=$(echo "$remote_dir" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g') local_dir_escaped=$(echo "$local_dir" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g') # Update mapping JSON (proper JSON manipulation) # Remove the closing brace, add a comma and the new mapping, then close with brace TRANSMISSION_DIR_MAPPING="${TRANSMISSION_DIR_MAPPING%\}}, \"$remote_dir_escaped\": \"$local_dir_escaped\"}" # Create the local directory if ! mkdir -p "$local_dir"; then log "ERROR" "Failed to create directory: $local_dir" else if ! chown -R "$USER:$USER" "$local_dir"; then log "WARN" "Failed to set permissions on directory: $local_dir" fi log "INFO" "Mapping added: $remote_dir → $local_dir" fi fi done # Set Transmission download dir for configuration TRANSMISSION_DOWNLOAD_DIR=$REMOTE_DOWNLOAD_DIR else # Local Transmission selected echo -e "${YELLOW}You've selected to use a local Transmission installation.${NC}" # Check if Transmission is already installed if command -v transmission-daemon &> /dev/null; then echo -e "${GREEN}Transmission is already installed on this system.${NC}" else echo -e "${YELLOW}NOTE: Transmission does not appear to be installed on this system.${NC}" echo -e "${YELLOW}You will be prompted to install it during the dependency installation step.${NC}" fi # Get and validate port while true; do read -p "Local Transmission port [9091]: " input_trans_port if [ -z "$input_trans_port" ]; then break elif validate_port "$input_trans_port"; then TRANSMISSION_PORT="$input_trans_port" break else log "WARN" "Invalid port number. Port must be between 1 and 65535." fi done # Get credentials if any read -p "Local Transmission username (leave empty if authentication is disabled) []: " input_trans_user TRANSMISSION_USER=${input_trans_user:-$TRANSMISSION_USER} if [ -n "$input_trans_user" ]; then # Use read -s for password to hide it read -s -p "Local Transmission password []: " input_trans_pass echo # Add a newline after the password input if [ -n "$input_trans_pass" ]; then TRANSMISSION_PASS="$input_trans_pass" fi fi read -p "Transmission download directory [/var/lib/transmission-daemon/downloads]: " input_trans_dir if [ -n "$input_trans_dir" ]; then if [[ ! "$input_trans_dir" =~ ^/ ]]; then log "WARN" "Download directory must be an absolute path. Using default." else TRANSMISSION_DOWNLOAD_DIR="$input_trans_dir" fi fi fi echo echo -e "${BOLD}Media Destination Configuration:${NC}" read -p "Media destination base directory [/mnt/media]: " input_media_dir if [ -n "$input_media_dir" ]; then if [[ ! "$input_media_dir" =~ ^/ ]]; then log "WARN" "Media directory must be an absolute path. Using default." else MEDIA_DIR="$input_media_dir" fi fi # Ask about enabling book/magazine sorting echo echo -e "${BOLD}Content Type Configuration:${NC}" read -p "Enable book and magazine sorting? (y/n) [y]: " input_book_sorting if [[ $input_book_sorting =~ ^[Nn]$ ]]; then ENABLE_BOOK_SORTING=false else ENABLE_BOOK_SORTING=true fi # Security configuration echo echo -e "${BOLD}Security Configuration:${NC}" # Ask about enabling authentication read -p "Enable authentication? (y/n) [n]: " input_auth_enabled AUTH_ENABLED=false ADMIN_USERNAME="" ADMIN_PASSWORD="" if [[ $input_auth_enabled =~ ^[Yy]$ ]]; then AUTH_ENABLED=true # Get admin username and password read -p "Admin username [admin]: " input_admin_username ADMIN_USERNAME=${input_admin_username:-"admin"} # Use read -s for password to avoid showing it on screen read -s -p "Admin password: " input_admin_password echo # Add a newline after the password input if [ -z "$input_admin_password" ]; then # Generate a random password if none provided ADMIN_PASSWORD=$(openssl rand -base64 12) echo -e "${YELLOW}Generated random admin password: $ADMIN_PASSWORD${NC}" echo -e "${YELLOW}Please save this password somewhere safe!${NC}" else ADMIN_PASSWORD="$input_admin_password" fi fi # Ask about enabling HTTPS read -p "Enable HTTPS? (requires SSL certificate) (y/n) [n]: " input_https_enabled HTTPS_ENABLED=false SSL_CERT_PATH="" SSL_KEY_PATH="" if [[ $input_https_enabled =~ ^[Yy]$ ]]; then HTTPS_ENABLED=true # Get SSL certificate paths read -p "SSL certificate path: " input_ssl_cert_path if [ -n "$input_ssl_cert_path" ]; then # Check if file exists if [ -f "$input_ssl_cert_path" ]; then SSL_CERT_PATH="$input_ssl_cert_path" else log "WARN" "SSL certificate file not found. HTTPS will be disabled." HTTPS_ENABLED=false fi else log "WARN" "SSL certificate path not provided. HTTPS will be disabled." HTTPS_ENABLED=false fi # Only ask for key if cert was found if [ "$HTTPS_ENABLED" = true ]; then read -p "SSL key path: " input_ssl_key_path if [ -n "$input_ssl_key_path" ]; then # Check if file exists if [ -f "$input_ssl_key_path" ]; then SSL_KEY_PATH="$input_ssl_key_path" else log "WARN" "SSL key file not found. HTTPS will be disabled." HTTPS_ENABLED=false fi else log "WARN" "SSL key path not provided. HTTPS will be disabled." HTTPS_ENABLED=false fi fi fi echo log "INFO" "Configuration gathering complete" echo -e "${GREEN}Configuration complete!${NC}" echo }