/** * ConsoleView — Linux Terminal Simulation for OTRS Turbo * Shortcut: Ctrl + Alt + T */ const ConsoleView = { isOpen: false, history: [], historyIndex: -1, currentTheme: 'dark', // dark, green, amber, cyber activeAnimation: null, toggle() { if (this.isOpen) { this.close(); } else { this.open(); } }, open() { let modal = document.getElementById('linux-console-modal'); if (!modal) { this.createModal(); modal = document.getElementById('linux-console-modal'); } modal.style.display = 'flex'; this.isOpen = true; const input = document.getElementById('console-input'); if (input) { input.focus(); } }, close() { const modal = document.getElementById('linux-console-modal'); if (modal) { modal.style.display = 'none'; } this.stopAnimation(); this.isOpen = false; }, createModal() { const overlay = document.createElement('div'); overlay.id = 'linux-console-modal'; overlay.className = 'console-modal-overlay theme-dark'; overlay.innerHTML = `
otrs-turbo@linux-server:~
BASH v5.2.15
  ____ _____ ____  ____    _____ _   _ ____  ____   ___  
 / ___|_   _|  _ \\/ ___|  |_   _| | | |  _ \\/ __ ) / _ \\ 
| |     | | | |_) \\___ \\    | | | | | | |_) |  _ \\| | | |
| |___  | | |  _ < ___) |   | | | |_| |  _ <| |_) | |_| |
 \\____| |_| |_| \\_\\____/    |_|  \\___/|_| \\_\\____/ \\___/ 
            
