()
| 91 | |
| 92 | // Optimized fetchConfigs function with parallel processing |
| 93 | async function fetchConfigs() { |
| 94 | try { |
| 95 | // Clear existing configs directory |
| 96 | const configsDir = path.join(getResourcePath('core'), 'configs'); |
| 97 | if (fs.existsSync(configsDir)) { |
| 98 | const files = fs.readdirSync(configsDir); |
| 99 | for (const file of files) { |
| 100 | fs.unlinkSync(path.join(configsDir, file)); |
| 101 | } |
| 102 | } else { |
| 103 | fs.mkdirSync(configsDir, { recursive: true }); |
| 104 | } |
| 105 | |
| 106 | // Ensure xray directory exists |
| 107 | const xrayDir = path.join(getResourcePath('core'), 'xray'); |
| 108 | if (!fs.existsSync(xrayDir)) { |
| 109 | fs.mkdirSync(xrayDir, { recursive: true }); |
| 110 | } |
| 111 | |
| 112 | // Fetch configs from the new URL with timeout |
| 113 | const response = await axios.get('https://raw.githubusercontent.com/darkvpnapp/CloudflarePlus/refs/heads/main/proxy', { |
| 114 | timeout: 10000 // 10 second timeout |
| 115 | }); |
| 116 | const rawData = response.data; |
| 117 | |
| 118 | // Split by lines and filter for supported protocols |
| 119 | const lines = rawData.split('\n').filter(line => |
| 120 | line.trim().startsWith('vless://') || |
| 121 | line.trim().startsWith('vmess://') || |
| 122 | line.trim().startsWith('ss://') || |
| 123 | line.trim().startsWith('trojan://') |
| 124 | ); |
| 125 | |
| 126 | const configs = []; |
| 127 | |
| 128 | // Check if x2j exists |
| 129 | if (!fs.existsSync(x2jPath)) { |
| 130 | throw new Error('x2j executable not found. Please ensure x2j is properly installed in core/x2j directory.'); |
| 131 | } |
| 132 | |
| 133 | // Process configs in parallel batches for better performance |
| 134 | const batchSize = 10; // Process 10 configs at a time |
| 135 | const batches = []; |
| 136 | |
| 137 | // Create batches |
| 138 | for (let i = 0; i < lines.length; i += batchSize) { |
| 139 | batches.push(lines.slice(i, i + batchSize)); |
| 140 | } |
| 141 | |
| 142 | // Process each batch |
| 143 | for (const batch of batches) { |
| 144 | const batchPromises = batch.map(async (line, indexInBatch) => { |
| 145 | const globalIndex = batches.indexOf(batch) * batchSize + indexInBatch; |
| 146 | const trimmedLine = line.trim(); |
| 147 | if (!trimmedLine) return null; |
| 148 | |
| 149 | try { |
| 150 | // Generate JSON filename |
no test coverage detected