From c495bce21fc898aedb5c74b715b4d30dd9279888 Mon Sep 17 00:00:00 2001 From: MasterDraco Date: Wed, 5 Mar 2025 00:48:57 +0000 Subject: [PATCH] Move config file to /etc/transmission-rss-manager MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Changed config location to /etc/transmission-rss-manager/config.json - Added fallback to maintain backward compatibility - Updated installers to create and use the new location - Added installPath property to configuration for updates - Enhanced documentation with new config location - Bumped version to 2.0.3 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- README.md | 10 +++- modules/config-module.sh | 1 + modules/dependencies-module.sh | 11 ++++ modules/file-creator-module.sh | 57 +++++++++++++++++++++ modules/service-setup-module.sh | 7 +++ package.json | 2 +- server.js | 90 +++++++++++++++++++++++++++++---- 7 files changed, 164 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 220c814..2f4fbbf 100755 --- a/README.md +++ b/README.md @@ -1,9 +1,14 @@ -# Transmission RSS Manager v2.0.2 +# Transmission RSS Manager v2.0.3 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.3 (2025-03-05) +- **New**: Configuration file now stored in `/etc/transmission-rss-manager/` +- **Improved**: Installer creates config directory with proper permissions +- **Improved**: Application now stores path to installation directory for easier updates + ### 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 @@ -132,10 +137,11 @@ If you prefer to install manually: ### Main Configuration Options -The system can be configured through the web interface or by editing the `config.json` file: +The system can be configured through the web interface or by editing the configuration file, which is located at `/etc/transmission-rss-manager/config.json` (or at the application's installation directory as a fallback): ```json { + "installPath": "/opt/transmission-rss-manager", "transmissionConfig": { "host": "localhost", "port": 9091, diff --git a/modules/config-module.sh b/modules/config-module.sh index 55204d7..546de62 100644 --- a/modules/config-module.sh +++ b/modules/config-module.sh @@ -3,6 +3,7 @@ # Configuration variables with defaults INSTALL_DIR="/opt/transmission-rss-manager" +CONFIG_DIR="/etc/transmission-rss-manager" SERVICE_NAME="transmission-rss-manager" PORT=3000 diff --git a/modules/dependencies-module.sh b/modules/dependencies-module.sh index 9175c68..a588b09 100644 --- a/modules/dependencies-module.sh +++ b/modules/dependencies-module.sh @@ -163,6 +163,12 @@ function create_directories() { exit 1 fi + # Check if CONFIG_DIR is defined + if [ -z "$CONFIG_DIR" ]; then + log "ERROR" "CONFIG_DIR is not defined" + exit 1 + fi + # Create directories and check for errors DIRECTORIES=( "$INSTALL_DIR" @@ -171,6 +177,7 @@ function create_directories() { "$INSTALL_DIR/public/css" "$INSTALL_DIR/modules" "$INSTALL_DIR/data" + "$CONFIG_DIR" ) for dir in "${DIRECTORIES[@]}"; do @@ -180,5 +187,9 @@ function create_directories() { fi done + # Set permissions for configuration directory + chown -R "$USER:$USER" "$CONFIG_DIR" + chmod 755 "$CONFIG_DIR" + log "INFO" "Directories created successfully." } \ No newline at end of file diff --git a/modules/file-creator-module.sh b/modules/file-creator-module.sh index d466d9b..0edd7e8 100644 --- a/modules/file-creator-module.sh +++ b/modules/file-creator-module.sh @@ -4,6 +4,63 @@ function create_config_files() { echo -e "${YELLOW}Creating configuration files...${NC}" + # Create initial config.json + echo "Creating config.json..." + cat > $CONFIG_DIR/config.json << EOF +{ + "version": "2.0.3", + "installPath": "$INSTALL_DIR", + "transmissionConfig": { + "host": "$TRANSMISSION_HOST", + "port": $TRANSMISSION_PORT, + "username": "$TRANSMISSION_USER", + "password": "$TRANSMISSION_PASS", + "path": "$TRANSMISSION_RPC_PATH" + }, + "remoteConfig": { + "isRemote": $TRANSMISSION_REMOTE, + "directoryMapping": $TRANSMISSION_DIR_MAPPING + }, + "destinationPaths": { + "movies": "$MEDIA_DIR/movies", + "tvShows": "$MEDIA_DIR/tvshows", + "music": "$MEDIA_DIR/music", + "books": "$MEDIA_DIR/books", + "magazines": "$MEDIA_DIR/magazines", + "software": "$MEDIA_DIR/software" + }, + "seedingRequirements": { + "minRatio": 1.0, + "minTimeMinutes": 60, + "checkIntervalSeconds": 300 + }, + "processingOptions": { + "enableBookSorting": $ENABLE_BOOK_SORTING, + "extractArchives": true, + "deleteArchives": true, + "createCategoryFolders": true, + "ignoreSample": true, + "ignoreExtras": true, + "renameFiles": true, + "autoReplaceUpgrades": true, + "removeDuplicates": true, + "keepOnlyBestVersion": true + }, + "rssFeeds": [], + "rssUpdateIntervalMinutes": 60, + "autoProcessing": false, + "securitySettings": { + "authEnabled": false, + "httpsEnabled": false, + "sslCertPath": "", + "sslKeyPath": "", + "users": [] + }, + "port": $PORT, + "logLevel": "info" +} +EOF + # Create package.json echo "Creating package.json..." cat > $INSTALL_DIR/package.json << EOF diff --git a/modules/service-setup-module.sh b/modules/service-setup-module.sh index 3dba137..f1889a2 100644 --- a/modules/service-setup-module.sh +++ b/modules/service-setup-module.sh @@ -21,6 +21,11 @@ function setup_service() { exit 1 fi + if [ -z "$CONFIG_DIR" ]; then + log "ERROR" "CONFIG_DIR variable is not set" + exit 1 + fi + if [ -z "$PORT" ]; then log "ERROR" "PORT variable is not set" exit 1 @@ -71,6 +76,7 @@ Environment=PORT=$PORT Environment=NODE_ENV=production Environment=DEBUG_ENABLED=false Environment=LOG_FILE=$INSTALL_DIR/logs/transmission-rss-manager.log +Environment=CONFIG_DIR=$CONFIG_DIR EOF # Preserve the existing JWT_SECRET if available @@ -117,6 +123,7 @@ Environment=PORT=$PORT Environment=NODE_ENV=production Environment=DEBUG_ENABLED=false Environment=LOG_FILE=$INSTALL_DIR/logs/transmission-rss-manager.log +Environment=CONFIG_DIR=$CONFIG_DIR # Generate a random JWT secret for security Environment=JWT_SECRET=$(openssl rand -hex 32) diff --git a/package.json b/package.json index 6ce7e22..a806596 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "transmission-rss-manager", - "version": "2.0.2", + "version": "2.0.3", "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": { diff --git a/server.js b/server.js index 1b028d5..d695671 100644 --- a/server.js +++ b/server.js @@ -20,7 +20,8 @@ const TransmissionClient = require('./modules/transmission-client.js'); const PostProcessor = require('./modules/post-processor.js'); // Constants and configuration -const DEFAULT_CONFIG_PATH = path.join(__dirname, 'config.json'); +const DEFAULT_CONFIG_PATH = '/etc/transmission-rss-manager/config.json'; +const FALLBACK_CONFIG_PATH = path.join(__dirname, 'config.json'); const DEFAULT_PORT = 3000; const JWT_SECRET = process.env.JWT_SECRET || 'transmission-rss-manager-secret'; const JWT_EXPIRY = '24h'; @@ -97,6 +98,7 @@ async function loadConfig() { // Define default configuration const defaultConfig = { version: APP_VERSION, // Use the version from package.json + installPath: __dirname, // Store the path to the installation directory transmissionConfig: { host: 'localhost', port: 9091, @@ -147,8 +149,10 @@ async function loadConfig() { logLevel: "info" }; + // Try primary config location first try { - // Try to read existing config + // Try to read existing config from primary location + console.log(`Trying to load config from: ${DEFAULT_CONFIG_PATH}`); const configData = await fs.readFile(DEFAULT_CONFIG_PATH, 'utf8'); const loadedConfig = JSON.parse(configData); @@ -162,17 +166,68 @@ async function loadConfig() { await saveConfig(mergedConfig); } + console.log(`Config loaded from ${DEFAULT_CONFIG_PATH}`); return mergedConfig; - } catch (readError) { - // If file not found, create default config - if (readError.code === 'ENOENT') { - console.log('Config file not found, creating default configuration'); - await saveConfig(defaultConfig); - return defaultConfig; + } catch (primaryError) { + // If file not found in primary location, try fallback location + if (primaryError.code === 'ENOENT') { + console.log(`Config not found at ${DEFAULT_CONFIG_PATH}, trying fallback location...`); + + try { + const fallbackData = await fs.readFile(FALLBACK_CONFIG_PATH, 'utf8'); + const fallbackConfig = JSON.parse(fallbackData); + + // Merge configs + const mergedConfig = mergeConfigs(defaultConfig, fallbackConfig); + + // If version is different, save updated config + if (fallbackConfig.version !== APP_VERSION) { + console.log(`Updating config from version ${fallbackConfig.version || 'unknown'} to ${APP_VERSION}`); + mergedConfig.version = APP_VERSION; + } + + // Try to save to primary location, but don't fail if we can't + try { + // Create directory if it doesn't exist + await fs.mkdir(path.dirname(DEFAULT_CONFIG_PATH), { recursive: true }); + await fs.writeFile(DEFAULT_CONFIG_PATH, JSON.stringify(mergedConfig, null, 2), 'utf8'); + console.log(`Migrated config from ${FALLBACK_CONFIG_PATH} to ${DEFAULT_CONFIG_PATH}`); + } catch (saveError) { + console.warn(`Could not save config to ${DEFAULT_CONFIG_PATH}: ${saveError.message}`); + console.warn('Continuing with fallback config location'); + } + + console.log(`Config loaded from fallback location: ${FALLBACK_CONFIG_PATH}`); + return mergedConfig; + } catch (fallbackError) { + // If file not found in fallback location, create default config + if (fallbackError.code === 'ENOENT') { + console.log('Config file not found in either location, creating default configuration'); + + // Try to save to primary location first + try { + await fs.mkdir(path.dirname(DEFAULT_CONFIG_PATH), { recursive: true }); + await fs.writeFile(DEFAULT_CONFIG_PATH, JSON.stringify(defaultConfig, null, 2), 'utf8'); + console.log(`Created default config at ${DEFAULT_CONFIG_PATH}`); + } catch (saveError) { + console.warn(`Could not save config to ${DEFAULT_CONFIG_PATH}: ${saveError.message}`); + console.warn('Saving to fallback location instead'); + + // Save to fallback location instead + await fs.writeFile(FALLBACK_CONFIG_PATH, JSON.stringify(defaultConfig, null, 2), 'utf8'); + console.log(`Created default config at ${FALLBACK_CONFIG_PATH}`); + } + + return defaultConfig; + } + + // For other errors, rethrow + throw fallbackError; + } } // For other errors, rethrow - throw readError; + throw primaryError; } } catch (error) { console.error('Error loading configuration:', error); @@ -231,8 +286,21 @@ function mergeConfigs(defaultConfig, userConfig) { */ async function saveConfig(config) { try { - await fs.writeFile(DEFAULT_CONFIG_PATH, JSON.stringify(config, null, 2), 'utf8'); - console.log('Configuration saved'); + // Always try to save to the primary config location first + try { + // Make sure directory exists + await fs.mkdir(path.dirname(DEFAULT_CONFIG_PATH), { recursive: true }); + await fs.writeFile(DEFAULT_CONFIG_PATH, JSON.stringify(config, null, 2), 'utf8'); + console.log(`Configuration saved to ${DEFAULT_CONFIG_PATH}`); + return; + } catch (primaryError) { + console.warn(`Could not save config to ${DEFAULT_CONFIG_PATH}: ${primaryError.message}`); + console.warn('Trying fallback location...'); + + // If we couldn't save to the primary location, try the fallback + await fs.writeFile(FALLBACK_CONFIG_PATH, JSON.stringify(config, null, 2), 'utf8'); + console.log(`Configuration saved to fallback location: ${FALLBACK_CONFIG_PATH}`); + } } catch (error) { console.error('Error saving configuration:', error); throw error;