PUGE há 1 mês atrás
pai
commit
7ab3a26cb0
1 ficheiros alterados com 221 adições e 21 exclusões
  1. 221 21
      MuMu.py

+ 221 - 21
MuMu.py

@@ -9,6 +9,10 @@ import threading
 import configparser
 from datetime import datetime
 
+# 用于存储线程的列表
+threads = []
+results = {}  # 存储每个模拟器的执行结果
+
 class MuMuEmulatorManager:
     # 类级别的剪贴板锁,所有实例共享
     _clipboard_lock = threading.Lock()
@@ -176,6 +180,54 @@ class MuMuEmulatorManager:
                 log_callback(f"✅ 点击坐标 ({x}, {y})")
             return True
         return False
+    def swipe(self, index, x1, y1, x2, y2, duration_ms=300, log_callback=None):
+        """从坐标 (x1, y1) 滑动到 (x2, y2)"""
+        adb_port = self.get_adb_port(index)
+        target_device = f"127.0.0.1:{adb_port}"
+        
+        subprocess.run(f"adb connect {target_device}", shell=True, capture_output=True)
+        
+        cmd = f"adb -s {target_device} shell input swipe {x1} {y1} {x2} {y2} {duration_ms}"
+        result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
+        
+        if result.returncode == 0:
+            if log_callback:
+                log_callback(f"✅ 滑动从 ({x1}, {y1}) 到 ({x2}, {y2}),耗时 {duration_ms}ms")
+            return True
+        else:
+            if log_callback:
+                log_callback(f"❌ 滑动失败: {result.stderr}")
+            return False
+    def get_screen_size(self, index, log_callback=None):
+        """获取模拟器屏幕分辨率,返回 (width, height)"""
+        adb_port = self.get_adb_port(index)
+        target_device = f"127.0.0.1:{adb_port}"
+        
+        subprocess.run(f"adb connect {target_device}", shell=True, capture_output=True)
+        time.sleep(0.5)
+        
+        get_resolution_cmd = f"adb -s {target_device} shell wm size"
+        result = subprocess.run(get_resolution_cmd, shell=True, capture_output=True, text=True)
+        
+        if result.stdout:
+            import re
+            match = re.search(r'(\d+)x(\d+)', result.stdout)
+            if match:
+                width = int(match.group(1))
+                height = int(match.group(2))
+                if log_callback:
+                    log_callback(f"📱 模拟器 {index} 分辨率: {width}x{height}")
+                return width, height
+        return None, None
+
+    def check_resolution(self, index, expected_width=720, log_callback=None):
+        """检查分辨率宽度是否符合要求,返回 True/False"""
+        width, height = self.get_screen_size(index, log_callback)
+        if width is None:
+            if log_callback:
+                log_callback(f"⚠️ 模拟器 {index} 无法获取分辨率")
+            return False
+        return width == expected_width
     
     def get_pixel_color(self, index, x, y, log_callback=None):
         """获取模拟器内指定坐标点的颜色"""
@@ -552,9 +604,21 @@ class MuMuAutoGUI:
         for item in self.emulator_tree.get_children():
             values = self.emulator_tree.item(item, 'values')
             if values[0] == "□":
-                self.emulator_tree.item(item, values=("☑", values[1], values[2], values[3], values[4]))
+                self.emulator_tree.item(item, values=("☑", values[1], values[2], values[3]))
         self.log_message("已全选所有模拟器")
     
+    def update_emulator_status(self, index, status):
+        """更新指定索引的模拟器状态显示
+        Args:
+            index: 模拟器索引(字符串)
+            status: 状态文本,如 "运行中" 或 "未运行"
+        """
+        for item in self.emulator_tree.get_children():
+            values = self.emulator_tree.item(item, 'values')
+            if values[1] == str(index):
+                self.emulator_tree.item(item, values=(values[0], values[1], values[2], status))
+                break
+    
     def load_emulators(self):
         """加载模拟器列表"""
         try:
@@ -670,13 +734,38 @@ class MuMuAutoGUI:
             self.is_running = False
             self.is_paused = False
             self.log_message("⏹ 正在停止任务...")
-    
+
     def openBook(self, manager, index):
+        global results
         # 执行操作
         manager.tap(index, 390, 90, self.log_message)
