Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>V-Sysop Extreme: BBS Manager</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| @keyframes terminal-blink { | |
| 0%, 100% { opacity: 1; } | |
| 50% { opacity: 0; } | |
| } | |
| @keyframes shake { | |
| 0% { transform: translateX(0); } | |
| 25% { transform: translateX(-5px); } | |
| 50% { transform: translateX(5px); } | |
| 75% { transform: translateX(-5px); } | |
| 100% { transform: translateX(0); } | |
| } | |
| .terminal { | |
| background-color: #0f172a; | |
| background-image: | |
| linear-gradient(rgba(30, 41, 59, 0.1) 1px, transparent 1px), | |
| linear-gradient(90deg, rgba(30, 41, 59, 0.1) 1px, transparent 1px); | |
| background-size: 20px 20px; | |
| font-family: 'Courier New', monospace; | |
| } | |
| .cursor { | |
| animation: terminal-blink 1s infinite; | |
| } | |
| .bbs-header { | |
| background: linear-gradient(90deg, #1e40af 0%, #7e22ce 100%); | |
| } | |
| .alert-shake { | |
| animation: shake 0.5s; | |
| } | |
| .user-active { | |
| box-shadow: 0 0 10px #10b981; | |
| } | |
| .user-idle { | |
| box-shadow: 0 0 10px #f59e0b; | |
| } | |
| .user-new { | |
| box-shadow: 0 0 10px #3b82f6; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-slate-900 text-slate-200 min-h-screen"> | |
| <div class="container mx-auto px-4 py-8"> | |
| <!-- Header with BBS Info --> | |
| <header class="mb-8 bbs-header rounded-lg p-4 text-white"> | |
| <div class="flex justify-between items-center"> | |
| <div> | |
| <h1 class="text-3xl font-bold">V-Sysop <span class="text-yellow-300">Extreme</span></h1> | |
| <div class="text-sm">Your BBS: <span class="font-mono">MEGABBS</span></div> | |
| </div> | |
| <div class="text-right"> | |
| <div class="text-xl">Nodes: <span id="node-count" class="font-bold">1</span>/4</div> | |
| <div class="text-sm">Uptime: <span id="bbs-uptime">0d 0h 0m</span></div> | |
| </div> | |
| </div> | |
| <div class="flex justify-between mt-4 text-xs"> | |
| <div>Sysop: <span class="font-mono">ADMIN</span></div> | |
| <div>Callers Today: <span id="caller-count">0</span></div> | |
| <div>Files: <span id="file-count">42</span></div> | |
| <div>Messages: <span id="message-count">128</span></div> | |
| </div> | |
| </header> | |
| <div class="grid grid-cols-1 lg:grid-cols-3 gap-6"> | |
| <!-- Main Terminal --> | |
| <div class="lg:col-span-2"> | |
| <div class="terminal rounded-lg border border-blue-500 p-4 h-full"> | |
| <div class="flex items-center mb-4"> | |
| <div class="w-3 h-3 rounded-full bg-red-500 mr-2"></div> | |
| <div class="w-3 h-3 rounded-full bg-yellow-500 mr-2"></div> | |
| <div class="w-3 h-3 rounded-full bg-green-500"></div> | |
| <div class="ml-auto text-sm text-slate-400">BBS MODE: ONLINE</div> | |
| </div> | |
| <div id="terminal-output" class="h-96 overflow-y-auto mb-4 font-mono space-y-2"> | |
| <p class="text-green-400">> Welcome to V-Sysop Extreme BBS Manager v2.0</p> | |
| <p class="text-green-400">> BBS system initialized...</p> | |
| <p class="text-green-400">> Loading node configuration...</p> | |
| <p class="text-green-400">> Ready for commands.</p> | |
| <p class="text-green-400">> Type 'help' for available commands</p> | |
| </div> | |
| <div class="flex items-center border-t border-slate-700 pt-2"> | |
| <span class="text-green-400 mr-2">></span> | |
| <input id="command-input" type="text" class="flex-grow bg-transparent border-none outline-none font-mono" placeholder="Enter command..." autofocus> | |
| <span class="cursor ml-1">█</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- BBS Dashboard --> | |
| <div class="space-y-6"> | |
| <!-- Active Users --> | |
| <div class="bg-slate-800 rounded-lg border border-slate-700 p-4"> | |
| <h2 class="text-xl font-bold mb-3 text-blue-400 flex items-center"> | |
| <i class="fas fa-users mr-2"></i> Active Callers | |
| </h2> | |
| <div id="active-users" class="space-y-2"> | |
| <div class="text-center py-4 text-slate-500"> | |
| <i class="fas fa-user-slash text-2xl mb-2"></i> | |
| <p>No active callers</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- BBS Statistics --> | |
| <div class="bg-slate-800 rounded-lg border border-slate-700 p-4"> | |
| <h2 class="text-xl font-bold mb-3 text-blue-400 flex items-center"> | |
| <i class="fas fa-chart-bar mr-2"></i> BBS Stats | |
| </h2> | |
| <div class="grid grid-cols-2 gap-4"> | |
| <div class="bg-slate-700 rounded p-2 text-center"> | |
| <div class="text-2xl font-bold" id="daily-calls">0</div> | |
| <div class="text-xs">Calls Today</div> | |
| </div> | |
| <div class="bg-slate-700 rounded p-2 text-center"> | |
| <div class="text-2xl font-bold" id="new-users">0</div> | |
| <div class="text-xs">New Users</div> | |
| </div> | |
| <div class="bg-slate-700 rounded p-2 text-center"> | |
| <div class="text-2xl font-bold" id="uploads">0</div> | |
| <div class="text-xs">Uploads</div> | |
| </div> | |
| <div class="bg-slate-700 rounded p-2 text-center"> | |
| <div class="text-2xl font-bold" id="downloads">0</div> | |
| <div class="text-xs">Downloads</div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Quick Commands --> | |
| <div class="bg-slate-800 rounded-lg border border-slate-700 p-4"> | |
| <h2 class="text-xl font-bold mb-3 text-blue-400 flex items-center"> | |
| <i class="fas fa-bolt mr-2"></i> Quick Commands | |
| </h2> | |
| <div class="grid grid-cols-2 gap-2"> | |
| <button class="quick-command-btn bg-blue-600 hover:bg-blue-500 text-sm py-1 px-2 rounded" data-command="users"> | |
| <i class="fas fa-users mr-1"></i> Users | |
| </button> | |
| <button class="quick-command-btn bg-purple-600 hover:bg-purple-500 text-sm py-1 px-2 rounded" data-command="files"> | |
| <i class="fas fa-file-archive mr-1"></i> Files | |
| </button> | |
| <button class="quick-command-btn bg-green-600 hover:bg-green-500 text-sm py-1 px-2 rounded" data-command="messages"> | |
| <i class="fas fa-comments mr-1"></i> Messages | |
| </button> | |
| <button class="quick-command-btn bg-yellow-600 hover:bg-yellow-500 text-sm py-1 px-2 rounded" data-command="config"> | |
| <i class="fas fa-cog mr-1"></i> Config | |
| </button> | |
| <button class="quick-command-btn bg-red-600 hover:bg-red-500 text-sm py-1 px-2 rounded" data-command="restart"> | |
| <i class="fas fa-sync-alt mr-1"></i> Restart | |
| </button> | |
| <button class="quick-command-btn bg-pink-600 hover:bg-pink-500 text-sm py-1 px-2 rounded" data-command="sysop"> | |
| <i class="fas fa-user-secret mr-1"></i> Sysop | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Alerts Section --> | |
| <div id="alerts-container" class="fixed bottom-4 right-4 space-y-2 w-80"></div> | |
| </div> | |
| <script> | |
| // BBS State | |
| const bbsState = { | |
| nodes: 1, | |
| maxNodes: 4, | |
| uptime: 0, // in minutes | |
| callersToday: 0, | |
| newUsersToday: 0, | |
| uploadsToday: 0, | |
| downloadsToday: 0, | |
| files: 42, | |
| messages: 128, | |
| activeUsers: [], | |
| achievements: [], | |
| commandsExecuted: 0, | |
| restarts: 0, | |
| filesUploaded: 0, | |
| messagesPosted: 0, | |
| usersBanned: 0, | |
| nodesAdded: 0 | |
| }; | |
| // Available Commands | |
| const commands = { | |
| 'help': { | |
| description: 'Show available commands', | |
| execute: () => { | |
| addTerminalOutput(` | |
| Available commands: | |
| <span class="text-yellow-400">help</span> - Show this help message | |
| <span class="text-yellow-400">users</span> - List all users | |
| <span class="text-yellow-400">callers</span> - Show active callers | |
| <span class="text-yellow-400">files</span> - Manage file areas | |
| <span class="text-yellow-400">messages</span> - Manage message areas | |
| <span class="text-yellow-400">config</span> - Configure BBS settings | |
| <span class="text-yellow-400">restart</span> - Restart BBS system | |
| <span class="text-yellow-400">sysop</span> - Sysop utilities | |
| <span class="text-yellow-400">stats</span> - Show BBS statistics | |
| `); | |
| } | |
| }, | |
| 'users': { | |
| description: 'List all users', | |
| execute: () => { | |
| addTerminalOutput('<span class="text-blue-400">> Loading user database...</span>'); | |
| setTimeout(() => { | |
| addTerminalOutput(` | |
| User List: | |
| <span class="text-green-400">ADMIN</span> - Sysop (Last call: Today) | |
| <span class="text-blue-400">JOHNDOE</span> - User (Last call: Yesterday) | |
| <span class="text-blue-400">JANEDOE</span> - User (Last call: 3 days ago) | |
| <span class="text-blue-400">HACKER</span> - User (Last call: 1 week ago) | |
| <span class="text-blue-400">NEWBIE</span> - New User (Last call: Today) | |
| `); | |
| addTerminalOutput('<span class="text-yellow-400">> Total users: 5</span>'); | |
| }, 1000); | |
| } | |
| }, | |
| 'callers': { | |
| description: 'Show active callers', | |
| execute: () => { | |
| if (bbsState.activeUsers.length === 0) { | |
| addTerminalOutput('<span class="text-yellow-400">> No active callers</span>'); | |
| } else { | |
| addTerminalOutput('<span class="text-blue-400">> Active callers:</span>'); | |
| bbsState.activeUsers.forEach(user => { | |
| addTerminalOutput(`<span class="text-green-400">> ${user.name}</span> - ${user.status} (Node ${user.node})`); | |
| }); | |
| } | |
| } | |
| }, | |
| 'files': { | |
| description: 'Manage file areas', | |
| execute: (args) => { | |
| if (args.length === 0) { | |
| addTerminalOutput(` | |
| File Area Management: | |
| <span class="text-yellow-400">files list</span> - List file areas | |
| <span class="text-yellow-400">files add [name]</span> - Add new file area | |
| <span class="text-yellow-400">files del [name]</span> - Delete file area | |
| <span class="text-yellow-400">files stats</span> - Show file statistics | |
| `); | |
| } else if (args[0] === 'list') { | |
| addTerminalOutput(` | |
| File Areas: | |
| 1. Public Files (${Math.floor(bbsState.files * 0.7)} files) | |
| 2. Games (${Math.floor(bbsState.files * 0.2)} files) | |
| 3. Utilities (${Math.floor(bbsState.files * 0.1)} files) | |
| `); | |
| } else if (args[0] === 'stats') { | |
| addTerminalOutput(` | |
| File Statistics: | |
| Total files: ${bbsState.files} | |
| Uploads today: ${bbsState.uploadsToday} | |
| Downloads today: ${bbsState.downloadsToday} | |
| `); | |
| } else if (args[0] === 'add' && args[1]) { | |
| addTerminalOutput(`<span class="text-blue-400">> Creating new file area: ${args[1]}</span>`); | |
| setTimeout(() => { | |
| addTerminalOutput(`<span class="text-green-400">> File area "${args[1]}" created successfully</span>`); | |
| }, 1500); | |
| } else if (args[0] === 'del' && args[1]) { | |
| addTerminalOutput(`<span class="text-blue-400">> Deleting file area: ${args[1]}</span>`); | |
| setTimeout(() => { | |
| addTerminalOutput(`<span class="text-green-400">> File area "${args[1]}" deleted successfully</span>`); | |
| }, 1500); | |
| } else { | |
| addTerminalOutput('<span class="text-red-400">> Error: Invalid files command</span>'); | |
| } | |
| } | |
| }, | |
| 'messages': { | |
| description: 'Manage message areas', | |
| execute: (args) => { | |
| if (args.length === 0) { | |
| addTerminalOutput(` | |
| Message Area Management: | |
| <span class="text-yellow-400">messages list</span> - List message areas | |
| <span class="text-yellow-400">messages read [area]</span> - Read messages | |
| <span class="text-yellow-400">messages post [area]</span> - Post new message | |
| <span class="text-yellow-400">messages stats</span> - Show message statistics | |
| `); | |
| } else if (args[0] === 'list') { | |
| addTerminalOutput(` | |
| Message Areas: | |
| 1. General Discussion (${Math.floor(bbsState.messages * 0.5)} messages) | |
| 2. Tech Talk (${Math.floor(bbsState.messages * 0.3)} messages) | |
| 3. Announcements (${Math.floor(bbsState.messages * 0.2)} messages) | |
| `); | |
| } else if (args[0] === 'stats') { | |
| addTerminalOutput(` | |
| Message Statistics: | |
| Total messages: ${bbsState.messages} | |
| New today: ${Math.floor(bbsState.messages * 0.1)} | |
| `); | |
| } else if (args[0] === 'read' && args[1]) { | |
| addTerminalOutput(`<span class="text-blue-400">> Loading messages from area: ${args[1]}</span>`); | |
| setTimeout(() => { | |
| addTerminalOutput(` | |
| Recent Messages: | |
| 1. ADMIN - Welcome to the BBS! (Today) | |
| 2. JOHNDOE - Testing the system (Today) | |
| 3. JANEDOE - Hello everyone! (Yesterday) | |
| `); | |
| }, 1500); | |
| } else if (args[0] === 'post' && args[1]) { | |
| addTerminalOutput(`<span class="text-blue-400">> Posting to area: ${args[1]}</span>`); | |
| setTimeout(() => { | |
| addTerminalOutput('<span class="text-green-400">> Message posted successfully</span>'); | |
| bbsState.messages++; | |
| bbsState.messagesPosted++; | |
| updateStats(); | |
| checkAchievements(); | |
| }, 1500); | |
| } else { | |
| addTerminalOutput('<span class="text-red-400">> Error: Invalid messages command</span>'); | |
| } | |
| } | |
| }, | |
| 'config': { | |
| description: 'Configure BBS settings', | |
| execute: (args) => { | |
| if (args.length === 0) { | |
| addTerminalOutput(` | |
| Configuration: | |
| <span class="text-yellow-400">config show</span> - Show current configuration | |
| <span class="text-yellow-400">config nodes [number]</span> - Set number of nodes | |
| <span class="text-yellow-400">config name [name]</span> - Change BBS name | |
| `); | |
| } else if (args[0] === 'show') { | |
| addTerminalOutput(` | |
| Current Configuration: | |
| BBS Name: MEGABBS | |
| Nodes: ${bbsState.nodes}/${bbsState.maxNodes} | |
| File Areas: 3 | |
| Message Areas: 3 | |
| `); | |
| } else if (args[0] === 'nodes' && args[1]) { | |
| const nodes = parseInt(args[1]); | |
| if (nodes > 0 && nodes <= bbsState.maxNodes) { | |
| addTerminalOutput(`<span class="text-blue-400">> Setting nodes to ${nodes}</span>`); | |
| setTimeout(() => { | |
| if (nodes > bbsState.nodes) { | |
| bbsState.nodesAdded += (nodes - bbsState.nodes); | |
| checkAchievements(); | |
| } | |
| bbsState.nodes = nodes; | |
| updateStats(); | |
| addTerminalOutput(`<span class="text-green-400">> Nodes set to ${nodes}</span>`); | |
| }, 1500); | |
| } else { | |
| addTerminalOutput(`<span class="text-red-400">> Error: Nodes must be between 1 and ${bbsState.maxNodes}</span>`); | |
| } | |
| } else if (args[0] === 'name' && args[1]) { | |
| addTerminalOutput(`<span class="text-blue-400">> Changing BBS name to ${args[1]}</span>`); | |
| setTimeout(() => { | |
| addTerminalOutput(`<span class="text-green-400">> BBS name changed to ${args[1]}</span>`); | |
| document.querySelector('header h1').innerHTML = `V-Sysop <span class="text-yellow-300">Extreme</span>`; | |
| document.querySelector('header .text-sm span').textContent = args[1]; | |
| }, 1500); | |
| } else { | |
| addTerminalOutput('<span class="text-red-400">> Error: Invalid config command</span>'); | |
| } | |
| } | |
| }, | |
| 'restart': { | |
| description: 'Restart BBS system', | |
| execute: () => { | |
| addTerminalOutput('<span class="text-red-400">> WARNING: This will disconnect all users</span>'); | |
| addTerminalOutput('<span class="text-yellow-400">> Type "restart confirm" to proceed</span>'); | |
| if (args && args[0] === 'confirm') { | |
| addTerminalOutput('<span class="text-blue-400">> Restarting BBS system...</span>'); | |
| setTimeout(() => { | |
| // Disconnect all users | |
| bbsState.activeUsers = []; | |
| updateActiveUsers(); | |
| // Increment uptime by 1 minute (simulating quick restart) | |
| bbsState.uptime += 1; | |
| updateStats(); | |
| bbsState.restarts++; | |
| checkAchievements(); | |
| addTerminalOutput('<span class="text-green-400">> BBS restarted successfully</span>'); | |
| createAlert('System Restart', 'BBS has been restarted', 'yellow'); | |
| }, 2000); | |
| } | |
| } | |
| }, | |
| 'sysop': { | |
| description: 'Sysop utilities', | |
| execute: (args) => { | |
| if (args.length === 0) { | |
| addTerminalOutput(` | |
| Sysop Utilities: | |
| <span class="text-yellow-400">sysop ban [user]</span> - Ban a user | |
| <span class="text-yellow-400">sysop promote [user]</span> - Promote user to co-sysop | |
| <span class="text-yellow-400">sysop extreme</span> - Enable extreme mode | |
| `); | |
| } else if (args[0] === 'ban' && args[1]) { | |
| addTerminalOutput(`<span class="text-red-400">> Banning user: ${args[1]}</span>`); | |
| setTimeout(() => { | |
| addTerminalOutput(`<span class="text-green-400">> User ${args[1]} banned successfully</span>`); | |
| bbsState.usersBanned++; | |
| checkAchievements(); | |
| createAlert('User Banned', `${args[1]} has been banned`, 'red'); | |
| }, 1500); | |
| } else if (args[0] === 'promote' && args[1]) { | |
| addTerminalOutput(`<span class="text-blue-400">> Promoting user: ${args[1]}</span>`); | |
| setTimeout(() => { | |
| addTerminalOutput(`<span class="text-green-400">> User ${args[1]} promoted to co-sysop</span>`); | |
| createAlert('Promotion', `${args[1]} is now a co-sysop`, 'green'); | |
| }, 1500); | |
| } else if (args[0] === 'extreme') { | |
| addTerminalOutput('<span class="text-purple-400">> ACTIVATING EXTREME MODE</span>'); | |
| setTimeout(() => { | |
| document.body.classList.add('bg-gradient-to-br', 'from-slate-900', 'to-purple-900'); | |
| addTerminalOutput('<span class="text-purple-400">> EXTREME MODE ENGAGED</span>'); | |
| addTerminalOutput('<span class="text-purple-400">> ALL NODES AT 200% CAPACITY</span>'); | |
| createAlert('Extreme Mode', 'All nodes operating at maximum capacity!', 'purple'); | |
| }, 1000); | |
| } else { | |
| addTerminalOutput('<span class="text-red-400">> Error: Invalid sysop command</span>'); | |
| } | |
| } | |
| }, | |
| 'stats': { | |
| description: 'Show BBS statistics', | |
| execute: () => { | |
| addTerminalOutput(` | |
| BBS Statistics: | |
| Uptime: ${Math.floor(bbsState.uptime / 1440)}d ${Math.floor((bbsState.uptime % 1440) / 60)}h ${bbsState.uptime % 60}m | |
| Callers Today: ${bbsState.callersToday} | |
| New Users Today: ${bbsState.newUsersToday} | |
| Files: ${bbsState.files} | |
| Messages: ${bbsState.messages} | |
| Active Nodes: ${bbsState.nodes}/${bbsState.maxNodes} | |
| `); | |
| } | |
| } | |
| }; | |
| // Achievements | |
| const achievements = [ | |
| { | |
| id: 'first_command', | |
| name: 'First Command', | |
| description: 'Execute your first command', | |
| icon: 'fa-terminal', | |
| color: 'bg-blue-500', | |
| check: () => bbsState.commandsExecuted >= 1 | |
| }, | |
| { | |
| id: 'power_user', | |
| name: 'Power User', | |
| description: 'Execute 10 commands', | |
| icon: 'fa-keyboard', | |
| color: 'bg-green-500', | |
| check: () => bbsState.commandsExecuted >= 10 | |
| }, | |
| { | |
| id: 'sysop_tools', | |
| name: 'Sysop Tools', | |
| description: 'Use all sysop commands', | |
| icon: 'fa-user-secret', | |
| color: 'bg-purple-500', | |
| check: () => bbsState.usersBanned >= 1 && bbsState.restarts >= 1 | |
| }, | |
| { | |
| id: 'file_master', | |
| name: 'File Master', | |
| description: 'Upload 5 files', | |
| icon: 'fa-file-upload', | |
| color: 'bg-yellow-500', | |
| check: () => bbsState.filesUploaded >= 5 | |
| }, | |
| { | |
| id: 'message_king', | |
| name: 'Message King', | |
| description: 'Post 10 messages', | |
| icon: 'fa-comment-alt', | |
| color: 'bg-pink-500', | |
| check: () => bbsState.messagesPosted >= 10 | |
| }, | |
| { | |
| id: 'node_expander', | |
| name: 'Node Expander', | |
| description: 'Add a node', | |
| icon: 'fa-server', | |
| color: 'bg-red-500', | |
| check: () => bbsState.nodesAdded >= 1 | |
| }, | |
| { | |
| id: 'bbs_legend', | |
| name: 'BBS Legend', | |
| description: 'Reach 24 hours uptime', | |
| icon: 'fa-trophy', | |
| color: 'bg-indigo-500', | |
| check: () => bbsState.uptime >= 1440 | |
| } | |
| ]; | |
| // DOM Elements | |
| const terminalOutput = document.getElementById('terminal-output'); | |
| const commandInput = document.getElementById('command-input'); | |
| const activeUsersContainer = document.getElementById('active-users'); | |
| const alertsContainer = document.getElementById('alerts-container'); | |
| const quickCommandBtns = document.querySelectorAll('.quick-command-btn'); | |
| // Initialize the BBS | |
| function init() { | |
| // Set up event listeners | |
| commandInput.addEventListener('keypress', (e) => { | |
| if (e.key === 'Enter') executeCommand(); | |
| }); | |
| quickCommandBtns.forEach(btn => { | |
| btn.addEventListener('click', function() { | |
| commandInput.value = this.getAttribute('data-command'); | |
| commandInput.focus(); | |
| }); | |
| }); | |
| // Start uptime counter | |
| setInterval(() => { | |
| bbsState.uptime++; | |
| updateStats(); | |
| // Check for achievements | |
| checkAchievements(); | |
| // Random user activity | |
| if (Math.random() < 0.1) simulateUserActivity(); | |
| }, 60000); // 1 minute = 1 minute uptime | |
| // Initial stats update | |
| updateStats(); | |
| // Simulate initial user activity | |
| setTimeout(simulateUserActivity, 3000); | |
| } | |
| // Execute a command | |
| function executeCommand() { | |
| const input = commandInput.value.trim(); | |
| if (!input) return; | |
| // Add command to terminal | |
| addTerminalOutput(`<span class="text-blue-400">> ${input}</span>`); | |
| // Parse command | |
| const parts = input.split(' '); | |
| const cmd = parts[0].toLowerCase(); | |
| const args = parts.slice(1); | |
| // Execute command if found | |
| if (commands[cmd]) { | |
| commands[cmd].execute(args); | |
| bbsState.commandsExecuted++; | |
| checkAchievements(); | |
| } else { | |
| addTerminalOutput(`<span class="text-red-400">> Error: Unknown command '${cmd}'</span>`); | |
| } | |
| // Clear input | |
| commandInput.value = ''; | |
| } | |
| // Add output to terminal | |
| function addTerminalOutput(text) { | |
| const line = document.createElement('p'); | |
| line.innerHTML = text; | |
| terminalOutput.appendChild(line); | |
| terminalOutput.scrollTop = terminalOutput.scrollHeight; | |
| } | |
| // Update stats display | |
| function updateStats() { | |
| // Update header stats | |
| document.getElementById('node-count').textContent = `${bbsState.nodes}/${bbsState.maxNodes}`; | |
| const days = Math.floor(bbsState.uptime / 1440); | |
| const hours = Math.floor((bbsState.uptime % 1440) / 60); | |
| const minutes = bbsState.uptime % 60; | |
| document.getElementById('bbs-uptime').textContent = `${days}d ${hours}h ${minutes}m`; | |
| document.getElementById('caller-count').textContent = bbsState.callersToday; | |
| document.getElementById('file-count').textContent = bbsState.files; | |
| document.getElementById('message-count').textContent = bbsState.messages; | |
| // Update dashboard stats | |
| document.getElementById('daily-calls').textContent = bbsState.callersToday; | |
| document.getElementById('new-users').textContent = bbsState.newUsersToday; | |
| document.getElementById('uploads').textContent = bbsState.uploadsToday; | |
| document.getElementById('downloads').textContent = bbsState.downloadsToday; | |
| } | |
| // Update active users display | |
| function updateActiveUsers() { | |
| activeUsersContainer.innerHTML = ''; | |
| if (bbsState.activeUsers.length === 0) { | |
| activeUsersContainer.innerHTML = ` | |
| <div class="text-center py-4 text-slate-500"> | |
| <i class="fas fa-user-slash text-2xl mb-2"></i> | |
| <p>No active callers</p> | |
| </div> | |
| `; | |
| } else { | |
| bbsState.activeUsers.forEach(user => { | |
| const userEl = document.createElement('div'); | |
| userEl.className = `flex items-center p-2 rounded ${user.status === 'Active' ? 'user-active' : user.status === 'New' ? 'user-new' : 'user-idle'}`; | |
| userEl.innerHTML = ` | |
| <div class="w-10 h-10 rounded-full bg-slate-700 flex items-center justify-center mr-3"> | |
| <i class="fas fa-user"></i> | |
| </div> | |
| <div> | |
| <div class="font-bold">${user.name}</div> | |
| <div class="text-xs">${user.status} • Node ${user.node}</div> | |
| </div> | |
| <div class="ml-auto text-xs text-slate-400"> | |
| ${user.time} min | |
| </div> | |
| `; | |
| activeUsersContainer.appendChild(userEl); | |
| }); | |
| } | |
| } | |
| // Simulate user activity | |
| function simulateUserActivity() { | |
| // Random chance of user connecting/disconnecting | |
| if (bbsState.activeUsers.length === 0 || Math.random() < 0.3) { | |
| // New user connects | |
| if (bbsState.activeUsers.length < bbsState.nodes) { | |
| const userTypes = [ | |
| { name: 'JOHNDOE', status: 'Active' }, | |
| { name: 'JANEDOE', status: 'Idle' }, | |
| { name: 'NEWBIE', status: 'New' }, | |
| { name: 'HACKER', status: 'Active' } | |
| ]; | |
| const user = userTypes[Math.floor(Math.random() * userTypes.length)]; | |
| user.node = bbsState.activeUsers.length + 1; | |
| user.time = Math.floor(Math.random() * 30) + 1; | |
| bbsState.activeUsers.push(user); | |
| bbsState.callersToday++; | |
| if (user.status === 'New') { | |
| bbsState.newUsersToday++; | |
| } | |
| updateStats(); | |
| updateActiveUsers(); | |
| if (user.status === 'New') { | |
| createAlert('New User', `${user.name} has joined the BBS!`, 'blue'); | |
| } | |
| } | |
| } else if (Math.random() < 0.2) { | |
| // User disconnects | |
| const index = Math.floor(Math.random() * bbsState.activeUsers.length); | |
| const user = bbsState.activeUsers[index]; | |
| bbsState.activeUsers.splice(index, 1); | |
| // Random file upload/download | |
| if (Math.random() < 0.5) { | |
| bbsState.uploadsToday++; | |
| bbsState.files++; | |
| bbsState.filesUploaded++; | |
| } else { | |
| bbsState.downloadsToday++; | |
| } | |
| updateStats(); | |
| updateActiveUsers(); | |
| checkAchievements(); | |
| } else { | |
| // Update time for active users | |
| bbsState.activeUsers.forEach(user => { | |
| user.time += Math.floor(Math.random() * 5) + 1; | |
| // Random chance to post message | |
| if (Math.random() < 0.1) { | |
| bbsState.messages++; | |
| bbsState.messagesPosted++; | |
| } | |
| }); | |
| updateActiveUsers(); | |
| checkAchievements(); | |
| } | |
| } | |
| // Check for achievements | |
| function checkAchievements() { | |
| achievements.forEach(achievement => { | |
| if (!bbsState.achievements.includes(achievement.id) && achievement.check()) { | |
| // Unlock achievement | |
| bbsState.achievements.push(achievement.id); | |
| createAlert('Achievement Unlocked!', achievement.name, 'purple'); | |
| } | |
| }); | |
| } | |
| // Create an alert | |
| function createAlert(title, message, color) { | |
| const alertEl = document.createElement('div'); | |
| alertEl.className = `alert-shake bg-slate-800 border-l-4 border-${color}-500 p-3 rounded shadow-lg`; | |
| alertEl.innerHTML = ` | |
| <div class="flex items-start"> | |
| <div class="flex-shrink-0"> | |
| <i class="fas ${getAlertIcon(color)} text-${color}-500"></i> | |
| </div> | |
| <div class="ml-3"> | |
| <h3 class="text-sm font-medium text-white">${title}</h3> | |
| <div class="mt-1 text-sm text-slate-300">${message}</div> | |
| <div class="mt-2"> | |
| <button class="close-alert-btn text-xs bg-slate-700 hover:bg-slate-600 px-2 py-1 rounded"> | |
| Dismiss | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| alertsContainer.appendChild(alertEl); | |
| // Auto-remove after 5 seconds | |
| const timeout = setTimeout(() => { | |
| alertEl.remove(); | |
| }, 5000); | |
| // Add close button event | |
| const closeBtn = alertEl.querySelector('.close-alert-btn'); | |
| closeBtn.addEventListener('click', () => { | |
| clearTimeout(timeout); | |
| alertEl.remove(); | |
| }); | |
| } | |
| // Get icon for alert type | |
| function getAlertIcon(color) { | |
| switch(color) { | |
| case 'red': return 'fa-exclamation-circle'; | |
| case 'green': return 'fa-check-circle'; | |
| case 'yellow': return 'fa-exclamation-triangle'; | |
| case 'blue': return 'fa-info-circle'; | |
| case 'purple': return 'fa-trophy'; | |
| default: return 'fa-bell'; | |
| } | |
| } | |
| // Initialize the BBS | |
| window.addEventListener('DOMContentLoaded', init); | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=DevXen/xenthra-inc" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |