️ 优化导入抽卡记录命令,无需绑定 Cookie

This commit is contained in:
omg-xtao 2022-10-08 18:56:40 +08:00 committed by GitHub
parent 7f2bb53c7f
commit bbb6cd6e82
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 108 additions and 97 deletions

View File

@ -160,7 +160,7 @@ class GachaLog:
""" """
data, state = await GachaLog.load_history_info(user_id, uid) data, state = await GachaLog.load_history_info(user_id, uid)
if not state: if not state:
return False, f'UID{uid} 还没有导入任何抽卡记录数据。', None return False, f'派蒙还没有找到你导入的任何抽卡记录哦,快试试导入吧~', None
save_path = GACHA_LOG_PATH / f'{user_id}-{uid}-uigf.json' save_path = GACHA_LOG_PATH / f'{user_id}-{uid}-uigf.json'
uigf_dict = { uigf_dict = {
'info': { 'info': {
@ -456,12 +456,12 @@ class GachaLog:
""" """
gacha_log, status = await GachaLog.load_history_info(str(user_id), str(client.uid)) gacha_log, status = await GachaLog.load_history_info(str(user_id), str(client.uid))
if not status: if not status:
return "获取数据失败,未找到抽卡记录" return "派蒙没有找到你的抽卡记录,快来私聊派蒙导入吧~"
pool_name = GACHA_TYPE_LIST[pool] pool_name = GACHA_TYPE_LIST[pool]
data = gacha_log.item_list[pool_name] data = gacha_log.item_list[pool_name]
total = len(data) total = len(data)
if total == 0: if total == 0:
return "获取数据失败,未找到抽卡记录" return "派蒙没有找到这个卡池的抽卡记录,快来私聊派蒙导入吧~"
all_five, no_five_star = await GachaLog.get_all_5_star_items(data, assets, pool_name) all_five, no_five_star = await GachaLog.get_all_5_star_items(data, assets, pool_name)
all_four, no_four_star = await GachaLog.get_all_4_star_items(data, assets) all_four, no_four_star = await GachaLog.get_all_4_star_items(data, assets)
summon_data = None summon_data = None
@ -498,12 +498,12 @@ class GachaLog:
""" """
gacha_log, status = await GachaLog.load_history_info(str(user_id), str(client.uid)) gacha_log, status = await GachaLog.load_history_info(str(user_id), str(client.uid))
if not status: if not status:
return "获取数据失败,未找到抽卡记录" return "派蒙没有找到你的抽卡记录,快来私聊派蒙导入吧~"
pool_name = GACHA_TYPE_LIST[pool] pool_name = GACHA_TYPE_LIST[pool]
data = gacha_log.item_list[pool_name] data = gacha_log.item_list[pool_name]
total = len(data) total = len(data)
if total == 0: if total == 0:
return "获取数据失败,未找到抽卡记录" return "派蒙没有找到这个卡池的抽卡记录,快来私聊派蒙导入吧~"
all_five, _ = await GachaLog.get_all_5_star_items(data, assets, pool_name) all_five, _ = await GachaLog.get_all_5_star_items(data, assets, pool_name)
all_four, _ = await GachaLog.get_all_4_star_items(data, assets) all_four, _ = await GachaLog.get_all_4_star_items(data, assets)
pool_data = [] pool_data = []

View File

@ -1,10 +1,9 @@
import json import json
import os
from io import BytesIO
from io import BytesIO
from genshin.models import BannerType from genshin.models import BannerType
from pyppeteer import launch
from telegram import Update, User from telegram import Update, User, Message, Document
from telegram.constants import ChatAction from telegram.constants import ChatAction
from telegram.ext import CallbackContext, CommandHandler, MessageHandler, filters, ConversationHandler from telegram.ext import CallbackContext, CommandHandler, MessageHandler, filters, ConversationHandler
@ -13,6 +12,7 @@ from core.baseplugin import BasePlugin
from core.cookies.error import CookiesNotFoundError from core.cookies.error import CookiesNotFoundError
from core.plugin import Plugin, handler, conversation from core.plugin import Plugin, handler, conversation
from core.template import TemplateService from core.template import TemplateService
from core.user import UserService
from core.user.error import UserNotFoundError from core.user.error import UserNotFoundError
from modules.apihelper.gacha_log import GachaLog as GachaLogService from modules.apihelper.gacha_log import GachaLog as GachaLogService
from utils.bot import get_all_args from utils.bot import get_all_args
@ -27,13 +27,10 @@ INPUT_URL, INPUT_FILE = 10100, 10101
class GachaLog(Plugin.Conversation, BasePlugin.Conversation): class GachaLog(Plugin.Conversation, BasePlugin.Conversation):
""" 抽卡记录导入/导出/分析""" """ 抽卡记录导入/导出/分析"""
def __init__(self, template_service: TemplateService = None, assets: AssetsService = None): def __init__(self, template_service: TemplateService = None, user_service: UserService = None,
assets: AssetsService = None):
self.template_service = template_service self.template_service = template_service
self.browser: launch = None self.user_service = user_service
self.current_dir = os.getcwd()
self.resources_dir = os.path.join(self.current_dir, "resources")
self.character_gacha_card = {}
self.user_time = {}
self.assets_service = assets self.assets_service = assets
@staticmethod @staticmethod
@ -57,66 +54,22 @@ class GachaLog(Plugin.Conversation, BasePlugin.Conversation):
""" """
try: try:
logger.debug("尝试获取已绑定的原神账号") logger.debug("尝试获取已绑定的原神账号")
client = await get_genshin_client(user.id) client = await get_genshin_client(user.id, need_cookie=False)
if authkey: if authkey:
return await GachaLogService.get_gacha_log_data(user.id, client, authkey) return await GachaLogService.get_gacha_log_data(user.id, client, authkey)
if data: if data:
return await GachaLogService.import_gacha_log_data(user.id, data) return await GachaLogService.import_gacha_log_data(user.id, data)
except (UserNotFoundError, CookiesNotFoundError): except UserNotFoundError:
logger.info(f"未查询到用户({user.full_name} {user.id}) 所绑定的账号信息") logger.info(f"未查询到用户({user.full_name} {user.id}) 所绑定的账号信息")
return "未查询到您所绑定的账号信息,请先私聊派蒙绑定账号" return "派蒙没有找到您所绑定的账号信息,请先私聊派蒙绑定账号"
@conversation.entry_point async def import_from_file(self, user: User, message: Message, document: Document = None) -> None:
@handler(CommandHandler, command="gacha_log_refresh", filters=filters.ChatType.PRIVATE, block=True)
@handler(MessageHandler, filters=filters.Regex("^更新抽卡记录(.*)") & filters.ChatType.PRIVATE, block=True)
@restricts()
@error_callable
async def command_start(self, update: Update, context: CallbackContext) -> int:
message = update.effective_message
user = update.effective_user
args = get_all_args(context)
if not args:
await message.reply_text("请发送从游戏中获取到的抽卡记录链接\n\n"
"获取抽卡记录链接教程https://paimon.moe/wish/import")
return INPUT_URL
authkey = self.from_url_get_authkey(args[0])
data = await self._refresh_user_data(user, authkey=authkey)
await message.reply_text(data)
@conversation.state(state=INPUT_URL)
@handler.message(filters=filters.TEXT & ~filters.COMMAND,
block=True)
@restricts()
@error_callable
async def import_data_from_url(self, update: Update, _: CallbackContext) -> int:
message = update.effective_message
user = update.effective_user
authkey = self.from_url_get_authkey(message.text)
reply = await message.reply_text("正在从米哈游服务器获取数据,请稍后")
text = await self._refresh_user_data(user, authkey=authkey)
await reply.edit_text(text)
return ConversationHandler.END
@handler(CommandHandler, command="gacha_log_import", filters=filters.ChatType.PRIVATE, block=True)
@handler(MessageHandler, filters=filters.Regex("^导入抽卡记录(.*)") & filters.ChatType.PRIVATE, block=True)
@restricts()
@error_callable
async def command_start_import(self, update: Update, _: CallbackContext) -> None:
message = update.effective_message
user = update.effective_user
if message.reply_to_message:
document = message.reply_to_message.document
else:
document = message.document
if not document: if not document:
await message.reply_text("请回复符合 UIGF 标准的抽卡记录文件") document = message.document
return
if not document.file_name.endswith(".json"): if not document.file_name.endswith(".json"):
await message.reply_text("文件格式错误,请发送符合 UIGF 标准的抽卡记录文件") await message.reply_text("文件格式错误,请发送符合 UIGF 标准的抽卡记录文件")
return
if document.file_size > 50 * 1024 * 1024: if document.file_size > 50 * 1024 * 1024:
await message.reply_text("文件过大,请发送小于 50MB 的文件") await message.reply_text("文件过大,请发送小于 50MB 的文件")
return
try: try:
data = BytesIO() data = BytesIO()
await (await document.get_file()).download(out=data) await (await document.get_file()).download(out=data)
@ -127,37 +80,80 @@ class GachaLog(Plugin.Conversation, BasePlugin.Conversation):
logger.error(f"文件解析失败:{repr(exc)}") logger.error(f"文件解析失败:{repr(exc)}")
await message.reply_text("文件解析失败,请检查文件是否符合 UIGF 标准") await message.reply_text("文件解析失败,请检查文件是否符合 UIGF 标准")
return return
await message.reply_chat_action(ChatAction.TYPING)
reply = await message.reply_text("文件解析成功,正在导入数据") reply = await message.reply_text("文件解析成功,正在导入数据")
try: try:
text = await self._refresh_user_data(user, data=data) text = await self._refresh_user_data(user, data=data)
except Exception as exc: except Exception as exc:
logger.error(f"文件解析失败:{repr(exc)}") logger.error(f"文件解析失败:{repr(exc)}")
await reply.edit_text("文件解析失败,请检查文件是否符合 UIGF 标准") text = "文件解析失败,请检查文件是否符合 UIGF 标准"
return
await reply.edit_text(text) await reply.edit_text(text)
return
@handler(CommandHandler, command="gacha_log_export", filters=filters.ChatType.PRIVATE, block=True) @conversation.entry_point
@handler(MessageHandler, filters=filters.Regex("^导出抽卡记录(.*)") & filters.ChatType.PRIVATE, block=True) @handler(CommandHandler, command="gacha_log_import", filters=filters.ChatType.PRIVATE, block=False)
@handler(MessageHandler, filters=filters.Regex("^导入抽卡记录(.*)") & filters.ChatType.PRIVATE, block=False)
@restricts()
@error_callable
async def command_start(self, update: Update, context: CallbackContext) -> int:
message = update.effective_message
user = update.effective_user
args = get_all_args(context)
logger.info(f"用户 {user.full_name}[{user.id}] 导入抽卡记录命令请求")
if not args:
if message.document:
await self.import_from_file(user, message)
return ConversationHandler.END
elif message.reply_to_message and message.reply_to_message.document:
await self.import_from_file(user, message, document=message.reply_to_message.document)
return ConversationHandler.END
await message.reply_text("<b>导入祈愿历史记录</b>\n\n"
"请直接向派蒙发送从游戏中获取到的抽卡记录链接\n\n"
"获取抽卡记录链接可以参考https://paimon.moe/wish/import",
parse_mode="html")
return INPUT_URL
authkey = self.from_url_get_authkey(args[0])
data = await self._refresh_user_data(user, authkey=authkey)
await message.reply_text(data)
@conversation.state(state=INPUT_URL)
@handler.message(filters=~filters.COMMAND, block=False)
@restricts()
@error_callable
async def import_data_from_message(self, update: Update, _: CallbackContext) -> int:
message = update.effective_message
user = update.effective_user
if message.document:
await self.import_from_file(user, message)
return ConversationHandler.END
authkey = self.from_url_get_authkey(message.text)
reply = await message.reply_text("小派蒙正在从米哈游服务器获取数据,请稍后")
text = await self._refresh_user_data(user, authkey=authkey)
await reply.edit_text(text)
return ConversationHandler.END
@handler(CommandHandler, command="gacha_log_export", filters=filters.ChatType.PRIVATE, block=False)
@handler(MessageHandler, filters=filters.Regex("^导出抽卡记录(.*)") & filters.ChatType.PRIVATE, block=False)
@restricts() @restricts()
@error_callable @error_callable
async def command_start_export(self, update: Update, _: CallbackContext) -> None: async def command_start_export(self, update: Update, _: CallbackContext) -> None:
message = update.effective_message message = update.effective_message
user = update.effective_user user = update.effective_user
logger.info(f"用户 {user.full_name}[{user.id}] 导出抽卡记录命令请求")
try: try:
client = await get_genshin_client(user.id) client = await get_genshin_client(user.id, need_cookie=False)
await message.reply_chat_action(ChatAction.TYPING)
state, text, path = await GachaLogService.gacha_log_to_uigf(str(user.id), str(client.uid)) state, text, path = await GachaLogService.gacha_log_to_uigf(str(user.id), str(client.uid))
if state: if state:
await message.reply_chat_action(ChatAction.UPLOAD_DOCUMENT)
await message.reply_document(document=open(path, "rb+"), caption="抽卡记录导出文件") await message.reply_document(document=open(path, "rb+"), caption="抽卡记录导出文件")
else: else:
await message.reply_text(text) await message.reply_text(text)
except (UserNotFoundError, CookiesNotFoundError): except UserNotFoundError:
logger.info(f"未查询到用户({user.full_name} {user.id}) 所绑定的账号信息") logger.info(f"未查询到用户({user.full_name} {user.id}) 所绑定的账号信息")
await message.reply_text("未查询到您所绑定的账号信息,请先私聊派蒙绑定账号") await message.reply_text("未查询到您所绑定的账号信息,请先私聊派蒙绑定账号")
return
@handler(CommandHandler, command="gacha_log", block=True) @handler(CommandHandler, command="gacha_log", block=False)
@handler(MessageHandler, filters=filters.Regex("^抽卡记录(.*)"), block=True) @handler(MessageHandler, filters=filters.Regex("^抽卡记录(.*)"), block=False)
@restricts() @restricts()
@error_callable @error_callable
async def command_start_analysis(self, update: Update, context: CallbackContext) -> None: async def command_start_analysis(self, update: Update, context: CallbackContext) -> None:
@ -171,22 +167,22 @@ class GachaLog(Plugin.Conversation, BasePlugin.Conversation):
pool_type = BannerType.STANDARD pool_type = BannerType.STANDARD
logger.info(f"用户 {user.full_name}[{user.id}] 抽卡记录命令请求 || 参数 {pool_type.name}") logger.info(f"用户 {user.full_name}[{user.id}] 抽卡记录命令请求 || 参数 {pool_type.name}")
try: try:
client = await get_genshin_client(user.id) client = await get_genshin_client(user.id, need_cookie=False)
await message.reply_chat_action(ChatAction.TYPING)
data = await GachaLogService.get_analysis(user.id, client, pool_type, self.assets_service) data = await GachaLogService.get_analysis(user.id, client, pool_type, self.assets_service)
if isinstance(data, str): if isinstance(data, str):
reply_message = await message.reply_text(data) reply_message = await message.reply_text(data)
if filters.ChatType.GROUPS.filter(message):
self._add_delete_message_job(context, reply_message.chat_id, reply_message.message_id, 300)
self._add_delete_message_job(context, message.chat_id, message.message_id, 300)
else: else:
await message.reply_chat_action(ChatAction.UPLOAD_PHOTO) await message.reply_chat_action(ChatAction.UPLOAD_PHOTO)
png_data = await self.template_service.render('genshin/gacha_log', "gacha_log.html", data, png_data = await self.template_service.render('genshin/gacha_log', "gacha_log.html", data,
full_page=True, query_selector=".body_box") full_page=True, query_selector=".body_box")
reply_message = await message.reply_photo(png_data) await message.reply_photo(png_data)
if filters.ChatType.GROUPS.filter(message): except UserNotFoundError:
self._add_delete_message_job(context, reply_message.chat_id, reply_message.message_id, 300)
self._add_delete_message_job(context, message.chat_id, message.message_id, 300)
except (UserNotFoundError, CookiesNotFoundError):
logger.info(f"未查询到用户({user.full_name} {user.id}) 所绑定的账号信息") logger.info(f"未查询到用户({user.full_name} {user.id}) 所绑定的账号信息")
await message.reply_text("未查询到您所绑定的账号信息,请先私聊派蒙绑定账号") await message.reply_text("未查询到您所绑定的账号信息,请先私聊派蒙绑定账号")
return
@handler(CommandHandler, command="gacha_count", block=True) @handler(CommandHandler, command="gacha_count", block=True)
@handler(MessageHandler, filters=filters.Regex("^抽卡统计(.*)"), block=True) @handler(MessageHandler, filters=filters.Regex("^抽卡统计(.*)"), block=True)
@ -203,13 +199,16 @@ class GachaLog(Plugin.Conversation, BasePlugin.Conversation):
pool_type = BannerType.STANDARD pool_type = BannerType.STANDARD
logger.info(f"用户 {user.full_name}[{user.id}] 抽卡统计命令请求 || 参数 {pool_type.name}") logger.info(f"用户 {user.full_name}[{user.id}] 抽卡统计命令请求 || 参数 {pool_type.name}")
try: try:
client = await get_genshin_client(user.id) client = await get_genshin_client(user.id, need_cookie=False)
group = filters.ChatType.GROUPS.filter(message) group = filters.ChatType.GROUPS.filter(message)
await message.reply_chat_action(ChatAction.TYPING)
data = await GachaLogService.get_pool_analysis(user.id, client, pool_type, self.assets_service, group) data = await GachaLogService.get_pool_analysis(user.id, client, pool_type, self.assets_service, group)
if isinstance(data, str): if isinstance(data, str):
reply_message = await message.reply_text(data) reply_message = await message.reply_text(data)
if filters.ChatType.GROUPS.filter(message):
self._add_delete_message_job(context, reply_message.chat_id, reply_message.message_id, 300)
self._add_delete_message_job(context, message.chat_id, message.message_id, 300)
else: else:
await message.reply_chat_action(ChatAction.UPLOAD_PHOTO)
document = False document = False
if data["hasMore"] and not group: if data["hasMore"] and not group:
document = True document = True
@ -217,13 +216,11 @@ class GachaLog(Plugin.Conversation, BasePlugin.Conversation):
png_data = await self.template_service.render('genshin/gacha_count', "gacha_count.html", data, png_data = await self.template_service.render('genshin/gacha_count', "gacha_count.html", data,
full_page=True, query_selector=".body_box") full_page=True, query_selector=".body_box")
if document: if document:
reply_message = await message.reply_document(png_data, filename="抽卡统计.png") await message.reply_chat_action(ChatAction.UPLOAD_DOCUMENT)
await message.reply_document(png_data, filename="抽卡统计.png")
else: else:
reply_message = await message.reply_photo(png_data) await message.reply_chat_action(ChatAction.UPLOAD_PHOTO)
if filters.ChatType.GROUPS.filter(message): await message.reply_photo(png_data)
self._add_delete_message_job(context, reply_message.chat_id, reply_message.message_id, 300)
self._add_delete_message_job(context, message.chat_id, message.message_id, 300)
except (UserNotFoundError, CookiesNotFoundError): except (UserNotFoundError, CookiesNotFoundError):
logger.info(f"未查询到用户({user.full_name} {user.id}) 所绑定的账号信息") logger.info(f"未查询到用户({user.full_name} {user.id}) 所绑定的账号信息")
await message.reply_text("未查询到您所绑定的账号信息,请先私聊派蒙绑定账号") await message.reply_text("未查询到您所绑定的账号信息,请先私聊派蒙绑定账号")
return

View File

@ -9,8 +9,10 @@ from core.cookies.error import CookiesNotFoundError
from core.plugin import Plugin, handler from core.plugin import Plugin, handler
from core.user import UserService from core.user import UserService
from core.user.error import UserNotFoundError from core.user.error import UserNotFoundError
from modules.apihelper.gacha_log import GachaLog
from utils.bot import get_all_args from utils.bot import get_all_args
from utils.decorators.admins import bot_admins_rights_check from utils.decorators.admins import bot_admins_rights_check
from utils.helpers import get_genshin_client
from utils.log import logger from utils.log import logger
from utils.models.base import RegionEnum from utils.models.base import RegionEnum
@ -46,7 +48,8 @@ class GetChat(Plugin):
return text return text
async def parse_private_chat(self, chat: Chat) -> str: async def parse_private_chat(self, chat: Chat) -> str:
text = f"用户 ID<code>{chat.id}</code>\n" \ text = f"<a href=\"tg://user?id={chat.id}\">MENTION</a>\n" \
f"用户 ID<code>{chat.id}</code>\n" \
f"用户名称:<code>{chat.full_name}</code>\n" f"用户名称:<code>{chat.full_name}</code>\n"
if chat.username: if chat.username:
text += f"用户名:@{chat.username}\n" text += f"用户名:@{chat.username}\n"
@ -58,11 +61,19 @@ class GetChat(Plugin):
text += "米游社绑定:" if user_info.region == RegionEnum.HYPERION else "HOYOLAB 绑定:" text += "米游社绑定:" if user_info.region == RegionEnum.HYPERION else "HOYOLAB 绑定:"
temp = "Cookie 绑定" temp = "Cookie 绑定"
try: try:
await self.cookies_service.get_cookies(chat.id, user_info.region) await get_genshin_client(chat.id)
except CookiesNotFoundError: except CookiesNotFoundError:
temp = "UID 绑定" temp = "UID 绑定"
uid = user_info.genshin_uid or user_info.yuanshen_uid
text += f"<code>{temp}</code>\n" \ text += f"<code>{temp}</code>\n" \
f"游戏 ID<code>{user_info.genshin_uid or user_info.yuanshen_uid}</code>" f"游戏 ID<code>{uid}</code>"
gacha_log, status = await GachaLog.load_history_info(str(chat.id), str(uid))
if status:
text += f"\n抽卡记录:"
for key, value in gacha_log.item_list.items():
text += f"\n - {key}{len(value)}"
else:
text += f"\n抽卡记录:<code>未导入</code>"
return text return text
@handler(CommandHandler, command="get_chat", block=False) @handler(CommandHandler, command="get_chat", block=False)

View File

@ -84,7 +84,7 @@ async def url_to_file(url: str, return_path: bool = False) -> str:
return Path(file_dir).as_uri() return Path(file_dir).as_uri()
async def get_genshin_client(user_id: int, region: Optional[RegionEnum] = None) -> Client: async def get_genshin_client(user_id: int, region: Optional[RegionEnum] = None, need_cookie: bool = True) -> Client:
if user_service is None: if user_service is None:
raise ServiceNotFoundError(UserService) raise ServiceNotFoundError(UserService)
if cookies_service is None: if cookies_service is None:
@ -92,13 +92,16 @@ async def get_genshin_client(user_id: int, region: Optional[RegionEnum] = None)
user = await user_service.get_user_by_id(user_id) user = await user_service.get_user_by_id(user_id)
if region is None: if region is None:
region = user.region region = user.region
cookies = None
if need_cookie:
cookies = await cookies_service.get_cookies(user_id, region) cookies = await cookies_service.get_cookies(user_id, region)
cookies = cookies.cookies
if region == RegionEnum.HYPERION: if region == RegionEnum.HYPERION:
uid = user.yuanshen_uid uid = user.yuanshen_uid
client = genshin.Client(cookies=cookies.cookies, game=types.Game.GENSHIN, region=types.Region.CHINESE, uid=uid) client = genshin.Client(cookies=cookies, game=types.Game.GENSHIN, region=types.Region.CHINESE, uid=uid)
elif region == RegionEnum.HOYOLAB: elif region == RegionEnum.HOYOLAB:
uid = user.genshin_uid uid = user.genshin_uid
client = genshin.Client(cookies=cookies.cookies, client = genshin.Client(cookies=cookies,
game=types.Game.GENSHIN, region=types.Region.OVERSEAS, lang="zh-cn", uid=uid) game=types.Game.GENSHIN, region=types.Region.OVERSEAS, lang="zh-cn", uid=uid)
else: else:
raise TypeError("region is not RegionEnum.NULL") raise TypeError("region is not RegionEnum.NULL")