| … | … | @@ -10,7 +10,7 @@ |
| 10 | 10 | import http from 'http' |
| 11 | 11 | import https from 'https' |
| 12 | 12 | import { WebSocket, WebSocketServer } from 'ws' |
| 13 | | import { apds } from '../lib/wirecore-apds.js' |
| 13 | import { apds, config } from '../lib/wirecore-apds.js' |
| 14 | 14 | |
| 15 | 15 | // Initialize wirecore-apds |
| 16 | 16 | await apds.start('wirecore-relay-v1') |
| … | … | @@ -228,6 +228,39 @@ 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> |
| 231 | 264 | |
| 232 | 265 | <div class="messages" id="messages"> |
| 233 | 266 | <div class="no-messages">Loading messages...</div> |
| … | … | @@ -281,6 +314,75 @@ const handleHTTP = async (req, res) => { |
| 281 | 314 | return div.innerHTML |
| 282 | 315 | } |
| 283 | 316 | |
| 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 | |
| 284 | 386 | loadStats() |
| 285 | 387 | loadMessages() |
| 286 | 388 | setInterval(loadStats, 5000) |
| … | … | @@ -330,6 +432,78 @@ const handleHTTP = async (req, res) => { |
| 330 | 432 | return |
| 331 | 433 | } |
| 332 | 434 | |
| 435 | // GET /config - view current configuration |
| 436 | if (key === 'config' && req.method === 'GET') { |
| 437 | res.writeHead(200, { 'Content-Type': 'application/json' }) |
| 438 | res.end(JSON.stringify({ |
| 439 | maxConcurrentFetches: config.maxConcurrentFetches, |
| 440 | maxCachedMessages: config.maxCachedMessages, |
| 441 | lazyLoadLimit: config.lazyLoadLimit, |
| 442 | fetchTimeout: config.fetchTimeout, |
| 443 | remoteServer: config.remoteServer |
| 444 | }, null, 2)) |
| 445 | return |
| 446 | } |
| 447 | |
| 448 | // POST /config - update configuration |
| 449 | if (key === 'config' && req.method === 'POST') { |
| 450 | let body = '' |
| 451 | req.on('data', chunk => body += chunk) |
| 452 | req.on('end', () => { |
| 453 | try { |
| 454 | const updates = JSON.parse(body) |
| 455 | |
| 456 | // Validate and apply updates |
| 457 | if (updates.maxConcurrentFetches !== undefined) { |
| 458 | const val = parseInt(updates.maxConcurrentFetches) |
| 459 | if (val > 0 && val <= 100) { |
| 460 | config.maxConcurrentFetches = val |
| 461 | https.globalAgent.maxSockets = val |
| 462 | console.log(`Updated maxConcurrentFetches: ${val}`) |
| 463 | } |
| 464 | } |
| 465 | |
| 466 | if (updates.maxCachedMessages !== undefined) { |
| 467 | const val = parseInt(updates.maxCachedMessages) |
| 468 | if (val >= 100 && val <= 100000) { |
| 469 | config.maxCachedMessages = val |
| 470 | console.log(`Updated maxCachedMessages: ${val}`) |
| 471 | } |
| 472 | } |
| 473 | |
| 474 | if (updates.lazyLoadLimit !== undefined) { |
| 475 | const val = parseInt(updates.lazyLoadLimit) |
| 476 | if (val > 0 && val <= 100) { |
| 477 | config.lazyLoadLimit = val |
| 478 | console.log(`Updated lazyLoadLimit: ${val}`) |
| 479 | } |
| 480 | } |
| 481 | |
| 482 | if (updates.fetchTimeout !== undefined) { |
| 483 | const val = parseInt(updates.fetchTimeout) |
| 484 | if (val >= 1000 && val <= 30000) { |
| 485 | config.fetchTimeout = val |
| 486 | console.log(`Updated fetchTimeout: ${val}ms`) |
| 487 | } |
| 488 | } |
| 489 | |
| 490 | if (updates.remoteServer !== undefined && typeof updates.remoteServer === 'string') { |
| 491 | if (updates.remoteServer.startsWith('http://') || updates.remoteServer.startsWith('https://')) { |
| 492 | config.remoteServer = updates.remoteServer |
| 493 | console.log(`Updated remoteServer: ${updates.remoteServer}`) |
| 494 | } |
| 495 | } |
| 496 | |
| 497 | res.writeHead(200, { 'Content-Type': 'application/json' }) |
| 498 | res.end(JSON.stringify({ success: true, config })) |
| 499 | } catch (err) { |
| 500 | res.writeHead(400, { 'Content-Type': 'application/json' }) |
| 501 | res.end(JSON.stringify({ error: 'Invalid JSON' })) |
| 502 | } |
| 503 | }) |
| 504 | return |
| 505 | } |
| 506 | |
| 333 | 507 | // GET /{hash} - specific blob |
| 334 | 508 | const blob = await apds.get(key) |
| 335 | 509 | if (blob) { |