🐛 Fix support for Chinese public cookies

This commit is contained in:
omg-xtao 2023-10-19 18:58:51 +08:00 committed by GitHub
parent 0b4dd0879a
commit e65a08b235
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 144 additions and 292 deletions

View File

@ -0,0 +1,25 @@
"""devices_valid
Revision ID: c6282bc5bf67
Revises: 1df05b897d3f
Create Date: 2023-10-19 14:54:35.164497
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = "c6282bc5bf67"
down_revision = "1df05b897d3f"
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column("devices", sa.Column("is_valid", sa.Boolean(), nullable=False, server_default="1"))
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("devices", "is_valid")
# ### end Alembic commands ###

View File

@ -1,3 +1,5 @@
from typing import Optional
from gram_core.base_service import BaseService
from gram_core.basemodel import RegionEnum
from gram_core.services.cookies.error import CookieServiceError
@ -17,11 +19,27 @@ __all__ = ("CookiesService", "PublicCookiesService")
class PublicCookiesService(BaseService, BasePublicCookiesService):
async def check_public_cookie(self, region: RegionEnum, cookies: Cookies, public_id: int):
async def initialize(self) -> None:
logger.info("正在初始化公共Cookies池")
await self.refresh()
logger.success("刷新公共Cookies池成功")
async def check_public_cookie(self, region: RegionEnum, cookies: Cookies, public_id: int): # skipcq: PY-R1000 #
device_id: Optional[str] = None
device_fp: Optional[str] = None
devices = await self.devices_repository.get(cookies.account_id)
if devices:
device_id = devices.device_id
device_fp = devices.device_fp
if region == RegionEnum.HYPERION:
client = StarRailClient(cookies=cookies.data, region=Region.CHINESE)
client = StarRailClient(
cookies=cookies.data, region=Region.CHINESE, device_id=device_id, device_fp=device_fp
)
elif region == RegionEnum.HOYOLAB:
client = StarRailClient(cookies=cookies.data, region=Region.OVERSEAS, lang="zh-cn")
client = StarRailClient(
cookies=cookies.data, region=Region.OVERSEAS, lang="zh-cn", device_id=device_id, device_fp=device_fp
)
else:
raise CookieServiceError
try:
@ -61,6 +79,7 @@ class PublicCookiesService(BaseService, BasePublicCookiesService):
raise exc
if exc.ret_code == 1034:
logger.warning("用户 [%s] 触发验证", public_id)
await self.set_device_valid(client.account_id, False)
else:
logger.warning("用户 [%s] 获取账号信息发生错误,错误信息为", public_id)
logger.exception(exc)

@ -1 +1 @@
Subproject commit f5994842531164370fef6a34400d04b955c68d11
Subproject commit f18ce6dd6da2bb54a375bbb3ab46f638af8a6e51

View File

@ -15,10 +15,10 @@ from telegram.helpers import escape_markdown
from core.basemodel import RegionEnum
from core.plugin import Plugin, conversation, handler
from core.services.cookies.error import TooManyRequestPublicCookies
from core.services.cookies.models import CookiesStatusEnum
from core.services.cookies.services import CookiesService, PublicCookiesService
from core.services.players.models import PlayersDataBase as Player, PlayerInfoSQLModel
from core.services.players.services import PlayersService, PlayerInfoService
from plugins.tools.genshin import GenshinHelper
from utils.log import logger
if TYPE_CHECKING:
@ -51,11 +51,13 @@ class BindAccountPlugin(Plugin.Conversation):
cookies_service: CookiesService = None,
player_info_service: PlayerInfoService = None,
public_cookies_service: PublicCookiesService = None,
helper: GenshinHelper = None,
):
self.public_cookies_service = public_cookies_service
self.cookies_service = cookies_service
self.players_service = players_service
self.player_info_service = player_info_service
self.helper = helper
@conversation.entry_point
@handler.command(command="setuid", filters=filters.ChatType.PRIVATE, block=False)
@ -106,10 +108,10 @@ class BindAccountPlugin(Plugin.Conversation):
await message.reply_text("退出任务", reply_markup=ReplyKeyboardRemove())
return ConversationHandler.END
if message.text == "通过玩家ID":
await message.reply_text("请输入你的游戏ID非通行证ID", reply_markup=ReplyKeyboardRemove())
await message.reply_text("请输入你的玩家ID非通行证ID此 ID 在 游戏客户端 左/右下角。", reply_markup=ReplyKeyboardRemove())
return CHECK_PLAYER_ID
if message.text == "通过账号ID":
await message.reply_text("请输入你的通行证ID非玩家ID", reply_markup=ReplyKeyboardRemove())
await message.reply_text("请输入你的通行证ID非玩家ID,此 ID 在 社区APP '我的' 页面。", reply_markup=ReplyKeyboardRemove())
return CHECK_ACCOUNT_ID
await message.reply_text("选择错误,请重新选择")
return CHECK_METHOD
@ -192,18 +194,11 @@ class BindAccountPlugin(Plugin.Conversation):
await message.reply_text("ID 格式有误,请检查", reply_markup=ReplyKeyboardRemove())
return ConversationHandler.END
try:
cookies = await self.public_cookies_service.get_cookies(user.id, region)
async with self.helper.public_genshin(user.id, region=region, uid=player_id) as client:
player_stats = await client.get_starrail_user(player_id)
except TooManyRequestPublicCookies:
await message.reply_text("用户查询次数过多,请稍后重试", reply_markup=ReplyKeyboardRemove())
return ConversationHandler.END
if region == RegionEnum.HYPERION:
client = StarRailClient(cookies=cookies.data, region=Region.CHINESE, lang="zh-cn")
elif region == RegionEnum.HOYOLAB:
client = StarRailClient(cookies=cookies.data, region=Region.OVERSEAS, lang="zh-cn")
else:
return ConversationHandler.END
try:
player_stats = await client.get_starrail_user(player_id)
except AccountNotFound:
await message.reply_text("找不到用户uid可能无效", reply_markup=ReplyKeyboardRemove())
logger.warning("获取账号信息发生错误 %s 找不到用户 uid可能无效", player_id)
@ -213,12 +208,11 @@ class BindAccountPlugin(Plugin.Conversation):
logger.warning("获取账号信息发生错误 %s 账户信息未公开", player_id)
return ConversationHandler.END
except InvalidCookies:
await self.public_cookies_service.undo(user.id, cookies, CookiesStatusEnum.INVALID_COOKIES)
await self.public_cookies_service.undo(user.id)
await message.reply_text("出错了呜呜呜 ~ 请稍后重试")
return ConversationHandler.END
except SimnetBadRequest as exc:
if exc.retcode == 1034:
await self.public_cookies_service.undo(user.id)
await message.reply_text("出错了呜呜呜 ~ 请稍后重试")
return ConversationHandler.END
await message.reply_text("获取账号信息发生错误", reply_markup=ReplyKeyboardRemove())
@ -228,8 +222,6 @@ class BindAccountPlugin(Plugin.Conversation):
except ValueError:
await message.reply_text("ID 格式有误,请检查", reply_markup=ReplyKeyboardRemove())
return ConversationHandler.END
finally:
await client.shutdown()
player_info = await self.players_service.get(
user.id, player_id=player_id, region=bind_account_plugin_data.region
)

View File

@ -237,7 +237,8 @@ class AccountCookiesPlugin(Plugin.Conversation):
try:
account_cookies_plugin_data.device = self.parse_headers(cookie)
except ValueError:
await message.reply_text("警告,解析 Devices 出现错误,可能无法绕过风控,查询操作将需要通过验证。")
account_cookies_plugin_data.device = None
await message.reply_text("解析 Devices 出现错误,可能无法绕过风控,查询操作将需要通过验证。")
if not cookies:
logger.info("用户 %s[%s] Cookies格式有误", user.full_name, user.id)
await message.reply_text("Cookies格式有误请检查后重新尝试绑定", reply_markup=ReplyKeyboardRemove())
@ -382,6 +383,7 @@ class AccountCookiesPlugin(Plugin.Conversation):
device_model.device_id = device.device_id
device_model.device_fp = device.device_fp
device_model.device_name = device.device_name
device_model.is_valid = True
await self.devices_service.update(device_model)
else:
device_model = Devices(
@ -389,6 +391,7 @@ class AccountCookiesPlugin(Plugin.Conversation):
device_id=device.device_id,
device_fp=device.device_fp,
device_name=device.device_name,
is_valid=True,
)
await self.devices_service.add(device_model)

View File

@ -1,187 +0,0 @@
from typing import Optional
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, TelegramObject, Update
from telegram.ext import CallbackContext, ConversationHandler, filters
from telegram.helpers import escape_markdown
from core.basemodel import RegionEnum
from core.plugin import Plugin, conversation, handler
from core.services.cookies.services import CookiesService
from core.services.devices import DevicesService
from core.services.devices.models import DevicesDataBase as Devices
from core.services.players.services import PlayersService
from modules.apihelper.utility.devices import devices_methods
from utils.log import logger
__all__ = ("AccountDevicesPlugin",)
class AccountDevicesPluginData(TelegramObject):
device_id: str = ""
device_fp: str = ""
device_name: Optional[str] = None
account_id: int = 0
def reset(self):
self.device_id = ""
self.device_fp = ""
self.device_name = None
self.account_id = 0
CHECK_SERVER, INPUT_DEVICES, COMMAND_RESULT = range(10100, 10103)
class AccountDevicesPlugin(Plugin.Conversation):
"""设备绑定"""
def __init__(
self,
players_service: PlayersService = None,
cookies_service: CookiesService = None,
devices_service: DevicesService = None,
):
self.cookies_service = cookies_service
self.players_service = players_service
self.devices_service = devices_service
devices_methods.service = devices_service
@staticmethod
def parse_headers(data: AccountDevicesPluginData, headers_text: str) -> None:
headers = {}
for line in headers_text.splitlines():
if not line:
continue
try:
k, v = line.split(":", 1)
headers[k.strip()] = v.strip()
except ValueError:
continue
must_keys = {"x-rpc-device_id": 36, "x-rpc-device_fp": 13}
optional_keys = ["x-rpc-device_name"]
for k, v in must_keys.items():
if (k not in headers) or (not headers.get(k)):
raise ValueError
if len(headers.get(k)) != v:
raise ValueError
for k in optional_keys:
if k not in headers:
continue
elif headers.get(k) and len(headers.get(k)) > 64:
raise ValueError
data.device_id = headers.get("x-rpc-device_id")
data.device_fp = headers.get("x-rpc-device_fp")
data.device_name = headers.get("x-rpc-device_name")
@conversation.entry_point
@handler.command(command="setdevice", filters=filters.ChatType.PRIVATE, block=False)
@handler.command(command="setdevices", filters=filters.ChatType.PRIVATE, block=False)
async def command_start(self, update: Update, context: CallbackContext) -> int:
user = update.effective_user
message = update.effective_message
logger.info("用户 %s[%s] 绑定设备命令请求", user.full_name, user.id)
account_devices_plugin_data: AccountDevicesPluginData = context.chat_data.get("account_devices_plugin_data")
if account_devices_plugin_data is None:
account_devices_plugin_data = AccountDevicesPluginData()
context.chat_data["account_devices_plugin_data"] = account_devices_plugin_data
else:
account_devices_plugin_data.reset()
text = f'你好 {user.mention_markdown_v2()} {escape_markdown("!请选择要绑定的服务器!或回复退出取消操作")}'
reply_keyboard = [["米游社"], ["退出"]]
await message.reply_markdown_v2(text, reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True))
return CHECK_SERVER
@conversation.state(state=CHECK_SERVER)
@handler.message(filters=filters.TEXT & ~filters.COMMAND, block=False)
async def check_server(self, update: Update, context: CallbackContext) -> int:
user = update.effective_user
message = update.effective_message
account_devices_plugin_data: AccountDevicesPluginData = context.chat_data.get("account_devices_plugin_data")
if message.text == "退出":
await message.reply_text("退出任务", reply_markup=ReplyKeyboardRemove())
return ConversationHandler.END
if message.text == "米游社":
region = RegionEnum.HYPERION
bbs_name = "米游社"
else:
await message.reply_text("选择错误,请重新选择")
return CHECK_SERVER
player_info = await self.players_service.get(user.id, region=region)
if player_info:
cookies_database = await self.cookies_service.get(user.id, player_info.account_id, region)
if not cookies_database:
await message.reply_text(f"你还没有绑定 {bbs_name} 的Cookies请先绑定Cookies")
return ConversationHandler.END
account_devices_plugin_data.account_id = player_info.account_id
else:
await message.reply_text(f"你还没有绑定 {bbs_name} 的Cookies请先绑定Cookies")
return ConversationHandler.END
help_message = (
"<b>关于如何获取Device</b>\n"
"<b>此操作只能在PC上进行。</b>\n\n"
"PC\n"
"1、打开<a href='https://user.mihoyo.com/'>通行证</a>并登录\n"
"2、进入通行证按F12打开开发者工具\n"
"3、将开发者工具切换至网络(Network)并点击过滤栏中的 Fetch/XHR 并刷新页面\n"
"4、在请求列表中找到 login_by_cookie\n"
"5、右键并复制请求标头(Request Headers)\n"
"<u>如发现没有此请求大概因为缓存的存在需要你点击禁用缓存(Disable Cache)再次刷新页面</u>"
)
await message.reply_html(help_message, disable_web_page_preview=True)
await message.reply_text(f"请输入{bbs_name}的请求标头!或回复退出取消操作", reply_markup=ReplyKeyboardRemove())
return INPUT_DEVICES
@conversation.state(state=INPUT_DEVICES)
@handler.message(filters=filters.TEXT & ~filters.COMMAND, block=False)
async def input_cookies(self, update: Update, context: CallbackContext) -> int:
message = update.effective_message
user = update.effective_user
account_devices_plugin_data: AccountDevicesPluginData = context.chat_data.get("account_devices_plugin_data")
if message.text == "退出":
await message.reply_text("退出任务", reply_markup=ReplyKeyboardRemove())
return ConversationHandler.END
try:
self.parse_headers(account_devices_plugin_data, message.text)
except ValueError as exc:
logger.info("用户 %s[%s] Devices解析出现错误\ntext:%s", user.full_name, user.id, message.text)
logger.debug("解析Devices出现错误", exc_info=exc)
await message.reply_text("解析Devices出现错误请检查是否正确", reply_markup=ReplyKeyboardRemove())
return ConversationHandler.END
reply_keyboard = [["确认", "退出"]]
await message.reply_markdown_v2(
"请确认修改!", reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)
)
return COMMAND_RESULT
@conversation.state(state=COMMAND_RESULT)
@handler.message(filters=filters.TEXT & ~filters.COMMAND, block=False)
async def command_result(self, update: Update, context: CallbackContext) -> int:
user = update.effective_user
message = update.effective_message
account_devices_plugin_data: AccountDevicesPluginData = context.chat_data.get("account_devices_plugin_data")
if message.text == "退出":
await message.reply_text("退出任务", reply_markup=ReplyKeyboardRemove())
return ConversationHandler.END
if message.text == "确认":
device = await self.devices_service.get(account_devices_plugin_data.account_id)
if device:
device.device_id = account_devices_plugin_data.device_id
device.device_fp = account_devices_plugin_data.device_fp
device.device_name = account_devices_plugin_data.device_name
await self.devices_service.update(device)
logger.success("用户 %s[%s] 更新Devices", user.full_name, user.id)
else:
device = Devices(
account_id=account_devices_plugin_data.account_id,
device_id=account_devices_plugin_data.device_id,
device_fp=account_devices_plugin_data.device_fp,
device_name=account_devices_plugin_data.device_name,
)
await self.devices_service.add(device)
logger.info("用户 %s[%s] 绑定Devices成功", user.full_name, user.id)
await message.reply_text("保存成功", reply_markup=ReplyKeyboardRemove())
return ConversationHandler.END
await message.reply_text("回复错误,请重新输入")
return COMMAND_RESULT

View File

@ -12,6 +12,7 @@ from core.services.cookies import CookiesService
from core.services.players import PlayersService
from core.services.players.services import PlayerInfoService
from gram_core.services.cookies.models import CookiesStatusEnum
from gram_core.services.devices import DevicesService
from modules.apihelper.models.genshin.cookies import CookiesModel
from utils.log import logger
@ -24,10 +25,17 @@ __all__ = ("PlayersManagesPlugin",)
class PlayersManagesPlugin(Plugin):
def __init__(self, players: PlayersService, cookies: CookiesService, player_info_service: PlayerInfoService):
def __init__(
self,
players: PlayersService,
cookies: CookiesService,
player_info_service: PlayerInfoService,
devices_service: DevicesService,
):
self.cookies_service = cookies
self.players_service = players
self.player_info_service = player_info_service
self.devices_service = devices_service
@staticmethod
def players_manager_callback(callback_query_data: str) -> Tuple[str, int, int]:
@ -273,10 +281,15 @@ class PlayersManagesPlugin(Plugin):
await callback_query.edit_message_text(
f"玩家 {player.player_id} {player_info.nickname} cookies 未找到", reply_markup=InlineKeyboardMarkup(buttons)
)
return
device = await self.devices_service.get(player.account_id)
cookies = SimpleCookie()
for key, value in cookies_data.data.items():
cookies[key] = value
if device is not None:
cookies["x-rpc-device_id"] = device.device_id
cookies["x-rpc-device_fp"] = device.device_fp
cookie_str = cookies.output(header="", sep=";")

View File

@ -1,8 +1,8 @@
from datetime import datetime
from typing import List, Optional
from httpx import AsyncClient
from pydantic import BaseModel
from telegram import Update, InlineKeyboardMarkup, InlineKeyboardButton
from telegram.ext import CallbackContext, filters

View File

@ -15,8 +15,8 @@ from telegram.constants import ParseMode
from telegram.error import BadRequest
from telegram.ext import CallbackContext
from core.plugin import Plugin, handler
from core.dependence.assets import AssetsService
from core.plugin import Plugin, handler
from core.services.search.services import SearchServices
from core.services.wiki.services import WikiService
from utils.log import logger

View File

@ -105,7 +105,7 @@ class StartPlugin(Plugin):
async def process_validate(self, message: Message, user: User, bot_username: Optional[str] = None):
await message.reply_text(
"由于官方对第三方工具限制以及账户安全的考虑,频繁使用第三方工具会导致账号被风控并要求用过验证才能进行访问。\n"
"如出现频繁验证请求,可尝试使用 /setdevice 设置设备标识符以尝试解决该问题。\n"
"如出现频繁验证请求,可尝试使用 /setcookies 的新方法重新绑定以尝试解决该问题。\n"
"如担心账号安全,建议修改密码以保护账号安全,修改账号密码后任何登录令牌都会被强制注销。\n"
)
try:

View File

@ -80,7 +80,7 @@ class PlayerActivityPlugins(Plugin):
logger.info("用户 %s[%s] 查询评书奇谭信息命令请求", user.full_name, user.id)
try:
uid = await self.get_uid(user.id, context.args, message.reply_to_message)
async with self.helper.genshin(user.id) as client:
async with self.helper.genshin_or_public(user.id, uid=uid) as client:
render_result = await self.fantastic_story_render(client, uid)
except AttributeError as exc:
logger.error(ACTIVITY_DATA_ERROR)
@ -136,7 +136,7 @@ class PlayerActivityPlugins(Plugin):
logger.info("用户 %s[%s] 查询以太战线信息命令请求", user.full_name, user.id)
try:
uid = await self.get_uid(user.id, context.args, message.reply_to_message)
async with self.helper.genshin(user.id) as client:
async with self.helper.genshin_or_public(user.id, uid=uid) as client:
render_result = await self.yitai_battle_render(client, uid)
except AttributeError as exc:
logger.error(ACTIVITY_DATA_ERROR)
@ -184,7 +184,7 @@ class PlayerActivityPlugins(Plugin):
logger.info("用户 %s[%s] 查询地城探宝信息命令请求", user.full_name, user.id)
try:
uid = await self.get_uid(user.id, context.args, message.reply_to_message)
async with self.helper.genshin(user.id) as client:
async with self.helper.genshin_or_public(user.id, uid=uid) as client:
render_result = await self.treasure_dungeon_render(client, uid)
if render_result is None:
raise NotHaveData
@ -251,7 +251,7 @@ class PlayerActivityPlugins(Plugin):
logger.info("用户 %s[%s] 查询金人巷信息命令请求", user.full_name, user.id)
try:
uid = await self.get_uid(user.id, context.args, message.reply_to_message)
async with self.helper.genshin(user.id) as client:
async with self.helper.genshin_or_public(user.id, uid=uid) as client:
render_result = await self.copper_man_render(client, uid)
except AttributeError as exc:
logger.error(ACTIVITY_DATA_ERROR)

View File

@ -6,7 +6,6 @@ from typing import Any, List, Optional, Tuple, Union, TYPE_CHECKING
from arkowrapper import ArkoWrapper
from pytz import timezone
from simnet.errors import BadRequest as SimnetBadRequest
from telegram import Message, Update
from telegram.constants import ChatAction, ParseMode
from telegram.ext import CallbackContext, filters
@ -16,7 +15,7 @@ from core.plugin import Plugin, handler
from core.services.cookies.error import TooManyRequestPublicCookies
from core.services.template.models import RenderGroupResult, RenderResult
from core.services.template.services import TemplateService
from plugins.tools.genshin import GenshinHelper, CookiesNotFoundError
from plugins.tools.genshin import GenshinHelper
from utils.log import logger
from utils.uid import mask_number
@ -135,20 +134,11 @@ class ChallengePlugin(Plugin):
reply_text: Optional[Message] = None
try:
try:
async with self.helper.genshin(user.id) as client:
if client.player_id != uid:
raise CookiesNotFoundError(uid)
if total:
reply_text = await message.reply_text("彦卿需要时间整理混沌回忆数据,还请耐心等待哦~")
await message.reply_chat_action(ChatAction.TYPING)
images = await self.get_rendered_pic(client, uid, floor, total, previous)
except CookiesNotFoundError:
async with self.helper.public_genshin(user.id) as client:
if total:
reply_text = await message.reply_text("彦卿需要时间整理混沌回忆数据,还请耐心等待哦~")
await message.reply_chat_action(ChatAction.TYPING)
images = await self.get_rendered_pic(client, uid, floor, total, previous)
async with self.helper.genshin_or_public(user.id, uid=uid) as client:
if total:
reply_text = await message.reply_text("彦卿需要时间整理混沌回忆数据,还请耐心等待哦~")
await message.reply_chat_action(ChatAction.TYPING)
images = await self.get_rendered_pic(client, uid, floor, total, previous)
except TooManyRequestPublicCookies:
reply_message = await message.reply_text("查询次数太多,请您稍后重试")
if filters.ChatType.GROUPS.filter(message):
@ -161,11 +151,6 @@ class ChallengePlugin(Plugin):
except IndexError: # 若混沌回忆为挑战此层
await reply_message_func("还没有挑战本层呢,咕咕咕~")
return
except SimnetBadRequest as exc:
if exc.retcode == 1034 and client.player_id != uid:
await message.reply_text("出错了呜呜呜 ~ 请稍后重试 ~ 米游社风控太严力")
return
raise exc
if images is None:
await reply_message_func(f"还没有第 {floor} 层的挑战数据")
return

View File

@ -11,7 +11,7 @@ from core.plugin import Plugin, handler
from core.services.cookies.error import TooManyRequestPublicCookies
from core.services.template.models import RenderResult
from core.services.template.services import TemplateService
from plugins.tools.genshin import GenshinHelper, CookiesNotFoundError
from plugins.tools.genshin import GenshinHelper
from utils.log import logger
from utils.uid import mask_number
@ -70,19 +70,8 @@ class PlayerMuseumPlugins(Plugin):
logger.info("用户 %s[%s] 查询博物馆信息命令请求", user.full_name, user.id)
try:
uid = await self.get_uid(user.id, context.args, message.reply_to_message)
try:
async with self.helper.genshin(user.id) as client:
if client.player_id != uid:
raise CookiesNotFoundError(uid)
render_result = await self.render(client, uid)
except CookiesNotFoundError:
async with self.helper.public_genshin(user.id) as client:
render_result = await self.render(client, uid)
except SimnetBadRequest as exc:
if exc.retcode == 1034:
await message.reply_text("出错了呜呜呜 ~ 请稍后重试")
return
raise exc
async with self.helper.genshin_or_public(user.id, uid=uid) as client:
render_result = await self.render(client, uid)
except TooManyRequestPublicCookies:
await message.reply_text("用户查询次数过多 请稍后重试")
return

View File

@ -12,7 +12,7 @@ from core.plugin import Plugin, handler
from core.services.cookies.error import TooManyRequestPublicCookies
from core.services.template.models import RenderResult
from core.services.template.services import TemplateService
from plugins.tools.genshin import GenshinHelper, CookiesNotFoundError
from plugins.tools.genshin import GenshinHelper
from utils.log import logger
from utils.uid import mask_number
@ -91,19 +91,8 @@ class PlayerRoguePlugins(Plugin):
logger.info("用户 %s[%s] 查询模拟宇宙信息命令请求", user.full_name, user.id)
try:
uid, pre = await self.get_uid(user.id, context.args, message.reply_to_message)
try:
async with self.helper.genshin(user.id) as client:
if client.player_id != uid:
raise CookiesNotFoundError(uid)
render_result = await self.render(client, pre, uid)
except CookiesNotFoundError:
async with self.helper.public_genshin(user.id) as client:
render_result = await self.render(client, pre, uid)
except SimnetBadRequest as exc:
if exc.retcode == 1034:
await message.reply_text("出错了呜呜呜 ~ 请稍后重试")
return
raise exc
async with self.helper.genshin_or_public(user.id, uid=uid) as client:
render_result = await self.render(client, pre, uid)
except TooManyRequestPublicCookies:
await message.reply_text("用户查询次数过多 请稍后重试")
return

View File

@ -9,7 +9,7 @@ from core.plugin import Plugin, handler
from core.services.cookies.error import TooManyRequestPublicCookies
from core.services.template.models import RenderResult
from core.services.template.services import TemplateService
from plugins.tools.genshin import GenshinHelper, CookiesNotFoundError
from plugins.tools.genshin import GenshinHelper
from utils.log import logger
from utils.uid import mask_number
@ -62,19 +62,8 @@ class PlayerStatsPlugins(Plugin):
logger.info("用户 %s[%s] 查询游戏用户命令请求", user.full_name, user.id)
try:
uid: int = await self.get_uid(user.id, context.args, message.reply_to_message)
try:
async with self.helper.genshin(user.id) as client:
if client.player_id != uid:
raise CookiesNotFoundError(uid)
render_result = await self.render(client, uid)
except CookiesNotFoundError:
async with self.helper.public_genshin(user.id) as client:
render_result = await self.render(client, uid)
except SimnetBadRequest as exc:
if exc.retcode == 1034:
await message.reply_text("出错了呜呜呜 ~ 请稍后重试")
return
raise exc
async with self.helper.genshin_or_public(user.id, uid=uid) as client:
render_result = await self.render(client, uid)
except TooManyRequestPublicCookies:
await message.reply_text("用户查询次数过多 请稍后重试")
return

View File

@ -10,6 +10,7 @@ from simnet import StarRailClient, Region
from simnet.errors import BadRequest as SimnetBadRequest, InvalidCookies, NetworkError, CookieException
from simnet.models.genshin.calculator import CalculatorCharacterDetails
from simnet.models.genshin.chronicle.characters import Character
from simnet.utils.player import recognize_game_biz
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.orm.exc import StaleDataError
from sqlmodel import BigInteger, Column, DateTime, Field, Index, Integer, SQLModel, String, delete, func, select
@ -193,7 +194,9 @@ class PlayerNotFoundError(Exception):
class CookiesNotFoundError(Exception):
def __init__(self, user_id):
def __init__(self, user_id: int, region: Optional[RegionEnum] = None):
self.user_id = user_id
self.region = region
super().__init__(f"{user_id} cookies not found")
@ -215,16 +218,16 @@ class GenshinHelper(Plugin):
raise ServiceNotFoundError(*filter(lambda x: x is None, temp))
@asynccontextmanager
async def genshin(self, user_id: int, region: Optional[RegionEnum] = None) -> StarRailClient:
async def genshin(self, user_id: int, region: Optional[RegionEnum] = None) -> StarRailClient: # skipcq: PY-R1000 #
player = await self.players_service.get_player(user_id, region)
if player is None:
raise PlayerNotFoundError(user_id)
if player.account_id is None:
raise CookiesNotFoundError(user_id)
raise CookiesNotFoundError(user_id, player.region)
cookie_model = await self.cookies_service.get(player.user_id, player.account_id, player.region)
if cookie_model is None:
raise CookiesNotFoundError(user_id)
raise CookiesNotFoundError(user_id, player.region)
cookies = cookie_model.data
if player.region == RegionEnum.HYPERION: # 国服
@ -252,6 +255,11 @@ class GenshinHelper(Plugin):
) as client:
try:
yield client
except SimnetBadRequest as exc:
if exc.ret_code == 1034 and devices is not None:
devices.is_valid = False
await self.devices_service.update(devices)
raise exc
except InvalidCookies as exc:
refresh = False
cookie_model.status = CookiesStatusEnum.INVALID_COOKIES
@ -298,10 +306,10 @@ class GenshinHelper(Plugin):
raise PlayerNotFoundError(user_id)
if player.account_id is None:
raise CookiesNotFoundError(user_id)
raise CookiesNotFoundError(user_id, player.region)
cookie_model = await self.cookies_service.get(player.user_id, player.account_id, player.region)
if cookie_model is None:
raise CookiesNotFoundError(user_id)
raise CookiesNotFoundError(user_id, player.region)
cookies = cookie_model.data
if player.region == RegionEnum.HYPERION:
@ -329,16 +337,20 @@ class GenshinHelper(Plugin):
)
@asynccontextmanager
async def public_genshin(self, user_id: int, region: Optional[RegionEnum] = None) -> StarRailClient:
player = await self.players_service.get_player(user_id, region)
async def public_genshin(
self, user_id: int, region: Optional[RegionEnum] = None, uid: Optional[int] = None
) -> StarRailClient:
if not (region or uid):
player = await self.players_service.get_player(user_id, region)
if player:
region = player.region
uid = player.player_id
region = player.region
cookies = await self.public_cookies_service.get_cookies(user_id, region)
uid = player.player_id
if player.region == RegionEnum.HYPERION:
if region == RegionEnum.HYPERION:
region = Region.CHINESE
elif player.region == RegionEnum.HOYOLAB:
elif region == RegionEnum.HOYOLAB:
region = Region.OVERSEAS
else:
raise TypeError("Region is not `RegionEnum.NULL`")
@ -353,7 +365,6 @@ class GenshinHelper(Plugin):
async with StarRailClient(
cookies.data,
region=region,
account_id=player.account_id,
player_id=uid,
lang="zh-cn",
device_id=device_id,
@ -364,4 +375,28 @@ class GenshinHelper(Plugin):
except SimnetBadRequest as exc:
if exc.ret_code == 1034:
await self.public_cookies_service.undo(user_id)
await self.public_cookies_service.set_device_valid(client.account_id, False)
raise exc
@asynccontextmanager
async def genshin_or_public(
self, user_id: int, region: Optional[RegionEnum] = None, uid: Optional[int] = None
) -> StarRailClient:
try:
async with self.genshin(user_id, region) as client:
client.public = False
if uid and recognize_game_biz(uid, client.game) != recognize_game_biz(client.player_id, client.game):
# 如果 uid 和 player_id 服务器不一致,说明是跨服的,需要使用公共的 cookies
raise CookiesNotFoundError(user_id)
yield client
except CookiesNotFoundError:
if uid:
region = RegionEnum.HYPERION if uid < 600000000 else RegionEnum.HOYOLAB
async with self.public_genshin(user_id, region, uid) as client:
try:
client.public = True
yield client
except SimnetBadRequest as exc:
if exc.ret_code == 1034:
raise CookiesNotFoundError(user_id) from exc
raise exc