Benvenuto nella console di simulazione Linux per OTRS Turbo.
Digita help per vedere l'elenco dei comandi disponibili.
agent@otrs-turbo:~$
`; document.body.appendChild(overlay); // Event Bindings overlay.querySelector('#console-btn-close').addEventListener('click', () => this.close()); overlay.addEventListener('click', (e) => { if (e.target === overlay) this.close(); else { const input = document.getElementById('console-input'); if (input && document.activeElement !== input) input.focus(); } }); const input = overlay.querySelector('#console-input'); input.addEventListener('keydown', (e) => this.handleKeyDown(e)); }, stopAnimation() { if (this.activeAnimation) { clearInterval(this.activeAnimation); this.activeAnimation = null; } }, handleKeyDown(e) { if (e.key === 'Escape') { e.preventDefault(); this.close(); return; } if (e.key === 'Enter') { const input = e.target; const cmdText = input.value.trim(); input.value = ''; if (cmdText) { this.history.push(cmdText); this.historyIndex = this.history.length; this.executeCommand(cmdText); } else { this.printPrompt(''); } return; } if (e.key === 'ArrowUp') { e.preventDefault(); if (this.history.length > 0 && this.historyIndex > 0) { this.historyIndex--; e.target.value = this.history[this.historyIndex]; } return; } if (e.key === 'ArrowDown') { e.preventDefault(); if (this.historyIndex < this.history.length - 1) { this.historyIndex++; e.target.value = this.history[this.historyIndex]; } else { this.historyIndex = this.history.length; e.target.value = ''; } return; } if (e.key === 'Tab') { e.preventDefault(); this.autocomplete(e.target); return; } if (e.ctrlKey && e.key.toLowerCase() === 'c') { if (this.activeAnimation) { e.preventDefault(); this.stopAnimation(); this.printOutput('^C Animation interrupted'); this.showInputRow(); } } }, autocomplete(inputEl) { const val = inputEl.value.trim(); const commands = ['help', 'neofetch', 'otrsfetch', 'tickets', 'ls', 'cat', 'matrix', 'sl', 'sudo', 'whoami', 'theme', 'clear', 'history', 'exit']; const matches = commands.filter(c => c.startsWith(val)); if (matches.length === 1) { inputEl.value = matches[0] + ' '; } else if (matches.length > 1) { this.printOutput(`${matches.join(' ')}`); } }, printPrompt(cmdText) { const outputDiv = document.getElementById('console-output'); const line = document.createElement('div'); line.className = 'console-line'; line.innerHTML = `agent@otrs-turbo:~$ ${App.escapeHtml(cmdText)}`; outputDiv.appendChild(line); this.scrollToBottom(); }, printOutput(htmlContent) { const outputDiv = document.getElementById('console-output'); const line = document.createElement('div'); line.className = 'console-output-line'; line.innerHTML = htmlContent; outputDiv.appendChild(line); this.scrollToBottom(); }, scrollToBottom() { const body = document.getElementById('console-body'); if (body) { body.scrollTop = body.scrollHeight; } }, showInputRow() { const row = document.getElementById('console-input-row'); if (row) row.style.display = 'flex'; const input = document.getElementById('console-input'); if (input) input.focus(); }, hideInputRow() { const row = document.getElementById('console-input-row'); if (row) row.style.display = 'none'; }, async executeCommand(rawCmd) { this.stopAnimation(); this.printPrompt(rawCmd); const parts = rawCmd.trim().split(/\s+/); const mainCmd = parts[0].toLowerCase(); const args = parts.slice(1); switch (mainCmd) { case 'help': this.cmdHelp(); break; case 'clear': document.getElementById('console-output').innerHTML = ''; break; case 'whoami': const agent = App.activeAgent || 'gabriele.cimaschi'; this.printOutput(`${App.escapeHtml(agent)} (OTRS Turbo Operator)`); break; case 'sudo': this.printOutput(`agent is not in the sudoers file. This incident will be reported to OTRS Admins.`); break; case 'ls': this.cmdLs(); break; case 'cat': this.cmdCat(args[0]); break; case 'history': this.cmdHistory(); break; case 'neofetch': case 'otrsfetch': await this.cmdNeofetch(); break; case 'tickets': await this.cmdTickets(); break; case 'theme': this.cmdTheme(args[0]); break; case 'matrix': this.cmdMatrix(); break; case 'sl': this.cmdSl(); break; case 'exit': this.close(); break; default: this.printOutput(`bash: ${App.escapeHtml(mainCmd)}: command not found. Digita help per la lista dei comandi.`); break; } }, cmdHelp() { const helpHtml = `
helpMostra questo messaggio di aiuto
neofetch / otrsfetchVisualizza informazioni ed ASCII art di OTRS Turbo
ticketsElenca i ticket recenti ed i conteggi direttamente dal DB
lsElenca i file della directory corrente
cat <file>Legge il contenuto di un file virtuale
whoamiMostra l'agente attualmente autenticato
theme <dark|green|amber|cyber>Cambia il tema cromatico del terminale
matrixAvvia l'animazione della pioggia digitale Matrix (Ctrl+C per uscire)
slFai passare la locomotiva a vapore ASCII nel terminale
sudo <comando>Esegue un comando con privilegi di amministratore
historyMostra lo storico dei comandi usati
clearPulisce lo schermo della console
exitChiude la finestra del terminale
`; this.printOutput(helpHtml); }, cmdLs() { this.printOutput(` drwxr-xr-x 2 agent otrs 4096 Sep 16 15:00 . drwxr-xr-x 10 agent otrs 4096 Sep 16 15:00 .. -rw-r--r-- 1 agent otrs 2450 Sep 16 15:00 tickets.db -rw-r--r-- 1 agent otrs 777 Sep 16 15:00 motivational.txt -rw-r--r-- 1 agent otrs 1180 Sep 16 15:00 demotivational.txt -rw-r--r-- 1 agent otrs 512 Sep 16 15:00 secret.key -rwxr-xr-x 1 agent otrs 8192 Sep 16 15:00 system.log `); }, cmdCat(fileName) { if (!fileName) { this.printOutput('cat: specifica un nome file. Es: cat motivational.txt'); return; } const name = fileName.toLowerCase(); if (name === 'motivational.txt') { const phrases = App.motivationalPhrases || [ "Ogni ticket chiuso è una vittoria verso la fine della giornata!", "La velocità è la nostra virtù con OTRS Turbo!", "Mantieni la calma ed applica le macro." ]; const random = phrases[Math.floor(Math.random() * phrases.length)]; this.printOutput(`💡 ${App.escapeHtml(random)}`); } else if (name === 'demotivational.txt') { const phrases = App.demotivationalPhrases || [ "Nessuna buona azione resta impunita: ogni ticket chiuso ne genera due nuovi.", "Il weekend si avvicina, ma la coda di ticket non dorme mai.", "Hai davvero controllato se il cavo di rete è collegato?" ]; const random = phrases[Math.floor(Math.random() * phrases.length)]; this.printOutput(`💀 ${App.escapeHtml(random)}`); } else if (name === 'secret.key') { this.printOutput('🔒 Access Denied: 0x8840192A (Encryption key locked by OTRS Turbo core)'); } else if (name === 'tickets.db') { this.printOutput('SQLite/PG Binary format header. Usare il comando "tickets" per consultare i dati.'); } else if (name === 'system.log') { this.printOutput('[INFO] 2026-09-16 15:10:00 - OTRS Turbo Engine v1.0 running cleanly.\n[INFO] LDAP auto-sync skipped (within 24h window).\n[OK] Database query latency < 4ms.'); } else { this.printOutput(`cat: ${App.escapeHtml(fileName)}: No such file or directory`); } }, cmdHistory() { if (this.history.length === 0) { this.printOutput('Nessun comando nello storico.'); return; } const lines = this.history.map((c, i) => ` ${i + 1} ${App.escapeHtml(c)}`).join('\n'); this.printOutput(`
${lines}
`); }, async cmdNeofetch() { let ticketStats = { total: 0, open: 0 }; try { const data = await App.api('/api/tickets/stats'); if (data) { ticketStats.total = data.total_tickets || data.total || 0; ticketStats.open = data.open_tickets || data.open || 0; } } catch (e) {} const agent = App.activeAgent || 'gabriele.cimaschi'; const html = `
${App.escapeHtml(agent)}@otrs-turbo
----------------------------------
OS: OTRS Turbo Linux Web Console
Host: Enterprise Ticket Engine 1.0
Uptime: 17 hours, 42 mins
Shell: OTRS-Bash 5.2
Engine: Express / PG SQL Node.js 18.x
Tickets In DB: ${ticketStats.total} total (${ticketStats.open} aperti)
Theme: ${this.currentTheme}
`; this.printOutput(html); }, async cmdTickets() { this.printOutput('Caricamento ultimi ticket dal database...'); try { const res = await App.api('/api/tickets?page=1&per_page=8'); const tickets = res.tickets || []; if (tickets.length === 0) { this.printOutput('Nessun ticket trovato.'); return; } let rows = ` `; tickets.forEach(t => { rows += ` `; }); rows += `
TN Titolo Stato Coda Cliente
#${App.escapeHtml(t.tn)} ${App.escapeHtml((t.title || '').substring(0, 35))} ${App.escapeHtml(t.state_name || '')} ${App.escapeHtml(t.queue_name || '')} ${App.escapeHtml(t.customer_first ? `${t.customer_first} ${t.customer_last}` : (t.customer_user_id || '—'))}
`; this.printOutput(rows); } catch (err) { this.printOutput(`Errore recupero ticket: ${App.escapeHtml(err.message)}`); } }, cmdTheme(themeName) { const valid = ['dark', 'green', 'amber', 'cyber']; if (!themeName || !valid.includes(themeName.toLowerCase())) { this.printOutput('Uso: theme <dark|green|amber|cyber>'); return; } const t = themeName.toLowerCase(); const overlay = document.getElementById('linux-console-modal'); if (overlay) { overlay.className = `console-modal-overlay theme-${t}`; } this.currentTheme = t; this.printOutput(`Tema terminale cambiato in: ${t}`); }, cmdMatrix() { this.printOutput('Inizializzazione matrice in corso... premi Esc o Ctrl+C per fermare.'); this.hideInputRow(); const outputDiv = document.getElementById('console-output'); const matrixBox = document.createElement('pre'); matrixBox.className = 'matrix-stream'; outputDiv.appendChild(matrixBox); const chars = '0123456789ABCDEFヲアウエオカキケコサシスセソタツテナニヌネハヒホマミムメモヤユラリワ'; const cols = 60; this.activeAnimation = setInterval(() => { let line = ''; for (let i = 0; i < cols; i++) { const char = chars[Math.floor(Math.random() * chars.length)]; line += char + ' '; } matrixBox.textContent += line + '\n'; this.scrollToBottom(); if (matrixBox.textContent.length > 3000) { matrixBox.textContent = matrixBox.textContent.substring(1500); } }, 80); }, cmdSl() { this.printOutput('Choo Choo! Locomotiva in transito...'); this.hideInputRow(); const outputDiv = document.getElementById('console-output'); const trainBox = document.createElement('pre'); trainBox.className = 'sl-train-box'; outputDiv.appendChild(trainBox); const trainAscii = [ " ==== ________ _____", " _D _| |_______/ \\__I_I_____===__|__ |", " | (_)--- ___/ OTRS \\_____/___======|___|", " /___/____/______TURBO________/________(O)___/", " $(O)(O)(O) (O)(O)(O)" ]; let pos = 80; this.activeAnimation = setInterval(() => { pos -= 3; if (pos < -60) { this.stopAnimation(); this.showInputRow(); trainBox.remove(); this.printOutput('La locomotiva ha completato la corsa!'); return; } const spaces = ' '.repeat(Math.max(0, pos)); trainBox.textContent = trainAscii.map(l => spaces + l).join('\n'); this.scrollToBottom(); }, 50); } }; window.ConsoleView = ConsoleView;