示例#1
0
    def app_start_adb(self, package_name, allow_failure=False):
        """
        Args:
            package_name (str):
            allow_failure (bool):

        Returns:
            bool: If success to start
        """
        result = self.adb_shell([
            'monkey', '-p', package_name, '-c',
            'android.intent.category.LAUNCHER', '1'
        ])
        if 'No activities found' in result:
            # ** No activities found to run, monkey aborted.
            if allow_failure:
                return False
            else:
                logger.error(result)
                possible_reasons(
                    f'"{package_name}" not found, please check setting Emulator.PackageName'
                )
                raise RequestHumanTakeover
        else:
            # Events injected: 1
            # ## Network stats: elapsed time=4ms (0ms mobile, 0ms wifi, 4ms not connected)
            return True
示例#2
0
    def app_start_wsa(self, package_name=None, display=0):
        """
        Args:
            package_name (str):
            display (int):

        Returns:
            bool: If success to start
        """
        if not package_name:
            package_name = self.package
        self.adb_shell(['svc', 'power', 'stayon', 'true'])
        activity_name = self.get_main_activity_name(package_name=package_name)
        result = self.adb_shell([
            'am', 'start', '--display', display,
            f'{package_name}/{activity_name}'
        ])
        if 'Activity not started' in result or 'does not exist' in result:
            # Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] pkg=xxx }
            # Error: Activity not started, unable to resolve Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 pkg=xxx }

            # Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.bilibili.azurlane/xxx }
            # Error type 3
            # Error: Activity class {com.bilibili.azurlane/com.manjuu.azurlane.MainAct} does not exist.
            logger.error(result)
            raise PackageNotInstalled(package_name)
        else:
            # Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.bilibili.azurlane/com.manjuu.azurlane.MainActivity }
            return True
示例#3
0
    def app_start_adb(self, package_name=None, allow_failure=False):
        """
        Args:
            package_name (str):
            allow_failure (bool):

        Returns:
            bool: If success to start
        """
        if not package_name:
            package_name = self.package
        result = self.adb_shell([
            'monkey', '-p', package_name, '-c',
            'android.intent.category.LAUNCHER', '1'
        ])
        if 'No activities found' in result:
            # ** No activities found to run, monkey aborted.
            if allow_failure:
                return False
            else:
                logger.error(result)
                raise PackageNotInstalled(package_name)
        else:
            # Events injected: 1
            # ## Network stats: elapsed time=4ms (0ms mobile, 0ms wifi, 4ms not connected)
            return True
示例#4
0
    def hermit_send(self, url, **kwargs):
        """
        Args:
            url (str):
            **kwargs:

        Returns:
            dict: Usually to be {"code":0,"msg":"ok"}
        """
        result = self.hermit_session.get(f'{self._hermit_url}{url}', params=kwargs, timeout=3).text
        try:
            result = json.loads(result, encoding='utf-8')
            if result['code'] != 0:
                # {"code":-1,"msg":"error"}
                raise HermitError(result)
        except (json.decoder.JSONDecodeError, KeyError):
            e = HermitError(result)
            if 'GestureDescription$Builder' in result:
                logger.error(e)
                logger.critical('Hermit cannot run on current device, hermit requires Android>=7.0')
                raise RequestHumanTakeover
            if 'accessibilityservice' in result:
                # Attempt to invoke virtual method
                # 'boolean android.accessibilityservice.AccessibilityService.dispatchGesture(
                #     android.accessibilityservice.GestureDescription,
                #     android.accessibilityservice.AccessibilityService$GestureResultCallback,
                #     android.os.Handler
                # )' on a null object reference
                logger.error('Unable to access accessibility service')
            raise e

        # Hermit only takes 2-4ms
        # Add a 50ms delay because game can't response quickly.
        self.sleep(0.05)
        return result
    def adb_connect(self, serial):
        """
        Connect to a serial, try 3 times at max.
        If there's an old ADB server running while Alas is using a newer one, which happens on Chinese emulators,
        the first connection is used to kill the other one, and the second is the real connect.

        Args:
            serial (str):

        Returns:
            bool: If success
        """
        if 'emulator' in serial:
            return True
        else:
            for _ in range(3):
                msg = self.adb_client.connect(serial)
                logger.info(msg)
                if 'connected' in msg:
                    # Connected to 127.0.0.1:59865
                    # Already connected to 127.0.0.1:59865
                    return True
                elif 'bad port' in msg:
                    # bad port number '598265' in '127.0.0.1:598265'
                    logger.error(msg)
                    possible_reasons('Serial incorrect, might be a typo')
                    raise RequestHumanTakeover
            logger.warning(f'Failed to connect {serial} after 3 trial, assume connected')
            return False
