aboutsummaryrefslogtreecommitdiff
path: root/handlers/admin
diff options
context:
space:
mode:
Diffstat (limited to 'handlers/admin')
-rw-r--r--handlers/admin/__init__.py2
-rw-r--r--handlers/admin/new_announcement.py9
-rw-r--r--handlers/admin/new_invoice.py109
3 files changed, 116 insertions, 4 deletions
diff --git a/handlers/admin/__init__.py b/handlers/admin/__init__.py
index 2f7c74f..98b127f 100644
--- a/handlers/admin/__init__.py
+++ b/handlers/admin/__init__.py
@@ -3,6 +3,7 @@ from aiogram.filters import MagicData
3 3
4# isort: off 4# isort: off
5from . import new_announcement 5from . import new_announcement
6from . import new_invoice
6# isort: on 7# isort: on
7 8
8router = Router(name="admin") 9router = Router(name="admin")
@@ -11,4 +12,5 @@ router.callback_query.filter(MagicData(F.user.is_admin()))
11 12
12router.include_routers( 13router.include_routers(
13 new_announcement.router, 14 new_announcement.router,
15 new_invoice.router,
14) 16)
diff --git a/handlers/admin/new_announcement.py b/handlers/admin/new_announcement.py
index 79cf8d4..0920c47 100644
--- a/handlers/admin/new_announcement.py
+++ b/handlers/admin/new_announcement.py
@@ -1,6 +1,7 @@
1from datetime import UTC, datetime 1from datetime import UTC, datetime
2 2
3from aiogram import Bot, F, Router 3from aiogram import Bot, F, Router
4from aiogram.enums import ButtonStyle
4from aiogram.exceptions import TelegramAPIError 5from aiogram.exceptions import TelegramAPIError
5from aiogram.filters import Command 6from aiogram.filters import Command
6from aiogram.fsm.context import FSMContext 7from aiogram.fsm.context import FSMContext
@@ -17,7 +18,7 @@ from sqlalchemy import select
17from sqlalchemy.ext.asyncio import AsyncSession 18from sqlalchemy.ext.asyncio import AsyncSession
18 19
19from libs.fsm import get_data, set_data 20from libs.fsm import get_data, set_data
20from libs.msg import publish 21from libs.msg import publish_announcement
21from models import Announcement, RichText, User 22from models import Announcement, RichText, User
22 23
23router = Router(name="new_announcement") 24router = Router(name="new_announcement")
@@ -42,8 +43,8 @@ async def new_announcement_command(msg: Message, state: FSMContext) -> None:
42 reply_markup=ReplyKeyboardMarkup( 43 reply_markup=ReplyKeyboardMarkup(
43 keyboard=[ 44 keyboard=[
44 [ 45 [
45 KeyboardButton(text=SEND_BUTTON), 46 KeyboardButton(text=SEND_BUTTON, style=ButtonStyle.SUCCESS),
46 KeyboardButton(text=CANCEL_BUTTON), 47 KeyboardButton(text=CANCEL_BUTTON, style=ButtonStyle.DANGER),
47 ] 48 ]
48 ], 49 ],
49 resize_keyboard=True, 50 resize_keyboard=True,
@@ -69,7 +70,7 @@ async def announcement_send(
69 status_template = "Публикация анонса...\nОпубликовано: {}" 70 status_template = "Публикация анонса...\nОпубликовано: {}"
70 status_msg = await msg.answer(status_template.format(0)) 71 status_msg = await msg.answer(status_template.format(0))
71 72
72 async for n in publish(bot, users, data.rich_text): 73 async for n in publish_announcement(bot, users, data.rich_text):
73 try: 74 try:
74 await status_msg.edit_text(status_template.format(n)) 75 await status_msg.edit_text(status_template.format(n))
75 except TelegramAPIError: 76 except TelegramAPIError:
diff --git a/handlers/admin/new_invoice.py b/handlers/admin/new_invoice.py
new file mode 100644
index 0000000..7e1a64d
--- /dev/null
+++ b/handlers/admin/new_invoice.py
@@ -0,0 +1,109 @@
1from datetime import UTC, datetime
2
3from aiogram import Bot, F, Router
4from aiogram.enums import ButtonStyle, ContentType
5from aiogram.exceptions import TelegramAPIError
6from aiogram.filters import Command
7from aiogram.fsm.context import FSMContext
8from aiogram.fsm.state import State, StatesGroup
9from aiogram.types import (
10 KeyboardButton,
11 Message,
12 ReplyKeyboardMarkup,
13 ReplyKeyboardRemove,
14)
15from pydantic import BaseModel
16from sqlalchemy import select
17from sqlalchemy.ext.asyncio import AsyncSession
18
19from libs.fsm import get_data, set_data
20from libs.msg import send_invoice
21from models import Invoice, RichText, User
22
23router = Router(name="new_invoice")
24
25
26class NewInvoiceStates(StatesGroup):
27 message = State()
28
29
30class NewInvoiceData(BaseModel):
31 rich_text: RichText | None = None
32
33
34CREATE_BUTTON = "Создать"
35CANCEL_BUTTON = "Отменить создание"
36
37
38@router.message(Command("new_invoice"))
39async def new_invoice_command(msg: Message, state: FSMContext) -> None:
40 await msg.answer(
41 "Укажите сообщение для создания счёта",
42 reply_markup=ReplyKeyboardMarkup(
43 keyboard=[
44 [
45 KeyboardButton(text=CREATE_BUTTON, style=ButtonStyle.SUCCESS),
46 KeyboardButton(text=CANCEL_BUTTON, style=ButtonStyle.DANGER),
47 ]
48 ],
49 resize_keyboard=True,
50 ),
51 )
52 await state.set_state(NewInvoiceStates.message)
53
54
55@router.message(NewInvoiceStates.message, F.text == CREATE_BUTTON)
56async def invoice_send(
57 msg: Message,
58 bot: Bot,
59 state: FSMContext,
60 session: AsyncSession,
61) -> None:
62 users = await session.scalars(select(User.id).where(User.id != msg.chat.id))
63 data = await get_data(state, NewInvoiceData)
64
65 if data.rich_text is None:
66 await msg.answer("Для создания счёта укажите сообщение.")
67 return
68
69 status_template = "Рассылка счёта...\nОтправлено: {}"
70 status_msg = await msg.answer(status_template.format(0))
71
72 invoice = Invoice(message=data, datetime=datetime.now(UTC))
73 session.add(invoice)
74 await session.flush()
75
76 async for n in send_invoice(bot, users, data.rich_text, invoice.id):
77 try:
78 await status_msg.edit_text(status_template.format(n))
79 except TelegramAPIError:
80 pass
81
82 await status_msg.delete()
83 await msg.answer(
84 "Счёт отправлен всем пользователям",
85 # reply_markup=ReplyKeyboardRemove(),
86 )
87 # await state.clear()
88
89
90@router.message(NewInvoiceStates.message, F.text == CANCEL_BUTTON)
91async def invoice_cancel(msg: Message, state: FSMContext) -> None:
92 await msg.answer("Создание счёта отменено", reply_markup=ReplyKeyboardRemove())
93 await state.clear()
94
95
96@router.message(NewInvoiceStates.message)
97async def invoice_message(msg: Message, bot: Bot, state: FSMContext) -> None:
98 if msg.content_type != ContentType.TEXT or msg.text is None:
99 await msg.answer(
100 "Неверный тип сообщения.\n"
101 "Бот поддерживает отправку только текстовых счетов."
102 )
103 return
104
105 rich_text = RichText.from_message(msg)
106 await set_data(state, NewInvoiceData(rich_text=rich_text))
107
108 msg_rich_text = RichText.from_text("Сообщение вашего счёта:\n", rich_text)
109 await msg_rich_text.send(bot, msg.chat.id)