aboutsummaryrefslogtreecommitdiff
path: root/handlers/admin/new_invoice.py
diff options
context:
space:
mode:
Diffstat (limited to 'handlers/admin/new_invoice.py')
-rw-r--r--handlers/admin/new_invoice.py109
1 files changed, 109 insertions, 0 deletions
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)