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 @@