2022-11-20 15:38:05 +00:00
|
|
|
|
from typing import Optional
|
|
|
|
|
|
2022-11-20 11:32:56 +00:00
|
|
|
|
from genshin import Region, GenshinException
|
|
|
|
|
from pydantic import BaseModel
|
|
|
|
|
from telegram import ReplyKeyboardRemove, Update, WebAppInfo, ReplyKeyboardMarkup, KeyboardButton
|
|
|
|
|
from telegram.ext import CallbackContext, filters
|
|
|
|
|
|
|
|
|
|
from core.base.redisdb import RedisDB
|
|
|
|
|
from core.config import config
|
|
|
|
|
from core.cookies import CookiesService
|
|
|
|
|
from core.cookies.error import CookiesNotFoundError
|
|
|
|
|
from core.plugin import Plugin, handler
|
|
|
|
|
from core.user import UserService
|
|
|
|
|
from core.user.error import UserNotFoundError
|
2022-12-10 12:37:43 +00:00
|
|
|
|
from modules.apihelper.client.components.verify import Verify
|
2022-11-20 11:32:56 +00:00
|
|
|
|
from modules.apihelper.error import ResponseException
|
|
|
|
|
from plugins.genshin.verification import VerificationSystem
|
|
|
|
|
from utils.decorators.restricts import restricts
|
|
|
|
|
from utils.helpers import get_genshin_client
|
|
|
|
|
from utils.log import logger
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class WebAppData(BaseModel):
|
|
|
|
|
path: str
|
2022-11-20 15:38:05 +00:00
|
|
|
|
data: Optional[dict]
|
2022-11-20 11:32:56 +00:00
|
|
|
|
code: int
|
|
|
|
|
message: str
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class WebAppDataException(Exception):
|
|
|
|
|
def __init__(self, data):
|
|
|
|
|
self.data = data
|
|
|
|
|
super().__init__()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class WebApp(Plugin):
|
|
|
|
|
def __init__(self, user_service: UserService = None, cookies_service: CookiesService = None, redis: RedisDB = None):
|
|
|
|
|
self.cookies_service = cookies_service
|
|
|
|
|
self.user_service = user_service
|
|
|
|
|
self.verification_system = VerificationSystem(redis)
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def de_web_app_data(data: str) -> WebAppData:
|
|
|
|
|
try:
|
|
|
|
|
return WebAppData.parse_raw(data)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
raise WebAppDataException(data) from exc
|
|
|
|
|
|
|
|
|
|
@handler.message(filters=filters.StatusUpdate.WEB_APP_DATA, block=False)
|
|
|
|
|
@restricts()
|
|
|
|
|
async def app(self, update: Update, context: CallbackContext):
|
|
|
|
|
user = update.effective_user
|
|
|
|
|
message = update.effective_message
|
|
|
|
|
web_app_data = message.web_app_data
|
|
|
|
|
if web_app_data:
|
|
|
|
|
logger.info("用户 %s[%s] 触发 WEB_APP_DATA 请求", user.full_name, user.id)
|
|
|
|
|
result = self.de_web_app_data(web_app_data.data)
|
2022-11-23 01:11:29 +00:00
|
|
|
|
logger.debug(
|
|
|
|
|
"path[%s]\ndata[%s]\ncode[%s]\nmessage[%s]", result.path, result.data, result.code, result.message
|
|
|
|
|
)
|
2022-11-20 11:32:56 +00:00
|
|
|
|
if result.code == 0:
|
|
|
|
|
if result.path == "verify":
|
|
|
|
|
validate = result.data.get("geetest_validate")
|
|
|
|
|
try:
|
|
|
|
|
client = await get_genshin_client(user.id)
|
|
|
|
|
if client.region != Region.CHINESE:
|
|
|
|
|
await message.reply_text("非法用户", reply_markup=ReplyKeyboardRemove())
|
|
|
|
|
return
|
|
|
|
|
except UserNotFoundError:
|
|
|
|
|
await message.reply_text("用户未找到", reply_markup=ReplyKeyboardRemove())
|
|
|
|
|
return
|
|
|
|
|
except CookiesNotFoundError:
|
|
|
|
|
await message.reply_text("检测到用户为UID绑定,无需认证", reply_markup=ReplyKeyboardRemove())
|
|
|
|
|
return
|
2022-12-10 12:37:43 +00:00
|
|
|
|
verify = Verify(cookies=client.cookie_manager.cookies)
|
2022-11-20 11:32:56 +00:00
|
|
|
|
if validate:
|
|
|
|
|
_, challenge = await self.verification_system.get_challenge(client.uid)
|
|
|
|
|
if challenge:
|
|
|
|
|
logger.info(
|
2022-11-21 12:50:08 +00:00
|
|
|
|
"用户 %s[%s] 请求通过认证\nchallenge[%s]\nvalidate[%s]",
|
2022-11-20 11:32:56 +00:00
|
|
|
|
user.full_name,
|
|
|
|
|
user.id,
|
|
|
|
|
challenge,
|
|
|
|
|
validate,
|
|
|
|
|
)
|
|
|
|
|
try:
|
2022-12-10 12:37:43 +00:00
|
|
|
|
await verify.verify(challenge=challenge, validate=validate)
|
2022-11-20 11:32:56 +00:00
|
|
|
|
logger.success("用户 %s[%s] 验证成功", user.full_name, user.id)
|
|
|
|
|
await message.reply_text("验证成功", reply_markup=ReplyKeyboardRemove())
|
|
|
|
|
except ResponseException as exc:
|
|
|
|
|
logger.warning(
|
|
|
|
|
"用户 %s[%s] 验证失效 API返回 [%s]%s", user.full_name, user.id, exc.code, exc.message
|
|
|
|
|
)
|
2022-11-20 11:52:36 +00:00
|
|
|
|
if "拼图已过期" in exc.message:
|
|
|
|
|
await message.reply_text(
|
|
|
|
|
"验证失败,拼图已过期,请稍后重试或更换使用环境进行验证", reply_markup=ReplyKeyboardRemove()
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
await message.reply_text(
|
|
|
|
|
f"验证失败,错误信息为 [{exc.code}]{exc.message},请稍后重试",
|
|
|
|
|
reply_markup=ReplyKeyboardRemove(),
|
|
|
|
|
)
|
2022-11-20 11:32:56 +00:00
|
|
|
|
else:
|
|
|
|
|
logger.warning("用户 %s[%s] 验证失效 请求已经过期", user.full_name, user.id)
|
|
|
|
|
await message.reply_text("验证失效 请求已经过期 请稍后重试", reply_markup=ReplyKeyboardRemove())
|
|
|
|
|
return
|
|
|
|
|
try:
|
|
|
|
|
await client.get_genshin_notes()
|
|
|
|
|
except GenshinException as exc:
|
|
|
|
|
if exc.retcode != 1034:
|
|
|
|
|
raise exc
|
|
|
|
|
else:
|
|
|
|
|
await message.reply_text("账户正常,无需认证")
|
|
|
|
|
return
|
|
|
|
|
try:
|
2022-12-10 12:37:43 +00:00
|
|
|
|
data = await verify.create(is_high=True)
|
2022-11-20 11:32:56 +00:00
|
|
|
|
challenge = data["challenge"]
|
|
|
|
|
gt = data["gt"]
|
2022-11-20 11:52:36 +00:00
|
|
|
|
logger.success("用户 %s[%s] 创建验证成功\ngt:%s\nchallenge%s", user.full_name, user.id, gt, challenge)
|
2022-11-20 11:32:56 +00:00
|
|
|
|
except ResponseException as exc:
|
|
|
|
|
logger.warning("用户 %s[%s] 创建验证失效 API返回 [%s]%s", user.full_name, user.id, exc.code, exc.message)
|
2022-11-20 11:52:36 +00:00
|
|
|
|
await message.reply_text(
|
|
|
|
|
f"创建验证失败 错误信息为 [{exc.code}]{exc.message} 请稍后重试", reply_markup=ReplyKeyboardRemove()
|
|
|
|
|
)
|
2022-11-20 11:32:56 +00:00
|
|
|
|
return
|
|
|
|
|
await self.verification_system.set_challenge(client.uid, gt, challenge)
|
|
|
|
|
url = f"{config.pass_challenge_user_web}/webapp?username={context.bot.username}&command=verify>={gt}&challenge={challenge}&uid={client.uid}"
|
|
|
|
|
await message.reply_text(
|
|
|
|
|
"请尽快点击下方手动验证 或发送 /web_cancel 取消操作",
|
|
|
|
|
reply_markup=ReplyKeyboardMarkup.from_button(
|
|
|
|
|
KeyboardButton(
|
|
|
|
|
text="点我手动验证",
|
|
|
|
|
web_app=WebAppInfo(url=url),
|
|
|
|
|
)
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
logger.warning(
|
|
|
|
|
"用户 %s[%s] WEB_APP_DATA 请求错误 [%s]%s", user.full_name, user.id, result.code, result.message
|
|
|
|
|
)
|
2022-12-10 12:44:04 +00:00
|
|
|
|
if result.path == "verify":
|
|
|
|
|
await message.reply_text(
|
|
|
|
|
"验证过程中出现问题 %s\n如果继续遇到该问题,请打开米游社→我的角色中尝试手动通过验证" % result.message,
|
|
|
|
|
reply_markup=ReplyKeyboardRemove(),
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
await message.reply_text("WebApp返回错误 %s" % result.message, reply_markup=ReplyKeyboardRemove())
|
2022-11-20 11:32:56 +00:00
|
|
|
|
else:
|
|
|
|
|
logger.warning("用户 %s[%s] WEB_APP_DATA 非法数据", user.full_name, user.id)
|
|
|
|
|
|
|
|
|
|
@handler.command("web_cancel", block=False)
|
|
|
|
|
@restricts()
|
|
|
|
|
async def web_cancel(self, update: Update, _: CallbackContext) -> None:
|
|
|
|
|
message = update.effective_message
|
|
|
|
|
await message.reply_text("取消操作", reply_markup=ReplyKeyboardRemove())
|