UNPKG

@koodosbots/kprcli

Version:

KprCli - Global CLI automation client for Telegram bot integration

295 lines (253 loc) • 8.07 kB
#!/usr/bin/env node /** * KprCli - Ultra Simple CLI Client * Zero dependencies, single file solution */ const http = require('http'); const https = require('https'); const readline = require('readline'); const os = require('os'); // Default config const CONFIG = { botUrl: 'http://localhost:3333', version: '1.0.0' }; // Colors for terminal output const colors = { red: '\x1b[31m', green: '\x1b[32m', yellow: '\x1b[33m', blue: '\x1b[34m', magenta: '\x1b[35m', cyan: '\x1b[36m', white: '\x1b[37m', reset: '\x1b[0m' }; function log(message, color = 'white') { console.log(colors[color] + message + colors.reset); } function makeRequest(url, options = {}) { return new Promise((resolve, reject) => { const urlObj = new URL(url); const client = urlObj.protocol === 'https:' ? https : http; const req = client.request(url, options, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { try { const json = JSON.parse(data); resolve({ status: res.statusCode, data: json }); } catch (e) { resolve({ status: res.statusCode, data: data }); } }); }); req.on('error', reject); if (options.body) { req.write(options.body); } req.end(); }); } function askQuestion(question) { const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); return new Promise(resolve => { rl.question(question, answer => { rl.close(); resolve(answer); }); }); } async function login() { log('\nšŸ¤– KprCli Login', 'cyan'); log('===============', 'cyan'); log('\n1. Go to your Telegram bot and run /link', 'white'); log('2. Copy the 6-digit code from Telegram\n', 'white'); const authCode = await askQuestion('Enter authentication code: '); if (!authCode.match(/^[A-F0-9]{6}$/)) { log('āŒ Invalid code format. Expected 6 uppercase hex characters (e.g., ABC123)', 'red'); process.exit(1); } log(`šŸ” Authenticating with code: ${authCode}`, 'yellow'); try { const response = await makeRequest(`${CONFIG.botUrl}/api/cli/auth`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ authCode: authCode, deviceInfo: { hostname: os.hostname(), platform: os.platform(), version: CONFIG.version } }) }); if (response.status === 200 && response.data.success) { log('āœ… Device authenticated successfully!', 'green'); log(`šŸ“± Device ID: ${response.data.deviceId}`, 'blue'); log(`šŸ”‘ Access Token: ${response.data.accessToken.substring(0, 16)}...`, 'blue'); // Save credentials to file require('fs').writeFileSync('.kprcli-config', JSON.stringify({ deviceId: response.data.deviceId, accessToken: response.data.accessToken, botUrl: CONFIG.botUrl })); log('šŸ’¾ Credentials saved to .kprcli-config', 'green'); log('\nRun: kprcli start', 'cyan'); } else { log('āŒ Authentication failed: ' + (response.data.error || 'Unknown error'), 'red'); process.exit(1); } } catch (error) { log('āŒ Connection error: ' + error.message, 'red'); process.exit(1); } } async function start() { // Load credentials let config; try { const configFile = require('fs').readFileSync('.kprcli-config', 'utf8'); config = JSON.parse(configFile); } catch (e) { log('āŒ No configuration found. Please run: kprcli login', 'red'); process.exit(1); } log('\nšŸš€ KprCli Agent Starting...', 'green'); log(`šŸ“± Device: ${config.deviceId.substring(0, 8)}...`, 'blue'); log('šŸ”„ Polling for jobs every 5 seconds', 'yellow'); log('Press Ctrl+C to stop\n', 'white'); let pollCount = 0; const poll = async () => { try { const response = await makeRequest(`${config.botUrl}/api/cli/jobs/${config.deviceId}`, { method: 'GET', headers: { 'Authorization': `Bearer ${config.accessToken}` } }); if (response.status === 200) { pollCount++; const jobs = response.data.jobs || []; if (jobs.length > 0) { log(`šŸ“¬ Found ${jobs.length} job(s):`, 'green'); jobs.forEach(job => { log(` • Job ID: ${job.id}`, 'white'); log(` • Task: ${job.taskType}`, 'white'); log(` • Status: ${job.status}`, 'white'); // Execute job after 2 seconds setTimeout(() => executeJob(config, job), 2000); }); } else { if (pollCount % 12 === 0) { // Show every minute (12 * 5 seconds) log(`šŸ“” Polling... (${pollCount} checks, ${Math.floor(pollCount * 5 / 60)} min)`, 'blue'); } } } } catch (error) { log('āŒ Polling error: ' + error.message, 'red'); } }; // Poll every 5 seconds const interval = setInterval(poll, 5000); // Handle Ctrl+C process.on('SIGINT', () => { clearInterval(interval); log('\nšŸ‘‹ Stopping KprCli agent...', 'yellow'); process.exit(0); }); // Start polling immediately poll(); } async function executeJob(config, job) { log(`⚔ Executing job: ${job.id}...`, 'yellow'); // Simulate work for 1-3 seconds const workTime = Math.random() * 2000 + 1000; await new Promise(resolve => setTimeout(resolve, workTime)); try { const response = await makeRequest(`${config.botUrl}/api/cli/jobs/${job.id}/complete`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ success: true, result: `Task completed successfully by ${os.hostname()}`, error: null }) }); if (response.status === 200) { log(`āœ… Job ${job.id.substring(0, 8)}... completed successfully`, 'green'); } else { log(`āŒ Failed to report job completion`, 'red'); } } catch (error) { log('āŒ Job completion error: ' + error.message, 'red'); } } function showHelp() { log('\nšŸ¤– KprCli - Simple Automation Client', 'cyan'); log('=====================================', 'cyan'); log('\nCommands:', 'white'); log(' kprcli login - Link device to Telegram bot', 'green'); log(' kprcli start - Start automation agent', 'green'); log(' kprcli status - Show device status', 'green'); log(' kprcli help - Show this help', 'green'); log('\nUsage:', 'white'); log(' 1. Run "kprcli login" first', 'yellow'); log(' 2. Enter auth code from Telegram bot', 'yellow'); log(' 3. Run "kprcli start" to begin automation\n', 'yellow'); } function showStatus() { try { const configFile = require('fs').readFileSync('.kprcli-config', 'utf8'); const config = JSON.parse(configFile); log('\nšŸ“Š KprCli Status', 'cyan'); log('================', 'cyan'); log(`Device ID: ${config.deviceId}`, 'blue'); log(`Bot URL: ${config.botUrl}`, 'blue'); log(`Token: ${config.accessToken.substring(0, 16)}...`, 'blue'); log('Status: Configured āœ…', 'green'); log('\nRun: kprcli start', 'yellow'); } catch (e) { log('\nšŸ“Š KprCli Status', 'cyan'); log('================', 'cyan'); log('Status: Not configured āŒ', 'red'); log('Run: kprcli login', 'yellow'); } } // Main CLI handler function main() { const args = process.argv.slice(2); const command = args[0] || 'help'; switch (command) { case 'login': login(); break; case 'start': start(); break; case 'status': showStatus(); break; case 'help': case '--help': case '-h': showHelp(); break; default: log(`āŒ Unknown command: ${command}`, 'red'); showHelp(); break; } } // Run if called directly if (require.main === module) { main(); } module.exports = { main };