From 04f08bf7c398fe4cfe1301c391307012e7ce69a4 Mon Sep 17 00:00:00 2001 From: Zoom-Developer Date: Sun, 3 Nov 2024 19:59:48 +0300 Subject: [PATCH] unban / unverify --- backend/src/application/user/service.py | 23 ++++++++++++++++++++--- backend/src/domain/user/models.py | 6 +++++- backend/src/infrastructure/exc/basic.py | 1 + backend/src/infrastructure/exc/user.py | 6 +++++- backend/src/interface/api/user.py | 11 ++++++++++- backend/src/interface/rabbit/admin.py | 13 ++++++++++++- bot/src/models/admin.py | 4 +++- bot/src/rabbit/app.py | 2 -- bot/src/rabbit/routers/admin.py | 8 ++++++++ bot/src/telegram/dispatcher.py | 4 ++-- bot/src/telegram/handlers/__init__.py | 2 +- bot/src/telegram/handlers/admin.py | 20 +++++++++++++++----- docker-compose.yaml | 4 +--- 13 files changed, 83 insertions(+), 21 deletions(-) diff --git a/backend/src/application/user/service.py b/backend/src/application/user/service.py index 35171df..62b439d 100644 --- a/backend/src/application/user/service.py +++ b/backend/src/application/user/service.py @@ -6,7 +6,7 @@ from infrastructure.db import User from infrastructure.exc.auth import UsernameRequired from infrastructure.exc.likes import FocusNotSelected -from infrastructure.exc.user import AlreadyRegisteredException, FileSizeException, BannedException, SubscriptionRequiredException, VerifyRestrictionsException +from infrastructure.exc.user import AlreadyRegisteredException, AlreadyVerifiedException, FileSizeException, BannedException, SubscriptionRequiredException, VerifyRestrictionsException class UserService: @@ -34,7 +34,7 @@ async def register(self, userdata: dict, data: BaseUser, avatar: bytes) -> User: await AttachmentService().upload(avatar, user) await self.select_focus(user) await TelegramService().send_media_to_chat( - "Новый пользователь" + "👤 Новый пользователь" f"\nИмя: {user.mention} ({user.id})" f"\nКласс: {user.literal}" f"\nПол: {'Мужской' if user.male else 'Женский'}" @@ -47,6 +47,7 @@ async def select_focus(self, user: User) -> User | None: if not user.is_active: return + user.is_active = True user.focus_user = None user.focus_is_liked = False focus = await self.repo.get_noviewed(user) @@ -58,6 +59,18 @@ async def select_focus(self, user: User) -> User | None: await ViewRepository().insert(user, focus) user.focus_user = focus return focus + + async def send_verify_request(self, user: User) -> None: + if user.verify: + raise AlreadyVerifiedException() + await TelegramService().send_media_to_chat( + "🔰 Новый запрос на верификацию" + f"\nИмя: {user.mention} ({user.id})" + f"\nКласс: {user.literal}" + f"\nПол: {'Мужской' if user.male else 'Женский'}" + f"\nОписание: {user.desc}", + [attachment.url for attachment in user.attachments] + ) async def update_avatar(self, user: User, avatar: bytes) -> None: if len(avatar) > MAX_AVATAR_SIZE: @@ -117,4 +130,8 @@ async def check_user_subcription(self, user: User) -> None: async def ban(self, user: User, reason: str) -> None: user.is_banned = True user.ban_reason = reason - user.is_active = False \ No newline at end of file + user.is_active = False + + async def unban(self, user: User) -> None: + user.is_banned = False + user.ban_reason = None \ No newline at end of file diff --git a/backend/src/domain/user/models.py b/backend/src/domain/user/models.py index c5654e8..63cab67 100644 --- a/backend/src/domain/user/models.py +++ b/backend/src/domain/user/models.py @@ -48,7 +48,11 @@ class PatchUser(BaseUser): class ReportUser(BaseModel): reason: str = Field(min_length=3, max_length=64) -class BanUser(BaseModel): +class UnbanUser(BaseModel): + msg_id: int + user_id: int + +class BanUser(UnbanUser): msg_id: int user_id: int reason: str diff --git a/backend/src/infrastructure/exc/basic.py b/backend/src/infrastructure/exc/basic.py index 79d38d9..5c5106b 100644 --- a/backend/src/infrastructure/exc/basic.py +++ b/backend/src/infrastructure/exc/basic.py @@ -17,6 +17,7 @@ class ErrorCode(Enum): E3003_FOCUS_NOTSELECTED = 3003 # 403 E3004_SUBSCRIPTION_REQ = 3004 # 403 E3005_BANNED = 3005 # 403 + E3006_ALREADY_VERIFY = 3006 # 403 class HTTPError(Exception): diff --git a/backend/src/infrastructure/exc/user.py b/backend/src/infrastructure/exc/user.py index 423a964..9cc2daf 100644 --- a/backend/src/infrastructure/exc/user.py +++ b/backend/src/infrastructure/exc/user.py @@ -26,4 +26,8 @@ def __init__(self) -> None: class BannedException(HTTPError): def __init__(self, reason: str) -> None: - super().__init__(403, ErrorCode.E3005_BANNED, "Your account has been banned", headers={"X-Reason": quote(reason)}) \ No newline at end of file + super().__init__(403, ErrorCode.E3005_BANNED, "Your account has been banned", headers={"X-Reason": quote(reason)}) + +class AlreadyVerifiedException(HTTPError): + def __init__(self) -> None: + super().__init__(403, ErrorCode.E3006_ALREADY_VERIFY, "You already verified") diff --git a/backend/src/interface/api/user.py b/backend/src/interface/api/user.py index e485337..e02b08c 100644 --- a/backend/src/interface/api/user.py +++ b/backend/src/interface/api/user.py @@ -32,7 +32,7 @@ async def get_user_info(user: User = Depends(get_user)) -> FullUserDTO: "description": "Exceeded max file size (limit %s KB) (2002) / Invalid image file (2003)" % (MAX_AVATAR_SIZE / 1024) }, - 401: {"description": "undefined in endpoint"}, + 401: {"description": "Username required (2001)"}, 403: {"description": "Already registered (3001) / Subscription to channel required (3004) / Your account has been banned (3005)"} } ) @@ -81,6 +81,15 @@ async def update_avatar(avatar: bytes = File(), user: User = Depends(get_user)) await CTX_SESSION.get().commit() return user +@router.post( + "/verify", + responses={ + 403: {"description": "You already verified (3006)"} + } +) +async def send_verify(user: User = Depends(get_user)) -> FullUserDTO: + await UserService().send_verify_request(user) + return user ###################### # TEST ONLY diff --git a/backend/src/interface/rabbit/admin.py b/backend/src/interface/rabbit/admin.py index c2a3e6f..fd2867a 100644 --- a/backend/src/interface/rabbit/admin.py +++ b/backend/src/interface/rabbit/admin.py @@ -1,7 +1,7 @@ from faststream.rabbit import RabbitRouter from application.user import UserService -from domain.user import BanUser, BannedUser, VerifyUser, VerifiedUser, UserRepository +from domain.user import BanUser, BannedUser, VerifyUser, VerifiedUser, UnbanUser, UserRepository from infrastructure.db import CTX_SESSION @@ -17,6 +17,17 @@ async def ban_user(data: BanUser) -> BannedUser: await CTX_SESSION.get().commit() return BannedUser(msg_id = data.msg_id, success = True) +@router.subscriber("unban") +@router.publisher("unbanned") +async def ban_user(data: UnbanUser) -> BannedUser: + user = await UserRepository().get(data.user_id) + if not user: + return BannedUser(msg_id = data.msg_id, success = False) + await UserService().unban(user) + await CTX_SESSION.get().commit() + return BannedUser(msg_id = data.msg_id, success = True) + + @router.subscriber("verify") @router.publisher("verified") async def ban_user(data: VerifyUser) -> VerifiedUser: diff --git a/bot/src/models/admin.py b/bot/src/models/admin.py index 4f8482f..c2cdf9f 100644 --- a/bot/src/models/admin.py +++ b/bot/src/models/admin.py @@ -1,9 +1,11 @@ from pydantic import BaseModel -class BanUser(BaseModel): +class UnbanUser(BaseModel): msg_id: int user_id: int + +class BanUser(UnbanUser): reason: str class BannedUser(BaseModel): diff --git a/bot/src/rabbit/app.py b/bot/src/rabbit/app.py index f8499cd..37fd867 100644 --- a/bot/src/rabbit/app.py +++ b/bot/src/rabbit/app.py @@ -1,8 +1,6 @@ from faststream import FastStream - from .broker import broker from .routers import TelegramRouter, AdminRouter - app = FastStream(broker) broker.include_routers(TelegramRouter, AdminRouter) \ No newline at end of file diff --git a/bot/src/rabbit/routers/admin.py b/bot/src/rabbit/routers/admin.py index e9491f4..eb512a6 100644 --- a/bot/src/rabbit/routers/admin.py +++ b/bot/src/rabbit/routers/admin.py @@ -15,6 +15,14 @@ async def msg(ban: BannedUser) -> None: text = "🚫 Пользователь заблокирован" if ban.success else "❕ Неверный пользователь" ) +@router.subscriber("unbanned") +async def msg(ban: BannedUser) -> None: + await bot.send_message( + chat_id = TG_ADMIN_CHAT, + reply_to_message_id = ban.msg_id, + text = "⛓️‍💥 Пользователь разблокирован" if ban.success else "❕ Неверный пользователь" + ) + @router.subscriber("verified") async def msg(ban: VerifiedUser) -> None: await bot.send_message( diff --git a/bot/src/telegram/dispatcher.py b/bot/src/telegram/dispatcher.py index ae0f7ea..eada646 100644 --- a/bot/src/telegram/dispatcher.py +++ b/bot/src/telegram/dispatcher.py @@ -1,7 +1,7 @@ from aiogram import Dispatcher -from .handlers import AdminRouter +from .handlers import AdminHandler dp = Dispatcher() -dp.include_router(AdminRouter) \ No newline at end of file +dp.include_router(AdminHandler) \ No newline at end of file diff --git a/bot/src/telegram/handlers/__init__.py b/bot/src/telegram/handlers/__init__.py index 9adef29..9833b03 100644 --- a/bot/src/telegram/handlers/__init__.py +++ b/bot/src/telegram/handlers/__init__.py @@ -1 +1 @@ -from .admin import router as AdminRouter \ No newline at end of file +from .admin import handler as AdminHandler \ No newline at end of file diff --git a/bot/src/telegram/handlers/admin.py b/bot/src/telegram/handlers/admin.py index a657b49..d7c74a3 100644 --- a/bot/src/telegram/handlers/admin.py +++ b/bot/src/telegram/handlers/admin.py @@ -3,12 +3,12 @@ from aiogram.types import Message from config import TG_ADMIN_CHAT -from models.admin import BanUser, VerifyUser +from models.admin import BanUser, UnbanUser, VerifyUser from rabbit.broker import broker -router = Router() +handler = Router() -@router.message(Command("ban"), F.chat.id == TG_ADMIN_CHAT) +@handler.message(Command("ban"), F.chat.id == TG_ADMIN_CHAT) async def ban(msg: Message): args = msg.text.split()[1:] if len(args) < 2 or not args[0].isdigit(): @@ -19,7 +19,17 @@ async def ban(msg: Message): "adm_ban" ) -@router.message(Command("verify"), F.chat.id == TG_ADMIN_CHAT) +@handler.message(Command("unban"), F.chat.id == TG_ADMIN_CHAT) +async def ban(msg: Message): + args = msg.text.split()[1:] + if len(args) < 1 or not args[0].isdigit(): + return msg.reply("❕ Use: /unban [USER_ID]") + await broker.publish( + UnbanUser(msg_id = msg.message_id, user_id = args[0]), + "adm_unban" + ) + +@handler.message(Command("verify"), F.chat.id == TG_ADMIN_CHAT) async def ban(msg: Message): args = msg.text.split()[1:] if len(args) < 1 or not args[0].isdigit(): @@ -29,7 +39,7 @@ async def ban(msg: Message): "adm_verify" ) -@router.message(Command("unverify"), F.chat.id == TG_ADMIN_CHAT) +@handler.message(Command("unverify"), F.chat.id == TG_ADMIN_CHAT) async def ban(msg: Message): args = msg.text.split()[1:] if len(args) < 1 or not args[0].isdigit(): diff --git a/docker-compose.yaml b/docker-compose.yaml index 2c50dd6..401d08a 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -40,15 +40,13 @@ services: env_file: - .env depends_on: - backend: - condition: service_healthy rabbitmq: condition: service_healthy restart: true deploy: resources: limits: - cpus: '0.1' + cpus: '0.3' memory: 256M db: