|
|
|
|
@ -4178,6 +4178,134 @@ app.post('/api/wsjtx/relay', (req, res) => {
|
|
|
|
|
res.json({ ok: true, processed, timestamp: Date.now() });
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// API endpoint: download pre-configured relay agent script
|
|
|
|
|
// Embeds relay.js + server URL + relay key into a one-file launcher
|
|
|
|
|
app.get('/api/wsjtx/relay/download/:platform', (req, res) => {
|
|
|
|
|
if (!WSJTX_RELAY_KEY) {
|
|
|
|
|
return res.status(503).json({ error: 'Relay not configured — set WSJTX_RELAY_KEY in .env' });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const platform = req.params.platform; // 'linux', 'mac', or 'windows'
|
|
|
|
|
const relayJsPath = path.join(__dirname, 'wsjtx-relay', 'relay.js');
|
|
|
|
|
|
|
|
|
|
let relayJs;
|
|
|
|
|
try {
|
|
|
|
|
relayJs = fs.readFileSync(relayJsPath, 'utf8');
|
|
|
|
|
} catch (e) {
|
|
|
|
|
return res.status(500).json({ error: 'relay.js not found on server' });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Detect server URL from request
|
|
|
|
|
const proto = req.headers['x-forwarded-proto'] || req.protocol || 'http';
|
|
|
|
|
const host = req.headers['x-forwarded-host'] || req.headers.host;
|
|
|
|
|
const serverURL = proto + '://' + host;
|
|
|
|
|
|
|
|
|
|
if (platform === 'linux' || platform === 'mac') {
|
|
|
|
|
// Build bash script with relay.js embedded as heredoc
|
|
|
|
|
const lines = [
|
|
|
|
|
'#!/bin/bash',
|
|
|
|
|
'# OpenHamClock WSJT-X Relay — Auto-configured',
|
|
|
|
|
'# Generated by ' + serverURL,
|
|
|
|
|
'#',
|
|
|
|
|
'# Usage: bash ' + (platform === 'mac' ? 'start-relay.command' : 'start-relay.sh'),
|
|
|
|
|
'# Stop: Ctrl+C',
|
|
|
|
|
'# Requires: Node.js 14+ (https://nodejs.org)',
|
|
|
|
|
'#',
|
|
|
|
|
'# In WSJT-X: Settings > Reporting > UDP Server',
|
|
|
|
|
'# Address: 127.0.0.1 Port: 2237',
|
|
|
|
|
'',
|
|
|
|
|
'set -e',
|
|
|
|
|
'',
|
|
|
|
|
'# Check for Node.js',
|
|
|
|
|
'if ! command -v node &> /dev/null; then',
|
|
|
|
|
' echo ""',
|
|
|
|
|
' echo "Node.js is not installed."',
|
|
|
|
|
' echo "Install from https://nodejs.org (LTS recommended)"',
|
|
|
|
|
' echo ""',
|
|
|
|
|
' echo "Quick install:"',
|
|
|
|
|
' echo " Ubuntu/Debian: sudo apt install nodejs"',
|
|
|
|
|
' echo " Mac (Homebrew): brew install node"',
|
|
|
|
|
' echo " Fedora: sudo dnf install nodejs"',
|
|
|
|
|
' echo ""',
|
|
|
|
|
' exit 1',
|
|
|
|
|
'fi',
|
|
|
|
|
'',
|
|
|
|
|
'# Write relay agent to temp file',
|
|
|
|
|
'RELAY_FILE=$(mktemp /tmp/ohc-relay-XXXXXX.js)',
|
|
|
|
|
'trap "rm -f $RELAY_FILE" EXIT',
|
|
|
|
|
'',
|
|
|
|
|
"cat > \"$RELAY_FILE\" << 'OPENHAMCLOCK_RELAY_EOF'",
|
|
|
|
|
relayJs,
|
|
|
|
|
'OPENHAMCLOCK_RELAY_EOF',
|
|
|
|
|
'',
|
|
|
|
|
'# Run relay',
|
|
|
|
|
'exec node "$RELAY_FILE" \\',
|
|
|
|
|
' --url "' + serverURL + '" \\',
|
|
|
|
|
' --key "' + WSJTX_RELAY_KEY + '"',
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const script = lines.join('\n') + '\n';
|
|
|
|
|
const filename = platform === 'mac' ? 'start-relay.command' : 'start-relay.sh';
|
|
|
|
|
res.setHeader('Content-Type', 'application/x-sh');
|
|
|
|
|
res.setHeader('Content-Disposition', 'attachment; filename="' + filename + '"');
|
|
|
|
|
return res.send(script);
|
|
|
|
|
|
|
|
|
|
} else if (platform === 'windows') {
|
|
|
|
|
// Build PowerShell script with relay.js embedded
|
|
|
|
|
const escapedJs = relayJs.replace(/'/g, "''");
|
|
|
|
|
|
|
|
|
|
const lines = [
|
|
|
|
|
'# OpenHamClock WSJT-X Relay - Auto-configured',
|
|
|
|
|
'# Generated by ' + serverURL,
|
|
|
|
|
'# Right-click > "Run with PowerShell" or run from terminal',
|
|
|
|
|
'# Requires: Node.js 14+ (https://nodejs.org)',
|
|
|
|
|
'#',
|
|
|
|
|
'# In WSJT-X: Settings > Reporting > UDP Server',
|
|
|
|
|
'# Address: 127.0.0.1 Port: 2237',
|
|
|
|
|
'',
|
|
|
|
|
'# Check for Node.js',
|
|
|
|
|
'try {',
|
|
|
|
|
' $nv = (node -v 2>$null)',
|
|
|
|
|
' if (-not $nv) { throw "missing" }',
|
|
|
|
|
' Write-Host "Found Node.js $nv" -ForegroundColor Green',
|
|
|
|
|
'} catch {',
|
|
|
|
|
' Write-Host "Node.js is not installed." -ForegroundColor Red',
|
|
|
|
|
' Write-Host "Download from https://nodejs.org (LTS version)" -ForegroundColor Yellow',
|
|
|
|
|
' Read-Host "Press Enter to exit"',
|
|
|
|
|
' exit 1',
|
|
|
|
|
'}',
|
|
|
|
|
'',
|
|
|
|
|
'# Write relay agent to temp file',
|
|
|
|
|
'$relayFile = Join-Path $env:TEMP "ohc-relay.js"',
|
|
|
|
|
'',
|
|
|
|
|
"$relayCode = @'",
|
|
|
|
|
escapedJs,
|
|
|
|
|
"'@",
|
|
|
|
|
'',
|
|
|
|
|
'$relayCode | Out-File -FilePath $relayFile -Encoding UTF8',
|
|
|
|
|
'',
|
|
|
|
|
'Write-Host "Starting WSJT-X relay agent..." -ForegroundColor Cyan',
|
|
|
|
|
'Write-Host "Press Ctrl+C to stop" -ForegroundColor DarkGray',
|
|
|
|
|
'Write-Host ""',
|
|
|
|
|
'',
|
|
|
|
|
'# Run relay',
|
|
|
|
|
'try {',
|
|
|
|
|
' node $relayFile --url "' + serverURL + '" --key "' + WSJTX_RELAY_KEY + '"',
|
|
|
|
|
'} finally {',
|
|
|
|
|
' Remove-Item $relayFile -ErrorAction SilentlyContinue',
|
|
|
|
|
'}',
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const script = lines.join('\r\n') + '\r\n';
|
|
|
|
|
res.setHeader('Content-Type', 'application/x-powershell');
|
|
|
|
|
res.setHeader('Content-Disposition', 'attachment; filename="start-relay.ps1"');
|
|
|
|
|
return res.send(script);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
return res.status(400).json({ error: 'Invalid platform. Use: linux, mac, or windows' });
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// ============================================
|
|
|
|
|
// CATCH-ALL FOR SPA
|
|
|
|
|
// ============================================
|
|
|
|
|
|