-        while manager.get_pixel_color(index, 560, 65, log_callback=self.log_message) != "#F7F7F7":
-            self.log_message(f"模拟器 {index} 等待搜索页面准备就绪...")
+        color56065 = manager.get_pixel_color(index, 560, 65, log_callback=self.log_message)
+        errNumber = 0
+        while color56065 != "#F7F7F7":
+            if color56065 == "#EBF8EC":
+                manager.tap(index, 390, 90, self.log_message)
+                self.log_message(f"模拟器 {index} 尝试重新点击搜索...")
+            if color56065 == "#5E635E":
+                self.log_message(f"模拟器 {index} 需要关闭红包弹窗...")
+                manager.tap(index, 640, 260, self.log_message)
+                time.sleep(20)
+                manager.tap(index, 57, 193, self.log_message)
+            if color56065 in ["#EBE8E4", "#CDD0D1"]:
+                self.log_message(f"模拟器 {index} 进入错误页面,返回...")
+                manager.tap(index, 44, 92, self.log_message)
+            else:
+                errNumber = errNumber + 1
+                if errNumber > 30:
+                    self.log_message(f"模拟器 {index} 连续多次未检测到搜索页面,设置错误并退出...")
+                    # 关闭模拟器
+                    self.log_message(f"正在关闭模拟器 {index}...")
+                    manager.stop_emulator(index)
+                    results[index] = False
+                    self.log_message(f"✅ 模拟器 {index} 错误退出")
+                    self.root.after(0, lambda: self.update_emulator_status(index, "遇到错误"))
+                self.log_message(f"模拟器 {index} 等待搜索页面准备就绪...")
             time.sleep(3)
+            color56065 = manager.get_pixel_color(index, 560, 65, log_callback=self.log_message)
         time.sleep(3)
         # 点输入框
         manager.tap(index, 340, 90, self.log_message)
@@ -684,7 +773,17 @@ class MuMuAutoGUI:
         # 黏贴
         manager.paste_text(index, self.search_content_var.get(), self.log_message)
         time.sleep(3)
+        errNumber = 0
         while manager.get_pixel_color(index, 435, 880, log_callback=self.log_message) != "#FFFFFF":
+            errNumber = errNumber + 1
+            if errNumber > 30:
+                self.log_message(f"模拟器 {index} 连续多次未检测到搜索页面,设置错误并退出...")
+                # 关闭模拟器
+                self.log_message(f"正在关闭模拟器 {index}...")
+                manager.stop_emulator(index)
+                results[index] = False
+                self.log_message(f"✅ 模拟器 {index} 错误退出")
+                self.root.after(0, lambda: self.update_emulator_status(index, "遇到错误"))
             self.log_message(f"模拟器 {index} 没有输入搜索内容...")
             # 点输入框
             manager.tap(index, 556, 87, self.log_message)
@@ -696,7 +795,30 @@ class MuMuAutoGUI:
             time.sleep(3)
         manager.tap(index, 655, 92, self.log_message)
         time.sleep(6)
-        while manager.get_pixel_color(index, 630, 235, log_callback=self.log_message) != "#FFFFFF":
+        
+        while True:
+            color630235 = manager.get_pixel_color(index, 630, 235, log_callback=self.log_message)
+            print(color630235)
+            errNumber = 0
+            if color630235 in ["#FFFFFF"]:
+                self.log_message(f"模拟器 {index} 已经在搜索结果页面,继续...")
+                break
+            elif color630235 in ["#E8E3CE", "#E0DBC6", "#CCCBCB", "#DFDAC5", "#141000"]:
+                self.log_message(f"模拟器 {index} 已经在看书目录界面,继续...")
+                break
+            elif color630235 in ["#F9F9FC"]:
+                self.log_message(f"模拟器 {index} 关闭广告弹窗,继续...")
+                manager.tap(index, 634, 123, self.log_message)
+            else:
+                errNumber = errNumber + 1
+                if errNumber > 30:
+                    self.log_message(f"模拟器 {index} 连续多次未检测到搜索页面,设置错误并退出...")
+                    # 关闭模拟器
+                    self.log_message(f"正在关闭模拟器 {index}...")
+                    manager.stop_emulator(index)
+                    results[index] = False
+                    self.log_message(f"✅ 模拟器 {index} 错误退出")
+                    self.root.after(0, lambda: self.update_emulator_status(index, "遇到错误"))
             self.log_message(f"模拟器 {index} 等待搜索结果...")
             time.sleep(3)
 
@@ -704,12 +826,30 @@ class MuMuAutoGUI:
         time.sleep(6)
         manager.tap(index, 355, 333, self.log_message)
         time.sleep(5)
-        while manager.get_pixel_color(index, 630, 235, log_callback=self.log_message) == "#FFFFFF":
+        errNumber = 0
+        while True:
+            color630235 = manager.get_pixel_color(index, 630, 235, log_callback=self.log_message)
+            print(color630235)
+            if color630235 in ["#E8E3CE", "#E0DBC6", "#CCCBCB", "#DFDAC5", "#141000", "#E3DEC9"]:
+                self.log_message(f"模拟器 {index} 已经在看书目录界面,继续...")
+                break
+            else:
+                errNumber = errNumber + 1
+                if errNumber > 20:
+                    self.log_message(f"模拟器 {index} 连续多次未检测到搜索页面,设置错误并退出...")
+                    # 关闭模拟器
+                    self.log_message(f"正在关闭模拟器 {index}...")
+                    manager.stop_emulator(index)
+                    results[index] = False
+                    self.log_message(f"✅ 模拟器 {index} 错误退出")
+                    self.root.after(0, lambda: self.update_emulator_status(index, "遇到错误"))
             self.log_message(f"模拟器 {index} 还在搜索结果页面,重新点击...")
             manager.tap(index, 355, 333, self.log_message)
             time.sleep(5)
 
     def run_task(self):
