🐛 Fix support for Chinese public cookies

Co-authored-by: luoshuijs <luoshuijs@outlook.com>
This commit is contained in:
omg-xtao 2023-10-19 18:58:00 +08:00 committed by 洛水居室
parent 635b8444d5
commit 441713236b
No known key found for this signature in database
GPG Key ID: C9DE87DA724B88FC
11 changed files with 137 additions and 262 deletions

View File

@ -0,0 +1,27 @@
"""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,28 +19,43 @@ __all__ = ("CookiesService", "PublicCookiesService")
class PublicCookiesService(BaseService, BasePublicCookiesService):
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 = GenshinClient(cookies=cookies.data, region=Region.CHINESE)
client = GenshinClient(
cookies=cookies.data, region=Region.CHINESE, device_id=device_id, device_fp=device_fp
)
elif region == RegionEnum.HOYOLAB:
client = GenshinClient(cookies=cookies.data, region=Region.OVERSEAS, lang="zh-cn")
client = GenshinClient(
cookies=cookies.data, region=Region.OVERSEAS, lang="zh-cn", device_id=device_id, device_fp=device_fp
)
else:
raise CookieServiceError
try:
if client.account_id is None:
raise RuntimeError("account_id not found")
record_cards = await client.get_record_cards()
if client.region == Region.OVERSEAS:
for record_card in record_cards:
if record_card.game == Game.GENSHIN:
await client.get_partial_genshin_user(record_card.uid)
for record_card in record_cards:
if record_card.game == Game.GENSHIN:
await client.get_partial_genshin_user(record_card.uid)
break
else:
accounts = await client.get_game_accounts()
for account in accounts:
if account.game == Game.GENSHIN:
await client.get_partial_genshin_user(account.uid)
break
else:
accounts = await client.get_game_accounts()
for account in accounts:
if account.game == Game.GENSHIN:
await client.get_partial_genshin_user(account.uid)
break
except InvalidCookies as exc:
if exc.ret_code in (10001, -100):
logger.warning("用户 [%s] Cookies无效", public_id)
@ -62,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)
@ -86,14 +88,13 @@ class BindAccountPlugin(Plugin.Conversation):
await message.reply_text("退出任务", reply_markup=ReplyKeyboardRemove())
return ConversationHandler.END
if message.text == "米游社":
reply_keyboard = [["通过账号ID"], ["退出"]]
bind_account_plugin_data.region = RegionEnum.HYPERION
elif message.text == "HoYoLab":
reply_keyboard = [["通过玩家ID", "通过账号ID"], ["退出"]]
bind_account_plugin_data.region = RegionEnum.HOYOLAB
else:
await message.reply_text("选择错误,请重新选择")
return CHECK_SERVER
reply_keyboard = [["通过玩家ID", "通过账号ID"], ["退出"]]
await message.reply_markdown_v2(
"请选择你要绑定的方式", reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)
)
@ -101,17 +102,16 @@ class BindAccountPlugin(Plugin.Conversation):
@conversation.state(state=CHECK_METHOD)
@handler.message(filters=filters.TEXT & ~filters.COMMAND, block=False)
async def check_method(self, update: "Update", context: "ContextTypes.DEFAULT_TYPE") -> int:
async def check_method(self, update: "Update", _: "ContextTypes.DEFAULT_TYPE") -> int:
message = update.effective_message
bind_account_plugin_data: BindAccountPluginData = context.chat_data.get("bind_account_plugin_data")
if message.text == "退出":
await message.reply_text("退出任务", reply_markup=ReplyKeyboardRemove())
return ConversationHandler.END
if message.text == "通过玩家ID" and bind_account_plugin_data.region != RegionEnum.HYPERION:
await message.reply_text("请输入你的玩家ID非通行证ID", reply_markup=ReplyKeyboardRemove())
if message.text == "通过玩家ID":
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
@ -194,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_genshin_user(player_id)
except TooManyRequestPublicCookies:
await message.reply_text("用户查询次数过多,请稍后重试", reply_markup=ReplyKeyboardRemove())
return ConversationHandler.END
if region == RegionEnum.HYPERION:
client = GenshinClient(cookies=cookies.data, region=Region.CHINESE)
elif region == RegionEnum.HOYOLAB:
client = GenshinClient(cookies=cookies.data, region=Region.OVERSEAS, lang="zh-cn")
else:
return ConversationHandler.END
try:
player_stats = await client.get_genshin_user(player_id)
except AccountNotFound:
await message.reply_text("找不到用户uid可能无效", reply_markup=ReplyKeyboardRemove())
logger.warning("获取账号信息发生错误 %s 找不到用户 uid可能无效", player_id)
@ -215,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("出错了呜呜呜 ~ 请稍后重试或者绑定 cookie")
return ConversationHandler.END
except SimnetBadRequest as exc:
if exc.ret_code == 1034:
await self.public_cookies_service.undo(user.id)
await message.reply_text("出错了呜呜呜 ~ 请稍后重试或者绑定 cookie")
return ConversationHandler.END
await message.reply_text("获取账号信息发生错误", reply_markup=ReplyKeyboardRemove())
@ -230,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
if 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

@ -109,7 +109,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

@ -8,7 +8,6 @@ from typing import Any, Coroutine, List, Optional, Tuple, Union
from arkowrapper import ArkoWrapper
from pytz import timezone
from simnet import GenshinClient
from simnet.errors import BadRequest as SimnetBadRequest
from telegram import Message, Update
from telegram.constants import ChatAction, ParseMode
from telegram.ext import CallbackContext, filters
@ -18,8 +17,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 gram_core.basemodel import RegionEnum
from plugins.tools.genshin import CookiesNotFoundError, GenshinHelper
from plugins.tools.genshin import GenshinHelper
from utils.log import logger
from utils.uid import mask_number
@ -80,7 +78,6 @@ class AbyssPlugin(Plugin):
async def command_start(self, update: Update, _: CallbackContext) -> None: # skipcq: PY-R1000 #
user = update.effective_user
message = update.effective_message
uid: Optional[int] = None
# 若查询帮助
if (message.text.startswith("/") and "help" in message.text) or "帮助" in message.text:
@ -124,20 +121,11 @@ class AbyssPlugin(Plugin):
if total:
reply_text = await message.reply_text("派蒙需要时间整理深渊数据,还请耐心等待哦~")
try:
try:
async with self.helper.genshin(user.id) as client:
async with self.helper.genshin_or_public(user.id) as client:
if not client.public:
await client.get_record_cards()
images = await self.get_rendered_pic(client, client.player_id, floor, total, previous)
except CookiesNotFoundError as exc:
if exc.region == RegionEnum.HYPERION:
raise exc
# Cookie 不存在使用公开接口
async with self.helper.public_genshin(user.id) as client:
images = await self.get_rendered_pic(client, uid, floor, total, previous)
except SimnetBadRequest as exc:
raise exc
images = await self.get_rendered_pic(client, client.player_id, floor, total, previous)
except AbyssUnlocked: # 若深渊未解锁
await message.reply_text("还未解锁深渊哦~")
return

View File

@ -1,7 +1,5 @@
import random
from typing import Optional, TYPE_CHECKING
from simnet.errors import BadRequest as SimnetBadRequest
from telegram.constants import ChatAction
from telegram.ext import filters
@ -9,8 +7,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 gram_core.basemodel import RegionEnum
from plugins.tools.genshin import CookiesNotFoundError, GenshinHelper
from plugins.tools.genshin import GenshinHelper
from utils.log import logger
from utils.uid import mask_number
@ -46,17 +43,10 @@ class PlayerStatsPlugins(Plugin):
await message.reply_text("输入错误")
return
try:
try:
async with self.helper.genshin(user.id) as client:
async with self.helper.genshin_or_public(user.id) as client:
if not client.public:
await client.get_record_cards()
render_result = await self.render(client, uid)
except CookiesNotFoundError as exc:
if exc.region == RegionEnum.HYPERION:
raise exc
async with self.helper.public_genshin(user.id) as client:
render_result = await self.render(client, uid)
except SimnetBadRequest as exc:
raise exc
render_result = await self.render(client, uid)
except TooManyRequestPublicCookies:
await message.reply_text("用户查询次数过多 请稍后重试")
return

View File

@ -10,6 +10,7 @@ from simnet import GenshinClient, 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
@ -217,7 +218,7 @@ class GenshinHelper(Plugin):
raise ServiceNotFoundError(*filter(lambda x: x is None, temp))
@asynccontextmanager
async def genshin(self, user_id: int, region: Optional[RegionEnum] = None) -> GenshinClient:
async def genshin(self, user_id: int, region: Optional[RegionEnum] = None) -> GenshinClient: # skipcq: PY-R1000 #
player = await self.players_service.get_player(user_id, region)
if player is None:
raise PlayerNotFoundError(user_id)
@ -254,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
@ -331,16 +337,20 @@ class GenshinHelper(Plugin):
)
@asynccontextmanager
async def public_genshin(self, user_id: int, region: Optional[RegionEnum] = None) -> GenshinClient:
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
) -> GenshinClient:
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`")
@ -355,7 +365,6 @@ class GenshinHelper(Plugin):
async with GenshinClient(
cookies.data,
region=region,
account_id=player.account_id,
player_id=uid,
lang="zh-cn",
device_id=device_id,
@ -366,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
) -> GenshinClient:
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