示例#6
0
    def app_start_wsa(self, package_name, display, allow_failure=False):
        """
        Args:
            package_name (str):
            display (int):
            allow_failure (bool):

        Returns:
            bool: If success to start
        """

        self.adb_shell(['svc', 'power', 'stayon', 'true'])
        activity_name = self.get_main_activity_name(package_name=package_name)
        result = self.adb_shell([
            'am', 'start', '--display', display,
            package_name + '/' + activity_name
        ])
        if 'No activities found' in result:
            # ** No activities found to run, monkey aborted.
            if allow_failure:
                return False
            else:
                logger.error(result)
                possible_reasons(
                    f'"{package_name}" not found, please check setting Emulator.PackageName'
                )
                raise RequestHumanTakeover
        else:
            # Events injected: 1
            # ## Network stats: elapsed time=4ms (0ms mobile, 0ms wifi, 4ms not connected)
            return True
示例#7
0
 def _adb_connect(self, serial):
     if serial.startswith('127.0.0.1'):
         msg = self.adb_command(['connect', serial]).decode("utf-8")
         if msg.startswith('unable'):
             logger.error('Unable to connect %s' % serial)
             exit(1)
         else:
             logger.info(msg.strip())
示例#8
0
 def stop(self):
     if self.is_alive():
         thread_id = self._get_id()
         res = ctypes.pythonapi.PyThreadState_SetAsyncExc(
             thread_id, ctypes.py_object(SystemExit))
         if res > 1:
             ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, 0)
             logger.error('Exception raise failure')
 def app_start_uiautomator2(self, package_name):
     try:
         self.u2.app_start(package_name)
     except u2.exceptions.BaseError as e:
         # BaseError: package "com.bilibili.azurlane" not found
         logger.error(e)
         possible_reasons(f'"{package_name}" not found, please check setting Emulator.PackageName')
         raise RequestHumanTakeover
示例#10
0
 def app_start_uiautomator2(self, package_name=None):
     if not package_name:
         package_name = self.package
     try:
         self.u2.app_start(package_name)
     except u2.exceptions.BaseError as e:
         # BaseError: package "com.bilibili.azurlane" not found
         logger.error(e)
         raise PackageNotInstalled(package_name)
示例#11
0
 def update(self):
     logger.hr("Run update")
     backup, builtins.print = builtins.print, logger.info
     try:
         self.git_install()
         self.pip_install()
     except ExecutionError:
         logger.error("Update failed")
         builtins.print = backup
         return False
     builtins.print = backup
     return True