+        global results
+        global threads
         """执行任务(支持并发)"""
         try:
             manager = MuMuEmulatorManager(self.mumu_path_var.get())
@@ -719,9 +859,7 @@ class MuMuAutoGUI:
             self.thread_semaphore = threading.Semaphore(max_threads)
             self.log_message(f"📌 最大并发数: {max_threads}")
             
-            # 用于存储线程的列表
-            threads = []
-            results = {}  # 存储每个模拟器的执行结果
+            
             
             def process_emulator(emu):
                 """处理单个模拟器的函数"""
@@ -734,6 +872,9 @@ class MuMuAutoGUI:
                     self.log_message(f"开始处理模拟器 {index} ({emu['name']})")
                     self.log_message(f"{'='*50}")
                     
+                    # 更新状态为运行中
+                    self.root.after(0, lambda: self.update_emulator_status(index, "运行中"))
+                    
                     try:
                         # 启动模拟器
                         self.log_message(f"正在启动模拟器 {index}...")
@@ -749,7 +890,12 @@ class MuMuAutoGUI:
                             return
                         
                         time.sleep(5)
-                        
+                        if not manager.check_resolution(index, 720, self.log_message):
+                            self.log_message(f"❌ 模拟器 {index} 分辨率不是720,停止任务并关闭模拟器")
+                            manager.stop_emulator(index)
+                            results[index] = False
+                            self.root.after(0, lambda: self.update_emulator_status(index, "分辨率错误"))
+                            return
                         # 安装APK
                         if not manager.install_apk(index, self.apk_path_var.get(), self.log_message):
                             self.log_message(f"❌ APK安装失败")
@@ -765,31 +911,72 @@ class MuMuAutoGUI:
                         # 是否是第一次进入
                         if (button_color and button_color.upper() == "#FC7838"):
                             manager.tap(index, 394, 846, self.log_message)
-                            time.sleep(90)
+                            time.sleep(120)
+                            boxColor = manager.get_pixel_color(index, 640, 260, log_callback=self.log_message)
                             manager.tap(index, 640, 260, self.log_message)
-                            time.sleep(10)
+                            time.sleep(20)
+                            
                             manager.tap(index, 57, 193, self.log_message)
                             time.sleep(5)
                         else:
                             time.sleep(10)
                         
-                        while manager.get_pixel_color(index, 560, 130, log_callback=self.log_message) != "#EEF8EE":
+                        while True:
+                            color560130 = manager.get_pixel_color(index, 560, 130, log_callback=self.log_message)
+                            if color560130 in ["#EEF8EE", "#F7F7F7"]:
+                                self.log_message(f"模拟器 {index} 已经进入主界面,继续...")
+                                break
+                            if color560130 in ["#5F635F"]:
+                                self.log_message(f"模拟器 {index} 需要关闭红包弹窗...")
+                                manager.tap(index, 640, 260, self.log_message)
+                                time.sleep(20)
+                                
+                                manager.tap(index, 57, 193, self.log_message)
+                            if color560130 in ["#CED0D2"]:
+                                self.log_message(f"模拟器 {index} 需要关闭广告弹窗...")
+                                manager.tap(index, 200, 80, self.log_message)
+
+                            # F3CEA9可能是推荐榜
+                            if color560130 in ["#F3CEA9"]:
+                                self.log_message(f"模拟器 {index} 进入错误页面,返回...")
+                                manager.tap(index, 44, 92, self.log_message)
+                                time.sleep(20)
+                                
+                                manager.tap(index, 57, 193, self.log_message)
                             self.log_message(f"模拟器 {index} 等待进入主界面中...")
-                            manager.get_pixel_color(index, 640, 260, log_callback=self.log_message)
+                            # manager.get_pixel_color(index, 640, 260, log_callback=self.log_message)
                             time.sleep(5)
                         # 执行操作
                         self.openBook(manager, index)
                         
                         
                         time.sleep(8)
+                        errNumber = 0
                         # 翻页
                         for page in range(int(self.page_count_var.get()) if self.page_count_var.get().isdigit() else 5):
                             # 判断是否在看书目录界面
