Add binding by player ID

This commit is contained in:
洛水居室 2023-03-15 20:32:36 +08:00
parent 6a52b4a508
commit 4e87424766
No known key found for this signature in database
GPG Key ID: C9DE87DA724B88FC
2 changed files with 102 additions and 22 deletions

View File

@ -24,7 +24,7 @@ class Player(SQLModel):
default=None, primary_key=True, sa_column=Column(Integer(), primary_key=True, autoincrement=True) default=None, primary_key=True, sa_column=Column(Integer(), primary_key=True, autoincrement=True)
) )
user_id: int = Field(primary_key=True, sa_column=Column(BigInteger())) user_id: int = Field(primary_key=True, sa_column=Column(BigInteger()))
account_id: int = Field(primary_key=True, sa_column=Column(BigInteger())) account_id: int = Field(default=None, primary_key=True, sa_column=Column(BigInteger()))
player_id: int = Field(primary_key=True, sa_column=Column(BigInteger())) player_id: int = Field(primary_key=True, sa_column=Column(BigInteger()))
region: RegionEnum = Field(sa_column=Column(Enum(RegionEnum))) region: RegionEnum = Field(sa_column=Column(Enum(RegionEnum)))
is_chosen: Optional[bool] = Field(sa_column=Column(Boolean)) is_chosen: Optional[bool] = Field(sa_column=Column(Boolean))

View File