示例#12
0
    def gacha_goto_pool(self, target_pool):
        """
        Transition to appropriate build pool page.

        Args:
            target_pool (str): Name of pool, default to
            'light' path if outside of acceptable range

        Returns:
            str: Current pool location based on availability

        Pages:
            in: page_build (gacha pool selection)
            out: page_build (gacha pool allowed)

        Except:
            May exit if 'wishing_well' but not
            complete configuration
        """
        # Switch view to 'light' pool
        self.gacha_bottom_navbar_ensure(right=3, is_build=True)

        # Transition to 'target_pool' if needed, update
        # 'target_pool' appropriately
        if target_pool == 'wishing_well':
            if self._gacha_side_navbar.get_total(main=self) != 5:
                logger.warning('\'wishing_well\' is not available, '
                               'default to \'light\' pool')
                target_pool = 'light'
            else:
                self.gacha_side_navbar_ensure(upper=2)
                if self.appear(BUILD_WW_CHECK):
                    logger.error('\'wishing_well\' must be configured '
                                 'manually by user, cannot continue '
                                 'gacha_goto_pool')
                    exit(1)
        elif target_pool == 'event':
            gacha_bottom_navbar = self._gacha_bottom_navbar(is_build=True)
            if gacha_bottom_navbar.get_total(main=self) == 3:
                logger.warning('\'event\' is not available, default '
                               'to \'light\' pool')
                target_pool = 'light'
            else:
                self.gacha_bottom_navbar_ensure(left=1, is_build=True)
        elif target_pool in ['heavy', 'special']:
            if target_pool == 'heavy':
                self.gacha_bottom_navbar_ensure(right=2, is_build=True)
            else:
                self.gacha_bottom_navbar_ensure(right=1, is_build=True)

        return target_pool
示例#13
0
def handle_adb_error(e):
    """
    Args:
        e (Exception):

    Returns:
        bool: If should retry
    """
    text = str(e)
    if 'not found' in text:
        # When you call `adb disconnect <serial>`
        # Or when adb server was killed (low possibility)
        # AdbError(device '127.0.0.1:59865' not found)
        logger.error(e)
        return True
    elif 'timeout' in text:
        # AdbTimeout(adb read timeout)
        logger.error(e)
        return True
    elif 'closed' in text:
        # AdbError(closed)
        # Usually after AdbTimeout(adb read timeout)
        # Disconnect and re-connect should fix this.
        logger.error(e)
        return True
    elif 'device offline' in text:
        # AdbError(device offline)
        # When a device that has been connected wirelessly is disconnected passively,
        # it does not disappear from the adb device list,
        # but will be displayed as offline.
        # In many cases, such as disconnection and recovery caused by network fluctuations,
        # or after VMOS reboot when running Alas on a phone,
        # the device is still available, but it needs to be disconnected and re-connected.
        logger.error(e)
        return True
    elif 'unknown host service' in text:
        # AdbError(unknown host service)
        # Another version of ADB service started, current ADB service has been killed.
        # Usually because user opened a Chinese emulator, which uses ADB from the Stone Age.
        logger.error(e)
        return True
    else:
        # AdbError()
        logger.exception(e)
        possible_reasons(
            'If you are using BlueStacks or LD player or WSA, please enable ADB in the settings of your emulator',
            'Emulator died, please restart emulator',
            'Serial incorrect, no such device exists or emulator is not running'
        )
        return False
示例#14
0
    def retry_wrapper(self, *args, **kwargs):
        """
        Args:
            self (AScreenCap):
        """
        init = None
        for _ in range(RETRY_TRIES):
            try:
                if callable(init):
                    self.sleep(RETRY_DELAY)
                    init()
                return func(self, *args, **kwargs)
            # Can't handle
            except RequestHumanTakeover:
                break
            # When adb server was killed
            except ConnectionResetError as e:
                logger.error(e)

                def init():
                    self.adb_disconnect(self.serial)
                    self.adb_connect(self.serial)
            # When ascreencap is not installed
            except AscreencapError as e:
                logger.error(e)

                def init():
                    self.ascreencap_init()
            # AdbError
            except AdbError as e:
                if handle_adb_error(e):

                    def init():
                        self.adb_disconnect(self.serial)
                        self.adb_connect(self.serial)
                else:
                    break

            # Unknown, probably a trucked image
            except Exception as e:
                logger.exception(e)

                def init():
                    pass

        logger.critical(f'Retry {func.__name__}() failed')
        raise RequestHumanTakeover
