diff --git a/.idea/workspace.xml b/.idea/workspace.xml index fe82f53..f72c7f4 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -5,8 +5,17 @@ + + + - + + + + + + + - { - "keyToString": { - "ASKED_ADD_EXTERNAL_FILES": "true", - "Python.123.executor": "Run", - "Python.Main.executor": "Run", - "RunOnceActivity.ShowReadmeOnStart": "true", - "SHARE_PROJECT_CONFIGURATION_FILES": "true", - "git-widget-placeholder": "main", - "javascript.nodejs.core.library.configured.version": "22.18.0", - "javascript.nodejs.core.library.typings.version": "22.18.0", - "last_opened_file_path": "F:/company code/AI item/20250820/iOSAI", - "node.js.detected.package.eslint": "true", - "node.js.detected.package.tslint": "true", - "node.js.selected.package.eslint": "(autodetect)", - "node.js.selected.package.tslint": "(autodetect)", - "nodejs_package_manager_path": "npm", - "settings.editor.selected.configurable": "com.gitee.ui.GiteeSettingsConfigurable", - "vue.rearranger.settings.migration": "true" + +}]]> @@ -119,8 +131,56 @@ - + + + \ No newline at end of file diff --git a/Utils/AiUtils.py b/Utils/AiUtils.py index 4ea7541..97c7d9c 100644 --- a/Utils/AiUtils.py +++ b/Utils/AiUtils.py @@ -203,7 +203,7 @@ class AiUtils(object): print("1.找到了") return homeButton else: - print("没找到") + print("1.没找到") return None except Exception as e: print(e) @@ -241,23 +241,34 @@ class AiUtils(object): # 获取关注按钮 @classmethod def getFollowButton(cls, session: Client): - followButton = session.xpath("//Window[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[2]/Other[2]/Other[1]/Other[1]/Other[3]/Other[1]/Other[1]/Button[1]") + # followButton = session.xpath("//Window[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[2]/Other[2]/Other[1]/Other[1]/Other[3]/Other[1]/Other[1]/Button[1]") + + followButton = session.xpath( + '//XCUIElementTypeOther[@name="cta_social_interaction"]//XCUIElementTypeButton[@name="关注"]') + if followButton.exists: - print("2.找到了") + print("2.关注找到了") + LogManager.info("2.关注找到了") return followButton else: - print("没找到") + print("2.关注没找到") + print("2.关注没找到") return None # 查找发消息按钮 @classmethod def getSendMesageButton(cls, session: Client): - msgButton = session.xpath("//Window[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[2]/Other[2]/Other[1]/Other[1]/Other[3]/Other[1]/Other[1]") + # msgButton = session.xpath("//Window[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[1]/Other[2]/Other[2]/Other[1]/Other[1]/Other[3]/Other[1]/Other[1]") + + msgButton = session.xpath( + '//XCUIElementTypeOther[@name="cta_social_interaction"]//XCUIElementTypeButton[@name="发消息"]') if msgButton.exists: - print("3.找到了") + print("3.发消息按钮找到了") + LogManager.info("3.发消息按钮找到了") return msgButton else: - print("没找到") + print("3.发消息按钮没找到") + LogManager.info("3.发消息按钮没找到") return None # 获取当前屏幕上的节点 diff --git a/Utils/ControlUtils.py b/Utils/ControlUtils.py index af037f5..81e19b9 100644 --- a/Utils/ControlUtils.py +++ b/Utils/ControlUtils.py @@ -1,6 +1,7 @@ import re import tidevice +import wda from wda import Client from Utils.AiUtils import AiUtils from Utils.LogManager import LogManager @@ -81,11 +82,11 @@ class ControlUtils(object): x, y = AiUtils.findImageInScreen("add", udid) print(x, y) if x > -1: - LogManager.info("点赞了",udid) + LogManager.info("点赞了", udid) session.click(x // scale, y // scale + 50) return True else: - LogManager.info("没有找到目标",udid) + LogManager.info("没有找到目标", udid) return False # 点击搜索 @@ -139,3 +140,31 @@ class ControlUtils(object): else: print("没有找到主页的第一个视频") return False, num + + @classmethod + def clickFollow(cls, session, aid): + # 1) 含“关注/已关注/Follow/Following”的首个 cell + cell_xpath = ( + '(//XCUIElementTypeCollectionView[@name="TTKSearchCollectionComponent"]' + '//XCUIElementTypeCell[.//XCUIElementTypeButton[@name="关注" or @name="Follow" or @name="已关注" or @name="Following"]])[1]' + ) + cell = session.xpath(cell_xpath).get(timeout=5) + + # 2) 先试“用户信息 Button”(label/name 里包含 aid) + profile_btn_xpath = ( + f'{cell_xpath}//XCUIElementTypeButton[contains(@label, "{aid}") or contains(@name, "{aid}")]' + ) + + try: + profile_btn = session.xpath(profile_btn_xpath).get(timeout=3) + profile_btn.click() + except wda.WDAElementNotFoundError: + # 3) 兜底:用“关注”按钮做锚点,向左偏移点击头像/用户名区域 + follow_btn_xpath = ( + f'{cell_xpath}//XCUIElementTypeButton[@name="关注" or @name="Follow" or @name="已关注" or @name="Following"]' + ) + follow_btn = session.xpath(follow_btn_xpath).get(timeout=5) + rect = follow_btn.bounds + left_x = max(1, rect.x - 20) + center_y = rect.y + rect.height // 2 + session.tap(left_x, center_y) diff --git a/Utils/ThreadManager.py b/Utils/ThreadManager.py index d641e2a..82032f7 100644 --- a/Utils/ThreadManager.py +++ b/Utils/ThreadManager.py @@ -20,8 +20,8 @@ class ThreadManager(): try: info = cls.threads[udid] if info: - info["stopEvent"].set() # 停止线程 - info["thread"].join(timeout=3) # 等待线程退出 + info["stopEvent"].set() # 停止线程 + info["thread"].join(timeout=3) # 等待线程退出 del cls.threads[udid] LogManager.info("停止线程成功", udid) return 200, "停止线程成功 " + udid @@ -30,4 +30,4 @@ class ThreadManager(): return 1001, "无此线程,无需关闭 " + udid except KeyError as e: LogManager.info("无此线程,无需关闭", udid) - return 1001, "停止脚本失败 " + udid \ No newline at end of file + return 1001, "停止脚本失败 " + udid diff --git a/resources/833c034d29ee6b79e1dfd88dc1d454f3da1e8a3d/bgv.png b/resources/833c034d29ee6b79e1dfd88dc1d454f3da1e8a3d/bgv.png deleted file mode 100644 index 1e4bc0e..0000000 Binary files a/resources/833c034d29ee6b79e1dfd88dc1d454f3da1e8a3d/bgv.png and /dev/null differ diff --git a/resources/eca000fcb6f55d7ed9b4c524055214c26a7de7aa/bgv.png b/resources/eca000fcb6f55d7ed9b4c524055214c26a7de7aa/bgv.png deleted file mode 100644 index 65716f6..0000000 Binary files a/resources/eca000fcb6f55d7ed9b4c524055214c26a7de7aa/bgv.png and /dev/null differ diff --git a/resources/fc18bc21951daf7be012a8a687b00a4de8b24c18/bgv.png b/resources/fc18bc21951daf7be012a8a687b00a4de8b24c18/bgv.png deleted file mode 100644 index 2c232b1..0000000 Binary files a/resources/fc18bc21951daf7be012a8a687b00a4de8b24c18/bgv.png and /dev/null differ diff --git a/script/ScriptManager.py b/script/ScriptManager.py index 3f7f4d8..55d60e7 100644 --- a/script/ScriptManager.py +++ b/script/ScriptManager.py @@ -49,7 +49,7 @@ class ScriptManager(): time.sleep(1) ControlUtils.openTikTok(session, udid) time.sleep(3) - LogManager.info("养号重启tiktok") + LogManager.info("养号重启tiktok", udid) AiUtils.makeUdidDir(udid) # ========= 主循环 ========= @@ -183,7 +183,6 @@ class ScriptManager(): if live_button.exists: continue - # 下滑一下 client.swipe_up() @@ -479,6 +478,7 @@ class ScriptManager(): # 关注打招呼以及回复主播消息 def greetNewFollowers(self, udid, needReply, event): + client = wda.USBClient(udid) session = client.session() print(f"是否要自动回复消息:{needReply}") @@ -536,24 +536,8 @@ class ScriptManager(): session.appium_settings({"snapshotMaxDepth": 23}) try: - - # 查找“关注”按钮 - follow_btn = session.xpath( - '//XCUIElementTypeButton[@name="关注" or @name="Follow" or @name="已关注" or @name="Following"]').get( - timeout=5) - - # 获取按钮位置和大小 - rect = follow_btn.bounds - left_x = max(1, rect.x - 20) # 向左偏移 20px,确保不会点到屏幕外 - center_y = rect.y + rect.height // 2 - - # 打印调试信息 - print(f"关注按钮位置 x={rect.x}, y={rect.y}, width={rect.width}, height={rect.height}") - print(f"即将点击的位置 x={left_x}, y={center_y}") - - # 点击关注按钮左侧区域(通常是头像) - session.tap(left_x, center_y) - + # 点击关注按钮 + ControlUtils.clickFollow(session, aid) except wda.WDAElementNotFoundError: # 如果没有“关注”按钮,则不点击 print("未找到‘关注’按钮,跳过点击。") @@ -596,6 +580,7 @@ class ScriptManager(): time.sleep(2) # 查找add图标 r = ControlUtils.clickLike(session, udid) + # 点赞成功。 # if r == True: @@ -628,8 +613,8 @@ class ScriptManager(): followButton.click() else: LogManager.info("没找到关注按钮", udid) - removeModelFromAnchorList(anchor) goBack(3) + session.appium_settings({"snapshotMaxDepth": 15}) continue time.sleep(2) @@ -641,8 +626,8 @@ class ScriptManager(): msgButton.click() else: print("没有识别出发消息按钮") - removeModelFromAnchorList(anchor) goBack(3) + session.appium_settings({"snapshotMaxDepth": 15}) continue time.sleep(3) @@ -666,6 +651,8 @@ class ScriptManager(): # 接着下一个主播 # removeModelFromAnchorList(anchor) + session.appium_settings({"snapshotMaxDepth": 15}) + goBack(4) else: @@ -697,6 +684,7 @@ class ScriptManager(): time.sleep(3) print("重新创建wda会话 防止wda会话失效") + client = wda.USBClient(udid) session = client.session() @@ -738,9 +726,8 @@ class ScriptManager(): # 调整节点的深度为 7 session.appium_settings({"snapshotMaxDepth": 7}) - el = session(xpath='//XCUIElementTypeButton[@name="a11y_vo_inbox"]') - print(111111111111111111111111) + el = session(xpath='//XCUIElementTypeButton[@name="a11y_vo_inbox"]') # 如果收件箱有消息 则进行点击 if el.exists: @@ -751,7 +738,6 @@ class ScriptManager(): session.appium_settings({"snapshotMaxDepth": 25}) time.sleep(3) while True: - info_count = 0 # 创建新的会话 @@ -776,7 +762,6 @@ class ScriptManager(): LogManager.error(f"当前页面不再收件箱页面,重启", udid) raise Exception("当前页面不再收件箱页面,重启") - print(3333333333333333333333333333333) m = re.search(r'(\d+)', el.label) # 抓到的第一个数字串 count = int(m.group(1)) if m else 0 @@ -818,7 +803,70 @@ class ScriptManager(): ']//XCUIElementTypeStaticText[@value and translate(@value,"0123456789","")=""]' ) - print(44444444444444444444444444444444) + try: + # 如果 2 秒内找不到,会抛异常 + user_text = session.xpath(xp_badge_numeric).get(timeout=2.0) + val = (user_text.info.get("value") or + user_text.info.get("label") or + user_text.info.get("name")) + LogManager.info(f"用户未读数量:{val}", udid) + except Exception: + LogManager.warning("当前屏幕没有找到 用户 未读徽标数字", udid) + print("当前屏幕没有找到 用户消息 未读徽标数字", udid) + user_text = None + info_count += 1 + + if user_text: + user_text.tap() + time.sleep(3) + xml = session.source() + msgs = AiUtils.extract_messages_from_xml(xml) + # 检测出对方发的最后一条信息 + last_msg_text = next(item['text'] for item in reversed(msgs) if item['type'] == 'msg') + # 向ai发送信息 + + # 获取主播的名称 + anchor_name = AiUtils.get_navbar_anchor_name(session) + + # 找到输入框 + + sel = session.xpath("//TextView") + + if anchor_name not in anchorWithSession: + # 如果是第一次发消息(没有sessionId的情况) + response = Requester.chatToAi({"msg": last_msg_text}) + aiResult = response['result'] + sessionId = response['session_id'] + + anchorWithSession[anchor_name] = sessionId + # 找到输入框,输入ai返回出来的消息 + if sel.exists: + sel.click() # 聚焦 + time.sleep(1) + sel.clear_text() + sel.set_text(aiResult + "\n") + else: + LogManager.error("找不到输入框,重启", udid) + raise Exception("找不到输入框,重启") + else: + # 如果不是第一次发消息(证明存储的有sessionId) + sessionId = anchorWithSession[anchor_name] + response = Requester.chatToAi({"msg": last_msg_text, "sid": sessionId}) + aiResult = response['result'] + if sel.exists: + sel.click() # 聚焦 + time.sleep(1) + sel.clear_text() + sel.set_text(aiResult + "\n") + + LogManager.info(f"存储的sessionId:{anchorWithSession}", udid) + time.sleep(1) + # 返回 + ControlUtils.clickBack(session) + + # 重新回到收件箱页面后,强制刷新节点 + session.appium_settings({"snapshotMaxDepth": 25}) + time.sleep(1) try: # 如果 2 秒内找不到,会抛异常 @@ -894,71 +942,6 @@ class ScriptManager(): badge_text = None info_count += 1 - try: - # 如果 2 秒内找不到,会抛异常 - user_text = session.xpath(xp_badge_numeric).get(timeout=2.0) - val = (user_text.info.get("value") or - user_text.info.get("label") or - user_text.info.get("name")) - LogManager.info(f"用户未读数量:{val}", udid) - except Exception: - LogManager.warning("当前屏幕没有找到 用户 未读徽标数字", udid) - print("当前屏幕没有找到 用户消息 未读徽标数字", udid) - user_text = None - info_count += 1 - - if user_text: - user_text.tap() - time.sleep(3) - xml = session.source() - msgs = AiUtils.extract_messages_from_xml(xml) - # 检测出对方发的最后一条信息 - last_msg_text = next(item['text'] for item in reversed(msgs) if item['type'] == 'msg') - # 向ai发送信息 - - # 获取主播的名称 - anchor_name = AiUtils.get_navbar_anchor_name(session) - - # 找到输入框 - - sel = session.xpath("//TextView") - - if anchor_name not in anchorWithSession: - # 如果是第一次发消息(没有sessionId的情况) - response = Requester.chatToAi({"msg": last_msg_text}) - aiResult = response['result'] - sessionId = response['session_id'] - - anchorWithSession[anchor_name] = sessionId - # 找到输入框,输入ai返回出来的消息 - if sel.exists: - sel.click() # 聚焦 - time.sleep(1) - sel.clear_text() - sel.set_text(aiResult + "\n") - else: - LogManager.error("找不到输入框,重启", udid) - raise Exception("找不到输入框,重启") - else: - # 如果不是第一次发消息(证明存储的有sessionId) - sessionId = anchorWithSession[anchor_name] - response = Requester.chatToAi({"msg": last_msg_text, "sid": sessionId}) - aiResult = response['result'] - if sel.exists: - sel.click() # 聚焦 - time.sleep(1) - sel.clear_text() - sel.set_text(aiResult + "\n") - - LogManager.info(f"存储的sessionId:{anchorWithSession}", udid) - time.sleep(1) - # 返回 - ControlUtils.clickBack(session) - - # 重新回到收件箱页面后,强制刷新节点 - session.appium_settings({"snapshotMaxDepth": 25}) - time.sleep(1) - # 双击收件箱 定位到消息的位置 if info_count == 5: r = el.bounds # 可能是命名属性,也可能是 tuple @@ -966,9 +949,9 @@ class ScriptManager(): cy = int((r.y + r.height / 2) if hasattr(r, "y") else (r[1] + r[3] / 2)) session.double_tap(cx, cy) # 可能抛异常:方法不存在 LogManager.info(f"双击收件箱 定位到信息", udid) + else: return else: LogManager.error(f"检测不到收件箱", udid) raise Exception("当前页面找不到收件箱,重启") -