UNPKG

altaf

Version:

Altaf Hossen - Interactive CLI Portfolio

889 lines (781 loc) 32.6 kB
#!/usr/bin/env node const fs = require('fs'); const path = require('path'); const readline = require('readline'); const { spawn } = require('child_process'); const { platform } = require('os'); const https = require('https'); const { promisify } = require('util'); // Enhanced color themes const themes = { default: { primary: '\x1b[36m', // cyan secondary: '\x1b[33m', // yellow accent: '\x1b[35m', // magenta success: '\x1b[32m', // green warning: '\x1b[33m', // yellow error: '\x1b[31m', // red info: '\x1b[34m', // blue text: '\x1b[37m', // white dim: '\x1b[90m', // gray bright: '\x1b[1m', reset: '\x1b[0m' }, matrix: { primary: '\x1b[92m', // bright green secondary: '\x1b[32m', // green accent: '\x1b[92m', // bright green success: '\x1b[92m', // bright green warning: '\x1b[33m', // yellow error: '\x1b[91m', // bright red info: '\x1b[92m', // bright green text: '\x1b[32m', // green dim: '\x1b[90m', // gray bright: '\x1b[1m', reset: '\x1b[0m' }, cyberpunk: { primary: '\x1b[95m', // bright magenta secondary: '\x1b[96m', // bright cyan accent: '\x1b[93m', // bright yellow success: '\x1b[92m', // bright green warning: '\x1b[93m', // bright yellow error: '\x1b[91m', // bright red info: '\x1b[94m', // bright blue text: '\x1b[97m', // bright white dim: '\x1b[90m', // gray bright: '\x1b[1m', reset: '\x1b[0m' }, professional: { primary: '\x1b[34m', // blue secondary: '\x1b[36m', // cyan accent: '\x1b[35m', // magenta success: '\x1b[32m', // green warning: '\x1b[33m', // yellow error: '\x1b[31m', // red info: '\x1b[34m', // blue text: '\x1b[37m', // white dim: '\x1b[90m', // gray bright: '\x1b[1m', reset: '\x1b[0m' } }; // Current theme let currentTheme = 'default'; // Helper function to colorize text with current theme const colorize = (text, colorType) => { const theme = themes[currentTheme]; return (theme[colorType] || theme.text) + text + theme.reset; }; // Animation utilities const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)); // Typewriter effect async function typeWriter(text, color = 'text', speed = 50) { for (let i = 0; i < text.length; i++) { process.stdout.write(colorize(text[i], color)); await sleep(speed); } } // Loading animation async function showLoading(text, duration = 2000) { const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']; let i = 0; const startTime = Date.now(); const interval = setInterval(() => { process.stdout.write('\r' + colorize(frames[i % frames.length] + ' ' + text, 'primary')); i++; }, 100); await sleep(duration); clearInterval(interval); process.stdout.write('\r' + colorize('✓ ' + text + ' completed!', 'success') + '\n'); } // Progress bar async function showProgress(text, steps = 20, duration = 1000) { process.stdout.write(colorize(text + '\n', 'info')); for (let i = 0; i <= steps; i++) { const percent = Math.round((i / steps) * 100); const filled = '█'.repeat(Math.round(i * 30 / steps)); const empty = '░'.repeat(30 - Math.round(i * 30 / steps)); process.stdout.write('\r' + colorize(`[${filled}${empty}] ${percent}%`, 'primary')); await sleep(duration / steps); } console.log('\n'); } // Glitch effect for text function glitchText(text, iterations = 3) { const glitchChars = '!@#$%^&*()_+-=[]{}|;:,.<>?'; let result = text; for (let i = 0; i < iterations; i++) { setTimeout(() => { let glitched = ''; for (let j = 0; j < text.length; j++) { if (Math.random() < 0.1) { glitched += glitchChars[Math.floor(Math.random() * glitchChars.length)]; } else { glitched += text[j]; } } process.stdout.write('\r' + colorize(glitched, 'accent')); if (i === iterations - 1) { setTimeout(() => { process.stdout.write('\r' + colorize(text, 'primary')); }, 100); } }, i * 100); } } // Personal Information const personalInfo = { name: 'ALTAF HOSSEN', title: 'Fullstack Web Developer', tagline: 'I create Exciting Stuff on the Internet', bio: `Hey there! 👋🏻 I'm ALTAF, a full stack web developer with a strong passion for crafting digital realms that captivate and inspire. If you're seeking a dedicated and passionate web developer, I'm eager to collaborate with you. Let's bring your ideas to life!`, email: 'altafhossen.pro@gmail.com', github: 'https://github.com/altafhossen-pro', linkedin: 'https://www.linkedin.com/in/altafhossen', website: 'https://altaf-hossen.netlify.app', phone: '+88 013 40 60 30 55', githubUsername: 'altafhossen-pro' // For API calls }; // Tech Stack with experience levels const techStack = { 'Frontend': [ 'HTML', 'CSS', 'JavaScript', 'TypeScript', 'React.js', 'Next.js', 'Bootstrap', 'Tailwind CSS', 'GSAP', 'Motion', 'Redux', 'Zustand', 'TS Query', ' React Query', ' React Hook Form', 'Formik', 'Framer Motion', 'Ant Design', 'Material UI', 'Chakra UI', 'Styled Components', 'Emotion' ], 'Backend': [ 'Node.js', 'Express.js', 'MongoDB', 'MySQL', 'Firebase', 'PHP', 'REST API', 'GraphQL', 'Socket.io', 'Drive API', 'AWS S3', 'Redis', 'PostgreSQL' ], 'Programming Languages': [ 'JavaScript', 'PHP', 'Python' ], 'DevOps': [ 'Docker', 'Kubernetes', 'CI/CD', 'GitHub Actions', 'Jenkins', 'Netlify', 'Vercel', 'AWS', 'Azure', 'Heroku', 'DigitalOcean', 'Firebase Hosting', 'Cloudflare', 'NGINX', 'Apache' ], 'Testing': [ 'Jest', 'Mocha', 'Chai', 'Cypress', 'Selenium', 'Supertest', 'Enzyme', 'React Testing Library', 'Vitest' ], 'Tools & Technologies': [ 'NPM', 'Bun', 'Git', 'GitHub', 'GitLab', 'BitBucket', 'VS Code', 'Figma', 'Postman', 'Swagger', 'Insomnia', 'Webpack', 'Babel', 'ESLint', 'Prettier' ] }; // Projects with detailed info const projects = [ { name: 'Famous Bazar', description: 'A modern ecommerce website for daily essentials and quality products, featuring secure shopping, discount management, and fast delivery system in all over Bangladesh.', demo: 'https://famousbazarbd.com', tech: ["React.js", "Next.js", "Redux", "Node.js", "MongoDB", "Express.js"], status: 'Live', year: 2024, features: ['Payment Integration', 'Admin Panel', 'Real-time Chat', 'Order Tracking'] }, { name: 'Bongo Courier', description: 'A modern courier service website for fast, secure, and trackable parcel delivery across Bangladesh, with real-time tracking and efficient parcel management system.', demo: 'https://bongo-courier.netlify.app', tech: ['Next.js', 'MongoDB', 'Express.js', 'Tailwind CSS'], status: 'Live', year: 2024, features: ['Real-time Tracking', 'SMS Notifications', 'Route Optimization', 'Mobile App'] }, { name: 'Parcel Score', description: 'A smart fraud-checking system to evaluate parcel risk levels using sender history, delivery behavior, and data patterns to prevent misuse and ensure secure courier operations.', demo: 'https://percelscore.top', tech: ['React.js', 'Next.js', 'MongoDB', 'REST API'], status: 'Beta', year: 2024, features: ['ML Algorithm', 'Risk Assessment', 'Analytics Dashboard', 'API Integration'] }, { name: 'Utility Tools', description: 'A multi-functional web platform offering 30+ fast, secure, and easy-to-use utility tools, designed to simplify daily digital tasks for users across all devices.', demo: 'https://altaf-tools.netlify.app', tech: ['JavaScript', 'React.js', 'Next.js'], status: 'Live', year: 2023, features: ['30+ Tools', 'Mobile Responsive', 'No Registration', 'Fast Processing'] }, { name: 'Rent Management System', description: 'A powerful bill and rent management system built for Bangladeshi landlords, mess managers, and property owners, featuring subscription plans, real-time tracking, digital payments, and tenant portals.', demo: 'https://rent-billing.netlify.app', tech: ['React.js', 'Next.js', 'Node.js', 'MySQL', 'Firebase'], status: 'Live', year: 2023, features: ['Payment Gateway', 'Tenant Portal', 'SMS Alerts', 'Report Generation'] }, { name: 'Job Portal X', description: 'A comprehensive job portal system for connecting employers with job seekers, featuring advanced search, application tracking, and profile management.', demo: 'https://job-portal-x.netlify.app', tech: ['Next.js', 'React.js', 'Redux', 'Node.js', 'Express.js', 'MongoDB', 'Tailwind CSS'], status: 'Development', year: 2024, features: ['AI Matching', 'Video Interviews', 'Skill Assessment', 'Analytics'] } ]; // GitHub stats cache let githubStats = null; let lastFetch = 0; // Fetch GitHub stats async function fetchGitHubStats() { const now = Date.now(); if (githubStats && (now - lastFetch) < 300000) { // 5 minutes cache return githubStats; } return new Promise((resolve) => { const options = { hostname: 'api.github.com', path: `/users/${personalInfo.githubUsername}`, method: 'GET', headers: { 'User-Agent': 'CLI-Portfolio' } }; const req = https.request(options, (res) => { let data = ''; res.on('data', (chunk) => data += chunk); res.on('end', () => { try { const parsed = JSON.parse(data); githubStats = { followers: parsed.followers || 0, following: parsed.following || 0, public_repos: parsed.public_repos || 0, created_at: parsed.created_at || '', updated_at: parsed.updated_at || '' }; lastFetch = now; resolve(githubStats); } catch (e) { resolve({ followers: 0, following: 0, public_repos: 0 }); } }); }); req.on('error', () => { resolve({ followers: 0, following: 0, public_repos: 0 }); }); req.setTimeout(5000, () => { req.abort(); resolve({ followers: 0, following: 0, public_repos: 0 }); }); req.end(); }); } let headerShown = false; // Enhanced ASCII Art with theme support function getAsciiArt() { const fixedMatrix = ` ╔═══════════════════════════════════════════════════════════════╗ ║ ║ ║ █████╗ ██╗ ████████╗ █████╗ ███████╗ ║ ║ ██╔══██╗██║ ╚══██╔══╝██╔══██╗██╔════╝ ║ ║ ███████║██║ ██║ ███████║█████╗ ║ ║ ██╔══██║██║ ██║ ██╔══██║██╔══╝ ║ ║ ██║ ██║███████╗██║ ██║ ██║██║ ║ ║ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝╚═╝ ║ ║ ║ ║ Welcome to my Portfolio Website ║ ║ ║ ║ FULLSTACK WEB DEVELOPER ║ ║ "I create Exciting Stuff on the Internet" ║ ║ ║ ╚═══════════════════════════════════════════════════════════════╝`; const arts = { default: fixedMatrix, matrix: fixedMatrix, cyberpunk: fixedMatrix, }; return arts[currentTheme] || arts.default; } // Create readline interface with better handling const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); // Enhanced keyboard input handling function setupKeyboardInput() { if (process.stdin.isTTY) { process.stdin.setRawMode(true); } process.stdin.setEncoding('utf8'); } // Clear screen function function clearScreen() { console.clear(); headerShown = false; // Reset header state when clearing } // Show header with animation async function showHeader() { if (!headerShown) { clearScreen(); console.log(colorize(getAsciiArt(), 'primary')); // console.log(colorize(` ${personalInfo.title}`, 'success')); // console.log(colorize(` ${personalInfo.tagline}\n`, 'dim')); headerShown = true; } } // Create enhanced box with better styling function createBox(text, title = '', color = 'text') { const lines = text.split('\n'); const maxLength = Math.max(...lines.map(line => line.length), title.length); const width = Math.max(Math.min(maxLength + 4, 80), 20); let box = ''; box += colorize('╔' + '═'.repeat(width - 2) + '╗\n', color); if (title) { const titlePadding = Math.max(0, Math.floor((width - title.length - 2) / 2)); const rightPadding = Math.max(0, width - title.length - titlePadding - 2); box += colorize('║' + ' '.repeat(titlePadding) + title + ' '.repeat(rightPadding) + '║\n', color); box += colorize('╠' + '═'.repeat(width - 2) + '╣\n', color); } lines.forEach(line => { const trimmedLine = line.substring(0, width - 4); const padding = Math.max(0, width - trimmedLine.length - 2); box += colorize('║ ' + trimmedLine + ' '.repeat(Math.max(0, padding - 1)) + '║\n', color); }); box += colorize('╚' + '═'.repeat(width - 2) + '╝\n', color); return box; } // Enhanced about section async function showAbout() { await showHeader(); await showLoading('Loading about information', 1000); console.log(createBox(personalInfo.bio, '👨‍💻 About Me', 'text')); console.log(colorize('\nPress Enter to continue...', 'dim')); } // Enhanced skills section with progress bars async function showSkills() { await showHeader(); await showLoading('Loading skills data', 1200); console.log(colorize('🚀 Tech Stack & Skills\n', 'primary')); for (const [category, skills] of Object.entries(techStack)) { console.log(colorize(`${category}:`, 'secondary')); // Display skills in a more organized way const skillsPerLine = 3; const chunks = []; for (let i = 0; i < skills.length; i += skillsPerLine) { chunks.push(skills.slice(i, i + skillsPerLine)); } chunks.forEach(chunk => { const line = chunk.map(skill => colorize(`• ${skill}`, 'success')).join(' '); console.log(` ${line}`); }); console.log(''); // Empty line between categories } // Show total skills count const totalSkills = Object.values(techStack).flat().length; console.log(colorize(`📊 Total Skills: ${totalSkills}`, 'info')); console.log(colorize('\nPress Enter to continue...', 'dim')); } // Enhanced projects section async function showProjects() { await showHeader(); await showLoading('Fetching project information', 1500); console.log(colorize('💼 My Projects\n', 'primary')); for (const [index, project] of projects.entries()) { const statusColor = project.status === 'Live' ? 'success' : project.status === 'Beta' ? 'warning' : 'info'; const projectInfo = `${project.description} Status: ${project.status} | Year: ${project.year} Tech Stack: ${project.tech.join(', ')} Features: ${project.features.join(', ')} Demo: ${project.demo}`; console.log(createBox(projectInfo, `${index + 1}. ${project.name}`, 'text')); } console.log(colorize('\nPress Enter to continue...', 'dim')); } // Enhanced contact section with GitHub stats async function showContact() { await showHeader(); await showLoading('Fetching contact information', 1000); console.log(colorize('Fetching GitHub stats...', 'info')); const stats = await fetchGitHubStats(); const contactInfo = `📧 Email: ${personalInfo.email} 📱 Phone: ${personalInfo.phone} 🌐 Website: ${personalInfo.website} 💼 GitHub: ${personalInfo.github} 🔗 LinkedIn: ${personalInfo.linkedin} 📊 GitHub Stats: Repositories: ${stats.public_repos} Followers: ${stats.followers} Following: ${stats.following} 💬 Let's collaborate! Contact me to discuss your web development needs or just to say hello. 😉`; console.log(createBox(contactInfo, '📞 Contact Information', 'accent')); console.log(colorize('\nPress Enter to continue...', 'dim')); } // Theme selector async function showThemeSelector() { await showHeader(); console.log(colorize('🎨 Choose Your Theme\n', 'primary')); console.log(colorize('1. Default Theme', 'text')); console.log(colorize('2. Matrix Theme', 'success')); console.log(colorize('3. Cyberpunk Theme', 'accent')); console.log(colorize('4. Professional Theme', 'info')); console.log(colorize('5. Back to Main Menu', 'dim')); rl.question(colorize('\nEnter your choice (1-5): ', 'secondary'), (answer) => { handleThemeChoice(answer.trim()); }); } // Handle theme choice async function handleThemeChoice(choice) { const themeMap = { '1': 'default', '2': 'matrix', '3': 'cyberpunk', '4': 'professional' }; if (themeMap[choice]) { currentTheme = themeMap[choice]; await showLoading(`Switching to ${currentTheme} theme`, 1000); console.log(colorize(`✓ Theme changed to ${currentTheme}!`, 'success')); setTimeout(() => showMenu(), 1000); } else if (choice === '5') { showMenu(); } else { console.log(colorize('Invalid choice! Please enter 1-5.', 'error')); setTimeout(() => showThemeSelector(), 1000); } } // Open URL function function openUrl(url) { const startCommand = platform() === 'win32' ? 'start' : platform() === 'darwin' ? 'open' : 'xdg-open'; try { if (platform() === 'win32') { spawn('cmd', ['/c', 'start', url], { stdio: 'ignore' }); } else { spawn(startCommand, [url], { stdio: 'ignore' }); } console.log(colorize(`✓ Opening ${url}...`, 'success')); } catch (error) { console.log(colorize(`Please visit: ${url}`, 'warning')); } } // Enhanced main menu async function showMenu() { await showHeader(); console.log(colorize('What would you like to know about Altaf?\n', 'primary')); console.log(colorize('1. 👨‍💻 About Me', 'text')); console.log(colorize('2. 🚀 Skills & Tech Stack', 'text')); console.log(colorize('3. 💼 My Projects', 'text')); console.log(colorize('4. 📞 Contact Information', 'text')); console.log(colorize('5. 🎨 Change Theme', 'text')); console.log(colorize('6. 🌐 Open Website', 'text')); console.log(colorize('7. 💼 Open GitHub', 'text')); console.log(colorize('8. 🔗 Open LinkedIn', 'text')); console.log(colorize('9. ❌ Exit', 'text')); rl.question(colorize('\nEnter your choice (1-9): ', 'secondary'), (answer) => { handleMenuChoice(answer.trim()); }); } // Handle menu choice async function handleMenuChoice(choice) { switch (choice) { case '1': await showAbout(); rl.question('', () => showMenu()); break; case '2': await showSkills(); rl.question('', () => showMenu()); break; case '3': await showProjects(); rl.question('', () => showMenu()); break; case '4': await showContact(); rl.question('', () => showMenu()); break; case '5': showThemeSelector(); break; case '6': openUrl(personalInfo.website); setTimeout(() => showMenu(), 1000); break; case '7': openUrl(personalInfo.github); setTimeout(() => showMenu(), 1000); break; case '8': openUrl(personalInfo.linkedin); setTimeout(() => showMenu(), 1000); break; case '9': console.log(colorize('\n🙏 Thanks for checking out my portfolio!', 'secondary')); console.log(colorize('Have a great day! 👋\n', 'success')); rl.close(); process.exit(0); break; default: console.log(colorize('Invalid choice! Please enter 1-9.', 'error')); setTimeout(() => showMenu(), 1000); } } // Handle command line arguments async function handleArgs() { const args = process.argv.slice(2); // Check for theme argument const themeIndex = args.indexOf('--theme'); if (themeIndex !== -1 && args[themeIndex + 1]) { const theme = args[themeIndex + 1]; if (themes[theme]) { currentTheme = theme; console.log(colorize(`Using ${theme} theme`, 'success')); } } if (args.includes('--about') || args.includes('-a')) { await showAbout(); rl.question('', () => rl.close()); } else if (args.includes('--skills') || args.includes('-s')) { await showSkills(); rl.question('', () => rl.close()); } else if (args.includes('--projects') || args.includes('-p')) { await showProjects(); rl.question('', () => rl.close()); } else if (args.includes('--contact') || args.includes('-c')) { await showContact(); rl.question('', () => rl.close()); } else if (args.includes('--theme')) { showThemeSelector(); } else if (args.includes('--help') || args.includes('-h')) { showHelp(); rl.question('', () => rl.close()); } else { // Show interactive menu showMenu(); } } // Show enhanced help function showHelp() { clearScreen(); console.log(colorize(getAsciiArt(), 'primary')); const helpText = `Available Commands: Interactive Mode: npx altaf Show interactive menu Direct Commands: npx altaf --about Show about information npx altaf --skills Show skills and tech stack npx altaf --projects Show projects npx altaf --contact Show contact information npx altaf --theme Show theme selector npx altaf --help Show this help message Theme Options: npx altaf --theme default Use default theme npx altaf --theme matrix Use matrix theme npx altaf --theme cyberpunk Use cyberpunk theme npx altaf --theme professional Use professional theme Short flags: -a, --about About information -s, --skills Skills and tech stack -p, --projects Projects -c, --contact Contact information -h, --help Help message Features: • Multiple color themes • Animated text effects • Loading animations • Progress bars • Live GitHub stats • Interactive navigation`; console.log(createBox(helpText, '📚 Help & Usage', 'info')); console.log(colorize('\nPress Enter to continue...', 'dim')); } // Easter egg - Matrix rain effect function matrixRain() { const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$%^&*()'; const columns = Math.floor(process.stdout.columns / 2); const drops = new Array(columns).fill(0); console.log(colorize('Entering the Matrix...', 'success')); const interval = setInterval(() => { process.stdout.write('\x1b[2J\x1b[0;0H'); // Clear screen for (let i = 0; i < drops.length; i++) { const char = chars[Math.floor(Math.random() * chars.length)]; process.stdout.write('\x1b[' + drops[i] + ';' + (i * 2) + 'H'); process.stdout.write(colorize(char, 'primary')); if (drops[i] * 2 > process.stdout.rows && Math.random() > 0.975) { drops[i] = 0; } drops[i]++; } }, 100); setTimeout(() => { clearInterval(interval); clearScreen(); console.log(colorize('Welcome back to reality!', 'success')); setTimeout(() => showMenu(), 1000); }, 5000); } // Enhanced startup animation async function startupAnimation() { console.log(colorize('Initializing Altaf\'s Portfolio...', 'primary')); await showProgress('Loading modules', 15, 800); await showProgress('Connecting to GitHub API', 10, 500); await showProgress('Setting up themes', 8, 400); await showProgress('Ready to launch', 5, 300); console.log(colorize('✓ Portfolio loaded successfully!', 'success')); await sleep(500); } // System information function getSystemInfo() { const os = require('os'); return { platform: os.platform(), arch: os.arch(), nodeVersion: process.version, uptime: Math.floor(process.uptime()), memory: Math.round(process.memoryUsage().heapUsed / 1024 / 1024) }; } // Show system info (hidden feature) function showSystemInfo() { const info = getSystemInfo(); const sysInfo = `Platform: ${info.platform} Architecture: ${info.arch} Node.js Version: ${info.nodeVersion} Uptime: ${info.uptime}s Memory Usage: ${info.memory}MB Current Theme: ${currentTheme} GitHub Cache: ${githubStats ? 'Active' : 'Empty'}`; console.log(createBox(sysInfo, '🔧 System Information', 'info')); } // Enhanced menu with hidden features async function showEnhancedMenu() { await showHeader(); console.log(colorize('What would you like to know about Altaf?\n', 'primary')); console.log(colorize('1. 👨‍💻 About Me', 'text')); console.log(colorize('2. 🚀 Skills & Tech Stack', 'text')); console.log(colorize('3. 💼 My Projects', 'text')); console.log(colorize('4. 📞 Contact Information', 'text')); console.log(colorize('5. 🎨 Change Theme', 'text')); console.log(colorize('6. 🌐 Open Website', 'text')); console.log(colorize('7. 💼 Open GitHub', 'text')); console.log(colorize('8. 🔗 Open LinkedIn', 'text')); console.log(colorize('9. ❌ Exit', 'text')); console.log(colorize('\nHidden: matrix, sys, glitch', 'dim')); rl.question(colorize('\nEnter your choice: ', 'secondary'), (answer) => { handleEnhancedMenuChoice(answer.trim().toLowerCase()); }); } // Handle enhanced menu choices with easter eggs async function handleEnhancedMenuChoice(choice) { switch (choice) { case '1': await showAbout(); rl.question('', () => showEnhancedMenu()); break; case '2': await showSkills(); rl.question('', () => showEnhancedMenu()); break; case '3': await showProjects(); rl.question('', () => showEnhancedMenu()); break; case '4': await showContact(); rl.question('', () => showEnhancedMenu()); break; case '5': showThemeSelector(); break; case '6': openUrl(personalInfo.website); setTimeout(() => showEnhancedMenu(), 1000); break; case '7': openUrl(personalInfo.github); setTimeout(() => showEnhancedMenu(), 1000); break; case '8': openUrl(personalInfo.linkedin); setTimeout(() => showEnhancedMenu(), 1000); break; case '9': console.log(colorize('\n🙏 Thanks for checking out my portfolio!', 'secondary')); console.log(colorize('Have a great day! 👋\n', 'success')); rl.close(); process.exit(0); break; // Easter eggs case 'matrix': matrixRain(); break; case 'sys': case 'system': showSystemInfo(); rl.question(colorize('\nPress Enter to continue...', 'dim'), () => showEnhancedMenu()); break; case 'glitch': console.log(''); glitchText(personalInfo.name, 5); setTimeout(() => { console.log('\n'); showEnhancedMenu(); }, 2000); break; default: console.log(colorize('Invalid choice! Please try again.', 'error')); setTimeout(() => showEnhancedMenu(), 1000); } } // Update the main menu function to use enhanced menu async function showMenu() { await showEnhancedMenu(); } // Visitor counter (simple file-based) function updateVisitorCount() { const counterFile = path.join(__dirname, '.visitor_count'); let count = 0; try { if (fs.existsSync(counterFile)) { count = parseInt(fs.readFileSync(counterFile, 'utf8')) || 0; } count++; fs.writeFileSync(counterFile, count.toString()); return count; } catch (error) { return 1; } } // Welcome message with visitor count async function showWelcome() { const visitorCount = updateVisitorCount(); console.log(colorize(`Welcome! You are visitor #${visitorCount}`, 'info')); await sleep(1000); } // Start the application async function startApplication() { try { setupKeyboardInput(); await showWelcome(); await startupAnimation(); await handleArgs(); } catch (error) { console.log(colorize('Error starting application:', 'error')); console.log(colorize(error.message, 'error')); process.exit(1); } } // Handle process exit with style process.on('SIGINT', async () => { console.log(colorize('\n\n🙏 Thanks for checking out my portfolio!', 'secondary')); await typeWriter('Have a great day! 👋', 'success', 50); console.log('\n'); process.exit(0); }); // Handle uncaught exceptions process.on('uncaughtException', (error) => { console.log(colorize('\nAn error occurred:', 'error')); console.log(colorize(error.message, 'error')); console.log(colorize('\nPlease try again or report this issue.', 'warning')); process.exit(1); }); // Start the application startApplication();