示例#15
0
 def report(self):
     report_file = os.path.abspath(
         os.path.join(os.path.dirname(__file__), "../report/%s") %
         report_file_name)
     if not os.path.exists(report_file_name):
         try:
             os.makedirs(os.path.dirname(report_file))
         except Exception as reason:
             logger.error(reason)
     try:
         with open(report_file, 'w', encoding='utf-8') as report:
             all_result = self.header + self.juicy_result + self.footer
             report.write(all_result)
         logger.info("报告生成完毕")
     except Exception as reason:
         logger.info("报告生成失败")
         logger.error(reason)
示例#16
0
文件: google_hack.py 项目: su18/Elena
 def read_json(self):
     # 加载字典文件,在前面加上site组成完成查询语句
     logger.info("正在读取 GHDB Json 文件")
     try:
         with open(file_name, "r", encoding=file_encode) as json_file:
             content = json.load(json_file)
             # 先不进行子域名查询和C段查询
             # del content['basic_information']
             # 生成查询队列列表
             for primary_category, sub_category in content.items():
                 for j in sub_category:
                     for i in range(len(j['query'])):
                         search_query = self.basic_site + (j['query'][i])
                         self.search_list.append(search_query)
     except Exception as reason:
         logger.error(reason)
         sys.exit()
     logger.info("文件读取已完成")
示例#17
0
def handle_adb_error(e):
    """
    Args:
        e (Exception):

    Returns:
        bool: If should retry
    """
    text = str(e)
    if 'not found' in text:
        # When you call `adb disconnect <serial>`
        # Or when adb server was killed (low possibility)
        # AdbError(device '127.0.0.1:59865' not found)
        logger.error(e)
        return True
    elif 'timeout' in text:
        # AdbTimeout(adb read timeout)
        logger.error(e)
        return True
    elif 'closed' in text:
        # AdbError(closed)
        # Usually after AdbTimeout(adb read timeout)
        # Disconnect and re-connect should fix this.
        logger.error(e)
        return True
    else:
        # AdbError(device offline)
        # AdbError()
        logger.exception(e)
        possible_reasons(
            'If you are using BlueStacks or LD player or WSA, please enable ADB in the settings of your emulator',
            'Emulator died, please restart emulator',
            'Serial incorrect, no such device exists or emulator is not running'
        )
        return False
示例#18
0
    def retry_wrapper(self, *args, **kwargs):
        """
        Args:
            self (Hermit):
        """
        init = None
        for _ in range(RETRY_TRIES):
            try:
                if callable(init):
                    self.sleep(RETRY_DELAY)
                    init()
                return func(self, *args, **kwargs)
            # Can't handle
            except RequestHumanTakeover:
                break
            # When adb server was killed
            except ConnectionResetError as e:
                logger.error(e)

                def init():
                    self.adb_reconnect()
            # When unable to send requests
            except requests.exceptions.ConnectionError as e:
                logger.error(e)
                text = str(e)
                if 'Connection aborted' in text:
                    # Hermit not installed or not running
                    # ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
                    def init():
                        self.adb_reconnect()
                        self.hermit_init()
                else:
                    # Lost connection, adb server was killed
                    # HTTPConnectionPool(host='127.0.0.1', port=20269):
                    # Max retries exceeded with url: /click?x=500&y=500
                    def init():
                        self.adb_reconnect()
            # AdbError
            except AdbError as e:
                if handle_adb_error(e):
                    def init():
                        self.adb_reconnect()
                else:
                    break
            # HermitError: {"code":-1,"msg":"error"}
            except HermitError as e:
                logger.error(e)

                def init():
                    self.adb_reconnect()
                    self.hermit_init()
            # Unknown, probably a trucked image
            except Exception as e:
                logger.exception(e)

                def init():
                    pass

        logger.critical(f'Retry {func.__name__}() failed')
        raise RequestHumanTakeover
