desktop-audio-proxy
Version:
A comprehensive audio streaming solution for Tauri and Electron apps that bypasses CORS and WebKit codec issues
876 lines (733 loc) • 40.5 kB
JavaScript
// Desktop Audio Proxy CLI Demo - Professional Terminal Edition
// Full implementation with real browser CORS testing
import { createAudioClient } from '../dist/browser.esm.js';
import fs from 'fs';
import readline from 'readline';
import puppeteer from 'puppeteer';
class HackerCLIDemo {
constructor() {
this.audioClient = null;
this.proxyServerAvailable = false;
this.environment = null;
this.workingProxyUrl = null;
this.testResults = new Map();
this.rl = null;
this.browser = null;
this.browserPage = null;
// Terminal colors and effects
this.colors = {
reset: '\x1b[0m',
bright: '\x1b[1m',
dim: '\x1b[2m',
red: '\x1b[31m',
green: '\x1b[32m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
magenta: '\x1b[35m',
cyan: '\x1b[36m',
white: '\x1b[37m',
bgBlack: '\x1b[40m',
bgRed: '\x1b[41m',
bgGreen: '\x1b[42m',
bgYellow: '\x1b[43m',
bgBlue: '\x1b[44m',
bgMagenta: '\x1b[45m',
bgCyan: '\x1b[46m',
bgWhite: '\x1b[47m'
};
// Handle graceful shutdown
process.on('SIGINT', async () => {
console.log('\nReceived SIGINT, shutting down gracefully...');
await this.cleanup();
process.exit(0);
});
process.on('SIGTERM', async () => {
console.log('\nReceived SIGTERM, shutting down gracefully...');
await this.cleanup();
process.exit(0);
});
this.init();
}
async cleanup() {
if (this.browser) {
try {
await this.browser.close();
console.log('✓ Browser closed');
} catch (error) {
console.log('! Error closing browser:', error.message);
}
}
if (this.rl) {
this.rl.close();
}
}
async init() {
this.clearScreen();
await this.showBootSequence();
await this.showBanner();
await this.initializeSystem();
await this.showMainMenu();
}
clearScreen() {
process.stdout.write('\x1b[2J\x1b[0f');
}
async delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async typeText(text, delay = 30) {
for (const char of text) {
process.stdout.write(char);
await this.delay(delay);
}
}
async showBootSequence() {
const c = this.colors;
console.log(`${c.green}${c.bright}INITIALIZING DESKTOP AUDIO PROXY SYSTEM...${c.reset}`);
await this.delay(500);
const bootMessages = [
"Loading audio proxy modules...",
"Mounting audio subsystems...",
"Initializing CORS bypass protocols...",
"Scanning proxy network topology...",
"Establishing secure channels...",
"Calibrating audio codecs...",
"System ready."
];
for (const msg of bootMessages) {
process.stdout.write(`${c.cyan}[${new Date().toISOString()}]${c.reset} ${msg}`);
await this.delay(Math.random() * 300 + 200);
console.log(` ${c.green}✓${c.reset}`);
}
await this.delay(800);
this.clearScreen();
}
async showBanner() {
const c = this.colors;
const banner = `
${c.cyan}${c.bright}
██████╗ █████╗ ██████╗
██╔══██╗██╔══██╗██╔══██╗
██║ ██║███████║██████╔╝
██║ ██║██╔══██║██╔═══╝
██████╔╝██║ ██║██║
╚═════╝ ╚═╝ ╚═╝╚═╝
${c.reset}
${c.magenta}${c.bright} DESKTOP AUDIO PROXY - TERMINAL INTERFACE${c.reset}
${c.dim} [CAME TO CREATION BY BANDONKER]${c.reset}
${c.yellow}┌─────────────────────────────────────────────────────────────────────────────┐
│ ${c.bright}WARNING: Bypassing CORS restrictions in progress...${c.reset}${c.yellow} │
│ This system enables unrestricted audio streaming across security boundaries │
│ Use responsibly and in accordance with applicable laws and policies │
└─────────────────────────────────────────────────────────────────────────────┘${c.reset}
${c.cyan}┌─────────────────────────────────────────────────────────────────────────────┐
│ ${c.bright}NOTICE: Proxy Server Required for Full Functionality${c.reset}${c.cyan} │
│ To demonstrate CORS bypass capabilities, start the proxy server: │
│ ${c.bright}npm run proxy:start${c.reset}${c.cyan} │
│ Then run this CLI demo in another terminal with: ${c.bright}npm run demo:cli${c.reset}${c.cyan} │
└─────────────────────────────────────────────────────────────────────────────┘${c.reset}
`;
console.log(banner);
await this.delay(1500);
}
async initializeSystem() {
const c = this.colors;
console.log(`${c.green}${c.bright}[SYSTEM INITIALIZATION]${c.reset}`);
console.log(`${c.cyan}➤${c.reset} Loading Desktop Audio Proxy library...`);
try {
await this.initializeLibrary();
console.log(`${c.green}✓${c.reset} Library loaded successfully`);
console.log(`${c.cyan}➤${c.reset} Initializing browser for real CORS testing...`);
await this.initializeBrowser();
console.log(`${c.green}✓${c.reset} Browser initialized successfully`);
console.log(`${c.cyan}➤${c.reset} Scanning network for proxy servers...`);
await this.checkInitialProxyStatus();
console.log(`${c.cyan}➤${c.reset} Detecting system configuration...`);
await this.detectSystemStatus();
console.log(`${c.cyan}➤${c.reset} Analyzing library version...`);
await this.detectLibraryVersion();
console.log(`${c.green}✓${c.reset} System initialization complete`);
// Show helpful tip if proxy server is not available
if (!this.proxyServerAvailable) {
console.log();
console.log(`${c.yellow} TIP: For full CORS bypass functionality, start the proxy server:${c.reset}`);
console.log(`${c.cyan} Terminal 1:${c.reset} npm run proxy:start`);
console.log(`${c.cyan} Terminal 2:${c.reset} npm run demo:cli`);
}
} catch (error) {
console.log(`${c.red}✗${c.reset} System initialization failed: ${error.message}`);
if (this.browser) {
await this.browser.close();
}
process.exit(1);
}
await this.delay(1000);
}
async initializeLibrary() {
// Auto-detect available package builds
const possibleBuilds = [
'../dist/browser.esm.js',
'../dist/browser.cjs',
'./browser.esm.js'
];
let audioClientImport = null;
for (const buildPath of possibleBuilds) {
try {
const module = await import(buildPath);
if (module.createAudioClient) {
audioClientImport = module.createAudioClient;
break;
}
} catch (error) {
// Try next build
}
}
if (!audioClientImport) {
throw new Error('Could not import Desktop Audio Proxy library');
}
// Create the audio client
this.audioClient = audioClientImport({
proxyUrl: 'http://localhost:3002',
autoDetect: true,
fallbackToOriginal: true,
retryAttempts: 3,
retryDelay: 1000,
proxyConfig: {
corsOrigins: '*',
timeout: 60000,
maxRedirects: 20,
enableLogging: false,
userAgent: 'DesktopAudioProxy-CLI/1.1.0'
}
});
}
async initializeBrowser() {
try {
// Launch headless browser for real CORS testing
this.browser = await puppeteer.launch({
headless: true,
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
// NOTE: NOT using --disable-web-security so we get real CORS enforcement
]
});
this.browserPage = await this.browser.newPage();
// Set a realistic user agent
await this.browserPage.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36');
} catch (error) {
throw new Error(`Failed to initialize browser: ${error.message}`);
}
}
async checkInitialProxyStatus() {
const possiblePorts = [3002, 3001, 3003];
this.proxyServerAvailable = false;
this.workingProxyUrl = null;
for (const port of possiblePorts) {
try {
const response = await fetch(`http://localhost:${port}/health`, {
method: 'GET',
headers: { 'Accept': 'application/json' },
signal: AbortSignal.timeout(2000)
});
if (response.ok) {
await response.json(); // Verify it's valid JSON
this.workingProxyUrl = `http://localhost:${port}`;
this.proxyServerAvailable = true;
break;
}
} catch (error) {
// Continue trying other ports
}
}
}
async detectSystemStatus() {
this.environment = this.audioClient.getEnvironment();
}
async detectLibraryVersion() {
let versionInfo = { version: 'unknown', features: [] };
// Try to get version from proxy server
if (this.proxyServerAvailable && this.workingProxyUrl) {
try {
const response = await fetch(`${this.workingProxyUrl}/health`);
if (response.ok) {
const data = await response.json();
if (data.version) {
versionInfo.version = data.version;
}
}
} catch (error) {
// Fallback to package.json
}
}
// Fallback to package.json
if (versionInfo.version === 'unknown') {
try {
const packageJson = JSON.parse(fs.readFileSync('../package.json', 'utf8'));
if (packageJson.version) {
versionInfo.version = packageJson.version;
}
} catch (error) {
// Last resort inference
versionInfo.version = '1.1.0+';
}
}
this.versionInfo = versionInfo;
}
async showMainMenu() {
const c = this.colors;
this.clearScreen();
await this.showSystemStatus();
console.log(`${c.green}${c.bright}[COMMAND INTERFACE]${c.reset}`);
console.log(`${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}`);
const commands = [
{ cmd: '1', desc: 'Test Audio URL' },
{ cmd: '2', desc: 'System Diagnostics' },
{ cmd: '3', desc: 'Proxy Server Status' },
{ cmd: '4', desc: 'Show Example URLs' },
{ cmd: '5', desc: 'Advanced Features Demo' },
{ cmd: '6', desc: 'View Test Results' },
{ cmd: '7', desc: 'Show Startup Commands' },
{ cmd: 'h', desc: 'Help & Documentation' },
{ cmd: 'q', desc: 'Quit System' }
];
commands.forEach(({ cmd, desc }) => {
console.log(`${c.bright}${cmd})${c.reset} ${desc}`);
});
console.log(`${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}`);
this.rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
this.promptCommand();
}
async showSystemStatus() {
const c = this.colors;
console.log(`${c.yellow}${c.bright}[SYSTEM STATUS MATRIX]${c.reset}`);
console.log(`${c.cyan}┌─────────────────────────────────────────────────────────────────────────────┐${c.reset}`);
// Environment status
const envColor = this.environment === 'web' ? c.green :
this.environment === 'unknown' ? c.cyan :
this.environment === 'tauri' ? c.green :
this.environment === 'electron' ? c.green : c.yellow;
const envDisplay = this.environment === 'web' ? 'Web Browser' :
this.environment === 'tauri' ? 'Tauri Application' :
this.environment === 'electron' ? 'Electron Application' :
this.environment === 'unknown' ? 'Node.js CLI' :
'Unknown Environment';
console.log(`${c.cyan}│${c.reset} Environment: ${envColor}${envDisplay.padEnd(60)}${c.reset}${c.cyan}│${c.reset}`);
// Proxy status
const proxyColor = this.proxyServerAvailable ? c.green : c.red;
const proxyStatus = this.proxyServerAvailable ?
`ONLINE (${this.workingProxyUrl.split(':')[2]})` : 'OFFLINE';
console.log(`${c.cyan}│${c.reset} Proxy Server: ${proxyColor}${proxyStatus.padEnd(60)}${c.reset}${c.cyan}│${c.reset}`);
// Library version
const versionColor = this.versionInfo?.version !== 'unknown' ? c.green : c.yellow;
const version = this.versionInfo?.version || 'Unknown';
console.log(`${c.cyan}│${c.reset} Library Ver: ${versionColor}v${version.padEnd(59)}${c.reset}${c.cyan}│${c.reset}`);
// Security status
const securityStatus = this.proxyServerAvailable ? 'CORS BYPASS ACTIVE' : 'LIMITED FUNCTIONALITY';
const securityColor = this.proxyServerAvailable ? c.green : c.yellow;
console.log(`${c.cyan}│${c.reset} Security: ${securityColor}${securityStatus.padEnd(60)}${c.reset}${c.cyan}│${c.reset}`);
console.log(`${c.cyan}└─────────────────────────────────────────────────────────────────────────────┘${c.reset}`);
console.log();
}
promptCommand() {
const c = this.colors;
this.rl.question(`${c.green}${c.bright}[DAP-CLI]${c.reset}${c.cyan}➤${c.reset} `, async (answer) => {
await this.handleCommand(answer.trim().toLowerCase());
});
}
async handleCommand(cmd) {
const c = this.colors;
switch (cmd) {
case '1':
await this.testAudioURL();
break;
case '2':
await this.systemDiagnostics();
break;
case '3':
await this.proxyServerStatus();
break;
case '4':
await this.showExampleURLs();
break;
case '5':
await this.advancedFeaturesDemo();
break;
case '6':
await this.viewTestResults();
break;
case '7':
await this.showStartupCommands();
break;
case 'h':
case 'help':
await this.showHelp();
break;
case 'q':
case 'quit':
case 'exit':
console.log(`${c.red}${c.bright}[SYSTEM SHUTDOWN]${c.reset}`);
console.log(`${c.cyan}➤${c.reset} Terminating connections...`);
await this.cleanup();
console.log(`${c.cyan}--END OF TRANSMISSION--${c.reset}`);
process.exit(0);
break;
default:
console.log(`${c.red}✗${c.reset} Unknown command: ${cmd}`);
console.log(`${c.yellow}Type 'h' for help${c.reset}`);
break;
}
console.log();
this.promptCommand();
}
async testAudioURL() {
const c = this.colors;
console.log(`${c.yellow}${c.bright}[AUDIO URL TESTING PROTOCOL]${c.reset}`);
console.log(`${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}`);
const url = await this.getInput('Enter audio URL to test: ');
if (!url) {
console.log(`${c.red}✗${c.reset} No URL provided`);
return;
}
console.log(`${c.cyan}➤${c.reset} Analyzing URL: ${c.bright}${url}${c.reset}`);
// Test direct URL
console.log(`${c.cyan}➤${c.reset} Testing direct access (without proxy)...`);
const directResult = await this.testDirectAccess(url);
// Test with proxy
console.log(`${c.cyan}➤${c.reset} Testing proxy bypass...`);
const proxyResult = await this.testProxyAccess(url);
// Show results
this.displayTestResults(url, directResult, proxyResult);
// Store results
this.testResults.set(url, {
timestamp: new Date(),
direct: directResult,
proxy: proxyResult,
environment: this.environment
});
}
async testDirectAccess(url) {
if (!this.browserPage) {
return {
success: false,
status: 0,
error: 'Browser not initialized',
details: 'Real browser testing unavailable'
};
}
try {
// Test real CORS behavior in actual browser environment
const result = await this.browserPage.evaluate(async (testUrl) => {
try {
// This is real browser fetch() - will enforce CORS policy
const response = await fetch(testUrl, {
method: 'HEAD',
mode: 'cors', // Explicitly require CORS compliance
headers: {
'X-Requested-With': 'XMLHttpRequest' // Force preflight for most servers
}
});
return {
success: true,
status: response.status,
error: null,
details: `HTTP ${response.status} - CORS allowed by server`
};
} catch (error) {
// Real CORS error from browser
return {
success: false,
status: 0,
error: error.name,
details: `CORS blocked - ${error.message} (real browser enforcement)`
};
}
}, url);
return result;
} catch (error) {
return {
success: false,
status: 0,
error: error.message,
details: `Browser evaluation error - ${error.message}`
};
}
}
async testProxyAccess(url) {
if (!this.proxyServerAvailable) {
return {
success: false,
status: 0,
error: 'Proxy server not available',
details: 'Start proxy server with: npm run proxy:start'
};
}
try {
const playableUrl = await this.audioClient.getPlayableUrl(url);
// Check if the proxy actually processed the URL or if it fell back to original
if (playableUrl === url) {
// The library fell back to the original URL, proxy failed
return {
success: false,
status: 0,
error: 'Proxy fallback occurred',
details: 'Proxy server unavailable - library fell back to original URL'
};
}
// Test if the proxied URL works
const response = await fetch(playableUrl, {
method: 'HEAD',
signal: AbortSignal.timeout(10000)
});
return {
success: response.ok,
status: response.status,
error: null,
details: `Proxied successfully via ${this.workingProxyUrl}`,
proxyUrl: playableUrl
};
} catch (error) {
return {
success: false,
status: 0,
error: error.message,
details: 'Proxy processing failed'
};
}
}
displayTestResults(url, directResult, proxyResult) {
const c = this.colors;
console.log(`${c.yellow}${c.bright}[TEST RESULTS]${c.reset}`);
console.log(`${c.cyan}┌─────────────────────────────────────────────────────────────────────────────┐${c.reset}`);
console.log(`${c.cyan}│${c.reset} URL: ${url.substring(0, 70).padEnd(70)} ${c.cyan}│${c.reset}`);
console.log(`${c.cyan}├─────────────────────────────────────────────────────────────────────────────┤${c.reset}`);
// Direct access result
const directIcon = directResult.success ? '✓' : '✗';
const directColor = directResult.success ? c.green : c.red;
console.log(`${c.cyan}│${c.reset} Direct Access:${directColor}${directIcon} ${directResult.details.padEnd(60)}${c.reset}${c.cyan}│${c.reset}`);
// Proxy access result
const proxyIcon = proxyResult.success ? '✓' : '✗';
const proxyColor = proxyResult.success ? c.green : c.red;
console.log(`${c.cyan}│${c.reset} Proxy Bypass: ${proxyColor}${proxyIcon} ${proxyResult.details.padEnd(60)}${c.reset}${c.cyan}│${c.reset}`);
console.log(`${c.cyan}└─────────────────────────────────────────────────────────────────────────────┘${c.reset}`);
// Analysis
if (directResult.success && proxyResult.success) {
console.log(`${c.green}${c.bright}ANALYSIS:${c.reset} ${c.green}URL is accessible both ways (no CORS restriction)${c.reset}`);
} else if (!directResult.success && proxyResult.success) {
console.log(`${c.green}${c.bright}ANALYSIS:${c.reset} ${c.green}CORS bypass successful! Proxy enables access${c.reset}`);
} else if (directResult.success && !proxyResult.success) {
console.log(`${c.yellow}${c.bright}ANALYSIS:${c.reset} ${c.yellow}Direct access works, proxy issue detected${c.reset}`);
} else {
console.log(`${c.red}${c.bright}ANALYSIS:${c.reset} ${c.red}URL inaccessible or not a valid audio source${c.reset}`);
}
}
async systemDiagnostics() {
const c = this.colors;
console.log(`${c.yellow}${c.bright}[SYSTEM DIAGNOSTICS]${c.reset}`);
console.log(`${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}`);
// Library capabilities
console.log(`${c.cyan}➤${c.reset} Running library capability tests...`);
const capabilities = [
'CORS Bypass via Proxy',
'Environment Auto-detection',
'Fallback Strategy',
'Multi-format Support',
'Range Request Support'
];
if (this.environment === 'tauri' || this.environment === 'electron') {
capabilities.push('Enhanced Codec Detection');
capabilities.push('Audio Metadata Extraction');
capabilities.push('Audio Device Enumeration');
}
console.log(`${c.green}✓${c.reset} Detected capabilities:`);
capabilities.forEach(cap => {
console.log(` ${c.cyan}•${c.reset} ${cap}`);
});
// Network diagnostics
console.log(`${c.cyan}➤${c.reset} Running network diagnostics...`);
const ports = [3002, 3001, 3003];
for (const port of ports) {
try {
const response = await fetch(`http://localhost:${port}/health`, {
signal: AbortSignal.timeout(2000)
});
if (response.ok) {
const data = await response.json();
console.log(` ${c.green}✓${c.reset} Port ${port}: ACTIVE (v${data.version})`);
} else {
console.log(` ${c.yellow}!${c.reset} Port ${port}: Responded but unhealthy`);
}
} catch (error) {
console.log(` ${c.red}✗${c.reset} Port ${port}: Not accessible`);
}
}
await this.delay(1000);
console.log(`${c.green}✓${c.reset} Diagnostics complete`);
}
async proxyServerStatus() {
const c = this.colors;
console.log(`${c.yellow}${c.bright}[PROXY SERVER STATUS]${c.reset}`);
console.log(`${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}`);
if (!this.proxyServerAvailable) {
console.log(`${c.red}✗${c.reset} No proxy server detected`);
console.log(`${c.yellow}!${c.reset} Start proxy server with: ${c.bright}npm run proxy:start${c.reset}`);
return;
}
try {
const response = await fetch(`${this.workingProxyUrl}/health`);
const data = await response.json();
console.log(`${c.green}✓${c.reset} Proxy server is ${c.green}ONLINE${c.reset}`);
console.log(`${c.cyan}┌─────────────────────────────────────────────────────────────────────────────┐${c.reset}`);
console.log(`${c.cyan}│${c.reset} URL: ${this.workingProxyUrl.padEnd(61)} ${c.cyan}│${c.reset}`);
console.log(`${c.cyan}│${c.reset} Version: v${data.version.padEnd(60)} ${c.cyan}│${c.reset}`);
console.log(`${c.cyan}│${c.reset} Status: ${data.status.padEnd(61)} ${c.cyan}│${c.reset}`);
console.log(`${c.cyan}│${c.reset} Uptime: ${Math.floor(data.uptime)}s${' '.repeat(60 - Math.floor(data.uptime).toString().length - 1)} ${c.cyan}│${c.reset}`);
console.log(`${c.cyan}│${c.reset} Port: ${data.config.port.toString().padEnd(61)} ${c.cyan}│${c.reset}`);
console.log(`${c.cyan}│${c.reset} Transcoding: ${data.config.enableTranscoding.toString().padEnd(61)} ${c.cyan}│${c.reset}`);
console.log(`${c.cyan}│${c.reset} Cache: ${data.config.cacheEnabled.toString().padEnd(61)} ${c.cyan}│${c.reset}`);
console.log(`${c.cyan}└─────────────────────────────────────────────────────────────────────────────┘${c.reset}`);
} catch (error) {
console.log(`${c.red}✗${c.reset} Error getting proxy status: ${error.message}`);
}
}
async showExampleURLs() {
const c = this.colors;
console.log(`${c.yellow}${c.bright}[EXAMPLE AUDIO URLS]${c.reset}`);
console.log(`${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}`);
const testUrls = [
{ url: 'https://d3ctxlq1ktw2nl.cloudfront.net/production/2019-6-29/19776794-44100-2-1840c87ba7791.mp3', desc: 'Podcast Episode (CORS Blocked)' },
{ url: 'https://d3ctxlq1ktw2nl.cloudfront.net/production/2019-4-20/15524768-44100-2-08241a87e299b.mp3', desc: 'Tech Podcast (CORS Blocked)' },
{ url: 'https://www.learningcontainer.com/wp-content/uploads/2020/02/Kalimba.mp3', desc: 'Kalimba MP3 (CORS Blocked)' },
{ url: 'https://www.kozco.com/tech/piano2.wav', desc: 'Piano WAV (CORS Blocked)' },
{ url: 'https://traffic.libsyn.com/secure/noclippodcast/233.mp3', desc: 'Gaming Podcast (CORS Allowed)' }
];
console.log(`${c.green}${c.bright}TEST AUDIO URLS:${c.reset}`);
testUrls.forEach((item, index) => {
console.log(`${c.bright}${index + 1})${c.reset} ${item.desc}`);
console.log(` ${c.dim}${item.url}${c.reset}`);
});
console.log();
const testUrl = await this.getInput('Enter number to test URL (or press Enter to continue): ');
if (testUrl && !isNaN(testUrl)) {
const num = parseInt(testUrl) - 1;
if (num >= 0 && num < testUrls.length) {
console.log(`${c.cyan}➤${c.reset} Testing ${testUrls[num].desc}...`);
await this.testSpecificUrl(testUrls[num].url);
}
}
}
async testSpecificUrl(url) {
const directResult = await this.testDirectAccess(url);
const proxyResult = await this.testProxyAccess(url);
this.displayTestResults(url, directResult, proxyResult);
}
async advancedFeaturesDemo() {
const c = this.colors;
console.log(`${c.yellow}${c.bright}[ADVANCED FEATURES DEMONSTRATION]${c.reset}`);
console.log(`${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}`);
console.log(`${c.cyan}➤${c.reset} Environment: ${this.environment}`);
console.log(`${c.cyan}➤${c.reset} Available methods:`);
const methods = Object.getOwnPropertyNames(Object.getPrototypeOf(this.audioClient));
methods.forEach(method => {
if (!method.startsWith('_') && method !== 'constructor') {
console.log(` ${c.cyan}•${c.reset} ${method}()`);
}
});
if (this.environment === 'tauri' || this.environment === 'electron') {
console.log(`${c.green}✓${c.reset} Enhanced features available for ${this.environment} environment`);
console.log(` ${c.cyan}•${c.reset} Audio metadata extraction`);
console.log(` ${c.cyan}•${c.reset} Device enumeration`);
console.log(` ${c.cyan}•${c.reset} System audio info`);
} else {
console.log(`${c.yellow}!${c.reset} Basic features only (web environment)`);
console.log(`${c.dim} Enhanced features require Tauri or Electron${c.reset}`);
}
}
async viewTestResults() {
const c = this.colors;
console.log(`${c.yellow}${c.bright}[TEST RESULTS HISTORY]${c.reset}`);
console.log(`${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}`);
if (this.testResults.size === 0) {
console.log(`${c.yellow}!${c.reset} No test results available`);
console.log(`${c.dim} Run some URL tests first (option 1)${c.reset}`);
return;
}
Array.from(this.testResults.entries()).forEach(([url, result], index) => {
const directIcon = result.direct.success ? '✓' : '✗';
const proxyIcon = result.proxy.success ? '✓' : '✗';
const directColor = result.direct.success ? c.green : c.red;
const proxyColor = result.proxy.success ? c.green : c.red;
console.log(`${c.bright}${index + 1})${c.reset} ${url.substring(0, 60)}...`);
console.log(` Direct: ${directColor}${directIcon}${c.reset} Proxy: ${proxyColor}${proxyIcon}${c.reset} ${c.dim}(${result.timestamp.toLocaleTimeString()})${c.reset}`);
});
}
async showHelp() {
const c = this.colors;
console.log(`${c.yellow}${c.bright}[HELP & DOCUMENTATION]${c.reset}`);
console.log(`${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}`);
console.log(`${c.green}${c.bright}ABOUT DESKTOP AUDIO PROXY:${c.reset}`);
console.log(`Desktop Audio Proxy is a TypeScript library that enables audio streaming`);
console.log(`in desktop applications by bypassing CORS restrictions and codec issues.`);
console.log();
console.log(`${c.green}${c.bright}KEY FEATURES:${c.reset}`);
console.log(`${c.cyan}•${c.reset} CORS bypass via proxy server`);
console.log(`${c.cyan}•${c.reset} Auto-detection of Tauri/Electron/Web environments`);
console.log(`${c.cyan}•${c.reset} Fallback strategies for reliability`);
console.log(`${c.cyan}•${c.reset} Support for multiple audio formats`);
console.log(`${c.cyan}•${c.reset} Range request support for seeking`);
console.log();
console.log(`${c.green}${c.bright}USAGE:${c.reset}`);
console.log(`1. Start proxy server: ${c.bright}npm run proxy:start${c.reset}`);
console.log(`2. Test audio URLs to see CORS bypass in action`);
console.log(`3. Use system diagnostics to verify configuration`);
console.log();
console.log(`${c.green}${c.bright}LINKS:${c.reset}`);
console.log(`GitHub: https://github.com/bandonker/desktop-audio-proxy`);
console.log(`NPM: https://www.npmjs.com/package/desktop-audio-proxy`);
}
async showStartupCommands() {
const c = this.colors;
console.log(`${c.yellow}${c.bright}[STARTUP COMMANDS REFERENCE]${c.reset}`);
console.log(`${c.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}`);
console.log(`${c.green}${c.bright}REQUIRED SETUP FOR FULL CORS BYPASS DEMONSTRATION:${c.reset}`);
console.log();
console.log(`${c.cyan}${c.bright}Terminal 1 - Start Proxy Server:${c.reset}`);
console.log(`${c.bright}npm run proxy:start${c.reset}`);
console.log(`${c.dim}This starts the Desktop Audio Proxy server on http://localhost:3002${c.reset}`);
console.log();
console.log(`${c.cyan}${c.bright}Terminal 2 - Run CLI Demo:${c.reset}`);
console.log(`${c.bright}npm run demo:cli${c.reset}`);
console.log(`${c.dim}This starts the interactive CLI demonstration interface${c.reset}`);
console.log();
console.log(`${c.green}${c.bright}ALTERNATIVE COMMANDS:${c.reset}`);
console.log(`${c.cyan}•${c.reset} Build library: ${c.bright}npm run build${c.reset}`);
console.log(`${c.cyan}•${c.reset} Run tests: ${c.bright}npm test${c.reset}`);
console.log(`${c.cyan}•${c.reset} Web demo: ${c.bright}npm run demo:serve${c.reset} (then visit http://localhost:8080)`);
console.log(`${c.cyan}•${c.reset} Integration test: ${c.bright}npm run test:integration${c.reset}`);
console.log();
console.log(`${c.green}${c.bright}CURRENT STATUS:${c.reset}`);
if (this.proxyServerAvailable) {
console.log(`${c.green}✓${c.reset} Proxy server is running on ${this.workingProxyUrl}`);
console.log(`${c.green}✓${c.reset} Ready to demonstrate CORS bypass functionality`);
} else {
console.log(`${c.red}✗${c.reset} Proxy server not detected`);
console.log(`${c.yellow}!${c.reset} Start proxy server to enable full CORS bypass testing`);
}
console.log();
console.log(`${c.dim}💡 Pro tip: Keep both terminals open for the best demonstration experience${c.reset}`);
}
async getInput(prompt) {
const c = this.colors;
return new Promise((resolve) => {
this.rl.question(`${c.cyan}${prompt}${c.reset}`, (answer) => {
resolve(answer.trim());
});
});
}
}
// Initialize the hacker CLI demo
new HackerCLIDemo();