PaiGram/plugins/genshin/pay_log.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

250 lines
14 KiB
Python
Raw Normal View History

from simnet import GenshinClient, Region
from simnet.utils.player import recognize_genshin_game_biz, recognize_genshin_server
2023-01-07 08:01:31 +00:00
from telegram import Update, User, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.constants import ChatAction
from telegram.ext import CallbackContext, CommandHandler, MessageHandler, filters, ConversationHandler
from telegram.helpers import create_deep_linked_url
from core.basemodel import RegionEnum
2023-01-07 08:01:31 +00:00
from core.plugin import Plugin, handler, conversation
from core.services.cookies import CookiesService
from core.services.players.services import PlayersService
from core.services.template.services import TemplateService
2023-01-07 08:01:31 +00:00
from modules.gacha_log.helpers import from_url_get_authkey
from modules.pay_log.error import PayLogNotFound, PayLogAccountNotFound, PayLogInvalidAuthkey, PayLogAuthkeyTimeout
from modules.pay_log.log import PayLog
2023-04-28 01:19:20 +00:00
from plugins.tools.player_info import PlayerInfoSystem
2023-01-07 08:01:31 +00:00
from utils.log import logger
INPUT_URL, CONFIRM_DELETE = range(10100, 10102)
class PlayerNotFoundError(Exception):
pass
class PayLogPlugin(Plugin.Conversation):
2023-01-07 08:01:31 +00:00
"""充值记录导入/导出/分析"""
def __init__(
self,
template_service: TemplateService,
players_service: PlayersService,
cookie_service: CookiesService,
2023-04-28 01:19:20 +00:00
player_info: PlayerInfoSystem,
2023-01-07 08:01:31 +00:00
):
self.template_service = template_service
self.players_service = players_service
2023-01-07 08:01:31 +00:00
self.cookie_service = cookie_service
self.pay_log = PayLog()
2023-04-28 01:19:20 +00:00
self.player_info = player_info
2023-07-19 03:41:40 +00:00
async def get_player_id(self, uid: int) -> int:
"""获取绑定的游戏ID"""
logger.debug("尝试获取已绑定的原神账号")
player = await self.players_service.get_player(uid)
if player is None:
raise PlayerNotFoundError(uid)
return player.player_id
2023-01-07 08:01:31 +00:00
async def _refresh_user_data(self, user: User, authkey: str = None) -> str:
"""刷新用户数据
:param user: 用户
:param authkey: 认证密钥
:return: 返回信息
"""
try:
2023-07-19 03:41:40 +00:00
player_id = await self.get_player_id(user.id)
new_num = await self.pay_log.get_log_data(user.id, player_id, authkey)
2023-01-07 10:48:53 +00:00
return "更新完成,本次没有新增数据" if new_num == 0 else f"更新完成,本次共新增{new_num}条充值记录"
2023-01-07 08:01:31 +00:00
except PayLogNotFound:
2023-01-07 10:48:53 +00:00
return "派蒙没有找到你的充值记录,快去充值吧~"
2023-01-07 08:01:31 +00:00
except PayLogAccountNotFound:
return "导入失败,可能文件包含的祈愿记录所属 uid 与你当前绑定的 uid 不同"
except PayLogInvalidAuthkey:
return "更新数据失败authkey 无效"
except PayLogAuthkeyTimeout:
return "更新数据失败authkey 已经过期"
except PlayerNotFoundError:
2023-01-07 08:01:31 +00:00
logger.info("未查询到用户 %s[%s] 所绑定的账号信息", user.full_name, user.id)
return "派蒙没有找到您所绑定的账号信息,请先私聊派蒙绑定账号"
@conversation.entry_point
@handler(CommandHandler, command="pay_log_import", filters=filters.ChatType.PRIVATE, block=False)
@handler(MessageHandler, filters=filters.Regex("^导入充值记录$") & filters.ChatType.PRIVATE, block=False)
async def command_start(self, update: Update, context: CallbackContext) -> int:
message = update.effective_message
user = update.effective_user
args = self.get_args(context)
2023-01-07 08:01:31 +00:00
logger.info("用户 %s[%s] 导入充值记录命令请求", user.full_name, user.id)
authkey = from_url_get_authkey(args[0] if args else "")
if not args:
player_info = await self.players_service.get_player(user.id, region=RegionEnum.HYPERION)
if player_info is not None:
cookies = await self.cookie_service.get(user.id, account_id=player_info.account_id)
if cookies is not None and cookies.data and "stoken" in cookies.data:
2023-01-07 08:01:31 +00:00
if stuid := next(
(value for key, value in cookies.data.items() if key in ["ltuid", "login_uid"]), None
2023-01-07 08:01:31 +00:00
):
cookies.data["stuid"] = stuid
async with GenshinClient(
cookies=cookies.data, region=Region.CHINESE, lang="zh-cn", player_id=player_info.player_id
) as client:
authkey = await client.get_authkey_by_stoken(
recognize_genshin_game_biz(client.player_id),
recognize_genshin_server(client.player_id),
"csc",
)
2023-01-07 08:01:31 +00:00
if not authkey:
await message.reply_text(
"<b>开始导入充值历史记录:请通过 https://paimon.moe/wish/import 获取抽卡记录链接后发送给我"
"(非 paimon.moe 导出的文件数据)</b>\n\n"
"> 在绑定 Cookie 时添加 stoken 可能有特殊效果哦(仅限国服)\n"
2023-01-07 08:01:31 +00:00
"<b>注意:导入的数据将会与旧数据进行合并。</b>",
parse_mode="html",
)
return INPUT_URL
text = "小派蒙正在从服务器获取数据,请稍后"
if not args:
text += "\n\n> 由于你绑定的 Cookie 中存在 stoken ,本次通过 stoken 自动刷新数据"
reply = await message.reply_text(text)
await message.reply_chat_action(ChatAction.TYPING)
data = await self._refresh_user_data(user, authkey=authkey)
await reply.edit_text(data)
return ConversationHandler.END
@conversation.state(state=INPUT_URL)
@handler.message(filters=~filters.COMMAND, block=False)
2023-01-07 08:01:31 +00:00
async def import_data_from_message(self, update: Update, _: CallbackContext) -> int:
message = update.effective_message
user = update.effective_user
if message.document:
2023-03-14 07:53:44 +00:00
await message.reply_text("呜呜呜~本次导入不支持文件导入,请尝试获取连接")
return INPUT_URL
if not message.text:
await message.reply_text("呜呜呜~输入错误,请尝试重新获取连接")
return INPUT_URL
2023-01-07 08:01:31 +00:00
authkey = from_url_get_authkey(message.text)
reply = await message.reply_text("小派蒙正在从服务器获取数据,请稍后")
await message.reply_chat_action(ChatAction.TYPING)
text = await self._refresh_user_data(user, authkey=authkey)
await reply.edit_text(text)
return ConversationHandler.END
@conversation.entry_point
@handler(CommandHandler, command="pay_log_delete", filters=filters.ChatType.PRIVATE, block=False)
@handler(MessageHandler, filters=filters.Regex("^删除充值记录$") & filters.ChatType.PRIVATE, block=False)
async def command_start_delete(self, update: Update, context: CallbackContext) -> int:
2023-01-07 08:01:31 +00:00
message = update.effective_message
user = update.effective_user
logger.info("用户 %s[%s] 删除充值记录命令请求", user.full_name, user.id)
player_info = await self.players_service.get_player(user.id)
if player_info is None:
2023-01-07 08:01:31 +00:00
logger.info("未查询到用户 %s[%s] 所绑定的账号信息", user.full_name, user.id)
await message.reply_text("未查询到您所绑定的账号信息,请先绑定账号")
2023-01-07 08:01:31 +00:00
return ConversationHandler.END
_, status = await self.pay_log.load_history_info(str(user.id), str(player_info.player_id), only_status=True)
2023-01-07 08:01:31 +00:00
if not status:
await message.reply_text("你还没有导入充值记录哦~")
return ConversationHandler.END
context.chat_data["uid"] = player_info.player_id
2023-01-07 08:01:31 +00:00
await message.reply_text("你确定要删除充值记录吗?(此项操作无法恢复),如果确定请发送 ”确定“,发送其他内容取消")
return CONFIRM_DELETE
@conversation.state(state=CONFIRM_DELETE)
@handler.message(filters=filters.TEXT & ~filters.COMMAND, block=False)
async def command_confirm_delete(self, update: Update, context: CallbackContext) -> int:
message = update.effective_message
user = update.effective_user
if message.text == "确定":
status = await self.pay_log.remove_history_info(str(user.id), str(context.chat_data["uid"]))
await message.reply_text("充值记录已删除" if status else "充值记录删除失败")
return ConversationHandler.END
await message.reply_text("已取消")
return ConversationHandler.END
@handler(CommandHandler, command="pay_log_force_delete", block=False, admin=True)
2023-01-07 08:01:31 +00:00
async def command_pay_log_force_delete(self, update: Update, context: CallbackContext):
message = update.effective_message
args = self.get_args(context)
2023-01-07 08:01:31 +00:00
if not args:
await message.reply_text("请指定用户ID")
return
try:
cid = int(args[0])
if cid < 0:
raise ValueError("Invalid cid")
player_info = await self.players_service.get_player(cid)
if player_info is None:
await message.reply_text("该用户暂未绑定账号")
return
_, status = await self.pay_log.load_history_info(str(cid), str(player_info.player_id), only_status=True)
2023-01-07 08:01:31 +00:00
if not status:
2023-01-07 10:48:53 +00:00
await message.reply_text("该用户还没有导入充值记录")
2023-01-07 08:01:31 +00:00
return
status = await self.pay_log.remove_history_info(str(cid), str(player_info.player_id))
2023-01-07 10:48:53 +00:00
await message.reply_text("充值记录已强制删除" if status else "充值记录删除失败")
2023-01-07 08:01:31 +00:00
except PayLogNotFound:
2023-01-07 10:48:53 +00:00
await message.reply_text("该用户还没有导入充值记录")
2023-01-07 08:01:31 +00:00
except (ValueError, IndexError):
await message.reply_text("用户ID 不合法")
@handler(CommandHandler, command="pay_log_export", filters=filters.ChatType.PRIVATE, block=False)
@handler(MessageHandler, filters=filters.Regex("^导出充值记录$") & filters.ChatType.PRIVATE, block=False)
async def command_start_export(self, update: Update, context: CallbackContext) -> None:
message = update.effective_message
user = update.effective_user
logger.info("用户 %s[%s] 导出充值记录命令请求", user.full_name, user.id)
try:
await message.reply_chat_action(ChatAction.TYPING)
2023-07-19 03:41:40 +00:00
player_id = await self.get_player_id(user.id)
path = self.pay_log.get_file_path(str(user.id), str(player_id))
if not path.exists():
raise PayLogNotFound
2023-01-07 08:01:31 +00:00
await message.reply_chat_action(ChatAction.UPLOAD_DOCUMENT)
await message.reply_document(document=open(path, "rb+"), caption="充值记录导出文件")
except PayLogNotFound:
buttons = [
[InlineKeyboardButton("点我导入", url=create_deep_linked_url(context.bot.username, "pay_log_import"))]
]
await message.reply_text("派蒙没有找到你的充值记录,快来私聊派蒙导入吧~", reply_markup=InlineKeyboardMarkup(buttons))
except PayLogAccountNotFound:
await message.reply_text("导出失败,可能文件包含的祈愿记录所属 uid 与你当前绑定的 uid 不同")
except PlayerNotFoundError:
2023-01-07 08:01:31 +00:00
logger.info("未查询到用户 %s[%s] 所绑定的账号信息", user.full_name, user.id)
await message.reply_text("未查询到您所绑定的账号信息,请先绑定账号")
2023-01-07 08:01:31 +00:00
@handler(CommandHandler, command="pay_log", block=False)
@handler(MessageHandler, filters=filters.Regex("^充值记录$"), block=False)
async def command_start_analysis(self, update: Update, context: CallbackContext) -> None:
message = update.effective_message
user = update.effective_user
logger.info("用户 %s[%s] 充值记录统计命令请求", user.full_name, user.id)
try:
await message.reply_chat_action(ChatAction.TYPING)
2023-07-19 03:41:40 +00:00
player_id = await self.get_player_id(user.id)
data = await self.pay_log.get_analysis(user.id, player_id)
2023-01-07 08:01:31 +00:00
await message.reply_chat_action(ChatAction.UPLOAD_PHOTO)
2023-07-19 03:41:40 +00:00
name_card = await self.player_info.get_name_card(player_id, user)
2023-04-28 01:19:20 +00:00
data["name_card"] = name_card
2023-01-07 08:01:31 +00:00
png_data = await self.template_service.render(
2023-04-28 01:19:20 +00:00
"genshin/pay_log/pay_log.jinja2", data, full_page=True, query_selector=".container"
2023-01-07 08:01:31 +00:00
)
await png_data.reply_photo(message)
except PayLogNotFound:
buttons = [
[InlineKeyboardButton("点我导入", url=create_deep_linked_url(context.bot.username, "pay_log_import"))]
]
await message.reply_text("派蒙没有找到你的充值记录,快来点击按钮私聊派蒙导入吧~", reply_markup=InlineKeyboardMarkup(buttons))
except PlayerNotFoundError:
2023-01-07 08:01:31 +00:00
logger.info("未查询到用户 %s[%s] 所绑定的账号信息", user.full_name, user.id)
buttons = [[InlineKeyboardButton("点我绑定账号", url=create_deep_linked_url(context.bot.username, "set_uid"))]]
if filters.ChatType.GROUPS.filter(message):
reply_message = await message.reply_text(
"未查询到您所绑定的账号信息,请先私聊派蒙绑定账号", reply_markup=InlineKeyboardMarkup(buttons)
)
self.add_delete_message_job(reply_message, delay=30)
self.add_delete_message_job(message, delay=30)
2023-01-07 08:01:31 +00:00
else:
await message.reply_text("未查询到您所绑定的账号信息,请先绑定账号", reply_markup=InlineKeyboardMarkup(buttons))