Implement admin sender handler

This commit is contained in:
hteppl
2025-01-12 17:29:48 +03:00
parent ab27328cb7
commit f11b014acf
2 changed files with 140 additions and 0 deletions
+105
View File
@@ -0,0 +1,105 @@
from datetime import datetime
from typing import Any
from aiogram import F, Router, types
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
from aiogram.types import CallbackQuery
from bot import bot
from filters.admin import IsAdminFilter
from keyboards.admin.panel_kb import AdminPanelCallback, build_admin_back_kb
from keyboards.admin.sender_kb import build_sender_kb, AdminSenderCallback
from logger import logger
router = Router()
class AdminSender(StatesGroup):
waiting_for_message = State()
@router.callback_query(
AdminPanelCallback.filter(F.action == "sender"),
IsAdminFilter(),
)
async def handle_sender(
callback_query: CallbackQuery
):
await callback_query.message.answer(
text="✍️ Выберите группу пользователей для рассылки:",
reply_markup=build_sender_kb(),
)
@router.callback_query(
AdminSenderCallback,
IsAdminFilter(),
)
async def handle_sender_callback(
callback_query: CallbackQuery,
callback_data: AdminSenderCallback,
state: FSMContext
):
await callback_query.message.answer(
text="✍️ Введите текст сообщения для рассылки:",
reply_markup=build_admin_back_kb("sender"),
)
await state.update_data(type=callback_data.type)
await state.set_state(AdminSender.waiting_for_message)
@router.message(
AdminSender.waiting_for_message,
IsAdminFilter(),
)
async def process_message(
message: types.Message,
state: FSMContext,
session: Any
):
text_message = message.text
try:
state_data = await state.get_data()
send_to = state_data.get("type", "all")
if send_to == "subscribed":
tg_ids = await session.fetch("""
SELECT DISTINCT c.tg_id
FROM connections c
JOIN keys k ON c.tg_id = k.tg_id
WHERE k.expiry_time > $1
""", int(datetime.utcnow().timestamp() * 1000))
elif send_to == "unsubscribed":
tg_ids = await session.fetch("""
SELECT c.tg_id
FROM connections c
LEFT JOIN keys k ON c.tg_id = k.tg_id
GROUP BY c.tg_id
HAVING COUNT(k.tg_id) = 0 OR MAX(k.expiry_time) <= $1
""", int(datetime.utcnow().timestamp() * 1000))
else:
tg_ids = await session.fetch("SELECT DISTINCT tg_id FROM connections")
total_users = len(tg_ids)
success_count = 0
for record in tg_ids:
tg_id = record["tg_id"]
try:
await bot.send_message(chat_id=tg_id, text=text_message)
success_count += 1
except Exception:
pass
await message.answer(
f"📤 Рассылка завершена:\n"
f"👥 Всего пользователей: {total_users}\n"
f"✅ Доставлено: {success_count}\n"
f"❌ Не доставлено: {total_users - success_count}"
)
except Exception as e:
logger.error(f"❗ Ошибка при подключении к базе данных: {e}")
await state.clear()
+35
View File
@@ -0,0 +1,35 @@
from aiogram.filters.callback_data import CallbackData
from aiogram.types import InlineKeyboardMarkup
from aiogram.utils.keyboard import InlineKeyboardBuilder
from keyboards.admin.panel_kb import build_admin_back_btn
class AdminSenderCallback(CallbackData, prefix='admin_sender'):
type: str
def build_sender_kb() -> InlineKeyboardMarkup:
builder = InlineKeyboardBuilder()
builder.button(
text="📢 Отправить всем",
callback_data=AdminSenderCallback(
type="all"
).pack()
)
builder.button(
text="📢 Отправить с подпиской",
callback_data=AdminSenderCallback(
type="subscribed"
).pack()
)
builder.button(
text="📢 Отправить без подписки",
callback_data=AdminSenderCallback(
type="unsubscribed"
).pack()
)
builder.row(
build_admin_back_btn("admin")
)
return builder.as_markup()