Refactor bot handlers and keyboards; implement admin features
- Removed unused prehandling, referrals, support, and states files. - Updated admin and client handlers to improve structure and functionality. - Introduced admin filters and routers for better access control. - Added new billing and deposit functionalities for client interactions. - Enhanced keyboard layouts for admin and client menus. - Implemented promotion handling for admin users. - Updated configuration to include admin settings. - Improved utility functions for quote fetching and menu text building. - Added common handlers for undefined commands and message deletions.
This commit is contained in:
@@ -1,21 +1,9 @@
|
||||
from .ads import router as ads_router
|
||||
from .billing import router as billing_router
|
||||
from .buy import router as buy_router
|
||||
from .common import router as common_router
|
||||
from .deposit import router as deposit_router
|
||||
from .menus import router as menus_router
|
||||
from .prehandling import router as prehandling_router
|
||||
from .referals import router as referal_router
|
||||
from .support import router as support_router
|
||||
from .admins import routers as admin_routers
|
||||
from .client import routers as client_routers
|
||||
from .system import routers as system_routers
|
||||
|
||||
routers = [
|
||||
prehandling_router,
|
||||
referal_router,
|
||||
billing_router,
|
||||
deposit_router,
|
||||
menus_router,
|
||||
ads_router,
|
||||
support_router,
|
||||
buy_router,
|
||||
common_router,
|
||||
__all__ = [
|
||||
"admin_routers",
|
||||
"client_routers",
|
||||
"system_routers",
|
||||
]
|
||||
|
||||
4
bot/handlers/admins/__init__.py
Normal file
4
bot/handlers/admins/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
from .admins import router as general_router
|
||||
from .ads import router as ads_router
|
||||
|
||||
routers = [general_router, ads_router]
|
||||
36
bot/handlers/admins/admins.py
Normal file
36
bot/handlers/admins/admins.py
Normal file
@@ -0,0 +1,36 @@
|
||||
from aiogram import F, Router
|
||||
from aiogram.filters import Command
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import CallbackQuery, Message
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from bot.filters.admins import AdminFilter
|
||||
from bot.keyboards.admins import main_menu
|
||||
from misc.utils import build_adm_main_menu_text
|
||||
from schemas.di import DependenciesDTO
|
||||
|
||||
router = Router()
|
||||
|
||||
|
||||
@router.message(AdminFilter(), Command(commands=["start", "cancel"]))
|
||||
async def standard_start(
|
||||
msg: Message, state: FSMContext, session: AsyncSession, deps: DependenciesDTO
|
||||
):
|
||||
await state.clear()
|
||||
|
||||
users = await deps.user_repository.user_count(session)
|
||||
await msg.answer(
|
||||
build_adm_main_menu_text(user_count=users, user_id=msg.from_user.id), reply_markup=main_menu
|
||||
)
|
||||
|
||||
|
||||
@router.callback_query(AdminFilter(), F.data == "menu:main")
|
||||
async def main_menu_cb(
|
||||
cb: CallbackQuery, state: FSMContext, session: AsyncSession, deps: DependenciesDTO
|
||||
):
|
||||
await state.clear()
|
||||
|
||||
users = await deps.user_repository.user_count(session)
|
||||
await cb.message.edit_text(
|
||||
build_adm_main_menu_text(user_count=users, user_id=cb.from_user.id), reply_markup=main_menu
|
||||
)
|
||||
52
bot/handlers/admins/ads.py
Normal file
52
bot/handlers/admins/ads.py
Normal file
@@ -0,0 +1,52 @@
|
||||
from aiogram import F, Router
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import CallbackQuery, Message
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from schemas.di import DependenciesDTO
|
||||
from schemas.promotions import NewPromotionContext
|
||||
from bot.texts import ADM_PROMO_INIT, CALLBACK_FALLBACK, GENERAL_PROCESSING, ADM_VERIFY_PROMOTION, SUCCESSFULLY_SENT_PROMO
|
||||
from bot.keyboards.common import return_to_menu
|
||||
from bot.keyboards.admins import action_confirmation
|
||||
from bot.states.admins import AdminStorage
|
||||
|
||||
router = Router()
|
||||
|
||||
@router.callback_query(F.data == "promotion")
|
||||
async def promo_init(cb: CallbackQuery, state: FSMContext):
|
||||
await state.clear()
|
||||
|
||||
await cb.message.edit_text(ADM_PROMO_INIT, reply_markup=return_to_menu)
|
||||
|
||||
ctx = NewPromotionContext(cb.message)
|
||||
await state.set_state(AdminStorage.promotion_msg)
|
||||
await state.set_data({"ctx": ctx})
|
||||
|
||||
@router.message(AdminStorage.promotion_msg)
|
||||
async def promo_text(msg: Message, state: FSMContext):
|
||||
data = await state.get_data()
|
||||
await state.clear()
|
||||
|
||||
edited_msg = await msg.answer(GENERAL_PROCESSING)
|
||||
ctx: NewPromotionContext | None = data.get("ctx")
|
||||
if ctx:
|
||||
await ctx.msg.delete()
|
||||
|
||||
ctx.promotion = msg
|
||||
await edited_msg.edit_text(ADM_VERIFY_PROMOTION, reply_markup=action_confirmation)
|
||||
|
||||
await state.set_state(AdminStorage.promotion_msg)
|
||||
await state.set_data({"ctx": ctx})
|
||||
|
||||
@router.callback_query(AdminStorage.promotion_msg, F.data.in_(("approve", "decline")))
|
||||
async def promo_send(cb: CallbackQuery, state: FSMContext, session: AsyncSession, deps: DependenciesDTO):
|
||||
data = await state.get_data()
|
||||
await state.clear()
|
||||
|
||||
ctx: NewPromotionContext | None = data.get("ctx")
|
||||
if not (ctx and ctx.promotion and ctx.msg):
|
||||
await cb.message.edit_text(CALLBACK_FALLBACK, reply_markup=return_to_menu)
|
||||
return
|
||||
|
||||
successful = await deps.user_service.launch_promotion(session, ctx.promotion)
|
||||
await cb.message.edit_text(SUCCESSFULLY_SENT_PROMO.format(successful=successful), reply_markup=return_to_menu)
|
||||
@@ -1,5 +0,0 @@
|
||||
from aiogram import Router
|
||||
|
||||
router = Router()
|
||||
|
||||
# FIXME: Refine newsletter system
|
||||
15
bot/handlers/client/__init__.py
Normal file
15
bot/handlers/client/__init__.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from .billing import router as billing_router
|
||||
from .buy import router as buy_router
|
||||
from .deposit import router as deposit_router
|
||||
from .menus import router as menus_router
|
||||
from .referals import router as referal_router
|
||||
from .support import router as support_router
|
||||
|
||||
routers = [
|
||||
referal_router,
|
||||
billing_router,
|
||||
deposit_router,
|
||||
menus_router,
|
||||
support_router,
|
||||
buy_router,
|
||||
]
|
||||
@@ -5,7 +5,8 @@ from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import CallbackQuery
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from bot.keyboards.client import pay_url, return_to_menu
|
||||
from bot.keyboards.client import pay_url
|
||||
from bot.keyboards.common import return_to_menu
|
||||
from bot.states.buy import BillingStorage
|
||||
from bot.texts import BILL_CREATED, BILL_CREATION, CALLBACK_FALLBACK
|
||||
from schemas.billing import BillingContext, BillingProviders
|
||||
@@ -6,7 +6,9 @@ from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import CallbackQuery
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from bot.keyboards.client import deposit_kb, devices_selector, duration_selector, return_to_menu
|
||||
from bot.keyboards.client import deposit_kb, devices_selector, duration_selector
|
||||
from bot.keyboards.common import return_to_menu
|
||||
|
||||
from bot.states.buy import SubscriptionStorage
|
||||
from bot.texts import (
|
||||
CALLBACK_FALLBACK,
|
||||
@@ -176,7 +178,10 @@ async def proceed_to_checkout(
|
||||
|
||||
if effective_balance < amount:
|
||||
await cb.message.edit_text(
|
||||
INSUFFICIENT_FUNDS.format(balance=user.balance, amount=amount, diff=abs(amount-user.balance)), reply_markup=deposit_kb
|
||||
INSUFFICIENT_FUNDS.format(
|
||||
balance=user.balance, amount=amount, diff=abs(amount - user.balance)
|
||||
),
|
||||
reply_markup=deposit_kb,
|
||||
)
|
||||
return
|
||||
|
||||
@@ -2,7 +2,8 @@ from aiogram import F, Router
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import CallbackQuery, Message
|
||||
|
||||
from bot.keyboards.client import payment_gateways, return_to_menu
|
||||
from bot.keyboards.client import payment_gateways
|
||||
from bot.keyboards.common import return_to_menu
|
||||
from bot.states.buy import BillingStorage
|
||||
from bot.states.deposit import DepositStorage
|
||||
from bot.texts import (
|
||||
@@ -4,7 +4,8 @@ from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import CallbackQuery, Message
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from bot.keyboards.client import close_kb, main_menu, return_to_menu, subscription_controls
|
||||
from bot.keyboards.client import close_kb, main_menu, subscription_controls
|
||||
from bot.keyboards.common import return_to_menu
|
||||
from bot.texts import (
|
||||
CALLBACK_FALLBACK,
|
||||
FAQ_TEXT,
|
||||
@@ -149,7 +150,9 @@ async def sub_info(
|
||||
deps.user_service.format_subscription_message(
|
||||
rw_user, link=user.subscription_link, autorenew=sub.autorenew
|
||||
),
|
||||
reply_markup=subscription_controls(show_autorenew=bool(rw_user), current_autorenewal_status=sub.autorenew),
|
||||
reply_markup=subscription_controls(
|
||||
show_autorenew=bool(rw_user), current_autorenewal_status=sub.autorenew
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -183,5 +186,7 @@ async def toggle_autorenewal(
|
||||
deps.user_service.format_subscription_message(
|
||||
rw_user, link=user.subscription_link, autorenew=sub.autorenew
|
||||
),
|
||||
reply_markup=subscription_controls(show_autorenew=bool(rw_user), current_autorenewal_status=sub.autorenew),
|
||||
reply_markup=subscription_controls(
|
||||
show_autorenew=bool(rw_user), current_autorenewal_status=sub.autorenew
|
||||
),
|
||||
)
|
||||
4
bot/handlers/system/__init__.py
Normal file
4
bot/handlers/system/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
from .common import router as common_router
|
||||
from .prehandling import router as prehandling_router
|
||||
|
||||
routers = [common_router, prehandling_router]
|
||||
Reference in New Issue
Block a user