Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
242 changes: 242 additions & 0 deletions app/api/scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from fastapi import APIRouter, Body

from app.core import Config
from app.models.config import OkNteConfig as RuntimeOkNteConfig
from app.models.schema import *

router = APIRouter(prefix="/api/scripts", tags=["脚本管理"])
Expand All @@ -48,13 +49,44 @@ def _okww_config_file_path(config_dir: Path, filename: str) -> Path:
return config_dir / filename


def _oknte_script_config(script_id: str) -> tuple[uuid.UUID, RuntimeOkNteConfig]:
script_uid = uuid.UUID(script_id)
script_config = Config.ScriptConfig[script_uid]
if not isinstance(script_config, RuntimeOkNteConfig):
raise ValueError("脚本配置类型错误, 不是 OK-NTE 类型")
return script_uid, script_config


def _oknte_legacy_mas_config_dir(script_id: str) -> Path:
script_uid, _ = _oknte_script_config(script_id)
return Path.cwd() / "data" / str(script_uid) / "Default" / "ConfigFile"


def _oknte_mas_config_dir(script_id: str, user_id: str) -> Path:
script_uid, _ = _oknte_script_config(script_id)
user_uid = uuid.UUID(user_id)
return Path.cwd() / "data" / str(script_uid) / str(user_uid) / "ConfigFile"


