Изменение БД, добавление регистрации, добавление сложной рассылки, кнопки для СР

This commit is contained in:
ada-dmitry
2025-04-18 20:41:45 +03:00
parent aa82634f75
commit e1063b669f
6 changed files with 166 additions and 22 deletions
+80
View File
@@ -0,0 +1,80 @@
from aiogram import Router, F, Bot
from aiogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import StatesGroup, State
from sqlalchemy import select
from database import async_session
from models import User
from uuid import uuid4
import os
router = Router()
admin_ids = list(map(int, os.getenv("ADMINS", "").split(",")))
# Храним рассылки
adv_memory = {} # {adv_id: {"text": str, "is_active": bool}}
current_adv_id = None
# Состояния для FSM
class AdvForm(StatesGroup):
short = State()
full = State()
@router.message(F.text == "/send_adv")
async def start_adv(message: Message, state: FSMContext):
if message.from_user.id not in admin_ids:
return await message.answer("⛔ Доступ запрещён.")
await state.set_state(AdvForm.short)
await message.answer("Введите краткую форму сообщения:")
@router.message(AdvForm.short)
async def get_short_text(message: Message, state: FSMContext):
await state.update_data(short=message.text)
await state.set_state(AdvForm.full)
await message.answer("Теперь введите полную форму сообщения:")
@router.message(AdvForm.full)
async def get_full_text_and_send(message: Message, state: FSMContext, bot: Bot):
global current_adv_id, adv_memory
data = await state.get_data()
short_text = data["short"]
full_text = message.text
# Генерируем уникальный ID рассылки
adv_id = str(uuid4())
# Деактивируем старые рассылки
for adv in adv_memory.values():
adv["is_active"] = False
# Сохраняем новую рассылку
adv_memory[adv_id] = {
"text": full_text,
"is_active": True
}
current_adv_id = adv_id
# Клавиатура
kb = InlineKeyboardMarkup(inline_keyboard=[
[
InlineKeyboardButton(text="👍 Интересно", callback_data=f"adv:{adv_id}"),
InlineKeyboardButton(text="👎 Не интересно", callback_data="adv:no")
]
])
# Рассылка краткой формы
async with async_session() as session:
result = await session.execute(select(User.user_id).where(User.is_subscribed == True))
users = result.scalars().all()
sent = 0
for uid in users:
try:
await bot.send_message(uid, short_text, reply_markup=kb)
sent += 1
except:
continue
await message.answer(f"📬 Рассылка завершена. Отправлено: {sent}")
await state.clear()
+25
View File
@@ -0,0 +1,25 @@
from aiogram import Router, F
from aiogram.types import CallbackQuery
from handlers.admin_adv import adv_memory
router = Router()
@router.callback_query(F.data.startswith("adv:"))
async def handle_adv_click(callback: CallbackQuery):
adv_id = callback.data.split(":")[1]
adv = adv_memory.get(adv_id)
if not adv:
await callback.answer("❌ Сообщение не найдено", show_alert=True)
return
if not adv["is_active"]:
await callback.answer("⏰ Срок действия сообщения истёк", show_alert=True)
return
await callback.message.answer(adv["text"])
await callback.answer("Вот подробности 👇")
@router.callback_query(F.data == "adv:no")
async def handle_not_interested(callback: CallbackQuery):
await callback.answer("Спасибо за обратную связь!")
+44 -18
View File
@@ -1,5 +1,7 @@
from aiogram import Router, F
from aiogram.fsm.context import FSMContext
from aiogram.types import Message, CallbackQuery
from aiogram.fsm.state import State, StatesGroup
from sqlalchemy import select, insert, update
from models import User
from database import async_session
@@ -7,27 +9,51 @@ from keyboards import get_subscription_keyboard
router = Router()
# Машина состояний
class Register(StatesGroup):
waiting_for_fullname = State()
waiting_for_study_group = State()
@router.message(F.text == "/start")
async def start_handler(message: Message):
async with async_session() as session:
async def start_handler(message: Message, state: FSMContext):
user_id = message.from_user.id
result = await session.execute(select(User).where(User.user_id == message.from_user.id))
async with async_session() as session:
result = await session.execute(select(User).where(User.user_id == user_id))
user = result.scalar_one_or_none()
if not user:
await session.execute(insert(User).values(user_id=message.from_user.id))
await session.commit()
text = "Добро пожаловать! Управляйте подпиской:"
await message.answer(text, reply_markup=get_subscription_keyboard(user.is_subscribed if user else True))
@router.callback_query(F.data.in_(["subscribe", "unsubscribe"]))
async def toggle_subscription(callback: CallbackQuery):
subscribe = callback.data == "subscribe"
if user:
# Приветствие при повторном запуске
text = f"👋 Привет, {user.full_name or 'друг'}!\n" \
f"Группа: {user.study_group or 'не указана'}\n" \
"Используй кнопки ниже, чтобы управлять подпиской:"
await message.answer(text, reply_markup=get_subscription_keyboard(user.is_subscribed))
else:
# Первый запуск — регистрация
await state.set_state(Register.waiting_for_fullname)
await message.answer("👋 Привет! Пожалуйста, напиши свои ФИО одной строкой:")
@router.message(Register.waiting_for_fullname)
async def get_fullname(message: Message, state: FSMContext):
await state.update_data(full_name=message.text)
await state.set_state(Register.waiting_for_study_group)
await message.answer("Теперь укажи номер своей группы (например, Б11-111):")
@router.message(Register.waiting_for_study_group)
async def get_study_group(message: Message, state: FSMContext):
data = await state.get_data()
full_name = data["full_name"]
study_group = message.text
async with async_session() as session:
await session.execute(
update(User)
.where(User.user_id == callback.from_user.id)
.values(is_subscribed=subscribe)
)
await session.execute(insert(User).values(
user_id=message.from_user.id,
full_name=full_name,
study_group=study_group,
is_subscribed=True
))
await session.commit()
await callback.message.edit_reply_markup(reply_markup=get_subscription_keyboard(subscribe))
await callback.answer("Вы подписались!" if subscribe else "Вы отписались.")
await message.answer(f"✅ Регистрация завершена!\nФИО: {full_name}\nГруппа: {study_group}")
await message.answer("Теперь ты можешь управлять подпиской ниже 👇", reply_markup=get_subscription_keyboard(True))
await state.clear()