Initial commit: get everything rolling
This commit is contained in:
45
services/copyparty.js
Normal file
45
services/copyparty.js
Normal file
@@ -0,0 +1,45 @@
|
||||
// services/copyparty.js
|
||||
import { spawn } from 'node:child_process';
|
||||
|
||||
let processHandle = null;
|
||||
|
||||
export function startCopyparty(config) {
|
||||
const cp = config.copyparty;
|
||||
if (!cp?.enabled || processHandle) return;
|
||||
|
||||
const mountPoint = config.system.mountPoint;
|
||||
|
||||
// volflag :c,hist=/tmp keeps sqlite write hits off the flash drive and sd card
|
||||
const volSpec = `${mountPoint}:${cp.volumeName}:${cp.permissions}:c,hist=/tmp/copyparty`;
|
||||
|
||||
const args = [
|
||||
cp.binaryPath,
|
||||
'-p', String(cp.port),
|
||||
'-a', `${cp.user}:${cp.password}`,
|
||||
'-v', volSpec,
|
||||
...(cp.extraArgs || [])
|
||||
];
|
||||
|
||||
console.log(`[COPYPARTY] Starting server on port ${cp.port}...`);
|
||||
processHandle = spawn('python3', args, {
|
||||
stdio: 'ignore', // swap to 'inherit' if debugging startup flags
|
||||
detached: false
|
||||
});
|
||||
|
||||
processHandle.on('error', (err) => {
|
||||
console.error('[COPYPARTY] Failed to spawn:', err.message);
|
||||
processHandle = null;
|
||||
});
|
||||
|
||||
processHandle.on('exit', (code) => {
|
||||
console.log(`[COPYPARTY] Process exited (code ${code})`);
|
||||
processHandle = null;
|
||||
});
|
||||
}
|
||||
|
||||
export function stopCopyparty() {
|
||||
if (!processHandle) return;
|
||||
console.log('[COPYPARTY] Stopping server...');
|
||||
processHandle.kill('SIGTERM');
|
||||
processHandle = null;
|
||||
}
|
||||
58
services/syncjobs.js
Normal file
58
services/syncjobs.js
Normal file
@@ -0,0 +1,58 @@
|
||||
// services/syncJobs.js
|
||||
// This file handles both
|
||||
import { spawn } from 'node:child_process';
|
||||
|
||||
function runCmd(bin, args) {
|
||||
return new Promise((resolve, reject) => {
|
||||
console.log(`[EXEC] ${bin} ${args.join(' ')}`);
|
||||
const proc = spawn(bin, args, { stdio: 'inherit' });
|
||||
proc.on('error', reject);
|
||||
proc.on('close', (code) => {
|
||||
if (code === 0) resolve();
|
||||
else reject(new Error(`${bin} failed with exit code ${code}`));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export async function runRsync(config) {
|
||||
const cfg = config.rsync;
|
||||
if (!cfg?.enabled) return;
|
||||
|
||||
const mountPoint = config.system.mountPoint;
|
||||
const excludes = (cfg.exclude || []).flatMap((pattern) => ['--exclude', pattern]);
|
||||
|
||||
console.log('[RSYNC] Syncing with NAS...');
|
||||
await runCmd('rsync', [...cfg.flags, ...excludes, `${mountPoint}/`, `${cfg.nasPath}/`]);
|
||||
|
||||
if (cfg.bidirectional) {
|
||||
await runCmd('rsync', [
|
||||
...cfg.flags,
|
||||
'--ignore-existing',
|
||||
...excludes,
|
||||
`${cfg.nasPath}/`,
|
||||
`${mountPoint}/`
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
export async function runRclone(config) {
|
||||
const cfg = config.rclone;
|
||||
if (!cfg?.enabled) return;
|
||||
|
||||
const mountPoint = config.system.mountPoint;
|
||||
const excludes = (cfg.exclude || []).flatMap((pattern) => ['--exclude', pattern]);
|
||||
|
||||
console.log('[RCLONE] Syncing with cloud...');
|
||||
await runCmd('rclone', ['copy', ...cfg.flags, ...excludes, mountPoint, cfg.remote]);
|
||||
|
||||
if (cfg.bidirectional) {
|
||||
await runCmd('rclone', [
|
||||
'copy',
|
||||
'--ignore-existing',
|
||||
...cfg.flags,
|
||||
...excludes,
|
||||
cfg.remote,
|
||||
mountPoint
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user