Как стать автором
Обновить

Делаем Telegram бота с Админ-панелью и многими другими плюшками. Часть 2

Время на прочтение5 мин
Количество просмотров59K

Прошлая статья оказалась провальной, именно поэтому хочу улучшить ситуацию путем написания продолжения. Ну буду отвлекаться на самые простые вещи, приступим!

Ну для начала, если вы из прошлой статьи, установите PyCharm. Думаю с установкой сложностей не возникнет, во всяком случае я на это надеюсь.

Открываем PyCharm, создаем файл main.py и начинаем писать.

Первые приготовления
  1. Импортируем необходимые библиотеки:

    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
  2. Обьявляем переменные

    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="Статистика"))
  3. Инициализируем проект

    logging.basicConfig(level=logging.INFO)
    storage = MemoryStorage()
    bot = Bot(token=API_TOKEN)
    dp = Dispatcher(bot, storage=storage)
  4. Создаем Базу Данных

    conn = sqlite3.connect('db.db')
    cur = conn.cursor()
    cur.execute("""CREATE TABLE IF NOT EXISTS users(user_id INTEGER, block INTEGER);""")
    conn.commit()
  5. Обьявляем 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

Спасибо за прочтение!

Теги:
Хабы:
Всего голосов 17: ↑4 и ↓13-9
Комментарии12

Публикации

Истории

Работа

Python разработчик
135 вакансий
Data Scientist
60 вакансий

Ближайшие события