示例#19
0
def start_ocr_server(port=22268):
    from module.ocr.al_ocr import AlOcr
    from module.ocr.models import OcrModel

    class OCRServer(OcrModel):
        def hello(self):
            return "hello"

        def ocr(self, lang, img_fp):
            img_fp = pickle.loads(img_fp)
            cnocr: AlOcr = self.__getattribute__(lang)
            return cnocr.ocr(img_fp)

        def ocr_for_single_line(self, lang, img_fp):
            img_fp = pickle.loads(img_fp)
            cnocr: AlOcr = self.__getattribute__(lang)
            return cnocr.ocr_for_single_line(img_fp)

        def ocr_for_single_lines(self, lang, img_list):
            img_list = [pickle.loads(img_fp) for img_fp in img_list]
            cnocr: AlOcr = self.__getattribute__(lang)
            return cnocr.ocr_for_single_lines(img_list)

        def set_cand_alphabet(self, lang, cand_alphabet):
            cnocr: AlOcr = self.__getattribute__(lang)
            return cnocr.set_cand_alphabet(cand_alphabet)

        def debug(self, lang, img_list):
            img_list = [pickle.loads(img_fp) for img_fp in img_list]
            cnocr: AlOcr = self.__getattribute__(lang)
            return cnocr.debug(img_list)

    server = zerorpc.Server(OCRServer())
    try:
        server.bind(f"tcp://*:{port}")
    except zmq.error.ZMQError:
        logger.error(f"Ocr server cannot bind on port {port}")
        return
    logger.info(f"Ocr server listen on port {port}")
    server.run()
示例#20
0
def bind(self) -> socket.socket:
    logger = uvicorn.config.logger
    logger_args: List[Union[str, int]]
    if self.uds:  # pragma: py-win32
        path = self.uds
        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        try:
            sock.bind(path)
            uds_perms = 0o666
            os.chmod(self.uds, uds_perms)
        except OSError as exc:
            logger.error(exc)
            sys.exit(1)

        message = "Uvicorn running on unix socket %s (Press CTRL+C to quit)"
        sock_name_format = "%s"
        color_message = ("Uvicorn running on " +
                         click.style(sock_name_format, bold=True) +
                         " (Press CTRL+C to quit)")
        logger_args = [self.uds]
    elif self.fd:  # pragma: py-win32
        sock = socket.fromfd(self.fd, socket.AF_UNIX, socket.SOCK_STREAM)
        message = "Uvicorn running on socket %s (Press CTRL+C to quit)"
        fd_name_format = "%s"
        color_message = ("Uvicorn running on " +
                         click.style(fd_name_format, bold=True) +
                         " (Press CTRL+C to quit)")
        logger_args = [sock.getsockname()]
    else:
        family = socket.AF_INET
        addr_format = "%s://%s:%d"

        if self.host and ":" in self.host:  # pragma: py-win32
            # It's an IPv6 address.
            family = socket.AF_INET6
            addr_format = "%s://[%s]:%d"
        sock = socket.socket(family=family)
        if reuseaddr:
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        try:
            sock.bind((self.host, self.port))
        except OSError as exc:
            logger.error(exc)
            logger.error(f"Already bind on address ({self.host}, {self.port})")
            sys.exit(1)

        message = f"Uvicorn running on {addr_format} (Press CTRL+C to quit)"
        color_message = ("Uvicorn running on " +
                         click.style(addr_format, bold=True) +
                         " (Press CTRL+C to quit)")
        protocol_name = "https" if self.is_ssl else "http"
        logger_args = [protocol_name, self.host, self.port]
    logger.info(message, *logger_args, extra={"color_message": color_message})
    sock.set_inheritable(True)
    return sock
