mirror of
https://github.com/PaiGramTeam/PaiGram.git
synced 2024-11-22 07:07:46 +00:00
🐛 Fix support for Chinese public cookies
Co-authored-by: luoshuijs <luoshuijs@outlook.com>
This commit is contained in:
parent
635b8444d5
commit
441713236b
27
alembic/versions/c6282bc5bf67_devices_valid.py
Normal file
27
alembic/versions/c6282bc5bf67_devices_valid.py
Normal 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 ###
|
@ -1,3 +1,5 @@
|
|||||||
|
from typing import Optional
|
||||||
|
|
||||||
from gram_core.base_service import BaseService
|
from gram_core.base_service import BaseService
|
||||||
from gram_core.basemodel import RegionEnum
|
from gram_core.basemodel import RegionEnum
|
||||||
from gram_core.services.cookies.error import CookieServiceError
|
from gram_core.services.cookies.error import CookieServiceError
|
||||||
@ -17,28 +19,43 @@ __all__ = ("CookiesService", "PublicCookiesService")
|
|||||||
|
|
||||||
|
|
||||||
class PublicCookiesService(BaseService, BasePublicCookiesService):
|
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 #
|
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:
|
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:
|
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:
|
else:
|
||||||
raise CookieServiceError
|
raise CookieServiceError
|
||||||
try:
|
try:
|
||||||
if client.account_id is None:
|
if client.account_id is None:
|
||||||
raise RuntimeError("account_id not found")
|
raise RuntimeError("account_id not found")
|
||||||
record_cards = await client.get_record_cards()
|
record_cards = await client.get_record_cards()
|
||||||
if client.region == Region.OVERSEAS:
|
for record_card in record_cards:
|
||||||
for record_card in record_cards:
|
if record_card.game == Game.GENSHIN:
|
||||||
if record_card.game == Game.GENSHIN:
|
await client.get_partial_genshin_user(record_card.uid)
|
||||||
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
|
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:
|
except InvalidCookies as exc:
|
||||||
if exc.ret_code in (10001, -100):
|
if exc.ret_code in (10001, -100):
|
||||||
logger.warning("用户 [%s] Cookies无效", public_id)
|
logger.warning("用户 [%s] Cookies无效", public_id)
|
||||||
@ -62,6 +79,7 @@ class PublicCookiesService(BaseService, BasePublicCookiesService):
|
|||||||
raise exc
|
raise exc
|
||||||
if exc.ret_code == 1034:
|
if exc.ret_code == 1034:
|
||||||
logger.warning("用户 [%s] 触发验证", public_id)
|
logger.warning("用户 [%s] 触发验证", public_id)
|
||||||
|
await self.set_device_valid(client.account_id, False)
|
||||||
else:
|
else:
|
||||||
logger.warning("用户 [%s] 获取账号信息发生错误,错误信息为", public_id)
|
logger.warning("用户 [%s] 获取账号信息发生错误,错误信息为", public_id)
|
||||||
logger.exception(exc)
|
logger.exception(exc)
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit f5994842531164370fef6a34400d04b955c68d11
|
Subproject commit f18ce6dd6da2bb54a375bbb3ab46f638af8a6e51
|
@ -15,10 +15,10 @@ from telegram.helpers import escape_markdown
|
|||||||
from core.basemodel import RegionEnum
|
from core.basemodel import RegionEnum
|
||||||
from core.plugin import Plugin, conversation, handler
|
from core.plugin import Plugin, conversation, handler
|
||||||
from core.services.cookies.error import TooManyRequestPublicCookies
|
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.cookies.services import CookiesService, PublicCookiesService
|
||||||
from core.services.players.models import PlayersDataBase as Player, PlayerInfoSQLModel
|
from core.services.players.models import PlayersDataBase as Player, PlayerInfoSQLModel
|
||||||
from core.services.players.services import PlayersService, PlayerInfoService
|
from core.services.players.services import PlayersService, PlayerInfoService
|
||||||
|
from plugins.tools.genshin import GenshinHelper
|
||||||
from utils.log import logger
|
from utils.log import logger
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@ -51,11 +51,13 @@ class BindAccountPlugin(Plugin.Conversation):
|
|||||||
cookies_service: CookiesService = None,
|
cookies_service: CookiesService = None,
|
||||||
player_info_service: PlayerInfoService = None,
|
player_info_service: PlayerInfoService = None,
|
||||||
public_cookies_service: PublicCookiesService = None,
|
public_cookies_service: PublicCookiesService = None,
|
||||||
|
helper: GenshinHelper = None,
|
||||||
):
|
):
|
||||||
self.public_cookies_service = public_cookies_service
|
self.public_cookies_service = public_cookies_service
|
||||||
self.cookies_service = cookies_service
|
self.cookies_service = cookies_service
|
||||||
self.players_service = players_service
|
self.players_service = players_service
|
||||||
self.player_info_service = player_info_service
|
self.player_info_service = player_info_service
|
||||||
|
self.helper = helper
|
||||||
|
|
||||||
@conversation.entry_point
|
@conversation.entry_point
|
||||||
@handler.command(command="setuid", filters=filters.ChatType.PRIVATE, block=False)
|
@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())
|
await message.reply_text("退出任务", reply_markup=ReplyKeyboardRemove())
|
||||||
return ConversationHandler.END
|
return ConversationHandler.END
|
||||||
if message.text == "米游社":
|
if message.text == "米游社":
|
||||||
reply_keyboard = [["通过账号ID"], ["退出"]]
|
|
||||||
bind_account_plugin_data.region = RegionEnum.HYPERION
|
bind_account_plugin_data.region = RegionEnum.HYPERION
|
||||||
elif message.text == "HoYoLab":
|
elif message.text == "HoYoLab":
|
||||||
reply_keyboard = [["通过玩家ID", "通过账号ID"], ["退出"]]
|
|
||||||
bind_account_plugin_data.region = RegionEnum.HOYOLAB
|
bind_account_plugin_data.region = RegionEnum.HOYOLAB
|
||||||
else:
|
else:
|
||||||
await message.reply_text("选择错误,请重新选择")
|
await message.reply_text("选择错误,请重新选择")
|
||||||
return CHECK_SERVER
|
return CHECK_SERVER
|
||||||
|
reply_keyboard = [["通过玩家ID", "通过账号ID"], ["退出"]]
|
||||||
await message.reply_markdown_v2(
|
await message.reply_markdown_v2(
|
||||||
"请选择你要绑定的方式", reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)
|
"请选择你要绑定的方式", reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)
|
||||||
)
|
)
|
||||||
@ -101,17 +102,16 @@ class BindAccountPlugin(Plugin.Conversation):
|
|||||||
|
|
||||||
@conversation.state(state=CHECK_METHOD)
|
@conversation.state(state=CHECK_METHOD)
|
||||||
@handler.message(filters=filters.TEXT & ~filters.COMMAND, block=False)
|
@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
|
message = update.effective_message
|
||||||
bind_account_plugin_data: BindAccountPluginData = context.chat_data.get("bind_account_plugin_data")
|
|
||||||
if message.text == "退出":
|
if message.text == "退出":
|
||||||
await message.reply_text("退出任务", reply_markup=ReplyKeyboardRemove())
|
await message.reply_text("退出任务", reply_markup=ReplyKeyboardRemove())
|
||||||
return ConversationHandler.END
|
return ConversationHandler.END
|
||||||
if message.text == "通过玩家ID" and bind_account_plugin_data.region != RegionEnum.HYPERION:
|
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
|
return CHECK_PLAYER_ID
|
||||||
if message.text == "通过账号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
|
return CHECK_ACCOUNT_ID
|
||||||
await message.reply_text("选择错误,请重新选择")
|
await message.reply_text("选择错误,请重新选择")
|
||||||
return CHECK_METHOD
|
return CHECK_METHOD
|
||||||
@ -194,18 +194,11 @@ class BindAccountPlugin(Plugin.Conversation):
|
|||||||
await message.reply_text("ID 格式有误,请检查", reply_markup=ReplyKeyboardRemove())
|
await message.reply_text("ID 格式有误,请检查", reply_markup=ReplyKeyboardRemove())
|
||||||
return ConversationHandler.END
|
return ConversationHandler.END
|
||||||
try:
|
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:
|
except TooManyRequestPublicCookies:
|
||||||
await message.reply_text("用户查询次数过多,请稍后重试", reply_markup=ReplyKeyboardRemove())
|
await message.reply_text("用户查询次数过多,请稍后重试", reply_markup=ReplyKeyboardRemove())
|
||||||
return ConversationHandler.END
|
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:
|
except AccountNotFound:
|
||||||
await message.reply_text("找不到用户,uid可能无效", reply_markup=ReplyKeyboardRemove())
|
await message.reply_text("找不到用户,uid可能无效", reply_markup=ReplyKeyboardRemove())
|
||||||
logger.warning("获取账号信息发生错误 %s 找不到用户 uid可能无效", player_id)
|
logger.warning("获取账号信息发生错误 %s 找不到用户 uid可能无效", player_id)
|
||||||
@ -215,12 +208,11 @@ class BindAccountPlugin(Plugin.Conversation):
|
|||||||
logger.warning("获取账号信息发生错误 %s 账户信息未公开", player_id)
|
logger.warning("获取账号信息发生错误 %s 账户信息未公开", player_id)
|
||||||
return ConversationHandler.END
|
return ConversationHandler.END
|
||||||
except InvalidCookies:
|
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")
|
await message.reply_text("出错了呜呜呜 ~ 请稍后重试或者绑定 cookie")
|
||||||
return ConversationHandler.END
|
return ConversationHandler.END
|
||||||
except SimnetBadRequest as exc:
|
except SimnetBadRequest as exc:
|
||||||
if exc.ret_code == 1034:
|
if exc.ret_code == 1034:
|
||||||
await self.public_cookies_service.undo(user.id)
|
|
||||||
await message.reply_text("出错了呜呜呜 ~ 请稍后重试或者绑定 cookie")
|
await message.reply_text("出错了呜呜呜 ~ 请稍后重试或者绑定 cookie")
|
||||||
return ConversationHandler.END
|
return ConversationHandler.END
|
||||||
await message.reply_text("获取账号信息发生错误", reply_markup=ReplyKeyboardRemove())
|
await message.reply_text("获取账号信息发生错误", reply_markup=ReplyKeyboardRemove())
|
||||||
@ -230,8 +222,6 @@ class BindAccountPlugin(Plugin.Conversation):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
await message.reply_text("ID 格式有误,请检查", reply_markup=ReplyKeyboardRemove())
|
await message.reply_text("ID 格式有误,请检查", reply_markup=ReplyKeyboardRemove())
|
||||||
return ConversationHandler.END
|
return ConversationHandler.END
|
||||||
finally:
|
|
||||||
await client.shutdown()
|
|
||||||
player_info = await self.players_service.get(
|
player_info = await self.players_service.get(
|
||||||
user.id, player_id=player_id, region=bind_account_plugin_data.region
|
user.id, player_id=player_id, region=bind_account_plugin_data.region
|
||||||
)
|
)
|
||||||
|
@ -237,7 +237,8 @@ class AccountCookiesPlugin(Plugin.Conversation):
|
|||||||
try:
|
try:
|
||||||
account_cookies_plugin_data.device = self.parse_headers(cookie)
|
account_cookies_plugin_data.device = self.parse_headers(cookie)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
await message.reply_text("警告,解析 Devices 出现错误,可能无法绕过风控,查询操作将需要通过验证。")
|
account_cookies_plugin_data.device = None
|
||||||
|
await message.reply_text("解析 Devices 出现错误,可能无法绕过风控,查询操作将需要通过验证。")
|
||||||
if not cookies:
|
if not cookies:
|
||||||
logger.info("用户 %s[%s] Cookies格式有误", user.full_name, user.id)
|
logger.info("用户 %s[%s] Cookies格式有误", user.full_name, user.id)
|
||||||
await message.reply_text("Cookies格式有误,请检查后重新尝试绑定", reply_markup=ReplyKeyboardRemove())
|
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_id = device.device_id
|
||||||
device_model.device_fp = device.device_fp
|
device_model.device_fp = device.device_fp
|
||||||
device_model.device_name = device.device_name
|
device_model.device_name = device.device_name
|
||||||
|
device_model.is_valid = True
|
||||||
await self.devices_service.update(device_model)
|
await self.devices_service.update(device_model)
|
||||||
else:
|
else:
|
||||||
device_model = Devices(
|
device_model = Devices(
|
||||||
@ -389,6 +391,7 @@ class AccountCookiesPlugin(Plugin.Conversation):
|
|||||||
device_id=device.device_id,
|
device_id=device.device_id,
|
||||||
device_fp=device.device_fp,
|
device_fp=device.device_fp,
|
||||||
device_name=device.device_name,
|
device_name=device.device_name,
|
||||||
|
is_valid=True,
|
||||||
)
|
)
|
||||||
await self.devices_service.add(device_model)
|
await self.devices_service.add(device_model)
|
||||||
|
|
||||||
|
@ -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
|
|
@ -12,6 +12,7 @@ from core.services.cookies import CookiesService
|
|||||||
from core.services.players import PlayersService
|
from core.services.players import PlayersService
|
||||||
from core.services.players.services import PlayerInfoService
|
from core.services.players.services import PlayerInfoService
|
||||||
from gram_core.services.cookies.models import CookiesStatusEnum
|
from gram_core.services.cookies.models import CookiesStatusEnum
|
||||||
|
from gram_core.services.devices import DevicesService
|
||||||
from modules.apihelper.models.genshin.cookies import CookiesModel
|
from modules.apihelper.models.genshin.cookies import CookiesModel
|
||||||
from utils.log import logger
|
from utils.log import logger
|
||||||
|
|
||||||
@ -24,10 +25,17 @@ __all__ = ("PlayersManagesPlugin",)
|
|||||||
|
|
||||||
|
|
||||||
class PlayersManagesPlugin(Plugin):
|
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.cookies_service = cookies
|
||||||
self.players_service = players
|
self.players_service = players
|
||||||
self.player_info_service = player_info_service
|
self.player_info_service = player_info_service
|
||||||
|
self.devices_service = devices_service
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def players_manager_callback(callback_query_data: str) -> Tuple[str, int, int]:
|
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(
|
await callback_query.edit_message_text(
|
||||||
f"玩家 {player.player_id} {player_info.nickname} cookies 未找到", reply_markup=InlineKeyboardMarkup(buttons)
|
f"玩家 {player.player_id} {player_info.nickname} cookies 未找到", reply_markup=InlineKeyboardMarkup(buttons)
|
||||||
)
|
)
|
||||||
|
return
|
||||||
|
device = await self.devices_service.get(player.account_id)
|
||||||
|
|
||||||
cookies = SimpleCookie()
|
cookies = SimpleCookie()
|
||||||
for key, value in cookies_data.data.items():
|
for key, value in cookies_data.data.items():
|
||||||
cookies[key] = value
|
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=";")
|
cookie_str = cookies.output(header="", sep=";")
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ class StartPlugin(Plugin):
|
|||||||
async def process_validate(self, message: Message, user: User, bot_username: Optional[str] = None):
|
async def process_validate(self, message: Message, user: User, bot_username: Optional[str] = None):
|
||||||
await message.reply_text(
|
await message.reply_text(
|
||||||
"由于官方对第三方工具限制以及账户安全的考虑,频繁使用第三方工具会导致账号被风控并要求用过验证才能进行访问。\n"
|
"由于官方对第三方工具限制以及账户安全的考虑,频繁使用第三方工具会导致账号被风控并要求用过验证才能进行访问。\n"
|
||||||
"如出现频繁验证请求,可尝试使用 /setdevice 设置设备标识符以尝试解决该问题。\n"
|
"如出现频繁验证请求,可尝试使用 /setcookies 的新方法重新绑定以尝试解决该问题。\n"
|
||||||
"如担心账号安全,建议修改密码以保护账号安全,修改账号密码后任何登录令牌都会被强制注销。\n"
|
"如担心账号安全,建议修改密码以保护账号安全,修改账号密码后任何登录令牌都会被强制注销。\n"
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
|
@ -8,7 +8,6 @@ from typing import Any, Coroutine, List, Optional, Tuple, Union
|
|||||||
from arkowrapper import ArkoWrapper
|
from arkowrapper import ArkoWrapper
|
||||||
from pytz import timezone
|
from pytz import timezone
|
||||||
from simnet import GenshinClient
|
from simnet import GenshinClient
|
||||||
from simnet.errors import BadRequest as SimnetBadRequest
|
|
||||||
from telegram import Message, Update
|
from telegram import Message, Update
|
||||||
from telegram.constants import ChatAction, ParseMode
|
from telegram.constants import ChatAction, ParseMode
|
||||||
from telegram.ext import CallbackContext, filters
|
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.cookies.error import TooManyRequestPublicCookies
|
||||||
from core.services.template.models import RenderGroupResult, RenderResult
|
from core.services.template.models import RenderGroupResult, RenderResult
|
||||||
from core.services.template.services import TemplateService
|
from core.services.template.services import TemplateService
|
||||||
from gram_core.basemodel import RegionEnum
|
from plugins.tools.genshin import GenshinHelper
|
||||||
from plugins.tools.genshin import CookiesNotFoundError, GenshinHelper
|
|
||||||
from utils.log import logger
|
from utils.log import logger
|
||||||
from utils.uid import mask_number
|
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 #
|
async def command_start(self, update: Update, _: CallbackContext) -> None: # skipcq: PY-R1000 #
|
||||||
user = update.effective_user
|
user = update.effective_user
|
||||||
message = update.effective_message
|
message = update.effective_message
|
||||||
uid: Optional[int] = None
|
|
||||||
|
|
||||||
# 若查询帮助
|
# 若查询帮助
|
||||||
if (message.text.startswith("/") and "help" in message.text) or "帮助" in message.text:
|
if (message.text.startswith("/") and "help" in message.text) or "帮助" in message.text:
|
||||||
@ -124,20 +121,11 @@ class AbyssPlugin(Plugin):
|
|||||||
|
|
||||||
if total:
|
if total:
|
||||||
reply_text = await message.reply_text("派蒙需要时间整理深渊数据,还请耐心等待哦~")
|
reply_text = await message.reply_text("派蒙需要时间整理深渊数据,还请耐心等待哦~")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
try:
|
async with self.helper.genshin_or_public(user.id) as client:
|
||||||
async with self.helper.genshin(user.id) as client:
|
if not client.public:
|
||||||
await client.get_record_cards()
|
await client.get_record_cards()
|
||||||
images = await self.get_rendered_pic(client, client.player_id, floor, total, previous)
|
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
|
|
||||||
except AbyssUnlocked: # 若深渊未解锁
|
except AbyssUnlocked: # 若深渊未解锁
|
||||||
await message.reply_text("还未解锁深渊哦~")
|
await message.reply_text("还未解锁深渊哦~")
|
||||||
return
|
return
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import random
|
import random
|
||||||
from typing import Optional, TYPE_CHECKING
|
from typing import Optional, TYPE_CHECKING
|
||||||
|
|
||||||
from simnet.errors import BadRequest as SimnetBadRequest
|
|
||||||
from telegram.constants import ChatAction
|
from telegram.constants import ChatAction
|
||||||
from telegram.ext import filters
|
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.cookies.error import TooManyRequestPublicCookies
|
||||||
from core.services.template.models import RenderResult
|
from core.services.template.models import RenderResult
|
||||||
from core.services.template.services import TemplateService
|
from core.services.template.services import TemplateService
|
||||||
from gram_core.basemodel import RegionEnum
|
from plugins.tools.genshin import GenshinHelper
|
||||||
from plugins.tools.genshin import CookiesNotFoundError, GenshinHelper
|
|
||||||
from utils.log import logger
|
from utils.log import logger
|
||||||
from utils.uid import mask_number
|
from utils.uid import mask_number
|
||||||
|
|
||||||
@ -46,17 +43,10 @@ class PlayerStatsPlugins(Plugin):
|
|||||||
await message.reply_text("输入错误")
|
await message.reply_text("输入错误")
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
try:
|
async with self.helper.genshin_or_public(user.id) as client:
|
||||||
async with self.helper.genshin(user.id) as client:
|
if not client.public:
|
||||||
await client.get_record_cards()
|
await client.get_record_cards()
|
||||||
render_result = await self.render(client, uid)
|
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
|
|
||||||
except TooManyRequestPublicCookies:
|
except TooManyRequestPublicCookies:
|
||||||
await message.reply_text("用户查询次数过多 请稍后重试")
|
await message.reply_text("用户查询次数过多 请稍后重试")
|
||||||
return
|
return
|
||||||
|
@ -10,6 +10,7 @@ from simnet import GenshinClient, Region
|
|||||||
from simnet.errors import BadRequest as SimnetBadRequest, InvalidCookies, NetworkError, CookieException
|
from simnet.errors import BadRequest as SimnetBadRequest, InvalidCookies, NetworkError, CookieException
|
||||||
from simnet.models.genshin.calculator import CalculatorCharacterDetails
|
from simnet.models.genshin.calculator import CalculatorCharacterDetails
|
||||||
from simnet.models.genshin.chronicle.characters import Character
|
from simnet.models.genshin.chronicle.characters import Character
|
||||||
|
from simnet.utils.player import recognize_game_biz
|
||||||
from sqlalchemy.exc import SQLAlchemyError
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
from sqlalchemy.orm.exc import StaleDataError
|
from sqlalchemy.orm.exc import StaleDataError
|
||||||
from sqlmodel import BigInteger, Column, DateTime, Field, Index, Integer, SQLModel, String, delete, func, select
|
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))
|
raise ServiceNotFoundError(*filter(lambda x: x is None, temp))
|
||||||
|
|
||||||
@asynccontextmanager
|
@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)
|
player = await self.players_service.get_player(user_id, region)
|
||||||
if player is None:
|
if player is None:
|
||||||
raise PlayerNotFoundError(user_id)
|
raise PlayerNotFoundError(user_id)
|
||||||
@ -254,6 +255,11 @@ class GenshinHelper(Plugin):
|
|||||||
) as client:
|
) as client:
|
||||||
try:
|
try:
|
||||||
yield client
|
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:
|
except InvalidCookies as exc:
|
||||||
refresh = False
|
refresh = False
|
||||||
cookie_model.status = CookiesStatusEnum.INVALID_COOKIES
|
cookie_model.status = CookiesStatusEnum.INVALID_COOKIES
|
||||||
@ -331,16 +337,20 @@ class GenshinHelper(Plugin):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def public_genshin(self, user_id: int, region: Optional[RegionEnum] = None) -> GenshinClient:
|
async def public_genshin(
|
||||||
player = await self.players_service.get_player(user_id, region)
|
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)
|
cookies = await self.public_cookies_service.get_cookies(user_id, region)
|
||||||
|
|
||||||
uid = player.player_id
|
if region == RegionEnum.HYPERION:
|
||||||
if player.region == RegionEnum.HYPERION:
|
|
||||||
region = Region.CHINESE
|
region = Region.CHINESE
|
||||||
elif player.region == RegionEnum.HOYOLAB:
|
elif region == RegionEnum.HOYOLAB:
|
||||||
region = Region.OVERSEAS
|
region = Region.OVERSEAS
|
||||||
else:
|
else:
|
||||||
raise TypeError("Region is not `RegionEnum.NULL`")
|
raise TypeError("Region is not `RegionEnum.NULL`")
|
||||||
@ -355,7 +365,6 @@ class GenshinHelper(Plugin):
|
|||||||
async with GenshinClient(
|
async with GenshinClient(
|
||||||
cookies.data,
|
cookies.data,
|
||||||
region=region,
|
region=region,
|
||||||
account_id=player.account_id,
|
|
||||||
player_id=uid,
|
player_id=uid,
|
||||||
lang="zh-cn",
|
lang="zh-cn",
|
||||||
device_id=device_id,
|
device_id=device_id,
|
||||||
@ -366,4 +375,28 @@ class GenshinHelper(Plugin):
|
|||||||
except SimnetBadRequest as exc:
|
except SimnetBadRequest as exc:
|
||||||
if exc.ret_code == 1034:
|
if exc.ret_code == 1034:
|
||||||
await self.public_cookies_service.undo(user_id)
|
await self.public_cookies_service.undo(user_id)
|
||||||
|
await self.public_cookies_service.set_device_valid(client.account_id, False)
|
||||||
raise exc
|
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
|
||||||
|
Loading…
Reference in New Issue
Block a user