// Proxy Management Module class ProxyManager { constructor(API_BASE) { this.API_BASE = API_BASE; this.providers = []; } // Initialize proxy manager init(providers) { this.providers = providers; } // Load proxy forms async loadProxyForms() { const proxyContainer = document.getElementById('proxy-container'); if (!this.providers || this.providers.length === 0) { proxyContainer.innerHTML = `

No providers available

Load providers from credentials tab first

`; return; } const htmls = await Promise.all(this.providers.map(async (provider) => { return await this.createProxyCard(provider); })); proxyContainer.innerHTML = htmls.join(''); } // Create proxy card HTML for a provider async createProxyCard(provider) { try { // Try to load existing proxy config const existingProxy = await this.getProxyConfig(provider.name); return `
${provider.logo ? `` : ''}

${provider.label}

Proxy Configuration • ${provider.country}
${existingProxy ? `
Proxy Configured ${(existingProxy.proxy_type || 'http').toUpperCase()}
` : `
No Proxy
`}
${this.createAdvancedProxySection(provider.name, existingProxy)}
${existingProxy ? ` ` : ''}
`; } catch (error) { console.error(`Error creating proxy card for ${provider.name}:`, error); return ''; // Return empty string on error } } // Create advanced proxy section createAdvancedProxySection(providerName, existingProxy) { const scope = existingProxy?.scope || { api_calls: true, authentication: true, manifests: true, license: true, all: true }; return `
Advanced Options

Proxy Scope

Select which operations should use this proxy:

`; } // Get proxy configuration from API async getProxyConfig(providerName) { try { const response = await fetch(`${this.API_BASE}/api/providers/${providerName}/proxy`); if (response.ok) { const data = await response.json(); return data.proxy_config || null; } return null; } catch (error) { console.error(`Error getting proxy config for ${providerName}:`, error); return null; } } // Save proxy configuration async saveProxy(providerName) { const host = document.getElementById(`proxy-host-${providerName}`).value.trim(); const port = document.getElementById(`proxy-port-${providerName}`).value.trim(); const type = document.getElementById(`proxy-type-${providerName}`).value; const user = document.getElementById(`proxy-user-${providerName}`).value.trim(); const pass = document.getElementById(`proxy-pass-${providerName}`).value; // Advanced options const timeout = document.getElementById(`proxy-timeout-${providerName}`)?.value || 30; const verifySsl = document.getElementById(`proxy-verify-ssl-${providerName}`)?.checked !== false; // Scope settings const scope = { api_calls: document.getElementById(`proxy-scope-api-${providerName}`)?.checked || false, authentication: document.getElementById(`proxy-scope-auth-${providerName}`)?.checked || false, manifests: document.getElementById(`proxy-scope-manifests-${providerName}`)?.checked || false, license: document.getElementById(`proxy-scope-license-${providerName}`)?.checked || false, all: document.getElementById(`proxy-scope-all-${providerName}`)?.checked || false }; if (!host || !port) { this.showProxyAlert('error', 'Please fill in at least Host and Port fields', providerName); return; } const proxyConfig = { host, port: parseInt(port), proxy_type: type, timeout: parseInt(timeout), verify_ssl: verifySsl, scope: scope }; if (user) { proxyConfig.auth = { username: user }; if (pass) { proxyConfig.auth.password = pass; } } try { const response = await fetch(`${this.API_BASE}/api/providers/${providerName}/proxy`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(proxyConfig) }); if (response.ok) { this.showProxyAlert('success', `Proxy configuration saved for ${providerName}`, providerName); // Clear password field if (document.getElementById(`proxy-pass-${providerName}`)) { document.getElementById(`proxy-pass-${providerName}`).value = ''; } // Reload proxy form to show updated status await this.loadProxyForms(); } else { const result = await response.json(); this.showProxyAlert('error', result.error || `Failed to save proxy for ${providerName}`, providerName); } } catch (error) { this.showProxyAlert('error', `Network error: ${error.message}`, providerName); console.error('Proxy save error:', error); } } // Delete proxy configuration async deleteProxy(providerName) { if (!confirm(`Delete proxy configuration for ${providerName}?`)) return; try { const response = await fetch(`${this.API_BASE}/api/providers/${providerName}/proxy`, { method: 'DELETE' }); if (response.ok) { this.showProxyAlert('success', `Proxy configuration deleted for ${providerName}`, providerName); // Reload proxy form await this.loadProxyForms(); } else { const result = await response.json(); this.showProxyAlert('error', result.error || `Failed to delete proxy for ${providerName}`, providerName); } } catch (error) { this.showProxyAlert('error', `Network error: ${error.message}`, providerName); console.error('Proxy delete error:', error); } } // Test proxy connection async testProxy(providerName) { const testResultEl = document.getElementById(`proxy-test-result-${providerName}`); if (testResultEl) { testResultEl.innerHTML = ' Testing proxy connection...'; testResultEl.className = 'proxy-test-result'; } try { // Try to fetch a test endpoint through the provider const response = await fetch(`${this.API_BASE}/api/providers/${providerName}/channels?limit=1`); if (response.ok) { if (testResultEl) { testResultEl.innerHTML = ' Proxy connection successful!'; testResultEl.className = 'proxy-test-result success'; } this.showProxyAlert('success', `Proxy test passed for ${providerName}`, providerName); } else { if (testResultEl) { testResultEl.innerHTML = ` Proxy test failed (HTTP ${response.status})`; testResultEl.className = 'proxy-test-result error'; } this.showProxyAlert('error', `Proxy test failed for ${providerName} (HTTP ${response.status})`, providerName); } } catch (error) { if (testResultEl) { testResultEl.innerHTML = ` Network error: ${error.message}`; testResultEl.className = 'proxy-test-result error'; } this.showProxyAlert('error', `Proxy test failed: ${error.message}`, providerName); console.error('Proxy test error:', error); } } // Toggle advanced options toggleAdvanced(providerName) { const contentEl = document.getElementById(`proxy-advanced-content-${providerName}`); const iconEl = document.getElementById(`proxy-advanced-icon-${providerName}`); if (contentEl && iconEl) { const isExpanded = contentEl.classList.contains('expanded'); if (isExpanded) { contentEl.classList.remove('expanded'); iconEl.classList.remove('fa-chevron-up'); iconEl.classList.add('fa-chevron-down'); } else { contentEl.classList.add('expanded'); iconEl.classList.remove('fa-chevron-down'); iconEl.classList.add('fa-chevron-up'); } } } // Show alert for proxy operations showProxyAlert(type, message, providerName = null) { const alert = document.createElement('div'); alert.className = `alert alert-${type}`; alert.innerHTML = `
${providerName ? `${providerName}: ` : ''}${message}
`; // Insert at beginning of proxy container const proxyContainer = document.getElementById('proxy-container'); if (proxyContainer) { proxyContainer.insertBefore(alert, proxyContainer.firstChild); } else { // Fallback to card body const cardBody = document.querySelector('.card-body'); if (cardBody) { cardBody.insertBefore(alert, cardBody.firstChild); } } // Remove after 5 seconds setTimeout(() => alert.remove(), 5000); } } // Make ProxyManager globally available window.ProxyManager = ProxyManager; // Initialize proxy manager when DOM is loaded document.addEventListener('DOMContentLoaded', () => { window.proxyManager = new ProxyManager(window.location.origin); });