Files
NeoTachyon/fe-app-podkop/watch-upload.js
T
ushan0v 1e50faa471 Initial public release of Podkop Plus
publish current Podkop Plus fork state as a single public snapshot

include release installer overhaul with zapret auto-install
2026-04-09 23:24:33 +03:00

101 lines
3.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dotenv/config';
import chokidar from 'chokidar';
import SFTPClient from 'ssh2-sftp-client';
import path from 'path';
import fs from 'fs';
import { glob } from 'glob';
const sftp = new SFTPClient();
const config = {
host: process.env.SFTP_HOST,
port: Number(process.env.SFTP_PORT || 22),
username: process.env.SFTP_USER,
...(process.env.SFTP_PRIVATE_KEY
? { privateKey: fs.readFileSync(process.env.SFTP_PRIVATE_KEY) }
: { password: process.env.SFTP_PASS }),
};
const syncDirs = [
{
local: path.resolve(process.env.LOCAL_DIR_FE ?? '../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop'),
remote: process.env.REMOTE_DIR_FE ?? '/www/luci-static/resources/view/podkop',
},
{
local: path.resolve(process.env.LOCAL_DIR_BIN ?? '../podkop/files/usr/bin/'),
remote: process.env.REMOTE_DIR_BIN ?? '/usr/bin/',
},
{
local: path.resolve(process.env.LOCAL_DIR_LIB ?? '../podkop/files/usr/lib/'),
remote: process.env.REMOTE_DIR_LIB ?? '/usr/lib/podkop-plus/',
},
{
local: path.resolve(process.env.LOCAL_DIR_INIT ?? '../podkop/files/etc/init.d/'),
remote: process.env.REMOTE_DIR_INIT ?? '/etc/init.d/',
}
];
async function uploadFile(filePath, baseDir, remoteBase) {
const relativePath = path.relative(baseDir, filePath);
const remotePath = path.posix.join(remoteBase, relativePath);
console.log(`↑ Uploading: ${relativePath} -> ${remotePath}`);
try {
await sftp.fastPut(filePath, remotePath);
console.log(`✓ Uploaded: ${relativePath}`);
} catch (err) {
console.error(`✗ Failed: ${relativePath}: ${err.message}`);
}
}
async function deleteFile(filePath, baseDir, remoteBase) {
const relativePath = path.relative(baseDir, filePath);
const remotePath = path.posix.join(remoteBase, relativePath);
console.log(`⨯ Removing: ${relativePath}`);
try {
await sftp.delete(remotePath);
console.log(`✓ Removed: ${relativePath}`);
} catch (err) {
console.warn(`⚠ Could not delete ${relativePath}: ${err.message}`);
}
}
async function uploadAllFiles() {
for (const { local, remote } of syncDirs) {
console.log(`📂 Uploading all from ${local}`);
const files = await glob(`${local}/**/*`, { nodir: true });
for (const file of files) {
await uploadFile(file, local, remote);
}
}
console.log('✅ Initial upload complete!');
}
async function main() {
await sftp.connect(config);
console.log(`🔌 Connected to ${config.host}`);
await uploadAllFiles();
for (const { local, remote } of syncDirs) {
chokidar.watch(local, { ignoreInitial: true }).on('all', async (event, filePath) => {
if (event === 'add' || event === 'change') {
await uploadFile(filePath, local, remote);
} else if (event === 'unlink') {
await deleteFile(filePath, local, remote);
}
});
}
process.on('SIGINT', async () => {
console.log('👋 Disconnecting...');
await sftp.end();
process.exit();
});
}
main().catch((err) => {
console.error('💥 Fatal:', err);
});