new changes
This commit is contained in:
@@ -1,4 +1,9 @@
|
|||||||
"""YakPanel - App Store / Software API"""
|
"""YakPanel - App Store / Software API"""
|
||||||
|
import asyncio
|
||||||
|
import os
|
||||||
|
import shlex
|
||||||
|
import subprocess
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, HTTPException
|
from fastapi import APIRouter, Depends, HTTPException
|
||||||
|
|
||||||
from app.core.utils import exec_shell_sync
|
from app.core.utils import exec_shell_sync
|
||||||
@@ -26,6 +31,31 @@ SOFTWARE_LIST = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def _apt_env() -> dict[str, str]:
|
||||||
|
env = os.environ.copy()
|
||||||
|
env.setdefault("DEBIAN_FRONTEND", "noninteractive")
|
||||||
|
env.setdefault("APT_LISTCHANGES_FRONTEND", "none")
|
||||||
|
return env
|
||||||
|
|
||||||
|
|
||||||
|
def _run_apt_shell(script: str, timeout: int) -> None:
|
||||||
|
"""Run apt/dpkg shell snippet; raise HTTPException if command fails."""
|
||||||
|
result = subprocess.run(
|
||||||
|
script,
|
||||||
|
shell=True,
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
timeout=timeout,
|
||||||
|
env=_apt_env(),
|
||||||
|
)
|
||||||
|
if result.returncode == 0:
|
||||||
|
return
|
||||||
|
out = (result.stdout or "").strip()
|
||||||
|
err = (result.stderr or "").strip()
|
||||||
|
msg = err or out or f"Command failed (exit {result.returncode})"
|
||||||
|
raise HTTPException(status_code=500, detail=msg[:4000])
|
||||||
|
|
||||||
|
|
||||||
def _check_installed(pkg: str) -> tuple[bool, str]:
|
def _check_installed(pkg: str) -> tuple[bool, str]:
|
||||||
"""Check if package is installed. Returns (installed, version_or_error)."""
|
"""Check if package is installed. Returns (installed, version_or_error)."""
|
||||||
out, err = exec_shell_sync(f"dpkg -l {pkg} 2>/dev/null | grep ^ii", timeout=5)
|
out, err = exec_shell_sync(f"dpkg -l {pkg} 2>/dev/null | grep ^ii", timeout=5)
|
||||||
@@ -60,9 +90,8 @@ async def soft_install(
|
|||||||
pkg = next((s["pkg"] for s in SOFTWARE_LIST if s["id"] == pkg_id), None)
|
pkg = next((s["pkg"] for s in SOFTWARE_LIST if s["id"] == pkg_id), None)
|
||||||
if not pkg:
|
if not pkg:
|
||||||
raise HTTPException(status_code=404, detail="Package not found")
|
raise HTTPException(status_code=404, detail="Package not found")
|
||||||
out, err = exec_shell_sync(f"apt-get update && apt-get install -y {pkg}", timeout=300)
|
quoted = shlex.quote(pkg)
|
||||||
if err and "error" in err.lower() and "E: " in err:
|
_run_apt_shell(f"apt-get update -qq && apt-get install -y {quoted}", timeout=600)
|
||||||
raise HTTPException(status_code=500, detail=err.strip() or out.strip())
|
|
||||||
return {"status": True, "msg": "Installed"}
|
return {"status": True, "msg": "Installed"}
|
||||||
|
|
||||||
|
|
||||||
@@ -75,7 +104,6 @@ async def soft_uninstall(
|
|||||||
pkg = next((s["pkg"] for s in SOFTWARE_LIST if s["id"] == pkg_id), None)
|
pkg = next((s["pkg"] for s in SOFTWARE_LIST if s["id"] == pkg_id), None)
|
||||||
if not pkg:
|
if not pkg:
|
||||||
raise HTTPException(status_code=404, detail="Package not found")
|
raise HTTPException(status_code=404, detail="Package not found")
|
||||||
out, err = exec_shell_sync(f"apt-get remove -y {pkg}", timeout=120)
|
quoted = shlex.quote(pkg)
|
||||||
if err and "error" in err.lower() and "E: " in err:
|
await asyncio.to_thread(_run_apt_shell, f"apt-get remove -y {quoted}", 180)
|
||||||
raise HTTPException(status_code=500, detail=err.strip() or out.strip())
|
|
||||||
return {"status": True, "msg": "Uninstalled"}
|
return {"status": True, "msg": "Uninstalled"}
|
||||||
|
|||||||
Reference in New Issue
Block a user