示例#21
0
    def search(self,
               query,
               num_results=search_num_results,
               prefetch_pages=True,
               prefetch_threads=10,
               language=search_language,
               proxy_list=None):
        # 初始化搜索结果为空
        search_results = []
        # 计算返回结果的页数
        pages = int(math.ceil(num_results / self.RESULTS_PER_PAGE))
        # 双初始化端队列
        fetcher_threads = deque([])
        total = None

        for i in range(pages):
            start = i * self.RESULTS_PER_PAGE

            # 设置通过代理发包
            if proxy_list:
                proxy = random.choice(proxy_list)
                proxy_handler = urllib.request.ProxyHandler(proxy)
            else:
                proxy_handler = urllib.request.ProxyHandler({})
            try:
                opener = urllib.request.build_opener(proxy_handler)
                # 覆盖 addheaders 值
                opener.addheaders = self.DEFAULT_HEADERS

                # 使用 urllib.request 按页数获取 Google 查询返回的结果
                response = opener.open(self.SEARCH_URL + "?q=" +
                                       urllib.request.quote(query) + "&hl=" +
                                       language +
                                       ("" if start == 0 else ("&start=" +
                                                               str(start))))

                # 使用BeautifulSoup lxml 解析器处理返回结果
                soup = BeautifulSoup(response.read(), 'lxml')
                response.close()
            except Exception as reason:
                logger.error(reason)
                sys.exit()

            if total is None:
                # 处理总共返回结果的数量
                if soup.select(self.TOTAL_SELECTOR):

                    # 查询返回结果数目
                    total_text = soup.select(
                        self.TOTAL_SELECTOR)[0].children.__next__().encode(
                            'utf-8')

                    # 使用正则匹配总共返回多少条结果
                    total = int(
                        re.sub(
                            "[', ]", "",
                            re.search("(([0-9]+[', ])*[0-9]+)",
                                      total_text.decode('utf-8')).group(1)))
                else:
                    logger.info("查询结果为空")
                    total = 0

            # 从结果中选择 href 便签下的结果链接
            results = self.parse_results(soup.select(self.RESULT_SELECTOR))

            # 去除脏数据
            if len(results) > total:
                del results[total - len(results):]

            # 截取查询结果长度
            if len(search_results) + len(results) > num_results:
                del results[num_results - len(search_results):]

            # 将结果加入搜索结果列表中
            search_results += results

            # 采用多线程处理返回结果
            if prefetch_pages:
                for result in results:
                    while True:
                        running = 0
                        for thread in fetcher_threads:
                            if thread.is_alive():
                                running += 1
                        if running < prefetch_threads:
                            break
                        sleep(1)
                    fetcher_thread = Thread(target=result.get_text_)
                    fetcher_thread.start()
                    fetcher_threads.append(fetcher_thread)

        for thread in fetcher_threads:
            thread.join()
        return SearchResponse(search_results, total)
示例#22
0
    def retry_wrapper(self, *args, **kwargs):
        """
        Args:
            self (Minitouch):
        """
        init = None
        sleep = True
        for _ in range(RETRY_TRIES):
            try:
                if callable(init):
                    if sleep:
                        self.sleep(RETRY_DELAY)
                        sleep = True
                    init()
                return func(self, *args, **kwargs)
            # Can't handle
            except RequestHumanTakeover:
                break
            # When adb server was killed
            except ConnectionResetError as e:
                logger.error(e)

                def init():
                    self.adb_disconnect(self.serial)
                    self.adb_connect(self.serial)
            # Emulator closed
            except ConnectionAbortedError as e:
                logger.error(e)

                def init():
                    self.adb_disconnect(self.serial)
                    self.adb_connect(self.serial)
            # MinitouchNotInstalledError: Received empty data from minitouch
            except MinitouchNotInstalledError as e:
                logger.error(e)
                sleep = False

                def init():
                    self.install_uiautomator2()
                    if self._minitouch_port:
                        self.adb_forward_remove(f'tcp:{self._minitouch_port}')
                    del_cached_property(self, 'minitouch_builder')
            # MinitouchOccupiedError: Timeout when connecting to minitouch
            except MinitouchOccupiedError as e:
                logger.error(e)
                sleep = False

                def init():
                    self.restart_atx()
                    if self._minitouch_port:
                        self.adb_forward_remove(f'tcp:{self._minitouch_port}')
                    del_cached_property(self, 'minitouch_builder')
            # AdbError
            except AdbError as e:
                if handle_adb_error(e):

                    def init():
                        self.adb_disconnect(self.serial)
                        self.adb_connect(self.serial)
                else:
                    break
            except BrokenPipeError as e:
                logger.error(e)

                def init():
                    del_cached_property(self, 'minitouch_builder')

            # Unknown, probably a trucked image
            except Exception as e:
                logger.exception(e)

                def init():
                    pass

        logger.critical(f'Retry {func.__name__}() failed')
        raise RequestHumanTakeover
