support task services

This commit is contained in:
omg-xtao 2023-07-23 23:46:11 +08:00 committed by GitHub
parent 3be61dc5b4
commit 29efa649a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 1183 additions and 171 deletions

View 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 ###

View File

@ -1 +0,0 @@
"""SignService"""

View File

@ -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)

View File

@ -0,0 +1 @@
"""TaskService"""

View File

@ -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))

View File

@ -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()

View File

@ -0,0 +1,213 @@
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",
"TaskRealmServices",
"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 TaskRealmServices(BaseService):
TASK_TYPE = TaskTypeEnum.REALM
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,
)

View File

@ -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)

View File

@ -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

View File

@ -1,41 +1,33 @@
import re
from datetime import datetime
from typing import List, Optional, TYPE_CHECKING
from typing import TYPE_CHECKING
from simnet.client.routes import Route
from simnet.errors import BadRequest as SimnetBadRequest
from simnet.utils.player import recognize_genshin_server, recognize_genshin_game_biz
from simnet import Region
from simnet.errors import RegionNotSupported
from telegram import InlineKeyboardMarkup, InlineKeyboardButton
from telegram.constants import ParseMode
from telegram.ext import filters, MessageHandler, CommandHandler
from telegram.helpers import create_deep_linked_url
from core.basemodel import RegionEnum
from core.plugin import Plugin, handler
from core.services.cookies import CookiesService
from core.services.users.services import UserService
from core.services.task.models import Task as TaskUser, TaskStatusEnum
from core.services.task.services import TaskCardServices
from core.services.users.services import UserService, UserAdminService
from metadata.genshin import AVATAR_DATA
from metadata.shortname import roleToId, roleToName
from modules.apihelper.client.components.calendar import Calendar
from plugins.tools.birthday_card import (
BirthdayCardSystem,
rm_starting_str,
BirthdayCardNoBirthdayError,
BirthdayCardAlreadyClaimedError,
)
from plugins.tools.genshin import PlayerNotFoundError, CookiesNotFoundError, GenshinHelper
from utils.log import logger
if TYPE_CHECKING:
from simnet import GenshinClient
from telegram import Update
from telegram.ext import ContextTypes
BIRTHDAY_URL = Route(
"https://hk4e-api.mihoyo.com/event/birthdaystar/account/post_my_draw",
)
def rm_starting_str(string, starting):
"""Remove the starting character from a string."""
while string[0] == str(starting):
string = string[1:]
return string
class BirthdayPlugin(Plugin):
"""Birthday."""
@ -45,36 +37,23 @@ class BirthdayPlugin(Plugin):
user_service: UserService,
helper: GenshinHelper,
cookie_service: CookiesService,
card_system: BirthdayCardSystem,
user_admin_service: UserAdminService,
card_service: TaskCardServices,
):
"""Load Data."""
self.birthday_list = {}
self.user_service = user_service
self.cookie_service = cookie_service
self.helper = helper
async def initialize(self):
self.birthday_list = await Calendar.async_gen_birthday_list()
self.birthday_list.get("6_1", []).append("派蒙")
async def get_today_birthday(self) -> List[str]:
key = (
rm_starting_str(datetime.now().strftime("%m"), "0")
+ "_"
+ rm_starting_str(datetime.now().strftime("%d"), "0")
)
return (self.birthday_list.get(key, [])).copy()
self.card_system = card_system
self.user_admin_service = user_admin_service
self.card_service = card_service
@handler.command(command="birthday", block=False)
async def command_start(self, update: "Update", context: "ContextTypes.DEFAULT_TYPE") -> None:
message = update.effective_message
user = update.effective_user
key = (
rm_starting_str(datetime.now().strftime("%m"), "0")
+ "_"
+ rm_starting_str(datetime.now().strftime("%d"), "0")
)
args = self.get_args(context)
if len(args) >= 1:
msg = args[0]
logger.info("用户 %s[%s] 查询角色生日命令请求 || 参数 %s", user.full_name, user.id, msg)
@ -83,7 +62,7 @@ class BirthdayPlugin(Plugin):
month = rm_starting_str(re.findall(r"\d+", msg)[0], "0")
day = rm_starting_str(re.findall(r"\d+", msg)[1], "0")
key = f"{month}_{day}"
day_list = self.birthday_list.get(key, [])
day_list = self.card_system.birthday_list.get(key, [])
date = f"{month}{day}"
text = f"{date}{''.join(day_list)} 的生日哦~" if day_list else f"{date} 没有角色过生日哦~"
except IndexError:
@ -102,13 +81,11 @@ class BirthdayPlugin(Plugin):
birthday = AVATAR_DATA[aid]["birthday"]
text = f"{name} 的生日是 {birthday[0]}{birthday[1]}日 哦~"
reply_message = await message.reply_text(text)
except KeyError:
reply_message = await message.reply_text("请输入正确的日期格式如1-1或输入正确的角色名称。")
else:
logger.info("用户 %s[%s] 查询今日角色生日列表", user.full_name, user.id)
today_list = await self.get_today_birthday()
today_list = self.card_system.get_today_birthday()
text = f"今天是 {''.join(today_list)} 的生日哦~" if today_list else "今天没有角色过生日哦~"
reply_message = await message.reply_text(text)
@ -116,60 +93,65 @@ class BirthdayPlugin(Plugin):
self.add_delete_message_job(message)
self.add_delete_message_job(reply_message)
@staticmethod
async def get_card(client: "GenshinClient", role_id: int) -> None:
"""领取画片"""
url = BIRTHDAY_URL.get_url()
params = {
"game_biz": recognize_genshin_game_biz(client.player_id),
"lang": "zh-cn",
"badge_uid": client.player_id,
"badge_region": recognize_genshin_server(client.player_id),
"activity_id": "20220301153521",
}
json = {
"role_id": role_id,
}
await client.request_lab(url, method="POST", params=params, data=json)
@staticmethod
def role_to_id(name: str) -> Optional[int]:
if name == "派蒙":
return -1
return roleToId(name)
async def _process_auto_birthday_card(self, user_id: int, chat_id: int, method: str) -> str:
try:
async with self.helper.genshin(user_id) as client:
if client.region != Region.CHINESE:
return "此功能当前只支持国服账号哦~"
except (PlayerNotFoundError, CookiesNotFoundError):
return "未查询到账号信息,请先私聊派蒙绑定账号"
user: TaskUser = await self.card_service.get_by_user_id(user_id)
if user:
if method == "关闭":
await self.card_service.remove(user)
return "关闭自动领取生日画片成功"
if method == "开启":
if user.chat_id == chat_id:
return "自动领取生日画片已经开启过了"
user.chat_id = chat_id
user.status = TaskStatusEnum.STATUS_SUCCESS
await self.card_service.update(user)
return "修改自动领取生日画片对话成功"
elif method == "关闭":
return "您还没有开启自动领取生日画片"
elif method == "开启":
user = self.card_service.create(user_id, chat_id, TaskStatusEnum.STATUS_SUCCESS)
await self.card_service.add(user)
return "开启自动领取生日画片成功"
@handler(CommandHandler, command="birthday_card", block=False)
@handler(MessageHandler, filters=filters.Regex("^领取角色生日画片$"), block=False)
async def command_birthday_card_start(self, update: "Update", context: "ContextTypes.DEFAULT_TYPE") -> None:
message = update.effective_message
user = update.effective_user
args = self.get_args(context)
if len(args) >= 1:
msg = None
if args[0] == "开启自动领取":
if await self.user_admin_service.is_admin(user.id):
msg = await self._process_auto_birthday_card(user.id, message.chat_id, "开启")
else:
msg = await self._process_auto_birthday_card(user.id, user.id, "开启")
elif args[0] == "关闭自动领取":
msg = await self._process_auto_birthday_card(user.id, message.chat_id, "关闭")
if msg:
logger.info("用户 %s[%s] 自动领取生日画片命令请求 || 参数 %s", user.full_name, user.id, args[0])
reply_message = await message.reply_text(msg)
if filters.ChatType.GROUPS.filter(message):
self.add_delete_message_job(reply_message, delay=30)
self.add_delete_message_job(message, delay=30)
return
logger.info("用户 %s[%s] 领取生日画片命令请求", user.full_name, user.id)
today_list = await self.get_today_birthday()
if not today_list:
reply_message = await message.reply_text("今天没有角色过生日哦~")
if filters.ChatType.GROUPS.filter(reply_message):
self.add_delete_message_job(message)
self.add_delete_message_job(reply_message)
return
try:
async with self.helper.genshin(user.id) as client:
if client.region == RegionEnum.HOYOLAB:
try:
text = await self.card_system.start_get_card(client)
except RegionNotSupported:
text = "此功能当前只支持国服账号哦~"
else:
game_biz = recognize_genshin_game_biz(client.player_id)
region = recognize_genshin_server(client.player_id)
await client.get_hk4e_token_by_cookie_token(game_biz, region)
for name in today_list.copy():
if role_id := self.role_to_id(name):
try:
await self.get_card(client, role_id)
except SimnetBadRequest as e:
if e.ret_code in {-512008, -512009}: # 未过生日、已领取过
today_list.remove(name)
if today_list:
text = f"成功领取了 {''.join(today_list)} 的生日画片~"
else:
text = "没有领取到生日画片哦 ~ 可能是已经领取过了"
except BirthdayCardNoBirthdayError:
text = "今天没有角色过生日哦~"
except BirthdayCardAlreadyClaimedError:
text = "没有领取到生日画片哦 ~ 可能是已经领取过了"
reply_message = await message.reply_text(text)
if filters.ChatType.GROUPS.filter(reply_message):
self.add_delete_message_job(message)

