aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--handlers/admin/__init__.py2
-rw-r--r--handlers/admin/add_user.py99
-rw-r--r--handlers/admin/new_announcement.py10
-rw-r--r--handlers/admin/new_invoice.py6
4 files changed, 109 insertions, 8 deletions
diff --git a/handlers/admin/__init__.py b/handlers/admin/__init__.py
index 98b127f..02f9e6e 100644
--- a/handlers/admin/__init__.py
+++ b/handlers/admin/__init__.py
@@ -4,6 +4,7 @@ from aiogram.filters import MagicData
4# isort: off 4# isort: off
5from . import new_announcement 5from . import new_announcement
6from . import new_invoice 6from . import new_invoice
7from . import add_user
7# isort: on 8# isort: on
8 9
9router = Router(name="admin") 10router = Router(name="admin")
@@ -13,4 +14,5 @@ router.callback_query.filter(MagicData(F.user.is_admin()))
13router.include_routers( 14router.include_routers(
14 new_announcement.router, 15 new_announcement.router,
15 new_invoice.router, 16 new_invoice.router,
17 add_user.router,
16) 18)
diff --git a/handlers/admin/add_user.py b/handlers/admin/add_user.py
new file mode 100644
index 0000000..b9b8604
--- /dev/null
+++ b/handlers/admin/add_user.py
@@ -0,0 +1,99 @@
1from datetime import UTC, datetime
2
3from aiogram import F, Router
4from aiogram.enums.button_style import ButtonStyle
5from aiogram.filters import Command
6from aiogram.fsm.context import FSMContext
7from aiogram.fsm.state import State, StatesGroup
8from aiogram.types import (
9 KeyboardButton,
10 KeyboardButtonRequestUsers,
11 Message,
12 ReplyKeyboardMarkup,
13 ReplyKeyboardRemove,
14)
15from pydantic import BaseModel
16from sqlalchemy.ext.asyncio import AsyncSession
17
18from libs.fsm import edit_data, get_data, set_data
19from models import User
20
21router = Router(name="add_user")
22
23
24class AddUserStates(StatesGroup):
25 user_id = State()
26 vpn_link = State()
27
28
29class AddUserData(BaseModel):
30 user_id: int | None = None
31
32
33CANCEL_BUTTON = "Отменить добавление"
34
35
36@router.message(Command("add_user"))
37async def add_user_command(msg: Message, state: FSMContext) -> None:
38 await msg.answer(
39 "Выберете пользователя которого хотите добавить.",
40 reply_markup=ReplyKeyboardMarkup(
41 keyboard=[
42 [
43 KeyboardButton(
44 text="Выбрать пользователя",
45 style=ButtonStyle.PRIMARY,
46 request_users=KeyboardButtonRequestUsers(request_id=0),
47 ),
48 ],
49 [
50 KeyboardButton(text=CANCEL_BUTTON, style=ButtonStyle.DANGER),
51 ],
52 ],
53 resize_keyboard=True,
54 ),
55 )
56 await set_data(state, AddUserData(user_id=None))
57 await state.set_state(AddUserStates.user_id)
58
59
60@router.message(AddUserStates(), F.text == CANCEL_BUTTON)
61async def add_user_cancel(msg: Message, state: FSMContext) -> None:
62 await msg.answer(
63 "Добавление пользователей отменено",
64 reply_markup=ReplyKeyboardRemove(),
65 )
66 await state.clear()
67
68
69@router.message(AddUserStates.user_id)
70async def add_user_user_id(msg: Message, state: FSMContext) -> None:
71 if msg.users_shared is None:
72 await msg.answer("Вы должны воспользоваться кнопкой ниже.")
73 return
74
75 async with edit_data(state, AddUserData) as data:
76 data.user_id = msg.users_shared.users[0].user_id
77
78 await msg.answer("Укажите ссылку для доступа к VPN")
79 await state.set_state(AddUserStates.vpn_link)
80
81
82@router.message(AddUserStates.vpn_link)
83async def add_user_vpn_link(
84 msg: Message,
85 state: FSMContext,
86 session: AsyncSession,
87) -> None:
88 if msg.text is None:
89 await msg.answer("Вы должны указать ссылку отправив текстовое сообщение.")
90 return
91
92 data = await get_data(state, AddUserData)
93 assert data.user_id is not None
94
95 session.add(User(id=data.user_id, vpn_link=msg.text, datetime=datetime.now(UTC)))
96 await session.flush()
97
98 await msg.answer("Пользователь добавлен.")
99 await state.clear()
diff --git a/handlers/admin/new_announcement.py b/handlers/admin/new_announcement.py
index 0920c47..6aa099e 100644
--- a/handlers/admin/new_announcement.py
+++ b/handlers/admin/new_announcement.py
@@ -7,7 +7,6 @@ from aiogram.filters import Command
7from aiogram.fsm.context import FSMContext 7from aiogram.fsm.context import FSMContext
8from aiogram.fsm.state import State, StatesGroup 8from aiogram.fsm.state import State, StatesGroup
9from aiogram.types import ( 9from aiogram.types import (
10 ContentType,
11 KeyboardButton, 10 KeyboardButton,
12 Message, 11 Message,
13 ReplyKeyboardMarkup, 12 ReplyKeyboardMarkup,
@@ -67,6 +66,10 @@ async def announcement_send(
67 await msg.answer("Для публикации анонса укажите текст сообщения.") 66 await msg.answer("Для публикации анонса укажите текст сообщения.")
68 return 67 return
69 68
69 announcement = Announcement(message=data.rich_text, datetime=datetime.now(UTC))
70 session.add(announcement)
71 await session.flush()
72
70 status_template = "Публикация анонса...\nОпубликовано: {}" 73 status_template = "Публикация анонса...\nОпубликовано: {}"
71 status_msg = await msg.answer(status_template.format(0)) 74 status_msg = await msg.answer(status_template.format(0))
72 75
@@ -76,9 +79,6 @@ async def announcement_send(
76 except TelegramAPIError: 79 except TelegramAPIError:
77 pass 80 pass
78 81
79 announcement = Announcement(message=data, datetime=datetime.now(UTC))
80 session.add(announcement)
81
82 await status_msg.delete() 82 await status_msg.delete()
83 await msg.answer( 83 await msg.answer(
84 "Анонс отправлен всем пользователям", 84 "Анонс отправлен всем пользователям",
@@ -95,7 +95,7 @@ async def announcement_cancel(msg: Message, state: FSMContext) -> None:
95 95
96@router.message(NewAnnouncementStates.message) 96@router.message(NewAnnouncementStates.message)
97async def announcement_message(msg: Message, bot: Bot, state: FSMContext) -> None: 97async def announcement_message(msg: Message, bot: Bot, state: FSMContext) -> None:
98 if msg.content_type != ContentType.TEXT or msg.text is None: 98 if msg.text is None:
99 await msg.answer( 99 await msg.answer(
100 "Неверный тип сообщения.\n" 100 "Неверный тип сообщения.\n"
101 "Бот поддерживает отправку только текстовых анонсов." 101 "Бот поддерживает отправку только текстовых анонсов."
diff --git a/handlers/admin/new_invoice.py b/handlers/admin/new_invoice.py
index 7e1a64d..0427d90 100644
--- a/handlers/admin/new_invoice.py
+++ b/handlers/admin/new_invoice.py
@@ -1,7 +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, ContentType 4from aiogram.enums import ButtonStyle
5from aiogram.exceptions import TelegramAPIError 5from aiogram.exceptions import TelegramAPIError
6from aiogram.filters import Command 6from aiogram.filters import Command
7from aiogram.fsm.context import FSMContext 7from aiogram.fsm.context import FSMContext
@@ -69,7 +69,7 @@ async def invoice_send(
69 status_template = "Рассылка счёта...\nОтправлено: {}" 69 status_template = "Рассылка счёта...\nОтправлено: {}"
70 status_msg = await msg.answer(status_template.format(0)) 70 status_msg = await msg.answer(status_template.format(0))
71 71
72 invoice = Invoice(message=data, datetime=datetime.now(UTC)) 72 invoice = Invoice(message=data.rich_text, datetime=datetime.now(UTC))
73 session.add(invoice) 73 session.add(invoice)
74 await session.flush() 74 await session.flush()
75 75
@@ -95,7 +95,7 @@ async def invoice_cancel(msg: Message, state: FSMContext) -> None:
95 95
96@router.message(NewInvoiceStates.message) 96@router.message(NewInvoiceStates.message)
97async def invoice_message(msg: Message, bot: Bot, state: FSMContext) -> None: 97async def invoice_message(msg: Message, bot: Bot, state: FSMContext) -> None:
98 if msg.content_type != ContentType.TEXT or msg.text is None: 98 if msg.text is None:
99 await msg.answer( 99 await msg.answer(
100 "Неверный тип сообщения.\n" 100 "Неверный тип сообщения.\n"
101 "Бот поддерживает отправку только текстовых счетов." 101 "Бот поддерживает отправку только текстовых счетов."