Fix robustness issues across backend and frontend
- Add shutil.which guard to _run() in settings, asi_bridge routers - Catch RuntimeError on WebSocket disconnect in services, asi_bridge - Make file listing resilient to individual entry errors - Fix keyboard double-fire on touch devices (touchstart + click) - Update install.sh with correct Gitea repo URL - Add six to requirements.txt (python-pam dependency) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f9743bb29a
commit
342dc0f0cf
7 changed files with 21 additions and 5 deletions
|
|
@ -1,6 +1,7 @@
|
|||
fastapi==0.115.6
|
||||
uvicorn[standard]==0.34.0
|
||||
python-pam==2.0.2
|
||||
six==1.17.0
|
||||
PyJWT==2.10.1
|
||||
psutil==6.1.1
|
||||
ptyprocess==0.7.0
|
||||
|
|
|
|||
|
|
@ -110,7 +110,13 @@ async def list_dir(
|
|||
entries = sorted(p.iterdir(), key=lambda x: (not x.is_dir(), x.name.lower()))
|
||||
except PermissionError:
|
||||
raise HTTPException(403, f"Permission denied: {path}")
|
||||
return [_file_info(e) for e in entries]
|
||||
results = []
|
||||
for e in entries:
|
||||
try:
|
||||
results.append(_file_info(e))
|
||||
except (OSError, PermissionError):
|
||||
continue
|
||||
return results
|
||||
|
||||
|
||||
@router.get("/info")
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@ class MountConfig(BaseModel):
|
|||
|
||||
|
||||
async def _run(cmd: list[str]) -> tuple[int, str, str]:
|
||||
import shutil
|
||||
if not shutil.which(cmd[0]):
|
||||
return 1, "", f"{cmd[0]}: command not found"
|
||||
proc = await asyncio.create_subprocess_exec(
|
||||
*cmd,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
|
|
@ -195,7 +198,7 @@ async def bridge_ws(websocket: WebSocket):
|
|||
seen_files = current_paths
|
||||
|
||||
await asyncio.sleep(5)
|
||||
except WebSocketDisconnect:
|
||||
except (WebSocketDisconnect, RuntimeError):
|
||||
pass
|
||||
except Exception:
|
||||
log.exception("ASI Bridge WS error")
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ async def service_logs(websocket: WebSocket, unit: str):
|
|||
"unit": unit,
|
||||
"line": line.decode(errors="replace").rstrip(),
|
||||
})
|
||||
except WebSocketDisconnect:
|
||||
except (WebSocketDisconnect, RuntimeError):
|
||||
pass
|
||||
except Exception:
|
||||
log.exception("log stream error for %s", unit)
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@ class TimezoneRequest(BaseModel):
|
|||
|
||||
|
||||
async def _run(cmd: list[str]) -> tuple[int, str, str]:
|
||||
import shutil
|
||||
if not shutil.which(cmd[0]):
|
||||
return 1, "", f"{cmd[0]}: command not found"
|
||||
proc = await asyncio.create_subprocess_exec(
|
||||
*cmd,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
|
|
|
|||
|
|
@ -160,12 +160,15 @@
|
|||
const btn = document.createElement('button');
|
||||
btn.className = 'osk-key ' + className;
|
||||
btn.textContent = label;
|
||||
let touchFired = false;
|
||||
btn.addEventListener('touchstart', (e) => {
|
||||
e.preventDefault();
|
||||
touchFired = true;
|
||||
handler();
|
||||
});
|
||||
btn.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
if (touchFired) { touchFired = false; return; }
|
||||
handler();
|
||||
});
|
||||
return btn;
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
#!/usr/bin/env bash
|
||||
# Atlus installer — targets DietPi, Armbian, Debian, Ubuntu
|
||||
# Usage: curl -sSL https://raw.githubusercontent.com/YOUR_REPO/atlus/main/install.sh | bash
|
||||
# Usage: curl -sSL https://git.bytestud.io/roberts/atlus/raw/branch/main/install.sh | sudo bash
|
||||
set -euo pipefail
|
||||
|
||||
INSTALL_DIR="/opt/atlus"
|
||||
CONFIG_DIR="/etc/atlus"
|
||||
DATA_DIR="/var/lib/atlus"
|
||||
SERVICE_FILE="/etc/systemd/system/atlus.service"
|
||||
REPO_URL="https://github.com/YOUR_REPO/atlus.git"
|
||||
REPO_URL="https://git.bytestud.io/roberts/atlus.git"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Helpers
|
||||
|
|
|
|||
Loading…
Reference in a new issue