Skip to content
Merged
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
10 changes: 10 additions & 0 deletions app/models/config/script.py
Original file line number Diff line number Diff line change
Expand Up @@ -3057,6 +3057,14 @@ class TaskFields(ConfigGroup):
description="每日任务后运行的附加任务",
)

IfCustomArguments: bool = Field(
default_factory=lambda: False, description="启用自定义启动参数"
)
CustomArguments: str = Field(
default_factory=lambda: "-t DailyTask",
description="自定义启动参数,开启后原样传递给 ok-ww",
)

FarmNightmareNestForDailyEcho: bool = Field(
default_factory=lambda: True, description="使用梦魇巢穴完成日常声骸"
)
Expand Down Expand Up @@ -3096,6 +3104,8 @@ def getTags(self) -> str:
task_label = self.OKWW_TASK_BOOK.get(last_task_index, "未知")
if self.Data.LastTaskName == "MultiAccountConfigTask":
task_label = "原生多账号配置"
elif self.Data.LastTaskName == "CustomTask":
task_label = "自定义任务"
tags.append({"text": f"任务:{task_label}", "color": "orange"})
tags.append(_tag_remained_days(self))
tags.append(_tag_notes(self))
Expand Down
41 changes: 18 additions & 23 deletions app/task/Okww/AutoProxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
from datetime import datetime
from pathlib import Path

from packaging.version import InvalidVersion, Version

from app.config import ConfigCollection
from app.core import Notify, Publisher
from app.core.history import aggregate_data
Expand Down Expand Up @@ -60,6 +58,8 @@

