Feat: added notifier
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
2025-01-17 13:19:13 +03:00
parent 0d1dd4362d
commit 926774424e
6 changed files with 64 additions and 7 deletions

View File

@@ -25,5 +25,5 @@ if __name__ == "__main__":
# Start bot
bot = NwXrayBot(config.bot_token.get_secret_value())
bot.include_routers(HelloHandler(), MenuHandler(), AdminHandler())
bot.include_routers(HelloHandler(), MenuHandler(), AdminHandler(bot.bot))
loop.run_until_complete(bot.start(skip_updates=True))

View File

@@ -0,0 +1 @@
from nwxraybot.fsm.broadcast import BroadcastStates

View File

@@ -0,0 +1,6 @@
from aiogram.fsm.state import State, StatesGroup
class BroadcastStates(StatesGroup):
waiting_for_message = State()
confirming_message = State()

View File

@@ -1,19 +1,26 @@
import asyncio
import logging
import re
from datetime import datetime
from typing import Optional
from aiogram import Bot, F
from aiogram.enums import ParseMode
from aiogram.filters import Command
from aiogram.types import Message
from aiogram.fsm.context import FSMContext
from aiogram.types import (CallbackQuery, InlineKeyboardButton,
InlineKeyboardMarkup, Message)
from nwxraybot import get_code
from nwxraybot.fsm import BroadcastStates
from nwxraybot.meta import Handler
from nwxraybot.middlewares import AdminMiddleware
from nwxraybot.models import User
class AdminHandler(Handler):
def __init__(self) -> None:
super().__init__()
def __init__(self, bot: Optional[Bot] = None) -> None:
super().__init__(bot)
self.router.message.middleware(AdminMiddleware())
@@ -51,3 +58,46 @@ class AdminHandler(Handler):
User.name == user_dict['name'])
query.execute()
await message.answer('Информация о пользователе обновлена.')
@self.router.message(Command('broadcast'))
async def start_broadcast(message: Message, state: FSMContext):
await message.answer('Отправьте для рассылки')
await state.set_state(BroadcastStates.waiting_for_message)
@self.router.message(BroadcastStates.waiting_for_message)
async def broadcast_message(message: Message, state: FSMContext):
if message.media_group_id is not None:
await state.clear()
await message.answer('Пожалуйста, не отправляйте сообщение с несколькими изображениями.')
return
await state.set_state(BroadcastStates.confirming_message)
keyboard = InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(
text="Подтвердить", callback_data='confirm_broadcast')],
[InlineKeyboardButton(
text="Отменить", callback_data='cancel_broadcast')]
])
await state.update_data(message_id=message.message_id)
await message.answer("Подтвердите отправку сообщения", reply_markup=keyboard)
@self.router.callback_query(F.data == 'confirm_broadcast', BroadcastStates.confirming_message)
async def confirm_broadcast(callback: CallbackQuery, state: FSMContext):
await callback.answer()
data = await state.get_data()
message_id = data.get('message_id')
users = User.select().where((User.telegram_id != None))
semaphore = asyncio.Semaphore(10)
for user in users:
async with semaphore:
try:
await self.bot.copy_message(user.telegram_id, callback.from_user.id, message_id)
except Exception as e:
logging.error(f"Error while broadcasting message to user {
user.telegram_id}: {e}")
await state.clear()
@self.router.callback_query(F.data == 'cancel_broadcast', BroadcastStates.confirming_message)
async def cancel_broadcast(callback: CallbackQuery, state: FSMContext):
await callback.answer()
await state.clear()
await callback.message.answer('Рассылка отменена.')

View File

@@ -9,8 +9,8 @@ class Handler:
def __init__(self, bot: Optional[Bot] = None) -> None:
if bot:
assert isinstance(bot.bot, Optional[Bot])
self.bot = bot.bot
assert isinstance(bot, Bot)
self.bot = bot
self.router = Router()
def __call__(self) -> Router:

View File

@@ -14,7 +14,7 @@ class UserMiddleware(BaseMiddleware):
async def __call__(self, handler: Callable[[Message, Dict[str, Any]], Awaitable[Any]], event: Message, data: Dict[str, Any]) -> Any:
if event.chat.type != ChatType.PRIVATE:
return None
if event.text.startswith('/start'):
if event.text and event.text.startswith('/start'):
return await handler(event, data)
user: Optional[User] = User.select().where(
User.telegram_id == event.from_user.id).first()