Прошлая статья оказалась провальной, именно поэтому хочу улучшить ситуацию путем написания продолжения. Ну буду отвлекаться на самые простые вещи, приступим!
Ну для начала, если вы из прошлой статьи, установите PyCharm. Думаю с установкой сложностей не возникнет, во всяком случае я на это надеюсь.
Открываем PyCharm, создаем файл main.py и начинаем писать.
Первые приготовления
Импортируем необходимые библиотеки:
from aiogram import Bot, Dispatcher, executor, types from aiogram.contrib.fsm_storage.memory import MemoryStorage from aiogram.dispatcher import FSMContext from aiogram.dispatcher.filters.state import State, StatesGroup from aiogram.types import Message import logging import sqlite3
Обьявляем переменные
API_TOKEN = 'ТОКЕН' ADMIN = ваш user-id. Узнать можно тут @getmyid_bot kb = types.ReplyKeyboardMarkup(resize_keyboard=True) kb.add(types.InlineKeyboardButton(text="Рассылка")) kb.add(types.InlineKeyboardButton(text="Добавить в ЧС")) kb.add(types.InlineKeyboardButton(text="Убрать из ЧС")) kb.add(types.InlineKeyboardButton(text="Статистика"))
Инициализируем проект
logging.basicConfig(level=logging.INFO) storage = MemoryStorage() bot = Bot(token=API_TOKEN) dp = Dispatcher(bot, storage=storage)
Создаем Базу Данных
conn = sqlite3.connect('db.db') cur = conn.cursor() cur.execute("""CREATE TABLE IF NOT EXISTS users(user_id INTEGER, block INTEGER);""") conn.commit()
Обьявляем States
class dialog(StatesGroup): spam = State() blacklist = State() whitelist = State()
Это первые приготовления, теперь мы готовы начинать писать основную логику
Обработка команды "/start"
@dp.message_handler(commands=['start'])
async def start(message: Message):
cur = conn.cursor()
cur.execute(f"SELECT block FROM users WHERE user_id = {message.chat.id}")
result = cur.fetchone()
if message.from_user.id == ADMIN:
await message.answer('Добро пожаловать в Админ-Панель! Выберите действие на клавиатуре', reply_markup=kb)
else:
if result is None:
cur = conn.cursor()
cur.execute(f'''SELECT * FROM users WHERE (user_id="{message.from_user.id}")''')
entry = cur.fetchone()
if entry is None:
cur.execute(f'''INSERT INTO users VALUES ('{message.from_user.id}', '0')''')
conn.commit()
await message.answer('Привет')
else:
await message.answer('Ты был заблокирован!')
Тут мы добавляем три кнопки в админ-панель
Давайте напишем функцию обработки кнопки "Рассылка"
Функция Рассылки
Теперь давайте обработаем кнопку "Рассылка"
@dp.message_handler(content_types=['text'], text='Рассылка')
async def spam(message: Message):
await dialog.spam.set()
await message.answer('Напиши текст рассылки')
Но тут мы только спрашиваем у админа что за текст рассылки
Теперь давайте обработаем этот текст и отправим его пользователям
@dp.message_handler(state=dialog.spam)
async def start_spam(message: Message, state: FSMContext):
if message.text == 'Назад':
await message.answer('Главное меню', reply_markup=kb)
await state.finish()
else:
cur = conn.cursor()
cur.execute(f'''SELECT user_id FROM users''')
spam_base = cur.fetchall()
for z in range(len(spam_base)):
await bot.send_message(spam_base[z][0], message.text)
await message.answer('Рассылка завершена', reply_markup=kb)
await state.finish()
Тут мы получаем пользователей из Базы и отправляем каждому сообщение
Теперь давайте сделаем добавление пользователей в ЧС
Функция Блокировки
Сейчас мы будем обрабатывать кнопку "Добавить в ЧС"
@dp.message_handler(content_types=['text'], text='Добавить в ЧС')
async def hanadler(message: types.Message, state: FSMContext):
if message.chat.id == ADMIN:
keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
keyboard.add(types.InlineKeyboardButton(text="Назад"))
await message.answer('Введите id пользователя, которого нужно заблокировать.\nДля отмены нажмите кнопку ниже', reply_markup=keyboard)
await dialog.blacklist.set()
Но опять же, сейчас бот ничего не сделает с полученным ID. Давайте будем банить пользователей)
@dp.message_handler(state=dialog.blacklist)
async def proce(message: types.Message, state: FSMContext):
if message.text == 'Назад':
await message.answer('Отмена! Возвращаю назад.', reply_markup=kb)
await state.finish()
else:
if message.text.isdigit():
cur = conn.cursor()
cur.execute(f"SELECT block FROM users WHERE user_id = {message.text}")
result = cur.fetchall()
if len(result) == 0:
await message.answer('Такой пользователь не найден в базе данных.', reply_markup=kb)
await state.finish()
else:
a = result[0]
id = a[0]
if id == 0:
cur.execute(f"UPDATE users SET block = 1 WHERE user_id = {message.text}")
conn.commit()
await message.answer('Пользователь успешно добавлен в ЧС.', reply_markup=kb)
await state.finish()
await bot.send_message(message.text, 'Ты был забанен Администрацией')
else:
await message.answer('Данный пользователь уже получил бан', reply_markup=kb)
await state.finish()
else:
await message.answer('Ты вводишь буквы...\n\nВведи ID')
Вот теперь, после того как Вы отправите ему ID пользователя, он проверить его, и если нашел этого пользователя в Базе не забаненый, то банит! В остальных случаях возвращает в главное меню
Теперь давайте будем Удалять пользователей из ЧС
Функция Разблокировки
Для начала, по стандарту, обработаем кнопку
@dp.message_handler(content_types=['text'], text='Убрать из ЧС')
async def hfandler(message: types.Message, state: FSMContext):
cur = conn.cursor()
cur.execute(f"SELECT block FROM users WHERE user_id = {message.chat.id}")
result = cur.fetchone()
if result is None:
if message.chat.id == ADMIN:
keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
keyboard.add(types.InlineKeyboardButton(text="Назад"))
await message.answer('Введите id пользователя, которого нужно разблокировать.\nДля отмены нажмите кнопку ниже', reply_markup=keyboard)
await dialog.whitelist.set()
И снова бот ничего не делает, сейчас исправим это!
@dp.message_handler(state=dialog.whitelist)
async def proc(message: types.Message, state: FSMContext):
if message.text == 'Отмена':
await message.answer('Отмена! Возвращаю назад.', reply_markup=kb)
await state.finish()
else:
if message.text.isdigit():
cur = conn.cursor()
cur.execute(f"SELECT block FROM users WHERE user_id = {message.text}")
result = cur.fetchall()
conn.commit()
if len(result) == 0:
await message.answer('Такой пользователь не найден в базе данных.', reply_markup=kb)
await state.finish()
else:
a = result[0]
id = a[0]
if id == 1:
cur = conn.cursor()
cur.execute(f"UPDATE users SET block = 0 WHERE user_id = {message.text}")
conn.commit()
await message.answer('Пользователь успешно разбанен.', reply_markup=kb)
await state.finish()
await bot.send_message(message.text, 'Вы были разблокированы администрацией.')
else:
await message.answer('Данный пользователь не получал бан.', reply_markup=kb)
await state.finish()
else:
await message.answer('Ты вводишь буквы...\n\nВведи ID')
Теперь добавим статистику для нашего бота
Статистика
В отличии от других функций, эта будет самая простая.
Тут мы будем получать количество пользователей в боте, не активных, ни каких других, просто тех кто зашел хоть раз в бот
@dp.message_handler(content_types=['text'], text='Статистика')
async def hfandler(message: types.Message, state: FSMContext):
cur = conn.cursor()
cur.execute('''select * from users''')
results = cur.fetchall()
await message.answer(f'Людей которые когда либо заходили в бота: {len(results)}')
Теперь у вас есть еще и статистика для бота
Вот и всё!
В конце файла мы должны добавить две строчки
if __name__ == '__main__':
executor.start_polling(dp, skip_updates=True)
Теперь просто запускаем и идем проверять!
Понимаю функционал не большой, не то что говорилось в названии, но я принимаю предложения что же добавить еще! В будущем ваще предложения я скорее всего реализую, и буду добавлять в эту статью, либо в новую!
Весь код выложен на GITHUB
Как обычно, я доступен в ТГ: @derkown
Спасибо за прочтение!