chore: 添加签到重试,仅每日签到获取token (#229)

* fix: 修复无法构建docker镜像的问题

* Update Dockerfile

* 🔧 自动更新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

* 🔧 自动更新requirements

* chore: 更新版本号

* Update config.py

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Night-stars-1 2023-12-04 22:21:41 +08:00 committed by GitHub
parent 6f5bc44082
commit f85232e5ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 94 additions and 74 deletions

View File

@ -1,7 +1,7 @@
''' '''
Date: 2023-11-13 20:29:19 Date: 2023-11-13 20:29:19
LastEditors: Night-stars-1 nujj1042633805@gmail.com 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 # new Env("MIUI-Auto-Task") # pylint: disable=missing-module-docstring
# cron 30 8 * * * miuitask.py # cron 30 8 * * * miuitask.py
@ -9,7 +9,7 @@ LastEditTime: 2023-11-24 16:23:43
import asyncio import asyncio
from utils.api.login import Login 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.config import ConfigManager
from utils.logger import InterceptHandler, log from utils.logger import InterceptHandler, log
from utils.request import notify_me from utils.request import notify_me
@ -25,7 +25,6 @@ async def main():
for account in _conf.accounts: for account in _conf.accounts:
login_obj = Login(account) login_obj = Login(account)
if cookies := await login_obj.login(): if cookies := await login_obj.login():
token = await get_token(cookies["cUserId"])
sign_obj = BaseSign(cookies) sign_obj = BaseSign(cookies)
daily_tasks = await sign_obj.check_daily_tasks() daily_tasks = await sign_obj.check_daily_tasks()
sign_task_obj = sign_obj.AVAILABLE_SIGNS # 签到任务对象合集 sign_task_obj = sign_obj.AVAILABLE_SIGNS # 签到任务对象合集
@ -34,6 +33,7 @@ async def main():
log.info(f"开始执行{task.name}任务") log.info(f"开始执行{task.name}任务")
if task_obj := sign_task_obj.get(task.name): # 签到任务对象 if task_obj := sign_task_obj.get(task.name): # 签到任务对象
if getattr(account, task_obj.__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() await task_obj(cookies, token).sign()
else: else:
log.info(f"任务{task.name}被禁用") log.info(f"任务{task.name}被禁用")

View File

@ -100,8 +100,11 @@ dependencies = [
[[package]] [[package]]
name = "onepush" name = "onepush"
version = "1.3.0" version = "1.2.0"
requires_python = ">=3.6" 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." summary = "A Python library to send notifications to your iPhone, Discord, Telegram, WeChat, QQ and DingTalk."
dependencies = [ dependencies = [
"pycryptodome", "pycryptodome",
@ -204,7 +207,7 @@ summary = "A small Python utility to set file creation time on Windows"
lock_version = "4.2" lock_version = "4.2"
cross_platform = true cross_platform = true
groups = ["default"] groups = ["default"]
content_hash = "sha256:566a9a72c24c47971354bfa0ce10ce921cde51561fd737c3fd433c69621edd5e" content_hash = "sha256:7c922391569ae98b5aba9438d7da9b0ab1b413b23a1e333df2e61bfab038c0ac"
[metadata.files] [metadata.files]
"annotated-types 0.6.0" = [ "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/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"}, {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" = [ "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/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"}, {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"},

View File

@ -4,7 +4,6 @@ version = ""
description = "" description = ""
authors = [] authors = []
dependencies = [ dependencies = [
"onepush",
"orjson>=3.9.10", "orjson>=3.9.10",
"loguru>=0.7.2", "loguru>=0.7.2",
"pydantic>=2.4.2", "pydantic>=2.4.2",
@ -13,6 +12,7 @@ dependencies = [
"pyyaml>=6.0.1", "pyyaml>=6.0.1",
"tenacity>=8.2.3", "tenacity>=8.2.3",
"tzdata>=2023.3", "tzdata>=2023.3",
"onepush @ git+https://github.com/y1ndan/onepush.git@main",
] ]
requires-python = ">=3.11" requires-python = ">=3.11"
license = {text = "MIT"} license = {text = "MIT"}

View File

@ -1,5 +1,5 @@
cryptography==41.0.6 cryptography==41.0.7
httpx==0.25.1 httpx==0.25.2
loguru==0.7.2 loguru==0.7.2
onepush==1.3.0 onepush==1.3.0
orjson==3.9.10 orjson==3.9.10

View File

@ -3,10 +3,12 @@
import time import time
from typing import Dict, List, Optional, Type, Union, Any 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 ..data_model import ApiResultHandler, DailyTasksResult, SignResultHandler
from ..request import get, post from ..request import get, post
from ..logger import log from ..logger import log
from ..utils import is_incorrect_return
class BaseSign: class BaseSign:
@ -37,28 +39,32 @@ class BaseSign:
async def check_daily_tasks(self, nolog: bool = False) -> Union[List[DailyTasksResult], List[None]]: async def check_daily_tasks(self, nolog: bool = False) -> Union[List[DailyTasksResult], List[None]]:
"""获取每日任务状态""" """获取每日任务状态"""
try: try:
response = await get('https://api.vip.miui.com/mtop/planet/vip/member/getCheckinPageCakeList', for attempt in Retrying(stop=stop_after_attempt(3)):
cookies=self.cookie) with attempt:
log.debug(response.text) response = await get('https://api.vip.miui.com/mtop/planet/vip/member/getCheckinPageCakeList',
result = response.json() cookies=self.cookie)
api_data = ApiResultHandler(result) log.debug(response.text)
if api_data.success: result = response.json()
task_status = [] api_data = ApiResultHandler(result)
tasks: List[Dict[str, List[Dict[str, Any]]]] = list(filter( if api_data.success:
lambda x: x['head']['title'] in ["每日任务", "其他任务"], api_data.data)) task_status = []
for task in tasks: tasks: List[Dict[str, List[Dict[str, Any]]]] = list(filter(
for daily_task in task['data']: lambda x: x['head']['title'] in ["每日任务", "其他任务"], api_data.data))
task_name = daily_task['title'] for task in tasks:
task_desc = daily_task.get('desc', '') for daily_task in task['data']:
show_type = True if daily_task['showType'] == 0 else False # pylint: disable=simplifiable-if-expression task_name = daily_task['title']
task_status.append(DailyTasksResult(name=task_name, showType=show_type, desc=task_desc)) task_desc = daily_task.get('desc', '')
return task_status 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: else:
if not nolog:
log.error(f"获取每日任务状态失败:{api_data.message}")
return []
except Exception: # pylint: disable=broad-exception-caught
if not nolog:
log.exception("获取每日任务异常") log.exception("获取每日任务异常")
return [] return []
@ -67,40 +73,44 @@ class BaseSign:
每日任务处理器 每日任务处理器
""" """
try: try:
params = self.PARAMS.copy() for attempt in Retrying(stop=stop_after_attempt(3)):
params['miui_vip_ph'] = self.cookie['miui_vip_ph'] if 'miui_vip_ph' in self.cookie else params with attempt:
params['token'] = self.token if 'token' in params else params params = self.PARAMS.copy()
data = self.DATA.copy() params['miui_vip_ph'] = self.cookie['miui_vip_ph'] if 'miui_vip_ph' in self.cookie else params
data['miui_vip_ph'] = self.cookie['miui_vip_ph'] if 'miui_vip_ph' in self.cookie else data params['token'] = self.token if 'token' in params else params
if 'token' in data: data = self.DATA.copy()
if self.token: data['miui_vip_ph'] = self.cookie['miui_vip_ph'] if 'miui_vip_ph' in self.cookie else data
data['token'] = self.token if 'token' in data:
else: if self.token:
log.info(f"未获取到token, 跳过{self.NAME}") data['token'] = self.token
return False else:
response = await post(self.URL_SIGN, log.info(f"未获取到token, 跳过{self.NAME}")
params=params, data=data, return False
cookies=self.cookie, headers=self.headers) response = await post(self.URL_SIGN,
log.debug(response.text) params=params, data=data,
result = response.json() cookies=self.cookie, headers=self.headers)
api_data = SignResultHandler(result) log.debug(response.text)
if api_data: result = response.json()
if api_data.growth: api_data = SignResultHandler(result)
log.success(f"{self.NAME}结果: 成长值+{api_data.growth}") if api_data:
else: if api_data.growth:
log.success(f"{self.NAME}结果: {api_data.message}") log.success(f"{self.NAME}结果: 成长值+{api_data.growth}")
return True else:
elif api_data.ck_invalid: log.success(f"{self.NAME}结果: {api_data.message}")
log.error(f"{self.NAME}失败: Cookie无效") return True
return False 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: else:
log.error(f"{self.NAME}失败:{api_data.message}") log.exception("{self.NAME}出错")
return False
except Exception: # pylint: disable=broad-exception-caught
log.exception(f"{self.NAME}出错")
return False return False
class CheckIn(BaseSign): class CheckIn(BaseSign):
""" """
每日签到 每日签到

View File

@ -6,9 +6,9 @@ from json import JSONDecodeError
from pathlib import Path from pathlib import Path
from typing import Dict, List, Optional, Union from typing import Dict, List, Optional, Union
import yaml import orjson
from pydantic import BaseModel import yaml # pylint: disable=wrong-import-order
from pydantic import ValidationError, field_validator from pydantic import BaseModel, ValidationError, field_validator
from .logger import log from .logger import log
@ -17,7 +17,10 @@ ROOT_PATH = Path(__name__).parent.absolute()
DATA_PATH = ROOT_PATH / "data" 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) os.makedirs(DATA_PATH, exist_ok=True)
@ -128,14 +131,18 @@ def write_plugin_data(data: Config = None):
if data is None: if data is None:
data = ConfigManager.data_obj data = ConfigManager.data_obj
try: try:
# str_data = orjson.dumps(data.dict(), option=orjson.OPT_PASSTHROUGH_DATETIME | orjson.OPT_SERIALIZE_NUMPY | orjson.OPT_INDENT_2) if CONFIG_TYPE == "json":
str_data = yaml.dump(data.model_dump(), indent=4, allow_unicode=True, sort_keys=False) 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): except (AttributeError, TypeError, ValueError):
log.exception("数据对象序列化失败,可能是数据类型错误") log.exception("数据对象序列化失败,可能是数据类型错误")
return False return False
with open(CONFIG_PATH, "w", encoding="utf-8") as file:
file.write(str_data)
return True
except OSError: except OSError:
return False return False
@ -155,7 +162,10 @@ class ConfigManager:
if os.path.exists(DATA_PATH) and os.path.isfile(CONFIG_PATH): if os.path.exists(DATA_PATH) and os.path.isfile(CONFIG_PATH):
try: try:
with open(CONFIG_PATH, 'r', encoding="utf-8") as file: 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) new_model = Config.model_validate(data)
for attr in new_model.model_fields: for attr in new_model.model_fields:
# ConfigManager.data_obj.__setattr__(attr, new_model.__getattribute__(attr)) # ConfigManager.data_obj.__setattr__(attr, new_model.__getattribute__(attr))

View File

@ -10,7 +10,7 @@ from utils.logger import log
def print_info(): def print_info():
"""打印系统信息""" """打印系统信息"""
log.info("MIUI-AUTO-TASK v1.7.2") log.info("MIUI-AUTO-TASK v1.7.3")
log.info('---------- 系统信息 -------------') log.info('---------- 系统信息 -------------')
system_info() system_info()
log.info('---------- 项目信息 -------------') log.info('---------- 项目信息 -------------')