From f85232e5ee63e8ca2bb0f061a9abbad710f4cb2f Mon Sep 17 00:00:00 2001 From: Night-stars-1 <99261160+Night-stars-1@users.noreply.github.com> Date: Mon, 4 Dec 2023 22:21:41 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E6=B7=BB=E5=8A=A0=E7=AD=BE=E5=88=B0?= =?UTF-8?q?=E9=87=8D=E8=AF=95=EF=BC=8C=E4=BB=85=E6=AF=8F=E6=97=A5=E7=AD=BE?= =?UTF-8?q?=E5=88=B0=E8=8E=B7=E5=8F=96token=20(#229)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 修复无法构建docker镜像的问题 * Update Dockerfile * :wrench: 自动更新requirements * chore: 添加自动每日运行时间提示 * chore: 将时间类型从str改成int * Add files via upload * chore: 更新日志收集方法 * chore: 遵守代码规范 * chore: update issue templates * chore: 删除测试代码 * chore: 更改日志输出样式 * chore: docker生成配置时随机生成自动运行时间 * chore: trailing-whitespace * chore: 日志添加换行 * chore: 未配置验证码解决方案时直接跳过 * chore: 使用遍历方法找到键值,提升泛用性 * chore: 使用cron执行自动任务 * chore: snake_case * chore: 修改运行时间 * Update config.py * chore: 添加签到重试,仅每日签到获取token * :wrench: 自动更新requirements * chore: 更新版本号 * Update config.py --------- Co-authored-by: github-actions[bot] --- miuitask.py | 6 +-- pdm.lock | 10 ++-- pyproject.toml | 2 +- requirements.txt | 4 +- utils/api/sign.py | 114 +++++++++++++++++++++++-------------------- utils/config.py | 30 ++++++++---- utils/system_info.py | 2 +- 7 files changed, 94 insertions(+), 74 deletions(-) diff --git a/miuitask.py b/miuitask.py index 377040a..09fe2b6 100644 --- a/miuitask.py +++ b/miuitask.py @@ -1,7 +1,7 @@ ''' Date: 2023-11-13 20:29:19 LastEditors: Night-stars-1 nujj1042633805@gmail.com -LastEditTime: 2023-11-24 16:23:43 +LastEditTime: 2023-12-03 01:53:48 ''' # new Env("MIUI-Auto-Task") # pylint: disable=missing-module-docstring # cron 30 8 * * * miuitask.py @@ -9,7 +9,7 @@ LastEditTime: 2023-11-24 16:23:43 import asyncio from utils.api.login import Login -from utils.api.sign import BaseSign +from utils.api.sign import BaseSign, CheckIn from utils.config import ConfigManager from utils.logger import InterceptHandler, log from utils.request import notify_me @@ -25,7 +25,6 @@ async def main(): for account in _conf.accounts: login_obj = Login(account) if cookies := await login_obj.login(): - token = await get_token(cookies["cUserId"]) sign_obj = BaseSign(cookies) daily_tasks = await sign_obj.check_daily_tasks() sign_task_obj = sign_obj.AVAILABLE_SIGNS # 签到任务对象合集 @@ -34,6 +33,7 @@ async def main(): log.info(f"开始执行{task.name}任务") if task_obj := sign_task_obj.get(task.name): # 签到任务对象 if getattr(account, task_obj.__name__): + token = await get_token(cookies["cUserId"]) if task_obj == CheckIn else None await task_obj(cookies, token).sign() else: log.info(f"任务{task.name}被禁用") diff --git a/pdm.lock b/pdm.lock index 15b30e1..bdf81b1 100644 --- a/pdm.lock +++ b/pdm.lock @@ -100,8 +100,11 @@ dependencies = [ [[package]] name = "onepush" -version = "1.3.0" +version = "1.2.0" requires_python = ">=3.6" +git = "https://github.com/y1ndan/onepush.git" +ref = "main" +revision = "8b09e62330ad74ba3221bfc2b080d1732a1dcc55" summary = "A Python library to send notifications to your iPhone, Discord, Telegram, WeChat, QQ and DingTalk." dependencies = [ "pycryptodome", @@ -204,7 +207,7 @@ summary = "A small Python utility to set file creation time on Windows" lock_version = "4.2" cross_platform = true groups = ["default"] -content_hash = "sha256:566a9a72c24c47971354bfa0ce10ce921cde51561fd737c3fd433c69621edd5e" +content_hash = "sha256:7c922391569ae98b5aba9438d7da9b0ab1b413b23a1e333df2e61bfab038c0ac" [metadata.files] "annotated-types 0.6.0" = [ @@ -414,9 +417,6 @@ content_hash = "sha256:566a9a72c24c47971354bfa0ce10ce921cde51561fd737c3fd433c696 {url = "https://files.pythonhosted.org/packages/03/0a/4f6fed21aa246c6b49b561ca55facacc2a44b87d65b8b92362a8e99ba202/loguru-0.7.2-py3-none-any.whl", hash = "sha256:003d71e3d3ed35f0f8984898359d65b79e5b21943f78af86aa5491210429b8eb"}, {url = "https://files.pythonhosted.org/packages/9e/30/d87a423766b24db416a46e9335b9602b054a72b96a88a241f2b09b560fa8/loguru-0.7.2.tar.gz", hash = "sha256:e671a53522515f34fd406340ee968cb9ecafbc4b36c679da03c18fd8d0bd51ac"}, ] -"onepush 1.3.0" = [ - {url = "https://files.pythonhosted.org/packages/e1/a2/1d65907128f1b7980d7da0e68b134298ced50d38df8ddf5133e32c8e9f99/onepush-1.3.0-py3-none-any.whl", hash = "sha256:196af2e147a54381b5ffa32565f5f3955a0647328cc283812ce2f87f4bc09f47"}, -] "orjson 3.9.10" = [ {url = "https://files.pythonhosted.org/packages/03/96/4fd0da4f4a5a450054e69439875b4e856654dcbbfea6907d7753b827c937/orjson-3.9.10-cp312-none-win_amd64.whl", hash = "sha256:3e892621434392199efb54e69edfff9f699f6cc36dd9553c5bf796058b14b20d"}, {url = "https://files.pythonhosted.org/packages/09/33/d090754faab1a63ecf80b1df220d6787605caefd570331c757a3553afbf2/orjson-3.9.10-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:92af0d00091e744587221e79f68d617b432425a7e59328ca4c496f774a356071"}, diff --git a/pyproject.toml b/pyproject.toml index dc01467..252c31e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,6 @@ version = "" description = "" authors = [] dependencies = [ - "onepush", "orjson>=3.9.10", "loguru>=0.7.2", "pydantic>=2.4.2", @@ -13,6 +12,7 @@ dependencies = [ "pyyaml>=6.0.1", "tenacity>=8.2.3", "tzdata>=2023.3", + "onepush @ git+https://github.com/y1ndan/onepush.git@main", ] requires-python = ">=3.11" license = {text = "MIT"} diff --git a/requirements.txt b/requirements.txt index 26b6acc..64ba145 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ -cryptography==41.0.6 -httpx==0.25.1 +cryptography==41.0.7 +httpx==0.25.2 loguru==0.7.2 onepush==1.3.0 orjson==3.9.10 diff --git a/utils/api/sign.py b/utils/api/sign.py index f74c100..548d99b 100644 --- a/utils/api/sign.py +++ b/utils/api/sign.py @@ -3,10 +3,12 @@ import time from typing import Dict, List, Optional, Type, Union, Any +from tenacity import RetryError, Retrying, stop_after_attempt from ..data_model import ApiResultHandler, DailyTasksResult, SignResultHandler from ..request import get, post from ..logger import log +from ..utils import is_incorrect_return class BaseSign: @@ -37,28 +39,32 @@ class BaseSign: async def check_daily_tasks(self, nolog: bool = False) -> Union[List[DailyTasksResult], List[None]]: """获取每日任务状态""" try: - response = await get('https://api.vip.miui.com/mtop/planet/vip/member/getCheckinPageCakeList', - cookies=self.cookie) - log.debug(response.text) - result = response.json() - api_data = ApiResultHandler(result) - if api_data.success: - task_status = [] - tasks: List[Dict[str, List[Dict[str, Any]]]] = list(filter( - lambda x: x['head']['title'] in ["每日任务", "其他任务"], api_data.data)) - for task in tasks: - for daily_task in task['data']: - task_name = daily_task['title'] - task_desc = daily_task.get('desc', '') - show_type = True if daily_task['showType'] == 0 else False # pylint: disable=simplifiable-if-expression - task_status.append(DailyTasksResult(name=task_name, showType=show_type, desc=task_desc)) - return task_status + for attempt in Retrying(stop=stop_after_attempt(3)): + with attempt: + response = await get('https://api.vip.miui.com/mtop/planet/vip/member/getCheckinPageCakeList', + cookies=self.cookie) + log.debug(response.text) + result = response.json() + api_data = ApiResultHandler(result) + if api_data.success: + task_status = [] + tasks: List[Dict[str, List[Dict[str, Any]]]] = list(filter( + lambda x: x['head']['title'] in ["每日任务", "其他任务"], api_data.data)) + for task in tasks: + for daily_task in task['data']: + task_name = daily_task['title'] + task_desc = daily_task.get('desc', '') + show_type = True if daily_task['showType'] == 0 else False # pylint: disable=simplifiable-if-expression + task_status.append(DailyTasksResult(name=task_name, showType=show_type, desc=task_desc)) + return task_status + else: + if not nolog: + log.error(f"获取每日任务状态失败:{api_data.message}") + return [] + except RetryError as error: + if is_incorrect_return(error): + log.exception(f"每日任务 - 服务器没有正确返回 {response.text}") else: - if not nolog: - log.error(f"获取每日任务状态失败:{api_data.message}") - return [] - except Exception: # pylint: disable=broad-exception-caught - if not nolog: log.exception("获取每日任务异常") return [] @@ -67,40 +73,44 @@ class BaseSign: 每日任务处理器 """ try: - params = self.PARAMS.copy() - params['miui_vip_ph'] = self.cookie['miui_vip_ph'] if 'miui_vip_ph' in self.cookie else params - params['token'] = self.token if 'token' in params else params - data = self.DATA.copy() - data['miui_vip_ph'] = self.cookie['miui_vip_ph'] if 'miui_vip_ph' in self.cookie else data - if 'token' in data: - if self.token: - data['token'] = self.token - else: - log.info(f"未获取到token, 跳过{self.NAME}") - return False - response = await post(self.URL_SIGN, - params=params, data=data, - cookies=self.cookie, headers=self.headers) - log.debug(response.text) - result = response.json() - api_data = SignResultHandler(result) - if api_data: - if api_data.growth: - log.success(f"{self.NAME}结果: 成长值+{api_data.growth}") - else: - log.success(f"{self.NAME}结果: {api_data.message}") - return True - elif api_data.ck_invalid: - log.error(f"{self.NAME}失败: Cookie无效") - return False + for attempt in Retrying(stop=stop_after_attempt(3)): + with attempt: + params = self.PARAMS.copy() + params['miui_vip_ph'] = self.cookie['miui_vip_ph'] if 'miui_vip_ph' in self.cookie else params + params['token'] = self.token if 'token' in params else params + data = self.DATA.copy() + data['miui_vip_ph'] = self.cookie['miui_vip_ph'] if 'miui_vip_ph' in self.cookie else data + if 'token' in data: + if self.token: + data['token'] = self.token + else: + log.info(f"未获取到token, 跳过{self.NAME}") + return False + response = await post(self.URL_SIGN, + params=params, data=data, + cookies=self.cookie, headers=self.headers) + log.debug(response.text) + result = response.json() + api_data = SignResultHandler(result) + if api_data: + if api_data.growth: + log.success(f"{self.NAME}结果: 成长值+{api_data.growth}") + else: + log.success(f"{self.NAME}结果: {api_data.message}") + return True + elif api_data.ck_invalid: + log.error(f"{self.NAME}失败: Cookie无效") + return False + else: + log.error(f"{self.NAME}失败:{api_data.message}") + return False + except RetryError as error: + if is_incorrect_return(error): + log.exception(f"{self.NAME} - 服务器没有正确返回 {response.text}") else: - log.error(f"{self.NAME}失败:{api_data.message}") - return False - except Exception: # pylint: disable=broad-exception-caught - log.exception(f"{self.NAME}出错") + log.exception("{self.NAME}出错") return False - class CheckIn(BaseSign): """ 每日签到 diff --git a/utils/config.py b/utils/config.py index 4b793bc..7cc3dae 100644 --- a/utils/config.py +++ b/utils/config.py @@ -6,9 +6,9 @@ from json import JSONDecodeError from pathlib import Path from typing import Dict, List, Optional, Union -import yaml -from pydantic import BaseModel -from pydantic import ValidationError, field_validator +import orjson +import yaml # pylint: disable=wrong-import-order +from pydantic import BaseModel, ValidationError, field_validator from .logger import log @@ -17,7 +17,10 @@ ROOT_PATH = Path(__name__).parent.absolute() DATA_PATH = ROOT_PATH / "data" """数据保存目录""" -CONFIG_PATH = DATA_PATH / "config.yaml" if os.getenv("MIUITASK_CONFIG_PATH") is None else Path(os.getenv("MIUITASK_CONFIG_PATH")) +CONFIG_TYPE = "json" if os.path.isfile(DATA_PATH / "config.json") else "yaml" +"""数据文件类型""" + +CONFIG_PATH = DATA_PATH / f"config.{CONFIG_TYPE}" if os.getenv("MIUITASK_CONFIG_PATH") is None else Path(os.getenv("MIUITASK_CONFIG_PATH")) """数据文件默认路径""" os.makedirs(DATA_PATH, exist_ok=True) @@ -128,14 +131,18 @@ def write_plugin_data(data: Config = None): if data is None: data = ConfigManager.data_obj try: - # str_data = orjson.dumps(data.dict(), option=orjson.OPT_PASSTHROUGH_DATETIME | orjson.OPT_SERIALIZE_NUMPY | orjson.OPT_INDENT_2) - str_data = yaml.dump(data.model_dump(), indent=4, allow_unicode=True, sort_keys=False) + if CONFIG_TYPE == "json": + str_data = orjson.dumps(data.model_dump(), option=orjson.OPT_PASSTHROUGH_DATETIME | orjson.OPT_SERIALIZE_NUMPY | orjson.OPT_INDENT_2) + with open(CONFIG_PATH, "wb") as file: + file.write(str_data) + else: + str_data = yaml.dump(data.model_dump(), indent=4, allow_unicode=True, sort_keys=False) + with open(CONFIG_PATH, "w", encoding="utf-8") as file: + file.write(str_data) + return True except (AttributeError, TypeError, ValueError): log.exception("数据对象序列化失败,可能是数据类型错误") return False - with open(CONFIG_PATH, "w", encoding="utf-8") as file: - file.write(str_data) - return True except OSError: return False @@ -155,7 +162,10 @@ class ConfigManager: if os.path.exists(DATA_PATH) and os.path.isfile(CONFIG_PATH): try: with open(CONFIG_PATH, 'r', encoding="utf-8") as file: - data = yaml.safe_load(file) + if CONFIG_TYPE == "json": + data = orjson.loads(file.read()) + else: + data = yaml.safe_load(file) new_model = Config.model_validate(data) for attr in new_model.model_fields: # ConfigManager.data_obj.__setattr__(attr, new_model.__getattribute__(attr)) diff --git a/utils/system_info.py b/utils/system_info.py index 7b9891c..07994dc 100644 --- a/utils/system_info.py +++ b/utils/system_info.py @@ -10,7 +10,7 @@ from utils.logger import log def print_info(): """打印系统信息""" - log.info("MIUI-AUTO-TASK v1.7.2") + log.info("MIUI-AUTO-TASK v1.7.3") log.info('---------- 系统信息 -------------') system_info() log.info('---------- 项目信息 -------------')