from typing import Optional, Tuple from telegram import Update from telegram.constants import ChatAction from telegram.ext import CallbackContext from telegram.ext import filters 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.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, PlayerNotFoundError, CookiesNotFoundError from plugins.tools.sign import SignSystem, NeedChallenge from utils.log import logger class Sign(Plugin): """每日签到""" CHECK_SERVER, COMMAND_RESULT = range(10400, 10402) def __init__( self, genshin_helper: GenshinHelper, sign_service: SignServices, user_admin_service: UserAdminService, sign_system: SignSystem, ): self.user_admin_service = user_admin_service self.sign_service = sign_service self.sign_system = sign_system self.genshin_helper = genshin_helper async def _process_auto_sign(self, user_id: int, player_id: int, offset: int, chat_id: int, method: str) -> str: try: c = await self.genshin_helper.get_genshin_client(user_id, player_id=player_id, offset=offset) player_id = c.player_id except (PlayerNotFoundError, CookiesNotFoundError): return config.notice.user_not_found user: SignUser = await self.sign_service.get_by_user_id(user_id, player_id) if user: if method == "关闭": await self.sign_service.remove(user) return f"UID {player_id} 关闭自动签到成功" if method == "开启": if user.chat_id == chat_id: return f"UID {player_id} 自动签到已经开启过了" user.chat_id = chat_id user.status = TaskStatusEnum.STATUS_SUCCESS await self.sign_service.update(user) return f"UID {player_id} 修改自动签到通知对话成功" elif method == "关闭": return f"UID {player_id} 您还没有开启自动签到" elif method == "开启": user = self.sign_service.create(user_id, player_id, chat_id, TaskStatusEnum.STATUS_SUCCESS) await self.sign_service.add(user) return f"UID {player_id} 开启自动签到成功" @handler.command(command="sign", cookie=True, block=False) @handler.message(filters=filters.Regex("^每日签到(.*)"), cookie=True, block=False) @handler.command(command="start", filters=filters.Regex("sign$"), block=False) async def command_start(self, update: Update, context: CallbackContext) -> None: user_id = await self.get_real_user_id(update) uid, offset = self.get_real_uid_or_offset(update) message = update.effective_message args = self.get_args(context) validate: Optional[str] = None if len(args) >= 1: msg = None if args[0] == "开启自动签到": if await self.user_admin_service.is_admin(user_id): msg = await self._process_auto_sign(user_id, uid, offset, message.chat_id, "开启") else: msg = await self._process_auto_sign(user_id, uid, offset, user_id, "开启") elif args[0] == "关闭自动签到": msg = await self._process_auto_sign(user_id, uid, offset, message.chat_id, "关闭") elif args[0] != "sign" and not args[0].startswith("@"): validate = args[0] if msg: self.log_user(update, logger.info, "自动签到命令请求 || 参数 %s", 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 self.log_user(update, logger.info, "每日签到命令请求") if filters.ChatType.GROUPS.filter(message): self.add_delete_message_job(message) try: async with self.genshin_helper.genshin(user_id, player_id=uid, offset=offset) as client: await message.reply_chat_action(ChatAction.TYPING) _, challenge = await self.sign_system.get_challenge(client.player_id) if validate: _, challenge = await self.sign_system.get_challenge(client.player_id) if challenge: sign_text = await self.sign_system.start_sign(client, challenge=challenge, validate=validate) else: reply_message = await message.reply_text("请求已经过期") if filters.ChatType.GROUPS.filter(reply_message): self.add_delete_message_job(reply_message) return else: sign_text = await self.sign_system.start_sign(client) reply_message = await message.reply_text(sign_text) if filters.ChatType.GROUPS.filter(reply_message): self.add_delete_message_job(reply_message) except NeedChallenge as exc: button = await self.sign_system.get_challenge_button( context.bot.username, exc.uid, user_id, exc.gt, exc.challenge, not filters.ChatType.PRIVATE.filter(message), ) reply_message = await message.reply_text( "签到失败,触发验证码风控,请尝试点击下方按钮重新签到", reply_markup=button, ) if filters.ChatType.GROUPS.filter(reply_message): self.add_delete_message_job(reply_message) @handler.command(command="start", filters=filters.Regex(r" challenge_sign_(.*)"), block=False) async def command_challenge(self, update: Update, context: CallbackContext) -> None: user = update.effective_user uid, offset = self.get_real_uid_or_offset(update) message = update.effective_message args = context.args _data = args[0].split("_") validate = _data[2] logger.info("用户 %s[%s] 通过start命令 进入签到流程", user.full_name, user.id) try: async with self.genshin_helper.genshin(user.id, player_id=uid, offset=offset) as client: await message.reply_chat_action(ChatAction.TYPING) _, challenge = await self.sign_system.get_challenge(client.player_id) if not challenge: await message.reply_text("验证请求已过期。") return sign_text = await self.sign_system.start_sign(client, challenge=challenge, validate=validate) await message.reply_text(sign_text) except NeedChallenge: await message.reply_text("回调错误,请重新签到") @handler(CallbackQueryHandler, pattern=r"^sign\|", block=False) async def sign_gen_link(self, update: Update, context: CallbackContext) -> None: callback_query = update.callback_query user = callback_query.from_user async def get_sign_callback(callback_query_data: str) -> Tuple[int, int]: _data = callback_query_data.split("|") _user_id = int(_data[1]) _uid = int(_data[2]) logger.debug("get_sign_callback 函数返回 user_id[%s] uid[%s]", _user_id, _uid) return _user_id, _uid user_id, uid = await get_sign_callback(callback_query.data) if user.id != user_id: await callback_query.answer(text="这不是你的按钮!\n" + config.notice.user_mismatch, show_alert=True) return _, challenge = await self.sign_system.get_challenge(uid) if not challenge: await callback_query.answer(text="验证请求已经过期,请重新发起签到!", show_alert=True) return await callback_query.answer(url=create_deep_linked_url(context.bot.username, "sign"))