Spaces:
Running
Running
| // VPN Controller Logic | |
| class VPNController { | |
| constructor() { | |
| this.isConnected = false; | |
| this.connectionTime = 0; | |
| this.timerInterval = null; | |
| this.process = null; | |
| this.logs = []; | |
| this.initElements(); | |
| this.bindEvents(); | |
| this.simulateMetrics(); | |
| } | |
| initElements() { | |
| this.mainToggle = document.getElementById('mainToggle'); | |
| this.connectionStatus = document.getElementById('connectionStatus'); | |
| this.connectionSubtitle = document.getElementById('connectionSubtitle'); | |
| this.logConsole = document.getElementById('logConsole'); | |
| this.downloadStat = document.getElementById('downloadStat'); | |
| this.uploadStat = document.getElementById('uploadStat'); | |
| this.timeStat = document.getElementById('timeStat'); | |
| this.clearLogsBtn = document.getElementById('clearLogs'); | |
| } | |
| bindEvents() { | |
| // Power button toggle | |
| document.addEventListener('power-toggle', (e) => { | |
| this.toggleConnection(); | |
| }); | |
| // Clear logs | |
| this.clearLogsBtn.addEventListener('click', () => { | |
| this.logConsole.clear(); | |
| this.addLog('Logs cleared by user', 'info'); | |
| }); | |
| // Keyboard shortcut (Space to toggle) | |
| document.addEventListener('keydown', (e) => { | |
| if (e.code === 'Space' && e.target === document.body) { | |
| e.preventDefault(); | |
| this.toggleConnection(); | |
| } | |
| }); | |
| } | |
| toggleConnection() { | |
| if (this.isConnected) { | |
| this.disconnect(); | |
| } else { | |
| this.connect(); | |
| } | |
| } | |
| connect() { | |
| this.isConnected = true; | |
| this.updateUI(); | |
| this.startTimer(); | |
| this.addLog('Initializing Psiphon connection...', 'info'); | |
| this.addLog('Loading configuration from /home/hossein/Files/psiphon/psiphon.config', 'system'); | |
| // Simulate connection process | |
| setTimeout(() => { | |
| this.addLog('Starting tunnel core...', 'process'); | |
| }, 500); | |
| setTimeout(() => { | |
| this.addLog('Connecting to nearest available server...', 'network'); | |
| }, 1500); | |
| setTimeout(() => { | |
| this.addLog('Handshake successful', 'success'); | |
| this.addLog('Tunnel established via SSH+ protocol', 'success'); | |
| this.addLog('Local SOCKS proxy started on port 1080', 'info'); | |
| }, 2500); | |
| // Update stats simulation | |
| this.simulateTraffic(); | |
| } | |
| disconnect() { | |
| this.isConnected = false; | |
| this.updateUI(); | |
| this.stopTimer(); | |
| this.addLog('Terminating connection...', 'warning'); | |
| setTimeout(() => { | |
| this.addLog('Tunnel closed gracefully', 'info'); | |
| this.addLog('Process terminated', 'system'); | |
| }, 500); | |
| // Reset stats | |
| this.downloadStat.updateValue('0 MB/s'); | |
| this.uploadStat.updateValue('0 MB/s'); | |
| } | |
| updateUI() { | |
| if (this.isConnected) { | |
| this.connectionStatus.textContent = 'Connected'; | |
| this.connectionStatus.className = 'text-2xl font-bold text-secondary-400 mb-1'; | |
| this.connectionSubtitle.textContent = 'Secure connection active'; | |
| this.mainToggle.setAttribute('active', 'true'); | |
| document.body.classList.add('connection-active'); | |
| } else { | |
| this.connectionStatus.textContent = 'Disconnected'; | |
| this.connectionStatus.className = 'text-2xl font-bold text-gray-400 mb-1'; | |
| this.connectionSubtitle.textContent = 'Tap to connect'; | |
| this.mainToggle.setAttribute('active', 'false'); | |
| document.body.classList.remove('connection-active'); | |
| } | |
| } | |
| startTimer() { | |
| this.connectionTime = 0; | |
| this.updateTimerDisplay(); | |
| this.timerInterval = setInterval(() => { | |
| this.connectionTime++; | |
| this.updateTimerDisplay(); | |
| }, 1000); | |
| } | |
| stopTimer() { | |
| if (this.timerInterval) { | |
| clearInterval(this.timerInterval); | |
| this.timerInterval = null; | |
| } | |
| this.connectionTime = 0; | |
| this.timeStat.updateValue('00:00:00'); | |
| } | |
| updateTimerDisplay() { | |
| const hours = Math.floor(this.connectionTime / 3600); | |
| const minutes = Math.floor((this.connectionTime % 3600) / 60); | |
| const seconds = this.connectionTime % 60; | |
| const formatted = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; | |
| this.timeStat.updateValue(formatted); | |
| } | |
| addLog(message, type = 'info') { | |
| const timestamp = new Date().toLocaleTimeString('en-US', { hour12: false }); | |
| this.logConsole.addEntry(`[${timestamp}] ${message}`, type); | |
| } | |
| simulateTraffic() { | |
| if (!this.isConnected) return; | |
| const download = (Math.random() * 5 + 1).toFixed(1); | |
| const upload = (Math.random() * 2 + 0.5).toFixed(1); | |
| this.downloadStat.updateValue(`${download} MB/s`); | |
| this.uploadStat.updateValue(`${upload} MB/s`); | |
| if (this.isConnected) { | |
| setTimeout(() => this.simulateTraffic(), 2000); | |
| } | |
| } | |
| simulateMetrics() { | |
| // Random log entries when connected | |
| setInterval(() => { | |
| if (this.isConnected && Math.random() > 0.7) { | |
| const messages = [ | |
| 'Heartbeat received', | |
| 'Network status: optimal', | |
| 'Rotating upstream proxy...', | |
| 'Ping: 45ms', | |
| 'Bandwidth throttling detected, switching protocol...' | |
| ]; | |
| const randomMsg = messages[Math.floor(Math.random() * messages.length)]; | |
| this.addLog(randomMsg, 'debug'); | |
| } | |
| }, 5000); | |
| } | |
| } | |
| // Initialize when DOM is ready | |
| document.addEventListener('DOMContentLoaded', () => { | |
| window.vpnController = new VPNController(); | |
| // Initial logs | |
| setTimeout(() => { | |
| window.vpnController.addLog('Psiphon Pilot initialized', 'system'); | |
| window.vpnController.addLog('Ready to establish secure connection', 'info'); | |
| }, 100); | |
| }); |