from . import push_log as _push_log
from .tools import async_switch_account
from .tools.arguments import build_custom_arguments
from .tools.arguments import daily_task_argument as _daily_task_argument
from .tools.backup_archive import (
archive_mas_runtime_backup,
mas_config_dir,
Expand Down Expand Up @@ -139,24 +139,6 @@
_OKWW_LOG_TIME_FORMAT = "%Y-%m-%d %H:%M:%S,%f"


def _daily_task_argument(script_root: Path) -> str:
"""按已安装版本选择上游支持的日常任务参数。"""
app_config = json.loads(
(script_root / _OKWW_REL_APP_JSON).read_text(encoding="utf-8-sig")
)
if not isinstance(app_config, dict):
raise ValueError("OK-WW 启动器配置格式错误,请先在脚本启动器中完成安装或更新")
raw_version = app_config.get("current_version")
try:
version = Version(str(raw_version))
except InvalidVersion as exc:
raise ValueError(
"无法识别 OK-WW 当前版本,请先在脚本启动器中完成安装或更新"
) from exc
# 上游 f09ac771(ok-script 2.0.7b1);首个含此变更的预发布 tag。
return "DailyTask" if version >= Version("3.6.7b2") else "1"


def _okww_config_base(raw: object) -> str:
"""读取 OK-WW 配置来源(base 三态),并兼容旧版字面量。"""

Expand Down Expand Up @@ -271,6 +253,10 @@ async def check(self) -> str:
return "请设置ok-ww脚本路径"
if not (root / _OKWW_REL_APP_JSON).is_file():
return "请设置ok-ww脚本路径"
try:
self._build_run_arguments()
except ValueError as error:
return f"OK-WW 启动参数错误:{error}"
# 启动检查早于每日重置,旧日期的次数不参与今日上限判断。
curdate = datetime.now(tz=_utils_constants.UTC4).strftime("%Y-%m-%d")
proxy_times = (
Expand Down Expand Up @@ -444,13 +430,16 @@ async def prepare(self):

self.task_name = "DailyTask"
self.task_index = 1 if self.task_name == "DailyTask" else 0
self.okww_args = ["-t", _daily_task_argument(self.script_root_path), "-e"]
self.okww_args = self._build_run_arguments()
if self.cur_user_config.Task.IfCustomArguments:
self.task_name = "CustomTask"
self.task_index = 0

self.script_config_path = self.script_root_path / _OKWW_REL_CONFIG_DIR

async def _start_okww_with_current_arguments(self) -> None:
"""启动时刷新参数,自更新跨过兼容边界后用新参数重启。"""
daily = self.okww_args[1] in ("1", "DailyTask")
daily = self.task_name == "DailyTask"
while True:
if daily:
self.okww_args = [
Expand Down Expand Up @@ -481,6 +470,11 @@ async def _start_okww_with_current_arguments(self) -> None:
def _resolve_log_file_path(self) -> Path:
return self.script_log_path

def _build_run_arguments(self) -> list[str]:
if self.cur_user_config.Task.IfCustomArguments:
return build_custom_arguments(self.cur_user_config.Task.CustomArguments)
return ["-t", _daily_task_argument(self.script_config.Info.RootPath), "-e"]

def _apply_mas_overrides(self) -> None:
"""overlay 覆盖段:把 MAS 侧运行值覆盖到当前来源配置之上。

Expand Down Expand Up @@ -858,7 +852,7 @@ async def main_task(self):
# 开关在游戏配置区,依赖 Game.Enabled(未启用游戏配置则不生效);
# 用户未填写手机号时跳过不切换。
if (
self.task_name == "DailyTask"
self.task_name in ("DailyTask", "CustomTask")
and self.script_config.Game.AccountSwitchMethod == "MAS"
and self.script_config.Game.Enabled
and (self.game_manager is not None)
Expand Down Expand Up @@ -1052,6 +1046,7 @@ async def check_log(
success_logs = (
_OKWW_SUCCESS_LOG[:1]
if self.task_name == "MultiAccountConfigTask"
or self.cur_user_config.Task.IfCustomArguments
else _OKWW_SUCCESS_LOG
)
if any(needle in log for needle in success_logs):
Expand Down
21 changes: 15 additions & 6 deletions app/task/Okww/BatchProxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,7 @@ def __init__(
self, script_info, script_config, user_config, game_manager, *, participants
):
super().__init__(script_info, script_config, user_config, game_manager)
self.cur_user_item = UserItem(
user_id=self.cur_user_item.user_id,
name=self.cur_user_item.name if len(participants) == 1 else "OK-WW 批次",
status="等待",
)
# 准入检查始终保留真实账号节点;运行节点在 prepare 中另建。
self.participants = participants
self.succeeded = set()
self.pending = set()
Expand All @@ -54,6 +50,11 @@ def __init__(
self.account_failures = {}
self.attempted_accounts = set()

def _build_run_arguments(self) -> list[str]:
if self.cur_user_config.Task.IfCustomArguments:
return super()._build_run_arguments()
return ["-t", "MultiAccountConfigTask", "-e"]

async def check(self):
result = await super().check()
if result != "Pass":
Expand All @@ -72,6 +73,14 @@ async def check(self):

async def prepare(self):
await super().prepare()
# 内部轮次日志与真实账号的汇总记录隔离,单账号批次同样需要隔离。
self.cur_user_item = UserItem(
user_id=self.cur_user_item.user_id,
name=self.cur_user_item.name
if len(self.participants) == 1
else "OK-WW 批次",
status="等待",
)
today = datetime.now(tz=_utils_constants.UTC4)
for user in self.participants:
config = self.user_config[uuid.UUID(user.user_id)]
Expand All @@ -80,7 +89,7 @@ async def prepare(self):
config.Data.ProxyTimes = 0
await config.commit()
self.task_name = "MultiAccountConfigTask"
self.okww_args = ["-t", self.task_name, "-e"]
self.okww_args = self._build_run_arguments()
self.task_index = 0
# 原始账号历史独立于节点推送开关,关闭节点时也需保留日志。
if self._log_source is None:
Expand Down
32 changes: 32 additions & 0 deletions app/task/Okww/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

from fastapi import APIRouter
from pydantic import (
BaseModel,
Field,
)

Expand All @@ -37,6 +38,37 @@ class OkwwClientPathOut(OutBase):
logger = get_logger("托管管理 API")


class OkwwArgumentsIn(BaseModel):
scriptId: str
custom: bool = False
arguments: str = ""


class OkwwArgumentsOut(OutBase):
arguments: list[str] = Field(default_factory=list)
native_switch: bool = False


@router.post("/okww/startup-arguments", tags=["Get"], response_model=OkwwArgumentsOut)
async def preview_okww_arguments_api(data: OkwwArgumentsIn) -> OkwwArgumentsOut:
"""按实际启动规则预览参数,不启动脚本。"""
from .api_service import resolve_startup_arguments

try:
arguments, native = resolve_startup_arguments(
data.scriptId, custom=data.custom, arguments=data.arguments
)
return OkwwArgumentsOut(
code=200,
status="success",
message="",
arguments=arguments,
native_switch=native,
)
except (ValueError, KeyError, TypeError, OSError) as error:
return OkwwArgumentsOut(code=400, status="error", message=str(error))


@router.get(
"/okww/client-path",
tags=["Get"],
Expand Down
18 changes: 18 additions & 0 deletions app/task/Okww/api_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,21 @@ def resolve_client_path(script_id: str) -> Path:
launcher_path
)
return client_path


def resolve_startup_arguments(
script_id: str, *, custom: bool, arguments: str
) -> tuple[list[str], bool]:
from .tools.arguments import build_custom_arguments, daily_task_argument

config = Config.ScriptConfig[uuid.UUID(script_id)]
if not isinstance(config, RuntimeOkwwConfig):
raise TypeError("托管配置类型错误, 不是 OK-WW 类型")
native = config.Game.AccountSwitchMethod in ("OKWW", "OKWW_SINGLE")
if custom:
return build_custom_arguments(arguments), native
if native:
return ["-t", "MultiAccountConfigTask", "-e"], True
if config.Info.RootPath is None:
raise ValueError("请设置 ok-ww 脚本路径")
return ["-t", daily_task_argument(config.Info.RootPath), "-e"], False
33 changes: 26 additions & 7 deletions app/task/Okww/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,20 +289,28 @@ async def main_task(self):

if self.script_config.Game.AccountSwitchMethod == "OKWW":
participants = []
argument_groups = []
previous_arguments = None
for index, user in enumerate(self.script_info.user_list):
await self.script_info.set_current_index(index)
if await self.check_user_before_run(
user, self.user_config[uuid.UUID(user.user_id)]
):
candidate = AutoProxyTask(
candidate = BatchProxyTask(
self.script_info,
self.script_config,
self.user_config,
self.game_manager,
participants=[user],
)
result = await candidate.check()
if result == "Pass":
Comment thread
AthenaHibou marked this conversation as resolved.
Resolved
participants.append(user)
arguments = candidate._build_run_arguments()
if not argument_groups or arguments != previous_arguments:
argument_groups.append([])
argument_groups[-1].append(user)
previous_arguments = arguments
else:
await self.notify_user_check_failure(user, result)
if participants:
Expand All @@ -321,12 +329,23 @@ async def main_task(self):
for user in participants:
await self.notify_user_check_failure(user, result)
else:
try:
for user in participants:
self.record_user_run_start(user)
await self.spawn(method)
finally:
await self._restore_script_config_from_temp()
for group in argument_groups:
await self.script_info.set_current_index(
self.script_info.user_list.index(group[0])
)
method = BatchProxyTask(
self.script_info,
self.script_config,
self.user_config,
self.game_manager,
participants=group,
)
try:
for user in group:
self.record_user_run_start(user)
await self.spawn(method)
finally:
await self._restore_script_config_from_temp()
return

for _runtime_user_index in range(len(self.script_info.user_list)):
Expand Down
31 changes: 31 additions & 0 deletions app/task/Okww/tools/arguments.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""OK-WW 普通模式启动参数。"""

import json
from pathlib import Path

from packaging.version import InvalidVersion, Version

from app.task.proxy_helpers import split_args


def build_custom_arguments(arguments: str) -> list[str]:
"""按原样拆分用户参数,不补充或替换选项。"""
return split_args(arguments)


def daily_task_argument(script_root: Path) -> str:
"""按已安装版本选择上游支持的日常任务参数。"""
app_config = json.loads(
(script_root / "data/apps/ok-ww/app.json").read_text(encoding="utf-8-sig")
)
if not isinstance(app_config, dict):
raise ValueError("OK-WW 启动器配置格式错误,请先在脚本启动器中完成安装或更新")
raw_version = app_config.get("current_version")
try:
version = Version(str(raw_version))
except InvalidVersion as exc:
raise ValueError(
"无法识别 OK-WW 当前版本,请先在脚本启动器中完成安装或更新"
) from exc
# 上游 f09ac771(ok-script 2.0.7b1);首个含此变更的预发布 tag。
return "DailyTask" if version >= Version("3.6.7b2") else "1"
4 changes: 4 additions & 0 deletions app/task/Okww/tools/backup_archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ def mas_config_dir(script_id: str, owner: str) -> Path:
恢复时以当前值为准,回填旧值会静默翻转 shared/independent 来源。"""

_OVERLAY_TASK_KEYS = (
"IfCustomArguments",
"CustomArguments",
"WhichToFarm",
"WhichTacetSuppressionToFarm",
"WhichForgeryChallengeToFarm",
Expand Down Expand Up @@ -496,6 +498,8 @@ def restore_native_backup(config_path: Path, ts: str) -> None:
"""DailyTask.json 文件字段名 → MAS 账号配置 Task 键名(同一概念的两种 owner)"""

_OVERLAY_FIELD_LABELS = {
"IfCustomArguments": "自定义启动参数",
"CustomArguments": "启动参数",
"Id": "账号",
"Base": "配置文件来源",
**{overlay: _FIELD_LABELS[file] for file, overlay in _FILE_TO_OVERLAY_KEY.items()},
Expand Down
2 changes: 2 additions & 0 deletions changelog.d/feat-okww-custom-arguments.feat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
project: okww
支持为账号自定义启动参数
Loading
Loading