diff --git a/alembic/versions/c6282bc5bf67_devices_valid.py b/alembic/versions/c6282bc5bf67_devices_valid.py
new file mode 100644
index 0000000..1e2b6f4
--- /dev/null
+++ b/alembic/versions/c6282bc5bf67_devices_valid.py
@@ -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 ###
diff --git a/core/services/cookies/services.py b/core/services/cookies/services.py
index 2aaad2e..2916cba 100644
--- a/core/services/cookies/services.py
+++ b/core/services/cookies/services.py
@@ -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)
diff --git a/gram_core b/gram_core
index f599484..f18ce6d 160000
--- a/gram_core
+++ b/gram_core
@@ -1 +1 @@
-Subproject commit f5994842531164370fef6a34400d04b955c68d11
+Subproject commit f18ce6dd6da2bb54a375bbb3ab46f638af8a6e51
diff --git a/plugins/account/account.py b/plugins/account/account.py
index 7966123..9189f3c 100644
--- a/plugins/account/account.py
+++ b/plugins/account/account.py
@@ -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
)
diff --git a/plugins/account/cookies.py b/plugins/account/cookies.py
index 382e076..9c808dc 100644
--- a/plugins/account/cookies.py
+++ b/plugins/account/cookies.py
@@ -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)
diff --git a/plugins/account/devices.py b/plugins/account/devices.py
deleted file mode 100644
index 058613e..0000000
--- a/plugins/account/devices.py
+++ /dev/null
@@ -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 = (
- "关于如何获取Device\n"
- "此操作只能在PC上进行。\n\n"
- "PC:\n"
- "1、打开通行证并登录\n"
- "2、进入通行证按F12打开开发者工具\n"
- "3、将开发者工具切换至网络(Network)并点击过滤栏中的 Fetch/XHR 并刷新页面\n"
- "4、在请求列表中找到 login_by_cookie\n"
- "5、右键并复制请求标头(Request Headers)\n"
- "如发现没有此请求大概因为缓存的存在需要你点击禁用缓存(Disable Cache)再次刷新页面"
- )
- 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
diff --git a/plugins/account/players.py b/plugins/account/players.py
index c86b665..d5319bf 100644
--- a/plugins/account/players.py
+++ b/plugins/account/players.py
@@ -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=";")
diff --git a/plugins/app/gift.py b/plugins/app/gift.py
index 1886a4a..4b0aed7 100644
--- a/plugins/app/gift.py
+++ b/plugins/app/gift.py
@@ -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
diff --git a/plugins/app/inline.py b/plugins/app/inline.py
index 9ad88a1..8931e36 100644
--- a/plugins/app/inline.py
+++ b/plugins/app/inline.py
@@ -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
diff --git a/plugins/app/start.py b/plugins/app/start.py
index 0eec97c..e108bd5 100644
--- a/plugins/app/start.py
+++ b/plugins/app/start.py
@@ -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:
diff --git a/plugins/starrail/activity.py b/plugins/starrail/activity.py
index 88fed40..00d9a56 100644
--- a/plugins/starrail/activity.py
+++ b/plugins/starrail/activity.py
@@ -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)
diff --git a/plugins/starrail/challenge.py b/plugins/starrail/challenge.py
index 3a77fdb..bc0a756 100644
--- a/plugins/starrail/challenge.py
+++ b/plugins/starrail/challenge.py
@@ -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
diff --git a/plugins/starrail/museum.py b/plugins/starrail/museum.py
index fb6af1d..cdec14c 100644
--- a/plugins/starrail/museum.py
+++ b/plugins/starrail/museum.py
@@ -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
diff --git a/plugins/starrail/rogue.py b/plugins/starrail/rogue.py
index 2ceb9b5..217e18e 100644
--- a/plugins/starrail/rogue.py
+++ b/plugins/starrail/rogue.py
@@ -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
diff --git a/plugins/starrail/stats.py b/plugins/starrail/stats.py
index 3bcd827..1bdd38f 100644
--- a/plugins/starrail/stats.py
+++ b/plugins/starrail/stats.py
@@ -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
diff --git a/plugins/tools/genshin.py b/plugins/tools/genshin.py
index 0b1eb21..da3c4de 100644
--- a/plugins/tools/genshin.py
+++ b/plugins/tools/genshin.py
@@ -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