mirror of
https://github.com/PaiGramTeam/PamGram.git
synced 2024-11-21 13:48:19 +00:00
✨ support task services
Co-authored-by: 洛水居室 <luoshuijs@outlook.com>
This commit is contained in:
parent
98147c4aeb
commit
84f053b70d
134
alembic/versions/1df05b897d3f_tasks.py
Normal file
134
alembic/versions/1df05b897d3f_tasks.py
Normal file
@ -0,0 +1,134 @@
|
||||
"""tasks
|
||||
|
||||
Revision ID: 1df05b897d3f
|
||||
Revises: a1c10da5704b
|
||||
Create Date: 2023-07-23 14:44:59.592519
|
||||
|
||||
"""
|
||||
import logging
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy import text
|
||||
from sqlalchemy.dialects import mysql
|
||||
from sqlalchemy.exc import NoSuchTableError
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = "1df05b897d3f"
|
||||
down_revision = "a1c10da5704b"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
connection = op.get_bind()
|
||||
task_table = op.create_table(
|
||||
"task",
|
||||
sa.Column("id", sa.Integer(), autoincrement=True, nullable=False),
|
||||
sa.Column("user_id", sa.BigInteger(), nullable=True),
|
||||
sa.Column("chat_id", sa.BigInteger(), nullable=True),
|
||||
sa.Column(
|
||||
"time_created",
|
||||
sa.DateTime(),
|
||||
server_default=sa.text("now()"),
|
||||
nullable=True,
|
||||
),
|
||||
sa.Column("time_updated", sa.DateTime(), nullable=True),
|
||||
sa.Column(
|
||||
"type",
|
||||
sa.Enum(
|
||||
"SIGN",
|
||||
"RESIN",
|
||||
"REALM",
|
||||
"EXPEDITION",
|
||||
"TRANSFORMER",
|
||||
"CARD",
|
||||
name="tasktypeenum",
|
||||
),
|
||||
nullable=True,
|
||||
),
|
||||
sa.Column(
|
||||
"status",
|
||||
sa.Enum(
|
||||
"STATUS_SUCCESS",
|
||||
"INVALID_COOKIES",
|
||||
"ALREADY_CLAIMED",
|
||||
"NEED_CHALLENGE",
|
||||
"GENSHIN_EXCEPTION",
|
||||
"TIMEOUT_ERROR",
|
||||
"BAD_REQUEST",
|
||||
"FORBIDDEN",
|
||||
name="taskstatusenum",
|
||||
),
|
||||
nullable=True,
|
||||
),
|
||||
sa.Column("data", sa.JSON(), nullable=True),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
mysql_charset="utf8mb4",
|
||||
mysql_collate="utf8mb4_general_ci",
|
||||
)
|
||||
op.create_index("task_1", "task", ["user_id"], unique=False)
|
||||
try:
|
||||
statement = "SELECT * FROM sign;"
|
||||
old_sign_table_data = connection.execute(text(statement))
|
||||
except NoSuchTableError:
|
||||
logger.warning("Table 'sign' doesn't exist")
|
||||
return # should not happen
|
||||
if old_sign_table_data is not None:
|
||||
for row in old_sign_table_data:
|
||||
try:
|
||||
user_id = row["user_id"]
|
||||
chat_id = row["chat_id"]
|
||||
time_created = row["time_created"]
|
||||
time_updated = row["time_updated"]
|
||||
status = row["status"]
|
||||
task_type = "SIGN"
|
||||
insert = task_table.insert().values(
|
||||
user_id=int(user_id),
|
||||
chat_id=int(chat_id),
|
||||
time_created=time_created,
|
||||
time_updated=time_updated,
|
||||
type=task_type,
|
||||
status=status,
|
||||
)
|
||||
with op.get_context().autocommit_block():
|
||||
connection.execute(insert)
|
||||
except Exception as exc: # pylint: disable=W0703
|
||||
logger.error("Process sign->task Exception", exc_info=exc) # pylint: disable=W0703
|
||||
op.drop_table("sign")
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table(
|
||||
"sign",
|
||||
sa.Column("id", mysql.INTEGER(), autoincrement=False, nullable=False),
|
||||
sa.Column("user_id", mysql.BIGINT(), autoincrement=False, nullable=False),
|
||||
sa.Column("chat_id", mysql.BIGINT(), autoincrement=False, nullable=True),
|
||||
sa.Column("time_created", mysql.DATETIME(), nullable=True),
|
||||
sa.Column("time_updated", mysql.DATETIME(), nullable=True),
|
||||
sa.Column(
|
||||
"status",
|
||||
mysql.ENUM(
|
||||
"STATUS_SUCCESS",
|
||||
"INVALID_COOKIES",
|
||||
"ALREADY_CLAIMED",
|
||||
"GENSHIN_EXCEPTION",
|
||||
"TIMEOUT_ERROR",
|
||||
"BAD_REQUEST",
|
||||
"FORBIDDEN",
|
||||
),
|
||||
nullable=True,
|
||||
),
|
||||
sa.PrimaryKeyConstraint("id", "user_id"),
|
||||
mysql_collate="utf8mb4_general_ci",
|
||||
mysql_default_charset="utf8mb4",
|
||||
mysql_engine="InnoDB",
|
||||
)
|
||||
op.drop_index("task_1", table_name="task")
|
||||
op.drop_table("task")
|
||||
# ### end Alembic commands ###
|
@ -1 +0,0 @@
|
||||
"""SignService"""
|
@ -1,28 +0,0 @@
|
||||
from core.base_service import BaseService
|
||||
from core.services.sign.models import Sign
|
||||
from core.services.sign.repositories import SignRepository
|
||||
|
||||
__all__ = ["SignServices"]
|
||||
|
||||
|
||||
class SignServices(BaseService):
|
||||
def __init__(self, sign_repository: SignRepository) -> None:
|
||||
self._repository: SignRepository = sign_repository
|
||||
|
||||
async def get_all(self):
|
||||
return await self._repository.get_all()
|
||||
|
||||
async def add(self, sign: Sign):
|
||||
return await self._repository.add(sign)
|
||||
|
||||
async def remove(self, sign: Sign):
|
||||
return await self._repository.remove(sign)
|
||||
|
||||
async def update(self, sign: Sign):
|
||||
return await self._repository.update(sign)
|
||||
|
||||
async def get_by_user_id(self, user_id: int):
|
||||
return await self._repository.get_by_user_id(user_id)
|
||||
|
||||
async def get_by_chat_id(self, chat_id: int):
|
||||
return await self._repository.get_by_chat_id(chat_id)
|
1
core/services/task/__init__.py
Normal file
1
core/services/task/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
"""TaskService"""
|
@ -1,15 +1,15 @@
|
||||
import enum
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
from typing import Optional, Dict, Any
|
||||
|
||||
from sqlalchemy import func, BigInteger
|
||||
from sqlalchemy import func, BigInteger, JSON
|
||||
from sqlmodel import Column, DateTime, Enum, Field, SQLModel, Integer
|
||||
|
||||
__all__ = ("SignStatusEnum", "Sign")
|
||||
__all__ = ("Task", "TaskStatusEnum", "TaskTypeEnum")
|
||||
|
||||
|
||||
class SignStatusEnum(int, enum.Enum):
|
||||
STATUS_SUCCESS = 0 # 签到成功
|
||||
class TaskStatusEnum(int, enum.Enum):
|
||||
STATUS_SUCCESS = 0 # 任务执行成功
|
||||
INVALID_COOKIES = 1 # Cookie无效
|
||||
ALREADY_CLAIMED = 2 # 已经获取奖励
|
||||
NEED_CHALLENGE = 3 # 需要验证码
|
||||
@ -19,15 +19,26 @@ class SignStatusEnum(int, enum.Enum):
|
||||
FORBIDDEN = 7 # 这错误一般为通知失败 机器人被用户BAN
|
||||
|
||||
|
||||
class Sign(SQLModel, table=True):
|
||||
class TaskTypeEnum(int, enum.Enum):
|
||||
SIGN = 0 # 签到
|
||||
RESIN = 1 # 开拓力
|
||||
REALM = 2 # 洞天宝钱
|
||||
EXPEDITION = 3 # 委托
|
||||
TRANSFORMER = 4 # 参量质变仪
|
||||
CARD = 5 # 生日画片
|
||||
|
||||
|
||||
class Task(SQLModel, table=True):
|
||||
__table_args__ = dict(mysql_charset="utf8mb4", mysql_collate="utf8mb4_general_ci")
|
||||
id: Optional[int] = Field(
|
||||
default=None, primary_key=True, sa_column=Column(Integer(), primary_key=True, autoincrement=True)
|
||||
)
|
||||
user_id: int = Field(primary_key=True, sa_column=Column(BigInteger(), index=True))
|
||||
chat_id: Optional[int] = Field(default=None)
|
||||
chat_id: Optional[int] = Field(default=None, sa_column=Column(BigInteger()))
|
||||
time_created: Optional[datetime] = Field(
|
||||
sa_column=Column(DateTime, server_default=func.now()) # pylint: disable=E1102
|
||||
)
|
||||
time_updated: Optional[datetime] = Field(sa_column=Column(DateTime, onupdate=func.now())) # pylint: disable=E1102
|
||||
status: Optional[SignStatusEnum] = Field(sa_column=Column(Enum(SignStatusEnum)))
|
||||
type: TaskTypeEnum = Field(primary_key=True, sa_column=Column(Enum(TaskTypeEnum)))
|
||||
status: Optional[TaskStatusEnum] = Field(sa_column=Column(Enum(TaskStatusEnum)))
|
||||
data: Optional[Dict[str, Any]] = Field(sa_column=Column(JSON))
|
@ -4,47 +4,47 @@ from sqlmodel import select
|
||||
|
||||
from core.base_service import BaseService
|
||||
from core.dependence.database import Database
|
||||
from core.services.sign.models import Sign
|
||||
from core.services.task.models import Task, TaskTypeEnum
|
||||
from core.sqlmodel.session import AsyncSession
|
||||
|
||||
__all__ = ("SignRepository",)
|
||||
__all__ = ("TaskRepository",)
|
||||
|
||||
|
||||
class SignRepository(BaseService.Component):
|
||||
class TaskRepository(BaseService.Component):
|
||||
def __init__(self, database: Database):
|
||||
self.engine = database.engine
|
||||
|
||||
async def add(self, sign: Sign):
|
||||
async def add(self, task: Task):
|
||||
async with AsyncSession(self.engine) as session:
|
||||
session.add(sign)
|
||||
session.add(task)
|
||||
await session.commit()
|
||||
|
||||
async def remove(self, sign: Sign):
|
||||
async def remove(self, task: Task):
|
||||
async with AsyncSession(self.engine) as session:
|
||||
await session.delete(sign)
|
||||
await session.delete(task)
|
||||
await session.commit()
|
||||
|
||||
async def update(self, sign: Sign) -> Sign:
|
||||
async def update(self, task: Task) -> Task:
|
||||
async with AsyncSession(self.engine) as session:
|
||||
session.add(sign)
|
||||
session.add(task)
|
||||
await session.commit()
|
||||
await session.refresh(sign)
|
||||
return sign
|
||||
await session.refresh(task)
|
||||
return task
|
||||
|
||||
async def get_by_user_id(self, user_id: int) -> Optional[Sign]:
|
||||
async def get_by_user_id(self, user_id: int, task_type: TaskTypeEnum) -> Optional[Task]:
|
||||
async with AsyncSession(self.engine) as session:
|
||||
statement = select(Sign).where(Sign.user_id == user_id)
|
||||
statement = select(Task).where(Task.user_id == user_id).where(Task.type == task_type)
|
||||
results = await session.exec(statement)
|
||||
return results.first()
|
||||
|
||||
async def get_by_chat_id(self, chat_id: int) -> Optional[List[Sign]]:
|
||||
async def get_by_chat_id(self, chat_id: int, task_type: TaskTypeEnum) -> Optional[List[Task]]:
|
||||
async with AsyncSession(self.engine) as session:
|
||||
statement = select(Sign).where(Sign.chat_id == chat_id)
|
||||
statement = select(Task).where(Task.chat_id == chat_id).where(Task.type == task_type)
|
||||
results = await session.exec(statement)
|
||||
return results.all()
|
||||
|
||||
async def get_all(self) -> List[Sign]:
|
||||
async def get_all(self, task_type: TaskTypeEnum) -> List[Task]:
|
||||
async with AsyncSession(self.engine) as session:
|
||||
query = select(Sign)
|
||||
query = select(Task).where(Task.type == task_type)
|
||||
results = await session.exec(query)
|
||||
return results.all()
|
179
core/services/task/services.py
Normal file
179
core/services/task/services.py
Normal file
@ -0,0 +1,179 @@
|
||||
import datetime
|
||||
from typing import Optional, Dict, Any
|
||||
|
||||
from core.base_service import BaseService
|
||||
from core.services.task.models import Task, TaskTypeEnum
|
||||
from core.services.task.repositories import TaskRepository
|
||||
|
||||
__all__ = [
|
||||
"TaskServices",
|
||||
"SignServices",
|
||||
"TaskCardServices",
|
||||
"TaskResinServices",
|
||||
"TaskExpeditionServices",
|
||||
]
|
||||
|
||||
|
||||
class TaskServices(BaseService):
|
||||
TASK_TYPE: TaskTypeEnum
|
||||
|
||||
def __init__(self, task_repository: TaskRepository) -> None:
|
||||
self._repository: TaskRepository = task_repository
|
||||
|
||||
async def add(self, task: Task):
|
||||
return await self._repository.add(task)
|
||||
|
||||
async def remove(self, task: Task):
|
||||
return await self._repository.remove(task)
|
||||
|
||||
async def update(self, task: Task):
|
||||
task.time_updated = datetime.datetime.now()
|
||||
return await self._repository.update(task)
|
||||
|
||||
async def get_by_user_id(self, user_id: int):
|
||||
return await self._repository.get_by_user_id(user_id, self.TASK_TYPE)
|
||||
|
||||
async def get_all(self):
|
||||
return await self._repository.get_all(self.TASK_TYPE)
|
||||
|
||||
def create(self, user_id: int, chat_id: int, status: int, data: Optional[Dict[str, Any]] = None):
|
||||
return Task(
|
||||
user_id=user_id,
|
||||
chat_id=chat_id,
|
||||
time_created=datetime.datetime.now(),
|
||||
status=status,
|
||||
type=self.TASK_TYPE,
|
||||
data=data,
|
||||
)
|
||||
|
||||
|
||||
class SignServices(BaseService):
|
||||
TASK_TYPE = TaskTypeEnum.SIGN
|
||||
|
||||
def __init__(self, task_repository: TaskRepository) -> None:
|
||||
self._repository: TaskRepository = task_repository
|
||||
|
||||
async def add(self, task: Task):
|
||||
return await self._repository.add(task)
|
||||
|
||||
async def remove(self, task: Task):
|
||||
return await self._repository.remove(task)
|
||||
|
||||
async def update(self, task: Task):
|
||||
task.time_updated = datetime.datetime.now()
|
||||
return await self._repository.update(task)
|
||||
|
||||
async def get_by_user_id(self, user_id: int):
|
||||
return await self._repository.get_by_user_id(user_id, self.TASK_TYPE)
|
||||
|
||||
async def get_all(self):
|
||||
return await self._repository.get_all(self.TASK_TYPE)
|
||||
|
||||
def create(self, user_id: int, chat_id: int, status: int, data: Optional[Dict[str, Any]] = None):
|
||||
return Task(
|
||||
user_id=user_id,
|
||||
chat_id=chat_id,
|
||||
time_created=datetime.datetime.now(),
|
||||
status=status,
|
||||
type=self.TASK_TYPE,
|
||||
data=data,
|
||||
)
|
||||
|
||||
|
||||
class TaskCardServices(BaseService):
|
||||
TASK_TYPE = TaskTypeEnum.CARD
|
||||
|
||||
def __init__(self, task_repository: TaskRepository) -> None:
|
||||
self._repository: TaskRepository = task_repository
|
||||
|
||||
async def add(self, task: Task):
|
||||
return await self._repository.add(task)
|
||||
|
||||
async def remove(self, task: Task):
|
||||
return await self._repository.remove(task)
|
||||
|
||||
async def update(self, task: Task):
|
||||
task.time_updated = datetime.datetime.now()
|
||||
return await self._repository.update(task)
|
||||
|
||||
async def get_by_user_id(self, user_id: int):
|
||||
return await self._repository.get_by_user_id(user_id, self.TASK_TYPE)
|
||||
|
||||
async def get_all(self):
|
||||
return await self._repository.get_all(self.TASK_TYPE)
|
||||
|
||||
def create(self, user_id: int, chat_id: int, status: int, data: Optional[Dict[str, Any]] = None):
|
||||
return Task(
|
||||
user_id=user_id,
|
||||
chat_id=chat_id,
|
||||
time_created=datetime.datetime.now(),
|
||||
status=status,
|
||||
type=self.TASK_TYPE,
|
||||
data=data,
|
||||
)
|
||||
|
||||
|
||||
class TaskResinServices(BaseService):
|
||||
TASK_TYPE = TaskTypeEnum.RESIN
|
||||
|
||||
def __init__(self, task_repository: TaskRepository) -> None:
|
||||
self._repository: TaskRepository = task_repository
|
||||
|
||||
async def add(self, task: Task):
|
||||
return await self._repository.add(task)
|
||||
|
||||
async def remove(self, task: Task):
|
||||
return await self._repository.remove(task)
|
||||
|
||||
async def update(self, task: Task):
|
||||
task.time_updated = datetime.datetime.now()
|
||||
return await self._repository.update(task)
|
||||
|
||||
async def get_by_user_id(self, user_id: int):
|
||||
return await self._repository.get_by_user_id(user_id, self.TASK_TYPE)
|
||||
|
||||
async def get_all(self):
|
||||
return await self._repository.get_all(self.TASK_TYPE)
|
||||
|
||||
def create(self, user_id: int, chat_id: int, status: int, data: Optional[Dict[str, Any]] = None):
|
||||
return Task(
|
||||
user_id=user_id,
|
||||
chat_id=chat_id,
|
||||
time_created=datetime.datetime.now(),
|
||||
status=status,
|
||||
type=self.TASK_TYPE,
|
||||
data=data,
|
||||
)
|
||||
|
||||
|
||||
class TaskExpeditionServices(BaseService):
|
||||
TASK_TYPE = TaskTypeEnum.EXPEDITION
|
||||
|
||||
def __init__(self, task_repository: TaskRepository) -> None:
|
||||
self._repository: TaskRepository = task_repository
|
||||
|
||||
async def add(self, task: Task):
|
||||
return await self._repository.add(task)
|
||||
|
||||
async def remove(self, task: Task):
|
||||
return await self._repository.remove(task)
|
||||
|
||||
async def update(self, task: Task):
|
||||
task.time_updated = datetime.datetime.now()
|
||||
return await self._repository.update(task)
|
||||
|
||||
async def get_by_user_id(self, user_id: int):
|
||||
return await self._repository.get_by_user_id(user_id, self.TASK_TYPE)
|
||||
|
||||
async def get_all(self):
|
||||
return await self._repository.get_all(self.TASK_TYPE)
|
||||
|
||||
def create(self, user_id: int, chat_id: int, status: int, data: Optional[Dict[str, Any]] = None):
|
||||
return Task(
|
||||
user_id=user_id,
|
||||
chat_id=chat_id,
|
||||
time_created=datetime.datetime.now(),
|
||||
status=status,
|
||||
type=self.TASK_TYPE,
|
||||
data=data,
|
||||
)
|
@ -1,5 +1,5 @@
|
||||
from telegram import Update
|
||||
from telegram.ext import CallbackContext, CommandHandler
|
||||
from telegram.ext import CallbackContext
|
||||
|
||||
from core.plugin import Plugin, handler
|
||||
from plugins.tools.sign import SignSystem, SignJobType
|
||||
@ -10,7 +10,7 @@ class SignAll(Plugin):
|
||||
def __init__(self, sign_system: SignSystem):
|
||||
self.sign_system = sign_system
|
||||
|
||||
@handler(CommandHandler, command="sign_all", block=False, admin=True)
|
||||
@handler.command(command="sign_all", block=False, admin=True)
|
||||
async def sign_all(self, update: Update, context: CallbackContext):
|
||||
user = update.effective_user
|
||||
logger.info("用户 %s[%s] sign_all 命令请求", user.full_name, user.id)
|
||||
|
@ -2,7 +2,7 @@ from telegram import Update
|
||||
from telegram.ext import CallbackContext, CommandHandler
|
||||
|
||||
from core.plugin import Plugin, handler
|
||||
from core.services.sign.services import SignServices
|
||||
from core.services.task.services import SignServices
|
||||
from utils.log import logger
|
||||
|
||||
|
||||
|
20
plugins/jobs/daily_note.py
Normal file
20
plugins/jobs/daily_note.py
Normal file
@ -0,0 +1,20 @@
|
||||
import datetime
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from core.plugin import Plugin, job
|
||||
from plugins.tools.daily_note import DailyNoteSystem
|
||||
from utils.log import logger
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from telegram.ext import ContextTypes
|
||||
|
||||
|
||||
class NotesJob(Plugin):
|
||||
def __init__(self, daily_note_system: DailyNoteSystem):
|
||||
self.daily_note_system = daily_note_system
|
||||
|
||||
@job.run_repeating(interval=datetime.timedelta(minutes=20), name="NotesJob")
|
||||
async def card(self, context: "ContextTypes.DEFAULT_TYPE"):
|
||||
logger.info("正在执行自动便签提醒")
|
||||
await self.daily_note_system.do_get_notes_job(context)
|
||||
logger.success("执行自动便签提醒完成")
|
130
plugins/starrail/daily_note_tasks.py
Normal file
130
plugins/starrail/daily_note_tasks.py
Normal file
@ -0,0 +1,130 @@
|
||||
from pydantic import ValidationError
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from simnet import Region
|
||||
from simnet.errors import DataNotPublic, BadRequest as SimnetBadRequest
|
||||
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, Update, KeyboardButton, WebAppInfo
|
||||
from telegram.ext import CallbackContext, ConversationHandler, filters
|
||||
from telegram.helpers import escape_markdown
|
||||
|
||||
from core.config import config
|
||||
from core.plugin import Plugin, conversation, handler
|
||||
from core.services.cookies.services import CookiesService
|
||||
from core.services.players.services import PlayersService, PlayerInfoService
|
||||
from plugins.app.webapp import WebApp
|
||||
from plugins.tools.daily_note import DailyNoteSystem, WebAppData
|
||||
from plugins.tools.genshin import GenshinHelper, CookiesNotFoundError, PlayerNotFoundError
|
||||
from utils.log import logger
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from simnet import StarRailClient
|
||||
|
||||
__all__ = ("DailyNoteTasksPlugin",)
|
||||
|
||||
|
||||
SET_BY_WEB = 10100
|
||||
|
||||
|
||||
class DailyNoteTasksPlugin(Plugin.Conversation):
|
||||
"""自动便签提醒任务"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
players_service: PlayersService,
|
||||
cookies_service: CookiesService,
|
||||
player_info_service: PlayerInfoService,
|
||||
helper: GenshinHelper,
|
||||
note_system: DailyNoteSystem,
|
||||
):
|
||||
self.cookies_service = cookies_service
|
||||
self.players_service = players_service
|
||||
self.player_info_service = player_info_service
|
||||
self.helper = helper
|
||||
self.note_system = note_system
|
||||
|
||||
@conversation.entry_point
|
||||
@handler.command(command="daily_note_tasks", filters=filters.ChatType.PRIVATE, block=False)
|
||||
async def command_start(self, update: Update, _: CallbackContext) -> int:
|
||||
user = update.effective_user
|
||||
message = update.effective_message
|
||||
logger.info("用户 %s[%s] 设置自动便签提醒命令请求", user.full_name, user.id)
|
||||
text = await self.check_genshin_user(user.id, False)
|
||||
if text != "ok":
|
||||
await message.reply_text(text, reply_markup=ReplyKeyboardRemove())
|
||||
return ConversationHandler.END
|
||||
note_user = await self.note_system.get_single_task_user(user.id)
|
||||
url = f"{config.pass_challenge_user_web}/tasks2?command=tasks&bot_data={note_user.web_config}"
|
||||
text = f'你好 {user.mention_markdown_v2()} {escape_markdown("!请点击下方按钮,开始设置,或者回复退出取消操作")}'
|
||||
await message.reply_markdown_v2(
|
||||
text,
|
||||
reply_markup=ReplyKeyboardMarkup.from_button(
|
||||
KeyboardButton(
|
||||
text="点我开始设置",
|
||||
web_app=WebAppInfo(url=url),
|
||||
)
|
||||
),
|
||||
)
|
||||
return SET_BY_WEB
|
||||
|
||||
async def check_genshin_user(self, user_id: int, request_note: bool) -> str:
|
||||
try:
|
||||
async with self.helper.genshin(user_id) as client:
|
||||
client: "StarRailClient"
|
||||
if request_note:
|
||||
if client.region == Region.CHINESE:
|
||||
await client.get_starrail_notes_by_stoken()
|
||||
else:
|
||||
await client.get_starrail_notes()
|
||||
return "ok"
|
||||
except ValueError:
|
||||
return "Cookies 缺少 stoken ,请尝试重新绑定账号。"
|
||||
except DataNotPublic:
|
||||
return "查询失败惹,可能是便签功能被禁用了?请尝试通过米游社或者 hoyolab 获取一次便签信息后重试。"
|
||||
except SimnetBadRequest as e:
|
||||
return f"获取便签失败,可能遇到验证码风控,请尝试重新绑定账号。{e}"
|
||||
except (CookiesNotFoundError, PlayerNotFoundError):
|
||||
return "未查询到您所绑定的账号信息,请先私聊派蒙绑定账号"
|
||||
|
||||
@conversation.state(state=SET_BY_WEB)
|
||||
@handler.message(filters=filters.TEXT & ~filters.COMMAND, block=False)
|
||||
async def set_by_web_text(self, update: Update, _: CallbackContext) -> int:
|
||||
message = update.effective_message
|
||||
if message.text == "退出":
|
||||
await message.reply_text("退出任务", reply_markup=ReplyKeyboardRemove())
|
||||
return ConversationHandler.END
|
||||
else:
|
||||
await message.reply_text("输入错误,请重新输入")
|
||||
return SET_BY_WEB
|
||||
|
||||
@conversation.state(state=SET_BY_WEB)
|
||||
@handler.message(filters=filters.StatusUpdate.WEB_APP_DATA, block=False)
|
||||
async def set_by_web(self, update: Update, _: CallbackContext) -> int:
|
||||
user = update.effective_user
|
||||
message = update.effective_message
|
||||
web_app_data = message.web_app_data
|
||||
if web_app_data:
|
||||
result = WebApp.de_web_app_data(web_app_data.data)
|
||||
if result.code == 0:
|
||||
if result.path == "tasks":
|
||||
try:
|
||||
validate = WebAppData(**result.data)
|
||||
except ValidationError:
|
||||
await message.reply_text(
|
||||
"数据错误\n开拓力提醒数值必须在 100 ~ 180 之间",
|
||||
reply_markup=ReplyKeyboardRemove(),
|
||||
)
|
||||
return ConversationHandler.END
|
||||
need_note = await self.check_genshin_user(user.id, True)
|
||||
if need_note != "ok":
|
||||
await message.reply_text(need_note, reply_markup=ReplyKeyboardRemove())
|
||||
return ConversationHandler.END
|
||||
await self.note_system.import_web_config(user.id, validate)
|
||||
await message.reply_text("修改设置成功", reply_markup=ReplyKeyboardRemove())
|
||||
else:
|
||||
logger.warning(
|
||||
"用户 %s[%s] WEB_APP_DATA 请求错误 [%s]%s", user.full_name, user.id, result.code, result.message
|
||||
)
|
||||
await message.reply_text(f"WebApp返回错误 {result.message}", reply_markup=ReplyKeyboardRemove())
|
||||
else:
|
||||
logger.warning("用户 %s[%s] WEB_APP_DATA 非法数据", user.full_name, user.id)
|
||||
return ConversationHandler.END
|
@ -1,4 +1,3 @@
|
||||
import datetime
|
||||
from typing import Optional, Tuple
|
||||
|
||||
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
|
||||
@ -10,8 +9,8 @@ from telegram.helpers import create_deep_linked_url
|
||||
from core.config import config
|
||||
from core.handler.callbackqueryhandler import CallbackQueryHandler
|
||||
from core.plugin import Plugin, handler
|
||||
from core.services.sign.models import Sign as SignUser, SignStatusEnum
|
||||
from core.services.sign.services import SignServices
|
||||
from core.services.task.models import Task as SignUser, TaskStatusEnum
|
||||
from core.services.task.services import SignServices
|
||||
from core.services.users.services import UserAdminService
|
||||
from plugins.tools.genshin import GenshinHelper, CookiesNotFoundError, PlayerNotFoundError
|
||||
from plugins.tools.sign import SignSystem, NeedChallenge
|
||||
@ -49,18 +48,13 @@ class Sign(Plugin):
|
||||
if user.chat_id == chat_id:
|
||||
return "自动签到已经开启过了"
|
||||
user.chat_id = chat_id
|
||||
user.status = SignStatusEnum.STATUS_SUCCESS
|
||||
user.status = TaskStatusEnum.STATUS_SUCCESS
|
||||
await self.sign_service.update(user)
|
||||
return "修改自动签到通知对话成功"
|
||||
elif method == "关闭":
|
||||
return "您还没有开启自动签到"
|
||||
elif method == "开启":
|
||||
user = SignUser(
|
||||
user_id=user_id,
|
||||
chat_id=chat_id,
|
||||
time_created=datetime.datetime.now(),
|
||||
status=SignStatusEnum.STATUS_SUCCESS,
|
||||
)
|
||||
user = self.sign_service.create(user_id, chat_id, TaskStatusEnum.STATUS_SUCCESS)
|
||||
await self.sign_service.add(user)
|
||||
return "开启自动签到成功"
|
||||
|
||||
|
299
plugins/tools/daily_note.py
Normal file
299
plugins/tools/daily_note.py
Normal file
@ -0,0 +1,299 @@
|
||||
import base64
|
||||
from datetime import datetime
|
||||
from typing import TYPE_CHECKING, List, Optional
|
||||
|
||||
from pydantic import BaseModel, validator
|
||||
from simnet.errors import BadRequest as SimnetBadRequest, InvalidCookies, TimedOut as SimnetTimedOut
|
||||
from telegram.constants import ParseMode
|
||||
from telegram.error import BadRequest, Forbidden
|
||||
|
||||
from core.basemodel import RegionEnum
|
||||
from core.plugin import Plugin
|
||||
from core.services.task.models import Task as TaskUser, TaskStatusEnum
|
||||
from core.services.task.services import TaskResinServices, TaskExpeditionServices
|
||||
from plugins.tools.genshin import GenshinHelper, PlayerNotFoundError, CookiesNotFoundError
|
||||
from utils.log import logger
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from simnet import StarRailClient
|
||||
from telegram.ext import ContextTypes
|
||||
|
||||
|
||||
class TaskDataBase(BaseModel):
|
||||
noticed: Optional[bool] = False
|
||||
|
||||
|
||||
class ResinData(TaskDataBase):
|
||||
notice_num: Optional[int] = 140
|
||||
|
||||
@validator("notice_num")
|
||||
def notice_num_validator(cls, v):
|
||||
if v < 100 or v > 180:
|
||||
raise ValueError("开拓力提醒数值必须在 100 ~ 180 之间")
|
||||
return v
|
||||
|
||||
|
||||
class ExpeditionData(TaskDataBase):
|
||||
pass
|
||||
|
||||
|
||||
class WebAppData(BaseModel):
|
||||
resin: Optional[ResinData]
|
||||
expedition: Optional[ExpeditionData]
|
||||
|
||||
|
||||
class DailyNoteTaskUser:
|
||||
def __init__(
|
||||
self,
|
||||
user_id: int,
|
||||
resin_db: Optional[TaskUser] = None,
|
||||
expedition_db: Optional[TaskUser] = None,
|
||||
):
|
||||
self.user_id = user_id
|
||||
self.resin_db = resin_db
|
||||
self.expedition_db = expedition_db
|
||||
self.resin = ResinData(**self.resin_db.data) if self.resin_db else None
|
||||
self.expedition = ExpeditionData(**self.expedition_db.data) if self.expedition_db else None
|
||||
|
||||
@property
|
||||
def status(self) -> TaskStatusEnum:
|
||||
return max(
|
||||
[
|
||||
self.resin_db.status if self.resin_db else TaskStatusEnum.STATUS_SUCCESS,
|
||||
self.expedition_db.status if self.expedition_db else TaskStatusEnum.STATUS_SUCCESS,
|
||||
]
|
||||
)
|
||||
|
||||
@status.setter
|
||||
def status(self, value: TaskStatusEnum):
|
||||
if self.resin_db:
|
||||
self.resin_db.status = value
|
||||
if self.expedition_db:
|
||||
self.expedition_db.status = value
|
||||
|
||||
@staticmethod
|
||||
def js_bool(value: bool) -> str:
|
||||
return "true" if value else "false"
|
||||
|
||||
@staticmethod
|
||||
def set_model_noticed(model: TaskDataBase):
|
||||
data = model.copy(deep=True)
|
||||
data.noticed = True
|
||||
return data
|
||||
|
||||
@property
|
||||
def web_config(self) -> str:
|
||||
return base64.b64encode(
|
||||
(
|
||||
WebAppData(
|
||||
resin=self.set_model_noticed(self.resin) if self.resin else None,
|
||||
expedition=self.set_model_noticed(self.expedition) if self.expedition else None,
|
||||
).json()
|
||||
).encode()
|
||||
).decode()
|
||||
|
||||
def save(self):
|
||||
if self.resin_db:
|
||||
self.resin_db.data = self.resin.dict()
|
||||
if self.expedition_db:
|
||||
self.expedition_db.data = self.expedition.dict()
|
||||
|
||||
|
||||
class DailyNoteSystem(Plugin):
|
||||
def __init__(
|
||||
self,
|
||||
genshin_helper: GenshinHelper,
|
||||
resin_service: TaskResinServices,
|
||||
expedition_service: TaskExpeditionServices,
|
||||
):
|
||||
self.genshin_helper = genshin_helper
|
||||
self.resin_service = resin_service
|
||||
self.expedition_service = expedition_service
|
||||
|
||||
async def get_single_task_user(self, user_id: int) -> DailyNoteTaskUser:
|
||||
resin_db = await self.resin_service.get_by_user_id(user_id)
|
||||
expedition_db = await self.expedition_service.get_by_user_id(user_id)
|
||||
return DailyNoteTaskUser(
|
||||
user_id=user_id,
|
||||
resin_db=resin_db,
|
||||
expedition_db=expedition_db,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
async def start_get_notes(
|
||||
client: "StarRailClient",
|
||||
user: DailyNoteTaskUser = None,
|
||||
) -> List[str]:
|
||||
if client.region == RegionEnum.HOYOLAB:
|
||||
notes = await client.get_starrail_notes()
|
||||
else:
|
||||
notes = await client.get_starrail_notes_by_stoken()
|
||||
if not user:
|
||||
return []
|
||||
notices = []
|
||||
notice = None
|
||||
if user.resin_db and notes.max_stamina > 0:
|
||||
if notes.current_stamina >= user.resin.notice_num:
|
||||
if not user.resin.noticed:
|
||||
rec_time = datetime.now().astimezone() + notes.stamina_recover_time
|
||||
notice = (
|
||||
f"### 开拓力提示 ####\n\n当前开拓力为 {notes.current_stamina} / {notes.max_stamina} ,记得使用哦~\n"
|
||||
f"预计全部恢复完成:{rec_time.strftime('%Y-%m-%d %H:%M')}"
|
||||
)
|
||||
user.resin.noticed = True
|
||||
else:
|
||||
user.resin.noticed = False
|
||||
notices.append(notice)
|
||||
notice = None
|
||||
if user.expedition_db and len(notes.expeditions) > 0:
|
||||
all_finished = all(i.status == "Finished" for i in notes.expeditions)
|
||||
if all_finished:
|
||||
if not user.expedition.noticed:
|
||||
notice = "### 探索派遣提示 ####\n\n所有探索派遣已完成,记得重新派遣哦~"
|
||||
user.expedition.noticed = True
|
||||
else:
|
||||
user.expedition.noticed = False
|
||||
notices.append(notice)
|
||||
user.save()
|
||||
return notices
|
||||
|
||||
async def get_all_task_users(self) -> List[DailyNoteTaskUser]:
|
||||
resin_list = await self.resin_service.get_all()
|
||||
expedition_list = await self.expedition_service.get_all()
|
||||
user_list = set()
|
||||
for i in resin_list:
|
||||
user_list.add(i.user_id)
|
||||
for i in expedition_list:
|
||||
user_list.add(i.user_id)
|
||||
return [
|
||||
DailyNoteTaskUser(
|
||||
user_id=i,
|
||||
resin_db=next((x for x in resin_list if x.user_id == i), None),
|
||||
expedition_db=next((x for x in expedition_list if x.user_id == i), None),
|
||||
)
|
||||
for i in user_list
|
||||
]
|
||||
|
||||
async def remove_task_user(self, user: DailyNoteTaskUser):
|
||||
if user.resin_db:
|
||||
await self.resin_service.remove(user.resin_db)
|
||||
if user.expedition_db:
|
||||
await self.expedition_service.remove(user.expedition_db)
|
||||
|
||||
async def update_task_user(self, user: DailyNoteTaskUser):
|
||||
if user.resin_db:
|
||||
await self.resin_service.update(user.resin_db)
|
||||
if user.expedition_db:
|
||||
await self.expedition_service.update(user.expedition_db)
|
||||
|
||||
@staticmethod
|
||||
async def check_need_note(web_config: WebAppData) -> bool:
|
||||
need_verify = False
|
||||
if web_config.resin and web_config.resin.noticed:
|
||||
need_verify = True
|
||||
if web_config.expedition and web_config.expedition.noticed:
|
||||
need_verify = True
|
||||
return need_verify
|
||||
|
||||
async def import_web_config(self, user_id: int, web_config: WebAppData):
|
||||
user = await self.get_single_task_user(user_id)
|
||||
if web_config.resin:
|
||||
if web_config.resin.noticed:
|
||||
if not user.resin_db:
|
||||
resin = self.resin_service.create(
|
||||
user_id,
|
||||
user_id,
|
||||
status=TaskStatusEnum.STATUS_SUCCESS,
|
||||
data=ResinData(notice_num=web_config.resin.notice_num).dict(),
|
||||
)
|
||||
await self.resin_service.add(resin)
|
||||
else:
|
||||
user.resin.notice_num = web_config.resin.notice_num
|
||||
user.resin.noticed = False
|
||||
else:
|
||||
if user.resin_db:
|
||||
await self.resin_service.remove(user.resin_db)
|
||||
user.resin_db = None
|
||||
user.resin = None
|
||||
if web_config.expedition:
|
||||
if web_config.expedition.noticed:
|
||||
if not user.expedition_db:
|
||||
expedition = self.expedition_service.create(
|
||||
user_id,
|
||||
user_id,
|
||||
status=TaskStatusEnum.STATUS_SUCCESS,
|
||||
data=ExpeditionData().dict(),
|
||||
)
|
||||
await self.expedition_service.add(expedition)
|
||||
else:
|
||||
user.expedition.noticed = False
|
||||
else:
|
||||
if user.expedition_db:
|
||||
await self.expedition_service.remove(user.expedition_db)
|
||||
user.expedition_db = None
|
||||
user.expedition = None
|
||||
user.save()
|
||||
await self.update_task_user(user)
|
||||
|
||||
async def do_get_notes_job(self, context: "ContextTypes.DEFAULT_TYPE"):
|
||||
include_status: List[TaskStatusEnum] = [
|
||||
TaskStatusEnum.STATUS_SUCCESS,
|
||||
TaskStatusEnum.TIMEOUT_ERROR,
|
||||
]
|
||||
task_list = await self.get_all_task_users()
|
||||
for task_db in task_list:
|
||||
if task_db.status not in include_status:
|
||||
continue
|
||||
user_id = task_db.user_id
|
||||
try:
|
||||
async with self.genshin_helper.genshin(user_id) as client:
|
||||
text = await self.start_get_notes(client, task_db)
|
||||
if all(not i for i in text):
|
||||
continue
|
||||
except InvalidCookies:
|
||||
text = "自动便签提醒执行失败,Cookie无效"
|
||||
task_db.status = TaskStatusEnum.INVALID_COOKIES
|
||||
except SimnetBadRequest as exc:
|
||||
text = f"自动便签提醒执行失败,API返回信息为 {str(exc)}"
|
||||
task_db.status = TaskStatusEnum.GENSHIN_EXCEPTION
|
||||
except SimnetTimedOut:
|
||||
text = "便签获取失败了呜呜呜 ~ 服务器连接超时 服务器熟啦 ~ "
|
||||
task_db.status = TaskStatusEnum.TIMEOUT_ERROR
|
||||
except PlayerNotFoundError:
|
||||
logger.info("用户 user_id[%s] 玩家不存在 关闭并移除自动便签提醒", user_id)
|
||||
await self.remove_task_user(task_db)
|
||||
continue
|
||||
except CookiesNotFoundError:
|
||||
logger.info("用户 user_id[%s] cookie 不存在 关闭并移除自动便签提醒", user_id)
|
||||
await self.remove_task_user(task_db)
|
||||
continue
|
||||
except Exception as exc:
|
||||
logger.error("执行自动便签提醒时发生错误 user_id[%s]", user_id, exc_info=exc)
|
||||
text = "获取便签失败了呜呜呜 ~ 执行自动便签提醒时发生错误"
|
||||
else:
|
||||
task_db.status = TaskStatusEnum.STATUS_SUCCESS
|
||||
for idx, task_user_db in enumerate([task_db.resin_db, task_db.expedition_db]):
|
||||
if task_user_db is None:
|
||||
continue
|
||||
notice_text = text[idx] if isinstance(text, list) else text
|
||||
if not notice_text:
|
||||
continue
|
||||
if task_user_db.chat_id < 0:
|
||||
notice_text = (
|
||||
f'<a href="tg://user?id={task_user_db.user_id}">'
|
||||
f"NOTICE {task_user_db.user_id}</a>\n\n{notice_text}"
|
||||
)
|
||||
try:
|
||||
await context.bot.send_message(task_user_db.chat_id, notice_text, parse_mode=ParseMode.HTML)
|
||||
except BadRequest as exc:
|
||||
logger.error("执行自动便签提醒时发生错误 user_id[%s] Message[%s]", user_id, exc.message)
|
||||
task_user_db.status = TaskStatusEnum.BAD_REQUEST
|
||||
except Forbidden as exc:
|
||||
logger.error("执行自动便签提醒时发生错误 user_id[%s] message[%s]", user_id, exc.message)
|
||||
task_user_db.status = TaskStatusEnum.FORBIDDEN
|
||||
except Exception as exc:
|
||||
logger.error("执行自动便签提醒时发生错误 user_id[%s]", user_id, exc_info=exc)
|
||||
continue
|
||||
else:
|
||||
task_user_db.status = TaskStatusEnum.STATUS_SUCCESS
|
||||
await self.update_task_user(task_db)
|
@ -17,8 +17,8 @@ from core.config import config
|
||||
from core.dependence.redisdb import RedisDB
|
||||
from core.plugin import Plugin
|
||||
from core.services.cookies import CookiesService
|
||||
from core.services.sign.models import SignStatusEnum
|
||||
from core.services.sign.services import SignServices
|
||||
from core.services.task.models import TaskStatusEnum
|
||||
from core.services.task.services import SignServices
|
||||
from core.services.users.services import UserService
|
||||
from modules.apihelper.client.components.verify import Verify
|
||||
from plugins.tools.genshin import PlayerNotFoundError, CookiesNotFoundError, GenshinHelper
|
||||
@ -269,16 +269,16 @@ class SignSystem(Plugin):
|
||||
return message
|
||||
|
||||
async def do_sign_job(self, context: "ContextTypes.DEFAULT_TYPE", job_type: SignJobType):
|
||||
include_status: List[SignStatusEnum] = [
|
||||
SignStatusEnum.STATUS_SUCCESS,
|
||||
SignStatusEnum.TIMEOUT_ERROR,
|
||||
SignStatusEnum.NEED_CHALLENGE,
|
||||
include_status: List[TaskStatusEnum] = [
|
||||
TaskStatusEnum.STATUS_SUCCESS,
|
||||
TaskStatusEnum.TIMEOUT_ERROR,
|
||||
TaskStatusEnum.NEED_CHALLENGE,
|
||||
]
|
||||
if job_type == SignJobType.START:
|
||||
title = "自动签到"
|
||||
elif job_type == SignJobType.REDO:
|
||||
title = "自动重新签到"
|
||||
include_status.remove(SignStatusEnum.STATUS_SUCCESS)
|
||||
include_status.remove(TaskStatusEnum.STATUS_SUCCESS)
|
||||
else:
|
||||
raise ValueError
|
||||
sign_list = await self.sign_service.get_all()
|
||||
@ -291,19 +291,19 @@ class SignSystem(Plugin):
|
||||
text = await self.start_sign(client, is_sleep=True, is_raise=True, title=title)
|
||||
except InvalidCookies:
|
||||
text = "自动签到执行失败,Cookie无效"
|
||||
sign_db.status = SignStatusEnum.INVALID_COOKIES
|
||||
sign_db.status = TaskStatusEnum.INVALID_COOKIES
|
||||
except AlreadyClaimed:
|
||||
text = "今天开拓者已经签到过了~"
|
||||
sign_db.status = SignStatusEnum.ALREADY_CLAIMED
|
||||
sign_db.status = TaskStatusEnum.ALREADY_CLAIMED
|
||||
except SimnetBadRequest as exc:
|
||||
text = f"自动签到执行失败,API返回信息为 {str(exc)}"
|
||||
sign_db.status = SignStatusEnum.GENSHIN_EXCEPTION
|
||||
sign_db.status = TaskStatusEnum.GENSHIN_EXCEPTION
|
||||
except SimnetTimedOut:
|
||||
text = "签到失败了呜呜呜 ~ 服务器连接超时 服务器熟啦 ~ "
|
||||
sign_db.status = SignStatusEnum.TIMEOUT_ERROR
|
||||
sign_db.status = TaskStatusEnum.TIMEOUT_ERROR
|
||||
except NeedChallenge:
|
||||
text = "签到失败,触发验证码风控"
|
||||
sign_db.status = SignStatusEnum.NEED_CHALLENGE
|
||||
sign_db.status = TaskStatusEnum.NEED_CHALLENGE
|
||||
except PlayerNotFoundError:
|
||||
logger.info("用户 user_id[%s] 玩家不存在 关闭并移除自动签到", user_id)
|
||||
await self.sign_service.remove(sign_db)
|
||||
@ -316,21 +316,20 @@ class SignSystem(Plugin):
|
||||
logger.error("执行自动签到时发生错误 user_id[%s]", user_id, exc_info=exc)
|
||||
text = "签到失败了呜呜呜 ~ 执行自动签到时发生错误"
|
||||
else:
|
||||
sign_db.status = SignStatusEnum.STATUS_SUCCESS
|
||||
sign_db.status = TaskStatusEnum.STATUS_SUCCESS
|
||||
if sign_db.chat_id < 0:
|
||||
text = f'<a href="tg://user?id={sign_db.user_id}">NOTICE {sign_db.user_id}</a>\n\n{text}'
|
||||
try:
|
||||
await context.bot.send_message(sign_db.chat_id, text, parse_mode=ParseMode.HTML)
|
||||
except BadRequest as exc:
|
||||
logger.error("执行自动签到时发生错误 user_id[%s] Message[%s]", user_id, exc.message)
|
||||
sign_db.status = SignStatusEnum.BAD_REQUEST
|
||||
sign_db.status = TaskStatusEnum.BAD_REQUEST
|
||||
except Forbidden as exc:
|
||||
logger.error("执行自动签到时发生错误 user_id[%s] message[%s]", user_id, exc.message)
|
||||
sign_db.status = SignStatusEnum.FORBIDDEN
|
||||
sign_db.status = TaskStatusEnum.FORBIDDEN
|
||||
except Exception as exc:
|
||||
logger.error("执行自动签到时发生错误 user_id[%s]", user_id, exc_info=exc)
|
||||
continue
|
||||
else:
|
||||
sign_db.status = SignStatusEnum.STATUS_SUCCESS
|
||||
sign_db.time_updated = datetime.datetime.now()
|
||||
sign_db.status = TaskStatusEnum.STATUS_SUCCESS
|
||||
await self.sign_service.update(sign_db)
|
||||
|
Loading…
Reference in New Issue
Block a user