View File

@ -0,0 +1,124 @@
from pydantic import ValidationError
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
__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}/tasks1?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: "GenshinClient"
if request_note:
if client.region == Region.CHINESE:
await client.get_genshin_notes_by_stoken()
else:
await client.get_genshin_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
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 ~ 160 之间\n" "洞天宝钱提醒数值必须在 100 ~ 2400 之间",
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

View File

@ -1,4 +1,3 @@
import datetime
from typing import Optional, Tuple
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
@ -12,8 +11,8 @@ from core.handler.callbackqueryhandler import CallbackQueryHandler
from core.plugin import Plugin, handler
from core.services.cookies import CookiesService
from core.services.players import PlayersService
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 PlayerNotFoundError, CookiesNotFoundError, GenshinHelper
from plugins.tools.sign import SignSystem, NeedChallenge
@ -57,18 +56,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 "开启自动签到成功"

View File

@ -0,0 +1,20 @@
import datetime
from typing import TYPE_CHECKING
from core.plugin import Plugin, job
from plugins.tools.birthday_card import BirthdayCardSystem
from utils.log import logger
if TYPE_CHECKING:
from telegram.ext import ContextTypes
class CardJob(Plugin):
def __init__(self, card_system: BirthdayCardSystem):
self.card_system = card_system
@job.run_daily(time=datetime.time(hour=0, minute=1, second=0), name="CardJob")
async def card(self, context: "ContextTypes.DEFAULT_TYPE"):
logger.info("正在执行自动领取生日画片")
await self.card_system.do_get_card_job(context)
logger.success("执行自动领取生日画片完成")

