В этой статье мы улучшим структуру кода бота Telegram-магазина, разделив команды пользователей и администраторов. Теперь код станет чистым, структурированным и проще в управлении.
💡 Что мы сделаем
✅ Вынесем административные команды в admin_handlers.py
✅ Оставим только команды пользователей в handlers.py
✅ Обновим bot.py
, чтобы подключить оба файла
✅ Добавим управление товарами и заказами для админов
✅ Список всех команд для администраторов в конце статьи 📜
Код для admin_handlers.py
Давайте создадим новый файл admin_handlers.py
и пропишем туда функции для управления админами, заказами и товарами.
🔹 Обычные администраторы смогут:
✅ Добавлять, удалять товары и изменять их цену
✅ Просматривать список заказов и менять их статус
🔹 Супер-администратор может:
✅ Назначать и удалять администраторов
✅ Просматривать список админов
Импорт библиотек и подключение admin_router
Сначала подключаем все нужные модули и создаем роутер для админских команд.
from aiogram import Router
from aiogram.types import Message
from aiogram.filters import Command
from database import (
add_product, remove_product, edit_price, get_products,
get_orders, update_order_status, remove_order,
add_admin, remove_admin, get_admins, is_admin, is_super_admin
)
admin_router = Router()
Управление товарами 🛍
Теперь рассмотрим функции управления товарами.
Добавление товара
@admin_router.message(Command("add_product"))
async def add_product_handler(message: Message):
if not is_admin(message.from_user.id):
await message.answer("❌ У вас нет прав для этой команды.")
return
try:
args = message.text.split(maxsplit=2)
name, price = args[1], int(args[2])
add_product(name, price)
await message.answer(f"✅ Товар **{name}** добавлен с ценой **{price}₽**.")
except:
await message.answer("⚠️ Используйте команду так:\n`/add_product Название Цена`")
✅ Как это работает?
🔹 Проверяем, является ли отправитель администратором.
🔹 Разбираем сообщение (/add_product Название Цена
).
🔹 Добавляем товар в базу данных.
Добавляются товары командой /add_product Название Цена. Например, /add_product Клавиатура 1000 — добавит товар с название «Клавиатура» и ценой 1000 рублей.
Удаление товара
@admin_router.message(Command("remove_product"))
async def remove_product_handler(message: Message):
if not is_admin(message.from_user.id):
await message.answer("❌ У вас нет прав для этой команды.")
return
try:
product_id = int(message.text.split()[1])
remove_product(product_id)
await message.answer(f"✅ Товар с ID `{product_id}` удален.")
except:
await message.answer("⚠️ Используйте команду так:\n`/remove_product product_id`")
✅ Как это работает?
🔹 Проверяем права админа.
🔹 Читаем product_id
из команды.
🔹 Удаляем товар из базы данных.
Например, /remove_product 2, удалит товар с номером 2. Номера товаров можно посмотреть в списке, выполнив команду /products
Изменение цены товара
@admin_router.message(Command("edit_price"))
async def edit_price_handler(message: Message):
if not is_admin(message.from_user.id):
await message.answer("❌ У вас нет прав для этой команды.")
return
try:
product_id, new_price = map(int, message.text.split()[1:3])
edit_price(product_id, new_price)
await message.answer(f"✅ Цена товара с ID `{product_id}` изменена на **{new_price}₽**.")
except:
await message.answer("⚠️ Используйте команду так:\n`/edit_price product_id новая_цена`")
✅ Как это работает?
🔹 Проверяем права.
🔹 Читаем product_id
и новую цену
.
🔹 Обновляем цену товара в базе.
Например, /edit_price 3 10000, изменит цену товара под номером 3 поменяв цену на 10 000₽.
Просмотр списка товаров
@admin_router.message(Command("products"))
async def list_products_handler(message: Message):
if not is_admin(message.from_user.id):
await message.answer("❌ У вас нет прав для этой команды.")
return
products = get_products()
if not products:
await message.answer("❌ Товаров пока нет.")
else:
product_list = "\n".join([f"📦 **{p[0]}** – {p[1]}, **Цена:** {p[2]}₽" for p in products])
await message.answer(f"🛒 **Список товаров:**\n{product_list}")
✅ Как это работает?
🔹 Проверяем права.
🔹 Запрашиваем список товаров из базы.
🔹 Отправляем список пользователю.
Посмотреть весь список товаров можно выполнив команду /products
Управление заказами 📦
Просмотр всех заказов
@admin_router.message(Command("orders"))
async def list_orders_handler(message: Message):
if not is_admin(message.from_user.id):
await message.answer("❌ У вас нет прав для этой команды.")
return
orders = get_orders()
if not orders:
await message.answer("❌ Заказов нет.")
else:
order_list = "\n".join([f"📦 **Заказ #{o[0]}** – {o[1]}₽, **Статус:** {o[2]}" for o in orders])
await message.answer(f"📜 **Список заказов:**\n{order_list}")
✅ Запросит все заказы и выведет их в виде списка.
Посмотреть список заказов можно выполнив команду /orders
Обновление статуса заказа
@admin_router.message(Command("update_order"))
async def update_order_status_handler(message: Message):
if not is_admin(message.from_user.id):
await message.answer("❌ У вас нет прав для этой команды.")
return
try:
args = message.text.split(maxsplit=2)
order_id, new_status = int(args[1]), args[2]
update_order_status(order_id, new_status)
await message.answer(f"✅ Статус заказа **#{order_id}** изменен на **{new_status}**.")
except:
await message.answer("⚠️ Используйте команду так:\n`/update_order order_id новый_статус`")
✅ Позволяет администратору изменить статус заказа.
Изменение выполняется командой /update_order ID Статус. Например, /update_order 2 Ожидает оплату, изменить статус второго заказа на «Ожидает оплату»
Удаление заказа
@admin_router.message(Command("remove_order"))
async def remove_order_handler(message: Message):
if not is_admin(message.from_user.id):
await message.answer("❌ У вас нет прав для этой команды.")
return
try:
order_id = int(message.text.split()[1])
remove_order(order_id)
await message.answer(f"✅ Заказ **#{order_id}** удален.")
except:
await message.answer("⚠️ Используйте команду так:\n`/remove_order order_id`")
✅ Позволяет администратору удалить заказ.
Удаляется заказ командой /remove_order ID. Например, /remove_order 3, удалит заказ под номером 3.
Управление администраторами 🛠
🔹 Добавление администратора (только супер-админ)
@admin_router.message(Command("add_admin"))
async def add_admin_handler(message: Message):
if not is_super_admin(message.from_user.id):
await message.answer("❌ У вас нет прав для этой команды.")
return
try:
user_id = int(message.text.split()[1])
add_admin(user_id)
await message.answer(f"✅ Пользователь {user_id} добавлен в администраторы.")
except:
await message.answer("⚠️ Используйте команду так:\n`/add_admin user_id`")
✅ Супер админ может добавлять нового администратора.
- /add_admin user_id — Добавить администратора
- /remove_admin user_id — Удалить администратора
- /admins — Посмотреть администраторов
Полный код admin_handlers.py
:
from aiogram import Router
from aiogram.types import Message
from aiogram.filters import Command
from database import (
add_product, remove_product, edit_price, get_products,
get_orders, update_order_status, remove_order,
add_admin, remove_admin, get_admins, is_admin, is_super_admin
)
admin_router = Router()
### 🔹 ДОБАВЛЕНИЕ ТОВАРА (Только для админов)
@admin_router.message(Command("add_product"))
async def add_product_handler(message: Message):
if not is_admin(message.from_user.id):
await message.answer("❌ У вас нет прав для этой команды.")
return
try:
args = message.text.split(maxsplit=2)
name, price = args[1], int(args[2])
add_product(name, price)
await message.answer(f"✅ Товар **{name}** добавлен с ценой **{price}₽**.")
except:
await message.answer("⚠️ Используйте команду так:\n`/add_product Название Цена`")
### 🔹 УДАЛЕНИЕ ТОВАРА
@admin_router.message(Command("remove_product"))
async def remove_product_handler(message: Message):
if not is_admin(message.from_user.id):
await message.answer("❌ У вас нет прав для этой команды.")
return
try:
product_id = int(message.text.split()[1])
remove_product(product_id)
await message.answer(f"✅ Товар с ID `{product_id}` удален.")
except:
await message.answer("⚠️ Используйте команду так:\n`/remove_product product_id`")
### 🔹 ИЗМЕНЕНИЕ ЦЕНЫ ТОВАРА
@admin_router.message(Command("edit_price"))
async def edit_price_handler(message: Message):
if not is_admin(message.from_user.id):
await message.answer("❌ У вас нет прав для этой команды.")
return
try:
product_id, new_price = map(int, message.text.split()[1:3])
edit_price(product_id, new_price)
await message.answer(f"✅ Цена товара с ID `{product_id}` изменена на **{new_price}₽**.")
except:
await message.answer("⚠️ Используйте команду так:\n`/edit_price product_id новая_цена`")
### 🔹 ПРОСМОТР СПИСКА ЗАКАЗОВ
@admin_router.message(Command("orders"))
async def list_orders_handler(message: Message):
if not is_admin(message.from_user.id):
await message.answer("❌ У вас нет прав для этой команды.")
return
orders = get_orders()
if not orders:
await message.answer("❌ Заказов нет.")
else:
order_list = "\n".join([f"📦 **Заказ #{o[0]}** – {o[1]}₽, **Статус:** {o[2]}" for o in orders])
await message.answer(f"📜 **Список заказов:**\n{order_list}")
### 🔹 ОБНОВЛЕНИЕ СТАТУСА ЗАКАЗА
@admin_router.message(Command("update_order"))
async def update_order_status_handler(message: Message):
if not is_admin(message.from_user.id):
await message.answer("❌ У вас нет прав для этой команды.")
return
try:
args = message.text.split(maxsplit=2)
order_id, new_status = int(args[1]), args[2]
update_order_status(order_id, new_status)
await message.answer(f"✅ Статус заказа **#{order_id}** изменен на **{new_status}**.")
except:
await message.answer("⚠️ Используйте команду так:\n`/update_order order_id новый_статус`")
### 🔹 УДАЛЕНИЕ ЗАКАЗА
@admin_router.message(Command("remove_order"))
async def remove_order_handler(message: Message):
if not is_admin(message.from_user.id):
await message.answer("❌ У вас нет прав для этой команды.")
return
try:
order_id = int(message.text.split()[1])
remove_order(order_id)
await message.answer(f"✅ Заказ **#{order_id}** удален.")
except:
await message.answer("⚠️ Используйте команду так:\n`/remove_order order_id`")
### 🔹 ДОБАВЛЕНИЕ АДМИНИСТРАТОРА (ТОЛЬКО ДЛЯ СУПЕР-АДМИНА)
@admin_router.message(Command("add_admin"))
async def add_admin_handler(message: Message):
if not is_super_admin(message.from_user.id):
await message.answer("❌ У вас нет прав для этой команды.")
return
try:
user_id = int(message.text.split()[1])
add_admin(user_id)
await message.answer(f"✅ Пользователь {user_id} добавлен в администраторы.")
except:
await message.answer("⚠️ Используйте команду так:\n`/add_admin user_id`")
### 🔹 УДАЛЕНИЕ АДМИНИСТРАТОРА
@admin_router.message(Command("remove_admin"))
async def remove_admin_handler(message: Message):
if not is_super_admin(message.from_user.id):
await message.answer("❌ У вас нет прав для этой команды.")
return
try:
user_id = int(message.text.split()[1])
if is_super_admin(user_id):
await message.answer("⚠️ Нельзя удалить супер-администратора!")
else:
remove_admin(user_id)
await message.answer(f"✅ Пользователь {user_id} удален из администраторов.")
except:
await message.answer("⚠️ Используйте команду так:\n`/remove_admin user_id`")
### 🔹 СПИСОК АДМИНИСТРАТОРОВ
@admin_router.message(Command("admins"))
async def admins_handler(message: Message):
if not is_super_admin(message.from_user.id):
await message.answer("❌ У вас нет прав для этой команды.")
return
admins = get_admins()
if not admins:
await message.answer("❌ Администраторов нет.")
return
text = "👤 **Список администраторов:**\n"
for user_id, is_super in admins:
text += f"• `{user_id}` {'(Супер-админ)' if is_super else ''}\n"
await message.answer(text)
### 🔹 ПРОСМОТР СПИСКА ТОВАРОВ
@admin_router.message(Command("products"))
async def list_products_handler(message: Message):
if not is_admin(message.from_user.id):
await message.answer("❌ У вас нет прав для этой команды.")
return
products = get_products()
if not products:
await message.answer("❌ Товаров пока нет.")
else:
product_list = "\n".join([f"📦 **{p[0]}** – {p[1]}, **Цена:** {p[2]}₽" for p in products])
await message.answer(f"🛒 **Список товаров:**\n{product_list}")
Список доступных команд
Теперь администраторы могут использовать:
🔹 Работа с товарами
/add_product Название Цена
– добавить товар/remove_product product_id
– удалить товар/edit_price product_id новая_цена
– изменить цену/products
– посмотреть список товаров
🔹 Управление заказами
/orders
– список заказов/update_order order_id новый_статус
– изменить статус заказа/remove_order order_id
– удалить заказ
🔹 Администрирование
/add_admin user_id
– добавить администратора/remove_admin user_id
– удалить администратора/admins
– список администраторов
Код handlers.py
Теперь можно из handlers.py
удалить часть кода который мы добавляли в прошлой статье. Вот так теперь выглядит полный код:
from aiogram import Router, F
from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton, ReplyKeyboardMarkup, KeyboardButton
from aiogram.filters import Command
from database import get_products, add_to_cart, get_cart, create_order, remove_from_cart
from keyboards import main_menu
router = Router()
### 🔹 ОБРАБОТКА КОМАНДЫ /START
@router.message(Command("start"))
async def start_command(message: Message):
await message.answer("Добро пожаловать в магазин! Выберите действие: 👇", reply_markup=main_menu)
### 🔹 ОБРАБОТКА КОМАНДЫ "КАТАЛОГ"
@router.message(F.text == "🛍 Каталог")
async def catalog_command(message: Message):
await message.answer("Вот наш каталог. Выберите товар и укажите его количество:")
products = get_products()
for product in products:
product_id, name, price = product
keyboard = InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text="➕ Добавить", callback_data=f"add_{product_id}")],
[InlineKeyboardButton(text="➖ Убрать", callback_data=f"remove_{product_id}")]
])
await message.answer(f"{name} - {price}₽", reply_markup=keyboard)
### 🔹 ОБРАБОТКА КНОПОК "ДОБАВИТЬ" И "УДАЛИТЬ"
@router.callback_query(F.data.startswith("add_") | F.data.startswith("remove_"))
async def update_cart_handler(callback: CallbackQuery):
action, product_id = callback.data.split("_")
product_id = int(product_id)
if action == "add":
add_to_cart(callback.from_user.id, product_id)
await callback.answer("✅ Товар добавлен!")
elif action == "remove":
remove_from_cart(callback.from_user.id, product_id)
await callback.answer("❌ Товар убран!")
### 🔹 ОБРАБОТКА КОМАНДЫ "КОРЗИНА" + КНОПКА "ОБНОВИТЬ"
@router.message(F.text == "🛒 Корзина")
@router.callback_query(F.data == "refresh_cart")
async def cart_command(event):
user_id = event.from_user.id if isinstance(event, CallbackQuery) else event.from_user.id
cart_items = get_cart(user_id)
if not cart_items:
await event.message.answer("Ваша корзина пуста.")
else:
cart_text = "🛒 Ваша корзина:\n"
total_price = 0
keyboard_buttons = []
for name, quantity, price, product_id in cart_items:
total_price += quantity * price
cart_text += f"{name} — {quantity} шт. × {price}₽ = {quantity * price}₽\n"
keyboard_buttons.append([
InlineKeyboardButton(text="➕", callback_data=f"add_{product_id}"),
InlineKeyboardButton(text="➖", callback_data=f"remove_{product_id}")
])
cart_text += f"\n💰 Итоговая сумма: {total_price}₽"
keyboard_buttons.append([
InlineKeyboardButton(text="🔄 Обновить корзину", callback_data="refresh_cart")
])
keyboard_buttons.append([
InlineKeyboardButton(text="✅ Оформить заказ", callback_data="checkout")
])
keyboard = InlineKeyboardMarkup(inline_keyboard=keyboard_buttons)
if isinstance(event, CallbackQuery):
await event.message.edit_text(cart_text, reply_markup=keyboard)
await event.answer()
else:
await event.answer(cart_text, reply_markup=keyboard)
### 🔹 ОБРАБОТКА "ОФОРМИТЬ ЗАКАЗ"
@router.callback_query(F.data == "checkout")
async def request_contact(callback: CallbackQuery):
contact_keyboard = ReplyKeyboardMarkup(
keyboard=[[KeyboardButton(text="📱 Отправить номер", request_contact=True)]],
resize_keyboard=True,
one_time_keyboard=True
)
await callback.message.answer("📱 Отправьте свой номер телефона для оформления заказа:", reply_markup=contact_keyboard)
await callback.answer()
### 🔹 ПОЛУЧЕНИЕ НОМЕРА ТЕЛЕФОНА
@router.message(F.contact | F.text.regexp(r'^\+?\d{10,15}$'))
async def receive_contact(message: Message):
phone_number = message.contact.phone_number if message.contact else message.text
order_id = create_order(message.from_user.id)
if order_id:
await message.answer(f"✅ Заказ #{order_id} оформлен!\n📞 Мы свяжемся с вами по номеру: {phone_number}.")
else:
await message.answer("❌ Ваша корзина пуста, добавьте товары перед заказом.")
Код bot.py
В bot.py
нужно изменить код чтобы он мог обрабатывать пользовательские и админские функции. Вот полный код:
import asyncio
import os
from aiogram import Bot, Dispatcher
from dotenv import load_dotenv
from handlers import router
from admin_handlers import admin_router # Подключаем новый файл
import database
# Загружаем токен
load_dotenv()
BOT_TOKEN = os.getenv("BOT_TOKEN")
if not BOT_TOKEN:
raise ValueError("Ошибка: BOT_TOKEN не найден. Проверьте файл .env!")
bot = Bot(token=BOT_TOKEN)
dp = Dispatcher()
# Подключаем обработчики
dp.include_router(router) # Обычные команды
dp.include_router(admin_router) # Админские команды
async def main():
print("Бот запущен...")
database
await bot.delete_webhook(drop_pending_updates=True)
await dp.start_polling(bot)
if __name__ == "__main__":
asyncio.run(main())
На этом наш телеграм магазин готов. В следующей статье мы подведем итоги и напишем весь полный код нашего магазина.
Пока нет комментариев. Будьте первым!