unmovable.fix
parent
f472d2a6ca
commit
2e1734f5ea
628
app.py
628
app.py
|
|
@ -1,266 +1,406 @@
|
|||
$ErrorActionPreference = 'silentlycontinue'
|
||||
from fastapi import FastAPI, HTTPException, File, UploadFile, Form, Query, WebSocket, WebSocketDisconnect
|
||||
from pydantic import BaseModel
|
||||
import sqlite3
|
||||
import datetime
|
||||
import csv
|
||||
import markdown
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.responses import FileResponse, StreamingResponse
|
||||
import io
|
||||
import os
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from werkzeug.utils import secure_filename
|
||||
import json
|
||||
|
||||
# Формируем пароль из зашифрованных частей
|
||||
$p1 = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String("cDk4"))
|
||||
$p2 = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String("Nng="))
|
||||
$p3 = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String("Yjc4"))
|
||||
$rustdesk_pw = $p1 + $p2 + $p3
|
||||
# Создаем два экземпляра FastAPI
|
||||
web_app = FastAPI(title="Web Interface") # Для веб-интерфейса (порт 8001)
|
||||
api_app = FastAPI(title="API Endpoints") # Для API (порт 8002)
|
||||
|
||||
# Get your config string from your Web portal and Fill Below
|
||||
$rustdesk_cfg = "0nI1JnL09GclRWL0lmL0NXdy9yL6MHc0RHaiojIpBXYiwiI9gjYwBjbXVERFRXZiNEVYBjRGdHUZhUUvBVRx52dWlmenlTY6t0U1IlMLhlI6ISeltmIsISdy5CdvBXZk1Cdp5CdzVnciojI5FGblJnIsISdy5CdvBXZk1Cdp5CdzVnciojI0N3boJye"
|
||||
# Общий код для подключения к базе данных
|
||||
conn = sqlite3.connect("/db/rustdesk.db", check_same_thread=False)
|
||||
cursor = conn.cursor()
|
||||
|
||||
################################### Please Do Not Edit Below This Line #########################################
|
||||
# Проверяем и обновляем структуру таблицы 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()
|
||||
if 'note' not in columns:
|
||||
cursor.execute("ALTER TABLE installs ADD COLUMN note TEXT DEFAULT ''")
|
||||
conn.commit()
|
||||
if 'last_seen' not in columns:
|
||||
cursor.execute("ALTER TABLE installs ADD COLUMN last_seen TEXT DEFAULT NULL")
|
||||
conn.commit()
|
||||
|
||||
# Run as administrator and stays in the current directory
|
||||
if (-Not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
|
||||
if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
|
||||
Start-Process PowerShell -Verb RunAs -ArgumentList "-NoProfile -ExecutionPolicy Bypass -Command `"cd '$pwd'; & '$PSCommandPath';`"";
|
||||
Exit;
|
||||
# Создаем таблицы
|
||||
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',
|
||||
note TEXT DEFAULT '',
|
||||
last_seen TEXT DEFAULT NULL,
|
||||
FOREIGN KEY (folder_id) REFERENCES folders(id)
|
||||
)
|
||||
""")
|
||||
conn.commit()
|
||||
|
||||
# Проверяем/создаем папку "Несортированные" и получаем её ID
|
||||
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]
|
||||
|
||||
# Папка для загрузки изображений
|
||||
UPLOAD_FOLDER = "/app/uploads"
|
||||
if not os.path.exists(UPLOAD_FOLDER):
|
||||
os.makedirs(UPLOAD_FOLDER)
|
||||
|
||||
# Монтируем папку uploads для доступа к изображениям
|
||||
api_app.mount("/uploads", StaticFiles(directory=UPLOAD_FOLDER), name="uploads")
|
||||
web_app.mount("/uploads", StaticFiles(directory=UPLOAD_FOLDER), name="uploads")
|
||||
|
||||
# Модели данных
|
||||
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'
|
||||
note: str | None = ''
|
||||
last_seen: str | None = None
|
||||
|
||||
# Функция форматирования времени
|
||||
def format_time(time_str):
|
||||
if not time_str:
|
||||
return None
|
||||
try:
|
||||
dt = datetime.datetime.strptime(time_str, "%Y-%m-%dT%H:%M:%S.%fZ")
|
||||
return dt.strftime("%Y-%m-%d %H:%M:%S")
|
||||
except ValueError:
|
||||
try:
|
||||
dt = datetime.datetime.strptime(time_str, "%Y-%m-%d %H:%M:%S")
|
||||
return dt.strftime("%Y-%m-%d %H:%M:%S")
|
||||
except ValueError:
|
||||
return time_str
|
||||
|
||||
# Монтируем папки templates и icons
|
||||
web_app.mount("/templates", StaticFiles(directory="templates"), name="templates")
|
||||
web_app.mount("/icons", StaticFiles(directory="templates/icons"), name="icons")
|
||||
|
||||
# Веб-интерфейс
|
||||
@web_app.get("/")
|
||||
async def root():
|
||||
return FileResponse("templates/index.html")
|
||||
|
||||
# WebSocket для отправки обновлений статуса
|
||||
class ConnectionManager:
|
||||
def __init__(self):
|
||||
self.active_connections: list[WebSocket] = []
|
||||
self.max_connections = 100 # Ограничение числа подключений
|
||||
|
||||
async def connect(self, websocket: WebSocket):
|
||||
if len(self.active_connections) >= self.max_connections:
|
||||
await websocket.close(code=1008, reason="Too many connections")
|
||||
return
|
||||
await websocket.accept()
|
||||
self.active_connections.append(websocket)
|
||||
|
||||
def disconnect(self, websocket: WebSocket):
|
||||
self.active_connections.remove(websocket)
|
||||
|
||||
async def broadcast(self, message: str):
|
||||
for connection in self.active_connections[:]: # Копируем список для безопасного удаления
|
||||
await connection.send_text(message)
|
||||
|
||||
manager = ConnectionManager()
|
||||
|
||||
@api_app.websocket("/ws")
|
||||
async def websocket_endpoint(websocket: WebSocket):
|
||||
await manager.connect(websocket)
|
||||
try:
|
||||
while True:
|
||||
data = await websocket.receive_text()
|
||||
except WebSocketDisconnect:
|
||||
manager.disconnect(websocket)
|
||||
|
||||
# API-эндпоинты
|
||||
@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]
|
||||
|
||||
@api_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}
|
||||
|
||||
@api_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"}
|
||||
|
||||
@api_app.delete("/api/folders/{folder_id}")
|
||||
def delete_folder(folder_id: int):
|
||||
cursor.execute("SELECT name FROM folders WHERE id = ?", (folder_id,))
|
||||
folder_name = cursor.fetchone()
|
||||
if folder_name and folder_name[0] == 'Несортированные':
|
||||
raise HTTPException(status_code=403, detail="Папка 'Несортированные' не может быть удалена")
|
||||
|
||||
cursor.execute("DELETE FROM folders WHERE id = ?", (folder_id,))
|
||||
conn.commit()
|
||||
if cursor.rowcount == 0:
|
||||
raise HTTPException(status_code=404, detail="Папка не найдена")
|
||||
return {"status": "success"}
|
||||
|
||||
@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, i.note, i.last_seen
|
||||
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": format_time(row[3]),
|
||||
"folder_id": row[4], "folder_name": row[5], "protocol": row[6], "note": row[7], "last_seen": row[8]}
|
||||
for row in rows]
|
||||
|
||||
@api_app.post("/api/install")
|
||||
async def add_install(data: InstallData):
|
||||
rust_id = data.rust_id
|
||||
computer_name = data.computer_name or f"PC_{rust_id}"
|
||||
install_time = data.install_time or datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
protocol = data.protocol or 'rustdesk'
|
||||
note = data.note or ''
|
||||
last_seen = data.last_seen or datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
# Проверяем, существует ли запись с таким rust_id
|
||||
cursor.execute("SELECT id, folder_id, protocol, note FROM installs WHERE rust_id = ?", (rust_id,))
|
||||
existing = cursor.fetchone()
|
||||
|
||||
if existing:
|
||||
# Если запись существует, используем текущий folder_id из базы данных
|
||||
current_folder_id = existing[1] # Текущий folder_id
|
||||
current_protocol = existing[2] # Текущий protocol
|
||||
current_note = existing[3] # Текущая заметка
|
||||
|
||||
# Обновляем запись, сохраняя существующий folder_id
|
||||
cursor.execute("""
|
||||
UPDATE installs
|
||||
SET computer_name = ?, install_time = ?, protocol = ?, note = ?, last_seen = ?
|
||||
WHERE rust_id = ?
|
||||
""", (computer_name, install_time, current_protocol, current_note, last_seen, rust_id))
|
||||
else:
|
||||
# Если записи нет, создаем новую, используя folder_id из запроса или "Несортированные"
|
||||
folder_id = data.folder_id if data.folder_id is not None else unsorted_folder_id
|
||||
cursor.execute("""
|
||||
INSERT INTO installs (rust_id, computer_name, install_time, folder_id, protocol, note, last_seen)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
""", (rust_id, computer_name, install_time, folder_id, protocol, note, last_seen))
|
||||
|
||||
conn.commit()
|
||||
|
||||
# Получаем обновленную запись для отправки через WebSocket
|
||||
cursor.execute("""
|
||||
SELECT id, rust_id, computer_name, install_time, folder_id, protocol, note, last_seen
|
||||
FROM installs WHERE rust_id = ?
|
||||
""", (rust_id,))
|
||||
updated_install = cursor.fetchone()
|
||||
install_data = {
|
||||
"id": updated_install[0],
|
||||
"rust_id": updated_install[1],
|
||||
"computer_name": updated_install[2],
|
||||
"install_time": format_time(updated_install[3]),
|
||||
"folder_id": updated_install[4], # Используем folder_id из базы
|
||||
"protocol": updated_install[5],
|
||||
"note": updated_install[6],
|
||||
"last_seen": updated_install[7]
|
||||
}
|
||||
}
|
||||
# Отправляем обновленную запись через WebSocket
|
||||
await manager.broadcast(json.dumps({"type": "update", "data": install_data}))
|
||||
|
||||
# Проверка наличия установленного RustDesk
|
||||
$rustdeskInstalled = Test-Path "$env:ProgramFiles\RustDesk\rustdesk.exe"
|
||||
$rdver = ((Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\RustDesk\" -ErrorAction SilentlyContinue).Version)
|
||||
return {"status": "success"}
|
||||
|
||||
if ($rustdeskInstalled -and $rdver) {
|
||||
echo "RustDesk $rdver is already installed. Importing configuration..."
|
||||
cd $env:ProgramFiles\RustDesk
|
||||
.\rustdesk.exe --config $rustdesk_cfg
|
||||
.\rustdesk.exe --password $rustdesk_pw
|
||||
} else {
|
||||
$localRustDesk = Join-Path $PSScriptRoot "rustdesk.exe"
|
||||
$rustdeskExistsLocally = Test-Path $localRustDesk
|
||||
@api_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, note 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]
|
||||
new_note = data.note if data.note is not None else current[5]
|
||||
|
||||
if (-not $rustdeskExistsLocally) {
|
||||
$url = 'https://www.github.com//rustdesk/rustdesk/releases/latest'
|
||||
$request = [System.Net.WebRequest]::Create($url)
|
||||
$response = $request.GetResponse()
|
||||
$realTagUrl = $response.ResponseUri.OriginalString
|
||||
$RDLATEST = $realTagUrl.split('/')[-1].Trim('v')
|
||||
echo "RustDesk $RDLATEST is the latest version."
|
||||
} else {
|
||||
$RDLATEST = "local"
|
||||
if new_install_time:
|
||||
try:
|
||||
datetime.datetime.strptime(new_install_time, "%Y-%m-%d %H:%M:%S")
|
||||
except ValueError:
|
||||
raise HTTPException(status_code=400, detail="Неверный формат времени. Используйте YYYY-MM-DD HH:MM:SS")
|
||||
else:
|
||||
new_install_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
cursor.execute("""
|
||||
UPDATE installs
|
||||
SET rust_id = ?, computer_name = ?, install_time = ?, folder_id = ?, protocol = ?, note = ?
|
||||
WHERE id = ?
|
||||
""", (new_rust_id, new_computer_name, new_install_time, new_folder_id, new_protocol, new_note, install_id))
|
||||
conn.commit()
|
||||
return {"status": "success"}
|
||||
|
||||
@api_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"}
|
||||
|
||||
@api_app.get("/api/export/csv")
|
||||
async def export_csv(folder_id: int | None = Query(None, description="ID папки для экспорта, если None - экспортировать все папки")):
|
||||
if folder_id:
|
||||
cursor.execute("""
|
||||
SELECT i.rust_id, i.computer_name, i.install_time, f.name as folder_name, i.protocol, i.note, i.last_seen
|
||||
FROM installs i
|
||||
LEFT JOIN folders f ON i.folder_id = f.id
|
||||
WHERE i.folder_id = ?
|
||||
""", (folder_id,))
|
||||
else:
|
||||
cursor.execute("""
|
||||
SELECT i.rust_id, i.computer_name, i.install_time, f.name as folder_name, i.protocol, i.note, i.last_seen
|
||||
FROM installs i
|
||||
LEFT JOIN folders f ON i.folder_id = f.id
|
||||
""")
|
||||
rows = cursor.fetchall()
|
||||
|
||||
output = io.StringIO()
|
||||
writer = csv.writer(output, lineterminator='\n')
|
||||
writer.writerow(['ID подключения', 'Имя компьютера', 'Время установки', 'Папка', 'Протокол', 'Заметка', 'Последнее подключение'])
|
||||
for row in rows:
|
||||
install_time = format_time(row[2]) if row[2] else ""
|
||||
last_seen = format_time(row[6]) if row[6] else ""
|
||||
writer.writerow([row[0], row[1], install_time, row[3], row[4], row[5], last_seen])
|
||||
|
||||
headers = {
|
||||
'Content-Disposition': 'attachment; filename="rustdesk_data.csv"',
|
||||
'Content-Type': 'text/csv'
|
||||
}
|
||||
return StreamingResponse(iter([output.getvalue()]), headers=headers)
|
||||
|
||||
if (!(Test-Path C:\ProgramData\RustDesk)) {
|
||||
New-Item -ItemType Directory -Force -Path C:\ProgramData\RustDesk > null
|
||||
}
|
||||
@api_app.post("/api/import/csv")
|
||||
async def import_csv(file: UploadFile = File(...), folder_id: int | None = Query(None, description="ID папки для импорта, если None - использовать 'Несортированные'")):
|
||||
try:
|
||||
contents = await file.read()
|
||||
csv_data = io.StringIO(contents.decode('utf-8'))
|
||||
reader = csv.DictReader(csv_data)
|
||||
|
||||
cd C:\ProgramData\RustDesk
|
||||
target_folder_id = folder_id if folder_id is not None else unsorted_folder_id
|
||||
|
||||
if ($rustdeskExistsLocally) {
|
||||
echo "Found local rustdesk.exe, using it for installation."
|
||||
Copy-Item -Path $localRustDesk -Destination ".\rustdesk.exe" -Force
|
||||
} else {
|
||||
echo "Downloading RustDesk version $RDLATEST."
|
||||
powershell Invoke-WebRequest "https://github.com/rustdesk/rustdesk/releases/download/$RDLATEST/rustdesk-$RDLATEST-x86_64.exe" -Outfile "rustdesk.exe"
|
||||
}
|
||||
for row in reader:
|
||||
rust_id = row['ID подключения']
|
||||
computer_name = row['Имя компьютера']
|
||||
install_time = row['Время установки']
|
||||
folder_name = row.get('Папка', None)
|
||||
protocol = row.get('Протокол', 'rustdesk')
|
||||
note = row.get('Заметка', '')
|
||||
|
||||
echo "Installing RustDesk."
|
||||
Start-Process .\rustdesk.exe --silent-install
|
||||
Start-Sleep -Seconds 10
|
||||
cursor.execute("SELECT id FROM installs WHERE rust_id = ?", (rust_id,))
|
||||
if cursor.fetchone():
|
||||
continue
|
||||
|
||||
$ServiceName = 'rustdesk'
|
||||
$arrService = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
|
||||
if install_time:
|
||||
try:
|
||||
dt = datetime.datetime.strptime(install_time, "%Y-%m-%d %H:%M:%S")
|
||||
install_time = dt.strftime("%Y-%m-%d %H:%M:%S")
|
||||
except ValueError:
|
||||
try:
|
||||
dt = datetime.datetime.strptime(install_time, "%Y-%m-%dT%H:%M:%S.%fZ")
|
||||
install_time = dt.strftime("%Y-%m-%d %H:%M:%S")
|
||||
except ValueError:
|
||||
raise HTTPException(status_code=400, detail=f"Неверный формат времени для записи с ID {rust_id}. Используйте YYYY-MM-DD HH:MM:SS или ISO 8601")
|
||||
|
||||
if ($arrService -eq $null) {
|
||||
echo "Installing service."
|
||||
cd $env:ProgramFiles\RustDesk
|
||||
Start-Process .\rustdesk.exe --install-service -wait -Verbose
|
||||
Start-Sleep -Seconds 20
|
||||
}
|
||||
if folder_name:
|
||||
cursor.execute("SELECT id FROM folders WHERE name = ?", (folder_name,))
|
||||
folder = cursor.fetchone()
|
||||
folder_id = folder[0] if folder else unsorted_folder_id
|
||||
else:
|
||||
folder_id = target_folder_id
|
||||
|
||||
while ($arrService.Status -ne 'Running') {
|
||||
Start-Service $ServiceName
|
||||
Start-Sleep -seconds 5
|
||||
$arrService.Refresh()
|
||||
}
|
||||
cursor.execute("""
|
||||
INSERT INTO installs (rust_id, computer_name, install_time, folder_id, protocol, note)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
""", (rust_id, computer_name, install_time, folder_id, protocol, note))
|
||||
|
||||
conn.commit()
|
||||
return {"status": "success", "message": "Данные успешно импортированы"}
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=400, detail=f"Ошибка импорта: {str(e)}")
|
||||
|
||||
echo "Please wait a few seconds."
|
||||
Start-Sleep -Seconds 10
|
||||
Remove-Item -Path "C:\ProgramData\RustDesk\rustdesk.exe" -Force
|
||||
echo "Temporary installation files have been cleaned up."
|
||||
cd $env:ProgramFiles\RustDesk
|
||||
echo "Inputting configuration now."
|
||||
.\rustdesk.exe --config $rustdesk_cfg
|
||||
.\rustdesk.exe --password $rustdesk_pw
|
||||
}
|
||||
@api_app.post("/api/upload-image")
|
||||
async def upload_image(install_id: int = Form(...), file: UploadFile = File(...)):
|
||||
if not file.filename:
|
||||
raise HTTPException(status_code=400, detail="No file provided")
|
||||
|
||||
allowed_extensions = {'png', 'jpg', 'jpeg', 'gif'}
|
||||
if not secure_filename(file.filename).rsplit('.', 1)[1].lower() in allowed_extensions:
|
||||
raise HTTPException(status_code=400, detail="Invalid file format. Use png, jpg, jpeg, or gif")
|
||||
|
||||
# Добавляем папку RustDesk в исключения Windows Defender
|
||||
$defenderPath = "C:\Program Files\RustDesk"
|
||||
try {
|
||||
Add-MpPreference -ExclusionPath $defenderPath -ErrorAction Stop
|
||||
echo "Added $defenderPath to Windows Defender exclusions."
|
||||
} catch {
|
||||
echo "Failed to add $defenderPath to Windows Defender exclusions: $_"
|
||||
}
|
||||
filename = secure_filename(f"{install_id}_{file.filename}")
|
||||
file_path = os.path.join(UPLOAD_FOLDER, filename)
|
||||
|
||||
# Удаляем ярлык с общего рабочего стола
|
||||
$publicDesktop = "C:\Users\Public\Desktop\RustDesk.lnk"
|
||||
if (Test-Path $publicDesktop) {
|
||||
Remove-Item -Path $publicDesktop -Force
|
||||
echo "Removed RustDesk shortcut from Public Desktop."
|
||||
}
|
||||
with open(file_path, "wb") as buffer:
|
||||
buffer.write(await file.read())
|
||||
|
||||
# Создаем папку RustDesk в меню Пуск под Critical Fixes
|
||||
$startMenuPath = "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Critical Fixes\RustDesk"
|
||||
if (!(Test-Path $startMenuPath)) {
|
||||
New-Item -ItemType Directory -Force -Path $startMenuPath
|
||||
}
|
||||
url = f"/uploads/{filename}"
|
||||
return {"url": url}
|
||||
|
||||
$shortcutPath = "$startMenuPath\RustDesk.lnk"
|
||||
$shell = New-Object -ComObject WScript.Shell
|
||||
$shortcut = $shell.CreateShortcut($shortcutPath)
|
||||
$shortcut.TargetPath = "$env:ProgramFiles\RustDesk\rustdesk.exe"
|
||||
$shortcut.Save()
|
||||
echo "Created RustDesk shortcut in Start Menu under Critical Fixes\RustDesk."
|
||||
# CORS для API
|
||||
api_app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["https://rd.it-depot.ru"], # Обновлено для HTTPS
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
# Удаляем папку RustDesk из корня Programs
|
||||
$rustDeskStartMenu = "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\RustDesk"
|
||||
if (Test-Path $rustDeskStartMenu) {
|
||||
Remove-Item -Path $rustDeskStartMenu -Recurse -Force
|
||||
echo "Removed RustDesk folder from Start Menu Programs."
|
||||
}
|
||||
|
||||
# Добавляем параметры в конфигурационные файлы
|
||||
$configPath = "$env:USERPROFILE\AppData\Roaming\RustDesk\config"
|
||||
$config2Path = "$configPath\RustDesk2.toml"
|
||||
$configLocalPath = "$configPath\RustDesk_local.toml"
|
||||
|
||||
if (!(Test-Path $configPath)) {
|
||||
New-Item -ItemType Directory -Force -Path $configPath
|
||||
}
|
||||
|
||||
if (!(Test-Path $config2Path)) {
|
||||
"[options]`nallow-remote-config-modification = 'Y'" | Out-File -FilePath $config2Path -Encoding utf8
|
||||
} else {
|
||||
$content = Get-Content $config2Path
|
||||
if (!($content -match "allow-remote-config-modification")) {
|
||||
if ($content -match "\[options\]") {
|
||||
$content = $content -replace "\[options\]", "[options]`nallow-remote-config-modification = 'Y'"
|
||||
} else {
|
||||
$content += "`n[options]`nallow-remote-config-modification = 'Y'"
|
||||
}
|
||||
$content | Out-File -FilePath $config2Path -Encoding utf8
|
||||
}
|
||||
}
|
||||
|
||||
if (!(Test-Path $configLocalPath)) {
|
||||
"[options]`ntheme = 'dark'" | Out-File -FilePath $configLocalPath -Encoding utf8
|
||||
} else {
|
||||
$content = Get-Content $configLocalPath
|
||||
if (!($content -match "theme")) {
|
||||
if ($content -match "\[options\]") {
|
||||
$content = $content -replace "\[options\]", "[options]`ntheme = 'dark'"
|
||||
} else {
|
||||
$content += "`n[options]`ntheme = 'dark'"
|
||||
}
|
||||
$content | Out-File -FilePath $configLocalPath -Encoding utf8
|
||||
}
|
||||
}
|
||||
|
||||
# Создание BAT-файла для удаления
|
||||
$uninstallBatPath = "$env:ProgramFiles\RustDesk\Uninstall RustDesk.bat"
|
||||
$uninstallBatContent = @"
|
||||
@echo off
|
||||
echo Stopping RustDeskOnlineCheck task...
|
||||
schtasks /End /TN "RustDeskOnlineCheck"
|
||||
timeout /t 2 >nul
|
||||
echo Deleting RustDeskOnlineCheck task...
|
||||
schtasks /Delete /TN "RustDeskOnlineCheck" /F
|
||||
echo Stopping RustDesk service...
|
||||
sc stop rustdesk
|
||||
timeout /t 2 >nul
|
||||
echo Uninstalling RustDesk...
|
||||
"C:\Program Files\RustDesk\rustdesk.exe" --uninstall
|
||||
echo Cleaning up files...
|
||||
rd /s /q "C:\ProgramData\RustDesk"
|
||||
rd /s /q "%appdata%\RustDesk"
|
||||
rd /s /q "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Critical Fixes\RustDesk"
|
||||
echo Removing Windows Defender exclusion...
|
||||
powershell -Command "Remove-MpPreference -ExclusionPath 'C:\Program Files\RustDesk'" 2>nul
|
||||
echo RustDesk has been completely removed.
|
||||
pause
|
||||
"@
|
||||
|
||||
# Удаляем существующий ярлык Uninstall RustDesk, если он есть
|
||||
$uninstallLnkPath = "$env:ProgramFiles\RustDesk\Uninstall RustDesk.lnk"
|
||||
if (Test-Path $uninstallLnkPath) {
|
||||
Remove-Item -Path $uninstallLnkPath -Force
|
||||
echo "Removed original Uninstall RustDesk shortcut."
|
||||
}
|
||||
|
||||
# Создаем BAT-файл в папке RustDesk
|
||||
$uninstallBatContent | Out-File -FilePath $uninstallBatPath -Encoding ASCII
|
||||
echo "Created Uninstall RustDesk.bat in $env:ProgramFiles\RustDesk"
|
||||
|
||||
# Копируем BAT-файл в Critical Fixes\RustDesk
|
||||
Copy-Item -Path $uninstallBatPath -Destination "$startMenuPath\Uninstall RustDesk.bat" -Force
|
||||
echo "Copied Uninstall RustDesk.bat to $startMenuPath"
|
||||
|
||||
$rustdesk_id = .\rustdesk.exe --get-id | Write-Output -OutVariable rustdesk_id
|
||||
echo "All done! Please double check the Network settings tab in RustDesk."
|
||||
echo ""
|
||||
echo "..............................................."
|
||||
echo "RustDesk ID: $rustdesk_id"
|
||||
$RustID = $rustdesk_id
|
||||
$ComputerName = $env:COMPUTERNAME
|
||||
$InstallTime = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
|
||||
$ServerURL = "https://rd.it-depot.ru/api/install"
|
||||
$Body = @{
|
||||
"rust_id" = $RustID
|
||||
"computer_name" = $ComputerName
|
||||
"install_time" = $InstallTime
|
||||
} | ConvertTo-Json -Compress
|
||||
|
||||
Invoke-RestMethod -Uri $ServerURL -Method Post -Body $Body -ContentType "application/json"
|
||||
echo "Initial entry added to address book."
|
||||
echo "..............................................."
|
||||
echo ""
|
||||
|
||||
# Создание скрипта для проверки онлайн-статуса
|
||||
$checkScriptPath = "C:\ProgramData\RustDesk\RustDeskOnlineCheck.ps1"
|
||||
$checkScriptContent = @"
|
||||
`$ErrorActionPreference = 'SilentlyContinue'
|
||||
`$RustID = "$RustID"
|
||||
`$ComputerName = "$ComputerName"
|
||||
`$InstallTime = "$InstallTime"
|
||||
`$ServerURL = "https://rd.it-depot.ru/api/install"
|
||||
|
||||
while (`$true) {
|
||||
`$Body = @{
|
||||
`"rust_id`" = `$RustID
|
||||
`"computer_name`" = `$ComputerName
|
||||
`"install_time`" = `$InstallTime
|
||||
`"last_seen`" = (Get-Date -Format `"yyyy-MM-dd HH:mm:ss`")
|
||||
} | ConvertTo-Json -Compress
|
||||
try {
|
||||
Invoke-RestMethod -Uri `$ServerURL -Method Post -Body `$Body -ContentType `"application/json`" -ErrorAction Stop
|
||||
Write-Host "Online ping sent for ID `$RustID at `(Get-Date -Format 'HH:mm:ss')" -ForegroundColor Green
|
||||
}
|
||||
catch {
|
||||
Write-Host "Error sending online ping: `$_" -ForegroundColor Red
|
||||
}
|
||||
Start-Sleep -Seconds 30
|
||||
}
|
||||
"@
|
||||
$checkScriptContent | Out-File -FilePath $checkScriptPath -Encoding UTF8
|
||||
echo "Created online check script at $checkScriptPath"
|
||||
|
||||
# Создание задания в Планировщике задач
|
||||
$taskName = "RustDeskOnlineCheck"
|
||||
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$checkScriptPath`""
|
||||
$trigger = New-ScheduledTaskTrigger -AtStartup
|
||||
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable
|
||||
|
||||
Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -Settings $settings -User "SYSTEM" -RunLevel Highest -Force
|
||||
echo "Scheduled task '$taskName' created to check online status at system startup."
|
||||
|
||||
Start-ScheduledTask -TaskName $taskName
|
||||
echo "Scheduled task '$taskName' has been started."
|
||||
|
||||
echo "Press Enter to open RustDesk."
|
||||
pause
|
||||
.\rustdesk.exe
|
||||
# CORS для веб-интерфейса
|
||||
web_app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["https://rd.it-depot.ru"], # Обновлено для HTTPS
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
Loading…
Reference in New Issue