mirror of
https://github.com/smittix/intercept.git
synced 2026-04-24 06:40:00 -07:00
Fix str(e) in error responses, remove location modal, document GTK dependency
Co-authored-by: mitchross <6330506+mitchross@users.noreply.github.com>
This commit is contained in:
@@ -70,6 +70,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||||||
cmake \
|
cmake \
|
||||||
libncurses-dev \
|
libncurses-dev \
|
||||||
libsndfile1-dev \
|
libsndfile1-dev \
|
||||||
|
# GTK is required for slowrx (SSTV decoder GUI dependency).
|
||||||
|
# Note: slowrx is kept for backwards compatibility, but the pure Python
|
||||||
|
# SSTV decoder in utils/sstv/ is now the primary implementation.
|
||||||
|
# GTK can be removed if slowrx is deprecated in future releases.
|
||||||
libgtk-3-dev \
|
libgtk-3-dev \
|
||||||
libasound2-dev \
|
libasound2-dev \
|
||||||
libsoapysdr-dev \
|
libsoapysdr-dev \
|
||||||
@@ -195,6 +199,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||||||
&& ldconfig \
|
&& ldconfig \
|
||||||
&& rm -rf /tmp/dsd-fme \
|
&& rm -rf /tmp/dsd-fme \
|
||||||
# Cleanup build tools to reduce image size
|
# Cleanup build tools to reduce image size
|
||||||
|
# Note: libgtk-3-dev is removed here but runtime GTK libs (from first stage)
|
||||||
|
# remain for slowrx. This adds ~10MB to the image but is required for slowrx
|
||||||
|
# to function. Consider removing slowrx build entirely if moving fully to
|
||||||
|
# the pure Python SSTV decoder.
|
||||||
&& apt-get remove -y \
|
&& apt-get remove -y \
|
||||||
build-essential \
|
build-essential \
|
||||||
git \
|
git \
|
||||||
|
|||||||
@@ -120,9 +120,10 @@ def start_capture():
|
|||||||
device_index = validate_device_index(data.get('device', 0))
|
device_index = validate_device_index(data.get('device', 0))
|
||||||
gain = validate_gain(data.get('gain', 40.0))
|
gain = validate_gain(data.get('gain', 40.0))
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
|
logger.warning('Invalid parameter in start_capture: %s', e)
|
||||||
return jsonify({
|
return jsonify({
|
||||||
'status': 'error',
|
'status': 'error',
|
||||||
'message': str(e)
|
'message': 'Invalid parameter value'
|
||||||
}), 400
|
}), 400
|
||||||
|
|
||||||
bias_t = bool(data.get('bias_t', False))
|
bias_t = bool(data.get('bias_t', False))
|
||||||
@@ -464,7 +465,8 @@ def get_passes():
|
|||||||
lat = validate_latitude(raw_lat)
|
lat = validate_latitude(raw_lat)
|
||||||
lon = validate_longitude(raw_lon)
|
lon = validate_longitude(raw_lon)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
return jsonify({'status': 'error', 'message': str(e)}), 400
|
logger.warning('Invalid coordinates in get_passes: %s', e)
|
||||||
|
return jsonify({'status': 'error', 'message': 'Invalid coordinates'}), 400
|
||||||
|
|
||||||
hours = max(1, min(request.args.get('hours', 24, type=int), 72))
|
hours = max(1, min(request.args.get('hours', 24, type=int), 72))
|
||||||
min_elevation = max(0, min(request.args.get('min_elevation', 15, type=float), 90))
|
min_elevation = max(0, min(request.args.get('min_elevation', 15, type=float), 90))
|
||||||
@@ -555,9 +557,10 @@ def enable_schedule():
|
|||||||
device = validate_device_index(data.get('device', 0))
|
device = validate_device_index(data.get('device', 0))
|
||||||
gain_val = validate_gain(data.get('gain', 40.0))
|
gain_val = validate_gain(data.get('gain', 40.0))
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
|
logger.warning('Invalid parameter in enable_schedule: %s', e)
|
||||||
return jsonify({
|
return jsonify({
|
||||||
'status': 'error',
|
'status': 'error',
|
||||||
'message': str(e)
|
'message': 'Invalid parameter value'
|
||||||
}), 400
|
}), 400
|
||||||
|
|
||||||
scheduler = get_weather_sat_scheduler()
|
scheduler = get_weather_sat_scheduler()
|
||||||
|
|||||||
@@ -15270,172 +15270,6 @@
|
|||||||
<!-- Settings Modal -->
|
<!-- Settings Modal -->
|
||||||
{% include 'partials/settings-modal.html' %}
|
{% include 'partials/settings-modal.html' %}
|
||||||
|
|
||||||
<!-- Location Prompt (first-run) -->
|
|
||||||
<div id="locationPromptModal" style="display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.85); z-index:10001; backdrop-filter:blur(4px); align-items:center; justify-content:center;">
|
|
||||||
<div style="background:var(--bg-secondary); border:1px solid var(--accent-cyan); border-radius:10px; max-width:420px; width:90%; box-shadow:0 8px 32px rgba(0,0,0,0.6), 0 0 20px rgba(0,255,255,0.15); animation:locFadeIn 0.3s ease-out;">
|
|
||||||
<style>
|
|
||||||
@keyframes locFadeIn { from { transform:scale(0.95); opacity:0; } to { transform:scale(1); opacity:1; } }
|
|
||||||
@keyframes locSpin { to { transform:rotate(360deg); } }
|
|
||||||
</style>
|
|
||||||
<div style="padding:24px;">
|
|
||||||
<div style="text-align:center; margin-bottom:18px;">
|
|
||||||
<svg width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="var(--accent-cyan)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
|
||||||
<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/>
|
|
||||||
</svg>
|
|
||||||
<h3 style="margin:10px 0 4px; color:var(--text-primary); font-size:16px;">Set Your Location</h3>
|
|
||||||
<p style="color:var(--text-dim); font-size:12px; margin:0; line-height:1.4;">
|
|
||||||
INTERCEPT needs your location for satellite pass predictions,<br>weather satellite scheduling, and distance calculations.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="locPromptGpsSection" style="margin-bottom:16px;">
|
|
||||||
<button id="locPromptGpsBtn" onclick="locationPromptDetectGPS()" style="width:100%; padding:12px; background:var(--accent-cyan); color:#000; border:none; border-radius:6px; font-size:13px; font-weight:600; cursor:pointer; font-family:var(--font-mono); display:flex; align-items:center; justify-content:center; gap:8px;">
|
|
||||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
||||||
<circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="3"/><line x1="12" y1="2" x2="12" y2="6"/><line x1="12" y1="18" x2="12" y2="22"/><line x1="2" y1="12" x2="6" y2="12"/><line x1="18" y1="12" x2="22" y2="12"/>
|
|
||||||
</svg>
|
|
||||||
Auto-Detect (GPS)
|
|
||||||
</button>
|
|
||||||
<p id="locPromptGpsStatus" style="font-size:11px; color:var(--text-dim); text-align:center; margin:6px 0 0; min-height:16px;"></p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="display:flex; align-items:center; gap:10px; margin-bottom:14px;">
|
|
||||||
<div style="flex:1; height:1px; background:var(--border-color);"></div>
|
|
||||||
<span style="color:var(--text-dim); font-size:11px;">or enter manually</span>
|
|
||||||
<div style="flex:1; height:1px; background:var(--border-color);"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="display:flex; gap:10px; margin-bottom:16px;">
|
|
||||||
<div style="flex:1;">
|
|
||||||
<label style="display:block; font-size:11px; color:var(--text-dim); margin-bottom:4px;">Latitude</label>
|
|
||||||
<input type="number" id="locPromptLat" step="0.0001" min="-90" max="90" placeholder="51.5074" style="width:100%; padding:8px 10px; background:var(--bg-primary); border:1px solid var(--border-color); border-radius:4px; color:var(--text-primary); font-family:var(--font-mono); font-size:13px; box-sizing:border-box;">
|
|
||||||
</div>
|
|
||||||
<div style="flex:1;">
|
|
||||||
<label style="display:block; font-size:11px; color:var(--text-dim); margin-bottom:4px;">Longitude</label>
|
|
||||||
<input type="number" id="locPromptLon" step="0.0001" min="-180" max="180" placeholder="-0.1278" style="width:100%; padding:8px 10px; background:var(--bg-primary); border:1px solid var(--border-color); border-radius:4px; color:var(--text-primary); font-family:var(--font-mono); font-size:13px; box-sizing:border-box;">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="display:flex; gap:10px;">
|
|
||||||
<button onclick="locationPromptSave()" style="flex:1; padding:10px; background:var(--accent-cyan); color:#000; border:none; border-radius:6px; font-size:12px; font-weight:600; cursor:pointer; font-family:var(--font-mono);">
|
|
||||||
Save Location
|
|
||||||
</button>
|
|
||||||
<button onclick="locationPromptSkip()" style="flex:1; padding:10px; background:transparent; color:var(--text-dim); border:1px solid var(--border-color); border-radius:6px; font-size:12px; cursor:pointer; font-family:var(--font-mono);">
|
|
||||||
Skip for Now
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p style="font-size:10px; color:var(--text-dim); text-align:center; margin:12px 0 0; opacity:0.7;">
|
|
||||||
Stored locally in your browser. Never sent to external servers.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
(function() {
|
|
||||||
// Show location prompt on first load if no location has been set
|
|
||||||
function checkLocationPrompt() {
|
|
||||||
if (!window.ObserverLocation) return;
|
|
||||||
if (ObserverLocation.hasStoredLocation()) return;
|
|
||||||
// Don't show if disclaimer hasn't been accepted yet
|
|
||||||
if (localStorage.getItem('disclaimerAccepted') !== 'true') return;
|
|
||||||
|
|
||||||
// If server provided default lat/lon via env vars, auto-save without prompting
|
|
||||||
if (window.INTERCEPT_DEFAULT_LAT && window.INTERCEPT_DEFAULT_LON) {
|
|
||||||
ObserverLocation.setShared({
|
|
||||||
lat: window.INTERCEPT_DEFAULT_LAT,
|
|
||||||
lon: window.INTERCEPT_DEFAULT_LON
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't show if user explicitly skipped
|
|
||||||
if (localStorage.getItem('locationPromptSkipped') === 'true') return;
|
|
||||||
|
|
||||||
var modal = document.getElementById('locationPromptModal');
|
|
||||||
if (modal) modal.style.display = 'flex';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run after a short delay so disclaimer can show first
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
setTimeout(checkLocationPrompt, 1500);
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
|
|
||||||
function locationPromptDetectGPS() {
|
|
||||||
var btn = document.getElementById('locPromptGpsBtn');
|
|
||||||
var status = document.getElementById('locPromptGpsStatus');
|
|
||||||
|
|
||||||
if (!navigator.geolocation) {
|
|
||||||
status.textContent = 'Geolocation not supported by this browser.';
|
|
||||||
status.style.color = 'var(--accent-red, #ff4444)';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!window.isSecureContext) {
|
|
||||||
status.textContent = 'GPS requires HTTPS or localhost.';
|
|
||||||
status.style.color = 'var(--accent-red, #ff4444)';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
btn.disabled = true;
|
|
||||||
btn.innerHTML = '<span style="display:inline-block; width:14px; height:14px; border:2px solid #000; border-top-color:transparent; border-radius:50%; animation:locSpin 0.8s linear infinite;"></span> Detecting...';
|
|
||||||
status.textContent = '';
|
|
||||||
|
|
||||||
navigator.geolocation.getCurrentPosition(
|
|
||||||
function(pos) {
|
|
||||||
var lat = pos.coords.latitude;
|
|
||||||
var lon = pos.coords.longitude;
|
|
||||||
document.getElementById('locPromptLat').value = lat.toFixed(4);
|
|
||||||
document.getElementById('locPromptLon').value = lon.toFixed(4);
|
|
||||||
status.textContent = 'Location detected! Click Save to confirm.';
|
|
||||||
status.style.color = 'var(--accent-green, #00ff88)';
|
|
||||||
btn.disabled = false;
|
|
||||||
btn.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg> Detected';
|
|
||||||
},
|
|
||||||
function(err) {
|
|
||||||
status.textContent = 'Could not detect: ' + err.message;
|
|
||||||
status.style.color = 'var(--accent-red, #ff4444)';
|
|
||||||
btn.disabled = false;
|
|
||||||
btn.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="3"/><line x1="12" y1="2" x2="12" y2="6"/><line x1="12" y1="18" x2="12" y2="22"/><line x1="2" y1="12" x2="6" y2="12"/><line x1="18" y1="12" x2="22" y2="12"/></svg> Auto-Detect (GPS)';
|
|
||||||
},
|
|
||||||
{ enableHighAccuracy: true, timeout: 15000 }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function locationPromptSave() {
|
|
||||||
var lat = parseFloat(document.getElementById('locPromptLat').value);
|
|
||||||
var lon = parseFloat(document.getElementById('locPromptLon').value);
|
|
||||||
|
|
||||||
if (isNaN(lat) || lat < -90 || lat > 90) {
|
|
||||||
document.getElementById('locPromptGpsStatus').textContent = 'Invalid latitude (-90 to 90)';
|
|
||||||
document.getElementById('locPromptGpsStatus').style.color = 'var(--accent-red, #ff4444)';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (isNaN(lon) || lon < -180 || lon > 180) {
|
|
||||||
document.getElementById('locPromptGpsStatus').textContent = 'Invalid longitude (-180 to 180)';
|
|
||||||
document.getElementById('locPromptGpsStatus').style.color = 'var(--accent-red, #ff4444)';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window.ObserverLocation) {
|
|
||||||
ObserverLocation.setShared({ lat: lat, lon: lon });
|
|
||||||
}
|
|
||||||
localStorage.removeItem('locationPromptSkipped');
|
|
||||||
|
|
||||||
var modal = document.getElementById('locationPromptModal');
|
|
||||||
if (modal) modal.style.display = 'none';
|
|
||||||
|
|
||||||
if (typeof showNotification === 'function') {
|
|
||||||
showNotification('Location', 'Location set to ' + lat.toFixed(4) + ', ' + lon.toFixed(4));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function locationPromptSkip() {
|
|
||||||
localStorage.setItem('locationPromptSkipped', 'true');
|
|
||||||
var modal = document.getElementById('locationPromptModal');
|
|
||||||
if (modal) modal.style.display = 'none';
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- Toast Container -->
|
<!-- Toast Container -->
|
||||||
<div id="toastContainer"></div>
|
<div id="toastContainer"></div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user