2025-10-23 20:31:50 +02:00
// @ts-check
import { spawn , execSync } from "child_process" ;
import asar from "@electron/asar" ;
import chalk from "chalk" ;
import path from "path" ;
import fs from "fs" ;
import readline from "readline" ;
import https from "https" ;
import { fileURLToPath } from "url" ;
2025-11-29 00:06:24 +01:00
// Version info
const LOCAL_VERSION = "2.0.8" ;
const GITHUB_REPO = "xenos1337/httptoolkit-patcher" ;
2025-10-23 20:31:50 +02:00
const isWin = process . platform === "win32" ;
const isMac = process . platform === "darwin" ;
const isLinux = process . platform === "linux" ;
// Handle both ESM and pkg-bundled scenarios
const __filename = (() => {
// Check if running as pkg bundle
2025-11-24 05:47:59 +01:00
// @ts-ignore - pkg adds this property at runtime
2025-10-23 20:31:50 +02:00
if ( process . pkg ) {
return process . execPath ;
}
2025-11-24 05:47:59 +01:00
// ESM: use import.meta.url
return fileURLToPath ( import . meta . url );
2025-10-23 20:31:50 +02:00
})();
// Check if running with elevated privileges
2025-11-24 05:47:59 +01:00
function isElevated () {
2025-10-23 20:31:50 +02:00
if ( isWin ) {
try {
execSync ( "net session" , { stdio : "ignore" });
return true ;
} catch {
return false ;
}
} else {
return process . getuid && process . getuid () === 0 ;
}
2025-11-24 05:47:59 +01:00
}
2025-10-23 20:31:50 +02:00
// Helper function to prompt user for input
2025-11-24 05:47:59 +01:00
function prompt ( question ) {
2025-10-23 20:31:50 +02:00
const rl = readline . createInterface ({
input : process . stdin ,
output : process . stdout ,
});
return new Promise ( resolve => {
rl . question ( question , answer => {
rl . close ();
resolve ( answer );
});
});
2025-11-24 05:47:59 +01:00
}
2025-10-23 20:31:50 +02:00
2025-11-29 00:06:24 +01:00
/**
* Fetch JSON from a URL
* @param {string} url
* @returns {Promise<Array<{name: string}>>}
*/
function fetchJson ( url ) {
return new Promise (( resolve , reject ) => {
const options = {
headers : {
"User-Agent" : "httptoolkit-patcher" ,
"Accept" : "application/vnd.github.v3+json" ,
},
};
https
. get ( url , options , res => {
if ( res . statusCode !== 200 ) {
reject ( new Error ( `HTTP ${ res . statusCode } ` ));
return ;
}
let data = "" ;
res . on ( "data" , chunk => ( data += chunk ));
res . on ( "end" , () => {
try {
resolve ( JSON . parse ( data ));
} catch ( e ) {
reject ( e );
}
});
})
. on ( "error" , reject );
});
}
/**
* Compare two semver version strings
* @param {string} v1
* @param {string} v2
* @returns {number} 1 if v1 > v2, -1 if v1 < v2, 0 if equal
*/
function compareVersions ( v1 , v2 ) {
const normalize = ( /** @type {string} */ v ) => v . replace ( /^v/ , "" ). split ( "." ). map ( Number );
const parts1 = normalize ( v1 );
const parts2 = normalize ( v2 );
for ( let i = 0 ; i < Math . max ( parts1 . length , parts2 . length ); i ++ ) {
const num1 = parts1 [ i ] || 0 ;
const num2 = parts2 [ i ] || 0 ;
if ( num1 > num2 ) return 1 ;
if ( num1 < num2 ) return - 1 ;
}
return 0 ;
}
/**
* Check for updates from GitHub
*/
async function checkForUpdates () {
try {
const tags = await fetchJson ( `https://api.github.com/repos/ ${ GITHUB_REPO } /tags` );
if ( ! tags || tags . length === 0 ) {
return ; // No tags found, skip update check
}
// Tags are returned in order, first one is the latest
const latestTag = tags [ 0 ]. name ;
const latestVersion = latestTag . replace ( /^v/ , "" );
if ( compareVersions ( latestVersion , LOCAL_VERSION ) > 0 ) {
console . log ( chalk . yellowBright `\n╔════════════════════════════════════════════════════════════╗` );
console . log ( chalk . yellowBright `║` + chalk . white ` A new version is available: ` + chalk . greenBright `v ${ latestVersion } ` + chalk . white ` (current: ` + chalk . gray `v ${ LOCAL_VERSION } ` + chalk . white `) ` + chalk . yellowBright `║` );
console . log ( chalk . yellowBright `║` + chalk . white ` Update: ` + chalk . cyanBright `https://github.com/ ${ GITHUB_REPO } ` + chalk . white ` ` + chalk . yellowBright `║` );
console . log ( chalk . yellowBright `╚════════════════════════════════════════════════════════════╝\n` );
}
} catch ( e ) {
// Silently ignore update check errors (network issues, etc.)
}
}
2025-10-23 20:31:50 +02:00
// Helper function to remove directory recursively
2025-11-24 05:47:59 +01:00
function rm ( dirPath ) {
2025-10-23 20:31:50 +02:00
if ( ! fs . existsSync ( dirPath )) return ;
if ( ! fs . lstatSync ( dirPath ). isDirectory ()) return fs . rmSync ( dirPath , { force : true });
for ( const entry of fs . readdirSync ( dirPath )) {
const entryPath = path . join ( dirPath , entry );
if ( fs . lstatSync ( entryPath ). isDirectory ()) rm ( entryPath );
else fs . rmSync ( entryPath , { force : true });
}
fs . rmdirSync ( dirPath );
2025-11-24 05:47:59 +01:00
}
2025-10-23 20:31:50 +02:00
// Find HTTP Toolkit installation path
2025-11-24 05:47:59 +01:00
async function findAppPath () {
2025-11-29 00:04:31 +01:00
const possiblePaths = isWin ? [ path . join ( "C:" , "Program Files" , "HTTP Toolkit" , "resources" ), path . join ( "C:" , "Program Files (x86)" , "HTTP Toolkit" , "resources" ), path . join ( process . env . LOCALAPPDATA || path . join ( process . env . USERPROFILE || "" , "AppData" , "Local" ), "Programs" , "HTTP Toolkit" , "resources" )] : isMac ? [ "/Applications/HTTP Toolkit.app/Contents/Resources" ] : [ "/opt/HTTP Toolkit/resources" , "/opt/httptoolkit/resources" ];
2025-10-23 20:31:50 +02:00
for ( const p of possiblePaths ) {
if ( fs . existsSync ( path . join ( p , "app.asar" ))) {
return p ;
}
}
console . log ( chalk . yellowBright `[!] HTTP Toolkit not found in default locations` );
const userPath = await prompt ( "Please enter the path to HTTP Toolkit executable/app: " );
if ( ! userPath ) {
console . error ( chalk . redBright `[-] No path provided` );
process . exit ( 1 );
}
// Extract resources path from user input
let resourcesPath = userPath . trim (). replace ( /['"]/g , "" );
if ( resourcesPath . endsWith ( ".exe" ) || resourcesPath . endsWith ( ".app" )) resourcesPath = path . dirname ( resourcesPath );
if ( ! resourcesPath . endsWith ( "resources" )) resourcesPath = path . join ( resourcesPath , "resources" );
if ( ! fs . existsSync ( path . join ( resourcesPath , "app.asar" ))) {
console . error ( chalk . redBright `[-] app.asar not found at ${ resourcesPath } ` );
process . exit ( 1 );
}
return resourcesPath ;
2025-11-24 05:47:59 +01:00
}
2025-10-23 20:31:50 +02:00
// Request elevated permissions
2025-11-24 05:47:59 +01:00
async function requestElevation () {
2025-10-23 20:31:50 +02:00
console . log ( chalk . yellowBright `[!] Requesting elevated permissions...` );
2025-11-24 05:47:59 +01:00
// @ts-ignore - pkg adds this property at runtime
const isBundled = process . pkg ;
2025-10-23 20:31:50 +02:00
if ( isWin ) {
// Windows: Use PowerShell to run as administrator
2025-11-24 05:47:59 +01:00
let script ;
if ( isBundled ) {
script = `Start-Process -FilePath " ${ __filename } " -Verb RunAs` ;
} else {
script = `Start-Process -FilePath "node" -ArgumentList " ${ __filename } " -Verb RunAs` ;
}
2025-10-23 20:31:50 +02:00
try {
2025-11-24 05:47:59 +01:00
console . log ( chalk . greenBright `[+] Spawning PowerShell with script: ${ script } ` );
execSync ( `powershell -Command " ${ script } "` , { stdio : "inherit" });
2025-10-23 20:31:50 +02:00
console . log ( chalk . blueBright `[+] Restarting with administrator privileges...` );
process . exit ( 0 );
} catch ( e ) {
console . error ( chalk . redBright `[-] Failed to elevate permissions: ${ e . message } ` );
console . error ( chalk . redBright `[-] Please run as administrator manually` );
process . exit ( 1 );
}
2025-11-12 19:01:34 +01:00
} else if ( isLinux ) {
// Linux: Cannot auto-elevate with sudo, show instructions instead
console . log ( chalk . yellowBright `[!] Elevated permissions are required for patching on Linux` );
console . log ( chalk . yellowBright `[!] Please re-run this script with sudo:` );
2025-11-24 05:47:59 +01:00
if ( isBundled ) {
console . log ( chalk . blueBright ` sudo ${ __filename } ` );
} else {
console . log ( chalk . blueBright ` sudo node ${ __filename } ` );
}
2025-11-12 19:01:34 +01:00
process . exit ( 1 );
2025-10-23 20:31:50 +02:00
} else {
2025-11-12 19:01:34 +01:00
// macOS: Try to elevate with sudo
2025-10-23 20:31:50 +02:00
console . log ( chalk . blueBright `[+] Restarting with sudo...` );
try {
2025-11-24 05:47:59 +01:00
let child ;
if ( isBundled ) {
child = spawn ( "sudo" , [ __filename ], {
stdio : "inherit" ,
});
} else {
child = spawn ( "sudo" , [ "node" , __filename ], {
stdio : "inherit" ,
});
}
2025-10-23 20:31:50 +02:00
child . on ( "exit" , code => process . exit ( code || 0 ));
} catch ( e ) {
console . error ( chalk . redBright `[-] Failed to elevate permissions: ${ e . message } ` );
console . error ( chalk . redBright `[-] Please run with sudo manually` );
process . exit ( 1 );
}
}
2025-11-24 05:47:59 +01:00
}
2025-10-23 20:31:50 +02:00
// Check if we have write permissions
2025-11-24 05:47:59 +01:00
function checkPermissions ( filePath ) {
2025-10-23 20:31:50 +02:00
try {
2025-11-24 05:47:59 +01:00
// Check write access to the file/directory
2025-10-23 20:31:50 +02:00
fs . accessSync ( filePath , fs . constants . W_OK );
2025-11-24 05:47:59 +01:00
// Check if we can create directories
const testDirPath = path . join ( path . dirname ( filePath ), `.test_ ${ Date . now () } ` );
try {
fs . mkdirSync ( testDirPath , { recursive : true });
fs . rmdirSync ( testDirPath );
} catch ( dirError ) {
console . error ( chalk . redBright `[-] Cannot create directories in ${ path . dirname ( filePath ) } : ${ dirError . message } ` );
return false ;
}
console . log ( chalk . greenBright `[+] Permissions check passed for ${ filePath } ` );
2025-10-23 20:31:50 +02:00
return true ;
} catch ( e ) {
2025-11-24 05:47:59 +01:00
console . error ( chalk . redBright `[-] Permissions check failed for ${ filePath } : ${ e . message } ` );
2025-10-23 20:31:50 +02:00
return false ;
}
2025-11-24 05:47:59 +01:00
}
2025-10-23 20:31:50 +02:00
// Kill HTTP Toolkit processes
2025-11-24 05:47:59 +01:00
async function killHttpToolkit () {
2025-10-23 20:31:50 +02:00
console . log ( chalk . yellowBright `[+] Checking for running HTTP Toolkit processes...` );
try {
if ( isWin ) {
// Windows: Use tasklist to find and taskkill to terminate
const output = execSync ( 'tasklist /FI "IMAGENAME eq HTTP Toolkit.exe" /FO CSV /NH' , { encoding : "utf-8" });
if ( output . includes ( "HTTP Toolkit.exe" )) {
console . log ( chalk . yellowBright `[!] HTTP Toolkit is running, attempting to close it...` );
execSync ( 'taskkill /F /IM "HTTP Toolkit.exe" /T' , { stdio : "ignore" });
console . log ( chalk . greenBright `[+] HTTP Toolkit processes terminated` );
// Wait a moment for the process to fully close
await new Promise ( resolve => setTimeout ( resolve , 2000 ));
} else {
console . log ( chalk . greenBright `[+] HTTP Toolkit is not running` );
}
} else if ( isMac ) {
// macOS: Use pgrep and pkill
try {
execSync ( 'pgrep -f "HTTP Toolkit"' , { stdio : "ignore" });
console . log ( chalk . yellowBright `[!] HTTP Toolkit is running, attempting to close it...` );
execSync ( 'pkill -f "HTTP Toolkit"' , { stdio : "ignore" });
console . log ( chalk . greenBright `[+] HTTP Toolkit processes terminated` );
await new Promise ( resolve => setTimeout ( resolve , 2000 ));
} catch ( e ) {
console . log ( chalk . greenBright `[+] HTTP Toolkit is not running` );
}
} else {
// Linux: Use pgrep and pkill
try {
execSync ( 'pgrep -f "HTTP Toolkit"' , { stdio : "ignore" });
console . log ( chalk . yellowBright `[!] HTTP Toolkit is running, attempting to close it...` );
execSync ( 'pkill -f "HTTP Toolkit"' , { stdio : "ignore" });
console . log ( chalk . greenBright `[+] HTTP Toolkit processes terminated` );
await new Promise ( resolve => setTimeout ( resolve , 2000 ));
} catch ( e ) {
console . log ( chalk . greenBright `[+] HTTP Toolkit is not running` );
}
}
} catch ( e ) {
console . log ( chalk . yellowBright `[!] Could not check/kill processes: ${ e . message } ` );
console . log ( chalk . yellowBright `[!] If HTTP Toolkit is running, please close it manually` );
}
2025-11-24 05:47:59 +01:00
}
2025-10-23 20:31:50 +02:00
// Unpatch/restore function
2025-11-24 05:47:59 +01:00
async function unpatchApp () {
2025-10-23 20:31:50 +02:00
console . log ( chalk . blueBright `[+] HTTP Toolkit Unpatcher Started` );
// Step 1: Find app path
const appPath = await findAppPath ();
console . log ( chalk . greenBright `[+] HTTP Toolkit found at ${ appPath } ` );
// Step 2: Kill HTTP Toolkit if running
await killHttpToolkit ();
// Step 3: Check permissions
const asarPath = path . join ( appPath , "app.asar" );
const backupPath = path . join ( appPath , "app.asar.bak" );
const extractPath = path . join ( appPath , "app.asar_extracted" );
// Check if we have write permissions on both the directory and the file
const hasPermissions = checkPermissions ( appPath ) && checkPermissions ( asarPath );
if ( ! hasPermissions ) {
console . log ( chalk . yellowBright `[!] No write permissions for ${ appPath } ` );
if ( isElevated ()) {
console . error ( chalk . redBright `[-] Still no permissions even with elevated privileges` );
process . exit ( 1 );
}
console . log ( chalk . yellowBright `[!] Administrator/sudo privileges required for unpatching` );
2025-11-24 05:47:59 +01:00
await requestElevation ();
2025-10-23 20:31:50 +02:00
}
// Step 4: Check if backup exists
if ( ! fs . existsSync ( backupPath )) {
console . error ( chalk . redBright `[-] Backup file not found at ${ backupPath } ` );
console . error ( chalk . redBright `[-] Cannot unpatch without backup file` );
process . exit ( 1 );
}
// Step 5: Restore from backup
console . log ( chalk . yellowBright `[+] Restoring from backup...` );
try {
fs . copyFileSync ( backupPath , asarPath );
console . log ( chalk . greenBright `[+] Restored app.asar from backup` );
} catch ( e ) {
console . error ( chalk . redBright `[-] Failed to restore backup: ${ e . message } ` );
process . exit ( 1 );
}
// Step 6: Clean up extracted files if they exist
if ( fs . existsSync ( extractPath )) {
console . log ( chalk . yellowBright `[+] Removing extracted files...` );
rm ( extractPath );
console . log ( chalk . greenBright `[+] Cleaned up extracted files` );
}
// Step 7: Optionally remove backup
const removeBackup = await prompt ( "Do you want to remove the backup file? (y/n): " );
if ( removeBackup . toLowerCase () === "y" || removeBackup . toLowerCase () === "yes" ) {
fs . rmSync ( backupPath , { force : true });
console . log ( chalk . greenBright `[+] Backup file removed` );
}
console . log ( chalk . greenBright `[+] Successfully unpatched!` );
2025-11-24 05:47:59 +01:00
}
2025-10-23 20:31:50 +02:00
// Main patching function
2025-11-24 05:47:59 +01:00
async function patchApp () {
2025-10-23 20:31:50 +02:00
console . log ( chalk . blueBright `[+] HTTP Toolkit Patcher Started` );
// Step 1: Find app path
const appPath = await findAppPath ();
console . log ( chalk . greenBright `[+] HTTP Toolkit found at ${ appPath } ` );
// Step 2: Kill HTTP Toolkit if running
await killHttpToolkit ();
// Step 3: Check permissions
const asarPath = path . join ( appPath , "app.asar" );
// Check if we have write permissions on both the directory and the file
const hasPermissions = checkPermissions ( appPath ) && checkPermissions ( asarPath );
if ( ! hasPermissions ) {
console . log ( chalk . yellowBright `[!] No write permissions for ${ appPath } ` );
if ( isElevated ()) {
console . error ( chalk . redBright `[-] Still no permissions even with elevated privileges` );
process . exit ( 1 );
}
console . log ( chalk . yellowBright `[!] Administrator/sudo privileges required for patching` );
2025-11-24 05:47:59 +01:00
await requestElevation ();
2025-10-23 20:31:50 +02:00
}
// Step 4: Backup app.asar
const backupPath = path . join ( appPath , "app.asar.bak" );
if ( ! fs . existsSync ( backupPath )) {
console . log ( chalk . yellowBright `[+] Creating backup...` );
fs . copyFileSync ( asarPath , backupPath );
console . log ( chalk . greenBright `[+] Backup created at ${ backupPath } ` );
}
// Step 5: Extract app.asar
const extractPath = path . join ( appPath , "app.asar_extracted" );
console . log ( chalk . yellowBright `[+] Extracting app.asar...` );
rm ( extractPath );
asar . extractAll ( asarPath , extractPath );
console . log ( chalk . greenBright `[+] Extracted to ${ extractPath } ` );
2025-11-29 00:04:31 +01:00
// Step 6: Check if preload.cjs exists
const preloadPath = path . join ( extractPath , "build" , "preload.cjs" );
2025-10-23 20:31:50 +02:00
if ( ! fs . existsSync ( preloadPath )) {
2025-11-29 00:04:31 +01:00
console . error ( chalk . redBright `[-] preload.cjs not found in ${ path . join ( extractPath , "build" ) } ` );
console . error ( chalk . yellowBright `[!] Please download the latest version of HTTP Toolkit from https://httptoolkit.com/` );
rm ( extractPath );
process . exit ( 1 );
2025-10-23 20:31:50 +02:00
}
2025-11-29 00:04:31 +01:00
console . log ( chalk . greenBright `[+] Found preload.cjs` );
2025-10-23 20:31:50 +02:00
2025-11-29 00:04:31 +01:00
// Step 7: Read inject.js from local file (same directory as this script)
console . log ( chalk . yellowBright `[+] Reading inject code from local file...` );
const injectJsPath = path . join ( path . dirname ( __filename ), "inject.js" );
if ( ! fs . existsSync ( injectJsPath )) {
console . error ( chalk . redBright `[-] inject.js not found at ${ injectJsPath } ` );
2025-10-23 20:31:50 +02:00
rm ( extractPath );
process . exit ( 1 );
}
2025-11-29 00:04:31 +01:00
const injectCode = fs . readFileSync ( injectJsPath , "utf-8" );
if ( ! injectCode || ! injectCode . includes ( "PAGE-INJECT" )) {
console . error ( chalk . redBright `[-] Invalid inject.js file` );
rm ( extractPath );
process . exit ( 1 );
}
console . log ( chalk . greenBright `[+] Inject code loaded successfully` );
const preloadPatchCode = `
(function loadInjectScript() {
const injectCode = ${ JSON . stringify ( injectCode ) } ;
function injectViaWebFrame() {
try {
const { webFrame } = electron_1;
if (webFrame && webFrame.executeJavaScript) {
webFrame.executeJavaScript(injectCode).then(() => console.log("[PRELOAD] Injected via webFrame.executeJavaScript")).catch(err => console.error("[PRELOAD] webFrame injection failed:", err));
return true;
}
} catch (e) {
console.error("[PRELOAD] webFrame not available:", e);
}
return false;
}
if (!injectViaWebFrame()) {
const tryInject = () => {
if (!injectViaWebFrame()) {
console.error("[PRELOAD] All injection methods failed");
}
};
if (document.readyState === 'complete' || document.readyState === 'interactive') {
tryInject();
} else {
document.addEventListener('DOMContentLoaded', tryInject, { once: true });
}
}
})();
` ;
2025-10-23 20:31:50 +02:00
2025-11-29 00:04:31 +01:00
// Step 8: Read files and check if already patched
2025-10-23 20:31:50 +02:00
let preloadContent = fs . readFileSync ( preloadPath , "utf-8" );
2025-11-29 00:04:31 +01:00
const isPreloadPatched = preloadContent . includes ( "loadInjectScript" );
2025-10-23 20:31:50 +02:00
2025-11-29 00:04:31 +01:00
if ( isPreloadPatched ) {
console . log ( chalk . yellowBright `[!] Files already patched` );
2025-10-23 20:31:50 +02:00
const answer = await prompt ( "Do you want to repatch? (y/n): " );
if ( answer . toLowerCase () !== "y" && answer . toLowerCase () !== "yes" ) {
console . log ( chalk . blueBright `[+] Patching cancelled` );
rm ( extractPath );
process . exit ( 0 );
}
2025-11-29 00:04:31 +01:00
// Remove existing patches
console . log ( chalk . yellowBright `[+] Replacing existing patches...` );
// Remove preload patch
const preloadPatchRegex = /\n?\(function loadInjectScript\(\) \{[\s\S]*?\}\)\(\);/ ;
preloadContent = preloadContent . replace ( preloadPatchRegex , "" );
}
2025-10-23 20:31:50 +02:00
2025-11-29 00:04:31 +01:00
// Step 9: Patch preload file - find line with electron_1 and insert patch code below it
console . log ( chalk . yellowBright `[+] Applying preload patch...` );
const preloadLines = preloadContent . split ( "\n" );
let preloadInsertIndex = - 1 ;
for ( let i = 0 ; i < preloadLines . length ; i ++ ) {
if ( preloadLines [ i ]. includes ( "electron_1" )) {
preloadInsertIndex = i + 1 ;
break ;
2025-10-23 20:31:50 +02:00
}
2025-11-29 00:04:31 +01:00
}
2025-10-23 20:31:50 +02:00
2025-11-29 00:04:31 +01:00
if ( preloadInsertIndex === - 1 ) {
console . error ( chalk . redBright `[-] Could not find insertion point (electron_1) in ${ path . basename ( preloadPath ) } ` );
rm ( extractPath );
process . exit ( 1 );
2025-10-23 20:31:50 +02:00
}
2025-11-29 00:04:31 +01:00
preloadLines . splice ( preloadInsertIndex , 0 , preloadPatchCode );
preloadContent = preloadLines . join ( "\n" );
// Write patched preload file
2025-10-23 20:31:50 +02:00
fs . writeFileSync ( preloadPath , preloadContent , "utf-8" );
2025-11-24 05:47:59 +01:00
console . log ( chalk . greenBright `[+] ${ path . basename ( preloadPath ) } patched successfully` );
2025-10-23 20:31:50 +02:00
2025-11-29 00:04:31 +01:00
2025-10-23 20:31:50 +02:00
// Step 10: Repackage app.asar
console . log ( chalk . yellowBright `[+] Repackaging app.asar...` );
await asar . createPackage ( extractPath , asarPath );
console . log ( chalk . greenBright `[+] app.asar repackaged successfully` );
// Step 11: Clean up
console . log ( chalk . yellowBright `[+] Cleaning up temporary files...` );
rm ( extractPath );
console . log ( chalk . greenBright `[+] Successfully patched!` );
// Step 12: Open HTTP Toolkit as detached process
console . log ( chalk . blueBright `[+] Opening HTTP Toolkit...` );
try {
2025-11-12 19:01:34 +01:00
if ( isLinux ) {
// Linux: Cannot auto-launch reliably, show manual instructions
console . log ( chalk . yellowBright `[!] HTTP Toolkit has been successfully patched` );
console . log ( chalk . yellowBright `[!] Please manually launch HTTP Toolkit from your applications menu or using the command:` );
console . log ( chalk . blueBright ` httptoolkit` );
} else {
const command = isWin ? `" ${ path . resolve ( appPath , ".." , "HTTP Toolkit.exe" ) } "` : isMac ? 'open -a "HTTP Toolkit"' : "httptoolkit" ;
const child = spawn ( command , {
stdio : "ignore" ,
shell : true ,
detached : true ,
});
2025-11-24 05:47:59 +01:00
child . unref ();
2025-11-12 19:01:34 +01:00
console . log ( chalk . greenBright `[+] HTTP Toolkit launched successfully` );
}
2025-10-23 20:31:50 +02:00
} catch ( e ) {
console . error ( chalk . yellowBright `[!] Could not auto-start HTTP Toolkit: ${ e . message } ` );
console . log ( chalk . blueBright `[+] Please start HTTP Toolkit manually` );
}
2025-11-24 05:47:59 +01:00
}
2025-10-23 20:31:50 +02:00
const args = process . argv . slice ( 2 );
const command = args [ 0 ];
2025-11-24 05:47:59 +01:00
const commandName = (() => {
// @ts-ignore - pkg adds this property at runtime
if ( process . pkg ) {
return path . basename ( __filename );
} else {
return `node ${ process . argv [ 1 ] } ` ;
}
})();
2025-10-23 20:31:50 +02:00
// Run the appropriate command
( async () => {
try {
2025-11-29 00:06:24 +01:00
// Check for updates from GitHub
await checkForUpdates ();
2025-10-23 20:31:50 +02:00
if ( command === "unpatch" || command === "restore" ) {
await unpatchApp ();
} else if ( command === "help" || command === "-h" || command === "--help" ) {
console . log ( chalk . blueBright `HTTP Toolkit Patcher` );
console . log ( chalk . white `\nUsage:` );
console . log ( chalk . white ` ${ commandName } [command]` );
console . log ( chalk . white `\nCommands:` );
console . log ( chalk . white ` patch ${ chalk . gray `- Patch HTTP Toolkit (default)` } ` );
console . log ( chalk . white ` unpatch ${ chalk . gray `- Restore original HTTP Toolkit from backup` } ` );
console . log ( chalk . white ` restore ${ chalk . gray `- Alias for unpatch` } ` );
console . log ( chalk . white ` help ${ chalk . gray `- Show this help message` } ` );
process . exit ( 0 );
} else if ( ! command || command === "patch" ) {
// Ask for confirmation before patching
const answer = await prompt ( "Do you want to patch HTTP Toolkit? [Y/n]: " );
if ( answer . toLowerCase () === "n" || answer . toLowerCase () === "no" ) {
console . log ( chalk . blueBright `[+] Patching cancelled` );
process . exit ( 0 );
}
await patchApp ();
} else {
console . error ( chalk . redBright `[-] Unknown command: ${ command } ` );
console . log ( chalk . yellowBright `[!] Use 'help' to see available commands` );
process . exit ( 1 );
}
} catch ( error ) {
console . error ( chalk . redBright `[-] Error: ${ error . message } ` );
process . exit ( 1 );
}
})();