В этом обновлении мы добавим систему администраторов в наш Telegram-магазин. Теперь можно назначать администраторов, которые смогут управлять товарами и заказами, но не смогут назначать других админов. Мы создадим супер-администратора с возможностью добавлять обычных админов.
Удаляем старую базу и создаем новую
Так как нам нужно добавить новую таблицу admins
, нам нужно удалить старый файл shop.db
, иначе бот не сможет работать с обновленной структурой базы.
Удаляем файл shop.db
(его можно просто удалить вручную) или удалить через терминал, как это сделать можно посмотреть в предыдущей статьи.
Изменения в database.py
Теперь в файле database.py
нужно добавить таблицу admins
, в которой будут храниться user_id
администраторов. Так же не забываем добавить и другие таблицы.
import sqlite3
# Подключение к базе данных
conn = sqlite3.connect("shop.db")
cursor = conn.cursor()
# Таблица товаров
cursor.execute("""
CREATE TABLE IF NOT EXISTS products (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
price INTEGER NOT NULL
)
""")
# Таблица корзины
cursor.execute("""
CREATE TABLE IF NOT EXISTS cart (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
product_id INTEGER NOT NULL,
quantity INTEGER NOT NULL,
FOREIGN KEY (product_id) REFERENCES products (id)
)
""")
# Таблица заказов
cursor.execute("""
CREATE TABLE IF NOT EXISTS orders (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
total_price INTEGER NOT NULL,
status TEXT NOT NULL DEFAULT 'pending'
)
""")
# Таблица администраторов
cursor.execute("""
CREATE TABLE IF NOT EXISTS admins (
user_id INTEGER PRIMARY KEY,
is_super_admin INTEGER DEFAULT 0
)
""")
conn.commit()
conn.close()
Запускаем database.py
и таблицы с базой данной создадустся. Также мы добавим функции для управления администраторами:
def add_admin(user_id):
conn = sqlite3.connect("shop.db")
cursor = conn.cursor()
cursor.execute("INSERT OR IGNORE INTO admins (user_id) VALUES (?)", (user_id,))
conn.commit()
conn.close()
def remove_admin(user_id):
conn = sqlite3.connect("shop.db")
cursor = conn.cursor()
cursor.execute("DELETE FROM admins WHERE user_id = ?", (user_id,))
conn.commit()
conn.close()
def is_admin(user_id):
conn = sqlite3.connect("shop.db")
cursor = conn.cursor()
cursor.execute("SELECT 1 FROM admins WHERE user_id = ?", (user_id,))
result = cursor.fetchone()
conn.close()
return result is not None
Мы удаляли базу, поэтому нужно добавить тестовые товары. Чтобы добавить несколько тестовых товары, можно запустить Python-скрипт вручную.
✅ Открой терминал и запусти Python:
Далее в интерактивном режиме выполни команды:
from database import add_product
add_product("📦 Товар A", 100)
add_product("📦 Товар B", 200)
add_product("📦 Товар C", 300)
print("Товары добавлены!")
После этого товары появятся в базе. Чтобы убедиться, что товары записаны, в терминале введи:
from database import get_products
print(get_products())
Ты увидишь список товаров:
После всех изменений полный код
database.py
выглядит так:
import sqlite3
# Подключение к базе данных
conn = sqlite3.connect("shop.db")
cursor = conn.cursor()
# Таблица товаров
cursor.execute("""
CREATE TABLE IF NOT EXISTS products (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
price INTEGER NOT NULL
)
""")
# Таблица корзины
cursor.execute("""
CREATE TABLE IF NOT EXISTS cart (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
product_id INTEGER NOT NULL,
quantity INTEGER NOT NULL,
FOREIGN KEY (product_id) REFERENCES products (id)
)
""")
# Таблица заказов
cursor.execute("""
CREATE TABLE IF NOT EXISTS orders (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
total_price INTEGER NOT NULL,
status TEXT NOT NULL DEFAULT 'pending'
)
""")
# Таблица администраторов
cursor.execute("""
CREATE TABLE IF NOT EXISTS admins (
user_id INTEGER PRIMARY KEY,
is_super_admin INTEGER DEFAULT 0
)
""")
conn.commit()
conn.close()
### Функции для работы с товарами
def add_product(name, price):
conn = sqlite3.connect("shop.db")
cursor = conn.cursor()
cursor.execute("INSERT INTO products (name, price) VALUES (?, ?)", (name, price))
conn.commit()
conn.close()
def get_products():
conn = sqlite3.connect("shop.db")
cursor = conn.cursor()
cursor.execute("SELECT * FROM products")
products = cursor.fetchall()
conn.close()
return products
### Функции для работы с корзиной
def add_to_cart(user_id, product_id, quantity=1):
conn = sqlite3.connect("shop.db")
cursor = conn.cursor()
cursor.execute("SELECT quantity FROM cart WHERE user_id=? AND product_id=?", (user_id, product_id))
result = cursor.fetchone()
if result:
new_quantity = result[0] + quantity
cursor.execute("UPDATE cart SET quantity=? WHERE user_id=? AND product_id=?", (new_quantity, user_id, product_id))
else:
cursor.execute("INSERT INTO cart (user_id, product_id, quantity) VALUES (?, ?, ?)", (user_id, product_id, quantity))
conn.commit()
conn.close()
def remove_from_cart(user_id, product_id):
conn = sqlite3.connect("shop.db")
cursor = conn.cursor()
cursor.execute("SELECT quantity FROM cart WHERE user_id=? AND product_id=?", (user_id, product_id))
result = cursor.fetchone()
if result:
if result[0] > 1:
new_quantity = result[0] - 1
cursor.execute("UPDATE cart SET quantity=? WHERE user_id=? AND product_id=?", (new_quantity, user_id, product_id))
else:
cursor.execute("DELETE FROM cart WHERE user_id=? AND product_id=?", (user_id, product_id))
conn.commit()
conn.close()
def get_cart(user_id):
conn = sqlite3.connect("shop.db")
cursor = conn.cursor()
cursor.execute("""
SELECT products.name, cart.quantity, products.price, products.id
FROM cart
JOIN products ON cart.product_id = products.id
WHERE cart.user_id=?
""", (user_id,))
cart_items = cursor.fetchall()
conn.close()
return cart_items
def create_order(user_id):
conn = sqlite3.connect("shop.db")
cursor = conn.cursor()
cursor.execute("""
SELECT products.id, products.price, cart.quantity
FROM cart
JOIN products ON cart.product_id = products.id
WHERE cart.user_id=?
""", (user_id,))
cart_items = cursor.fetchall()
if not cart_items:
conn.close()
return None
total_price = sum(item[1] * item[2] for item in cart_items)
cursor.execute("INSERT INTO orders (user_id, total_price) VALUES (?, ?)", (user_id, total_price))
order_id = cursor.lastrowid
cursor.execute("DELETE FROM cart WHERE user_id=?", (user_id,))
conn.commit()
conn.close()
return order_id
### Функции для работы с администраторами
def set_super_admin(user_id):
conn = sqlite3.connect("shop.db")
cursor = conn.cursor()
cursor.execute("SELECT COUNT(*) FROM admins WHERE is_super_admin=1")
if cursor.fetchone()[0] == 0:
cursor.execute("INSERT INTO admins (user_id, is_super_admin) VALUES (?, 1)", (user_id,))
conn.commit()
conn.close()
return True
conn.close()
return False
def add_admin(user_id):
conn = sqlite3.connect("shop.db")
cursor = conn.cursor()
cursor.execute("INSERT OR IGNORE INTO admins (user_id) VALUES (?)", (user_id,))
conn.commit()
conn.close()
def remove_admin(user_id):
conn = sqlite3.connect("shop.db")
cursor = conn.cursor()
cursor.execute("DELETE FROM admins WHERE user_id=? AND is_super_admin=0", (user_id,))
conn.commit()
conn.close()
def is_admin(user_id):
conn = sqlite3.connect("shop.db")
cursor = conn.cursor()
cursor.execute("SELECT COUNT(*) FROM admins WHERE user_id=?", (user_id,))
result = cursor.fetchone()[0]
conn.close()
return result > 0
def is_super_admin(user_id):
conn = sqlite3.connect("shop.db")
cursor = conn.cursor()
cursor.execute("SELECT is_super_admin FROM admins WHERE user_id=?", (user_id,))
result = cursor.fetchone()
conn.close()
return result and result[0] == 1
def get_admins():
conn = sqlite3.connect("shop.db")
cursor = conn.cursor()
cursor.execute("SELECT user_id, is_super_admin FROM admins")
admins = cursor.fetchall()
conn.close()
return admins
Команды для управления администраторами в handlers.py
Теперь у нас будет три команды:
/add_admin <user_id>
— добавляет администратора (доступно только супер-админу)./remove_admin <user_id>
— удаляет администратора (доступно только супер-админу)./admins
— показывает список администраторов.
Добавляем их в handlers.py
:
from aiogram import Router
from aiogram.types import Message
from aiogram.filters import Command
from database import add_admin, remove_admin, is_admin, get_admins
router = Router()
SUPER_ADMIN_ID = 123456789 # Замените на ваш user_id
@router.message(Command("add_admin"))
async def add_admin_handler(message: Message):
if message.from_user.id != SUPER_ADMIN_ID:
await message.answer("У вас нет прав для выполнения этой команды.")
return
parts = message.text.split()
if len(parts) != 2 or not parts[1].isdigit():
await message.answer("Использование: /add_admin ")
return
user_id = int(parts[1])
add_admin(user_id)
await message.answer(f"Пользователь {user_id} добавлен в администраторы.")
@router.message(Command("remove_admin"))
async def remove_admin_handler(message: Message):
if message.from_user.id != SUPER_ADMIN_ID:
await message.answer("У вас нет прав для выполнения этой команды.")
return
parts = message.text.split()
if len(parts) != 2 or not parts[1].isdigit():
await message.answer("Использование: /remove_admin ")
return
user_id = int(parts[1])
remove_admin(user_id)
await message.answer(f"Пользователь {user_id} удален из администраторов.")
@router.message(Command("admins"))
async def list_admins_handler(message: Message):
admins = get_admins()
if not admins:
await message.answer("Список администраторов пуст.")
else:
admin_list = "\n".join([str(admin[0]) for admin in admins])
await message.answer(f"Администраторы:\n{admin_list}")
Теперь супер-админ сможет добавлять и удалять администраторов. При первом запуске нужно запустить команду /set_super_admin и если до этого не было супер админа, то вы будете им назначены. В противном случаи будет выводится сообщение «⚠️ Супер-администратор уже назначен.»
Полный код
handlers.py
теперь такой:
from aiogram import Router, F
from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton, ReplyKeyboardMarkup, KeyboardButton
from aiogram.filters import Command
from keyboards import main_menu
from database import (
set_super_admin, add_admin, remove_admin, is_admin, is_super_admin, get_admins,
get_products, add_to_cart, get_cart, create_order, remove_from_cart
)
router = Router()
### 🔹 ОБРАБОТКА КОМАНДЫ /START
@router.message(Command("start"))
async def start_command(message: Message):
await message.answer("Добро пожаловать в магазин! Выберите действие:", reply_markup=main_menu)
### 🔹 УСТАНОВКА СУПЕР-АДМИНА (ОДИН РАЗ)
@router.message(Command("set_super_admin"))
async def set_super_admin_handler(message: Message):
if set_super_admin(message.from_user.id):
await message.answer("✅ Вы назначены супер-администратором!")
else:
await message.answer("⚠️ Супер-администратор уже назначен.")
### 🔹 ДОБАВЛЕНИЕ АДМИНИСТРАТОРА (ТОЛЬКО ДЛЯ СУПЕР-АДМИНА)
@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("⚠️ Используйте: `/add_admin user_id`")
### 🔹 УДАЛЕНИЕ АДМИНИСТРАТОРА (ТОЛЬКО ДЛЯ СУПЕР-АДМИНА)
@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("⚠️ Используйте: `/remove_admin user_id`")
### 🔹 СПИСОК АДМИНИСТРАТОРОВ
@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)
### 🔹 ОБРАБОТКА КОМАНДЫ "КАТАЛОГ"
@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("❌ Ваша корзина пуста, добавьте товары перед заказом.")
Вывод:
Теперь у нас есть полноценная система администраторов в Telegram-магазине:
✅ Супер-админ – единственный, кто может управлять администраторами.
✅ Обычные админы – могут управлять товарами и заказами.
✅ Безопасность – супер-админа нельзя удалить.
Следующий шаг – улучшение панели администратора и управление магазином через меню! 🚀
Пока нет комментариев. Будьте первым!