예제 #1
0
    def RunTasks(self,
                 tasks: dict,
                 continue_=True,
                 max_retry=3,
                 first_init_home=True,
                 rec_addr="rec"):
        """
        运行任务集
        By TheAutumnOfRice 2020-07-26
        2020-7-27 Fix: 把tasks参数放在外面读,防止多进程同时读某一个文件造成的问题
        :param tasks: 合法的任务字典
        :param continue_: 是否继续上次未完成的任务
        :param max_retry:  最大试错次数,超过max_retry却还不停报错则只能下次再见!
        :param first_init_home: 是否一开始执行init_home。
        :param rec_addr: 记录文件存放目录
        """
        user = self.AR.getuser()  # 获取配置文件
        account = user["account"]
        password = user["password"]
        check_task_dict(tasks, True)
        self.ms = moveset(account, rec_addr)  # 创建行为列表用于断点恢复
        self.ms.startw(None, start=True)  # 使用自动序列创建的起手式

        def funwarper(funname, title, kwargs):
            # 将funname包装为一个函数,调用self.funname(**kwargs)
            def fun(var):
                # var参数:用于断点恢复的变量
                # 使用try来保证兼容性:如果函数没有var参数,则不传入var参数。
                self.log.write_log("info", f"正在执行: {title} 记录存放目录: {rec_addr}")
                # 标记当前执行的位置!
                self.task_current(title)
                flag = False
                try:
                    self.__getattribute__(funname)(**kwargs, var=var)
                except TypeError:
                    flag = True
                if flag:
                    self.__getattribute__(funname)(**kwargs)

            return fun

        self.log.write_log("info", f"任务列表:")
        # 解析任务列表
        for task in tasks["tasks"]:
            if "__disable__" in task and task["__disable__"]:
                continue
            typ = task["type"]
            cur = VALID_TASK.T[typ]
            kwargs = {}
            for param in task:
                if param == "type":
                    continue
                if param == "__disable__":
                    continue
                kwargs[param] = task[param]
            for v_p in cur["params"]:  # Valid Param: Default Param
                if v_p.default is not None and v_p.key not in kwargs:
                    kwargs[v_p.key] = v_p.default

            self.ms.nextwv(funwarper(cur["funname"], cur['title'],
                                     kwargs))  # 自动创建序列
            self.log.write_log("info", f"  +任务 {cur['title']}")  # 打印该任务
            for key in kwargs:
                self.log.write_log("info", f"    参数 {key} : {kwargs[key]}")
        self.ms.exitw(None)  # 结束自动序列创建
        # 未知异常:仍然是重启哒!万能的重启万岁!
        last_exception = None
        before_ = True
        retry = 0
        while retry <= max_retry:
            try:
                if before_:
                    self.task_current("登录")
                    _return_code = self.login_auth(account, password)
                    if _return_code == -1:
                        # 标记错误!
                        self.task_error(str('%s账号出现了验证码' % self.account))
                        if captcha_skip:
                            self.fix_reboot(False)
                            return False
                    if continue_ is False:
                        # 初次执行,记录一下
                        self.task_start()
                    if first_init_home:
                        self.init_home()  # 处理第一次进home的一系列问题
                    before_ = False
                try:
                    self.ms.run(continue_=continue_)
                except UnknownMovesetException as e:
                    pcr_log(account).write_log("warning",
                                               message=f'记录文件冲突,自动刷新运行记录:{e}')
                    self.ms.run(continue_=False)
                # 刷完啦!标记一下”我刷完了“
                self.task_finished()
                return True
            except ForceKillException as e:
                pcr_log(account).write_log(level='info', message=f'强制终止')
                try:
                    self.fix_reboot(False)
                except:
                    pcr_log(account).write_log(level='warning',
                                               message=f'强制终止-重启失败!')
                raise e
            except FastScreencutException as e:
                pcr_log(account).write_log(level='error',
                                           message=f'快速截图出现错误,{e},尝试重新连接……')
                self.fix_reboot()
                self.init_fastscreen()
            except OfflineException as e:
                pcr_log(account).write_log('error',
                                           message=f'main-检测到设备离线:{e}')
                return False
            except ReadTimeoutException as e:
                pcr_log(account).write_log(
                    'error', message=f'main-检测到连接超时,{e},尝试重新连接……')
                self.init_device(self.address)
            except Exception as e:
                retry += 1
                try:
                    os.makedirs(f"error_screenshot/{account}", exist_ok=True)
                    nowtime = datetime.datetime.strftime(
                        datetime.datetime.now(), "%Y%m%d_%H%M%S")
                    target = f"error_screenshot/{account}/{nowtime}_RT{retry}.bmp"
                    cv2.imwrite(target, self.last_screen)
                    pcr_log(account).write_log(level="error",
                                               message=f"错误截图已经保存至{target}")
                except Exception as es:
                    pcr_log(account).write_log(level="error",
                                               message=f"错误截图保存失败:{es}")
                if trace_exception_for_debug:
                    tb = traceback.format_exc()
                    pcr_log(account).write_log(level="error", message=tb)
                last_exception = e
                continue_ = True
                if retry == max_retry:
                    pcr_log(account).write_log(
                        level="error", message=f"main-检测出异常{e} 超出最大重试次数,跳过账号!")
                    # 标记错误!
                    self.task_error(str(last_exception))
                    self.fix_reboot(False)
                    return False
                pcr_log(account).write_log(
                    level='error',
                    message=f'main-检测出异常{e},重启中 次数{retry}/{max_retry}')

                try:
                    self.fix_reboot(before_)
                except Exception as e:
                    pcr_log(account).write_log(level='error',
                                               message=f'main-自动重启失败,跳过账号!{e}')
                    self.task_error(str(last_exception))
                    try:
                        self.fix_reboot(False)
                    except:
                        pass
                    return False