-                            while manager.get_pixel_color(index, 712, 147, log_callback=self.log_message) not in ["#E8E3CE", "#E0DBC6"]:
+                            while True:
+                                color7001000 = manager.get_pixel_color(index, 700, 1000, log_callback=self.log_message)
+                                if color7001000 in ["#E8E3CE", "#E0DBC6", "#CCCBCB"]:
+                                    self.log_message(f"模拟器 {index} 在看书目录界面,继续翻页...")
+                                    break
+                                if color7001000 in [ "#F9F9FC"]:
+                                    self.log_message(f"模拟器 {index} 遇到广告,点击跳过...")
+                                    manager.tap(index, 700, 300, self.log_message)
                                 self.log_message(f"模拟器 {index} 不在看书目录界面,等待中...")
+                                errNumber = errNumber + 1
+                                if errNumber > 10:
+                                    self.log_message(f"模拟器 {index} 连续多次未检测到目录界面,设置错误并退出...")
+                                    # 关闭模拟器
+                                    self.log_message(f"正在关闭模拟器 {index}...")
+                                    manager.stop_emulator(index)
+                                    
+                                    self.log_message(f"✅ 模拟器 {index} 错误退出")
+                                    results[index] = False
+                                    self.root.after(0, lambda: self.update_emulator_status(index, "遇到错误"))
                                 # 判断是否有广告
                                 time.sleep(2)
-                                if manager.get_pixel_color(index, 700, 1200, log_callback=self.log_message) in ["#e8e3ce"]:
+                                if manager.get_pixel_color(index, 700, 1200, log_callback=self.log_message) in ["#E8E3CE"]:
                                     self.log_message(f"模拟器 {index} 点击跳过广告!")
                                     manager.tap(index, 700, 1200, self.log_message)
                                 time.sleep(3)
@@ -806,13 +993,16 @@ class MuMuAutoGUI:
                                 intervalNum = int(self.page_interval_var.get()) if self.page_interval_var.get().isdigit() else 30
                             time.sleep(intervalNum)
                             # manager.tap(index, 700, 1055, self.log_message)
-                            manager.tap(index, 700, 1055, self.log_message)
+                            # 清空错误信息
+                            errNumber = 0
+                            # manager.tap(index, 700, 1000, self.log_message)
+                            manager.swipe(index, 700, 700, 200, 700, 500, self.log_message)
                         time.sleep(2)
                         # 加入书签
                         self.log_message(f"正在加入书架 {index}...")
                         manager.tap(index, 360, 600, self.log_message)
                         time.sleep(2)
-                        manager.tap(index, 255, 97, self.log_message)
+                        manager.tap(index, 255, 84, self.log_message)
                         time.sleep(3)
                         # 关闭模拟器
                         self.log_message(f"正在关闭模拟器 {index}...")
@@ -820,10 +1010,11 @@ class MuMuAutoGUI:
                         
                         self.log_message(f"✅ 模拟器 {index} 任务完成")
                         results[index] = True
-                        
+                        self.root.after(0, lambda: self.update_emulator_status(index, "任务完成"))
                     except Exception as e:
                         self.log_message(f"❌ 模拟器 {index} 执行出错: {e}")
                         results[index] = False
+                        self.root.after(0, lambda: self.update_emulator_status(index, "执行出错"))
             
             # 启动所有模拟器任务(信号量会自动控制并发数)
             for emu in self.selected_emulators:
@@ -879,6 +1070,9 @@ class MuMuAutoGUI:
                     self.log_message(f"开始处理模拟器 {index} ({emu['name']})")
                     self.log_message(f"{'='*50}")
                     
+                    # 更新状态为运行中
+                    self.root.after(0, lambda: self.update_emulator_status(index, "运行中"))
+                    
                     try:
                         # 启动模拟器
                         self.log_message(f"正在启动模拟器 {index}...")
@@ -894,7 +1088,12 @@ class MuMuAutoGUI:
                             return
                         
                         time.sleep(5)
-                        
+                        if not manager.check_resolution(index, 720, self.log_message):
+                            self.log_message(f"❌ 模拟器 {index} 分辨率不是720,停止任务并关闭模拟器")
+                            manager.stop_emulator(index)
+                            results[index] = False
+                            self.root.after(0, lambda: self.update_emulator_status(index, "分辨率错误"))
+                            return
                         # 安装APK
                         if not manager.install_apk(index, self.apk_path_var.get(), self.log_message):
                             self.log_message(f"❌ APK安装失败")
@@ -927,10 +1126,11 @@ class MuMuAutoGUI:
                         
                         self.log_message(f"✅ 模拟器 {index} 任务完成")
                         results[index] = True
-                        
+                        self.root.after(0, lambda: self.update_emulator_status(index, "任务完成"))
                     except Exception as e:
                         self.log_message(f"❌ 模拟器 {index} 执行出错: {e}")
                         results[index] = False
+                        self.root.after(0, lambda: self.update_emulator_status(index, "执行出错"))
             
             # 启动所有模拟器任务
             for emu in self.selected_emulators: