From 6b6ea8d2061434759d05452501bd95793ca0658e Mon Sep 17 00:00:00 2001 From: txperl Date: Thu, 31 Oct 2024 16:13:48 +0800 Subject: [PATCH] feat: optimize login steps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 优化 登录逻辑 - 优化 Token 刷新逻辑 - 移除 LoginHelper SSL 模式覆盖 --- app/config/language/en.yml | 7 +- app/config/language/es.yml | 7 +- app/config/language/zh.yml | 7 +- app/lib/common/login_helper/main.py | 76 +++++++++--------- app/lib/core/biu.py | 116 +++++++++++++++------------- main.py | 14 ---- 6 files changed, 109 insertions(+), 118 deletions(-) diff --git a/app/config/language/en.yml b/app/config/language/en.yml index f5d4246..c4ebac0 100644 --- a/app/config/language/en.yml +++ b/app/config/language/en.yml @@ -4,7 +4,7 @@ app.core.biu: success_to_login: "Login successful" config: hint_port_is_in_use: "Current port is in use, please modify the 'sys.host' item in config.yml" - hint_proxy_in_use: "Proxy enabled" + hint_proxy_in_use: "Proxy %s enabled" fail_to_load_config: "Failed to load configuration file, program cannot run normally" outdated: hint_latest: "Latest" @@ -16,7 +16,7 @@ app.core.biu: network: hint_in_check: "Checking network status..." fail_pixiv_and_use_bypass: "Cannot access Pixiv, enabling bypassSNI route (may not work properly)" - loginHelper: + login: hint_token_only: "Due to Pixiv blocking username/password login, only token login is available now" hint_before_start: "Network detection will begin shortly, this process can reduce the probability of being unable to use PixivBiu normally due to network issues" fail_to_get_token_due_to_network: "Your network cannot properly perform Pixiv token login, please adjust and try again" @@ -37,9 +37,8 @@ app.core.biu: app.common.loginHelper: network: - hint_in_check: "Checking network status..." press_need_to_type_proxy: "Please enter proxy address (can be empty): " - hint_detect_proxy_and_continue: "Detected proxy address as %s, continue? (y / n): " + hint_detect_proxy: "Detected proxy address as %s, need to change? (y / n): " is_need_to_type_proxy: "No proxy address detected, need to set manually? (y / n): " login: hint_intro_step_head: "[Login] Please follow these steps:" diff --git a/app/config/language/es.yml b/app/config/language/es.yml index b039249..ae6dbc9 100644 --- a/app/config/language/es.yml +++ b/app/config/language/es.yml @@ -4,7 +4,7 @@ app.core.biu: success_to_login: "inicio de sesión exitoso config: hint_port_is_in_use: "El puerto esta ocupado, please change the sys-host setting item in config.yml" - hint_proxy_in_use: "Proxy esta habilitado" + hint_proxy_in_use: "Proxy %s habilitado" fail_to_load_config: "Fallo para cargar el archivo de configuracion, PixivBiu no puede correr correctamente" outdated: hint_latest: "Reciente" @@ -16,7 +16,7 @@ app.core.biu: network: hint_in_check: "Comprobando estado de la red..." fail_pixiv_and_use_bypass: "No se puede conectar a Pixiv, habilitar la ruta bypassSNI (puede no estar disponible temporalmente)" - loginHelper: + login: hint_token_only: "Dado que Pixiv deshabilita el inicio de sesión con contraseña, por ahora solo puedes usar token para iniciar sesión" hint_before_start: "La detección de red está a punto de comenzar, este proceso puede reducir la probabilidad de no poder usar PixivBiu debido a problemas de red" fail_to_get_token_due_to_network: "Su red no está funcionando correctamente para iniciar sesión con el token Pixiv; ajústela y vuelva a intentarlo." @@ -37,9 +37,8 @@ app.core.biu: app.common.loginHelper: network: - hint_in_check: "Comprobando estado de la red..." press_need_to_type_proxy: "Por favor, introduzca la dirección del proxy (puede estar en blanco): " - hint_detect_proxy_and_continue: "Dirección de proxy (%s) detectada, ¿desea cambiarla? (y / n): " + hint_detect_proxy: "Dirección de proxy detectada como %s, ¿es necesario cambiarla? (y / n): " is_need_to_type_proxy: "No se detectó la dirección proxy del sistema, ¿necesita configurarla manualmente? (y / n): " login: hint_intro_step_head: "[Iniciar sesión] Siga los pasos a continuación:" diff --git a/app/config/language/zh.yml b/app/config/language/zh.yml index 958445c..7c54c9a 100644 --- a/app/config/language/zh.yml +++ b/app/config/language/zh.yml @@ -4,7 +4,7 @@ app.core.biu: success_to_login: "登录成功" config: hint_port_is_in_use: "现端口已被占用,请修改 config.yml 中的 sys.host 配置项" - hint_proxy_in_use: "已启用代理" + hint_proxy_in_use: "已启用代理 %s" fail_to_load_config: "读取配置文件失败,程序无法正常运行" outdated: hint_latest: "最新" @@ -16,7 +16,7 @@ app.core.biu: network: hint_in_check: "检测网络状态..." fail_pixiv_and_use_bypass: "无法访问 Pixiv,启用 bypassSNI 线路 (可能无法正常使用)" - loginHelper: + login: hint_token_only: "由于 Pixiv 禁止了账号密码登陆方式,目前只能使用 Token 进行登录" hint_before_start: "即将开始进行网络检测,此过程可以减少因网络问题导致的无法正常使用 PixivBiu 的概率" fail_to_get_token_due_to_network: "您的网络无法正常进行 Pixiv Token 登陆,请调整后重试" @@ -37,9 +37,8 @@ app.core.biu: app.common.loginHelper: network: - hint_in_check: "检测网络状态..." press_need_to_type_proxy: "请输入代理地址(可留空): " - hint_detect_proxy_and_continue: "检测到为 %s 的代理地址,是否继续? (y / n): " + hint_detect_proxy: "检测到为 %s 的代理地址,是否需要更改? (y / n): " is_need_to_type_proxy: "未能检测到代理地址,是否需要手动设置? (y / n): " login: hint_intro_step_head: "[Login] 请按以下步骤进行操作:" diff --git a/app/lib/common/login_helper/main.py b/app/lib/common/login_helper/main.py index 77b6ec3..f922159 100644 --- a/app/lib/common/login_helper/main.py +++ b/app/lib/common/login_helper/main.py @@ -2,6 +2,7 @@ from altfe.interface.root import interRoot from app.lib.common.login_helper.token import TokenGetter +from app.v2.utils.sprint import SPrint _ln = lambda val, header="Login Helper": print(f"[{header}] " + val if header else val) @@ -24,12 +25,12 @@ class CommonLoginHelper(interRoot): def __init__(self): self.lang = self.INS.i18n.get_bundle("app.common.loginHelper", func=True) self.requests = requests.Session() - self.requests.mount("https://", CustomAdapter()) + # self.requests.mount("https://", CustomAdapter()) self.token_getter = TokenGetter(lang=self.lang, requests=self.requests) self.proxy = "" self.auth_token_url = "" - def check_network(self, is_no_proxy: bool, silent=False): + def check_network(self, is_no_proxy: bool = False, is_silent: bool = False): """ 网络检测。筛选出本机可通的 Pixiv API 服务器。 :param URLS: 全部 URL @@ -37,16 +38,13 @@ def check_network(self, is_no_proxy: bool, silent=False): :param proxy_: 代理设置,auto 为程序自动判断 :return: bool """ - if not silent: - _ln(self.lang("network.hint_in_check")) - # Determine the final proxy address, or empty - self.proxy = "" if is_no_proxy else self._determine_proxy(silent=silent) + self.proxy = "" if is_no_proxy else self._determine_proxy(is_silent=is_silent) # Determine the final auth host # Check if the hosts are accessible is_conn_array = [ - self._test_access(url=url, proxy=self.proxy, silent=silent) + self._test_access(url=url, proxy=self.proxy, is_silent=False) for url in self.SOME_URLS ] @@ -146,27 +144,24 @@ def get_proxy(self) -> str: def is_bypass(self) -> bool: return self.auth_token_url != self.SOME_URLS[0] - def _determine_proxy(self, silent: bool = False) -> str: + def _determine_proxy(self, is_silent: bool = False) -> str: proxy = self.STATIC.util.get_system_proxy() if proxy != "" and self._test_pixiv_connection(proxy=proxy): pass elif self._test_pixiv_connection(proxy=""): proxy = "" - elif silent is False: + elif is_silent is False: # Require to set proxy manually - if proxy != "": - if ( - input(self.lang("network.hint_detect_proxy_and_continue") % proxy) - == "n" - ): - proxy = input(self.lang("network.press_need_to_type_proxy")) - else: - if input(self.lang("network.is_need_to_type_proxy")) == "y": - proxy = input(self.lang("network.press_need_to_type_proxy")) + if input( + self.lang("network.hint_detect_proxy") % proxy + if proxy + else self.lang("network.is_need_to_type_proxy") + ) in ["y", ""]: + proxy = input(self.lang("network.press_need_to_type_proxy")) return proxy @classmethod - def _test_access(cls, url: str, proxy: str = "", silent: bool = False): + def _test_access(cls, url: str, proxy: str = "", is_silent: bool = False): """ request get 请求。 :param url: URL @@ -174,18 +169,21 @@ def _test_access(cls, url: str, proxy: str = "", silent: bool = False): :param silent: 是否静默运行 :return: bool """ + is_ok = False try: if proxy != "": requests.head(url, proxies={"http": proxy, "https": proxy}, timeout=3) + is_ok = True else: requests.head(url, timeout=3) except: - if silent is False: - cls.STATIC.localMsger.red(f"{url} [ops]", header="Network") - return False - if silent is False: - cls.STATIC.localMsger.green(f"{url} [yep]", header="Network") - return True + pass + if not is_silent: + if is_ok: + _ln(SPrint.green(f"- {url} [yep]"), header=None) + else: + _ln(SPrint.red(f"- {url} [ops]"), header=None) + return is_ok @classmethod def _test_pixiv_connection(cls, proxy: str = "") -> bool: @@ -197,19 +195,19 @@ def _test_pixiv_connection(cls, proxy: str = "") -> bool: return True -class CustomAdapter(requests.adapters.HTTPAdapter): - """ - 防止在请求 Cloudflare 时可能的 SSL 相关错误。 - Thanks to @github/grawity. - """ +# class CustomAdapter(requests.adapters.HTTPAdapter): +# """ +# 防止在请求 Cloudflare 时可能的 SSL 相关错误。 +# Thanks to @github/grawity. +# """ - def init_poolmanager(self, *args, **kwargs): - # When urllib3 hand-rolls a SSLContext, it sets 'options |= OP_NO_TICKET' - # and CloudFlare really does not like this. We cannot control this behavior - # in urllib3, but we can just pass our own standard context instead. - import ssl +# def init_poolmanager(self, *args, **kwargs): +# # When urllib3 hand-rolls a SSLContext, it sets 'options |= OP_NO_TICKET' +# # and CloudFlare really does not like this. We cannot control this behavior +# # in urllib3, but we can just pass our own standard context instead. +# import ssl - ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) - ctx.load_default_certs() - ctx.set_alpn_protocols(["http/1.1"]) - return super().init_poolmanager(*args, **kwargs, ssl_context=ctx) +# ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) +# ctx.load_default_certs() +# ctx.set_alpn_protocols(["http/1.1"]) +# return super().init_poolmanager(*args, **kwargs, ssl_context=ctx) diff --git a/app/lib/core/biu.py b/app/lib/core/biu.py index 9ee39bf..1a6546f 100644 --- a/app/lib/core/biu.py +++ b/app/lib/core/biu.py @@ -44,7 +44,9 @@ def auto(self): try: self.__login() # 登录 except Exception as e: - _ln(str(e)) + e_str = str(e) + if e_str != "": + _ln(e_str) input(self.lang("common.press_to_exit")) sys.exit(0) self.__set_image_host() # 设置图片服务器地址 @@ -79,7 +81,7 @@ def __pre_check(self): _ln(SPrint.red(self.lang("config.hint_port_is_in_use"))) input(self.lang("common.press_to_exit")) sys.exit(0) - # 检测 cache 大小 + # 检测 Cache 大小 cache_path = self.getENV("rootPath") + "usr/cache/search/" size_cache = self.STATIC.file.get_dir_size_mib(cache_path) if size_cache > float(self.sets["biu"]["search"]["maxCacheSizeMiB"]): @@ -98,72 +100,70 @@ def __get_biu_info(self): "pPximgRProxyURL": "https://i.pixiv.re", } - def __login( - self, refresh_token: str | None = None, is_manual: bool = True - ) -> None | Exception: + def __login(self) -> None | Exception: """ 初始化登录函数。 """ helper = self.COMMON.loginHelper() - access, refresh, userid = False, False, False - is_no_proxy = self.sets["sys"]["proxy"] == "no" - is_guided = False - # Get refresh token - if refresh_token is None: - refresh_token = self.STATIC.file.ain(self.getENV("rootPath") + "usr/.token") + # Check and set network config + _ln(self.lang("network.hint_in_check")) + if ( + helper.check_network( + is_no_proxy=self.sets["sys"]["proxy"] == "no", is_silent=False + ) + is False + ): + raise Exception(self.lang("login.fail_to_get_token_due_to_network")) - if not refresh_token and is_manual: - # Guide user to get the initial refresh token - _ln(SPrint.green(self.lang("loginHelper.hint_token_only"))) - if input(self.lang("loginHelper.is_need_to_get_token")) != "y": - raise Exception("Canceled") - if helper.check_network(is_no_proxy=is_no_proxy) is False: - raise Exception( - self.lang("loginHelper.fail_to_get_token_due_to_network") - ) - time.sleep(3) - access, refresh, userid = helper.login() - is_guided = True + # Set proxy + self.proxy = helper.get_proxy() + _ln( + ( + f"- {self.lang('config.hint_proxy_in_use')}" % self.proxy + if self.proxy + else "- No Proxy" + ), + header=None, + ) - # Login with the refresh token - if not access and not is_guided: - if ( - helper.check_network(is_no_proxy=is_no_proxy, silent=not is_manual) - is False - ): - raise Exception("Ops, network error") - access, refresh, userid = helper.refresh(refresh_token=refresh_token) - if not access: - raise Exception("Ops, login error") + # Set bypass mode + if helper.is_bypass(): + _ln(SPrint.red(self.lang("network.fail_pixiv_and_use_bypass"))) + self.api_route = "bypassSNI" + self.proxy = "" - # Save the refresh token - self.STATIC.file.aout( - self.getENV("rootPath") + "usr/.token", refresh, dRename=False - ) + # Determine refresh token + access, userid = False, False + refresh = self.STATIC.file.ain(self.getENV("rootPath") + "usr/.token") + if not refresh: + # Guide user to get the initial refresh token manually + _ln(SPrint.green(self.lang("login.hint_token_only"))) + if input(self.lang("login.is_need_to_get_token")) not in ["y", ""]: + raise Exception() + access, refresh, userid = helper.login() - # Set the trusted network config - if is_manual: - self.proxy = helper.get_proxy() - if self.proxy != "": - _ln(f"{self.lang('config.hint_proxy_in_use')}: {self.proxy}") - if helper.is_bypass(): - _ln(SPrint.red(self.lang("network.fail_pixiv_and_use_bypass"))) - self.api_route = "bypassSNI" - self.proxy = "" + if not refresh: + raise Exception(self.lang("login.fail_to_get_token_anyway")) - # Create PixivPy instance + # Login and save refresh token self.__login_app_api( refresh_token=refresh, - access_token=access, - userid=userid if is_manual else None, + access_token=access if access else None, + userid=userid if userid else None, ) + self.save_token() - def __login_app_api(self, refresh_token, access_token=None, userid=None): + def __login_app_api( + self, + refresh_token: str, + access_token: str | None = None, + userid: str | None = None, + ): """ app 模式登录。 """ - if userid is not None: + if self.api is None: _REQUESTS_KWARGS = {} if self.proxy != "": _REQUESTS_KWARGS = { @@ -175,8 +175,9 @@ def __login_app_api(self, refresh_token, access_token=None, userid=None): self.api.set_accept_language("zh-cn") else: self.api = AppPixivAPI(**_REQUESTS_KWARGS) + if userid: self.api.user_id = userid - if access_token is not None: + if access_token: self.api.set_auth(access_token=access_token, refresh_token=refresh_token) else: self.api.auth(refresh_token=refresh_token) @@ -268,12 +269,21 @@ def update_token(self): header=None, ) try: - self.__login(refresh_token=self.api.refresh_token, is_manual=False) + self.__login_app_api(refresh_token=self.api.refresh_token) + self.save_token() except Exception as e: _ln(SPrint.red(e)) return False return self.api.access_token != ori_access_token + def save_token(self, refresh_token: str | None = None) -> bool: + token = refresh_token if refresh_token else self.api.refresh_token + if token is None: + return False + return self.STATIC.file.aout( + self.getENV("rootPath") + "usr/.token", token, dRename=False + ) + def update_status(self, type_, key, c): """ 线程池状态更新函数。 diff --git a/main.py b/main.py index e60a945..4cc690c 100644 --- a/main.py +++ b/main.py @@ -9,20 +9,6 @@ from altfe import bridge, handle from altfe.interface.root import classRoot -# Fix SSL socket connection issues in some systems -import ssl - -create_default_context_orig = ssl.create_default_context - - -def cdc(*args, **kwargs): - kwargs["purpose"] = ssl.Purpose.SERVER_AUTH - return create_default_context_orig(*args[1:], **kwargs) - - -ssl.create_default_context = cdc -# Fix End - rootPath = os.path.split(os.path.realpath(sys.argv[0]))[0] + "/" rootPathFrozen = sys._MEIPASS + "/" if getattr(sys, "frozen", False) else rootPath