162 lines
4.9 KiB
Python
162 lines
4.9 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""account ensure-web — pick if present, otherwise add-web then pick."""
|
|
from typing import Optional
|
|
|
|
from db.accounts_repo import count_active_accounts
|
|
from db.connection import get_conn, init_db
|
|
from service._svc_common import PlatformCallerMeta, _err_json, _resolve_or_auto_register, _say
|
|
from service.account_add_commands import create_web_account_record
|
|
from service.account_query_commands import cmd_account_pick_web
|
|
from util.logging_config import get_skill_logger
|
|
from util.platforms import seed_platforms
|
|
|
|
|
|
def cmd_account_ensure_web(
|
|
platform_input: str,
|
|
*,
|
|
login_id: Optional[str] = None,
|
|
login_id_type: str = "unknown",
|
|
label: Optional[str] = None,
|
|
tenant_id: Optional[str] = None,
|
|
environment: Optional[str] = None,
|
|
role: Optional[str] = None,
|
|
provider_code: Optional[str] = None,
|
|
url: Optional[str] = None,
|
|
extra_json_str: Optional[str] = None,
|
|
profile_dir_override: Optional[str] = None,
|
|
auth_strategy: Optional[str] = None,
|
|
session_persistent: Optional[int] = None,
|
|
device_fingerprint: Optional[str] = None,
|
|
do_lease: bool = False,
|
|
ttl_sec: int = 900,
|
|
holder: Optional[str] = None,
|
|
purpose: Optional[str] = None,
|
|
platform_meta: Optional[PlatformCallerMeta] = None,
|
|
) -> None:
|
|
"""Pick a web account; if none exist for filters, create one then pick.
|
|
|
|
Does NOT create a new account when matching accounts exist but are all leased.
|
|
Success stdout matches ``account pick-web`` (plus ``account_ensured`` when created).
|
|
"""
|
|
log = get_skill_logger()
|
|
log.info(
|
|
"account_ensure_web_attempt platform=%s env=%s tenant=%s role=%s lease=%s",
|
|
platform_input,
|
|
environment,
|
|
tenant_id,
|
|
role,
|
|
do_lease,
|
|
)
|
|
|
|
key = _resolve_or_auto_register(platform_input, platform_meta)
|
|
if not key:
|
|
return
|
|
|
|
init_db()
|
|
conn = get_conn()
|
|
try:
|
|
seed_platforms(conn)
|
|
finally:
|
|
conn.close()
|
|
|
|
existing_count = count_active_accounts(
|
|
platform_key=key,
|
|
environment=environment,
|
|
tenant_id=tenant_id,
|
|
role=role,
|
|
)
|
|
created = False
|
|
if existing_count == 0:
|
|
create_env = (environment or "").strip() or "production"
|
|
create_role = (role or "").strip() or "default"
|
|
create_label = (label or "").strip() or None
|
|
if not create_label:
|
|
create_label = f"{key} 默认"
|
|
|
|
created_payload = create_web_account_record(
|
|
platform_input,
|
|
login_id,
|
|
login_id_type,
|
|
create_label,
|
|
tenant_id,
|
|
create_env,
|
|
create_role,
|
|
provider_code,
|
|
url,
|
|
extra_json_str,
|
|
profile_dir_override,
|
|
auth_strategy=auth_strategy,
|
|
session_persistent=session_persistent,
|
|
device_fingerprint=device_fingerprint,
|
|
platform_meta=platform_meta,
|
|
platform_key=key,
|
|
)
|
|
if not created_payload:
|
|
return
|
|
created = True
|
|
log.info(
|
|
"account_ensure_web_created id=%s platform=%s profile_dir=%s",
|
|
created_payload.get("id"),
|
|
key,
|
|
created_payload.get("profile_dir"),
|
|
)
|
|
else:
|
|
log.info(
|
|
"account_ensure_web_reuse platform=%s existing_active=%s",
|
|
key,
|
|
existing_count,
|
|
)
|
|
|
|
# Capture pick output so we can annotate / remap lease-busy errors.
|
|
import io
|
|
import json
|
|
import sys
|
|
|
|
buf = io.StringIO()
|
|
old_out = sys.stdout
|
|
sys.stdout = buf
|
|
try:
|
|
cmd_account_pick_web(
|
|
platform_input,
|
|
environment=environment,
|
|
tenant_id=tenant_id,
|
|
role=role,
|
|
do_lease=do_lease,
|
|
ttl_sec=ttl_sec,
|
|
holder=holder,
|
|
purpose=purpose,
|
|
platform_meta=platform_meta,
|
|
)
|
|
finally:
|
|
sys.stdout = old_out
|
|
|
|
raw = buf.getvalue().strip()
|
|
if not raw:
|
|
_say(_err_json("ERROR:NO_ACCOUNT", "ensure 后未能挑选到账号。"))
|
|
return
|
|
|
|
try:
|
|
payload = json.loads(raw)
|
|
except json.JSONDecodeError:
|
|
_say(raw)
|
|
return
|
|
|
|
if isinstance(payload, dict) and payload.get("success") is False:
|
|
err = (payload.get("error") or {}) if isinstance(payload.get("error"), dict) else {}
|
|
code = str(err.get("code") or "")
|
|
if code == "ERROR:NO_ACCOUNT" and existing_count > 0 and not created:
|
|
_say(_err_json(
|
|
"ERROR:LEASE_CONFLICT",
|
|
"该平台下已有账号,但均被其他任务占用。请稍后重试或释放租约;不会自动新建账号。",
|
|
))
|
|
return
|
|
_say(raw)
|
|
return
|
|
|
|
if isinstance(payload, dict) and created:
|
|
payload["account_ensured"] = True
|
|
_say(json.dumps(payload, ensure_ascii=False))
|
|
return
|
|
|
|
_say(raw)
|