def _oknte_config_file_path(config_dir: Path, filename: str) -> Path:
file_path = Path(filename)
if (
file_path.name != filename
or file_path.is_absolute()
or ".." in file_path.parts
):
raise ValueError("配置文件名非法")
return config_dir / filename
Comment on lines +52 to +79

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这块看看要不后续你们ok系列的统一用一套轮子,和@1w1w11w1讨论一下(



SCRIPT_BOOK = {
"MaaConfig": MaaConfig,
"SrcConfig": SrcConfig,
"MaaEndConfig": MaaEndConfig,
"M9AConfig": M9AConfig,
"GeneralConfig": GeneralConfig,
"OkwwConfig": OkwwConfig,
"OkNteConfig": OkNteConfig,
"HSRConfig": HSRConfig,
}
USER_BOOK = {
Expand All @@ -64,6 +96,7 @@ def _okww_config_file_path(config_dir: Path, filename: str) -> Path:
"M9AConfig": M9AUserConfig,
"GeneralConfig": GeneralUserConfig,
"OkwwConfig": OkwwUserConfig,
"OkNteConfig": OkNteUserConfig,
"HSRConfig": HSRUserConfig,
}

Expand Down Expand Up @@ -878,3 +911,212 @@ async def batch_update_okww_configs(
"status": "error",
"message": f"{type(e).__name__}: {str(e)}",
}


@router.post(
"/oknte/configs/list",
tags=["OKNTE"],
summary="获取 OK-NTE 配置文件列表及 schema",
status_code=200,
)
async def get_oknte_configs_list(script_id: str, user_id: str):
"""
获取 OK-NTE 配置文件列表及 schema 定义。
读写用户配置目录(data/{script_id}/{user_id}/ConfigFile/),
若为空则自动从 ok-nte configs 目录初始化默认配置。

Args:
script_id: OK-NTE 脚本 ID
user_id: 用户 ID

Returns:
dict: 包含配置文件列表和 schema 的响应
"""
try:
import json
import shutil
from app.task.OkNte.config_schema import (
get_all_config_info, build_fields_for_config, load_oknte_option_labels,
)

_, script_config = _oknte_script_config(script_id)

# 从 ok-nte 安装目录加载翻译 → option_labels
root_path = script_config.get("Info", "RootPath")
option_labels = load_oknte_option_labels(root_path) if root_path else {}

# 用户配置目录;旧版 Default 目录仅作为升级后的初始化来源。
mas_config_dir = _oknte_mas_config_dir(script_id, user_id)

# ok-nte 源配置目录(用于自动初始化)
legacy_config_dir = _oknte_legacy_mas_config_dir(script_id)
oknte_configs_dir = (
legacy_config_dir
if legacy_config_dir.is_dir() and any(legacy_config_dir.iterdir())
else None
)
if oknte_configs_dir is None:
raw_config_path = script_config.get("Script", "ConfigPath")
oknte_configs_dir = Path(raw_config_path) if raw_config_path else None
if not oknte_configs_dir or not oknte_configs_dir.exists():
if root_path:
root = Path(root_path)
packaged_dir = root / "data" / "apps" / "ok-nte" / "working" / "configs"
source_dir = root / "configs"
oknte_configs_dir = packaged_dir if packaged_dir.is_dir() else source_dir

# 自动初始化:用户目录为空时从旧版共享目录或 ok-nte configs 复制默认配置
need_init = not mas_config_dir.exists() or not any(mas_config_dir.iterdir())
if need_init and oknte_configs_dir and oknte_configs_dir.is_dir():
mas_config_dir.mkdir(parents=True, exist_ok=True)
shutil.copytree(oknte_configs_dir, mas_config_dir, dirs_exist_ok=True)

configs_info = get_all_config_info()

# 读取 per-user JSON 配置,通过 build_fields_for_config 构建字段列表
result = []
for info in configs_info:
filename = info["filename"]
filepath = _oknte_config_file_path(mas_config_dir, filename)
current_data: dict[str, Any] = {}
if filepath.exists():
try:
current_data = json.loads(filepath.read_text(encoding="utf-8"))
except Exception:
pass

fields = build_fields_for_config(filename, current_data, option_labels)

result.append({
**info,
"fields": fields,
"currentData": current_data,
})

return {
"code": 200,
"status": "success",
"message": f"共 {len(result)} 个配置文件",
"data": result,
"optionLabels": option_labels,
"configPath": str(mas_config_dir) if mas_config_dir else None,
}
except Exception as e:
return {
"code": 500,
"status": "error",
"message": f"{type(e).__name__}: {str(e)}",
"data": [],
}


@router.post(
"/oknte/configs/update",
tags=["OKNTE"],
summary="更新 OK-NTE 配置文件",
status_code=200,
)
async def update_oknte_config(
script_id: str = Body(...),
user_id: str = Body(...),
filename: str = Body(...),
data: dict = Body(...),
):
"""
更新 OK-NTE 配置文件

Args:
script_id: OK-NTE 脚本 ID
user_id: 用户 ID
filename: 配置文件名(如 DailyTask.json)
data: 要更新的配置数据

Returns:
dict: 操作结果
"""
try:
import json

# 写入用户配置目录
mas_config_dir = _oknte_mas_config_dir(script_id, user_id)
mas_config_dir.mkdir(parents=True, exist_ok=True)

filepath = _oknte_config_file_path(mas_config_dir, filename)

existing_data = {}
if filepath.exists():
with open(filepath, "r", encoding="utf-8") as f:
existing_data = json.load(f)

existing_data.update(data)

with open(filepath, "w", encoding="utf-8") as f:
json.dump(existing_data, f, ensure_ascii=False, indent=4)

return {
"code": 200,
"status": "success",
"message": f"配置文件 {filename} 已更新",
"data": existing_data,
}
except Exception as e:
return {
"code": 500,
"status": "error",
"message": f"{type(e).__name__}: {str(e)}",
}


@router.post(
"/oknte/configs/batch-update",
tags=["OKNTE"],
summary="批量更新 OK-NTE 配置文件",
status_code=200,
)
async def batch_update_oknte_configs(
script_id: str = Body(...),
user_id: str = Body(...),
configs: dict = Body(...),
):
"""
批量更新 OK-NTE 配置文件

Args:
script_id: OK-NTE 脚本 ID
user_id: 用户 ID
configs: { filename: data } 格式的配置数据

Returns:
dict: 操作结果
"""
try:
import json

# 写入用户配置目录
mas_config_dir = _oknte_mas_config_dir(script_id, user_id)
mas_config_dir.mkdir(parents=True, exist_ok=True)

updated_files = []
for filename, data in configs.items():
filepath = _oknte_config_file_path(mas_config_dir, filename)
existing_data = {}
if filepath.exists():
with open(filepath, "r", encoding="utf-8") as f:
existing_data = json.load(f)
existing_data.update(data)
with open(filepath, "w", encoding="utf-8") as f:
json.dump(existing_data, f, ensure_ascii=False, indent=4)
updated_files.append(filename)

return {
"code": 200,
"status": "success",
"message": f"已更新 {len(updated_files)} 个配置文件",
"data": updated_files,
}
except Exception as e:
return {
"code": 500,
"status": "error",
"message": f"{type(e).__name__}: {str(e)}",
}
Comment on lines +916 to +1122

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这边也是,感觉和okww基本没啥区别,后续可以和@1w1w11w1和群主商量下要不要抽出来,具体实现看着没啥问题(

16 changes: 14 additions & 2 deletions app/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
M9AConfig,
MaaEndConfig,
OkwwConfig,
OkNteConfig,
HSRConfig,
HSRUserConfig,
MaaPlanConfig,
Expand All @@ -56,6 +57,7 @@
MaaEndUserConfig,
GeneralUserConfig,
OkwwUserConfig,
OkNteUserConfig,
GlobalConfig,
CLASS_BOOK,
Webhook,
Expand Down Expand Up @@ -532,11 +534,18 @@ def _get_git_info():

async def add_script(
self,
script: Literal["MAA", "SRC", "General", "MaaEnd", "M9A", "Okww", "HSR"],
script: Literal["MAA", "SRC", "General", "MaaEnd", "M9A", "Okww", "OkNte", "HSR"],
script_id: str | None = None,
) -> tuple[
uuid.UUID,
MaaConfig | SrcConfig | GeneralConfig | MaaEndConfig | M9AConfig | OkwwConfig | HSRConfig,
MaaConfig
| SrcConfig
| GeneralConfig
| MaaEndConfig
| M9AConfig
| OkwwConfig
| OkNteConfig
| HSRConfig,
]:
"""添加脚本配置"""

Expand Down Expand Up @@ -822,6 +831,7 @@ async def add_user(self, script_id: str) -> tuple[
| MaaEndUserConfig
| M9AUserConfig
| OkwwUserConfig
| OkNteUserConfig
| HSRUserConfig,
]:
"""添加用户配置"""
Expand All @@ -839,6 +849,8 @@ async def add_user(self, script_id: str) -> tuple[
uid, config = await script_config.UserData.add(GeneralUserConfig)
elif isinstance(script_config, OkwwConfig):
uid, config = await script_config.UserData.add(OkwwUserConfig)
elif isinstance(script_config, OkNteConfig):
uid, config = await script_config.UserData.add(OkNteUserConfig)
elif isinstance(script_config, MaaEndConfig):
uid, config = await script_config.UserData.add(MaaEndUserConfig)
elif isinstance(script_config, M9AConfig):
Expand Down
4 changes: 4 additions & 0 deletions app/core/task_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
MaaEndConfig,
M9AConfig,
OkwwConfig,
OkNteConfig,
HSRConfig,
)
from app.services import System
Expand All @@ -44,6 +45,7 @@
MaaEndManager,
M9AManager,
OkwwManager,
OkNteManager,
HSRManager,
)
from app.utils.constants import POWER_SIGN_MAP
Expand Down Expand Up @@ -176,6 +178,8 @@ async def main_task(self):
task_item = GeneralManager(script_item)
elif isinstance(Config.ScriptConfig[current_script_uid], OkwwConfig):
task_item = OkwwManager(script_item)
elif isinstance(Config.ScriptConfig[current_script_uid], OkNteConfig):
task_item = OkNteManager(script_item)
elif isinstance(Config.ScriptConfig[current_script_uid], MaaEndConfig):
task_item = MaaEndManager(script_item)
elif isinstance(Config.ScriptConfig[current_script_uid], M9AConfig):
Expand Down
Loading