diff --git a/core/cookies/repositories.py b/core/cookies/repositories.py index 483d95c..ae74f1c 100644 --- a/core/cookies/repositories.py +++ b/core/cookies/repositories.py @@ -89,3 +89,20 @@ class CookiesRepository: return [cookies[0] for cookies in db_cookies] else: raise RegionNotFoundError(region.name) + + async def del_cookies(self, user_id, region: RegionEnum): + async with self.mysql.Session() as session: + session = cast(AsyncSession, session) + if region == RegionEnum.HYPERION: + statement = select(HyperionCookie).where(HyperionCookie.user_id == user_id) + elif region == RegionEnum.HOYOLAB: + statement = select(HoyolabCookie).where(HoyolabCookie.user_id == user_id) + else: + raise RegionNotFoundError(region.name) + results = await session.execute(statement) + db_cookies = results.unique().scalar_one() + if db_cookies: + await session.delete(db_cookies) + await session.commit() + else: + raise CookiesNotFoundError(user_id) diff --git a/core/cookies/services.py b/core/cookies/services.py index 5b85184..36ee380 100644 --- a/core/cookies/services.py +++ b/core/cookies/services.py @@ -24,6 +24,9 @@ class CookiesService: async def get_cookies(self, user_id: int, region: RegionEnum): return await self._repository.get_cookies(user_id, region) + async def del_cookies(self, user_id: int, region: RegionEnum): + return await self._repository.del_cookies(user_id, region) + class PublicCookiesService: def __init__(self, cookies_repository: CookiesRepository, public_cookies_cache: PublicCookiesCache): diff --git a/core/user/repositories.py b/core/user/repositories.py index 8b149d2..616ab76 100644 --- a/core/user/repositories.py +++ b/core/user/repositories.py @@ -34,3 +34,15 @@ class UserRepository: session = cast(AsyncSession, session) session.add(user) await session.commit() + + async def del_user_by_id(self, user_id): + async with self.mysql.Session() as session: + session = cast(AsyncSession, session) + statement = select(User).where(User.user_id == user_id) + results = await session.execute(statement) + user = results.unique().scalar_one() + if user: + await session.delete(user) + await session.commit() + else: + raise UserNotFoundError(user_id) diff --git a/core/user/services.py b/core/user/services.py index 6e89d05..cf7eabd 100644 --- a/core/user/services.py +++ b/core/user/services.py @@ -13,6 +13,9 @@ class UserService: """ return await self._repository.get_by_user_id(user_id) + async def del_user_by_id(self, user_id: int) -> User: + return await self._repository.del_user_by_id(user_id) + async def update_user(self, user: User) -> User: return await self._repository.update_user(user) diff --git a/plugins/genshin/user.py b/plugins/genshin/user.py new file mode 100644 index 0000000..ccb57e8 --- /dev/null +++ b/plugins/genshin/user.py @@ -0,0 +1,111 @@ +from typing import Optional + +from telegram import Update, TelegramObject, User, ReplyKeyboardRemove +from telegram.ext import CallbackContext, filters, ConversationHandler + +from core.baseplugin import BasePlugin +from core.cookies import CookiesService +from core.cookies.error import CookiesNotFoundError +from core.cookies.models import Cookies +from core.plugin import Plugin, handler, conversation +from core.user import UserService +from core.user.error import UserNotFoundError +from utils.decorators.error import error_callable +from utils.decorators.restricts import restricts +from utils.log import logger +from utils.models.base import RegionEnum + + +class DelUserCommandData(TelegramObject): + user: Optional[User] = None + region: RegionEnum = RegionEnum.HYPERION + cookies: Optional[Cookies] = None + + +CHECK_SERVER, DEL_USER = range(10800, 10802) + + +class UserPlugin(Plugin.Conversation, BasePlugin.Conversation): + def __init__( + self, + user_service: UserService = None, + cookies_service: CookiesService = None, + ): + self.cookies_service = cookies_service + self.user_service = user_service + + @conversation.entry_point + @handler.command(command="deluser", filters=filters.ChatType.PRIVATE, block=True) + @restricts() + @error_callable + 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) + del_user_command_data: DelUserCommandData = context.chat_data.get("del_user_command_data") + if del_user_command_data is None: + del_user_command_data = DelUserCommandData() + context.chat_data["del_user_command_data"] = del_user_command_data + try: + user_info = await self.user_service.get_user_by_id(user.id) + del_user_command_data.user = user_info + except UserNotFoundError: + await message.reply_text("用户未找到") + return ConversationHandler.END + cookies_status: bool = False + try: + cookies = await self.cookies_service.get_cookies(user.id, user_info.region) + del_user_command_data.cookies = cookies + cookies_status = True + except CookiesNotFoundError: + logger.info("用户 %s[%s] Cookies 不存在", user.full_name, user.id) + if user_info.region == RegionEnum.HYPERION: + uid = user_info.yuanshen_uid + region_str = "米游社" + elif user_info.region == RegionEnum.HOYOLAB: + uid = user_info.genshin_uid + region_str = "HoYoLab" + else: + await message.reply_text("数据非法") + return ConversationHandler.END + await message.reply_text("获取用户信息成功") + text = ( + f"绑定信息\n" + f"UID:{uid}\n" + f"注册:{region_str}\n" + f"是否绑定Cookie:{'√' if cookies_status else '×'}" + ) + await message.reply_html(text) + await message.reply_html("请回复确认即可解除绑定并从数据库移除,如绑定Cookies也会跟着一起从数据库删除,删除后操作无法逆转,回复 /cancel 可退出操作") + return DEL_USER + + @conversation.state(state=DEL_USER) + @handler.message(filters=filters.TEXT & ~filters.COMMAND, block=True) + @error_callable + async def command_result(self, update: Update, context: CallbackContext) -> int: + user = update.effective_user + message = update.effective_message + if message.text == "退出": + await message.reply_text("退出任务", reply_markup=ReplyKeyboardRemove()) + return ConversationHandler.END + elif message.text == "确认": + del_user_command_data: DelUserCommandData = context.chat_data.get("del_user_command_data") + try: + await self.user_service.del_user_by_id(user.id) + except UserNotFoundError: + await message.reply_text("用户未找到") + return ConversationHandler.END + else: + logger.success("用户 %s[%s] 从数据库删除账号成功", user.full_name, user.id) + if del_user_command_data.cookies: + try: + await self.cookies_service.del_cookies(user.id, del_user_command_data.region) + except CookiesNotFoundError: + logger.info("用户 %s[%s] Cookies 不存在", user.full_name, user.id) + else: + logger.success("用户 %s[%s] 从数据库删除Cookies成功", user.full_name, user.id) + await message.reply_text("删除成功") + return ConversationHandler.END + else: + await message.reply_text("回复错误,退出当前会话") + return ConversationHandler.END diff --git a/resources/bot/help/help.html b/resources/bot/help/help.html index 516a28b..72ab232 100644 --- a/resources/bot/help/help.html +++ b/resources/bot/help/help.html @@ -184,6 +184,10 @@
/setcookie
添加/重设Cookie(请私聊BOT)
+
+
/deluser
+
删除/解绑账号(请私聊BOT)
+
/cancel