示例#23
0
    def retry_wrapper(self, *args, **kwargs):
        """
        Args:
            self (Uiautomator2):
        """
        init = None
        sleep = True
        for _ in range(RETRY_TRIES):
            try:
                if callable(init):
                    if sleep:
                        self.sleep(RETRY_DELAY)
                        sleep = True
                    init()
                return func(self, *args, **kwargs)
            # Can't handle
            except RequestHumanTakeover:
                break
            # When adb server was killed
            except ConnectionResetError as e:
                logger.error(e)

                def init():
                    self.adb_disconnect(self.serial)
                    self.adb_connect(self.serial)
            # In `device.set_new_command_timeout(604800)`
            # json.decoder.JSONDecodeError: Expecting value: line 1 column 2 (char 1)
            except JSONDecodeError as e:
                logger.error(e)
                sleep = False

                def init():
                    self.install_uiautomator2()
            # AdbError
            except AdbError as e:
                if handle_adb_error(e):

                    def init():
                        self.adb_disconnect(self.serial)
                        self.adb_connect(self.serial)
                else:
                    break
            # RuntimeError: USB device 127.0.0.1:5555 is offline
            except RuntimeError as e:
                if handle_adb_error(e):

                    def init():
                        self.adb_disconnect(self.serial)
                        self.adb_connect(self.serial)
                else:
                    break
            # In `assert c.read string(4) == _OKAY`
            # ADB on emulator not enabled
            except AssertionError as e:
                logger.exception(e)
                possible_reasons(
                    'If you are using BlueStacks or LD player, '
                    'please enable ADB in the settings of your emulator')
                break

            # Unknown, probably a trucked image
            except Exception as e:
                logger.exception(e)

                def init():
                    pass

        logger.critical(f'Retry {func.__name__}() failed')
        raise RequestHumanTakeover
示例#24
0
    def gacha_prep(self, target, skip_first_screenshot=True):
        """
        Initiate preparation to submit build orders.

        Args:
            target (int): Number of build orders to submit
            skip_first_screenshot (bool):

        Returns:
            bool: True if prep complete otherwise False.

        Pages:
            in: page_build (any)
            out: submit pop up

        Except:
            May exit if unable to process prep
        """
        # Nothing to prep if 'target' = 0
        if not target:
            return False

        # Ensure correct page to be able to prep in
        if not self.appear(BUILD_SUBMIT_ORDERS) \
                and not self.appear(BUILD_SUBMIT_WW_ORDERS):
            return False

        # Use 'appear' to update actual position of assets
        # for ui_ensure_index
        confirm_timer = Timer(1, count=2).start()
        ocr_submit = None
        index_offset = (60, 20)
        while 1:
            if skip_first_screenshot:
                skip_first_screenshot = False
            else:
                self.device.screenshot()

            if self.appear_then_click(BUILD_SUBMIT_ORDERS, interval=3):
                ocr_submit = OCR_BUILD_SUBMIT_COUNT
                confirm_timer.reset()
                continue

            if self.appear_then_click(BUILD_SUBMIT_WW_ORDERS, interval=3):
                ocr_submit = OCR_BUILD_SUBMIT_WW_COUNT
                confirm_timer.reset()
                continue

            # End
            if self.appear(BUILD_PLUS, offset=index_offset) \
                    and self.appear(BUILD_MINUS, offset=index_offset):
                if confirm_timer.reached():
                    break

        # Check for exception, exited prematurely
        # Apply appropriate submission count
        if ocr_submit is None:
            logger.error('Failed to identify ocr asset required, '
                         'cannot continue prep work')
            exit(1)
        area = ocr_submit.buttons[0]
        ocr_submit.buttons = [(BUILD_MINUS.button[2] + 3, area[1], BUILD_PLUS.button[0] - 3, area[3])]
        self.ui_ensure_index(target, letter=ocr_submit, prev_button=BUILD_MINUS,
                             next_button=BUILD_PLUS, skip_first_screenshot=True)

        return True
