Files
butubb 98cdc39224 chore: 删除抖音养号任务类型,平台只保留 generic_steps
tasks/douyin/(task_type=douyin_nurture)整体删除,唯一任务类型是 generic_steps。
所有默认值/文档/接口示例同步改成 generic_steps:

- tasks/:删 douyin 包;__init__ 只注册 generic;base.py/generic 注释改为照 generic 抄
- 默认值:core/models.py(列默认 + 旧 JSON 迁移默认)、core/task_manager.py TaskJob、
  web/tasks_api.py 建任务默认、static/admin/tasks.js 新建任务默认
- core/task_manager.py:去掉 douyin 专属的"清理废弃 comment 参数"迁移块,改为**启动时告警**
  仍残留已删类型的任务(只告警不改数据);run_job_now 对已删类型直接返回明确错误,
  不再"报已触发、线程里静默失败"
- 清理残留:douyin_running 状态位(无任何读取方)、core/__init__、core/actions/*、
  core/logger.py 注释里的抖音示例
- 文档:README(特性/目录树/类型表/参数表/示例)、TASK_DEV(目录树/注册说明/模板引用)、
  ARCHITECTURE(注册示例/action 注册表示例)、API.md(task_types 与任务 JSON 示例)、
  AI_TASK_GEN(P1 去掉 douyin 预设)、DEVELOPMENT
- 注:示例里"抖音"作为**App 名**(MCP 列应用、AI 建任务的需求举例)保留,与任务类型无关

自测(全部通过):类型列表只剩 generic_steps;建任务不传类型默认 generic_steps;传
douyin_nurture 被 400 拒;库里塞残留旧类型任务 → 启动日志告警 + 执行返回明确错误 +
不自动删用户数据;前端新建任务下拉 1 项且默认选中、界面建任务成功;监控页卡片两个按钮 +
覆盖设备正常。临时任务/数据验完已清理,任务集合复原。
2026-09-10 21:43:08 +08:00

121 lines
3.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Action 基类与注册机制(全局通用,所有 app 任务共享接口)。
设计要点:
1. BaseAction 定义统一接口:execute(d, params, worker) -> bool
2. 每个 app 任务有自己的注册表(create_action_registry),
互不污染——A 应用的 like 和 B 应用的 like 各注册各的。
3. 概率触发、状态上报等通用逻辑放这里,子类不重复写。
4. ActionContext 封装执行上下文,方便扩展(传 d/worker/进度/计数器)。
新增 app 专属操作步骤(在 tasks/<app>/actions/ 下新建,参考该包已有实现):
1. 在 tasks/<app>/actions/ 下新建 my_action.py
2. 写一个 BaseAction 子类,用 @register_action 装饰,实现 execute:
from core.actions import BaseAction, register_action, should_trigger
from . import ACTIONS # 本 app 的注册表
@register_action(ACTIONS)
class MyAction(BaseAction):
action_type = "my_action"
name = "我的操作"
description = "做什么"
default_params = {"rate": 0.5}
def execute(self, d, params, worker):
if not should_trigger(params["rate"]):
return False
# ... 用 d(xpath=...) / d(text=...) 操作
return True
3. 在 tasks/<app>/actions/__init__.py 加:from . import my_action
做完前端自动出现该操作的可勾选项。
"""
import random
from core.logger import get_logger
_log = get_logger("action")
class ActionContext:
"""操作执行上下文,封装给 Action 用的所有依赖。
现在只是简单封装,后续可扩展(如传任务参数、设备信息、进度回调)。
Action 子类通过 worker 间接访问,或直接用 execute 的 d 参数。
"""
def __init__(self, worker=None, params=None):
self.worker = worker
self.params = params or {}
class BaseAction:
"""所有操作的基类。子类实现 execute。
约定:
execute 返回 True = 执行成功(会计入 action_counts)
execute 返回 False = 跳过/失败(不影响主流程,不抛异常)
execute 内部异常由调用方捕获,不影响其他操作和主循环
"""
action_type = "base"
name = "基础操作"
description = ""
default_params = {}
def execute(self, d, params, worker):
"""执行操作。
d: u2.Device — 已连好的设备
params: 本操作的参数 dict(已合并默认值)
worker: Worker 实例,可调 worker.set_action() 上报状态
返回 True=执行成功,False=跳过/失败。
"""
raise NotImplementedError
def __repr__(self):
return f"<{self.__class__.__name__}({self.action_type})>"
def should_trigger(rate):
"""按概率决定是否触发(rate 是 0~1 的概率)。"""
return random.random() < rate
def register_action(registry):
"""装饰器:把 Action 类注册到指定注册表。
用法:
ACTIONS = create_action_registry()
@register_action(ACTIONS)
class MyAction(BaseAction): ...
每个 app 任务有自己的 ACTIONS 注册表,互不污染。
"""
def _decorator(action_cls):
registry[action_cls.action_type] = action_cls
_log.debug(f"注册操作: {action_cls.action_type} -> {action_cls.__name__}")
return action_cls
return _decorator
def create_action_registry():
"""创建一个独立的操作注册表(每个 app 任务一个)。
返回 dict: action_type -> ActionClass
"""
return {}
def list_actions(registry):
"""返回注册表中所有操作的元信息(供前端展示)。"""
return [{"action_type": a.action_type, "name": a.name,
"description": a.description,
"default_params": a.default_params} for a in registry.values()]
def get_action(registry, action_type):
"""按 action_type 取操作类。"""
return registry.get(action_type)