View 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("执行自动便签提醒完成")

View File

@ -0,0 +1,182 @@
from datetime import datetime
from typing import TYPE_CHECKING, List, Optional
from simnet.errors import BadRequest as SimnetBadRequest, RegionNotSupported, InvalidCookies, TimedOut as SimnetTimedOut
from simnet.client.routes import Route
from simnet.utils.player import recognize_genshin_game_biz, recognize_genshin_server
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 TaskStatusEnum
from core.services.task.services import TaskCardServices
from metadata.shortname import roleToId
from modules.apihelper.client.components.calendar import Calendar
from plugins.tools.genshin import GenshinHelper, PlayerNotFoundError, CookiesNotFoundError
from utils.log import logger
if TYPE_CHECKING:
from simnet import GenshinClient
from telegram.ext import ContextTypes
BIRTHDAY_URL = Route(
"https://hk4e-api.mihoyo.com/event/birthdaystar/account/post_my_draw",
)
def rm_starting_str(string, starting):
"""Remove the starting character from a string."""
while string[0] == str(starting):
string = string[1:]
return string
class BirthdayCardNoBirthdayError(Exception):
pass
class BirthdayCardAlreadyClaimedError(Exception):
pass
class BirthdayCardSystem(Plugin):
def __init__(
self,
card_service: TaskCardServices,
genshin_helper: GenshinHelper,
):
self.birthday_list = {}
self.card_service = card_service
self.genshin_helper = genshin_helper
async def initialize(self):
self.birthday_list = await Calendar.async_gen_birthday_list()
self.birthday_list.get("6_1", []).append("派蒙")
@property
def key(self):
return (
rm_starting_str(datetime.now().strftime("%m"), "0")
+ "_"
+ rm_starting_str(datetime.now().strftime("%d"), "0")
)
def get_today_birthday(self) -> List[str]:
key = self.key
return (self.birthday_list.get(key, [])).copy()
@staticmethod
def role_to_id(name: str) -> Optional[int]:
if name == "派蒙":
return -1
return roleToId(name)
@staticmethod
async def get_card(client: "GenshinClient", role_id: int) -> None:
"""领取画片"""
url = BIRTHDAY_URL.get_url()
params = {
"game_biz": recognize_genshin_game_biz(client.player_id),
"lang": "zh-cn",
"badge_uid": client.player_id,
"badge_region": recognize_genshin_server(client.player_id),
"activity_id": "20220301153521",
}
json = {
"role_id": role_id,
}
try:
await client.request_lab(url, method="POST", params=params, data=json)
except SimnetBadRequest as e:
if e.retcode == -512008:
raise BirthdayCardNoBirthdayError from e # 未过生日
if e.retcode == -512009:
raise BirthdayCardAlreadyClaimedError from e # 已领取过
raise e
async def start_get_card(
self,
client: "GenshinClient",
) -> str:
if client.region == RegionEnum.HOYOLAB:
raise RegionNotSupported
today_list = self.get_today_birthday()
if not today_list:
raise BirthdayCardNoBirthdayError
game_biz = recognize_genshin_game_biz(client.player_id)
region = recognize_genshin_server(client.player_id)
await client.get_hk4e_token_by_cookie_token(game_biz, region)
for name in today_list.copy():
if role_id := self.role_to_id(name):
try:
await self.get_card(client, role_id)
except BirthdayCardAlreadyClaimedError:
today_list.remove(name)
if today_list:
text = f"成功领取了 {''.join(today_list)} 的生日画片~"
else:
raise BirthdayCardAlreadyClaimedError
return text
async def do_get_card_job(self, context: "ContextTypes.DEFAULT_TYPE"):
if not self.get_today_birthday():
logger.info("今天没有角色过生日,跳过自动领取生日画片")
return
include_status: List[TaskStatusEnum] = [
TaskStatusEnum.STATUS_SUCCESS,
TaskStatusEnum.TIMEOUT_ERROR,
]
task_list = await self.card_service.get_all()
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_card(client)
except InvalidCookies:
text = "自动领取生日画片执行失败Cookie无效"
task_db.status = TaskStatusEnum.INVALID_COOKIES
except BirthdayCardAlreadyClaimedError:
text = "今天旅行者已经领取过了~"
task_db.status = TaskStatusEnum.ALREADY_CLAIMED
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.card_service.remove(task_db)
continue
except CookiesNotFoundError:
logger.info("用户 user_id[%s] cookie 不存在 关闭并移除自动领取生日画片", user_id)
await self.card_service.remove(task_db)
continue
except RegionNotSupported:
logger.info("用户 user_id[%s] 不支持的服务器 关闭并移除自动领取生日画片", user_id)
await self.card_service.remove(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
if task_db.chat_id < 0:
text = f'<a href="tg://user?id={task_db.user_id}">NOTICE {task_db.user_id}</a>\n\n{text}'
try:
await context.bot.send_message(task_db.chat_id, text, parse_mode=ParseMode.HTML)
except BadRequest as exc:
logger.error("执行自动领取生日画片时发生错误 user_id[%s] Message[%s]", user_id, exc.message)
task_db.status = TaskStatusEnum.BAD_REQUEST
except Forbidden as exc:
logger.error("执行自动领取生日画片时发生错误 user_id[%s] message[%s]", user_id, exc.message)
task_db.status = TaskStatusEnum.FORBIDDEN
except Exception as exc:
logger.error("执行自动领取生日画片时发生错误 user_id[%s]", user_id, exc_info=exc)
continue
else:
task_db.status = TaskStatusEnum.STATUS_SUCCESS
await self.card_service.update(task_db)

361
plugins/tools/daily_note.py Normal file
View File

@ -0,0 +1,361 @@
import base64
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, TaskRealmServices, TaskExpeditionServices
from plugins.tools.genshin import GenshinHelper, PlayerNotFoundError, CookiesNotFoundError
from utils.log import logger
if TYPE_CHECKING:
from simnet import GenshinClient
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 > 160:
raise ValueError("树脂提醒数值必须在 100 ~ 160 之间")
return v
class RealmData(TaskDataBase):
notice_num: Optional[int] = 2000
@validator("notice_num")
def notice_num_validator(cls, v):
if v < 100 or v > 2400:
raise ValueError("洞天宝钱提醒数值必须在 100 ~ 2400 之间")
return v
class ExpeditionData(TaskDataBase):
pass
class WebAppData(BaseModel):
resin: Optional[ResinData]
realm: Optional[RealmData]
expedition: Optional[ExpeditionData]
class DailyNoteTaskUser:
def __init__(
self,
user_id: int,
resin_db: Optional[TaskUser] = None,
realm_db: Optional[TaskUser] = None,
expedition_db: Optional[TaskUser] = None,
):
self.user_id = user_id
self.resin_db = resin_db
self.realm_db = realm_db
self.expedition_db = expedition_db
self.resin = ResinData(**self.resin_db.data) if self.resin_db else None
self.realm = RealmData(**self.realm_db.data) if self.realm_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.realm_db.status if self.realm_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.realm_db:
self.realm_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,
realm=self.set_model_noticed(self.realm) if self.realm 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.realm_db:
self.realm_db.data = self.realm.dict()
if self.expedition_db:
self.expedition_db.data = self.expedition.dict()
class DailyNoteSystem(Plugin):
def __init__(
self,
genshin_helper: GenshinHelper,
resin_service: TaskResinServices,
realm_service: TaskRealmServices,
expedition_service: TaskExpeditionServices,
):
self.genshin_helper = genshin_helper
self.resin_service = resin_service
self.realm_service = realm_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)
realm_db = await self.realm_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,
realm_db=realm_db,
expedition_db=expedition_db,
)
@staticmethod
async def start_get_notes(
client: "GenshinClient",
user: DailyNoteTaskUser = None,
) -> List[str]:
if client.region == RegionEnum.HOYOLAB:
notes = await client.get_genshin_notes()
else:
notes = await client.get_genshin_notes_by_stoken()
if not user:
return []
notices = []
notice = None
if user.resin_db and notes.max_resin > 0:
if notes.current_resin >= user.resin.notice_num:
if not user.resin.noticed:
notice = (
f"### 树脂提示 ####\n\n当前树脂为 {notes.current_resin} / {notes.max_resin} ,记得使用哦~\n"
f"预计全部恢复完成:{notes.resin_recovery_time.strftime('%Y-%m-%d %H:%M')}"
)
user.resin.noticed = True
else:
user.resin.noticed = False
notices.append(notice)
notice = None
if user.realm_db and notes.max_realm_currency > 0:
if notes.current_realm_currency >= user.realm.notice_num:
if not user.realm.noticed:
notice = (
f"### 洞天宝钱提示 ####\n\n"
f"当前存储为 {notes.current_realm_currency} / {notes.max_realm_currency} ,记得领取哦~"
)
user.realm.noticed = True
else:
user.realm.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()
realm_list = await self.realm_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 realm_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),
realm_db=next((x for x in realm_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.realm_db:
await self.realm_service.remove(user.realm_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.realm_db:
await self.realm_service.update(user.realm_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.realm and web_config.realm.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.realm:
if web_config.realm.noticed:
if not user.realm_db:
realm = self.realm_service.create(
user_id,
user_id,
status=TaskStatusEnum.STATUS_SUCCESS,
data=RealmData(notice_num=web_config.realm.notice_num).dict(),
)
await self.realm_service.add(realm)
else:
user.realm.notice_num = web_config.realm.notice_num
user.realm.noticed = False
else:
if user.realm_db:
await self.realm_service.remove(user.realm_db)
user.realm_db = None
user.realm = 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.realm_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)

View File

@ -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)