diff --git a/Entity/Variables.py b/Entity/Variables.py index 8f42e26..a8f9429 100644 --- a/Entity/Variables.py +++ b/Entity/Variables.py @@ -14,14 +14,7 @@ anchorList: list[AnchorModel] = [] # 线程锁 anchorListLock = threading.Lock() # 打招呼数据 -prologueList = { - "Cantonese": ["你好", "你係邊個", "我好鍾意你", "我係你爸爸"], - "English": ["Hello,", "Who are you?", "I like you.", "I'm your dad."], - "Greek": ["Γεια σου,", "Ποιος είσαι;", "Μου αρέσεις.", "Είμαι ο μπαμπάς σου."], - "Japanese": ["こんにちは", "あなたは誰ですか", "あなたが好きです", "私はあなたのパパです"], - "Khmer": ["សួស្តី", "អ្នកជាអ្នកណា", "ខ្ញុំចូលចិត្តអ្នក", "ខ្ញុំគឺជាប៉ារបស់អ្នក"], - "Malay": ["Hai,", "Siapakah kamu?", "Aku suka kamu,", "Aku adalah ayahmu."] -} +prologueList = {} # 评论数据 commentList = [] diff --git a/Entity/__pycache__/Variables.cpython-312.pyc b/Entity/__pycache__/Variables.cpython-312.pyc index a951898..11f2169 100644 Binary files a/Entity/__pycache__/Variables.cpython-312.pyc and b/Entity/__pycache__/Variables.cpython-312.pyc differ diff --git a/Module/DeviceInfo.py b/Module/DeviceInfo.py index 4c39fae..bbadad2 100644 --- a/Module/DeviceInfo.py +++ b/Module/DeviceInfo.py @@ -204,11 +204,10 @@ class DeviceInfo: if major > 17: print("进入iOS17设备的分支") print(f"[WDA] iOS>17 调用 IOSActivator (port={wdaScreenPort})") - try: - IOSActivator().activate(udid) - print("wda启动完成") - except Exception as e: - print("错误信息:",e) + print("准备启动隧道") + out = IOSActivator().activate(udid) + print("------------------",out) + print("wda启动完成") else: print(f"[WDA] iOS<=17 启动 WDA app_start (port={wdaScreenPort})") dev = tidevice.Device(udid) diff --git a/Module/FlaskService.py b/Module/FlaskService.py index f79ab93..94b5a79 100644 --- a/Module/FlaskService.py +++ b/Module/FlaskService.py @@ -382,8 +382,7 @@ def followAndGreetUnion(): # 是否需要回复 needReply = data.get("needReply", True) - # 是否需要进行翻译 - needTranslate = data.get("needTranslate", True) + # 获取打招呼数据 ev.prologueList = data.get("prologueList", []) @@ -396,7 +395,7 @@ def followAndGreetUnion(): event = threading.Event() # 启动脚本 thread = threading.Thread(target=manager.safe_followAndGreetUnion, - args=(udid, needReply, needTranslate, event)) + args=(udid, needReply, event)) # 添加到线程管理 ThreadManager.add(udid, thread, event) return ResultData(data="").toJson() @@ -750,6 +749,18 @@ def getAiConfig(): data = IOSAIStorage.load("aiConfig.json") return ResultData(data=data).toJson() +# 重新开启tiktok +@app.route("/restartTikTok", methods=['POST']) +def restartTikTok(): + json = request.get_json() + udid = json.get("udid") + client = wda.USBClient(udid, wdaFunctionPort) + session = client.session() + ControlUtils.closeTikTok(session, udid) + time.sleep(1) + ControlUtils.openTikTok(session, udid) + return ResultData(data="").toJson() + if __name__ == '__main__': # 注意:这里建议 debug=False,避免未来有人改成 use_reloader=True 导致多进程 app.run("0.0.0.0", port=5000, debug=False, use_reloader=False, threaded=True) \ No newline at end of file diff --git a/Module/IOSActivator.py b/Module/IOSActivator.py index 5c009d3..3769409 100644 --- a/Module/IOSActivator.py +++ b/Module/IOSActivator.py @@ -9,6 +9,7 @@ import subprocess from typing import Optional, List, Tuple, Dict, Set from Entity.Variables import WdaAppBundleId +import time as _t class IOSActivator: @@ -32,139 +33,178 @@ class IOSActivator: self._live_ifaces: Dict[str, Set[str]] = {} # udid -> {iface names} self._registered = False + # =============== 公共入口 =============== def activate( self, udid: str, - wda_bundle_id: str = WdaAppBundleId, - ready_timeout_sec: float = 60.0, + wda_bundle_id: Optional[str] = WdaAppBundleId, + ready_timeout_sec: float = 120.0, + mount_retries: int = 3, + backoff_seconds: float = 2.0, + rsd_probe_retries: int = 5, + rsd_probe_delay_sec: float = 3.0, pre_mount_first: bool = True, - mount_retries: int = 2, - backoff_seconds: float = 1.5, - keep_tunnel: bool = False, - broad_cleanup_on_exit: bool = True, + keep_tunnel: bool = False, # 默认 False:WDA 拉起后关闭隧道 + broad_cleanup_on_exit: bool = True, # 退出时顺带清理所有 pmd3 残留网卡 ) -> str: """ - Windows 简版:不读任何 tunneld 日志,也不做 RSD 解析。 - 逻辑:先探活 -> 开隧道 -> 直接用 HTTP 隧道端口反复尝试启动 WDA -> 探活成功即返回。 + 流程:挂镜像(可选) -> 开隧道 -> 等 RSD -> 启动 WDA + - keep_tunnel=False:WDA 启动后关闭隧道并清理 + - keep_tunnel=True:隧道常驻,由上层/atexit 清理 """ - import time, ctypes, traceback - if not udid or not isinstance(udid, str): raise ValueError("udid is required and must be a non-empty string") - print(f"[activate] UDID={udid}", flush=True) + print(f"[activate] UDID = {udid}") + self._ensure_exit_hooks(broad_cleanup_on_exit=broad_cleanup_on_exit) - # —— 管理员提示(Windows 清理虚拟网卡常用)—— - try: - if ctypes.windll.shell32.IsUserAnAdmin() == 0: - print("[⚠] 未以管理员运行:若需要移除虚拟网卡,可能失败。", flush=True) - except Exception: - pass - - # —— 退出钩子(可选)—— - try: - self._ensure_exit_hooks(broad_cleanup_on_exit=broad_cleanup_on_exit) # type: ignore[attr-defined] - except Exception as e: - print(f"[activate] _ensure_exit_hooks warn: {e}", flush=True) - - # —— 小工具:探活 WDA —— # - def _wda_alive(timeout: float = 2.0) -> bool: + # Windows 管理员检测 + if os.name == "nt": + import ctypes try: - if hasattr(self, "_wda_alive_now"): - return bool(self._wda_alive_now(udid, timeout=timeout)) # type: ignore[attr-defined] - if hasattr(self, "_wda_client"): - cli = self._wda_client(udid) # type: ignore[attr-defined] - if hasattr(cli, "wait_ready"): - return bool(cli.wait_ready(timeout=timeout)) + is_admin = ctypes.windll.shell32.IsUserAnAdmin() != 0 except Exception: - return False - return False + is_admin = False + if not is_admin: + print("[⚠] 未以管理员运行:若需要移除虚拟网卡,可能失败。") - # 0) 快路径:WDA 已活 - if _wda_alive(2.0): - print("[activate] WDA already alive, skip launching.", flush=True) - return "WDA already alive" + start_ts = _t.time() # 1) 预挂载(失败不致命) - if pre_mount_first and hasattr(self, "_auto_mount_developer_disk"): + if pre_mount_first: try: - self._auto_mount_developer_disk(udid, retries=mount_retries, - backoff_seconds=backoff_seconds) # type: ignore[attr-defined] - time.sleep(1.5) + self._auto_mount_developer_disk( + udid, retries=mount_retries, backoff_seconds=backoff_seconds + ) + _t.sleep(2) except Exception as e: - print(f"[activate] 预挂载失败(继续):{e}", flush=True) + print(f"[activate] 预挂载失败(稍后再试):{e}") - # 2) 开隧道(关键:拿到 HTTP 端口即可;不读取任何 stdout/stderr) - proc = None - http_host, http_port = "127.0.0.1", None - try: - ret = self._start_tunneld(udid) # type: ignore[attr-defined] - if isinstance(ret, tuple): - proc, http_port = ret[0], ret[1] - else: - proc = ret - if http_port is None: - # 若你的 _start_tunneld 固定端口,可在这里写死(例如 8100/某自定义端口) - raise RuntimeError("未获取到 HTTP 隧道端口(_start_tunneld 未返回端口)") - except Exception: - # 即便开隧道失败,也再探活一次(可能本来就活) - if _wda_alive(2.0): - print("[activate] WDA already alive (tunnel start failed but OK).", flush=True) - return "WDA already alive" - raise + # 2) 启动 tunneld + http_host: Optional[str] = None + http_port: Optional[str] = None # ⚠️ 端口以 str 存储 + rsd_host: Optional[str] = None + rsd_port: Optional[str] = None # ⚠️ 端口以 str 存储 + iface_names: Set[str] = set() - print(f"[tunneld] HTTP tunnel at {http_host}:{http_port}", flush=True) + proc, _port_ignored = self._start_tunneld(udid) + self._live_procs[udid] = proc + self._live_ifaces[udid] = iface_names - # 3) 直接用 HTTP 隧道反复尝试启动 WDA + 探活 - deadline = time.time() + (ready_timeout_sec if ready_timeout_sec > 0 else 60.0) - launched = False + captured: List[str] = [] + out: str = "" + wda_started = False + mount_done = pre_mount_first try: - while time.time() < deadline: - # 已活则成功返回 - if _wda_alive(1.5): - print("[activate] WDA detected alive.", flush=True) - launched = True + assert proc.stdout is not None + for line in proc.stdout: + captured.append(line) + # 日志长度控制,防止常驻时内存涨太多 + if len(captured) > 20000: + captured = captured[-10000:] + + print(f"[tunneld] {line}", end="") + + # 捕获虚拟网卡名 + for m in self.IFACE_RE.finditer(line): + iface_names.add(m.group(1)) + + # 子进程若退出则停止读取 + if proc.poll() is not None: break - # 尝试发起一次 HTTP 启动(失败就下一轮重试) - try: - if hasattr(self, "_launch_wda_via_http_tunnel"): - self._launch_wda_via_http_tunnel( # type: ignore[attr-defined] + # 捕获 HTTP 网关端口(保持为字符串) + if http_port is None: + m = self.HTTP_RE.search(line) + if m: + http_host = m.group(1) + http_port = m.group(2) + # 简单校验 + try: + _ = int(http_port) + except Exception: + print(f"[tunneld] bad http port: {http_port}") + http_host, http_port = None, None + else: + print(f"[tunneld] Tunnel API: {http_host}:{http_port}") + + # 只处理当前 UDID 的 RSD 行 + if not self._line_is_for_udid(line, udid): + continue + + m = self.RSD_CREATED_RE.search(line) or self.RSD_FALLBACK_RE.search(line) + if m and rsd_host is None and rsd_port is None: + rsd_host = m.group(1) + rsd_port = m.group(2) + try: + _ = int(rsd_port) # 仅作数字校验 + except Exception: + print(f"[tunneld] bad rsd port: {rsd_port}") + rsd_host, rsd_port = None, None + else: + print(f"[tunneld] Device-level tunnel ready (RSD {rsd_host}:{rsd_port}).") + + # ========= 尝试启动 WDA ========= + if (not wda_started) and wda_bundle_id and (rsd_host is not None) and (rsd_port is not None): + if not mount_done: + self._auto_mount_developer_disk( + udid, retries=mount_retries, backoff_seconds=backoff_seconds + ) + _t.sleep(2) + mount_done = True + + # RSD 优先;探测时临时转 int;启动命令仍传 str 端口 + rsd_port_int = int(rsd_port) + if self._wait_for_rsd_ready( + rsd_host, rsd_port_int, retries=rsd_probe_retries, delay=rsd_probe_delay_sec + ): + # 这里的实现通常会拼 subprocess 命令行,故端口保持 str + self._launch_wda_via_rsd( bundle_id=wda_bundle_id, - http_host=http_host, - http_port=str(http_port), + rsd_host=rsd_host, + rsd_port=rsd_port, # ⚠️ 传入 str,避免 subprocess 报错 udid=udid, ) - except Exception as e: - # 仅打印,不中断;下一次循环再试 - print(f"[activate] _launch_wda_via_http_tunnel error: {e}", flush=True) + wda_started = True + elif (http_host is not None) and (http_port is not None): + self._launch_wda_via_http_tunnel( + bundle_id=wda_bundle_id, + http_host=http_host, + http_port=http_port, # ⚠️ 传入 str + udid=udid, + ) + wda_started = True + else: + raise RuntimeError("No valid tunnel endpoint for WDA.") - # 启动后给一点时间让 WDA ready - for _ in range(3): - if _wda_alive(1.0): - launched = True + # ✅ WDA 已启动;默认一次性模式直接退出读取循环 + if wda_started and not keep_tunnel: + _t.sleep(0.5) # 给隧道多刷几行 + print("[activate] WDA launched; exiting reader loop (keep_tunnel=False).") break - time.sleep(0.5) - if launched: + # 超时保护(仅在 WDA 尚未启动时生效) + if (not wda_started) and ready_timeout_sec > 0 and (_t.time() - start_ts > ready_timeout_sec): + print(f"[tunneld] Timeout waiting for device tunnel ({ready_timeout_sec}s). Aborting.") break - time.sleep(1.0) # 下一轮重试 - - if not launched: - raise RuntimeError(f"WDA not ready within {ready_timeout_sec}s via HTTP tunnel") - - print("[activate] Done.", flush=True) - return f"http://{http_host}:{http_port}" + print("[activate] 启动 WDA 读取阶段结束") + out = "".join(captured) + except Exception as e: + print(f"[activate] 发生异常:{e}") + raise finally: if not keep_tunnel: try: - self.stop_tunnel(udid, broad_cleanup=broad_cleanup_on_exit) # type: ignore[attr-defined] - except Exception as e: - print(f"[activate] stop_tunnel warn: {e}", flush=True) + self.stop_tunnel(udid, broad_cleanup=broad_cleanup_on_exit) + except Exception as ce: + print(f"[activate] stop_tunnel 清理异常:{ce}") + + print("[activate] Done.") + return out # =============== 外部可显式调用的清理 =============== diff --git a/Module/__pycache__/DeviceInfo.cpython-312.pyc b/Module/__pycache__/DeviceInfo.cpython-312.pyc index 41b3501..65619bd 100644 Binary files a/Module/__pycache__/DeviceInfo.cpython-312.pyc and b/Module/__pycache__/DeviceInfo.cpython-312.pyc differ diff --git a/Module/__pycache__/FlaskService.cpython-312.pyc b/Module/__pycache__/FlaskService.cpython-312.pyc index 4573b4a..52dffbd 100644 Binary files a/Module/__pycache__/FlaskService.cpython-312.pyc and b/Module/__pycache__/FlaskService.cpython-312.pyc differ diff --git a/resources/e5ab9d3c548302dca3b1383589ac43eedd41f24e/bgv.png b/resources/e5ab9d3c548302dca3b1383589ac43eedd41f24e/bgv.png deleted file mode 100644 index ef6c940..0000000 Binary files a/resources/e5ab9d3c548302dca3b1383589ac43eedd41f24e/bgv.png and /dev/null differ diff --git a/resources/e5ab9d3c548302dca3b1383589ac43eedd41f24e/bgv_comment.png b/resources/e5ab9d3c548302dca3b1383589ac43eedd41f24e/bgv_comment.png deleted file mode 100644 index 30c015c..0000000 Binary files a/resources/e5ab9d3c548302dca3b1383589ac43eedd41f24e/bgv_comment.png and /dev/null differ diff --git a/script/ScriptManager.py b/script/ScriptManager.py index 0331e0e..8bf963f 100644 --- a/script/ScriptManager.py +++ b/script/ScriptManager.py @@ -50,30 +50,6 @@ class ScriptManager(): self.initialized = True # 标记已初始化 - # 放在类里或公共工具模块里均可 - def interruptible_wait(self,event: threading.Event, total: float, step: float = 0.2) -> bool: - """ - 等待 total 秒,但每 step 秒检查一次停止信号。 - 若在等待期间 event 被置位,立刻返回 True;否则到点返回 False。 - """ - deadline = time.time() + total - while time.time() < deadline: - if event.is_set(): - return True - - event.wait(timeout=min(step, max(0, deadline - time.time()))) - return event.is_set() - - def interruptible_sleep(self,event: threading.Event, seconds: float, step: float = 0.2) -> bool: - """语义同上;返回 True 表示期间接到停止信号。""" - return self.interruptible_wait(event, seconds, step) - - def check_stop(self,event: threading.Event, tag: str = ""): - """在关键点快速失败,保持调用栈整洁(不改变业务路径,只是早退出)。""" - if event.is_set(): - raise RuntimeError(f"stop-requested:{tag}") - - # ========= 评论逻辑 ========= def comment_flow(self, filePath, session, udid, recomend_cx, recomend_cy): """评论一条龙:点评论框->输入->发送->返回""" @@ -450,11 +426,9 @@ class ScriptManager(): break LogManager.method_error("greetNewFollowers 重试次数耗尽,任务终止", "关注打招呼", udid) + # 关注打招呼 def greetNewFollowers(self, udid, needReply, isComment, event): - if self.check_stop(event, "init"): # [ADD] - return - client = wda.USBClient(udid, ev.wdaFunctionPort) session = client.session() @@ -464,18 +438,11 @@ class ScriptManager(): # 先关闭Tik Tok ControlUtils.closeTikTok(session, udid) - - - if self.interruptible_sleep(event, 1): # [ADD] 可中断等待 - return - - if self.check_stop(event, "after-close-app"): # [ADD] - return + event.wait(timeout=1) # 重新打开Tik Tok ControlUtils.openTikTok(session, udid) - if self.interruptible_sleep(event, 3): # [ADD] - return + event.wait(timeout=3) LogManager.method_info(f"重启tiktok", "关注打招呼", udid) # 设置查找深度 @@ -488,12 +455,9 @@ class ScriptManager(): def goBack(count): for i in range(count): LogManager.method_info(f"返回上一步", "关注打招呼", udid) - if self.check_stop(event, f"goBack-{i + 1}/{count}"): # [ADD] - return session.appium_settings({"snapshotMaxDepth": 15}) ControlUtils.clickBack(session) - if self.interruptible_sleep(event, 2): # [ADD] - return + event.wait(timeout=2) LogManager.method_info(f"循环条件1:{not event.is_set()}", "关注打招呼", udid) LogManager.method_info(f"循环条件2:{len(anchorList) > 0}", "关注打招呼", udid) @@ -502,15 +466,13 @@ class ScriptManager(): # 循环条件。1、 循环关闭 2、 数据处理完毕 while not event.is_set(): - if self.check_stop(event, "loop-top"): # [ADD] - return - LogManager.method_info("=== 外层 while 新一轮 ===", "关注打招呼", udid) if event.is_set(): break # 获取一个主播, LogManager.method_info(f"开始获取数据", "关注打招呼", udid) + # 获取一个主播, result = AiUtils.peek_aclist_first() LogManager.method_info(f"数据是:{result}", "关注打招呼", udid) @@ -528,21 +490,17 @@ class ScriptManager(): if not anchor: LogManager.method_info(f"数据库中的数据不足", "关注打招呼", udid) - # 你原来的写法:等待完成就 continue;中途被打断就 return if not self.interruptible_sleep(event, 30): continue - return # [ADD] 被打断则退出 aid = anchor.get("anchorId", "") anchorCountry = anchor.get("country", "") LogManager.method_info(f"主播的数据,用户名:{aid},国家:{anchorCountry}", "关注打招呼", udid) - if self.check_stop(event, "before-search"): # [ADD] - return - # 点击搜索按钮 ControlUtils.clickSearch(session) + LogManager.method_info(f"点击搜索按钮", "关注打招呼", udid) # 强制刷新session @@ -554,21 +512,21 @@ class ScriptManager(): # 如果找到了输入框,就点击并且输入内容 if input.exists: input.click() - # 稍作停顿(用你的可中断等待) - if self.interruptible_sleep(event, 0.5): # [ADD] - return + # 稍作停顿 + event.wait(timeout=0.5) else: print(f"找不到输入框") + raise Exception("找不到输入框") input = session.xpath('//XCUIElementTypeSearchField') if input.exists: input.clear_text() - if self.interruptible_sleep(event, 1): # [ADD] - return + event.wait(timeout=1) # 输入主播id input.set_text(f"{aid or '暂无数据'}\n") # 定位 "关注" 按钮 通过关注按钮的位置点击主播首页 + session.appium_settings({"snapshotMaxDepth": 25}) try: @@ -583,22 +541,15 @@ class ScriptManager(): session.appium_settings({"snapshotMaxDepth": 15}) continue - if self.interruptible_sleep(event, 2): # [ADD] - return - + event.wait(timeout=2) # 找到并点击第一个视频 cellClickResult, workCount = ControlUtils.clickFirstVideoFromDetailPage(session) - LogManager.method_info(f"点击第一个视频", "关注打招呼", udid) - if self.interruptible_sleep(event, 2): # [ADD] - return + LogManager.method_info(f"点击第一个视频", "关注打招呼", udid) + event.wait(timeout=2) # 观看主播视频 def viewAnchorVideo(workCount): - - if self.check_stop(event, "viewVideo-enter"): # [ADD] - return - print("开始查看视频,并且重新调整查询深度") session.appium_settings({"snapshotMaxDepth": 5}) @@ -613,16 +564,12 @@ class ScriptManager(): LogManager.method_info("停止脚本中", method="task") if event.is_set(): break - if self.interruptible_sleep(event, 1): # [ADD] - return + event.wait(timeout=1) LogManager.method_info("停止脚本成功", method="task") - - if self.check_stop(event, "before-screenshot"): # [ADD] - return - img = client.screenshot() - if self.interruptible_sleep(event, 1): # [ADD] - return + event.wait(timeout=1) + + # filePath = f"resources/{udid}/bgv.png" base_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) # 当前脚本目录的上一级 filePath = os.path.join(base_dir, "resources", udid, "bgv.png") @@ -633,9 +580,7 @@ class ScriptManager(): img.save(filePath) LogManager.method_info("保存屏幕图像成功", "关注打招呼", udid) - if self.interruptible_sleep(event, 2): # [ADD] - return - + event.wait(timeout=2) # 查找add图标 r = ControlUtils.clickLike(session, udid) @@ -646,8 +591,7 @@ class ScriptManager(): LogManager.method_info("停止脚本中", method="task") if event.is_set(): break - if self.interruptible_sleep(event, 1): # [ADD] - return + event.wait(timeout=1) LogManager.method_info("停止脚本成功", method="task") # 使用OCR进行评论 @@ -668,20 +612,16 @@ class ScriptManager(): # 观看主播视频 LogManager.method_info("去查看主播视频", "关注打招呼", udid) viewAnchorVideo(workCount) - if self.interruptible_sleep(event, 3): # [ADD] - return + event.wait(timeout=3) LogManager.method_info("视频看完了,重置试图查询深度", "关注打招呼", udid) session.appium_settings({"snapshotMaxDepth": 25}) - if self.interruptible_sleep(event, 0.5): # [ADD] - return + event.wait(timeout=0.5) # 向上滑动 ControlUtils.swipe_down(udid) - if self.interruptible_sleep(event, 2): # [ADD] - return + event.wait(timeout=2) msgButton = AiUtils.getSendMesageButton(session) - if self.interruptible_sleep(event, 2): # [ADD] - return + event.wait(timeout=2) if msgButton.exists: # 进入聊天页面 @@ -695,8 +635,7 @@ class ScriptManager(): session.appium_settings({"snapshotMaxDepth": 15}) continue - if self.interruptible_sleep(event, 3): # [ADD] - return + event.wait(timeout=3) # 查找聊天界面中的输入框节点 chatInput = session.xpath("//TextView") if chatInput.exists: @@ -705,15 +644,15 @@ class ScriptManager(): LogManager.method_info("找到输入框了, 准备发送一条打招呼消息", "关注打招呼", udid) print("打招呼的数据", ev.prologueList) - LogManager.method_info(f"传递的打招呼的数据:{ev.prologueList}", "关注打招呼", udid) + # LogManager.method_info(f"传递的打招呼的数据:{ev.prologueList}", "关注打招呼", udid) # 取出国家进行对应国家语言代码 anchorCountry_code = CountryLanguageMapper.get_language_code(anchorCountry) + print(anchorCountry_code) - - + print("存储的是:",ev.prologueList) # 判断对应的语言代码是否在传入的字典中 if anchorCountry_code in ev.prologueList: # 进行原本的进行传入 @@ -746,10 +685,10 @@ class ScriptManager(): if chatInput.exists: chatInput.click() chatInput.set_text(f"{msg or '暂无数据'}\n") - if self.interruptible_sleep(event, 2): # [ADD] - return - if self.interruptible_sleep(event, 1): # [ADD] - return + event.wait(timeout=2) + # 发送消息 + # input.set_text(f"{aid or '暂无数据'}\n") + event.wait(timeout=1) else: print("无法发送信息") LogManager.method_info(f"给主播{aid} 发送消息失败", "关注打招呼", udid) @@ -757,6 +696,27 @@ class ScriptManager(): # 接着下一个主播 goBack(1) + # 点击关注按钮 + # followButton = AiUtils.getFollowButton(session).get(timeout=5) + # if followButton is not None: + # # LogManager.method_info("找到关注按钮了", "关注打招呼", udid) + # # followButton.click() + # x, y, w, h = followButton.bounds + # cx = int(x + w / 2) + # cy = int(y + h / 2) + # # 随机偏移 ±5 px(可自己改范围) + # cx += random.randint(-5, 5) + # cy += random.randint(-5, 5) + # + # session.click(cx, cy) + # + # else: + # LogManager.method_info("没找到关注按钮", "关注打招呼", udid) + # time.sleep(1) + # goBack(4) + # session.appium_settings({"snapshotMaxDepth": 15}) + # continue + session.appium_settings({"snapshotMaxDepth": 15}) goBack(3) @@ -769,8 +729,7 @@ class ScriptManager(): # 设置查找深度 session.appium_settings({"snapshotMaxDepth": 15}) - if self.interruptible_sleep(event, 2): # [ADD] - return + event.wait(timeout=2) print("即将要回复消息") LogManager.method_info("即将要回复消息", "关注打招呼", udid) @@ -787,11 +746,9 @@ class ScriptManager(): homeButton.click() else: ControlUtils.closeTikTok(session, udid) - if self.interruptible_sleep(event, 2): # [ADD] - return + event.wait(timeout=2) ControlUtils.openTikTok(session, udid) - if self.interruptible_sleep(event, 3): # [ADD] - return + event.wait(timeout=3) print("重新创建wda会话 防止wda会话失效") client = wda.USBClient(udid, ev.wdaFunctionPort) @@ -803,12 +760,12 @@ class ScriptManager(): print("greetNewFollowers方法执行完毕") - def safe_followAndGreetUnion(self, udid, needReply, needTranslate, event): + def safe_followAndGreetUnion(self, udid, needReply, event): retries = 0 while not event.is_set(): try: - self.followAndGreetUnion(udid, needReply, needTranslate, event) + self.followAndGreetUnion(udid, needReply, event) except Exception as e: retries += 1 @@ -821,7 +778,7 @@ class ScriptManager(): LogManager.method_error("greetNewFollowers 重试次数耗尽,任务终止", "关注打招呼", udid) # 关注打招呼以及回复主播消息(联盟号) - def followAndGreetUnion(self, udid, needReply, needTranslate, event): + def followAndGreetUnion(self, udid, needReply, event): client = wda.USBClient(udid, ev.wdaFunctionPort) session = client.session() @@ -910,6 +867,8 @@ class ScriptManager(): event.wait(timeout=0.5) else: print(f"找不到输入框") + raise Exception("找不到输入框") + input = session.xpath('//XCUIElementTypeSearchField') if input.exists: @@ -965,16 +924,25 @@ class ScriptManager(): print("找到输入框了, 准备发送一条打招呼消息") LogManager.method_info("找到输入框了, 准备发送一条打招呼消息", "关注打招呼(联盟号)", udid) - print("打招呼的数据", ev.prologueList) - LogManager.method_info(f"传递的打招呼的数据:{ev.prologueList}", "关注打招呼(联盟号)", udid) + # 取出国家进行对应国家语言代码 + anchorCountry_code = CountryLanguageMapper.get_language_code(anchorCountry) + print(anchorCountry_code) + + print("存储的是:", ev.prologueList) + # 判断对应的语言代码是否在传入的字典中 + if anchorCountry_code in ev.prologueList: + # 进行原本的进行传入 + privateMessageList = ev.prologueList[anchorCountry_code] + needTranslate = False + + else: + # 需要翻译 + privateMessageList = ev.prologueList['yolo'] + needTranslate = True # 使用yolo必须翻译 # 准备打招呼的文案 - text = random.choice(ev.prologueList) - # text = '你好' + text = random.choice(privateMessageList) - LogManager.method_info(f"取出打招呼的数据,{text}, 判断是否需要翻译", "关注打招呼(联盟号)", udid) - - isContainChniese = AiUtils.contains_chinese(text) if needTranslate: # 翻译成主播国家的语言 diff --git a/script/__pycache__/ScriptManager.cpython-312.pyc b/script/__pycache__/ScriptManager.cpython-312.pyc index 2c6b702..03baef6 100644 Binary files a/script/__pycache__/ScriptManager.cpython-312.pyc and b/script/__pycache__/ScriptManager.cpython-312.pyc differ