@ -3,7 +3,6 @@ from typing import Optional
import genshin import genshin
from genshin import DataNotPublic, GenshinException, types from genshin import DataNotPublic, GenshinException, types
from genshin.models import RecordCard
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, TelegramObject, Update from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, TelegramObject, Update
from telegram.ext import CallbackContext, ConversationHandler, filters from telegram.ext import CallbackContext, ConversationHandler, filters
from telegram.helpers import escape_markdown from telegram.helpers import escape_markdown
@ -21,19 +20,18 @@ __all__ = ("BindAccountPlugin",)
class BindAccountPluginData(TelegramObject): class BindAccountPluginData(TelegramObject):
player: Optional[Player] = None player: Optional[Player] = None
record_card: Optional[RecordCard] = None
region: RegionEnum = RegionEnum.HYPERION region: RegionEnum = RegionEnum.HYPERION
account_id: int = 0 player_id: Optional[int] = None
# player_id: int = 0 nickname: Optional[str] = None
def reset(self): def reset(self):
self.player = None self.player = None
self.region = RegionEnum.NULL self.region = RegionEnum.NULL
self.account_id = 0 self.player_id = None
self.record_card = None self.nickname = None
CHECK_SERVER, CHECK_UID, COMMAND_RESULT = range(10100, 10103) CHECK_SERVER, CHECK_METHOD, CHECK_ACCOUNT_ID, CHECK_PLAYER_ID, COMMAND_RESULT = range(10100, 10105)
class BindAccountPlugin(Plugin.Conversation): class BindAccountPlugin(Plugin.Conversation):
@ -52,7 +50,7 @@ class BindAccountPlugin(Plugin.Conversation):
self.player_info_service = player_info_service self.player_info_service = player_info_service
@conversation.entry_point @conversation.entry_point
@handler.command(command="setuid", filters=filters.ChatType.PRIVATE, block=True) @handler.command(command="setuid", filters=filters.ChatType.PRIVATE, block=False)
async def command_start(self, update: Update, context: CallbackContext) -> int: async def command_start(self, update: Update, context: CallbackContext) -> int:
user = update.effective_user user = update.effective_user
message = update.effective_message message = update.effective_message
@ -72,7 +70,7 @@ class BindAccountPlugin(Plugin.Conversation):
return CHECK_SERVER return CHECK_SERVER
@conversation.state(state=CHECK_SERVER) @conversation.state(state=CHECK_SERVER)
@handler.message(filters=filters.TEXT & ~filters.COMMAND, block=True) @handler.message(filters=filters.TEXT & ~filters.COMMAND, block=False)
async def check_server(self, update: Update, context: CallbackContext) -> int: async def check_server(self, update: Update, context: CallbackContext) -> int:
message = update.effective_message message = update.effective_message
bind_account_plugin_data: BindAccountPluginData = context.chat_data.get("bind_account_plugin_data") bind_account_plugin_data: BindAccountPluginData = context.chat_data.get("bind_account_plugin_data")
@ -86,12 +84,31 @@ class BindAccountPlugin(Plugin.Conversation):
else: else:
await message.reply_text("选择错误,请重新选择") await message.reply_text("选择错误,请重新选择")
return CHECK_SERVER return CHECK_SERVER
await message.reply_text("请输入你的通行证ID非玩家ID", reply_markup=ReplyKeyboardRemove()) reply_keyboard = [["通过玩家ID", "用过账号ID"], ["退出"]]
return CHECK_UID await message.reply_markdown_v2(
"请选择你要绑定的方式", reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)
)
return CHECK_METHOD
@conversation.state(state=CHECK_UID) @conversation.state(state=CHECK_METHOD)
@handler.message(filters=filters.TEXT & ~filters.COMMAND, block=True) @handler.message(filters=filters.TEXT & ~filters.COMMAND, block=False)
async def check_cookies(self, update: Update, context: CallbackContext) -> int: async def check_method(self, update: Update, _: CallbackContext) -> int:
message = update.effective_message
if message.text == "退出":
await message.reply_text("退出任务", reply_markup=ReplyKeyboardRemove())
return ConversationHandler.END
if message.text == "通过玩家ID":
await message.reply_text("请输入你的玩家ID非通行证ID", reply_markup=ReplyKeyboardRemove())
return CHECK_PLAYER_ID
if message.text == "用过账号ID":
await message.reply_text("请输入你的通行证ID非玩家ID", reply_markup=ReplyKeyboardRemove())
return CHECK_ACCOUNT_ID
await message.reply_text("选择错误,请重新选择")
return CHECK_METHOD
@conversation.state(state=CHECK_ACCOUNT_ID)
@handler.message(filters=filters.TEXT & ~filters.COMMAND, block=False)
async def check_account(self, update: Update, context: CallbackContext) -> int:
user = update.effective_user user = update.effective_user
message = update.effective_message message = update.effective_message
bind_account_plugin_data: BindAccountPluginData = context.chat_data.get("bind_account_plugin_data") bind_account_plugin_data: BindAccountPluginData = context.chat_data.get("bind_account_plugin_data")
@ -129,7 +146,7 @@ class BindAccountPlugin(Plugin.Conversation):
logger.exception(exc) logger.exception(exc)
return ConversationHandler.END return ConversationHandler.END
if record_card.game != types.Game.GENSHIN: if record_card.game != types.Game.GENSHIN:
await message.reply_text("角色信息查询返回非原神游戏信息," "请设置展示主界面为原神", reply_markup=ReplyKeyboardRemove()) await message.reply_text("角色信息查询返回非原神游戏信息,请设置展示主界面为原神", reply_markup=ReplyKeyboardRemove())
return ConversationHandler.END return ConversationHandler.END
player_info = await self.players_service.get( player_info = await self.players_service.get(
user.id, player_id=record_card.uid, region=bind_account_plugin_data.region user.id, player_id=record_card.uid, region=bind_account_plugin_data.region
@ -148,12 +165,75 @@ class BindAccountPlugin(Plugin.Conversation):
f"UID`{record_card.uid}`\n" f"UID`{record_card.uid}`\n"
f"服务器名称:`{record_card.server_name}`\n" f"服务器名称:`{record_card.server_name}`\n"
) )
bind_account_plugin_data.record_card = record_card bind_account_plugin_data.player_id = record_card.uid
bind_account_plugin_data.nickname = record_card.nickname
await message.reply_markdown_v2(text, reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True))
return COMMAND_RESULT
@conversation.state(state=CHECK_PLAYER_ID)
@handler.message(filters=filters.TEXT & ~filters.COMMAND, block=False)
async def check_player(self, update: Update, context: CallbackContext) -> int:
user = update.effective_user
message = update.effective_message
bind_account_plugin_data: BindAccountPluginData = context.chat_data.get("bind_account_plugin_data")
region = bind_account_plugin_data.region
if message.text == "退出":
await message.reply_text("退出任务", reply_markup=ReplyKeyboardRemove())
return ConversationHandler.END
try:
player_id = int(message.text)
except ValueError:
await message.reply_text("ID 格式有误,请检查", reply_markup=ReplyKeyboardRemove())
return ConversationHandler.END
try:
cookies = await self.public_cookies_service.get_cookies(user.id, region)
except TooManyRequestPublicCookies:
await message.reply_text("用户查询次数过多,请稍后重试", reply_markup=ReplyKeyboardRemove())
return ConversationHandler.END
if region == RegionEnum.HYPERION:
client = genshin.Client(cookies=cookies.data, game=types.Game.GENSHIN, region=types.Region.CHINESE)
elif region == RegionEnum.HOYOLAB:
client = genshin.Client(
cookies=cookies.data, game=types.Game.GENSHIN, region=types.Region.OVERSEAS, lang="zh-cn"
)
else:
return ConversationHandler.END
try:
player_stats = await client.get_genshin_user(player_id)
except DataNotPublic:
await message.reply_text("角色未公开", reply_markup=ReplyKeyboardRemove())
logger.warning("获取账号信息发生错误 %s 账户信息未公开", player_id)
return ConversationHandler.END
except GenshinException as exc:
if exc.retcode == 1034:
await message.reply_text("出错了呜呜呜 ~ 请稍后重试")
return ConversationHandler.END
await message.reply_text("获取账号信息发生错误", reply_markup=ReplyKeyboardRemove())
logger.error("获取账号信息发生错误")
logger.exception(exc)
return ConversationHandler.END
player_info = await self.players_service.get(
user.id, player_id=player_id, region=bind_account_plugin_data.region
)
if player_info:
await message.reply_text("你已经绑定该账号")
return ConversationHandler.END
reply_keyboard = [["确认", "退出"]]
await message.reply_text("获取角色基础信息成功,请检查是否正确!")
logger.info("用户 %s[%s] 获取账号 %s[%s] 信息成功", user.full_name, user.id, player_stats.info.nickname, player_id)
text = (
f"*角色信息*\n"
f"角色名称:{escape_markdown(player_stats.info.nickname, version=2)}\n"
f"角色等级:{player_stats.info.level}\n"
f"UID`{player_id}`\n"
)
bind_account_plugin_data.player_id = player_id
bind_account_plugin_data.nickname = player_stats.info.nickname
await message.reply_markdown_v2(text, reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)) await message.reply_markdown_v2(text, reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True))
return COMMAND_RESULT return COMMAND_RESULT
@conversation.state(state=COMMAND_RESULT) @conversation.state(state=COMMAND_RESULT)
@handler.message(filters=filters.TEXT & ~filters.COMMAND, block=True) @handler.message(filters=filters.TEXT & ~filters.COMMAND, block=False)
async def command_result(self, update: Update, context: CallbackContext) -> int: async def command_result(self, update: Update, context: CallbackContext) -> int:
user = update.effective_user user = update.effective_user
message = update.effective_message message = update.effective_message
@ -162,15 +242,15 @@ 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 == "确认":
record_card = bind_account_plugin_data.record_card player_id = bind_account_plugin_data.player_id
nickname = bind_account_plugin_data.nickname
is_chosen = True is_chosen = True
player_info = await self.players_service.get_player(user.id) # 寻找主账号 player_info = await self.players_service.get_player(user.id) # 寻找主账号
if player_info is not None and player_info.is_chosen: if player_info is not None and player_info.is_chosen:
is_chosen = False is_chosen = False
player = Player( player = Player(
user_id=user.id, user_id=user.id,
account_id=bind_account_plugin_data.account_id, player_id=player_id,
player_id=record_card.uid,
region=bind_account_plugin_data.region, region=bind_account_plugin_data.region,
is_chosen=is_chosen, # todo 多账号 is_chosen=is_chosen, # todo 多账号
) )
@ -180,7 +260,7 @@ class BindAccountPlugin(Plugin.Conversation):
player_info = PlayerInfoSQLModel( player_info = PlayerInfoSQLModel(
user_id=player.user_id, user_id=player.user_id,
player_id=player.player_id, player_id=player.player_id,
nickname=record_card.nickname, nickname=nickname,
create_time=datetime.now(), create_time=datetime.now(),
is_update=True, is_update=True,
) # 不添加更新时间 ) # 不添加更新时间