1
0
mirror of https://github.com/TheFunny/ArisuAutoSweeper synced 2026-06-10 04:44:52 +00:00

Implement FastAPI backend with REST API and basic frontend

Co-authored-by: TheFunny <26841179+TheFunny@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-11-19 08:08:41 +00:00
parent df4f3ef359
commit 4efae500d6
11 changed files with 1143 additions and 3 deletions
@@ -0,0 +1,3 @@
"""
API routes for FastAPI backend
"""
@@ -0,0 +1,119 @@
"""
Configuration management API endpoints
"""
from typing import Dict, List, Any
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from module.config.utils import alas_instance, alas_template, filepath_args, read_file
from module.webui.fake import load_config, get_config_mod
from module.webui.setting import State
from module.logger import logger
router = APIRouter()
class ConfigValue(BaseModel):
"""Config value update model"""
path: str
value: Any
@router.get("/instances")
async def get_instances():
"""Get list of all alas instances"""
return {
"instances": alas_instance(),
"templates": alas_template()
}
@router.get("/{instance_name}")
async def get_config(instance_name: str):
"""Get configuration for a specific instance"""
try:
config_obj = load_config(instance_name)
config_data = config_obj.read_file(instance_name)
mod = get_config_mod(instance_name)
# Get menu and args for this instance
menu = read_file(filepath_args("menu", mod))
args = read_file(filepath_args("args", mod))
return {
"name": instance_name,
"mod": mod,
"config": config_data,
"menu": menu,
"args": args
}
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=404, detail=f"Config not found: {instance_name}")
@router.post("/{instance_name}")
async def update_config(instance_name: str, updates: List[ConfigValue]):
"""Update configuration values"""
try:
config_obj = load_config(instance_name)
config_data = config_obj.read_file(instance_name)
# Apply updates
for update in updates:
path_parts = update.path.split(".")
# Navigate to the nested dict and update
current = config_data
for part in path_parts[:-1]:
if part not in current:
current[part] = {}
current = current[part]
current[path_parts[-1]] = update.value
# Save config
config_obj.write_file(instance_name, config_data)
logger.info(f"Updated config for {instance_name}")
return {"status": "success", "message": "Config updated"}
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=500, detail=str(e))
@router.post("/create")
async def create_instance(name: str, copy_from: str = "template-aas"):
"""Create a new alas instance"""
try:
# Validate name
if name in alas_instance():
raise HTTPException(status_code=400, detail="Instance already exists")
if set(name) & set(".\\/:*?\"'<>|"):
raise HTTPException(status_code=400, detail="Invalid characters in name")
if name.lower().startswith("template"):
raise HTTPException(status_code=400, detail="Cannot start with 'template'")
# Copy config
origin_config = load_config(copy_from).read_file(copy_from)
State.config_updater.write_file(name, origin_config, get_config_mod(copy_from))
logger.info(f"Created new instance: {name}")
return {"status": "success", "name": name}
except HTTPException:
raise
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=500, detail=str(e))
@router.delete("/{instance_name}")
async def delete_instance(instance_name: str):
"""Delete an alas instance"""
try:
# Add implementation for deleting instance
# This would need to be added based on how configs are stored
raise HTTPException(status_code=501, detail="Delete not implemented")
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=500, detail=str(e))
@@ -0,0 +1,90 @@
"""
Process management API endpoints
"""
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from typing import Optional
from module.webui.process_manager import ProcessManager
from module.webui.updater import updater
from module.logger import logger
router = APIRouter()
class ProcessCommand(BaseModel):
"""Process command model"""
task: Optional[str] = None
@router.get("/{instance_name}/status")
async def get_process_status(instance_name: str):
"""Get process status"""
try:
alas = ProcessManager.get_manager(instance_name)
return {
"name": instance_name,
"alive": alas.alive,
"state": alas.state,
"config_name": alas.config_name
}
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=404, detail=f"Process not found: {instance_name}")
@router.post("/{instance_name}/start")
async def start_process(instance_name: str, command: ProcessCommand = ProcessCommand()):
"""Start a process"""
try:
alas = ProcessManager.get_manager(instance_name)
alas.start(command.task, updater.event if command.task is None else None)
logger.info(f"Started process: {instance_name}")
return {"status": "success", "message": f"Started {instance_name}"}
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=500, detail=str(e))
@router.post("/{instance_name}/stop")
async def stop_process(instance_name: str):
"""Stop a process"""
try:
alas = ProcessManager.get_manager(instance_name)
alas.stop()
logger.info(f"Stopped process: {instance_name}")
return {"status": "success", "message": f"Stopped {instance_name}"}
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=500, detail=str(e))
@router.post("/{instance_name}/restart")
async def restart_process(instance_name: str):
"""Restart a process"""
try:
alas = ProcessManager.get_manager(instance_name)
alas.stop()
alas.start(None, updater.event)
logger.info(f"Restarted process: {instance_name}")
return {"status": "success", "message": f"Restarted {instance_name}"}
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=500, detail=str(e))
@router.get("/")
async def get_all_processes():
"""Get status of all processes"""
try:
processes = []
for name, alas in ProcessManager._processes.items():
processes.append({
"name": name,
"alive": alas.alive,
"state": alas.state
})
return {"processes": processes}
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=500, detail=str(e))
@@ -0,0 +1,115 @@
"""
System management API endpoints
"""
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from module.webui.updater import updater
from module.webui.setting import State
from module.webui import lang
from module.logger import logger
router = APIRouter()
class LanguageSetting(BaseModel):
"""Language setting model"""
language: str
class ThemeSetting(BaseModel):
"""Theme setting model"""
theme: str
@router.get("/info")
async def get_system_info():
"""Get system information"""
return {
"version": "1.0.0",
"language": lang.LANG,
"theme": State.deploy_config.Theme,
"deploy_config": {
"host": State.deploy_config.WebuiHost,
"port": State.deploy_config.WebuiPort,
"password_enabled": State.deploy_config.Password is not None,
"remote_access": State.deploy_config.EnableRemoteAccess,
}
}
@router.post("/language")
async def set_language(setting: LanguageSetting):
"""Set system language"""
try:
lang.set_language(setting.language)
State.deploy_config.Language = setting.language
return {"status": "success", "language": setting.language}
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=500, detail=str(e))
@router.post("/theme")
async def set_theme(setting: ThemeSetting):
"""Set system theme"""
try:
State.deploy_config.Theme = setting.theme
State.theme = setting.theme
return {"status": "success", "theme": setting.theme}
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=500, detail=str(e))
@router.get("/update/status")
async def get_update_status():
"""Get update status"""
try:
return {
"state": updater.state,
"branch": updater.Branch,
"local_commit": updater.get_commit(short_sha1=True),
"upstream_commit": updater.get_commit(f"origin/{updater.Branch}", short_sha1=True)
}
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=500, detail=str(e))
@router.post("/update/check")
async def check_update():
"""Check for updates"""
try:
updater.check_update()
return {"status": "success", "message": "Checking for updates"}
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=500, detail=str(e))
@router.post("/update/run")
async def run_update():
"""Run update"""
try:
updater.run_update()
return {"status": "success", "message": "Update started"}
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=500, detail=str(e))
@router.post("/restart")
async def restart_system():
"""Restart the system"""
try:
if State.restart_event is not None:
State.restart_event.set()
return {"status": "success", "message": "Restart initiated"}
else:
raise HTTPException(status_code=400, detail="Restart not enabled")
except HTTPException:
raise
except Exception as e:
logger.exception(e)
raise HTTPException(status_code=500, detail=str(e))