| … | … | @@ -228,39 +228,6 @@ const handleHTTP = async (req, res) => { |
| 228 | 228 | <button onclick="loadMessages()">🔄 Refresh</button> |
| 229 | 229 | <button onclick="window.location.href='stats'">📊 Stats JSON</button> |
| 230 | 230 | <button onclick="window.location.href='all'">📋 Messages JSON</button> |
| 231 | | <button onclick="toggleConfig()">⚙️ Configuration</button> |
| 232 | | |
| 233 | | <div id="configPanel" style="display: none; background: #161b22; border: 1px solid #30363d; border-radius: 6px; padding: 20px; margin-bottom: 20px;"> |
| 234 | | <h3 style="margin-bottom: 15px;">⚙️ Configuration</h3> |
| 235 | | <div style="margin-bottom: 15px;"> |
| 236 | | <label style="display: block; margin-bottom: 5px; color: #8b949e;">Max Concurrent Fetches (1-100):</label> |
| 237 | | <input type="number" id="maxConcurrentFetches" min="1" max="100" style="width: 100px; padding: 5px; background: #0d1117; border: 1px solid #30363d; color: #c9d1d9; border-radius: 4px;"> |
| 238 | | <span style="margin-left: 10px; color: #8b949e; font-size: 12px;">Current: <span id="currentMaxConcurrent">-</span></span> |
| 239 | | </div> |
| 240 | | <div style="margin-bottom: 15px;"> |
| 241 | | <label style="display: block; margin-bottom: 5px; color: #8b949e;">Lazy Load Limit (1-100):</label> |
| 242 | | <input type="number" id="lazyLoadLimit" min="1" max="100" style="width: 100px; padding: 5px; background: #0d1117; border: 1px solid #30363d; color: #c9d1d9; border-radius: 4px;"> |
| 243 | | <span style="margin-left: 10px; color: #8b949e; font-size: 12px;">Current: <span id="currentLazyLoad">-</span></span> |
| 244 | | </div> |
| 245 | | <div style="margin-bottom: 15px;"> |
| 246 | | <label style="display: block; margin-bottom: 5px; color: #8b949e;">Fetch Timeout (1000-30000ms):</label> |
| 247 | | <input type="number" id="fetchTimeout" min="1000" max="30000" step="1000" style="width: 100px; padding: 5px; background: #0d1117; border: 1px solid #30363d; color: #c9d1d9; border-radius: 4px;"> |
| 248 | | <span style="margin-left: 10px; color: #8b949e; font-size: 12px;">Current: <span id="currentTimeout">-</span>ms</span> |
| 249 | | </div> |
| 250 | | <div style="margin-bottom: 15px;"> |
| 251 | | <label style="display: block; margin-bottom: 5px; color: #8b949e;">Max Cached Messages (100-100000):</label> |
| 252 | | <input type="number" id="maxCachedMessages" min="100" max="100000" step="100" style="width: 100px; padding: 5px; background: #0d1117; border: 1px solid #30363d; color: #c9d1d9; border-radius: 4px;"> |
| 253 | | <span style="margin-left: 10px; color: #8b949e; font-size: 12px;">Current: <span id="currentMaxCached">-</span></span> |
| 254 | | </div> |
| 255 | | <div style="margin-bottom: 15px;"> |
| 256 | | <label style="display: block; margin-bottom: 5px; color: #8b949e;">Remote Server:</label> |
| 257 | | <input type="text" id="remoteServer" placeholder="https://pub.wiredove.net" style="width: 300px; padding: 5px; background: #0d1117; border: 1px solid #30363d; color: #c9d1d9; border-radius: 4px;"> |
| 258 | | <span style="margin-left: 10px; color: #8b949e; font-size: 12px;">Current: <span id="currentRemote">-</span></span> |
| 259 | | </div> |
| 260 | | <button onclick="updateConfig()" style="background: #238636;">💾 Save Configuration</button> |
| 261 | | <button onclick="toggleConfig()" style="background: #6e7681; margin-left: 10px;">Cancel</button> |
| 262 | | <div id="configResult" style="margin-top: 10px; padding: 10px; border-radius: 4px; display: none;"></div> |
| 263 | | </div> |
| 264 | 231 | |
| 265 | 232 | <div class="messages" id="messages"> |
| 266 | 233 | <div class="no-messages">Loading messages...</div> |
| … | … | @@ -314,75 +281,6 @@ const handleHTTP = async (req, res) => { |
| 314 | 281 | return div.innerHTML |
| 315 | 282 | } |
| 316 | 283 | |
| 317 | | async function loadConfig() { |
| 318 | | try { |
| 319 | | const res = await fetch('config') |
| 320 | | const config = await res.json() |
| 321 | | document.getElementById('currentMaxConcurrent').textContent = config.maxConcurrentFetches |
| 322 | | document.getElementById('currentLazyLoad').textContent = config.lazyLoadLimit |
| 323 | | document.getElementById('currentTimeout').textContent = config.fetchTimeout |
| 324 | | document.getElementById('currentMaxCached').textContent = config.maxCachedMessages |
| 325 | | document.getElementById('currentRemote').textContent = config.remoteServer |
| 326 | | |
| 327 | | document.getElementById('maxConcurrentFetches').value = config.maxConcurrentFetches |
| 328 | | document.getElementById('lazyLoadLimit').value = config.lazyLoadLimit |
| 329 | | document.getElementById('fetchTimeout').value = config.fetchTimeout |
| 330 | | document.getElementById('maxCachedMessages').value = config.maxCachedMessages |
| 331 | | document.getElementById('remoteServer').value = config.remoteServer |
| 332 | | } catch (err) { |
| 333 | | console.error('Failed to load config:', err) |
| 334 | | } |
| 335 | | } |
| 336 | | |
| 337 | | function toggleConfig() { |
| 338 | | const panel = document.getElementById('configPanel') |
| 339 | | if (panel.style.display === 'none') { |
| 340 | | panel.style.display = 'block' |
| 341 | | loadConfig() |
| 342 | | } else { |
| 343 | | panel.style.display = 'none' |
| 344 | | } |
| 345 | | } |
| 346 | | |
| 347 | | async function updateConfig() { |
| 348 | | const result = document.getElementById('configResult') |
| 349 | | try { |
| 350 | | const updates = { |
| 351 | | maxConcurrentFetches: parseInt(document.getElementById('maxConcurrentFetches').value), |
| 352 | | lazyLoadLimit: parseInt(document.getElementById('lazyLoadLimit').value), |
| 353 | | fetchTimeout: parseInt(document.getElementById('fetchTimeout').value), |
| 354 | | maxCachedMessages: parseInt(document.getElementById('maxCachedMessages').value), |
| 355 | | remoteServer: document.getElementById('remoteServer').value |
| 356 | | } |
| 357 | | |
| 358 | | const res = await fetch('config', { |
| 359 | | method: 'POST', |
| 360 | | headers: { 'Content-Type': 'application/json' }, |
| 361 | | body: JSON.stringify(updates) |
| 362 | | }) |
| 363 | | |
| 364 | | const data = await res.json() |
| 365 | | |
| 366 | | if (data.success) { |
| 367 | | result.style.display = 'block' |
| 368 | | result.style.background = '#238636' |
| 369 | | result.textContent = '✅ Configuration updated successfully!' |
| 370 | | await loadConfig() |
| 371 | | setTimeout(() => { |
| 372 | | result.style.display = 'none' |
| 373 | | }, 3000) |
| 374 | | } else { |
| 375 | | result.style.display = 'block' |
| 376 | | result.style.background = '#da3633' |
| 377 | | result.textContent = '❌ Failed to update: ' + (data.error || 'Unknown error') |
| 378 | | } |
| 379 | | } catch (err) { |
| 380 | | result.style.display = 'block' |
| 381 | | result.style.background = '#da3633' |
| 382 | | result.textContent = '❌ Error: ' + err.message |
| 383 | | } |
| 384 | | } |
| 385 | | |
| 386 | 284 | loadStats() |
| 387 | 285 | loadMessages() |
| 388 | 286 | setInterval(loadStats, 5000) |
| … | … | @@ -433,6 +331,8 @@ const handleHTTP = async (req, res) => { |
| 433 | 331 | } |
| 434 | 332 | |
| 435 | 333 | // GET /config - view current configuration |
| 334 | // NOTE: This endpoint should be protected in production (firewall, auth, etc.) |
| 335 | // Currently only accessible via localhost or internal network |
| 436 | 336 | if (key === 'config' && req.method === 'GET') { |
| 437 | 337 | res.writeHead(200, { 'Content-Type': 'application/json' }) |
| 438 | 338 | res.end(JSON.stringify({ |