Compare commits
3 Commits
54871518fc
...
70ccb8f4fd
Author | SHA1 | Date | |
---|---|---|---|
70ccb8f4fd | |||
301684886f | |||
f28d49284e |
@ -1,9 +1,15 @@
|
||||
# Transmission RSS Manager v2.0.7
|
||||
# Transmission RSS Manager v2.0.8
|
||||
|
||||
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.8 (2025-03-07)
|
||||
- **Fixed**: Module import issues on fresh installations with proper file extension handling
|
||||
- **Fixed**: Adding compatibility symlinks for different module naming styles
|
||||
- **Improved**: Server.js now uses consistent module import paths with .js extensions
|
||||
- **Improved**: More robust module file handling in the installer
|
||||
|
||||
### v2.0.7 (2025-03-07)
|
||||
- **Fixed**: Installation directory handling with prompt for choosing install path
|
||||
- **Fixed**: Bootstrap-installer now defaults to /opt/trans-install with user configuration option
|
||||
|
@ -136,8 +136,9 @@ const cors = require('cors');
|
||||
const Transmission = require('transmission');
|
||||
|
||||
// Import custom modules
|
||||
const PostProcessor = require('./modules/postProcessor');
|
||||
const RssFeedManager = require('./modules/rssFeedManager');
|
||||
const PostProcessor = require('./modules/post-processor.js');
|
||||
const RssFeedManager = require('./modules/rss-feed-manager.js');
|
||||
const TransmissionClient = require('./modules/transmission-client.js');
|
||||
|
||||
// Initialize Express app
|
||||
const app = express();
|
||||
@ -1823,6 +1824,20 @@ function copy_module_files() {
|
||||
echo "Copying module: $module_name"
|
||||
cp "$js_file" "$INSTALL_DIR/modules/$module_name"
|
||||
|
||||
# Create symlinks for alternative module names that might be referenced
|
||||
base_name=$(basename "$module_name" .js)
|
||||
case "$base_name" in
|
||||
"rss-feed-manager")
|
||||
ln -sf "$INSTALL_DIR/modules/$module_name" "$INSTALL_DIR/modules/rssFeedManager.js"
|
||||
;;
|
||||
"post-processor")
|
||||
ln -sf "$INSTALL_DIR/modules/$module_name" "$INSTALL_DIR/modules/postProcessor.js"
|
||||
;;
|
||||
"transmission-client")
|
||||
ln -sf "$INSTALL_DIR/modules/$module_name" "$INSTALL_DIR/modules/transmissionClient.js"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Set permissions
|
||||
chown "$USER:$USER" "$INSTALL_DIR/modules/$module_name"
|
||||
chmod 644 "$INSTALL_DIR/modules/$module_name"
|
||||
|
@ -28,8 +28,14 @@ class TransmissionClient {
|
||||
this.dirMappings = config.remoteConfig.directoryMapping;
|
||||
}
|
||||
|
||||
// Initialize the connection
|
||||
// Initialize the connection - but don't throw if it fails initially
|
||||
// This allows the object to be created even if the connection fails
|
||||
try {
|
||||
this.initializeConnection();
|
||||
} catch (error) {
|
||||
console.error("Failed to initialize Transmission connection:", error.message);
|
||||
// Don't throw - allow methods to handle connection retry logic
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -39,8 +45,11 @@ class TransmissionClient {
|
||||
const { host, port, username, password, path: rpcPath } = this.config.transmissionConfig;
|
||||
|
||||
try {
|
||||
// Only default to localhost if host is empty/null/undefined
|
||||
const connectionHost = (host === undefined || host === null || host === '') ? 'localhost' : host;
|
||||
|
||||
this.client = new Transmission({
|
||||
host: host || 'localhost',
|
||||
host: connectionHost,
|
||||
port: port || 9091,
|
||||
username: username || '',
|
||||
password: password || '',
|
||||
@ -48,7 +57,7 @@ class TransmissionClient {
|
||||
timeout: 30000 // 30 seconds
|
||||
});
|
||||
|
||||
console.log(`Initialized Transmission client connection to ${host}:${port}${rpcPath}`);
|
||||
console.log(`Initialized Transmission client connection to ${connectionHost}:${port}${rpcPath}`);
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize Transmission client:', error);
|
||||
throw error;
|
||||
@ -61,13 +70,17 @@ class TransmissionClient {
|
||||
*/
|
||||
async getStatus() {
|
||||
try {
|
||||
// Use the session-stats method for basic connectivity check
|
||||
const sessionInfo = await this.client.sessionStats();
|
||||
const version = await this.client.sessionGet();
|
||||
|
||||
// Use the session-get method to get version info
|
||||
// Note: In transmission-promise, this is 'session' not 'sessionGet'
|
||||
const session = await this.client.session();
|
||||
|
||||
return {
|
||||
connected: true,
|
||||
version: version.version,
|
||||
rpcVersion: version['rpc-version'],
|
||||
version: session.version || "Unknown",
|
||||
rpcVersion: session['rpc-version'] || "Unknown",
|
||||
downloadSpeed: sessionInfo.downloadSpeed,
|
||||
uploadSpeed: sessionInfo.uploadSpeed,
|
||||
torrentCount: sessionInfo.torrentCount,
|
||||
@ -443,7 +456,8 @@ class TransmissionClient {
|
||||
*/
|
||||
async setSessionParams(params) {
|
||||
try {
|
||||
await this.client.sessionSet(params);
|
||||
// In transmission-promise, the method is sessionUpdate not sessionSet
|
||||
await this.client.sessionUpdate(params);
|
||||
return {
|
||||
success: true,
|
||||
message: 'Session parameters updated successfully'
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "transmission-rss-manager",
|
||||
"version": "2.0.7",
|
||||
"version": "2.0.8",
|
||||
"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": {
|
||||
|
95
server.js
95
server.js
@ -18,37 +18,26 @@ const bcrypt = require('bcrypt');
|
||||
// Try to import with .js extension first, then fallback to no extension for better compatibility
|
||||
let RssFeedManager, TransmissionClient, PostProcessor;
|
||||
|
||||
// Always use explicit .js extension when importing our own modules
|
||||
try {
|
||||
RssFeedManager = require('./modules/rss-feed-manager.js');
|
||||
} catch (e) {
|
||||
try {
|
||||
RssFeedManager = require('./modules/rss-feed-manager');
|
||||
} catch (err) {
|
||||
} catch (err) {
|
||||
console.error('Failed to load RssFeedManager module:', err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
TransmissionClient = require('./modules/transmission-client.js');
|
||||
} catch (e) {
|
||||
try {
|
||||
TransmissionClient = require('./modules/transmission-client');
|
||||
} catch (err) {
|
||||
} catch (err) {
|
||||
console.error('Failed to load TransmissionClient module:', err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
PostProcessor = require('./modules/post-processor.js');
|
||||
} catch (e) {
|
||||
try {
|
||||
PostProcessor = require('./modules/post-processor');
|
||||
} catch (err) {
|
||||
} catch (err) {
|
||||
console.error('Failed to load PostProcessor module:', err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Constants and configuration
|
||||
@ -479,9 +468,45 @@ app.post('/api/config', authenticateJWT, async (req, res) => {
|
||||
// Merge the new config with the existing one
|
||||
const newConfig = { ...config, ...req.body };
|
||||
|
||||
// Keep passwords if they're not provided
|
||||
if (newConfig.transmissionConfig && !newConfig.transmissionConfig.password && config.transmissionConfig) {
|
||||
newConfig.transmissionConfig.password = config.transmissionConfig.password;
|
||||
// Preserve existing Transmission configuration values when not explicitly provided
|
||||
if (newConfig.transmissionConfig && config.transmissionConfig) {
|
||||
// First create a copy of the existing configuration
|
||||
const preservedTransConfig = { ...config.transmissionConfig };
|
||||
|
||||
// Only update values that are explicitly provided and not empty
|
||||
if (!req.body.transmissionConfig?.host) {
|
||||
newConfig.transmissionConfig.host = preservedTransConfig.host;
|
||||
}
|
||||
|
||||
if (!req.body.transmissionConfig?.port) {
|
||||
newConfig.transmissionConfig.port = preservedTransConfig.port;
|
||||
}
|
||||
|
||||
if (!req.body.transmissionConfig?.path) {
|
||||
newConfig.transmissionConfig.path = preservedTransConfig.path;
|
||||
}
|
||||
|
||||
if (!req.body.transmissionConfig?.username) {
|
||||
newConfig.transmissionConfig.username = preservedTransConfig.username;
|
||||
}
|
||||
|
||||
// Always preserve password if not provided
|
||||
if (!newConfig.transmissionConfig.password) {
|
||||
newConfig.transmissionConfig.password = preservedTransConfig.password;
|
||||
}
|
||||
}
|
||||
|
||||
// Preserve remote configuration settings if not explicitly provided
|
||||
if (newConfig.remoteConfig && config.remoteConfig) {
|
||||
// Make sure isRemote setting is preserved if not explicitly set
|
||||
if (req.body.remoteConfig?.isRemote === undefined) {
|
||||
newConfig.remoteConfig.isRemote = config.remoteConfig.isRemote;
|
||||
}
|
||||
|
||||
// Preserve directory mappings if not provided
|
||||
if (!req.body.remoteConfig?.directoryMapping && config.remoteConfig.directoryMapping) {
|
||||
newConfig.remoteConfig.directoryMapping = { ...config.remoteConfig.directoryMapping };
|
||||
}
|
||||
}
|
||||
|
||||
// Keep user passwords
|
||||
@ -860,7 +885,15 @@ app.post('/api/transmission/remove', authenticateJWT, async (req, res) => {
|
||||
|
||||
app.post('/api/transmission/test', authenticateJWT, async (req, res) => {
|
||||
try {
|
||||
const { host, port, username, password } = req.body;
|
||||
const { host, port, username, password, path: rpcPath } = req.body;
|
||||
|
||||
// Debug info
|
||||
console.log('Testing Transmission connection with params:', {
|
||||
host: host || 'from config',
|
||||
port: port || 'from config',
|
||||
username: username ? 'provided' : 'from config',
|
||||
path: rpcPath || 'from config',
|
||||
});
|
||||
|
||||
// Create a temporary client for testing
|
||||
const testConfig = {
|
||||
@ -869,10 +902,25 @@ app.post('/api/transmission/test', authenticateJWT, async (req, res) => {
|
||||
port: port || config.transmissionConfig.port,
|
||||
username: username || config.transmissionConfig.username,
|
||||
password: password || config.transmissionConfig.password,
|
||||
path: config.transmissionConfig.path
|
||||
path: rpcPath || config.transmissionConfig.path
|
||||
},
|
||||
// Also include remoteConfig to ensure proper remote handling
|
||||
remoteConfig: {
|
||||
// If host is provided and different from localhost, set isRemote to true
|
||||
isRemote: host && host !== 'localhost' ? true : config.remoteConfig?.isRemote || false,
|
||||
directoryMapping: config.remoteConfig?.directoryMapping || {}
|
||||
}
|
||||
};
|
||||
|
||||
// Log the actual test config (without password)
|
||||
console.log('Test configuration:', {
|
||||
host: testConfig.transmissionConfig.host,
|
||||
port: testConfig.transmissionConfig.port,
|
||||
path: testConfig.transmissionConfig.path,
|
||||
isRemote: testConfig.remoteConfig.isRemote
|
||||
});
|
||||
|
||||
try {
|
||||
const testClient = new TransmissionClient(testConfig);
|
||||
const status = await testClient.getStatus();
|
||||
|
||||
@ -891,6 +939,13 @@ app.post('/api/transmission/test', authenticateJWT, async (req, res) => {
|
||||
message: `Failed to connect: ${status.error}`
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error testing Transmission connection:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: `Error testing connection: ${error.message}`
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
|
Loading…
x
Reference in New Issue
Block a user