2025-10-14 16:04:37 +03:00
|
|
|
'''
|
|
|
|
|
File: main.py
|
|
|
|
|
Description: Веб-приложение для веб-сервера терминалов, основной файл FastAPI
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
__version__ = '0.1.0'
|
|
|
|
|
|
|
|
|
|
|
2025-10-04 15:10:53 +03:00
|
|
|
# Импортируем нужные классы из библиотек
|
2025-10-21 16:08:01 +03:00
|
|
|
from contextlib import asynccontextmanager
|
2025-10-14 23:54:26 +03:00
|
|
|
from fastapi import FastAPI, Request, Path
|
2025-10-10 10:16:59 +03:00
|
|
|
from fastapi.staticfiles import StaticFiles
|
2025-10-07 21:48:20 +03:00
|
|
|
from fastapi.responses import HTMLResponse, JSONResponse
|
2025-10-21 16:08:01 +03:00
|
|
|
from fastapi.templating import Jinja2Templates
|
|
|
|
|
from pydantic_settings import BaseSettings, JsonConfigSettingsSource, SettingsConfigDict
|
|
|
|
|
from pydantic import ConfigDict
|
|
|
|
|
import json
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from mt5_control import MT5_Control
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Config(BaseSettings):
|
|
|
|
|
terminals: list[dict]
|
|
|
|
|
model_config = SettingsConfigDict()
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def settings_customise_sources(
|
|
|
|
|
cls,
|
|
|
|
|
settings_cls,
|
|
|
|
|
init_settings,
|
|
|
|
|
env_settings,
|
|
|
|
|
dotenv_settings,
|
|
|
|
|
file_secret_settings,
|
|
|
|
|
):
|
|
|
|
|
return (
|
|
|
|
|
init_settings,
|
|
|
|
|
JsonConfigSettingsSource(settings_cls, json_file="config.json"),
|
|
|
|
|
env_settings,
|
|
|
|
|
dotenv_settings,
|
|
|
|
|
file_secret_settings,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@asynccontextmanager
|
|
|
|
|
async def lifespan(app: FastAPI):
|
|
|
|
|
print(2362323)
|
|
|
|
|
config = Config(_env_file=None)
|
|
|
|
|
app.state.terminals = {t['name']: t for t in config.terminals}
|
|
|
|
|
app.state.instances = {}
|
|
|
|
|
global control
|
|
|
|
|
control = MT5_Control(app.state.terminals)
|
|
|
|
|
yield
|
2025-10-04 15:10:53 +03:00
|
|
|
|
|
|
|
|
# Создаём объект приложения
|
2025-10-21 16:08:01 +03:00
|
|
|
app = FastAPI(lifespan=lifespan)
|
2025-10-04 15:10:53 +03:00
|
|
|
|
2025-10-14 14:59:40 +03:00
|
|
|
# Подключаем статические файлы
|
2025-10-14 16:04:37 +03:00
|
|
|
app.mount('/static', StaticFiles(directory='static'), name='static')
|
2025-10-14 14:59:40 +03:00
|
|
|
|
|
|
|
|
# Создаём объект для работы с шаблонами HTML-кода
|
2025-10-14 16:04:37 +03:00
|
|
|
templates = Jinja2Templates(directory='templates')
|
2025-10-10 10:16:59 +03:00
|
|
|
|
|
|
|
|
|
2025-10-06 23:34:05 +03:00
|
|
|
@app.get('/', response_class=HTMLResponse)
|
2025-10-10 10:16:59 +03:00
|
|
|
async def index(request: Request):
|
2025-10-14 16:04:37 +03:00
|
|
|
'''Обработчик GET / (корневой каталог) - панель управления терминалами'''
|
2025-10-21 16:08:01 +03:00
|
|
|
instances = control.load_instances()
|
|
|
|
|
# for name in instances:
|
|
|
|
|
# if instances[name]['pid']:
|
|
|
|
|
# instances[name]['info'] = control.instance_info(name)
|
|
|
|
|
# print(instances)
|
2025-10-14 16:04:37 +03:00
|
|
|
return templates.TemplateResponse('index.html', {'request': request, 'instances': instances})
|
2025-10-07 21:48:20 +03:00
|
|
|
|
2025-10-14 14:59:40 +03:00
|
|
|
|
2025-10-21 16:08:01 +03:00
|
|
|
@app.post('/instances/{name}')
|
|
|
|
|
async def info_instance(name: str = Path(..., description="Информация об экземпляре", example="MetaTrader5.1")):
|
|
|
|
|
'''Полусение информации об экземпляре терминала'''
|
|
|
|
|
result = control.instance_info(name)
|
|
|
|
|
return JSONResponse(result)
|
|
|
|
|
|
|
|
|
|
|
2025-10-14 14:12:34 +03:00
|
|
|
@app.post('/start/{name}')
|
2025-10-14 23:54:26 +03:00
|
|
|
async def start_instance(name: str = Path(..., description="Название экземпляра", example="MetaTrader5.1")):
|
|
|
|
|
'''Запуск экземпляра терминала'''
|
2025-10-21 16:08:01 +03:00
|
|
|
result = control.start_mt5(name)
|
2025-10-07 21:48:20 +03:00
|
|
|
return JSONResponse(result)
|
|
|
|
|
|
2025-10-14 14:59:40 +03:00
|
|
|
|
2025-10-14 14:12:34 +03:00
|
|
|
@app.post('/stop/{name}')
|
2025-10-14 23:54:26 +03:00
|
|
|
async def stop_instance(name: str = Path(..., description="Название экземпляра", example="MetaTrader5.1")):
|
|
|
|
|
'''Остановка экземпляра терминала'''
|
2025-10-21 16:08:01 +03:00
|
|
|
result = control.stop_mt5(name)
|
2025-10-07 21:48:20 +03:00
|
|
|
return JSONResponse(result)
|
2025-10-16 20:41:52 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.post('/create/{name}')
|
|
|
|
|
async def create_instance(name: str = Path(..., description="Название экземпляра", example="MetaTrader5.1")):
|
2025-10-21 16:08:01 +03:00
|
|
|
'''Создание экземпляра терминала'''
|
|
|
|
|
result = control.create_mt5(name)
|
|
|
|
|
return JSONResponse(result)
|