Move config file to /etc/transmission-rss-manager
- 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 <noreply@anthropic.com>
This commit is contained in:
parent
3cfc5f3489
commit
c495bce21f
10
README.md
10
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!
|
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.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)
|
### v2.0.2 (2025-03-05)
|
||||||
- **Fixed**: Bug in installer that would prompt to install Transmission for remote configurations
|
- **Fixed**: Bug in installer that would prompt to install Transmission for remote configurations
|
||||||
- **Improved**: Better detection of remote vs local Transmission installations
|
- **Improved**: Better detection of remote vs local Transmission installations
|
||||||
@ -132,10 +137,11 @@ If you prefer to install manually:
|
|||||||
|
|
||||||
### Main Configuration Options
|
### 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
|
```json
|
||||||
{
|
{
|
||||||
|
"installPath": "/opt/transmission-rss-manager",
|
||||||
"transmissionConfig": {
|
"transmissionConfig": {
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"port": 9091,
|
"port": 9091,
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
# Configuration variables with defaults
|
# Configuration variables with defaults
|
||||||
INSTALL_DIR="/opt/transmission-rss-manager"
|
INSTALL_DIR="/opt/transmission-rss-manager"
|
||||||
|
CONFIG_DIR="/etc/transmission-rss-manager"
|
||||||
SERVICE_NAME="transmission-rss-manager"
|
SERVICE_NAME="transmission-rss-manager"
|
||||||
PORT=3000
|
PORT=3000
|
||||||
|
|
||||||
|
@ -163,6 +163,12 @@ function create_directories() {
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
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
|
# Create directories and check for errors
|
||||||
DIRECTORIES=(
|
DIRECTORIES=(
|
||||||
"$INSTALL_DIR"
|
"$INSTALL_DIR"
|
||||||
@ -171,6 +177,7 @@ function create_directories() {
|
|||||||
"$INSTALL_DIR/public/css"
|
"$INSTALL_DIR/public/css"
|
||||||
"$INSTALL_DIR/modules"
|
"$INSTALL_DIR/modules"
|
||||||
"$INSTALL_DIR/data"
|
"$INSTALL_DIR/data"
|
||||||
|
"$CONFIG_DIR"
|
||||||
)
|
)
|
||||||
|
|
||||||
for dir in "${DIRECTORIES[@]}"; do
|
for dir in "${DIRECTORIES[@]}"; do
|
||||||
@ -180,5 +187,9 @@ function create_directories() {
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Set permissions for configuration directory
|
||||||
|
chown -R "$USER:$USER" "$CONFIG_DIR"
|
||||||
|
chmod 755 "$CONFIG_DIR"
|
||||||
|
|
||||||
log "INFO" "Directories created successfully."
|
log "INFO" "Directories created successfully."
|
||||||
}
|
}
|
@ -4,6 +4,63 @@
|
|||||||
function create_config_files() {
|
function create_config_files() {
|
||||||
echo -e "${YELLOW}Creating configuration files...${NC}"
|
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
|
# Create package.json
|
||||||
echo "Creating package.json..."
|
echo "Creating package.json..."
|
||||||
cat > $INSTALL_DIR/package.json << EOF
|
cat > $INSTALL_DIR/package.json << EOF
|
||||||
|
@ -21,6 +21,11 @@ function setup_service() {
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -z "$CONFIG_DIR" ]; then
|
||||||
|
log "ERROR" "CONFIG_DIR variable is not set"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -z "$PORT" ]; then
|
if [ -z "$PORT" ]; then
|
||||||
log "ERROR" "PORT variable is not set"
|
log "ERROR" "PORT variable is not set"
|
||||||
exit 1
|
exit 1
|
||||||
@ -71,6 +76,7 @@ Environment=PORT=$PORT
|
|||||||
Environment=NODE_ENV=production
|
Environment=NODE_ENV=production
|
||||||
Environment=DEBUG_ENABLED=false
|
Environment=DEBUG_ENABLED=false
|
||||||
Environment=LOG_FILE=$INSTALL_DIR/logs/transmission-rss-manager.log
|
Environment=LOG_FILE=$INSTALL_DIR/logs/transmission-rss-manager.log
|
||||||
|
Environment=CONFIG_DIR=$CONFIG_DIR
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Preserve the existing JWT_SECRET if available
|
# Preserve the existing JWT_SECRET if available
|
||||||
@ -117,6 +123,7 @@ Environment=PORT=$PORT
|
|||||||
Environment=NODE_ENV=production
|
Environment=NODE_ENV=production
|
||||||
Environment=DEBUG_ENABLED=false
|
Environment=DEBUG_ENABLED=false
|
||||||
Environment=LOG_FILE=$INSTALL_DIR/logs/transmission-rss-manager.log
|
Environment=LOG_FILE=$INSTALL_DIR/logs/transmission-rss-manager.log
|
||||||
|
Environment=CONFIG_DIR=$CONFIG_DIR
|
||||||
# Generate a random JWT secret for security
|
# Generate a random JWT secret for security
|
||||||
Environment=JWT_SECRET=$(openssl rand -hex 32)
|
Environment=JWT_SECRET=$(openssl rand -hex 32)
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "transmission-rss-manager",
|
"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",
|
"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": {
|
||||||
|
86
server.js
86
server.js
@ -20,7 +20,8 @@ const TransmissionClient = require('./modules/transmission-client.js');
|
|||||||
const PostProcessor = require('./modules/post-processor.js');
|
const PostProcessor = require('./modules/post-processor.js');
|
||||||
|
|
||||||
// Constants and configuration
|
// 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 DEFAULT_PORT = 3000;
|
||||||
const JWT_SECRET = process.env.JWT_SECRET || 'transmission-rss-manager-secret';
|
const JWT_SECRET = process.env.JWT_SECRET || 'transmission-rss-manager-secret';
|
||||||
const JWT_EXPIRY = '24h';
|
const JWT_EXPIRY = '24h';
|
||||||
@ -97,6 +98,7 @@ async function loadConfig() {
|
|||||||
// Define default configuration
|
// Define default configuration
|
||||||
const defaultConfig = {
|
const defaultConfig = {
|
||||||
version: APP_VERSION, // Use the version from package.json
|
version: APP_VERSION, // Use the version from package.json
|
||||||
|
installPath: __dirname, // Store the path to the installation directory
|
||||||
transmissionConfig: {
|
transmissionConfig: {
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
port: 9091,
|
port: 9091,
|
||||||
@ -147,8 +149,10 @@ async function loadConfig() {
|
|||||||
logLevel: "info"
|
logLevel: "info"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Try primary config location first
|
||||||
try {
|
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 configData = await fs.readFile(DEFAULT_CONFIG_PATH, 'utf8');
|
||||||
const loadedConfig = JSON.parse(configData);
|
const loadedConfig = JSON.parse(configData);
|
||||||
|
|
||||||
@ -162,17 +166,68 @@ async function loadConfig() {
|
|||||||
await saveConfig(mergedConfig);
|
await saveConfig(mergedConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log(`Config loaded from ${DEFAULT_CONFIG_PATH}`);
|
||||||
return mergedConfig;
|
return mergedConfig;
|
||||||
} catch (readError) {
|
} catch (primaryError) {
|
||||||
// If file not found, create default config
|
// If file not found in primary location, try fallback location
|
||||||
if (readError.code === 'ENOENT') {
|
if (primaryError.code === 'ENOENT') {
|
||||||
console.log('Config file not found, creating default configuration');
|
console.log(`Config not found at ${DEFAULT_CONFIG_PATH}, trying fallback location...`);
|
||||||
await saveConfig(defaultConfig);
|
|
||||||
|
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;
|
return defaultConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For other errors, rethrow
|
// For other errors, rethrow
|
||||||
throw readError;
|
throw fallbackError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For other errors, rethrow
|
||||||
|
throw primaryError;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading configuration:', error);
|
console.error('Error loading configuration:', error);
|
||||||
@ -231,8 +286,21 @@ function mergeConfigs(defaultConfig, userConfig) {
|
|||||||
*/
|
*/
|
||||||
async function saveConfig(config) {
|
async function saveConfig(config) {
|
||||||
try {
|
try {
|
||||||
|
// 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');
|
await fs.writeFile(DEFAULT_CONFIG_PATH, JSON.stringify(config, null, 2), 'utf8');
|
||||||
console.log('Configuration saved');
|
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) {
|
} catch (error) {
|
||||||
console.error('Error saving configuration:', error);
|
console.error('Error saving configuration:', error);
|
||||||
throw error;
|
throw error;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user