refactor: 初步完成单一ws重构
This commit is contained in:
@@ -23,6 +23,7 @@ __version__ = "5.0.0"
|
|||||||
__author__ = "DLmaster361 <DLmaster_361@163.com>"
|
__author__ = "DLmaster361 <DLmaster_361@163.com>"
|
||||||
__license__ = "GPL-3.0 license"
|
__license__ = "GPL-3.0 license"
|
||||||
|
|
||||||
|
from .core import router as core_router
|
||||||
from .info import router as info_router
|
from .info import router as info_router
|
||||||
from .scripts import router as scripts_router
|
from .scripts import router as scripts_router
|
||||||
from .plan import router as plan_router
|
from .plan import router as plan_router
|
||||||
@@ -32,6 +33,7 @@ from .history import router as history_router
|
|||||||
from .setting import router as setting_router
|
from .setting import router as setting_router
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
"core_router",
|
||||||
"info_router",
|
"info_router",
|
||||||
"scripts_router",
|
"scripts_router",
|
||||||
"plan_router",
|
"plan_router",
|
||||||
|
|||||||
47
app/api/core.py
Normal file
47
app/api/core.py
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# AUTO_MAA:A MAA Multi Account Management and Automation Tool
|
||||||
|
# Copyright © 2024-2025 DLmaster361
|
||||||
|
# Copyright © 2025 MoeSnowyFox
|
||||||
|
|
||||||
|
# This file is part of AUTO_MAA.
|
||||||
|
|
||||||
|
# AUTO_MAA is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published
|
||||||
|
# by the Free Software Foundation, either version 3 of the License,
|
||||||
|
# or (at your option) any later version.
|
||||||
|
|
||||||
|
# AUTO_MAA is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||||
|
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||||
|
# the GNU General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with AUTO_MAA. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Contact: DLmaster_361@163.com
|
||||||
|
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
from fastapi import APIRouter, WebSocket, WebSocketDisconnect
|
||||||
|
|
||||||
|
from app.core import Config, Broadcast
|
||||||
|
from app.services import System
|
||||||
|
from app.models.schema import *
|
||||||
|
|
||||||
|
router = APIRouter(prefix="/api/core", tags=["核心信息"])
|
||||||
|
|
||||||
|
|
||||||
|
@router.websocket("/ws")
|
||||||
|
async def connect_websocket(websocket: WebSocket):
|
||||||
|
await websocket.accept()
|
||||||
|
Config.websocket = websocket
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
data = await asyncio.wait_for(websocket.receive_json(), timeout=30.0)
|
||||||
|
await Broadcast.put(data)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
await websocket.send_json(
|
||||||
|
WebSocketMessage(type="Signal", data={"Ping": "无描述"}).model_dump()
|
||||||
|
)
|
||||||
|
except WebSocketDisconnect:
|
||||||
|
break
|
||||||
|
await System.set_power("KillSelf")
|
||||||
@@ -70,33 +70,3 @@ async def power_task(task: PowerIn = Body(...)) -> OutBase:
|
|||||||
code=500, status="error", message=f"{type(e).__name__}: {str(e)}"
|
code=500, status="error", message=f"{type(e).__name__}: {str(e)}"
|
||||||
)
|
)
|
||||||
return OutBase()
|
return OutBase()
|
||||||
|
|
||||||
|
|
||||||
@router.websocket("/ws/{websocketId}")
|
|
||||||
async def websocket_endpoint(
|
|
||||||
websocket: WebSocket,
|
|
||||||
websocketId: str = Path(..., description="要连接的WebSocket ID"),
|
|
||||||
):
|
|
||||||
await websocket.accept()
|
|
||||||
try:
|
|
||||||
uid = uuid.UUID(websocketId)
|
|
||||||
except ValueError:
|
|
||||||
await websocket.close(code=1008, reason="无效的WebSocket ID")
|
|
||||||
return
|
|
||||||
|
|
||||||
if uid in TaskManager.connection_events and uid not in TaskManager.websocket_dict:
|
|
||||||
TaskManager.websocket_dict[uid] = websocket
|
|
||||||
TaskManager.connection_events[uid].set()
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
data = await asyncio.wait_for(websocket.receive_json(), timeout=30.0)
|
|
||||||
await Broadcast.put(data)
|
|
||||||
except asyncio.TimeoutError:
|
|
||||||
await websocket.send_json(
|
|
||||||
TaskMessage(type="Signal", data={"Ping": "无描述"}).model_dump()
|
|
||||||
)
|
|
||||||
except WebSocketDisconnect:
|
|
||||||
TaskManager.websocket_dict.pop(uid, None)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
await websocket.close(code=1008, reason="任务不存在或已结束")
|
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ async def get_web_config() -> InfoOut:
|
|||||||
@router.post(
|
@router.post(
|
||||||
"/get/overview", summary="信息总览", response_model=InfoOut, status_code=200
|
"/get/overview", summary="信息总览", response_model=InfoOut, status_code=200
|
||||||
)
|
)
|
||||||
async def add_overview() -> InfoOut:
|
async def get_overview() -> InfoOut:
|
||||||
try:
|
try:
|
||||||
stage = await Config.get_stage_info("Info")
|
stage = await Config.get_stage_info("Info")
|
||||||
proxy = await Config.get_proxy_overview()
|
proxy = await Config.get_proxy_overview()
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import calendar
|
|||||||
import requests
|
import requests
|
||||||
import truststore
|
import truststore
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from fastapi import WebSocket
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from datetime import datetime, timedelta, date, timezone
|
from datetime import datetime, timedelta, date, timezone
|
||||||
from typing import Literal, Optional, Tuple
|
from typing import Literal, Optional, Tuple
|
||||||
@@ -583,6 +584,7 @@ class AppConfig(GlobalConfig):
|
|||||||
self.config_path.mkdir(parents=True, exist_ok=True)
|
self.config_path.mkdir(parents=True, exist_ok=True)
|
||||||
self.history_path.mkdir(parents=True, exist_ok=True)
|
self.history_path.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
self.websocket: Optional[WebSocket] = None
|
||||||
self.silence_dict: Dict[Path, datetime] = {}
|
self.silence_dict: Dict[Path, datetime] = {}
|
||||||
self.if_ignore_silence: List[uuid.UUID] = []
|
self.if_ignore_silence: List[uuid.UUID] = []
|
||||||
self.temp_task: List[asyncio.Task] = []
|
self.temp_task: List[asyncio.Task] = []
|
||||||
@@ -865,6 +867,13 @@ class AppConfig(GlobalConfig):
|
|||||||
db.close()
|
db.close()
|
||||||
logger.success("数据文件版本更新完成")
|
logger.success("数据文件版本更新完成")
|
||||||
|
|
||||||
|
async def send_json(self, data: dict) -> None:
|
||||||
|
"""通过WebSocket发送JSON数据"""
|
||||||
|
if Config.websocket is None:
|
||||||
|
raise RuntimeError("WebSocket 未连接")
|
||||||
|
else:
|
||||||
|
await Config.websocket.send_json(data)
|
||||||
|
|
||||||
async def add_script(
|
async def add_script(
|
||||||
self, script: Literal["MAA", "General"]
|
self, script: Literal["MAA", "General"]
|
||||||
) -> tuple[uuid.UUID, ConfigBase]:
|
) -> tuple[uuid.UUID, ConfigBase]:
|
||||||
|
|||||||
@@ -21,12 +21,11 @@
|
|||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
import asyncio
|
import asyncio
|
||||||
from fastapi import WebSocket
|
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from typing import Dict, Optional
|
from typing import Dict, Optional
|
||||||
|
|
||||||
from .config import Config, MaaConfig, GeneralConfig, QueueConfig
|
from .config import Config, MaaConfig, GeneralConfig, QueueConfig
|
||||||
from app.models.schema import TaskMessage
|
from app.models.schema import WebSocketMessage
|
||||||
from app.utils import get_logger
|
from app.utils import get_logger
|
||||||
from app.task import *
|
from app.task import *
|
||||||
|
|
||||||
@@ -41,8 +40,6 @@ class _TaskManager:
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
self.task_dict: Dict[uuid.UUID, asyncio.Task] = {}
|
self.task_dict: Dict[uuid.UUID, asyncio.Task] = {}
|
||||||
self.connection_events: Dict[uuid.UUID, asyncio.Event] = {}
|
|
||||||
self.websocket_dict: Dict[uuid.UUID, WebSocket] = {}
|
|
||||||
|
|
||||||
async def add_task(self, mode: str, uid: str) -> uuid.UUID:
|
async def add_task(self, mode: str, uid: str) -> uuid.UUID:
|
||||||
"""
|
"""
|
||||||
@@ -99,34 +96,23 @@ class _TaskManager:
|
|||||||
self, mode: str, task_id: uuid.UUID, actual_id: Optional[uuid.UUID]
|
self, mode: str, task_id: uuid.UUID, actual_id: Optional[uuid.UUID]
|
||||||
):
|
):
|
||||||
|
|
||||||
# 等待连接信号
|
|
||||||
if task_id in self.connection_events:
|
|
||||||
self.connection_events[task_id].clear()
|
|
||||||
else:
|
|
||||||
self.connection_events[task_id] = asyncio.Event()
|
|
||||||
|
|
||||||
await self.connection_events[task_id].wait()
|
|
||||||
|
|
||||||
if task_id not in self.websocket_dict:
|
|
||||||
raise RuntimeError(f"The task {task_id} is not connected to a WebSocket.")
|
|
||||||
|
|
||||||
logger.info(f"开始运行任务:{task_id},模式:{mode}")
|
logger.info(f"开始运行任务:{task_id},模式:{mode}")
|
||||||
|
|
||||||
websocket = self.websocket_dict[task_id]
|
|
||||||
|
|
||||||
if mode == "设置脚本":
|
if mode == "设置脚本":
|
||||||
|
|
||||||
if isinstance(Config.ScriptConfig[task_id], MaaConfig):
|
if isinstance(Config.ScriptConfig[task_id], MaaConfig):
|
||||||
task_item = MaaManager(mode, task_id, actual_id, websocket)
|
task_item = MaaManager(mode, task_id, actual_id, str(task_id))
|
||||||
elif isinstance(Config.ScriptConfig[task_id], GeneralConfig):
|
elif isinstance(Config.ScriptConfig[task_id], GeneralConfig):
|
||||||
task_item = GeneralManager(mode, task_id, actual_id, websocket)
|
task_item = GeneralManager(mode, task_id, actual_id, str(task_id))
|
||||||
else:
|
else:
|
||||||
logger.error(
|
logger.error(
|
||||||
f"不支持的脚本类型:{type(Config.ScriptConfig[task_id]).__name__}"
|
f"不支持的脚本类型:{type(Config.ScriptConfig[task_id]).__name__}"
|
||||||
)
|
)
|
||||||
await websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
type="Info", data={"Error": "脚本类型不支持"}
|
taskId=str(task_id),
|
||||||
|
type="Info",
|
||||||
|
data={"Error": "脚本类型不支持"},
|
||||||
).model_dump()
|
).model_dump()
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
@@ -148,9 +134,11 @@ class _TaskManager:
|
|||||||
logger.error(
|
logger.error(
|
||||||
f"不支持的队列类型:{type(Config.QueueConfig[task_id]).__name__}"
|
f"不支持的队列类型:{type(Config.QueueConfig[task_id]).__name__}"
|
||||||
)
|
)
|
||||||
await websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
type="Info", data={"Error": "队列类型不支持"}
|
taskId=str(task_id),
|
||||||
|
type="Info",
|
||||||
|
data={"Error": "队列类型不支持"},
|
||||||
).model_dump()
|
).model_dump()
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
@@ -180,9 +168,11 @@ class _TaskManager:
|
|||||||
if script_id in self.task_dict:
|
if script_id in self.task_dict:
|
||||||
|
|
||||||
task["status"] = "跳过"
|
task["status"] = "跳过"
|
||||||
await websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
type="Update", data={"task_list": task_list}
|
taskId=str(task_id),
|
||||||
|
type="Update",
|
||||||
|
data={"task_list": task_list},
|
||||||
).model_dump()
|
).model_dump()
|
||||||
)
|
)
|
||||||
logger.info(f"跳过任务:{script_id},该任务已在运行列表中")
|
logger.info(f"跳过任务:{script_id},该任务已在运行列表中")
|
||||||
@@ -190,24 +180,28 @@ class _TaskManager:
|
|||||||
|
|
||||||
# 标记为运行中
|
# 标记为运行中
|
||||||
task["status"] = "运行"
|
task["status"] = "运行"
|
||||||
await websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
type="Update", data={"task_list": task_list}
|
taskId=str(task_id),
|
||||||
|
type="Update",
|
||||||
|
data={"task_list": task_list},
|
||||||
).model_dump()
|
).model_dump()
|
||||||
)
|
)
|
||||||
logger.info(f"任务开始:{script_id}")
|
logger.info(f"任务开始:{script_id}")
|
||||||
|
|
||||||
if isinstance(Config.ScriptConfig[script_id], MaaConfig):
|
if isinstance(Config.ScriptConfig[script_id], MaaConfig):
|
||||||
task_item = MaaManager(mode, script_id, None, websocket)
|
task_item = MaaManager(mode, script_id, None, str(task_id))
|
||||||
elif isinstance(Config.ScriptConfig[task_id], GeneralConfig):
|
elif isinstance(Config.ScriptConfig[script_id], GeneralConfig):
|
||||||
task_item = GeneralManager(mode, task_id, actual_id, websocket)
|
task_item = GeneralManager(mode, script_id, actual_id, str(task_id))
|
||||||
else:
|
else:
|
||||||
logger.error(
|
logger.error(
|
||||||
f"不支持的脚本类型:{type(Config.ScriptConfig[script_id]).__name__}"
|
f"不支持的脚本类型:{type(Config.ScriptConfig[script_id]).__name__}"
|
||||||
)
|
)
|
||||||
await websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
type="Info", data={"Error": "脚本类型不支持"}
|
taskId=str(task_id),
|
||||||
|
type="Info",
|
||||||
|
data={"Error": "脚本类型不支持"},
|
||||||
).model_dump()
|
).model_dump()
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
@@ -264,11 +258,11 @@ class _TaskManager:
|
|||||||
logger.info(f"任务 {task_id} 已结束")
|
logger.info(f"任务 {task_id} 已结束")
|
||||||
self.task_dict.pop(task_id)
|
self.task_dict.pop(task_id)
|
||||||
|
|
||||||
websocket = self.websocket_dict.get(task_id, None)
|
await Config.send_json(
|
||||||
if websocket:
|
WebSocketMessage(
|
||||||
await websocket.send_json(
|
taskId=str(task_id), type="Signal", data={"Accomplish": "无描述"}
|
||||||
TaskMessage(type="Signal", data={"Accomplish": "无描述"}).model_dump()
|
).model_dump()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
TaskManager = _TaskManager()
|
TaskManager = _TaskManager()
|
||||||
|
|||||||
@@ -71,73 +71,95 @@ class GlobalConfig_Function(BaseModel):
|
|||||||
HistoryRetentionTime: Optional[Literal[7, 15, 30, 60, 90, 180, 365, 0]] = Field(
|
HistoryRetentionTime: Optional[Literal[7, 15, 30, 60, 90, 180, 365, 0]] = Field(
|
||||||
None, description="历史记录保留时间, 0表示永久保存"
|
None, description="历史记录保留时间, 0表示永久保存"
|
||||||
)
|
)
|
||||||
IfAllowSleep: Optional[bool] = Field(None, description="允许休眠")
|
IfAllowSleep: Optional[bool] = Field(default=None, description="允许休眠")
|
||||||
IfSilence: Optional[bool] = Field(None, description="静默模式")
|
IfSilence: Optional[bool] = Field(default=None, description="静默模式")
|
||||||
BossKey: Optional[str] = Field(None, description="模拟器老板键")
|
BossKey: Optional[str] = Field(default=None, description="模拟器老板键")
|
||||||
IfAgreeBilibili: Optional[bool] = Field(None, description="同意哔哩哔哩用户协议")
|
IfAgreeBilibili: Optional[bool] = Field(
|
||||||
|
default=None, description="同意哔哩哔哩用户协议"
|
||||||
|
)
|
||||||
IfSkipMumuSplashAds: Optional[bool] = Field(
|
IfSkipMumuSplashAds: Optional[bool] = Field(
|
||||||
None, description="跳过Mumu模拟器启动广告"
|
default=None, description="跳过Mumu模拟器启动广告"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class GlobalConfig_Voice(BaseModel):
|
class GlobalConfig_Voice(BaseModel):
|
||||||
Enabled: Optional[bool] = Field(None, description="语音功能是否启用")
|
Enabled: Optional[bool] = Field(default=None, description="语音功能是否启用")
|
||||||
Type: Optional[Literal["simple", "noisy"]] = Field(
|
Type: Optional[Literal["simple", "noisy"]] = Field(
|
||||||
None, description="语音类型, simple为简洁, noisy为聒噪"
|
default=None, description="语音类型, simple为简洁, noisy为聒噪"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class GlobalConfig_Start(BaseModel):
|
class GlobalConfig_Start(BaseModel):
|
||||||
IfSelfStart: Optional[bool] = Field(None, description="是否在系统启动时自动运行")
|
IfSelfStart: Optional[bool] = Field(
|
||||||
|
default=None, description="是否在系统启动时自动运行"
|
||||||
|
)
|
||||||
IfMinimizeDirectly: Optional[bool] = Field(
|
IfMinimizeDirectly: Optional[bool] = Field(
|
||||||
None, description="启动时是否直接最小化到托盘而不显示主窗口"
|
default=None, description="启动时是否直接最小化到托盘而不显示主窗口"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class GlobalConfig_UI(BaseModel):
|
class GlobalConfig_UI(BaseModel):
|
||||||
IfShowTray: Optional[bool] = Field(None, description="是否常态显示托盘图标")
|
IfShowTray: Optional[bool] = Field(default=None, description="是否常态显示托盘图标")
|
||||||
IfToTray: Optional[bool] = Field(None, description="是否最小化到托盘")
|
IfToTray: Optional[bool] = Field(default=None, description="是否最小化到托盘")
|
||||||
|
|
||||||
|
|
||||||
class GlobalConfig_Notify(BaseModel):
|
class GlobalConfig_Notify(BaseModel):
|
||||||
SendTaskResultTime: Optional[Literal["不推送", "任何时刻", "仅失败时"]] = Field(
|
SendTaskResultTime: Optional[Literal["不推送", "任何时刻", "仅失败时"]] = Field(
|
||||||
None, description="任务结果推送时机"
|
default=None, description="任务结果推送时机"
|
||||||
)
|
)
|
||||||
IfSendStatistic: Optional[bool] = Field(None, description="是否发送统计信息")
|
IfSendStatistic: Optional[bool] = Field(
|
||||||
IfSendSixStar: Optional[bool] = Field(None, description="是否发送公招六星通知")
|
default=None, description="是否发送统计信息"
|
||||||
IfPushPlyer: Optional[bool] = Field(None, description="是否推送系统通知")
|
)
|
||||||
IfSendMail: Optional[bool] = Field(None, description="是否发送邮件通知")
|
IfSendSixStar: Optional[bool] = Field(
|
||||||
SMTPServerAddress: Optional[str] = Field(None, description="SMTP服务器地址")
|
default=None, description="是否发送公招六星通知"
|
||||||
AuthorizationCode: Optional[str] = Field(None, description="SMTP授权码")
|
)
|
||||||
FromAddress: Optional[str] = Field(None, description="邮件发送地址")
|
IfPushPlyer: Optional[bool] = Field(default=None, description="是否推送系统通知")
|
||||||
ToAddress: Optional[str] = Field(None, description="邮件接收地址")
|
IfSendMail: Optional[bool] = Field(default=None, description="是否发送邮件通知")
|
||||||
IfServerChan: Optional[bool] = Field(None, description="是否使用ServerChan推送")
|
SMTPServerAddress: Optional[str] = Field(default=None, description="SMTP服务器地址")
|
||||||
ServerChanKey: Optional[str] = Field(None, description="ServerChan推送密钥")
|
AuthorizationCode: Optional[str] = Field(default=None, description="SMTP授权码")
|
||||||
|
FromAddress: Optional[str] = Field(default=None, description="邮件发送地址")
|
||||||
|
ToAddress: Optional[str] = Field(default=None, description="邮件接收地址")
|
||||||
|
IfServerChan: Optional[bool] = Field(
|
||||||
|
default=None, description="是否使用ServerChan推送"
|
||||||
|
)
|
||||||
|
ServerChanKey: Optional[str] = Field(default=None, description="ServerChan推送密钥")
|
||||||
IfCompanyWebHookBot: Optional[bool] = Field(
|
IfCompanyWebHookBot: Optional[bool] = Field(
|
||||||
None, description="是否使用企微Webhook推送"
|
default=None, description="是否使用企微Webhook推送"
|
||||||
|
)
|
||||||
|
CompanyWebHookBotUrl: Optional[str] = Field(
|
||||||
|
default=None, description="企微Webhook Bot URL"
|
||||||
)
|
)
|
||||||
CompanyWebHookBotUrl: Optional[str] = Field(None, description="企微Webhook Bot URL")
|
|
||||||
|
|
||||||
|
|
||||||
class GlobalConfig_Update(BaseModel):
|
class GlobalConfig_Update(BaseModel):
|
||||||
IfAutoUpdate: Optional[bool] = Field(None, description="是否自动更新")
|
IfAutoUpdate: Optional[bool] = Field(default=None, description="是否自动更新")
|
||||||
UpdateType: Optional[Literal["stable", "beta"]] = Field(
|
UpdateType: Optional[Literal["stable", "beta"]] = Field(
|
||||||
None, description="更新类型, stable为稳定版, beta为测试版"
|
default=None, description="更新类型, stable为稳定版, beta为测试版"
|
||||||
)
|
)
|
||||||
Source: Optional[Literal["GitHub", "MirrorChyan", "AutoSite"]] = Field(
|
Source: Optional[Literal["GitHub", "MirrorChyan", "AutoSite"]] = Field(
|
||||||
None, description="更新源: GitHub源, Mirror酱源, 自建源"
|
default=None, description="更新源: GitHub源, Mirror酱源, 自建源"
|
||||||
)
|
)
|
||||||
ProxyAddress: Optional[str] = Field(None, description="网络代理地址")
|
ProxyAddress: Optional[str] = Field(default=None, description="网络代理地址")
|
||||||
MirrorChyanCDK: Optional[str] = Field(None, description="Mirror酱CDK")
|
MirrorChyanCDK: Optional[str] = Field(default=None, description="Mirror酱CDK")
|
||||||
|
|
||||||
|
|
||||||
class GlobalConfig(BaseModel):
|
class GlobalConfig(BaseModel):
|
||||||
Function: Optional[GlobalConfig_Function] = Field(None, description="功能相关配置")
|
Function: Optional[GlobalConfig_Function] = Field(
|
||||||
Voice: Optional[GlobalConfig_Voice] = Field(None, description="语音相关配置")
|
default=None, description="功能相关配置"
|
||||||
Start: Optional[GlobalConfig_Start] = Field(None, description="启动相关配置")
|
)
|
||||||
UI: Optional[GlobalConfig_UI] = Field(None, description="界面相关配置")
|
Voice: Optional[GlobalConfig_Voice] = Field(
|
||||||
Notify: Optional[GlobalConfig_Notify] = Field(None, description="通知相关配置")
|
default=None, description="语音相关配置"
|
||||||
Update: Optional[GlobalConfig_Update] = Field(None, description="更新相关配置")
|
)
|
||||||
|
Start: Optional[GlobalConfig_Start] = Field(
|
||||||
|
default=None, description="启动相关配置"
|
||||||
|
)
|
||||||
|
UI: Optional[GlobalConfig_UI] = Field(default=None, description="界面相关配置")
|
||||||
|
Notify: Optional[GlobalConfig_Notify] = Field(
|
||||||
|
default=None, description="通知相关配置"
|
||||||
|
)
|
||||||
|
Update: Optional[GlobalConfig_Update] = Field(
|
||||||
|
default=None, description="更新相关配置"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class QueueIndexItem(BaseModel):
|
class QueueIndexItem(BaseModel):
|
||||||
@@ -157,36 +179,36 @@ class TimeSetIndexItem(BaseModel):
|
|||||||
|
|
||||||
class QueueItem_Info(BaseModel):
|
class QueueItem_Info(BaseModel):
|
||||||
ScriptId: Optional[str] = Field(
|
ScriptId: Optional[str] = Field(
|
||||||
None, description="任务所对应的脚本ID, 为None时表示未选择"
|
default=None, description="任务所对应的脚本ID, 为None时表示未选择"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class QueueItem(BaseModel):
|
class QueueItem(BaseModel):
|
||||||
Info: Optional[QueueItem_Info] = Field(None, description="队列项")
|
Info: Optional[QueueItem_Info] = Field(default=None, description="队列项")
|
||||||
|
|
||||||
|
|
||||||
class TimeSet_Info(BaseModel):
|
class TimeSet_Info(BaseModel):
|
||||||
Enabled: Optional[bool] = Field(None, description="是否启用")
|
Enabled: Optional[bool] = Field(default=None, description="是否启用")
|
||||||
Time: Optional[str] = Field(None, description="时间设置, 格式为HH:MM")
|
Time: Optional[str] = Field(default=None, description="时间设置, 格式为HH:MM")
|
||||||
|
|
||||||
|
|
||||||
class TimeSet(BaseModel):
|
class TimeSet(BaseModel):
|
||||||
Info: Optional[TimeSet_Info] = Field(None, description="时间项")
|
Info: Optional[TimeSet_Info] = Field(default=None, description="时间项")
|
||||||
|
|
||||||
|
|
||||||
class QueueConfig_Info(BaseModel):
|
class QueueConfig_Info(BaseModel):
|
||||||
Name: Optional[str] = Field(None, description="队列名称")
|
Name: Optional[str] = Field(default=None, description="队列名称")
|
||||||
TimeEnabled: Optional[bool] = Field(None, description="是否启用定时")
|
TimeEnabled: Optional[bool] = Field(default=None, description="是否启用定时")
|
||||||
StartUpEnabled: Optional[bool] = Field(None, description="是否启动时运行")
|
StartUpEnabled: Optional[bool] = Field(default=None, description="是否启动时运行")
|
||||||
AfterAccomplish: Optional[
|
AfterAccomplish: Optional[
|
||||||
Literal[
|
Literal[
|
||||||
"NoAction", "KillSelf", "Sleep", "Hibernate", "Shutdown", "ShutdownForce"
|
"NoAction", "KillSelf", "Sleep", "Hibernate", "Shutdown", "ShutdownForce"
|
||||||
]
|
]
|
||||||
] = Field(None, description="完成后操作")
|
] = Field(default=None, description="完成后操作")
|
||||||
|
|
||||||
|
|
||||||
class QueueConfig(BaseModel):
|
class QueueConfig(BaseModel):
|
||||||
Info: Optional[QueueConfig_Info] = Field(None, description="队列信息")
|
Info: Optional[QueueConfig_Info] = Field(default=None, description="队列信息")
|
||||||
|
|
||||||
|
|
||||||
class ScriptIndexItem(BaseModel):
|
class ScriptIndexItem(BaseModel):
|
||||||
@@ -202,15 +224,17 @@ class UserIndexItem(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class MaaUserConfig_Info(BaseModel):
|
class MaaUserConfig_Info(BaseModel):
|
||||||
Name: Optional[str] = Field(None, description="用户名")
|
Name: Optional[str] = Field(default=None, description="用户名")
|
||||||
Id: Optional[str] = Field(None, description="用户ID")
|
Id: Optional[str] = Field(default=None, description="用户ID")
|
||||||
Mode: Optional[Literal["简洁", "详细"]] = Field(None, description="用户配置模式")
|
Mode: Optional[Literal["简洁", "详细"]] = Field(
|
||||||
StageMode: Optional[str] = Field(None, description="关卡配置模式")
|
default=None, description="用户配置模式"
|
||||||
|
)
|
||||||
|
StageMode: Optional[str] = Field(default=None, description="关卡配置模式")
|
||||||
Server: Optional[
|
Server: Optional[
|
||||||
Literal["Official", "Bilibili", "YoStarEN", "YoStarJP", "YoStarKR", "txwy"]
|
Literal["Official", "Bilibili", "YoStarEN", "YoStarJP", "YoStarKR", "txwy"]
|
||||||
] = Field(None, description="服务器")
|
] = Field(default=None, description="服务器")
|
||||||
Status: Optional[bool] = Field(None, description="用户状态")
|
Status: Optional[bool] = Field(default=None, description="用户状态")
|
||||||
RemainedDay: Optional[int] = Field(None, description="剩余天数")
|
RemainedDay: Optional[int] = Field(default=None, description="剩余天数")
|
||||||
Annihilation: Optional[
|
Annihilation: Optional[
|
||||||
Literal[
|
Literal[
|
||||||
"Close",
|
"Close",
|
||||||
@@ -219,164 +243,186 @@ class MaaUserConfig_Info(BaseModel):
|
|||||||
"LungmenOutskirts@Annihilation",
|
"LungmenOutskirts@Annihilation",
|
||||||
"LungmenDowntown@Annihilation",
|
"LungmenDowntown@Annihilation",
|
||||||
]
|
]
|
||||||
] = Field(None, description="剿灭模式")
|
] = Field(default=None, description="剿灭模式")
|
||||||
Routine: Optional[bool] = Field(None, description="是否启用日常")
|
Routine: Optional[bool] = Field(default=None, description="是否启用日常")
|
||||||
InfrastMode: Optional[Literal["Normal", "Rotation", "Custom"]] = Field(
|
InfrastMode: Optional[Literal["Normal", "Rotation", "Custom"]] = Field(
|
||||||
None, description="基建模式"
|
default=None, description="基建模式"
|
||||||
)
|
)
|
||||||
Password: Optional[str] = Field(None, description="密码")
|
Password: Optional[str] = Field(default=None, description="密码")
|
||||||
Notes: Optional[str] = Field(None, description="备注")
|
Notes: Optional[str] = Field(default=None, description="备注")
|
||||||
MedicineNumb: Optional[int] = Field(None, description="吃理智药数量")
|
MedicineNumb: Optional[int] = Field(default=None, description="吃理智药数量")
|
||||||
SeriesNumb: Optional[Literal["0", "6", "5", "4", "3", "2", "1", "-1"]] = Field(
|
SeriesNumb: Optional[Literal["0", "6", "5", "4", "3", "2", "1", "-1"]] = Field(
|
||||||
None, description="连战次数"
|
default=None, description="连战次数"
|
||||||
)
|
)
|
||||||
Stage: Optional[str] = Field(None, description="关卡选择")
|
Stage: Optional[str] = Field(default=None, description="关卡选择")
|
||||||
Stage_1: Optional[str] = Field(None, description="备选关卡 - 1")
|
Stage_1: Optional[str] = Field(default=None, description="备选关卡 - 1")
|
||||||
Stage_2: Optional[str] = Field(None, description="备选关卡 - 2")
|
Stage_2: Optional[str] = Field(default=None, description="备选关卡 - 2")
|
||||||
Stage_3: Optional[str] = Field(None, description="备选关卡 - 3")
|
Stage_3: Optional[str] = Field(default=None, description="备选关卡 - 3")
|
||||||
Stage_Remain: Optional[str] = Field(None, description="剩余理智关卡")
|
Stage_Remain: Optional[str] = Field(default=None, description="剩余理智关卡")
|
||||||
IfSkland: Optional[bool] = Field(None, description="是否启用森空岛签到")
|
IfSkland: Optional[bool] = Field(default=None, description="是否启用森空岛签到")
|
||||||
SklandToken: Optional[str] = Field(None, description="SklandToken")
|
SklandToken: Optional[str] = Field(default=None, description="SklandToken")
|
||||||
|
|
||||||
|
|
||||||
class MaaUserConfig_Data(BaseModel):
|
class MaaUserConfig_Data(BaseModel):
|
||||||
LastProxyDate: Optional[str] = Field(None, description="上次代理日期")
|
LastProxyDate: Optional[str] = Field(default=None, description="上次代理日期")
|
||||||
LastAnnihilationDate: Optional[str] = Field(None, description="上次剿灭日期")
|
LastAnnihilationDate: Optional[str] = Field(
|
||||||
LastSklandDate: Optional[str] = Field(None, description="上次森空岛签到日期")
|
default=None, description="上次剿灭日期"
|
||||||
ProxyTimes: Optional[int] = Field(None, description="代理次数")
|
)
|
||||||
IfPassCheck: Optional[bool] = Field(None, description="是否通过人工排查")
|
LastSklandDate: Optional[str] = Field(
|
||||||
|
default=None, description="上次森空岛签到日期"
|
||||||
|
)
|
||||||
|
ProxyTimes: Optional[int] = Field(default=None, description="代理次数")
|
||||||
|
IfPassCheck: Optional[bool] = Field(default=None, description="是否通过人工排查")
|
||||||
|
|
||||||
|
|
||||||
class MaaUserConfig_Task(BaseModel):
|
class MaaUserConfig_Task(BaseModel):
|
||||||
IfWakeUp: Optional[bool] = Field(None, description="开始唤醒")
|
IfWakeUp: Optional[bool] = Field(default=None, description="开始唤醒")
|
||||||
IfRecruiting: Optional[bool] = Field(None, description="自动公招")
|
IfRecruiting: Optional[bool] = Field(default=None, description="自动公招")
|
||||||
IfBase: Optional[bool] = Field(None, description="基建换班")
|
IfBase: Optional[bool] = Field(default=None, description="基建换班")
|
||||||
IfCombat: Optional[bool] = Field(None, description="刷理智")
|
IfCombat: Optional[bool] = Field(default=None, description="刷理智")
|
||||||
IfMall: Optional[bool] = Field(None, description="获取信用及购物")
|
IfMall: Optional[bool] = Field(default=None, description="获取信用及购物")
|
||||||
IfMission: Optional[bool] = Field(None, description="领取奖励")
|
IfMission: Optional[bool] = Field(default=None, description="领取奖励")
|
||||||
IfAutoRoguelike: Optional[bool] = Field(None, description="自动肉鸽")
|
IfAutoRoguelike: Optional[bool] = Field(default=None, description="自动肉鸽")
|
||||||
IfReclamation: Optional[bool] = Field(None, description="生息演算")
|
IfReclamation: Optional[bool] = Field(default=None, description="生息演算")
|
||||||
|
|
||||||
|
|
||||||
class UserConfig_Notify(BaseModel):
|
class UserConfig_Notify(BaseModel):
|
||||||
Enabled: Optional[bool] = Field(None, description="是否启用通知")
|
Enabled: Optional[bool] = Field(default=None, description="是否启用通知")
|
||||||
IfSendStatistic: Optional[bool] = Field(None, description="是否发送统计信息")
|
IfSendStatistic: Optional[bool] = Field(
|
||||||
IfSendSixStar: Optional[bool] = Field(None, description="是否发送高资喜报")
|
default=None, description="是否发送统计信息"
|
||||||
IfSendMail: Optional[bool] = Field(None, description="是否发送邮件通知")
|
)
|
||||||
ToAddress: Optional[str] = Field(None, description="邮件接收地址")
|
IfSendSixStar: Optional[bool] = Field(default=None, description="是否发送高资喜报")
|
||||||
IfServerChan: Optional[bool] = Field(None, description="是否使用Server酱推送")
|
IfSendMail: Optional[bool] = Field(default=None, description="是否发送邮件通知")
|
||||||
ServerChanKey: Optional[str] = Field(None, description="ServerChanKey")
|
ToAddress: Optional[str] = Field(default=None, description="邮件接收地址")
|
||||||
IfCompanyWebHookBot: Optional[bool] = Field(None, description="是否使用Webhook推送")
|
IfServerChan: Optional[bool] = Field(
|
||||||
CompanyWebHookBotUrl: Optional[str] = Field(None, description="企微Webhook Bot URL")
|
default=None, description="是否使用Server酱推送"
|
||||||
|
)
|
||||||
|
ServerChanKey: Optional[str] = Field(default=None, description="ServerChanKey")
|
||||||
|
IfCompanyWebHookBot: Optional[bool] = Field(
|
||||||
|
default=None, description="是否使用Webhook推送"
|
||||||
|
)
|
||||||
|
CompanyWebHookBotUrl: Optional[str] = Field(
|
||||||
|
default=None, description="企微Webhook Bot URL"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class MaaUserConfig(BaseModel):
|
class MaaUserConfig(BaseModel):
|
||||||
Info: Optional[MaaUserConfig_Info] = Field(None, description="基础信息")
|
Info: Optional[MaaUserConfig_Info] = Field(default=None, description="基础信息")
|
||||||
Data: Optional[MaaUserConfig_Data] = Field(None, description="用户数据")
|
Data: Optional[MaaUserConfig_Data] = Field(default=None, description="用户数据")
|
||||||
Task: Optional[MaaUserConfig_Task] = Field(None, description="任务列表")
|
Task: Optional[MaaUserConfig_Task] = Field(default=None, description="任务列表")
|
||||||
Notify: Optional[UserConfig_Notify] = Field(None, description="单独通知")
|
Notify: Optional[UserConfig_Notify] = Field(default=None, description="单独通知")
|
||||||
|
|
||||||
|
|
||||||
class MaaConfig_Info(BaseModel):
|
class MaaConfig_Info(BaseModel):
|
||||||
Name: Optional[str] = Field(None, description="脚本名称")
|
Name: Optional[str] = Field(default=None, description="脚本名称")
|
||||||
Path: Optional[str] = Field(None, description="脚本路径")
|
Path: Optional[str] = Field(default=None, description="脚本路径")
|
||||||
|
|
||||||
|
|
||||||
class MaaConfig_Run(BaseModel):
|
class MaaConfig_Run(BaseModel):
|
||||||
TaskTransitionMethod: Optional[Literal["NoAction", "ExitGame", "ExitEmulator"]] = (
|
TaskTransitionMethod: Optional[Literal["NoAction", "ExitGame", "ExitEmulator"]] = (
|
||||||
Field(None, description="简洁任务间切换方式")
|
Field(default=None, description="简洁任务间切换方式")
|
||||||
)
|
)
|
||||||
ProxyTimesLimit: Optional[int] = Field(None, description="每日代理次数限制")
|
ProxyTimesLimit: Optional[int] = Field(default=None, description="每日代理次数限制")
|
||||||
ADBSearchRange: Optional[int] = Field(None, description="ADB端口搜索范围")
|
ADBSearchRange: Optional[int] = Field(default=None, description="ADB端口搜索范围")
|
||||||
RunTimesLimit: Optional[int] = Field(None, description="重试次数限制")
|
RunTimesLimit: Optional[int] = Field(default=None, description="重试次数限制")
|
||||||
AnnihilationTimeLimit: Optional[int] = Field(None, description="剿灭超时限制")
|
AnnihilationTimeLimit: Optional[int] = Field(
|
||||||
RoutineTimeLimit: Optional[int] = Field(None, description="日常超时限制")
|
default=None, description="剿灭超时限制"
|
||||||
|
)
|
||||||
|
RoutineTimeLimit: Optional[int] = Field(default=None, description="日常超时限制")
|
||||||
AnnihilationWeeklyLimit: Optional[bool] = Field(
|
AnnihilationWeeklyLimit: Optional[bool] = Field(
|
||||||
None, description="剿灭每周仅代理至上限"
|
default=None, description="剿灭每周仅代理至上限"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class MaaConfig(BaseModel):
|
class MaaConfig(BaseModel):
|
||||||
Info: Optional[MaaConfig_Info] = Field(None, description="脚本基础信息")
|
Info: Optional[MaaConfig_Info] = Field(default=None, description="脚本基础信息")
|
||||||
Run: Optional[MaaConfig_Run] = Field(None, description="脚本运行配置")
|
Run: Optional[MaaConfig_Run] = Field(default=None, description="脚本运行配置")
|
||||||
|
|
||||||
|
|
||||||
class GeneralUserConfig_Info(BaseModel):
|
class GeneralUserConfig_Info(BaseModel):
|
||||||
|
|
||||||
Name: Optional[str] = Field(None, description="用户名")
|
Name: Optional[str] = Field(default=None, description="用户名")
|
||||||
Status: Optional[bool] = Field(None, description="用户状态")
|
Status: Optional[bool] = Field(default=None, description="用户状态")
|
||||||
RemainedDay: Optional[int] = Field(None, description="剩余天数")
|
RemainedDay: Optional[int] = Field(default=None, description="剩余天数")
|
||||||
IfScriptBeforeTask: Optional[bool] = Field(None, description="是否在任务前执行脚本")
|
IfScriptBeforeTask: Optional[bool] = Field(
|
||||||
ScriptBeforeTask: Optional[str] = Field(None, description="任务前脚本路径")
|
default=None, description="是否在任务前执行脚本"
|
||||||
IfScriptAfterTask: Optional[bool] = Field(None, description="是否在任务后执行脚本")
|
)
|
||||||
ScriptAfterTask: Optional[str] = Field(None, description="任务后脚本路径")
|
ScriptBeforeTask: Optional[str] = Field(default=None, description="任务前脚本路径")
|
||||||
Notes: Optional[str] = Field(None, description="备注")
|
IfScriptAfterTask: Optional[bool] = Field(
|
||||||
|
default=None, description="是否在任务后执行脚本"
|
||||||
|
)
|
||||||
|
ScriptAfterTask: Optional[str] = Field(default=None, description="任务后脚本路径")
|
||||||
|
Notes: Optional[str] = Field(default=None, description="备注")
|
||||||
|
|
||||||
|
|
||||||
class GeneralUserConfig_Data(BaseModel):
|
class GeneralUserConfig_Data(BaseModel):
|
||||||
LastProxyDate: Optional[str] = Field(None, description="上次代理日期")
|
LastProxyDate: Optional[str] = Field(default=None, description="上次代理日期")
|
||||||
ProxyTimes: Optional[int] = Field(None, description="代理次数")
|
ProxyTimes: Optional[int] = Field(default=None, description="代理次数")
|
||||||
|
|
||||||
|
|
||||||
class GeneralUserConfig(BaseModel):
|
class GeneralUserConfig(BaseModel):
|
||||||
Info: Optional[GeneralUserConfig_Info] = Field(None, description="用户信息")
|
Info: Optional[GeneralUserConfig_Info] = Field(default=None, description="用户信息")
|
||||||
Data: Optional[GeneralUserConfig_Data] = Field(None, description="用户数据")
|
Data: Optional[GeneralUserConfig_Data] = Field(default=None, description="用户数据")
|
||||||
Notify: Optional[UserConfig_Notify] = Field(None, description="单独通知")
|
Notify: Optional[UserConfig_Notify] = Field(default=None, description="单独通知")
|
||||||
|
|
||||||
|
|
||||||
class GeneralConfig_Info(BaseModel):
|
class GeneralConfig_Info(BaseModel):
|
||||||
Name: Optional[str] = Field(None, description="脚本名称")
|
Name: Optional[str] = Field(default=None, description="脚本名称")
|
||||||
RootPath: Optional[str] = Field(None, description="脚本根目录")
|
RootPath: Optional[str] = Field(default=None, description="脚本根目录")
|
||||||
|
|
||||||
|
|
||||||
class GeneralConfig_Script(BaseModel):
|
class GeneralConfig_Script(BaseModel):
|
||||||
ScriptPath: Optional[str] = Field(None, description="脚本可执行文件路径")
|
ScriptPath: Optional[str] = Field(default=None, description="脚本可执行文件路径")
|
||||||
Arguments: Optional[str] = Field(None, description="脚本启动附加命令参数")
|
Arguments: Optional[str] = Field(default=None, description="脚本启动附加命令参数")
|
||||||
IfTrackProcess: Optional[bool] = Field(None, description="是否追踪脚本子进程")
|
IfTrackProcess: Optional[bool] = Field(
|
||||||
ConfigPath: Optional[str] = Field(None, description="配置文件路径")
|
default=None, description="是否追踪脚本子进程"
|
||||||
|
)
|
||||||
|
ConfigPath: Optional[str] = Field(default=None, description="配置文件路径")
|
||||||
ConfigPathMode: Optional[Literal["File", "Folder"]] = Field(
|
ConfigPathMode: Optional[Literal["File", "Folder"]] = Field(
|
||||||
None, description="配置文件类型: 单个文件, 文件夹"
|
default=None, description="配置文件类型: 单个文件, 文件夹"
|
||||||
)
|
)
|
||||||
UpdateConfigMode: Optional[Literal["Never", "Success", "Failure", "Always"]] = (
|
UpdateConfigMode: Optional[Literal["Never", "Success", "Failure", "Always"]] = (
|
||||||
Field(
|
Field(
|
||||||
None,
|
default=None,
|
||||||
description="更新配置时机, 从不, 仅成功时, 仅失败时, 任务结束时",
|
description="更新配置时机, 从不, 仅成功时, 仅失败时, 任务结束时",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
LogPath: Optional[str] = Field(None, description="日志文件路径")
|
LogPath: Optional[str] = Field(default=None, description="日志文件路径")
|
||||||
LogPathFormat: Optional[str] = Field(None, description="日志文件名格式")
|
LogPathFormat: Optional[str] = Field(default=None, description="日志文件名格式")
|
||||||
LogTimeStart: Optional[int] = Field(None, description="日志时间戳开始位置")
|
LogTimeStart: Optional[int] = Field(default=None, description="日志时间戳开始位置")
|
||||||
LogTimeEnd: Optional[int] = Field(None, description="日志时间戳结束位置")
|
LogTimeEnd: Optional[int] = Field(default=None, description="日志时间戳结束位置")
|
||||||
LogTimeFormat: Optional[str] = Field(None, description="日志时间戳格式")
|
LogTimeFormat: Optional[str] = Field(default=None, description="日志时间戳格式")
|
||||||
SuccessLog: Optional[str] = Field(None, description="成功时日志")
|
SuccessLog: Optional[str] = Field(default=None, description="成功时日志")
|
||||||
ErrorLog: Optional[str] = Field(None, description="错误时日志")
|
ErrorLog: Optional[str] = Field(default=None, description="错误时日志")
|
||||||
|
|
||||||
|
|
||||||
class GeneralConfig_Game(BaseModel):
|
class GeneralConfig_Game(BaseModel):
|
||||||
Enabled: Optional[bool] = Field(None, description="游戏/模拟器相关功能是否启用")
|
Enabled: Optional[bool] = Field(
|
||||||
Type: Optional[Literal["Emulator", "Client"]] = Field(
|
default=None, description="游戏/模拟器相关功能是否启用"
|
||||||
None, description="类型: 模拟器, PC端"
|
|
||||||
)
|
)
|
||||||
Path: Optional[str] = Field(None, description="游戏/模拟器程序路径")
|
Type: Optional[Literal["Emulator", "Client"]] = Field(
|
||||||
Arguments: Optional[str] = Field(None, description="游戏/模拟器启动参数")
|
default=None, description="类型: 模拟器, PC端"
|
||||||
WaitTime: Optional[int] = Field(None, description="游戏/模拟器等待启动时间")
|
)
|
||||||
|
Path: Optional[str] = Field(default=None, description="游戏/模拟器程序路径")
|
||||||
|
Arguments: Optional[str] = Field(default=None, description="游戏/模拟器启动参数")
|
||||||
|
WaitTime: Optional[int] = Field(default=None, description="游戏/模拟器等待启动时间")
|
||||||
IfForceClose: Optional[bool] = Field(
|
IfForceClose: Optional[bool] = Field(
|
||||||
None, description="是否强制关闭游戏/模拟器进程"
|
default=None, description="是否强制关闭游戏/模拟器进程"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class GeneralConfig_Run(BaseModel):
|
class GeneralConfig_Run(BaseModel):
|
||||||
ProxyTimesLimit: Optional[int] = Field(None, description="每日代理次数限制")
|
ProxyTimesLimit: Optional[int] = Field(default=None, description="每日代理次数限制")
|
||||||
RunTimesLimit: Optional[int] = Field(None, description="重试次数限制")
|
RunTimesLimit: Optional[int] = Field(default=None, description="重试次数限制")
|
||||||
RunTimeLimit: Optional[int] = Field(None, description="日志超时限制")
|
RunTimeLimit: Optional[int] = Field(default=None, description="日志超时限制")
|
||||||
|
|
||||||
|
|
||||||
class GeneralConfig(BaseModel):
|
class GeneralConfig(BaseModel):
|
||||||
|
|
||||||
Info: Optional[GeneralConfig_Info] = Field(None, description="脚本基础信息")
|
Info: Optional[GeneralConfig_Info] = Field(default=None, description="脚本基础信息")
|
||||||
Script: Optional[GeneralConfig_Script] = Field(None, description="脚本配置")
|
Script: Optional[GeneralConfig_Script] = Field(default=None, description="脚本配置")
|
||||||
Game: Optional[GeneralConfig_Game] = Field(None, description="游戏配置")
|
Game: Optional[GeneralConfig_Game] = Field(default=None, description="游戏配置")
|
||||||
Run: Optional[GeneralConfig_Run] = Field(None, description="运行配置")
|
Run: Optional[GeneralConfig_Run] = Field(default=None, description="运行配置")
|
||||||
|
|
||||||
|
|
||||||
class PlanIndexItem(BaseModel):
|
class PlanIndexItem(BaseModel):
|
||||||
@@ -385,33 +431,35 @@ class PlanIndexItem(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class MaaPlanConfig_Info(BaseModel):
|
class MaaPlanConfig_Info(BaseModel):
|
||||||
Name: Optional[str] = Field(None, description="计划表名称")
|
Name: Optional[str] = Field(default=None, description="计划表名称")
|
||||||
Mode: Optional[Literal["ALL", "Weekly"]] = Field(None, description="计划表模式")
|
Mode: Optional[Literal["ALL", "Weekly"]] = Field(
|
||||||
|
default=None, description="计划表模式"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class MaaPlanConfig_Item(BaseModel):
|
class MaaPlanConfig_Item(BaseModel):
|
||||||
MedicineNumb: Optional[int] = Field(None, description="吃理智药")
|
MedicineNumb: Optional[int] = Field(default=None, description="吃理智药")
|
||||||
SeriesNumb: Optional[Literal["0", "6", "5", "4", "3", "2", "1", "-1"]] = Field(
|
SeriesNumb: Optional[Literal["0", "6", "5", "4", "3", "2", "1", "-1"]] = Field(
|
||||||
None, description="连战次数"
|
None, description="连战次数"
|
||||||
)
|
)
|
||||||
Stage: Optional[str] = Field(None, description="关卡选择")
|
Stage: Optional[str] = Field(default=None, description="关卡选择")
|
||||||
Stage_1: Optional[str] = Field(None, description="备选关卡 - 1")
|
Stage_1: Optional[str] = Field(default=None, description="备选关卡 - 1")
|
||||||
Stage_2: Optional[str] = Field(None, description="备选关卡 - 2")
|
Stage_2: Optional[str] = Field(default=None, description="备选关卡 - 2")
|
||||||
Stage_3: Optional[str] = Field(None, description="备选关卡 - 3")
|
Stage_3: Optional[str] = Field(default=None, description="备选关卡 - 3")
|
||||||
Stage_Remain: Optional[str] = Field(None, description="剩余理智关卡")
|
Stage_Remain: Optional[str] = Field(default=None, description="剩余理智关卡")
|
||||||
|
|
||||||
|
|
||||||
class MaaPlanConfig(BaseModel):
|
class MaaPlanConfig(BaseModel):
|
||||||
|
|
||||||
Info: Optional[MaaPlanConfig_Info] = Field(None, description="基础信息")
|
Info: Optional[MaaPlanConfig_Info] = Field(default=None, description="基础信息")
|
||||||
ALL: Optional[MaaPlanConfig_Item] = Field(None, description="全局")
|
ALL: Optional[MaaPlanConfig_Item] = Field(default=None, description="全局")
|
||||||
Monday: Optional[MaaPlanConfig_Item] = Field(None, description="周一")
|
Monday: Optional[MaaPlanConfig_Item] = Field(default=None, description="周一")
|
||||||
Tuesday: Optional[MaaPlanConfig_Item] = Field(None, description="周二")
|
Tuesday: Optional[MaaPlanConfig_Item] = Field(default=None, description="周二")
|
||||||
Wednesday: Optional[MaaPlanConfig_Item] = Field(None, description="周三")
|
Wednesday: Optional[MaaPlanConfig_Item] = Field(default=None, description="周三")
|
||||||
Thursday: Optional[MaaPlanConfig_Item] = Field(None, description="周四")
|
Thursday: Optional[MaaPlanConfig_Item] = Field(default=None, description="周四")
|
||||||
Friday: Optional[MaaPlanConfig_Item] = Field(None, description="周五")
|
Friday: Optional[MaaPlanConfig_Item] = Field(default=None, description="周五")
|
||||||
Saturday: Optional[MaaPlanConfig_Item] = Field(None, description="周六")
|
Saturday: Optional[MaaPlanConfig_Item] = Field(default=None, description="周六")
|
||||||
Sunday: Optional[MaaPlanConfig_Item] = Field(None, description="周日")
|
Sunday: Optional[MaaPlanConfig_Item] = Field(default=None, description="周日")
|
||||||
|
|
||||||
|
|
||||||
class HistoryIndexItem(BaseModel):
|
class HistoryIndexItem(BaseModel):
|
||||||
@@ -422,19 +470,20 @@ class HistoryIndexItem(BaseModel):
|
|||||||
|
|
||||||
class HistoryData(BaseModel):
|
class HistoryData(BaseModel):
|
||||||
index: Optional[List[HistoryIndexItem]] = Field(
|
index: Optional[List[HistoryIndexItem]] = Field(
|
||||||
None, description="历史记录索引列表"
|
default=None, description="历史记录索引列表"
|
||||||
)
|
)
|
||||||
recruit_statistics: Optional[Dict[str, int]] = Field(
|
recruit_statistics: Optional[Dict[str, int]] = Field(
|
||||||
None, description="公招统计数据, key为星级, value为对应的公招数量"
|
default=None, description="公招统计数据, key为星级, value为对应的公招数量"
|
||||||
)
|
)
|
||||||
drop_statistics: Optional[Dict[str, Dict[str, int]]] = Field(
|
drop_statistics: Optional[Dict[str, Dict[str, int]]] = Field(
|
||||||
None, description="掉落统计数据, 格式为 { '关卡号': { '掉落物': 数量 } }"
|
default=None,
|
||||||
|
description="掉落统计数据, 格式为 { '关卡号': { '掉落物': 数量 } }",
|
||||||
)
|
)
|
||||||
error_info: Optional[Dict[str, str]] = Field(
|
error_info: Optional[Dict[str, str]] = Field(
|
||||||
None, description="报错信息, key为时间戳, value为错误描述"
|
default=None, description="报错信息, key为时间戳, value为错误描述"
|
||||||
)
|
)
|
||||||
log_content: Optional[str] = Field(
|
log_content: Optional[str] = Field(
|
||||||
None, description="日志内容, 仅在提取单条历史记录数据时返回"
|
default=None, description="日志内容, 仅在提取单条历史记录数据时返回"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -451,7 +500,7 @@ class ScriptCreateOut(OutBase):
|
|||||||
|
|
||||||
class ScriptGetIn(BaseModel):
|
class ScriptGetIn(BaseModel):
|
||||||
scriptId: Optional[str] = Field(
|
scriptId: Optional[str] = Field(
|
||||||
None, description="脚本ID, 未携带时表示获取所有脚本数据"
|
default=None, description="脚本ID, 未携带时表示获取所有脚本数据"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -498,7 +547,7 @@ class UserInBase(BaseModel):
|
|||||||
|
|
||||||
class UserGetIn(UserInBase):
|
class UserGetIn(UserInBase):
|
||||||
userId: Optional[str] = Field(
|
userId: Optional[str] = Field(
|
||||||
None, description="用户ID, 未携带时表示获取所有用户数据"
|
default=None, description="用户ID, 未携带时表示获取所有用户数据"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -547,7 +596,7 @@ class PlanCreateOut(OutBase):
|
|||||||
|
|
||||||
class PlanGetIn(BaseModel):
|
class PlanGetIn(BaseModel):
|
||||||
planId: Optional[str] = Field(
|
planId: Optional[str] = Field(
|
||||||
None, description="计划ID, 未携带时表示获取所有计划数据"
|
default=None, description="计划ID, 未携带时表示获取所有计划数据"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -576,7 +625,7 @@ class QueueCreateOut(OutBase):
|
|||||||
|
|
||||||
class QueueGetIn(BaseModel):
|
class QueueGetIn(BaseModel):
|
||||||
queueId: Optional[str] = Field(
|
queueId: Optional[str] = Field(
|
||||||
None, description="队列ID, 未携带时表示获取所有队列数据"
|
default=None, description="队列ID, 未携带时表示获取所有队列数据"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -606,7 +655,7 @@ class QueueSetInBase(BaseModel):
|
|||||||
|
|
||||||
class TimeSetGetIn(QueueSetInBase):
|
class TimeSetGetIn(QueueSetInBase):
|
||||||
timeSetId: Optional[str] = Field(
|
timeSetId: Optional[str] = Field(
|
||||||
None, description="时间设置ID, 未携带时表示获取所有时间设置数据"
|
default=None, description="时间设置ID, 未携带时表示获取所有时间设置数据"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -637,7 +686,7 @@ class TimeSetReorderIn(QueueSetInBase):
|
|||||||
|
|
||||||
class QueueItemGetIn(QueueSetInBase):
|
class QueueItemGetIn(QueueSetInBase):
|
||||||
queueItemId: Optional[str] = Field(
|
queueItemId: Optional[str] = Field(
|
||||||
None, description="队列项ID, 未携带时表示获取所有队列项数据"
|
default=None, description="队列项ID, 未携带时表示获取所有队列项数据"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -683,7 +732,10 @@ class TaskCreateOut(OutBase):
|
|||||||
websocketId: str = Field(..., description="新创建的任务ID")
|
websocketId: str = Field(..., description="新创建的任务ID")
|
||||||
|
|
||||||
|
|
||||||
class TaskMessage(BaseModel):
|
class WebSocketMessage(BaseModel):
|
||||||
|
taskId: Optional[str] = Field(
|
||||||
|
default=None, description="任务ID, 不存在时表示消息来自主程序"
|
||||||
|
)
|
||||||
type: Literal["Update", "Message", "Info", "Signal"] = Field(
|
type: Literal["Update", "Message", "Info", "Signal"] = Field(
|
||||||
...,
|
...,
|
||||||
description="消息类型 Update: 更新数据, Message: 请求弹出对话框, Info: 需要在UI显示的消息, Signal: 程序信号",
|
description="消息类型 Update: 更新数据, Message: 请求弹出对话框, Info: 需要在UI显示的消息, Signal: 程序信号",
|
||||||
|
|||||||
163
app/task/MAA.py
163
app/task/MAA.py
@@ -26,13 +26,12 @@ import subprocess
|
|||||||
import shutil
|
import shutil
|
||||||
import win32com.client
|
import win32com.client
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from fastapi import WebSocket
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from jinja2 import Environment, FileSystemLoader
|
from jinja2 import Environment, FileSystemLoader
|
||||||
from typing import List, Dict, Optional
|
from typing import List, Dict, Optional
|
||||||
|
|
||||||
from app.core import Broadcast, Config, MaaConfig, MaaUserConfig
|
from app.core import Broadcast, Config, MaaConfig, MaaUserConfig
|
||||||
from app.models.schema import TaskMessage
|
from app.models.schema import WebSocketMessage
|
||||||
from app.models.ConfigBase import MultipleConfig
|
from app.models.ConfigBase import MultipleConfig
|
||||||
from app.services import Notify, System
|
from app.services import Notify, System
|
||||||
from app.utils import get_logger, LogMonitor, ProcessManager
|
from app.utils import get_logger, LogMonitor, ProcessManager
|
||||||
@@ -50,18 +49,14 @@ class MaaManager:
|
|||||||
"""MAA控制器"""
|
"""MAA控制器"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self, mode: str, script_id: uuid.UUID, user_id: Optional[uuid.UUID], ws_id: str
|
||||||
mode: str,
|
|
||||||
script_id: uuid.UUID,
|
|
||||||
user_id: Optional[uuid.UUID],
|
|
||||||
websocket: WebSocket,
|
|
||||||
):
|
):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
self.script_id = script_id
|
self.script_id = script_id
|
||||||
self.user_id = user_id
|
self.user_id = user_id
|
||||||
self.websocket = websocket
|
self.ws_id = ws_id
|
||||||
|
|
||||||
self.emulator_process_manager = ProcessManager()
|
self.emulator_process_manager = ProcessManager()
|
||||||
self.maa_process_manager = ProcessManager()
|
self.maa_process_manager = ProcessManager()
|
||||||
@@ -123,8 +118,10 @@ class MaaManager:
|
|||||||
self.check_result = self.check_config()
|
self.check_result = self.check_config()
|
||||||
if self.check_result != "Success!":
|
if self.check_result != "Success!":
|
||||||
logger.error(f"未通过配置检查:{self.check_result}")
|
logger.error(f"未通过配置检查:{self.check_result}")
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(type="Info", data={"Error": self.check_result}).model_dump()
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id, type="Info", data={"Error": self.check_result}
|
||||||
|
).model_dump()
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -188,16 +185,20 @@ class MaaManager:
|
|||||||
< self.script_config.get("Run", "ProxyTimesLimit")
|
< self.script_config.get("Run", "ProxyTimesLimit")
|
||||||
):
|
):
|
||||||
user["status"] = "运行"
|
user["status"] = "运行"
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
type="Update", data={"user_list": self.user_list}
|
taskId=self.ws_id,
|
||||||
|
type="Update",
|
||||||
|
data={"user_list": self.user_list},
|
||||||
).model_dump()
|
).model_dump()
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
user["status"] = "跳过"
|
user["status"] = "跳过"
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
type="Update", data={"user_list": self.user_list}
|
taskId=self.ws_id,
|
||||||
|
type="Update",
|
||||||
|
data={"user_list": self.user_list},
|
||||||
).model_dump()
|
).model_dump()
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
@@ -228,8 +229,9 @@ class MaaManager:
|
|||||||
"Data", "LastSklandDate"
|
"Data", "LastSklandDate"
|
||||||
) != datetime.now().strftime("%Y-%m-%d"):
|
) != datetime.now().strftime("%Y-%m-%d"):
|
||||||
|
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Update",
|
type="Update",
|
||||||
data={"log": "正在执行森空岛签到中\n请稍候~"},
|
data={"log": "正在执行森空岛签到中\n请稍候~"},
|
||||||
).model_dump()
|
).model_dump()
|
||||||
@@ -246,8 +248,9 @@ class MaaManager:
|
|||||||
logger.info(
|
logger.info(
|
||||||
f"用户: {user['user_id']} - 森空岛签到{type}: {'、'.join(user_list)}",
|
f"用户: {user['user_id']} - 森空岛签到{type}: {'、'.join(user_list)}",
|
||||||
)
|
)
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Info",
|
type="Info",
|
||||||
data={
|
data={
|
||||||
(
|
(
|
||||||
@@ -258,8 +261,9 @@ class MaaManager:
|
|||||||
)
|
)
|
||||||
if skland_result["总计"] == 0:
|
if skland_result["总计"] == 0:
|
||||||
logger.info(f"用户: {user['user_id']} - 森空岛签到失败")
|
logger.info(f"用户: {user['user_id']} - 森空岛签到失败")
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Info",
|
type="Info",
|
||||||
data={
|
data={
|
||||||
"Error": f"用户 {user['name']} 森空岛签到失败",
|
"Error": f"用户 {user['name']} 森空岛签到失败",
|
||||||
@@ -281,8 +285,9 @@ class MaaManager:
|
|||||||
logger.warning(
|
logger.warning(
|
||||||
f"用户: {user['user_id']} - 未配置森空岛签到Token,跳过森空岛签到"
|
f"用户: {user['user_id']} - 未配置森空岛签到Token,跳过森空岛签到"
|
||||||
)
|
)
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Info",
|
type="Info",
|
||||||
data={
|
data={
|
||||||
"Warning": f"用户 {user['name']} 未配置森空岛签到Token,跳过森空岛签到"
|
"Warning": f"用户 {user['name']} 未配置森空岛签到Token,跳过森空岛签到"
|
||||||
@@ -324,8 +329,9 @@ class MaaManager:
|
|||||||
logger.error(
|
logger.error(
|
||||||
f"用户: {user['user_id']} - 未找到日常详细配置文件"
|
f"用户: {user['user_id']} - 未找到日常详细配置文件"
|
||||||
)
|
)
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Info",
|
type="Info",
|
||||||
data={"Error": f"未找到 {user['name']} 的详细配置文件"},
|
data={"Error": f"未找到 {user['name']} 的详细配置文件"},
|
||||||
).model_dump()
|
).model_dump()
|
||||||
@@ -334,8 +340,9 @@ class MaaManager:
|
|||||||
break
|
break
|
||||||
|
|
||||||
# 更新当前模式到界面
|
# 更新当前模式到界面
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Update",
|
type="Update",
|
||||||
data={
|
data={
|
||||||
"user_status": {
|
"user_status": {
|
||||||
@@ -417,8 +424,9 @@ class MaaManager:
|
|||||||
self.emulator_arguments = shortcut.Arguments.split()
|
self.emulator_arguments = shortcut.Arguments.split()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(f"解析快捷方式时出现异常:{e}")
|
logger.exception(f"解析快捷方式时出现异常:{e}")
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Info",
|
type="Info",
|
||||||
data={
|
data={
|
||||||
"Error": f"解析快捷方式时出现异常:{e}",
|
"Error": f"解析快捷方式时出现异常:{e}",
|
||||||
@@ -429,8 +437,9 @@ class MaaManager:
|
|||||||
break
|
break
|
||||||
elif not self.emulator_path.exists():
|
elif not self.emulator_path.exists():
|
||||||
logger.error(f"模拟器快捷方式不存在:{self.emulator_path}")
|
logger.error(f"模拟器快捷方式不存在:{self.emulator_path}")
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Info",
|
type="Info",
|
||||||
data={
|
data={
|
||||||
"Error": f"模拟器快捷方式 {self.emulator_path} 不存在",
|
"Error": f"模拟器快捷方式 {self.emulator_path} 不存在",
|
||||||
@@ -480,8 +489,9 @@ class MaaManager:
|
|||||||
logger.warning(f"释放ADB时出现异常:{e}")
|
logger.warning(f"释放ADB时出现异常:{e}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(f"释放ADB时出现异常:{e}")
|
logger.exception(f"释放ADB时出现异常:{e}")
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Info",
|
type="Info",
|
||||||
data={"Warning": f"释放ADB时出现异常:{e}"},
|
data={"Warning": f"释放ADB时出现异常:{e}"},
|
||||||
).model_dump()
|
).model_dump()
|
||||||
@@ -497,8 +507,9 @@ class MaaManager:
|
|||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(f"启动模拟器时出现异常:{e}")
|
logger.exception(f"启动模拟器时出现异常:{e}")
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Info",
|
type="Info",
|
||||||
data={
|
data={
|
||||||
"Error": "启动模拟器时出现异常,请检查MAA中模拟器路径设置"
|
"Error": "启动模拟器时出现异常,请检查MAA中模拟器路径设置"
|
||||||
@@ -544,8 +555,9 @@ class MaaManager:
|
|||||||
logger.info(
|
logger.info(
|
||||||
f"用户: {user['user_id']} - MAA进程完成代理任务"
|
f"用户: {user['user_id']} - MAA进程完成代理任务"
|
||||||
)
|
)
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Update",
|
type="Update",
|
||||||
data={
|
data={
|
||||||
"log": "检测到MAA进程完成代理任务\n正在等待相关程序结束\n请等待10s"
|
"log": "检测到MAA进程完成代理任务\n正在等待相关程序结束\n请等待10s"
|
||||||
@@ -559,8 +571,9 @@ class MaaManager:
|
|||||||
)
|
)
|
||||||
# 打印中止信息
|
# 打印中止信息
|
||||||
# 此时,log变量内存储的就是出现异常的日志信息,可以保存或发送用于问题排查
|
# 此时,log变量内存储的就是出现异常的日志信息,可以保存或发送用于问题排查
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Update",
|
type="Update",
|
||||||
data={
|
data={
|
||||||
"log": f"{self.maa_result}\n正在中止相关程序\n请等待10s"
|
"log": f"{self.maa_result}\n正在中止相关程序\n请等待10s"
|
||||||
@@ -602,8 +615,9 @@ class MaaManager:
|
|||||||
logger.warning(f"释放ADB时出现异常:{e}")
|
logger.warning(f"释放ADB时出现异常:{e}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(f"释放ADB时出现异常:{e}")
|
logger.exception(f"释放ADB时出现异常:{e}")
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Info",
|
type="Info",
|
||||||
data={"Error": f"释放ADB时出现异常:{e}"},
|
data={"Error": f"释放ADB时出现异常:{e}"},
|
||||||
).model_dump()
|
).model_dump()
|
||||||
@@ -674,8 +688,9 @@ class MaaManager:
|
|||||||
|
|
||||||
logger.info(f"检测到MAA更新,正在执行更新动作")
|
logger.info(f"检测到MAA更新,正在执行更新动作")
|
||||||
|
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Update",
|
type="Update",
|
||||||
data={
|
data={
|
||||||
"log": "检测到MAA存在更新\nMAA正在执行更新动作\n请等待10s"
|
"log": "检测到MAA存在更新\nMAA正在执行更新动作\n请等待10s"
|
||||||
@@ -714,9 +729,11 @@ class MaaManager:
|
|||||||
logger.info(f"开始排查用户: {user['user_id']}")
|
logger.info(f"开始排查用户: {user['user_id']}")
|
||||||
|
|
||||||
user["status"] = "运行"
|
user["status"] = "运行"
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
type="Update", data={"user_list": self.user_list}
|
taskId=self.ws_id,
|
||||||
|
type="Update",
|
||||||
|
data={"user_list": self.user_list},
|
||||||
).model_dump()
|
).model_dump()
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -759,8 +776,9 @@ class MaaManager:
|
|||||||
f"用户: {user['user_id']} - MAA进程成功登录PRTS",
|
f"用户: {user['user_id']} - MAA进程成功登录PRTS",
|
||||||
)
|
)
|
||||||
self.run_book["SignIn"] = True
|
self.run_book["SignIn"] = True
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Update",
|
type="Update",
|
||||||
data={"log": "检测到MAA进程成功登录PRTS"},
|
data={"log": "检测到MAA进程成功登录PRTS"},
|
||||||
).model_dump()
|
).model_dump()
|
||||||
@@ -769,8 +787,9 @@ class MaaManager:
|
|||||||
logger.error(
|
logger.error(
|
||||||
f"用户: {user['user_id']} - MAA未能正确登录到PRTS: {self.maa_result}"
|
f"用户: {user['user_id']} - MAA未能正确登录到PRTS: {self.maa_result}"
|
||||||
)
|
)
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Update",
|
type="Update",
|
||||||
data={
|
data={
|
||||||
"log": f"{self.maa_result}\n正在中止相关程序\n请等待10s"
|
"log": f"{self.maa_result}\n正在中止相关程序\n请等待10s"
|
||||||
@@ -791,8 +810,9 @@ class MaaManager:
|
|||||||
else:
|
else:
|
||||||
|
|
||||||
uid = str(uuid.uuid4())
|
uid = str(uuid.uuid4())
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Message",
|
type="Message",
|
||||||
data={
|
data={
|
||||||
"message_id": uid,
|
"message_id": uid,
|
||||||
@@ -810,8 +830,9 @@ class MaaManager:
|
|||||||
if self.run_book["SignIn"]:
|
if self.run_book["SignIn"]:
|
||||||
|
|
||||||
uid = str(uuid.uuid4())
|
uid = str(uuid.uuid4())
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Message",
|
type="Message",
|
||||||
data={
|
data={
|
||||||
"message_id": uid,
|
"message_id": uid,
|
||||||
@@ -827,9 +848,11 @@ class MaaManager:
|
|||||||
|
|
||||||
await self.result_record()
|
await self.result_record()
|
||||||
|
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
type="Update", data={"user_list": self.user_list}
|
taskId=self.ws_id,
|
||||||
|
type="Update",
|
||||||
|
data={"user_list": self.user_list},
|
||||||
).model_dump()
|
).model_dump()
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -906,9 +929,9 @@ class MaaManager:
|
|||||||
)
|
)
|
||||||
self.user_list[self.index]["status"] = "异常"
|
self.user_list[self.index]["status"] = "异常"
|
||||||
|
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
type="Update", data={"user_list": self.user_list}
|
taskId=self.ws_id, type="Update", data={"user_list": self.user_list}
|
||||||
).model_dump()
|
).model_dump()
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1085,8 +1108,9 @@ class MaaManager:
|
|||||||
async def search_ADB_address(self) -> None:
|
async def search_ADB_address(self) -> None:
|
||||||
"""搜索ADB实际地址"""
|
"""搜索ADB实际地址"""
|
||||||
|
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Update",
|
type="Update",
|
||||||
data={
|
data={
|
||||||
"log": f"即将搜索ADB实际地址\n正在等待模拟器完成启动\n请等待{self.wait_time}s"
|
"log": f"即将搜索ADB实际地址\n正在等待模拟器完成启动\n请等待{self.wait_time}s"
|
||||||
@@ -1175,8 +1199,10 @@ class MaaManager:
|
|||||||
# 更新MAA日志
|
# 更新MAA日志
|
||||||
if await self.maa_process_manager.is_running():
|
if await self.maa_process_manager.is_running():
|
||||||
|
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(type="Update", data={"log": log}).model_dump()
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id, type="Update", data={"log": log}
|
||||||
|
).model_dump()
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.mode == "自动代理":
|
if self.mode == "自动代理":
|
||||||
@@ -1600,13 +1626,14 @@ class MaaManager:
|
|||||||
logger.warning(
|
logger.warning(
|
||||||
f"未选择用户 {self.cur_user_data.get('Info', 'Name')} 的自定义基建配置文件"
|
f"未选择用户 {self.cur_user_data.get('Info', 'Name')} 的自定义基建配置文件"
|
||||||
)
|
)
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Info",
|
type="Info",
|
||||||
data={
|
data={
|
||||||
"warning": f"未选择用户 {self.cur_user_data.get('Info', 'Name')} 的自定义基建配置文件"
|
"warning": f"未选择用户 {self.cur_user_data.get('Info', 'Name')} 的自定义基建配置文件"
|
||||||
},
|
},
|
||||||
)
|
).model_dump()
|
||||||
)
|
)
|
||||||
data["Configurations"]["Default"][
|
data["Configurations"]["Default"][
|
||||||
"Infrast.CustomInfrastEnabled"
|
"Infrast.CustomInfrastEnabled"
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ from typing import Union, List, Dict, Optional
|
|||||||
|
|
||||||
|
|
||||||
from app.core import Config, GeneralConfig, GeneralUserConfig
|
from app.core import Config, GeneralConfig, GeneralUserConfig
|
||||||
from app.models.schema import TaskMessage
|
from app.models.schema import WebSocketMessage
|
||||||
from app.models.ConfigBase import MultipleConfig
|
from app.models.ConfigBase import MultipleConfig
|
||||||
from app.services import Notify, System
|
from app.services import Notify, System
|
||||||
from app.utils import get_logger, LogMonitor, ProcessManager, strptime
|
from app.utils import get_logger, LogMonitor, ProcessManager, strptime
|
||||||
@@ -46,18 +46,14 @@ class GeneralManager:
|
|||||||
"""通用脚本通用控制器"""
|
"""通用脚本通用控制器"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self, mode: str, script_id: uuid.UUID, user_id: Optional[uuid.UUID], ws_id: str
|
||||||
mode: str,
|
|
||||||
script_id: uuid.UUID,
|
|
||||||
user_id: Optional[uuid.UUID],
|
|
||||||
websocket: WebSocket,
|
|
||||||
):
|
):
|
||||||
super(GeneralManager, self).__init__()
|
super(GeneralManager, self).__init__()
|
||||||
|
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
self.script_id = script_id
|
self.script_id = script_id
|
||||||
self.user_id = user_id
|
self.user_id = user_id
|
||||||
self.websocket = websocket
|
self.ws_id = ws_id
|
||||||
|
|
||||||
self.game_process_manager = ProcessManager()
|
self.game_process_manager = ProcessManager()
|
||||||
self.general_process_manager = ProcessManager()
|
self.general_process_manager = ProcessManager()
|
||||||
@@ -164,8 +160,10 @@ class GeneralManager:
|
|||||||
self.check_result = self.check_config()
|
self.check_result = self.check_config()
|
||||||
if self.check_result != "Success!":
|
if self.check_result != "Success!":
|
||||||
logger.error(f"未通过配置检查:{self.check_result}")
|
logger.error(f"未通过配置检查:{self.check_result}")
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(type="Info", data={"Error": self.check_result}).model_dump()
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id, type="Info", data={"Error": self.check_result}
|
||||||
|
).model_dump()
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -229,16 +227,20 @@ class GeneralManager:
|
|||||||
< self.script_config.get("Run", "ProxyTimesLimit")
|
< self.script_config.get("Run", "ProxyTimesLimit")
|
||||||
):
|
):
|
||||||
user["status"] = "运行"
|
user["status"] = "运行"
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
type="Update", data={"user_list": self.user_list}
|
taskId=self.ws_id,
|
||||||
|
type="Update",
|
||||||
|
data={"user_list": self.user_list},
|
||||||
).model_dump()
|
).model_dump()
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
user["status"] = "跳过"
|
user["status"] = "跳过"
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
type="Update", data={"user_list": self.user_list}
|
taskId=self.ws_id,
|
||||||
|
type="Update",
|
||||||
|
data={"user_list": self.user_list},
|
||||||
).model_dump()
|
).model_dump()
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
@@ -254,8 +256,9 @@ class GeneralManager:
|
|||||||
).exists():
|
).exists():
|
||||||
|
|
||||||
logger.error(f"用户: {user['user_id']} - 未找到配置文件")
|
logger.error(f"用户: {user['user_id']} - 未找到配置文件")
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Info",
|
type="Info",
|
||||||
data={"Error": f"未找到 {user['user_id']} 的配置文件"},
|
data={"Error": f"未找到 {user['user_id']} 的配置文件"},
|
||||||
).model_dump()
|
).model_dump()
|
||||||
@@ -306,8 +309,9 @@ class GeneralManager:
|
|||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(f"启动游戏/模拟器时出现异常:{e}")
|
logger.exception(f"启动游戏/模拟器时出现异常:{e}")
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Info",
|
type="Info",
|
||||||
data={"Error": f"启动游戏/模拟器时出现异常:{e}"},
|
data={"Error": f"启动游戏/模拟器时出现异常:{e}"},
|
||||||
).model_dump()
|
).model_dump()
|
||||||
@@ -326,8 +330,9 @@ class GeneralManager:
|
|||||||
seconds=self.script_config.get("Game", "WaitTime") + 10
|
seconds=self.script_config.get("Game", "WaitTime") + 10
|
||||||
)
|
)
|
||||||
|
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Update",
|
type="Update",
|
||||||
data={
|
data={
|
||||||
"log": f"正在等待游戏/模拟器完成启动\n请等待{self.script_config.get('Game', 'WaitTime')}s"
|
"log": f"正在等待游戏/模拟器完成启动\n请等待{self.script_config.get('Game', 'WaitTime')}s"
|
||||||
@@ -368,8 +373,9 @@ class GeneralManager:
|
|||||||
logger.info(
|
logger.info(
|
||||||
f"用户: {user['user_id']} - 通用脚本进程完成代理任务"
|
f"用户: {user['user_id']} - 通用脚本进程完成代理任务"
|
||||||
)
|
)
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Update",
|
type="Update",
|
||||||
data={
|
data={
|
||||||
"log": "检测到通用脚本进程完成代理任务\n正在等待相关程序结束\n请等待10s"
|
"log": "检测到通用脚本进程完成代理任务\n正在等待相关程序结束\n请等待10s"
|
||||||
@@ -425,8 +431,9 @@ class GeneralManager:
|
|||||||
)
|
)
|
||||||
# 打印中止信息
|
# 打印中止信息
|
||||||
# 此时,log变量内存储的就是出现异常的日志信息,可以保存或发送用于问题排查
|
# 此时,log变量内存储的就是出现异常的日志信息,可以保存或发送用于问题排查
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id,
|
||||||
type="Update",
|
type="Update",
|
||||||
data={
|
data={
|
||||||
"log": f"{self.general_result}\n正在中止相关程序\n请等待10s"
|
"log": f"{self.general_result}\n正在中止相关程序\n请等待10s"
|
||||||
@@ -768,8 +775,10 @@ class GeneralManager:
|
|||||||
# 更新日志
|
# 更新日志
|
||||||
if await self.general_process_manager.is_running():
|
if await self.general_process_manager.is_running():
|
||||||
|
|
||||||
await self.websocket.send_json(
|
await Config.send_json(
|
||||||
TaskMessage(type="Update", data={"log": log}).model_dump()
|
WebSocketMessage(
|
||||||
|
taskId=self.ws_id, type="Update", data={"log": log}
|
||||||
|
).model_dump()
|
||||||
)
|
)
|
||||||
|
|
||||||
if "自动代理" in self.mode:
|
if "自动代理" in self.mode:
|
||||||
|
|||||||
2
main.py
2
main.py
@@ -79,6 +79,7 @@ def main():
|
|||||||
|
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
from app.api import (
|
from app.api import (
|
||||||
|
core_router,
|
||||||
info_router,
|
info_router,
|
||||||
scripts_router,
|
scripts_router,
|
||||||
plan_router,
|
plan_router,
|
||||||
@@ -103,6 +104,7 @@ def main():
|
|||||||
allow_headers=["*"], # 允许所有请求头
|
allow_headers=["*"], # 允许所有请求头
|
||||||
)
|
)
|
||||||
|
|
||||||
|
app.include_router(core_router)
|
||||||
app.include_router(info_router)
|
app.include_router(info_router)
|
||||||
app.include_router(scripts_router)
|
app.include_router(scripts_router)
|
||||||
app.include_router(plan_router)
|
app.include_router(plan_router)
|
||||||
|
|||||||
Reference in New Issue
Block a user