예제 #2
0
    def RunTasks(self,
                 tasks: dict,
                 continue_=True,
                 max_retry=3,
                 first_init_home=True,
                 rec_addr="rec"):
        """
        运行任务集
        By TheAutumnOfRice 2020-07-26
        2020-7-27 Fix: 把tasks参数放在外面读,防止多进程同时读某一个文件造成的问题
        :param tasks: 合法的任务字典
        :param continue_: 是否继续上次未完成的任务
        :param max_retry:  最大试错次数,超过max_retry却还不停报错则只能下次再见!
        :param first_init_home: 是否一开始执行init_home。
        :param rec_addr: 记录文件存放目录
        """
        user = self.AR.getuser()  # 获取配置文件
        account = user["account"]
        password = user["password"]
        check_task_dict(tasks, True)
        self.ms = moveset(account, rec_addr)  # 创建行为列表用于断点恢复
        self.ms.startw(None, start=True)  # 使用自动序列创建的起手式

        def funwarper(funname, title, kwargs):
            # 将funname包装为一个函数,调用self.funname(**kwargs)
            def fun(var):
                # var参数:用于断点恢复的变量
                # 使用try来保证兼容性:如果函数没有var参数,则不传入var参数。
                self.log.write_log("info", f"正在执行: {title} 记录存放目录: {rec_addr}")
                # 标记当前执行的位置!
                self.task_current(title)
                # 防止泄露全局影响
                self.ES.FCs.clear()  # 清除全部ES
                self.headers_group.clear()  # 清除全部header
                self.register_basic_ES()
                self.prechecks.clear()
                self.enable_precheck = True
                flag = False
                try:
                    self.__getattribute__(funname)(**kwargs, var=var)
                except TypeError as e:
                    if debug:
                        self.log.write_log(
                            "debug",
                            f"Catch Type Error:{e} - {funname} - {kwargs}")
                    flag = True
                    if 'var' not in str(e):
                        raise e
                if flag:
                    self.__getattribute__(funname)(**kwargs)

            return fun

        self.log.write_log("info", f"任务列表:")
        # 解析任务列表
        self._task_index = {}
        for task in tasks["tasks"]:
            typ = task["type"]

            if "__disable__" in task:
                # 存在禁用配置
                if task["__disable__"] is True:
                    typ = "nothing"  # 直接禁用
                elif task["__disable__"] is not False:
                    # 有开关
                    FLAGS = list_all_flags()
                    detail = None
                    for flag, details in FLAGS.items():
                        if task["__disable__"] == flag:
                            detail = details
                            break
                    if detail is not None:
                        use_default = True
                        if self.account in detail["user"] and detail["user"][
                                self.account] is True:
                            typ = "nothing"  # 针对用户特殊:直接禁用
                            use_default = False
                        elif self.account in detail["user"] and detail["user"][
                                self.account] is False:
                            use_default = False
                        else:
                            # 针对组特殊:
                            for group, set in detail["group"].items():
                                if is_in_group(self.account, group):
                                    if set is False:
                                        use_default = False
                                    else:
                                        typ = "nothing"
                                        use_default = False
                                    break
                        if use_default:
                            # 使用默认设置
                            if detail["default"] is True:
                                typ = "nothing"

            cur = VALID_TASK.T[typ]
            kwargs = {}
            if typ != "nothing":  # 未禁用
                for param in task:
                    if param == "type":
                        continue
                    if param == "__disable__":
                        continue
                    kwargs[param] = task[param]
            for v_p in cur["params"]:  # Valid Param: Default Param
                if v_p.default is not None and v_p.key not in kwargs:
                    kwargs[v_p.key] = v_p.default

            idx = self.ms.nextwv(
                funwarper(cur["funname"], cur['title'], kwargs))  # 自动创建序列
            if typ != "nothing":
                self.log.write_log("info", f"  +任务 {cur['title']}")  # 打印该任务
                for key in kwargs:
                    self.log.write_log("info", f"    参数 {key} : {kwargs[key]}")
                self._task_index[idx] = cur['title']
        self.ms.exitw(None)  # 结束自动序列创建
        # 未知异常:仍然是重启哒!万能的重启万岁!
        last_exception = None
        before_ = True
        retry = 0
        while retry <= max_retry:
            try:
                if before_:
                    self.task_current("登录")
                    _return_code = self.login_auth(account, password)
                    if _return_code == -1:
                        # 标记错误!
                        self.task_error(str('%s账号出现了验证码' % self.account))
                        if captcha_skip:
                            self.fix_reboot(False)
                            return False
                    if continue_ is False:
                        # 初次执行,记录一下
                        self.task_start()
                    if first_init_home:
                        self.init_home()  # 处理第一次进home的一系列问题
                    before_ = False
                try:
                    self.ms.run(continue_=continue_)
                except UnknownMovesetException as e:
                    pcr_log(account).write_log(
                        "warning", message=f'记录文件冲突,自动刷新运行记录:{str(e)}')
                    self.ms.run(continue_=False)
                # 刷完啦!标记一下”我刷完了“
                self.task_finished()
                return True
            except ForceKillException as e:
                pcr_log(account).write_log(level='info', message=f'强制终止')
                try:
                    self.fix_reboot(False)
                except:
                    pcr_log(account).write_log(level='warning',
                                               message=f'强制终止-重启失败!')
                raise e
            except FastScreencutException as e:
                pcr_log(account).write_log(
                    level='error', message=f'快速截图出现错误,{str(e)},尝试重新连接……')
                self.fix_reboot(not before_)
                self.init_fastscreen()
            except OfflineException as e:
                pcr_log(account).write_log('error',
                                           message=f'main-检测到设备离线:{str(e)}')
                return False
            except ReadTimeoutException as e:
                pcr_log(account).write_log(
                    'error', message=f'main-检测到连接超时,{str(e)},尝试重新连接……')
                self.init_device(self.address)
            except BadLoginException as e:
                pcr_log(account).write_log('error',
                                           message=f'main-严重登录错误,{e}跳过账号!')
                self.task_error(str(e))
                self.fix_reboot(False)
                return False
            except Exception as e:
                retry += 1
                try:
                    os.makedirs(f"error_screenshot/{account}", exist_ok=True)
                    nowtime = datetime.datetime.strftime(
                        datetime.datetime.now(), "%Y%m%d_%H%M%S")
                    target = f"error_screenshot/{account}/{nowtime}_RT{retry}.jpg"
                    cv2.imwrite(target, self.last_screen)
                    pcr_log(account).write_log(level="error",
                                               message=f"错误截图已经保存至{target}")
                    # 错误截图日志为0级消息,后面可能会改成warning级别或者error
                    Bot().server_bot(
                        '', '', '', self.last_screen, f"模拟器:{self.address}\n"
                        f"账号:{self.account}的运行错误重启截图\n"
                        f"错误原因:{str(e)}")
                except Exception as es:
                    pcr_log(account).write_log(level="error",
                                               message=f"错误截图保存失败:{str(es)}")
                if trace_exception_for_debug:
                    tb = traceback.format_exc()
                    pcr_log(account).write_log(level="error", message=tb)
                last_exception = e
                continue_ = True
                if retry == max_retry:
                    pcr_log(account).write_log(
                        level="error",
                        message=f"main-检测出异常{str(e)} 超出最大重试次数,跳过账号!")
                    # 标记错误!
                    self.task_error(str(last_exception))
                    self.fix_reboot(False)
                    return False
                pcr_log(account).write_log(
                    level='error',
                    message=f'main-检测出异常{str(e)},重启中 次数{retry}/{max_retry}')

                try:
                    self.fix_reboot(not before_)
                except Exception as e:
                    pcr_log(account).write_log(
                        level='error', message=f'main-自动重启失败,跳过账号!{str(e)}')
                    self.task_error(str(last_exception))
                    try:
                        self.fix_reboot(False)
                    except:
                        pass
                    return False