#!/bin/bash # Transmission-related functions for torrent-mover # get_destination: Maps a source directory to a destination directory based on keywords and patterns get_destination() { local source_path="$1" # Check if source_path is valid before accessing the array if [[ -z "${source_path}" ]]; then log_warn "Empty source path provided to get_destination" return "${DEFAULT_DST}" fi # Check if path is already in the cache if [[ -n "${PATH_CACHE["${source_path}"]+x}" ]]; then local cached_destination="${PATH_CACHE["${source_path}"]}" log_debug "Using cached destination for ${source_path}: ${cached_destination}" echo "${cached_destination}" return fi # Skip recursive path analysis - only log once if [[ "${source_path}" =~ ^/mnt/dsnas1/ ]]; then # Already in destination format, return as is log_debug "Path already in destination format: ${source_path}" PATH_CACHE["${source_path}"]="${source_path}" echo "${source_path}" return fi # For paths in dsnas2, check if they map to same structure in dsnas1 if [[ "${source_path}" =~ ^/mnt/dsnas2/ ]]; then local dir_suffix="${source_path#/mnt/dsnas2/}" local potential_dest="/mnt/dsnas1/${dir_suffix}" # If the directories match exactly in structure, only on different mounts, # return the source to avoid needless copying if [[ -d "${potential_dest}" ]]; then log_debug "Path maps to same structure on different mount: ${source_path} -> ${source_path}" PATH_CACHE["${source_path}"]="${source_path}" echo "${source_path}" return fi fi log_info "Analyzing path: ${source_path}" local destination="${DEFAULT_DST}" # Match using custom patterns from config file if they exist if [[ -n "${CUSTOM_PATTERNS}" ]]; then log_debug "Using custom patterns from config..." # Parse and apply each pattern IFS=';' read -ra PATTERN_ARRAY <<< "${CUSTOM_PATTERNS}" for pattern in "${PATTERN_ARRAY[@]}"; do IFS='=' read -ra PARTS <<< "${pattern}" if [[ "${#PARTS[@]}" -eq 2 ]]; then local regex="${PARTS[0]}" local dest="${PARTS[1]}" if [[ "${source_path,,}" =~ ${regex,,} ]]; then log_info "Custom pattern match: ${regex} -> ${dest}" destination="${dest}" break fi fi done fi # If no custom pattern matched, use default category mapping if [[ "${destination}" == "${DEFAULT_DST}" ]]; then case "${source_path,,}" in *games*) destination="${DIR_GAMES_DST}";; *apps*|*applications*|*programs*|*software*) destination="${DIR_APPS_DST}";; *movies*|*film*|*video*) destination="${DIR_MOVIES_DST}";; *books*|*ebook*|*pdf*|*epub*) destination="${DIR_BOOKS_DST}";; *tv*|*series*|*episode*) if [[ -n "${DIR_TV_DST}" ]]; then destination="${DIR_TV_DST}" else destination="${DIR_MOVIES_DST}" fi ;; *music*|*audio*|*mp3*|*flac*) if [[ -n "${DIR_MUSIC_DST}" ]]; then destination="${DIR_MUSIC_DST}" else destination="${DEFAULT_DST}" fi ;; esac fi log_info "Mapped to: ${destination}" # Only set in cache if source_path is not empty if [[ -n "${source_path}" ]]; then PATH_CACHE["${source_path}"]="${destination}" fi echo "${destination}" } # process_removal: Removes a torrent via Transmission. process_removal() { local id="$1" if (( DRY_RUN )); then log_info "[DRY RUN] Would remove torrent ${id}" return fi local cmd="transmission-remote ${TRANSMISSION_IP}:${TRANSMISSION_PORT} -n ${TRANSMISSION_USER}:${TRANSMISSION_PASSWORD} -t ${id} --remove-and-delete" retry_command "$cmd" 3 15 } # get_torrents: Retrieves a list of torrents from Transmission get_torrents() { # Log connection parameters (redacted password) log_info "Transmission connection parameters:" log_info " IP: ${TRANSMISSION_IP}:${TRANSMISSION_PORT}" log_info " Username: ${TRANSMISSION_USER}" log_info " Password: [redacted]" # Try a direct command without using retry_command to get clearer error messages log_info "Direct transmission-remote access test:" local test_output test_output=$(transmission-remote "${TRANSMISSION_IP}:${TRANSMISSION_PORT}" -n "${TRANSMISSION_USER}:${TRANSMISSION_PASSWORD}" -l 2>&1) local test_exit=$? if [[ $test_exit -ne 0 ]]; then log_error "Direct transmission-remote test failed with exit code: $test_exit" log_error "Error output: $test_output" # Continue anyway to see retry attempt logs else log_info "Direct transmission-remote test succeeded" fi # Execute the actual command with retries local real_cmd="transmission-remote ${TRANSMISSION_IP}:${TRANSMISSION_PORT} -n ${TRANSMISSION_USER}:${TRANSMISSION_PASSWORD} -l" local output output=$(retry_command "$real_cmd" 3 20) # Line-by-line raw output inspection (debugging) log_info "Raw command output detailed analysis:" if [[ -z "$output" ]]; then log_error "Command produced EMPTY output" else log_info "Output length: $(echo "$output" | wc -l) lines" echo "$output" | while IFS= read -r line; do log_info " LINE: '$line'" done fi # Extract IDs directly using awk with detailed debugging log_info "Extracting torrent IDs from output..." local line_num=0 local found_ids=0 echo "$output" | while IFS= read -r line; do line_num=$((line_num + 1)) # Skip header line if [[ $line_num -eq 1 ]]; then log_info " Skipping header: '$line'" continue fi # Check for torrent ID in first column local potential_id potential_id=$(echo "$line" | awk '{gsub(/^[ ]+/, "", $1); print $1}') log_info " Line $line_num: potential ID '$potential_id'" if [[ "$potential_id" =~ ^[0-9]+$ ]]; then log_info " Found valid ID: $potential_id" found_ids=$((found_ids + 1)) echo "$potential_id" else log_info " Not a valid ID: '$potential_id'" fi done | tee /tmp/torrent_ids.txt # Read back the file to get around pipe subshell issues local torrent_ids torrent_ids=$(cat /tmp/torrent_ids.txt) rm -f /tmp/torrent_ids.txt # Check if we found any torrents if [[ -z "$torrent_ids" ]]; then log_error "NO TORRENT IDs FOUND in transmission output" else log_info "Found torrent IDs: $torrent_ids" fi # Fallback to hardcoded ID for testing if nothing found if [[ -z "$torrent_ids" && "${DRY_RUN}" -eq 1 ]]; then log_info "DRY RUN MODE: Adding test torrent ID 1 for debugging" echo "1" else echo "$torrent_ids" fi } # get_torrent_info: Gets detailed info for a specific torrent get_torrent_info() { local id="$1" local cmd="transmission-remote ${TRANSMISSION_IP}:${TRANSMISSION_PORT} -n ${TRANSMISSION_USER}:${TRANSMISSION_PASSWORD} -t ${id} -i" retry_command "$cmd" 3 15 }