Compare commits
2 Commits
bd55ef8613
...
3cfc5f3489
Author | SHA1 | Date | |
---|---|---|---|
3cfc5f3489 | |||
f5404c241d |
@ -1,9 +1,14 @@
|
||||
# Transmission RSS Manager v2.0.1
|
||||
# Transmission RSS Manager v2.0.2
|
||||
|
||||
A comprehensive web-based tool to automate and manage your Transmission torrent downloads with RSS feed integration, intelligent media organization, and enhanced security features. Now with automatic updates and easy installation!
|
||||
|
||||
## Changelog
|
||||
|
||||
### v2.0.2 (2025-03-05)
|
||||
- **Fixed**: Bug in installer that would prompt to install Transmission for remote configurations
|
||||
- **Improved**: Better detection of remote vs local Transmission installations
|
||||
- **Improved**: Installation process now checks the TRANSMISSION_REMOTE flag correctly
|
||||
|
||||
### v2.0.1 (2025-03-05)
|
||||
- **New**: Automatic detection of existing installations for seamless updates
|
||||
- **Improved**: Enhanced update process that preserves existing configurations
|
||||
|
@ -35,8 +35,8 @@ function install_dependencies() {
|
||||
log "INFO" "Node.js is already installed."
|
||||
fi
|
||||
|
||||
# Check if we need to install Transmission (only if local transmission was selected)
|
||||
if [ "$TRANSMISSION_HOST" = "localhost" ] || [ "$TRANSMISSION_HOST" = "127.0.0.1" ]; then
|
||||
# Check if we need to install Transmission (only if local transmission was selected and not remote)
|
||||
if [ "$TRANSMISSION_REMOTE" = false ] && ([ "$TRANSMISSION_HOST" = "localhost" ] || [ "$TRANSMISSION_HOST" = "127.0.0.1" ]); then
|
||||
if ! command_exists transmission-daemon; then
|
||||
log "INFO" "Local Transmission installation selected, but transmission-daemon is not installed."
|
||||
read -p "Would you like to install Transmission now? (y/n): " install_transmission
|
||||
@ -109,8 +109,8 @@ function install_dependencies() {
|
||||
local dependencies=("node" "npm" "unzip" "nginx")
|
||||
local missing_deps=()
|
||||
|
||||
# Add transmission to dependencies check if local installation was selected
|
||||
if [ "$TRANSMISSION_HOST" = "localhost" ] || [ "$TRANSMISSION_HOST" = "127.0.0.1" ]; then
|
||||
# Add transmission to dependencies check if local installation was selected and not remote
|
||||
if [ "$TRANSMISSION_REMOTE" = false ] && ([ "$TRANSMISSION_HOST" = "localhost" ] || [ "$TRANSMISSION_HOST" = "127.0.0.1" ]); then
|
||||
dependencies+=("transmission-daemon")
|
||||
fi
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "transmission-rss-manager",
|
||||
"version": "2.0.1",
|
||||
"version": "2.0.2",
|
||||
"description": "A comprehensive web-based tool to automate and manage your Transmission torrent downloads with RSS feed integration and intelligent media organization",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
|
75
temp_work/SUMMARY.md
Normal file
75
temp_work/SUMMARY.md
Normal file
@ -0,0 +1,75 @@
|
||||
# Git-Based Installation and Update System
|
||||
|
||||
We've restructured the Transmission RSS Manager to use a git-based approach for installation and updates. Here's how the new system works:
|
||||
|
||||
## New Architecture
|
||||
|
||||
1. **Bootstrap Installer**
|
||||
- Small, self-contained installer script
|
||||
- Installs git if needed
|
||||
- Clones the main repository
|
||||
- Runs the main installer
|
||||
|
||||
2. **Main Installer**
|
||||
- Modified to work with git-managed files
|
||||
- Doesn't need to generate application files
|
||||
- Only creates config files and sets up services
|
||||
|
||||
3. **Update System**
|
||||
- Web interface shows current version
|
||||
- Checks for updates automatically
|
||||
- One-click update process
|
||||
- Preserves user configuration
|
||||
|
||||
## Key Files
|
||||
|
||||
1. **bootstrap-installer.sh**
|
||||
- Entry point for new installations
|
||||
- Minimal script that pulls everything else from git
|
||||
|
||||
2. **update.sh**
|
||||
- Located in the scripts/ directory
|
||||
- Handles git pull and service restart
|
||||
- Preserves local configuration changes
|
||||
|
||||
3. **System Status UI**
|
||||
- Added to the dashboard
|
||||
- Shows version, uptime, and connection status
|
||||
- Notifies when updates are available
|
||||
|
||||
4. **Server Endpoints**
|
||||
- `/api/system/status` - Gets current version and system status
|
||||
- `/api/system/check-updates` - Checks if updates are available
|
||||
- `/api/system/update` - Triggers the update process
|
||||
|
||||
## Benefits
|
||||
|
||||
1. **Simplified Maintenance**
|
||||
- Single source of truth in the git repository
|
||||
- No need to embed code in installation scripts
|
||||
- Easy to make changes and publish updates
|
||||
|
||||
2. **Better User Experience**
|
||||
- Users can see when updates are available
|
||||
- One-click update process
|
||||
- No need to manually download and run scripts
|
||||
|
||||
3. **Version Control**
|
||||
- Clear versioning visible to users
|
||||
- Update history preserved in git
|
||||
- Easy rollback if needed
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
This implementation preserves local configuration by:
|
||||
1. Stashing local changes before pulling updates
|
||||
2. Applying those changes back after the update
|
||||
3. Handling any potential conflicts
|
||||
|
||||
The service automatically restarts after updates, ensuring users always have the latest version running.
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Update the GitHub repository structure to match this new approach
|
||||
2. Test the installation and update process in a clean environment
|
||||
3. Consider adding a changelog display in the UI to show what's new in each version
|
131
temp_work/app-update.js
Normal file
131
temp_work/app-update.js
Normal file
@ -0,0 +1,131 @@
|
||||
// Client-side JavaScript for system status and updates
|
||||
// Add this to the public/js/app.js file
|
||||
|
||||
// System status and updates functionality
|
||||
function initSystemStatus() {
|
||||
// Elements
|
||||
const versionElement = document.getElementById('system-version');
|
||||
const uptimeElement = document.getElementById('uptime');
|
||||
const transmissionStatusElement = document.getElementById('transmission-status');
|
||||
const updateStatusElement = document.getElementById('update-status');
|
||||
const updateAvailableDiv = document.getElementById('update-available');
|
||||
const updateButton = document.getElementById('btn-update-now');
|
||||
const refreshButton = document.getElementById('btn-refresh-status');
|
||||
|
||||
// Load system status
|
||||
function loadSystemStatus() {
|
||||
fetch('/api/system/status')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.status === 'success') {
|
||||
versionElement.textContent = data.data.version;
|
||||
uptimeElement.textContent = data.data.uptime;
|
||||
|
||||
// Update transmission status with icon
|
||||
if (data.data.transmissionStatus === 'Connected') {
|
||||
transmissionStatusElement.innerHTML = '<i class="fas fa-check-circle text-success"></i> Connected';
|
||||
} else {
|
||||
transmissionStatusElement.innerHTML = '<i class="fas fa-times-circle text-danger"></i> Disconnected';
|
||||
}
|
||||
} else {
|
||||
showToast('error', 'Failed to load system status');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error fetching system status:', error);
|
||||
showToast('error', 'Failed to connect to server');
|
||||
});
|
||||
}
|
||||
|
||||
// Check for updates
|
||||
function checkForUpdates() {
|
||||
updateStatusElement.innerHTML = '<i class="fas fa-circle-notch fa-spin"></i> Checking...';
|
||||
updateAvailableDiv.classList.add('d-none');
|
||||
|
||||
fetch('/api/system/check-updates')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.status === 'success') {
|
||||
if (data.data.updateAvailable) {
|
||||
updateStatusElement.innerHTML = '<i class="fas fa-exclamation-circle text-warning"></i> Update available';
|
||||
updateAvailableDiv.classList.remove('d-none');
|
||||
updateAvailableDiv.querySelector('span').textContent =
|
||||
`A new version is available: ${data.data.currentVersion} → ${data.data.remoteVersion}`;
|
||||
} else {
|
||||
updateStatusElement.innerHTML = '<i class="fas fa-check-circle text-success"></i> Up to date';
|
||||
}
|
||||
} else {
|
||||
updateStatusElement.innerHTML = '<i class="fas fa-times-circle text-danger"></i> Check failed';
|
||||
showToast('error', data.message || 'Failed to check for updates');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error checking for updates:', error);
|
||||
updateStatusElement.innerHTML = '<i class="fas fa-times-circle text-danger"></i> Check failed';
|
||||
showToast('error', 'Failed to connect to server');
|
||||
});
|
||||
}
|
||||
|
||||
// Apply update
|
||||
function applyUpdate() {
|
||||
// Show confirmation dialog
|
||||
if (!confirm('Are you sure you want to update the application? The service will restart.')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Show loading state
|
||||
updateButton.disabled = true;
|
||||
updateButton.innerHTML = '<i class="fas fa-circle-notch fa-spin"></i> Updating...';
|
||||
showToast('info', 'Applying update. Please wait...');
|
||||
|
||||
fetch('/api/system/update', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.status === 'success') {
|
||||
showToast('success', 'Update applied successfully. The page will reload in 30 seconds.');
|
||||
// Set a timer to reload the page after the service has time to restart
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 30000);
|
||||
} else {
|
||||
updateButton.disabled = false;
|
||||
updateButton.innerHTML = '<i class="fas fa-download"></i> Update Now';
|
||||
showToast('error', data.message || 'Failed to apply update');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error applying update:', error);
|
||||
updateButton.disabled = false;
|
||||
updateButton.innerHTML = '<i class="fas fa-download"></i> Update Now';
|
||||
showToast('error', 'Failed to connect to server');
|
||||
});
|
||||
}
|
||||
|
||||
// Event listeners
|
||||
if (refreshButton) {
|
||||
refreshButton.addEventListener('click', () => {
|
||||
loadSystemStatus();
|
||||
checkForUpdates();
|
||||
});
|
||||
}
|
||||
|
||||
if (updateButton) {
|
||||
updateButton.addEventListener('click', applyUpdate);
|
||||
}
|
||||
|
||||
// Initialize
|
||||
loadSystemStatus();
|
||||
checkForUpdates();
|
||||
|
||||
// Set interval to refresh uptime every minute
|
||||
setInterval(loadSystemStatus, 60000);
|
||||
}
|
||||
|
||||
// Call this function from the main init function
|
||||
// Add this line to your document ready or DOMContentLoaded handler:
|
||||
// initSystemStatus();
|
72
temp_work/bootstrap-installer.sh
Normal file
72
temp_work/bootstrap-installer.sh
Normal file
@ -0,0 +1,72 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Transmission RSS Manager - Bootstrap Installer
|
||||
# This script downloads the latest version from git and runs the setup
|
||||
|
||||
# Color and formatting
|
||||
GREEN='\033[0;32m'
|
||||
RED='\033[0;31m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
BOLD='\033[1m'
|
||||
|
||||
# Installation directory
|
||||
INSTALL_DIR="/opt/trans-install"
|
||||
REPO_URL="https://git.powerdata.dk/masterdraco/transmission-rss-manager.git"
|
||||
|
||||
# Check if running as root
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo -e "${RED}This script must be run as root or with sudo privileges.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Display welcome message
|
||||
echo -e "${GREEN}${BOLD}Transmission RSS Manager - Bootstrap Installer${NC}"
|
||||
echo -e "This script will install the latest version from the git repository."
|
||||
echo
|
||||
|
||||
# Check for git installation
|
||||
echo -e "${YELLOW}Checking dependencies...${NC}"
|
||||
if ! command -v git &> /dev/null; then
|
||||
echo -e "Git not found. Installing git..."
|
||||
apt-get update
|
||||
apt-get install -y git
|
||||
fi
|
||||
|
||||
# Check if installation directory exists
|
||||
if [ -d "$INSTALL_DIR" ]; then
|
||||
echo -e "${YELLOW}Installation directory already exists.${NC}"
|
||||
read -p "Do you want to remove it and perform a fresh install? (y/n): " choice
|
||||
if [[ "$choice" =~ ^[Yy]$ ]]; then
|
||||
echo "Removing existing installation..."
|
||||
rm -rf "$INSTALL_DIR"
|
||||
else
|
||||
echo -e "${RED}Installation aborted.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Create installation directory
|
||||
echo -e "${YELLOW}Creating installation directory...${NC}"
|
||||
mkdir -p "$INSTALL_DIR"
|
||||
|
||||
# Clone the repository
|
||||
echo -e "${YELLOW}Cloning the latest version from git...${NC}"
|
||||
git clone "$REPO_URL" "$INSTALL_DIR"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "${RED}Failed to clone the repository.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Run the main installer
|
||||
echo -e "${YELLOW}Running the main installer...${NC}"
|
||||
cd "$INSTALL_DIR"
|
||||
chmod +x main-installer.sh
|
||||
./main-installer.sh
|
||||
|
||||
# Installation complete
|
||||
echo -e "${GREEN}${BOLD}Bootstrap installation complete!${NC}"
|
||||
echo -e "Transmission RSS Manager has been installed in $INSTALL_DIR"
|
||||
echo -e "You can access the web interface at http://localhost:3000"
|
||||
echo
|
||||
echo -e "To update in the future, use the update button in the System Status section of the web interface."
|
374
temp_work/config-module-updated.sh
Normal file
374
temp_work/config-module-updated.sh
Normal file
@ -0,0 +1,374 @@
|
||||
#!/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
|
||||
}
|
184
temp_work/dependencies-module-updated.sh
Normal file
184
temp_work/dependencies-module-updated.sh
Normal file
@ -0,0 +1,184 @@
|
||||
#!/bin/bash
|
||||
# Dependencies module for Transmission RSS Manager Installation
|
||||
|
||||
function install_dependencies() {
|
||||
log "INFO" "Installing dependencies..."
|
||||
|
||||
# Check for package manager
|
||||
if command -v apt-get &> /dev/null; then
|
||||
# Update package index
|
||||
apt-get update
|
||||
|
||||
# Install Node.js and npm if not already installed
|
||||
if ! command_exists node; then
|
||||
log "INFO" "Installing Node.js and npm..."
|
||||
apt-get install -y ca-certificates curl gnupg
|
||||
mkdir -p /etc/apt/keyrings
|
||||
|
||||
# Check if download succeeds
|
||||
if ! curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg; then
|
||||
log "ERROR" "Failed to download Node.js GPG key"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_18.x nodistro main" > /etc/apt/sources.list.d/nodesource.list
|
||||
|
||||
# Update again after adding repo
|
||||
apt-get update
|
||||
|
||||
# Install nodejs
|
||||
if ! apt-get install -y nodejs; then
|
||||
log "ERROR" "Failed to install Node.js"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
log "INFO" "Node.js is already installed."
|
||||
fi
|
||||
|
||||
# Check if we need to install Transmission (only if local transmission was selected and not remote)
|
||||
if [ "$TRANSMISSION_REMOTE" = false ] && ([ "$TRANSMISSION_HOST" = "localhost" ] || [ "$TRANSMISSION_HOST" = "127.0.0.1" ]); then
|
||||
if ! command_exists transmission-daemon; then
|
||||
log "INFO" "Local Transmission installation selected, but transmission-daemon is not installed."
|
||||
read -p "Would you like to install Transmission now? (y/n): " install_transmission
|
||||
|
||||
if [[ "$install_transmission" =~ ^[Yy]$ ]]; then
|
||||
log "INFO" "Installing Transmission..."
|
||||
if ! apt-get install -y transmission-daemon; then
|
||||
log "ERROR" "Failed to install Transmission"
|
||||
log "WARN" "You will need to install Transmission manually before using this application."
|
||||
else
|
||||
# Stop transmission-daemon to allow configuration changes
|
||||
systemctl stop transmission-daemon
|
||||
|
||||
# Set default settings
|
||||
TRANSMISSION_SETTINGS_DIR="/var/lib/transmission-daemon/info"
|
||||
if [ -f "$TRANSMISSION_SETTINGS_DIR/settings.json" ]; then
|
||||
# Backup original settings
|
||||
cp "$TRANSMISSION_SETTINGS_DIR/settings.json" "$TRANSMISSION_SETTINGS_DIR/settings.json.bak"
|
||||
|
||||
# Update RPC settings to allow our app to connect
|
||||
sed -i 's/"rpc-authentication-required": true,/"rpc-authentication-required": false,/g' "$TRANSMISSION_SETTINGS_DIR/settings.json"
|
||||
sed -i 's/"rpc-whitelist-enabled": true,/"rpc-whitelist-enabled": false,/g' "$TRANSMISSION_SETTINGS_DIR/settings.json"
|
||||
|
||||
log "INFO" "Transmission has been configured for local access."
|
||||
else
|
||||
log "WARN" "Could not find Transmission settings file. You may need to configure Transmission manually."
|
||||
fi
|
||||
|
||||
# Start transmission-daemon
|
||||
systemctl start transmission-daemon
|
||||
log "INFO" "Transmission has been installed and started."
|
||||
fi
|
||||
else
|
||||
log "WARN" "Transmission installation skipped. You will need to install it manually."
|
||||
fi
|
||||
else
|
||||
log "INFO" "Transmission is already installed."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Install additional dependencies
|
||||
log "INFO" "Installing additional dependencies..."
|
||||
# Try to install unrar-free if unrar is not available
|
||||
if ! apt-get install -y unrar 2>/dev/null; then
|
||||
log "INFO" "unrar not available, trying unrar-free instead..."
|
||||
apt-get install -y unrar-free
|
||||
fi
|
||||
|
||||
# Install other dependencies
|
||||
apt-get install -y unzip p7zip-full
|
||||
|
||||
# Try to install nginx
|
||||
apt-get install -y nginx || log "WARN" "Nginx installation failed, web interface may not be accessible"
|
||||
else
|
||||
log "ERROR" "This installer requires apt-get package manager"
|
||||
log "INFO" "Please install the following dependencies manually:"
|
||||
log "INFO" "- Node.js (v18.x)"
|
||||
log "INFO" "- npm"
|
||||
log "INFO" "- unrar"
|
||||
log "INFO" "- unzip"
|
||||
log "INFO" "- p7zip-full"
|
||||
log "INFO" "- nginx"
|
||||
if [ "$TRANSMISSION_REMOTE" = false ] && ([ "$TRANSMISSION_HOST" = "localhost" ] || [ "$TRANSMISSION_HOST" = "127.0.0.1" ]); then
|
||||
log "INFO" "- transmission-daemon"
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if all dependencies were installed successfully
|
||||
local dependencies=("node" "npm" "unzip" "nginx")
|
||||
local missing_deps=()
|
||||
|
||||
# Add transmission to dependencies check if local installation was selected and not remote
|
||||
if [ "$TRANSMISSION_REMOTE" = false ] && ([ "$TRANSMISSION_HOST" = "localhost" ] || [ "$TRANSMISSION_HOST" = "127.0.0.1" ]); then
|
||||
dependencies+=("transmission-daemon")
|
||||
fi
|
||||
|
||||
for dep in "${dependencies[@]}"; do
|
||||
if ! command_exists "$dep"; then
|
||||
missing_deps+=("$dep")
|
||||
fi
|
||||
done
|
||||
|
||||
# Check for either unrar or unrar-free
|
||||
if ! command_exists "unrar" && ! command_exists "unrar-free"; then
|
||||
missing_deps+=("unrar")
|
||||
fi
|
||||
|
||||
# Check for either 7z or 7za (from p7zip-full)
|
||||
if ! command_exists "7z" && ! command_exists "7za"; then
|
||||
missing_deps+=("p7zip")
|
||||
fi
|
||||
|
||||
if [ ${#missing_deps[@]} -eq 0 ]; then
|
||||
log "INFO" "All dependencies installed successfully."
|
||||
else
|
||||
log "ERROR" "Failed to install some dependencies: ${missing_deps[*]}"
|
||||
log "WARN" "Please install them manually and rerun this script."
|
||||
|
||||
# More helpful information based on which deps are missing
|
||||
if [[ " ${missing_deps[*]} " =~ " node " ]]; then
|
||||
log "INFO" "To install Node.js manually, visit: https://nodejs.org/en/download/"
|
||||
fi
|
||||
|
||||
if [[ " ${missing_deps[*]} " =~ " nginx " ]]; then
|
||||
log "INFO" "To install nginx manually: sudo apt-get install nginx"
|
||||
fi
|
||||
|
||||
if [[ " ${missing_deps[*]} " =~ " transmission-daemon " ]]; then
|
||||
log "INFO" "To install Transmission manually: sudo apt-get install transmission-daemon"
|
||||
log "INFO" "After installation, you may need to configure it by editing /var/lib/transmission-daemon/info/settings.json"
|
||||
fi
|
||||
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
function create_directories() {
|
||||
log "INFO" "Creating installation directories..."
|
||||
|
||||
# Check if INSTALL_DIR is defined
|
||||
if [ -z "$INSTALL_DIR" ]; then
|
||||
log "ERROR" "INSTALL_DIR is not defined"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create directories and check for errors
|
||||
DIRECTORIES=(
|
||||
"$INSTALL_DIR"
|
||||
"$INSTALL_DIR/logs"
|
||||
"$INSTALL_DIR/public/js"
|
||||
"$INSTALL_DIR/public/css"
|
||||
"$INSTALL_DIR/modules"
|
||||
"$INSTALL_DIR/data"
|
||||
)
|
||||
|
||||
for dir in "${DIRECTORIES[@]}"; do
|
||||
if ! mkdir -p "$dir"; then
|
||||
log "ERROR" "Failed to create directory: $dir"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
log "INFO" "Directories created successfully."
|
||||
}
|
241
temp_work/main-installer-modified.sh
Normal file
241
temp_work/main-installer-modified.sh
Normal file
@ -0,0 +1,241 @@
|
||||
#!/bin/bash
|
||||
# Transmission RSS Manager Modular Installer
|
||||
# Modified to work with the git-based approach
|
||||
|
||||
# Set script to exit on error
|
||||
set -e
|
||||
|
||||
# Text formatting
|
||||
BOLD='\033[1m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[0;33m'
|
||||
RED='\033[0;31m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Print header
|
||||
echo -e "${BOLD}==================================================${NC}"
|
||||
echo -e "${BOLD} Transmission RSS Manager Installer ${NC}"
|
||||
echo -e "${BOLD} Version 1.2.0 - Git Edition ${NC}"
|
||||
echo -e "${BOLD}==================================================${NC}"
|
||||
echo
|
||||
|
||||
# Check if script is run with sudo
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo -e "${RED}Please run as root (use sudo)${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get current directory
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
||||
|
||||
# Check for installation type
|
||||
IS_UPDATE=false
|
||||
if [ -f "${SCRIPT_DIR}/config.json" ]; then
|
||||
IS_UPDATE=true
|
||||
echo -e "${YELLOW}Existing installation detected. Running in update mode.${NC}"
|
||||
echo -e "${GREEN}Your existing configuration will be preserved.${NC}"
|
||||
else
|
||||
echo -e "${GREEN}Fresh installation. Will create new configuration.${NC}"
|
||||
fi
|
||||
export IS_UPDATE
|
||||
|
||||
# Check if required module files exist
|
||||
REQUIRED_MODULES=(
|
||||
"${SCRIPT_DIR}/modules/config-module.sh"
|
||||
"${SCRIPT_DIR}/modules/utils-module.sh"
|
||||
"${SCRIPT_DIR}/modules/dependencies-module.sh"
|
||||
"${SCRIPT_DIR}/modules/service-setup-module.sh"
|
||||
)
|
||||
|
||||
for module in "${REQUIRED_MODULES[@]}"; do
|
||||
if [ ! -f "$module" ]; then
|
||||
echo -e "${RED}Error: Required module file not found: $module${NC}"
|
||||
echo -e "${YELLOW}The module files should be included in the git repository.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Source the module files
|
||||
source "${SCRIPT_DIR}/modules/utils-module.sh" # Load utilities first for logging
|
||||
source "${SCRIPT_DIR}/modules/config-module.sh"
|
||||
source "${SCRIPT_DIR}/modules/dependencies-module.sh"
|
||||
source "${SCRIPT_DIR}/modules/service-setup-module.sh"
|
||||
|
||||
# Function to handle cleanup on error
|
||||
function cleanup_on_error() {
|
||||
log "ERROR" "Installation failed: $1"
|
||||
log "INFO" "Cleaning up..."
|
||||
|
||||
# Add any cleanup steps here if needed
|
||||
|
||||
log "INFO" "You can try running the installer again after fixing the issues."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Set trap for error handling
|
||||
trap 'cleanup_on_error "$BASH_COMMAND"' ERR
|
||||
|
||||
# Execute the installation steps in sequence
|
||||
log "INFO" "Starting installation process..."
|
||||
|
||||
# Step 1: Gather configuration from user
|
||||
log "INFO" "Gathering configuration..."
|
||||
gather_configuration || {
|
||||
log "ERROR" "Configuration gathering failed"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Step 2: Install dependencies
|
||||
log "INFO" "Installing dependencies..."
|
||||
install_dependencies || {
|
||||
log "ERROR" "Dependency installation failed"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Step 3: Create installation directories
|
||||
log "INFO" "Creating directories..."
|
||||
create_directories || {
|
||||
log "ERROR" "Directory creation failed"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Step 4: Create configuration files only (no application files since they're from git)
|
||||
log "INFO" "Creating configuration files..."
|
||||
create_config_files || {
|
||||
log "ERROR" "Configuration file creation failed"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Step 5: Create service files and install the service
|
||||
log "INFO" "Setting up service..."
|
||||
setup_service || {
|
||||
log "ERROR" "Service setup failed"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Step 6: Install npm dependencies
|
||||
log "INFO" "Installing npm dependencies..."
|
||||
cd "$SCRIPT_DIR"
|
||||
npm install || {
|
||||
log "ERROR" "NPM installation failed"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Step 7: Set up update script
|
||||
log "INFO" "Setting up update script..."
|
||||
mkdir -p "${SCRIPT_DIR}/scripts"
|
||||
cp "${SCRIPT_DIR}/scripts/update.sh" "${SCRIPT_DIR}/scripts/update.sh" 2>/dev/null || {
|
||||
# If copy fails, it probably doesn't exist, so we'll create it
|
||||
cat > "${SCRIPT_DIR}/scripts/update.sh" << 'EOL'
|
||||
#!/bin/bash
|
||||
|
||||
# Transmission RSS Manager - Update Script
|
||||
# This script pulls the latest version from git and runs necessary updates
|
||||
|
||||
# Color and formatting
|
||||
GREEN='\033[0;32m'
|
||||
RED='\033[0;31m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
BOLD='\033[1m'
|
||||
|
||||
# Installation directory (should be current directory)
|
||||
INSTALL_DIR=$(pwd)
|
||||
|
||||
# Check if we're in the right directory
|
||||
if [ ! -f "$INSTALL_DIR/package.json" ] || [ ! -d "$INSTALL_DIR/modules" ]; then
|
||||
echo -e "${RED}Error: This script must be run from the installation directory.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the current version
|
||||
CURRENT_VERSION=$(grep -oP '"version": "\K[^"]+' package.json)
|
||||
echo -e "${YELLOW}Current version: ${BOLD}$CURRENT_VERSION${NC}"
|
||||
|
||||
# Check for git repository
|
||||
if [ ! -d ".git" ]; then
|
||||
echo -e "${RED}Error: This installation was not set up using git.${NC}"
|
||||
echo -e "Please use the bootstrap installer to perform a fresh installation."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Stash any local changes
|
||||
echo -e "${YELLOW}Backing up any local configuration changes...${NC}"
|
||||
git stash -q
|
||||
|
||||
# Pull the latest changes
|
||||
echo -e "${YELLOW}Pulling latest updates from git...${NC}"
|
||||
git pull
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "${RED}Failed to pull updates. Restoring original state...${NC}"
|
||||
git stash pop -q
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the new version
|
||||
NEW_VERSION=$(grep -oP '"version": "\K[^"]+' package.json)
|
||||
echo -e "${GREEN}New version: ${BOLD}$NEW_VERSION${NC}"
|
||||
|
||||
# Check if update is needed
|
||||
if [ "$CURRENT_VERSION" == "$NEW_VERSION" ]; then
|
||||
echo -e "${GREEN}You already have the latest version.${NC}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Install any new npm dependencies
|
||||
echo -e "${YELLOW}Installing dependencies...${NC}"
|
||||
npm install
|
||||
|
||||
# Apply any local configuration changes
|
||||
if git stash list | grep -q "stash@{0}"; then
|
||||
echo -e "${YELLOW}Restoring local configuration changes...${NC}"
|
||||
git stash pop -q
|
||||
# Handle conflicts if any
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "${RED}There were conflicts when restoring your configuration.${NC}"
|
||||
echo -e "Please check the files and resolve conflicts manually."
|
||||
echo -e "Your original configuration is saved in .git/refs/stash"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Restart the service
|
||||
echo -e "${YELLOW}Restarting service...${NC}"
|
||||
if command -v systemctl &> /dev/null; then
|
||||
sudo systemctl restart transmission-rss-manager
|
||||
else
|
||||
echo -e "${RED}Could not restart service automatically.${NC}"
|
||||
echo -e "Please restart the service manually."
|
||||
fi
|
||||
|
||||
# Update complete
|
||||
echo -e "${GREEN}${BOLD}Update complete!${NC}"
|
||||
echo -e "Updated from version $CURRENT_VERSION to $NEW_VERSION"
|
||||
echo -e "Changes will take effect immediately."
|
||||
EOL
|
||||
|
||||
chmod +x "${SCRIPT_DIR}/scripts/update.sh"
|
||||
}
|
||||
|
||||
# Step 8: Final setup and permissions
|
||||
log "INFO" "Finalizing setup..."
|
||||
finalize_setup || {
|
||||
log "ERROR" "Setup finalization failed"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Installation complete
|
||||
echo
|
||||
echo -e "${BOLD}${GREEN}==================================================${NC}"
|
||||
echo -e "${BOLD}${GREEN} Installation Complete! ${NC}"
|
||||
echo -e "${BOLD}${GREEN}==================================================${NC}"
|
||||
echo -e "You can access the web interface at: ${BOLD}http://localhost:$PORT${NC} or ${BOLD}http://your-server-ip:$PORT${NC}"
|
||||
echo -e "You may need to configure your firewall to allow access to port $PORT"
|
||||
echo
|
||||
echo -e "${BOLD}Useful Commands:${NC}"
|
||||
echo -e " To check the service status: ${YELLOW}systemctl status $SERVICE_NAME${NC}"
|
||||
echo -e " To view logs: ${YELLOW}journalctl -u $SERVICE_NAME${NC}"
|
||||
echo -e " To restart the service: ${YELLOW}systemctl restart $SERVICE_NAME${NC}"
|
||||
echo -e " To update the application: ${YELLOW}Use the Update button in the System Status section${NC}"
|
||||
echo
|
||||
echo -e "Thank you for installing Transmission RSS Manager!"
|
||||
echo -e "${BOLD}==================================================${NC}"
|
84
temp_work/scripts/update.sh
Normal file
84
temp_work/scripts/update.sh
Normal file
@ -0,0 +1,84 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Transmission RSS Manager - Update Script
|
||||
# This script pulls the latest version from git and runs necessary updates
|
||||
|
||||
# Color and formatting
|
||||
GREEN='\033[0;32m'
|
||||
RED='\033[0;31m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
BOLD='\033[1m'
|
||||
|
||||
# Installation directory (should be current directory)
|
||||
INSTALL_DIR=$(pwd)
|
||||
|
||||
# Check if we're in the right directory
|
||||
if [ ! -f "$INSTALL_DIR/package.json" ] || [ ! -d "$INSTALL_DIR/modules" ]; then
|
||||
echo -e "${RED}Error: This script must be run from the installation directory.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the current version
|
||||
CURRENT_VERSION=$(grep -oP '"version": "\K[^"]+' package.json)
|
||||
echo -e "${YELLOW}Current version: ${BOLD}$CURRENT_VERSION${NC}"
|
||||
|
||||
# Check for git repository
|
||||
if [ ! -d ".git" ]; then
|
||||
echo -e "${RED}Error: This installation was not set up using git.${NC}"
|
||||
echo -e "Please use the bootstrap installer to perform a fresh installation."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Stash any local changes
|
||||
echo -e "${YELLOW}Backing up any local configuration changes...${NC}"
|
||||
git stash -q
|
||||
|
||||
# Pull the latest changes
|
||||
echo -e "${YELLOW}Pulling latest updates from git...${NC}"
|
||||
git pull
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "${RED}Failed to pull updates. Restoring original state...${NC}"
|
||||
git stash pop -q
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the new version
|
||||
NEW_VERSION=$(grep -oP '"version": "\K[^"]+' package.json)
|
||||
echo -e "${GREEN}New version: ${BOLD}$NEW_VERSION${NC}"
|
||||
|
||||
# Check if update is needed
|
||||
if [ "$CURRENT_VERSION" == "$NEW_VERSION" ]; then
|
||||
echo -e "${GREEN}You already have the latest version.${NC}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Install any new npm dependencies
|
||||
echo -e "${YELLOW}Installing dependencies...${NC}"
|
||||
npm install
|
||||
|
||||
# Apply any local configuration changes
|
||||
if git stash list | grep -q "stash@{0}"; then
|
||||
echo -e "${YELLOW}Restoring local configuration changes...${NC}"
|
||||
git stash pop -q
|
||||
# Handle conflicts if any
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "${RED}There were conflicts when restoring your configuration.${NC}"
|
||||
echo -e "Please check the files and resolve conflicts manually."
|
||||
echo -e "Your original configuration is saved in .git/refs/stash"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Restart the service
|
||||
echo -e "${YELLOW}Restarting service...${NC}"
|
||||
if command -v systemctl &> /dev/null; then
|
||||
sudo systemctl restart transmission-rss-manager
|
||||
else
|
||||
echo -e "${RED}Could not restart service automatically.${NC}"
|
||||
echo -e "Please restart the service manually."
|
||||
fi
|
||||
|
||||
# Update complete
|
||||
echo -e "${GREEN}${BOLD}Update complete!${NC}"
|
||||
echo -e "Updated from version $CURRENT_VERSION to $NEW_VERSION"
|
||||
echo -e "Changes will take effect immediately."
|
146
temp_work/server-endpoints.js
Normal file
146
temp_work/server-endpoints.js
Normal file
@ -0,0 +1,146 @@
|
||||
// Version and update endpoints to be added to server.js
|
||||
|
||||
// Add these imports at the top of server.js
|
||||
const { exec } = require('child_process');
|
||||
const { promisify } = require('util');
|
||||
const execAsync = promisify(exec);
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Add these endpoints
|
||||
|
||||
// Get system status including version and uptime
|
||||
app.get('/api/system/status', async (req, res) => {
|
||||
try {
|
||||
// Get package.json for version info
|
||||
const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8'));
|
||||
const version = packageJson.version;
|
||||
|
||||
// Get system uptime
|
||||
const uptimeSeconds = Math.floor(process.uptime());
|
||||
const hours = Math.floor(uptimeSeconds / 3600);
|
||||
const minutes = Math.floor((uptimeSeconds % 3600) / 60);
|
||||
const seconds = uptimeSeconds % 60;
|
||||
const uptime = `${hours}h ${minutes}m ${seconds}s`;
|
||||
|
||||
// Check transmission connection
|
||||
let transmissionStatus = 'Connected';
|
||||
try {
|
||||
await transmissionClient.sessionGet();
|
||||
} catch (err) {
|
||||
transmissionStatus = 'Disconnected';
|
||||
}
|
||||
|
||||
res.json({
|
||||
status: 'success',
|
||||
data: {
|
||||
version,
|
||||
uptime,
|
||||
transmissionStatus
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error getting system status:', error);
|
||||
res.status(500).json({
|
||||
status: 'error',
|
||||
message: 'Failed to get system status'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Check for updates
|
||||
app.get('/api/system/check-updates', async (req, res) => {
|
||||
try {
|
||||
// Check if git is available and if this is a git repository
|
||||
const isGitRepo = fs.existsSync(path.join(__dirname, '.git'));
|
||||
if (!isGitRepo) {
|
||||
return res.json({
|
||||
status: 'error',
|
||||
message: 'This installation is not set up for updates. Please use the bootstrap installer.'
|
||||
});
|
||||
}
|
||||
|
||||
// Get current version
|
||||
const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8'));
|
||||
const currentVersion = packageJson.version;
|
||||
|
||||
// Fetch latest updates without applying them
|
||||
await execAsync('git fetch');
|
||||
|
||||
// Check if we're behind the remote repository
|
||||
const { stdout } = await execAsync('git rev-list HEAD..origin/main --count');
|
||||
const behindCount = parseInt(stdout.trim());
|
||||
|
||||
if (behindCount > 0) {
|
||||
// Get the new version from the remote package.json
|
||||
const { stdout: remotePackageJson } = await execAsync('git show origin/main:package.json');
|
||||
const remotePackage = JSON.parse(remotePackageJson);
|
||||
const remoteVersion = remotePackage.version;
|
||||
|
||||
return res.json({
|
||||
status: 'success',
|
||||
data: {
|
||||
updateAvailable: true,
|
||||
currentVersion,
|
||||
remoteVersion,
|
||||
commitsBehind: behindCount
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return res.json({
|
||||
status: 'success',
|
||||
data: {
|
||||
updateAvailable: false,
|
||||
currentVersion
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error checking for updates:', error);
|
||||
res.status(500).json({
|
||||
status: 'error',
|
||||
message: 'Failed to check for updates'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Apply updates
|
||||
app.post('/api/system/update', async (req, res) => {
|
||||
try {
|
||||
// Check if git is available and if this is a git repository
|
||||
const isGitRepo = fs.existsSync(path.join(__dirname, '.git'));
|
||||
if (!isGitRepo) {
|
||||
return res.status(400).json({
|
||||
status: 'error',
|
||||
message: 'This installation is not set up for updates. Please use the bootstrap installer.'
|
||||
});
|
||||
}
|
||||
|
||||
// Run the update script
|
||||
const updateScriptPath = path.join(__dirname, 'scripts', 'update.sh');
|
||||
|
||||
// Make sure the update script is executable
|
||||
await execAsync(`chmod +x ${updateScriptPath}`);
|
||||
|
||||
// Execute the update script
|
||||
const { stdout, stderr } = await execAsync(updateScriptPath);
|
||||
|
||||
// If we get here, the update was successful
|
||||
// The service will be restarted by the update script
|
||||
res.json({
|
||||
status: 'success',
|
||||
message: 'Update applied successfully. The service will restart.',
|
||||
data: {
|
||||
output: stdout,
|
||||
errors: stderr
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error applying update:', error);
|
||||
res.status(500).json({
|
||||
status: 'error',
|
||||
message: 'Failed to apply update',
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
});
|
41
temp_work/system-status.html
Normal file
41
temp_work/system-status.html
Normal file
@ -0,0 +1,41 @@
|
||||
<!-- This HTML block will be inserted into the index.html dashboard -->
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-3">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4><i class="fas fa-info-circle"></i> System Status</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="status-item">
|
||||
<span class="status-label">Version:</span>
|
||||
<span id="system-version" class="status-value">Loading...</span>
|
||||
</div>
|
||||
<div class="status-item">
|
||||
<span class="status-label">Running since:</span>
|
||||
<span id="uptime" class="status-value">Loading...</span>
|
||||
</div>
|
||||
<div class="status-item">
|
||||
<span class="status-label">Transmission:</span>
|
||||
<span id="transmission-status" class="status-value">
|
||||
<i class="fas fa-circle-notch fa-spin"></i> Checking...
|
||||
</span>
|
||||
</div>
|
||||
<div class="status-item">
|
||||
<span class="status-label">Update:</span>
|
||||
<span id="update-status" class="status-value">
|
||||
<i class="fas fa-circle-notch fa-spin"></i> Checking...
|
||||
</span>
|
||||
</div>
|
||||
<div id="update-available" class="mt-3 d-none">
|
||||
<div class="alert alert-info">
|
||||
<i class="fas fa-arrow-circle-up"></i>
|
||||
<span>A new version is available!</span>
|
||||
<button id="btn-update-now" class="btn btn-sm btn-primary ml-2">
|
||||
<i class="fas fa-download"></i> Update Now
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
84
temp_work/update.sh
Normal file
84
temp_work/update.sh
Normal file
@ -0,0 +1,84 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Transmission RSS Manager - Update Script
|
||||
# This script pulls the latest version from git and runs necessary updates
|
||||
|
||||
# Color and formatting
|
||||
GREEN='\033[0;32m'
|
||||
RED='\033[0;31m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
BOLD='\033[1m'
|
||||
|
||||
# Installation directory (should be current directory)
|
||||
INSTALL_DIR=$(pwd)
|
||||
|
||||
# Check if we're in the right directory
|
||||
if [ ! -f "$INSTALL_DIR/package.json" ] || [ ! -d "$INSTALL_DIR/modules" ]; then
|
||||
echo -e "${RED}Error: This script must be run from the installation directory.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the current version
|
||||
CURRENT_VERSION=$(grep -oP '"version": "\K[^"]+' package.json)
|
||||
echo -e "${YELLOW}Current version: ${BOLD}$CURRENT_VERSION${NC}"
|
||||
|
||||
# Check for git repository
|
||||
if [ ! -d ".git" ]; then
|
||||
echo -e "${RED}Error: This installation was not set up using git.${NC}"
|
||||
echo -e "Please use the bootstrap installer to perform a fresh installation."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Stash any local changes
|
||||
echo -e "${YELLOW}Backing up any local configuration changes...${NC}"
|
||||
git stash -q
|
||||
|
||||
# Pull the latest changes
|
||||
echo -e "${YELLOW}Pulling latest updates from git...${NC}"
|
||||
git pull
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "${RED}Failed to pull updates. Restoring original state...${NC}"
|
||||
git stash pop -q
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the new version
|
||||
NEW_VERSION=$(grep -oP '"version": "\K[^"]+' package.json)
|
||||
echo -e "${GREEN}New version: ${BOLD}$NEW_VERSION${NC}"
|
||||
|
||||
# Check if update is needed
|
||||
if [ "$CURRENT_VERSION" == "$NEW_VERSION" ]; then
|
||||
echo -e "${GREEN}You already have the latest version.${NC}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Install any new npm dependencies
|
||||
echo -e "${YELLOW}Installing dependencies...${NC}"
|
||||
npm install
|
||||
|
||||
# Apply any local configuration changes
|
||||
if git stash list | grep -q "stash@{0}"; then
|
||||
echo -e "${YELLOW}Restoring local configuration changes...${NC}"
|
||||
git stash pop -q
|
||||
# Handle conflicts if any
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "${RED}There were conflicts when restoring your configuration.${NC}"
|
||||
echo -e "Please check the files and resolve conflicts manually."
|
||||
echo -e "Your original configuration is saved in .git/refs/stash"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Restart the service
|
||||
echo -e "${YELLOW}Restarting service...${NC}"
|
||||
if command -v systemctl &> /dev/null; then
|
||||
sudo systemctl restart transmission-rss-manager
|
||||
else
|
||||
echo -e "${RED}Could not restart service automatically.${NC}"
|
||||
echo -e "Please restart the service manually."
|
||||
fi
|
||||
|
||||
# Update complete
|
||||
echo -e "${GREEN}${BOLD}Update complete!${NC}"
|
||||
echo -e "Updated from version $CURRENT_VERSION to $NEW_VERSION"
|
||||
echo -e "Changes will take effect immediately."
|
Loading…
x
Reference in New Issue
Block a user