def remote_access_service(
    local_host="127.0.0.1",
    local_port=22267,
    server="app.pywebio.online",
    server_port=1022,
    remote_port="/",
    setup_timeout=60,
):
    """
    Wait at most one minute to get the ssh output, if it gets a normal out, the connection is successfully established.
    Otherwise report error and kill ssh process.

    :param local_port: ssh local listen port
    :param server: ssh server domain
    :param server_port: ssh server port
    :param setup_timeout: If the service can't setup successfully in `setup_timeout` seconds, then exit.
    """
    global _ssh_process, _ssh_notfound

    bin = State.deploy_config.SSHExecutable
    cmd = f"{bin} -oStrictHostKeyChecking=no -R {remote_port}:{local_host}:{local_port} -p {server_port} {server} -- --output json"
    args = shlex.split(cmd)
    logger.debug(f"remote access service command: {cmd}")

    if _ssh_process is not None and _ssh_process.poll() is None:
        logger.warning(f"Kill previous ssh process [{_ssh_process.pid}]")
        _ssh_process.kill()
    try:
        _ssh_process = Popen(args, stdout=PIPE, stderr=PIPE)
    except FileNotFoundError as e:
        logger.critical(
            f"Cannot find SSH executable {bin}, please install OpenSSH or specify SSHExecutable in deploy.yaml"
        )
        _ssh_notfound = True
        return
    logger.info(f"remote access process pid: {_ssh_process.pid}")
    success = False

    def timeout_killer(wait_sec):
        time.sleep(wait_sec)
        if not success and _ssh_process.poll() is None:
            logger.info("Connection timeout, kill ssh process")
            _ssh_process.kill()

    threading.Thread(target=timeout_killer,
                     kwargs=dict(wait_sec=setup_timeout),
                     daemon=True).start()

    stdout = _ssh_process.stdout.readline().decode("utf8")
    logger.info(f"ssh server stdout: {stdout}")
    connection_info = {}
    try:
        connection_info = json.loads(stdout)
        success = True
    except json.decoder.JSONDecodeError:
        if not success and _ssh_process.poll() is None:
            _ssh_process.kill()

    if success:
        if connection_info.get("status", "fail") != "success":
            logger.info(
                f"Failed to establish remote access, this is the error message from service provider: {connection_info.get('message', '')}"
            )
            new_username = connection_info.get("change_username", None)
            if new_username:
                logger.info(
                    f"Server requested to change username, change it to: {new_username}"
                )
                State.deploy_config.SSHUser = new_username
        else:
            global address
            address = connection_info["address"]
            logger.debug(f"Remote access url: {address}")

    # wait ssh or main thread exit
    while not am_i_the_only_thread() and _ssh_process.poll() is None:
        # while _ssh_process.poll() is None:
        time.sleep(1)

    if _ssh_process.poll() is None:  # main thread exit, kill ssh process
        logger.info("App process exit, killing ssh process")
        _ssh_process.kill()
    else:  # ssh process exit by itself or by timeout killer
        stderr = _ssh_process.stderr.read().decode("utf8")
        if stderr:
            logger.error(
                f"PyWebIO application remote access service error: {stderr}")
        else:
            logger.info("PyWebIO application remote access service exit.")
    address = None