Files
workphone-sdk/sdk/app/agent/anti_ban/touch_hardener.py
卡若 9118df9eee
Some checks failed
SDK CI / python-compile (push) Has been cancelled
feat: sdk agent、Android 与文档同步至 Gitea
- 新增 sdk/app/agent(Hook/Skills/Anti-ban 等)及 NAS/ADB 脚本
- 更新 Android 端、unified、PHP SDK、Docker Compose
- Soul 文档迁移至 Soul调研/;移除资料目录内 APK
- .gitignore 排除 sdk/tmp、sdk/logs、sdk/tmp_rom

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-06 18:20:14 +08:00

159 lines
5.6 KiB
Python
Raw 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.

"""
触摸加固层 — 将机器精确操作伪装为真人触摸
功能:
1. 坐标随机偏移 (+-3~8px)
2. 点击时长随机化 (50~150ms)
3. 贝塞尔曲线轨迹滑动 (替代直线滑动)
4. 按压-微移-抬起时序模拟
5. 可配置的「手抖」程度
"""
import logging
import math
import random
import time
from typing import List, Optional, Tuple
logger = logging.getLogger(__name__)
Point = Tuple[float, float]
class TouchHardener:
"""触摸事件加固 — 让自动化操作看起来像人"""
def __init__(self, device=None, tremor_level: float = 1.0):
"""
Args:
device: uiautomator2 设备对象
tremor_level: 手抖程度倍数 (0.5=稳手, 1.0=普通, 2.0=抖得厉害)
"""
self.d = device
self.tremor = max(0.1, tremor_level)
def humanized_click(self, x: int, y: int) -> Tuple[int, int]:
"""
带随机偏移的点击。返回实际点击坐标。
"""
offset_x = random.gauss(0, 3 * self.tremor)
offset_y = random.gauss(0, 3 * self.tremor)
actual_x = max(0, int(x + offset_x))
actual_y = max(0, int(y + offset_y))
duration_ms = random.randint(50, 150)
if self.d:
self.d.click(actual_x, actual_y)
settle_ms = random.uniform(30, 80)
time.sleep(settle_ms / 1000)
logger.debug(f"click ({x},{y}) → ({actual_x},{actual_y}) dur={duration_ms}ms")
return actual_x, actual_y
def humanized_swipe(self, x1: int, y1: int, x2: int, y2: int,
duration: float = 0.5, steps: int = 0) -> List[Point]:
"""
贝塞尔曲线滑动。返回轨迹点序列。
"""
sx = x1 + random.gauss(0, 2 * self.tremor)
sy = y1 + random.gauss(0, 2 * self.tremor)
ex = x2 + random.gauss(0, 2 * self.tremor)
ey = y2 + random.gauss(0, 2 * self.tremor)
ctrl_points = self._random_bezier_controls(sx, sy, ex, ey)
if steps <= 0:
dist = math.hypot(ex - sx, ey - sy)
steps = max(8, int(dist / 15))
trajectory = self._bezier_curve(sx, sy, ex, ey, ctrl_points, steps)
if self.d:
self.d.swipe(int(sx), int(sy), int(ex), int(ey), duration=duration, steps=steps)
logger.debug(f"swipe ({x1},{y1})→({x2},{y2}) pts={len(trajectory)}")
return trajectory
def humanized_long_press(self, x: int, y: int, duration_ms: int = 800):
"""长按 — 带起始微抖"""
actual_x = int(x + random.gauss(0, 2 * self.tremor))
actual_y = int(y + random.gauss(0, 2 * self.tremor))
actual_dur = duration_ms + random.randint(-100, 150)
actual_dur = max(300, actual_dur)
if self.d:
self.d.long_click(actual_x, actual_y, duration=actual_dur / 1000)
logger.debug(f"long_press ({x},{y})→({actual_x},{actual_y}) dur={actual_dur}ms")
def humanized_type(self, text: str, char_delay_range: Tuple[float, float] = (0.03, 0.12)):
"""
逐字输入 — 每个字符间隔随机延迟,模拟打字节奏。
"""
for i, char in enumerate(text):
if self.d:
self.d.send_keys(char)
delay = random.uniform(*char_delay_range)
if char in (' ', ',', '.', '', ''):
delay *= random.uniform(1.5, 3.0)
time.sleep(delay)
logger.debug(f"typed {len(text)} chars")
def pre_action_pause(self):
"""操作前的微停顿 — 模拟人的反应时间"""
pause = random.uniform(0.2, 0.8) * self.tremor
time.sleep(pause)
def post_action_pause(self):
"""操作后的短暂停顿 — 模拟人看结果"""
pause = random.uniform(0.3, 1.2) * self.tremor
time.sleep(pause)
# ---- 内部方法 ----
@staticmethod
def _random_bezier_controls(x1: float, y1: float,
x2: float, y2: float) -> List[Point]:
"""生成 1~2 个随机控制点,使路径弯曲"""
mx = (x1 + x2) / 2
my = (y1 + y2) / 2
dist = math.hypot(x2 - x1, y2 - y1)
spread = dist * random.uniform(0.1, 0.35)
c1 = (mx + random.gauss(0, spread), my + random.gauss(0, spread))
if random.random() > 0.5:
c2 = (mx + random.gauss(0, spread * 0.6), my + random.gauss(0, spread * 0.6))
return [c1, c2]
return [c1]
@staticmethod
def _bezier_curve(x1: float, y1: float, x2: float, y2: float,
controls: List[Point], steps: int) -> List[Point]:
"""计算贝塞尔曲线点"""
points: List[Point] = []
if len(controls) == 1:
cx, cy = controls[0]
for i in range(steps + 1):
t = i / steps
bx = (1 - t) ** 2 * x1 + 2 * (1 - t) * t * cx + t ** 2 * x2
by = (1 - t) ** 2 * y1 + 2 * (1 - t) * t * cy + t ** 2 * y2
points.append((bx, by))
elif len(controls) >= 2:
c1x, c1y = controls[0]
c2x, c2y = controls[1]
for i in range(steps + 1):
t = i / steps
bx = ((1 - t) ** 3 * x1 + 3 * (1 - t) ** 2 * t * c1x +
3 * (1 - t) * t ** 2 * c2x + t ** 3 * x2)
by = ((1 - t) ** 3 * y1 + 3 * (1 - t) ** 2 * t * c1y +
3 * (1 - t) * t ** 2 * c2y + t ** 3 * y2)
points.append((bx, by))
else:
for i in range(steps + 1):
t = i / steps
points.append((x1 + (x2 - x1) * t, y1 + (y2 - y1) * t))
return points