Compare commits
No commits in common. "3cfc5f34891d9937287fe3b6ce0ad014975e0cc7" and "bd55ef8613c6bd344a8699116ea250ded6f420b6" have entirely different histories.
3cfc5f3489
...
bd55ef8613
@ -1,14 +1,9 @@
|
|||||||
# Transmission RSS Manager v2.0.2
|
# Transmission RSS Manager v2.0.1
|
||||||
|
|
||||||
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!
|
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
|
## 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)
|
### v2.0.1 (2025-03-05)
|
||||||
- **New**: Automatic detection of existing installations for seamless updates
|
- **New**: Automatic detection of existing installations for seamless updates
|
||||||
- **Improved**: Enhanced update process that preserves existing configurations
|
- **Improved**: Enhanced update process that preserves existing configurations
|
||||||
|
@ -35,8 +35,8 @@ function install_dependencies() {
|
|||||||
log "INFO" "Node.js is already installed."
|
log "INFO" "Node.js is already installed."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check if we need to install Transmission (only if local transmission was selected and not remote)
|
# Check if we need to install Transmission (only if local transmission was selected)
|
||||||
if [ "$TRANSMISSION_REMOTE" = false ] && ([ "$TRANSMISSION_HOST" = "localhost" ] || [ "$TRANSMISSION_HOST" = "127.0.0.1" ]); then
|
if [ "$TRANSMISSION_HOST" = "localhost" ] || [ "$TRANSMISSION_HOST" = "127.0.0.1" ]; then
|
||||||
if ! command_exists transmission-daemon; then
|
if ! command_exists transmission-daemon; then
|
||||||
log "INFO" "Local Transmission installation selected, but transmission-daemon is not installed."
|
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
|
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 dependencies=("node" "npm" "unzip" "nginx")
|
||||||
local missing_deps=()
|
local missing_deps=()
|
||||||
|
|
||||||
# Add transmission to dependencies check if local installation was selected and not remote
|
# Add transmission to dependencies check if local installation was selected
|
||||||
if [ "$TRANSMISSION_REMOTE" = false ] && ([ "$TRANSMISSION_HOST" = "localhost" ] || [ "$TRANSMISSION_HOST" = "127.0.0.1" ]); then
|
if [ "$TRANSMISSION_HOST" = "localhost" ] || [ "$TRANSMISSION_HOST" = "127.0.0.1" ]; then
|
||||||
dependencies+=("transmission-daemon")
|
dependencies+=("transmission-daemon")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "transmission-rss-manager",
|
"name": "transmission-rss-manager",
|
||||||
"version": "2.0.2",
|
"version": "2.0.1",
|
||||||
"description": "A comprehensive web-based tool to automate and manage your Transmission torrent downloads with RSS feed integration and intelligent media organization",
|
"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",
|
"main": "server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -1,75 +0,0 @@
|
|||||||
# 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
|
|
@ -1,131 +0,0 @@
|
|||||||
// 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();
|
|
@ -1,72 +0,0 @@
|
|||||||
#!/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."
|
|
@ -1,374 +0,0 @@
|
|||||||
#!/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
|
|
||||||
}
|
|
@ -1,184 +0,0 @@
|
|||||||
#!/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."
|
|
||||||
}
|
|
@ -1,241 +0,0 @@
|
|||||||
#!/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}"
|
|
@ -1,84 +0,0 @@
|
|||||||
#!/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."
|
|
@ -1,146 +0,0 @@
|
|||||||
// 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
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,41 +0,0 @@
|
|||||||
<!-- 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>
|
|
@ -1,84 +0,0 @@
|
|||||||
#!/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