2023-12-16 10:01:27 +00:00
|
|
|
|
from typing import TYPE_CHECKING, Optional, List
|
2023-12-12 13:41:29 +00:00
|
|
|
|
|
2023-07-18 09:29:31 +00:00
|
|
|
|
from simnet import GenshinClient, Region
|
2023-12-12 13:41:29 +00:00
|
|
|
|
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
|
2023-01-07 08:01:31 +00:00
|
|
|
|
from telegram.constants import ChatAction
|
2023-12-12 13:41:29 +00:00
|
|
|
|
from telegram.ext import CommandHandler, MessageHandler, filters, ConversationHandler
|
2023-01-07 08:01:31 +00:00
|
|
|
|
from telegram.helpers import create_deep_linked_url
|
|
|
|
|
|
2023-03-14 01:27:22 +00:00
|
|
|
|
from core.basemodel import RegionEnum
|
2024-06-07 15:22:30 +00:00
|
|
|
|
from core.config import config
|
2023-01-07 08:01:31 +00:00
|
|
|
|
from core.plugin import Plugin, handler, conversation
|
2023-03-14 01:27:22 +00:00
|
|
|
|
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-12-16 10:01:27 +00:00
|
|
|
|
from modules.pay_log.migrate import PayLogMigrate
|
2023-12-12 13:41:29 +00:00
|
|
|
|
from plugins.tools.genshin import PlayerNotFoundError, CookiesNotFoundError
|
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
|
|
|
|
|
|
2023-12-12 13:41:29 +00:00
|
|
|
|
if TYPE_CHECKING:
|
|
|
|
|
from telegram import Update, User
|
|
|
|
|
from telegram.ext import ContextTypes
|
2023-12-16 10:01:27 +00:00
|
|
|
|
from gram_core.services.players.models import Player
|
2023-12-12 13:41:29 +00:00
|
|
|
|
|
|
|
|
|
|
2023-01-07 08:01:31 +00:00
|
|
|
|
INPUT_URL, CONFIRM_DELETE = range(10100, 10102)
|
2024-06-07 15:22:30 +00:00
|
|
|
|
WAITING = f"小{config.notice.bot_name}正在从服务器获取数据,请稍后"
|
|
|
|
|
PAYLOG_NOT_FOUND = f"{config.notice.bot_name}没有找到你的充值记录,快来私聊{config.notice.bot_name}导入吧~"
|
2023-01-07 08:01:31 +00:00
|
|
|
|
|
|
|
|
|
|
2023-03-14 01:27:22 +00:00
|
|
|
|
class PayLogPlugin(Plugin.Conversation):
|
2023-01-07 08:01:31 +00:00
|
|
|
|
"""充值记录导入/导出/分析"""
|
|
|
|
|
|
|
|
|
|
def __init__(
|
|
|
|
|
self,
|
2023-03-14 01:27:22 +00:00
|
|
|
|
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
|
2023-03-14 01:27:22 +00:00
|
|
|
|
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
|
|
|
|
|
2023-12-12 13:41:29 +00:00
|
|
|
|
async def _refresh_user_data(self, user: "User", authkey: str = None) -> str:
|
2023-01-07 08:01:31 +00:00
|
|
|
|
"""刷新用户数据
|
|
|
|
|
: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:
|
2024-06-07 15:22:30 +00:00
|
|
|
|
return f"{config.notice.bot_name}没有找到你的充值记录,快去充值吧~"
|
2023-01-07 08:01:31 +00:00
|
|
|
|
except PayLogAccountNotFound:
|
|
|
|
|
return "导入失败,可能文件包含的祈愿记录所属 uid 与你当前绑定的 uid 不同"
|
|
|
|
|
except PayLogInvalidAuthkey:
|
|
|
|
|
return "更新数据失败,authkey 无效"
|
|
|
|
|
except PayLogAuthkeyTimeout:
|
|
|
|
|
return "更新数据失败,authkey 已经过期"
|
2023-03-14 01:27:22 +00:00
|
|
|
|
except PlayerNotFoundError:
|
2023-01-07 08:01:31 +00:00
|
|
|
|
logger.info("未查询到用户 %s[%s] 所绑定的账号信息", user.full_name, user.id)
|
2024-06-07 15:22:30 +00:00
|
|
|
|
return config.notice.user_not_found
|
2023-01-07 08:01:31 +00:00
|
|
|
|
|
|
|
|
|
@conversation.entry_point
|
2023-12-24 13:53:05 +00:00
|
|
|
|
@handler.command(command="pay_log_import", filters=filters.ChatType.PRIVATE, block=False)
|
|
|
|
|
@handler.message(filters=filters.Regex("^导入充值记录$") & filters.ChatType.PRIVATE, block=False)
|
|
|
|
|
@handler.command(command="start", filters=filters.Regex("pay_log_import$"), block=False)
|
2023-12-12 13:41:29 +00:00
|
|
|
|
async def command_start(self, update: "Update", _: "ContextTypes.DEFAULT_TYPE") -> 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)
|
2023-12-12 13:41:29 +00:00
|
|
|
|
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:
|
|
|
|
|
if "stoken" in cookies.data:
|
2023-01-07 08:01:31 +00:00
|
|
|
|
if stuid := next(
|
2023-03-14 01:27:22 +00:00
|
|
|
|
(value for key, value in cookies.data.items() if key in ["ltuid", "login_uid"]), None
|
2023-01-07 08:01:31 +00:00
|
|
|
|
):
|
2023-03-14 01:27:22 +00:00
|
|
|
|
cookies.data["stuid"] = stuid
|
2023-07-18 09:29:31 +00:00
|
|
|
|
async with GenshinClient(
|
|
|
|
|
cookies=cookies.data, region=Region.CHINESE, lang="zh-cn", player_id=player_info.player_id
|
|
|
|
|
) as client:
|
2023-09-11 13:24:05 +00:00
|
|
|
|
authkey = await client.get_authkey_by_stoken("csc")
|
2023-12-12 13:41:29 +00:00
|
|
|
|
else:
|
|
|
|
|
await message.reply_text("该功能需要绑定 stoken 才能使用")
|
|
|
|
|
return ConversationHandler.END
|
|
|
|
|
else:
|
2023-12-16 10:01:27 +00:00
|
|
|
|
raise CookiesNotFoundError(user.id)
|
2023-12-12 13:41:29 +00:00
|
|
|
|
else:
|
2023-12-16 10:01:27 +00:00
|
|
|
|
raise CookiesNotFoundError(user.id)
|
2024-06-07 15:22:30 +00:00
|
|
|
|
reply = await message.reply_text(WAITING)
|
2023-01-07 08:01:31 +00:00
|
|
|
|
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)
|
2023-03-14 01:27:22 +00:00
|
|
|
|
@handler.message(filters=~filters.COMMAND, block=False)
|
2023-12-12 13:41:29 +00:00
|
|
|
|
async def import_data_from_message(self, update: "Update", _: "ContextTypes.DEFAULT_TYPE") -> int:
|
2023-01-07 08:01:31 +00:00
|
|
|
|
message = update.effective_message
|
|
|
|
|
user = update.effective_user
|
2023-03-14 01:27:22 +00:00
|
|
|
|
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)
|
2024-06-07 15:22:30 +00:00
|
|
|
|
reply = await message.reply_text(WAITING)
|
2023-01-07 08:01:31 +00:00
|
|
|
|
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)
|
2023-12-12 13:41:29 +00:00
|
|
|
|
async def command_start_delete(self, update: "Update", context: "ContextTypes.DEFAULT_TYPE") -> 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)
|
2023-07-18 09:29:31 +00:00
|
|
|
|
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)
|
2024-06-07 15:22:30 +00:00
|
|
|
|
await message.reply_text(config.notice.user_not_found)
|
2023-01-07 08:01:31 +00:00
|
|
|
|
return ConversationHandler.END
|
2023-07-18 09:29:31 +00:00
|
|
|
|
_, 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
|
2023-07-18 09:29:31 +00:00
|
|
|
|
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)
|
2023-12-12 13:41:29 +00:00
|
|
|
|
async def command_confirm_delete(self, update: "Update", context: "ContextTypes.DEFAULT_TYPE") -> int:
|
2023-01-07 08:01:31 +00:00
|
|
|
|
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
|
|
|
|
|
|
2023-03-14 01:27:22 +00:00
|
|
|
|
@handler(CommandHandler, command="pay_log_force_delete", block=False, admin=True)
|
2023-12-12 13:41:29 +00:00
|
|
|
|
async def command_pay_log_force_delete(self, update: "Update", context: "ContextTypes.DEFAULT_TYPE"):
|
2023-01-07 08:01:31 +00:00
|
|
|
|
message = update.effective_message
|
2023-03-14 01:27:22 +00:00
|
|
|
|
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")
|
2023-07-18 09:29:31 +00:00
|
|
|
|
player_info = await self.players_service.get_player(cid)
|
|
|
|
|
if player_info is None:
|
2023-03-14 01:27:22 +00:00
|
|
|
|
await message.reply_text("该用户暂未绑定账号")
|
|
|
|
|
return
|
2023-07-18 09:29:31 +00:00
|
|
|
|
_, 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
|
2023-07-18 09:29:31 +00:00
|
|
|
|
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)
|
2023-12-12 13:41:29 +00:00
|
|
|
|
async def command_start_export(self, update: "Update", context: "ContextTypes.DEFAULT_TYPE") -> None:
|
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)
|
|
|
|
|
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))
|
2023-03-06 09:04:31 +00:00
|
|
|
|
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"))]
|
|
|
|
|
]
|
2024-06-07 15:22:30 +00:00
|
|
|
|
await message.reply_text(PAYLOG_NOT_FOUND, reply_markup=InlineKeyboardMarkup(buttons))
|
2023-01-07 08:01:31 +00:00
|
|
|
|
except PayLogAccountNotFound:
|
|
|
|
|
await message.reply_text("导出失败,可能文件包含的祈愿记录所属 uid 与你当前绑定的 uid 不同")
|
2023-03-14 01:27:22 +00:00
|
|
|
|
except PlayerNotFoundError:
|
2023-01-07 08:01:31 +00:00
|
|
|
|
logger.info("未查询到用户 %s[%s] 所绑定的账号信息", user.full_name, user.id)
|
2024-06-07 15:22:30 +00:00
|
|
|
|
await message.reply_text(config.notice.user_not_found)
|
2023-01-07 08:01:31 +00:00
|
|
|
|
|
|
|
|
|
@handler(CommandHandler, command="pay_log", block=False)
|
|
|
|
|
@handler(MessageHandler, filters=filters.Regex("^充值记录$"), block=False)
|
2023-12-12 13:41:29 +00:00
|
|
|
|
async def command_start_analysis(self, update: "Update", context: "ContextTypes.DEFAULT_TYPE") -> None:
|
2024-03-10 12:40:26 +00:00
|
|
|
|
user_id = await self.get_real_user_id(update)
|
2023-01-07 08:01:31 +00:00
|
|
|
|
message = update.effective_message
|
2024-03-10 12:40:26 +00:00
|
|
|
|
self.log_user(update, logger.info, "充值记录统计命令请求")
|
2023-01-07 08:01:31 +00:00
|
|
|
|
try:
|
|
|
|
|
await message.reply_chat_action(ChatAction.TYPING)
|
2024-03-10 12:40:26 +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)
|
2024-03-10 12:40:26 +00:00
|
|
|
|
name_card = await self.player_info.get_name_card(player_id, user_id)
|
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"))]
|
|
|
|
|
]
|
2024-06-07 15:22:30 +00:00
|
|
|
|
await message.reply_text(PAYLOG_NOT_FOUND, reply_markup=InlineKeyboardMarkup(buttons))
|
2023-12-16 10:01:27 +00:00
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
async def get_migrate_data(
|
|
|
|
|
old_user_id: int, new_user_id: int, old_players: List["Player"]
|
|
|
|
|
) -> Optional[PayLogMigrate]:
|
|
|
|
|
return await PayLogMigrate.create(old_user_id, new_user_id, old_players)
|