from fastapi import FastAPI, HTTPException from pydantic import BaseModel import sqlite3 import datetime from fastapi.staticfiles import StaticFiles from fastapi.responses import FileResponse app = FastAPI() # Соединение с базой данных conn = sqlite3.connect("/db/rustdesk.db", check_same_thread=False) cursor = conn.cursor() # Проверяем и обновляем структуру таблицы installs cursor.execute("PRAGMA table_info(installs)") columns = [row[1] for row in cursor.fetchall()] if 'protocol' not in columns: cursor.execute("ALTER TABLE installs ADD COLUMN protocol TEXT DEFAULT 'rustdesk'") conn.commit() # Создаем таблицы (добавляем поле protocol, если таблицы нет) cursor.execute(""" CREATE TABLE IF NOT EXISTS folders ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, parent_id INTEGER, FOREIGN KEY (parent_id) REFERENCES folders(id) ) """) cursor.execute(""" CREATE TABLE IF NOT EXISTS installs ( id INTEGER PRIMARY KEY AUTOINCREMENT, rust_id TEXT, computer_name TEXT, install_time TEXT, folder_id INTEGER, protocol TEXT DEFAULT 'rustdesk', FOREIGN KEY (folder_id) REFERENCES folders(id) ) """) conn.commit() # Проверяем/создаем папку "Несортированные" cursor.execute("SELECT id FROM folders WHERE name = 'Несортированные'") unsorted_folder = cursor.fetchone() if not unsorted_folder: cursor.execute("INSERT INTO folders (name) VALUES ('Несортированные')") conn.commit() unsorted_folder_id = cursor.lastrowid else: unsorted_folder_id = unsorted_folder[0] # Модели данных class Folder(BaseModel): name: str parent_id: int | None = None class FolderUpdate(BaseModel): name: str class InstallData(BaseModel): rust_id: str | None = None computer_name: str | None = None install_time: str | None = None folder_id: int | None = None protocol: str | None = 'rustdesk' # По умолчанию RustDesk # Монтируем папку templates как статические файлы app.mount("/templates", StaticFiles(directory="templates"), name="templates") # Главная страница @app.get("/") async def root(): return FileResponse("templates/index.html") # --- Folders API --- @app.get("/api/folders") def get_folders(): cursor.execute("SELECT * FROM folders") rows = cursor.fetchall() return [{"id": row[0], "name": row[1], "parent_id": row[2]} for row in rows] @app.post("/api/folders") def add_folder(folder: Folder): cursor.execute("INSERT INTO folders (name, parent_id) VALUES (?, ?)", (folder.name, folder.parent_id)) conn.commit() return {"status": "success", "id": cursor.lastrowid} @app.put("/api/folders/{folder_id}") def update_folder(folder_id: int, folder: FolderUpdate): cursor.execute("UPDATE folders SET name = ? WHERE id = ?", (folder.name, folder_id)) conn.commit() if cursor.rowcount == 0: raise HTTPException(status_code=404, detail="Папка не найдена") return {"status": "success"} @app.delete("/api/folders/{folder_id}") def delete_folder(folder_id: int): cursor.execute("DELETE FROM folders WHERE id = ?", (folder_id,)) conn.commit() if cursor.rowcount == 0: raise HTTPException(status_code=404, detail="Папка не найдена") return {"status": "success"} # --- Installs API --- @app.get("/api/installs") def get_installs(): cursor.execute(""" SELECT i.id, i.rust_id, i.computer_name, i.install_time, i.folder_id, f.name as folder_name, i.protocol FROM installs i LEFT JOIN folders f ON i.folder_id = f.id """) rows = cursor.fetchall() return [{"id": row[0], "rust_id": row[1], "computer_name": row[2], "install_time": row[3], "folder_id": row[4], "folder_name": row[5], "protocol": row[6]} for row in rows] @app.post("/api/install") def add_install(data: InstallData): install_time = data.install_time or datetime.datetime.now().isoformat() folder_id = data.folder_id if data.folder_id is not None else unsorted_folder_id protocol = data.protocol or 'rustdesk' # По умолчанию RustDesk для POST-запросов cursor.execute("INSERT INTO installs (rust_id, computer_name, install_time, folder_id, protocol) VALUES (?, ?, ?, ?, ?)", (data.rust_id, data.computer_name, install_time, folder_id, protocol)) conn.commit() return {"status": "success"} @app.put("/api/install/{install_id}") def update_install(install_id: int, data: InstallData): cursor.execute("SELECT rust_id, computer_name, install_time, folder_id, protocol FROM installs WHERE id = ?", (install_id,)) current = cursor.fetchone() if not current: raise HTTPException(status_code=404, detail="Запись не найдена") new_rust_id = data.rust_id if data.rust_id is not None else current[0] new_computer_name = data.computer_name if data.computer_name is not None else current[1] new_install_time = data.install_time if data.install_time is not None else current[2] new_folder_id = data.folder_id if data.folder_id is not None else current[3] new_protocol = data.protocol if data.protocol is not None else current[4] cursor.execute(""" UPDATE installs SET rust_id = ?, computer_name = ?, install_time = ?, folder_id = ?, protocol = ? WHERE id = ? """, (new_rust_id, new_computer_name, new_install_time, new_folder_id, new_protocol, install_id)) conn.commit() return {"status": "success"} @app.delete("/api/install/{install_id}") def delete_install(install_id: int): cursor.execute("DELETE FROM installs WHERE id = ?", (install_id,)) conn.commit() if cursor.rowcount == 0: raise HTTPException(status_code=404, detail="Запись не найдена") return {"status": "success"} # CORS from fastapi.middleware.cors import CORSMiddleware app.add_middleware( CORSMiddleware, allow_origins=["http://10.0.0.10:8001", "http://localhost:8001"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], )