We make a Telegram bot with the Admin panel and many other goodies. Part 2
The last article was a failure, which is why I want to improve the situation by writing a sequel. Well, I’ll be distracted by the simplest things, let’s get started!
Well, for starters, if you’re from the last article, install PyCharm. I think there will be no difficulties with the installation, at least I hope so.
Open up PyCharm, create a main.py file and start writing.
First preparations
We import the required libraries:
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
Declaring variables
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="Статистика"))
Initializing the project
logging.basicConfig(level=logging.INFO) storage = MemoryStorage() bot = Bot(token=API_TOKEN) dp = Dispatcher(bot, storage=storage)
Create a Database
conn = sqlite3.connect('db.db') cur = conn.cursor() cur.execute("""CREATE TABLE IF NOT EXISTS users(user_id INTEGER, block INTEGER);""") conn.commit()
Declaring States
class dialog(StatesGroup): spam = State() blacklist = State() whitelist = State()
These are the first preparations, now we are ready to start writing the basic logic.
Processing the “/ start” command
@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('Ты был заблокирован!')
Here we add three buttons to the admin panel
Let’s write a function to handle the “Subscribe” button
Mailing function
Now let’s process the “Subscribe” button
@dp.message_handler(content_types=['text'], text="Рассылка")
async def spam(message: Message):
await dialog.spam.set()
await message.answer('Напиши текст рассылки')
But here we just ask the admin what kind of mailing text is
Now let’s process this text and send it to users.
@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()
Here we get users from the Base and send each message
Now let’s add users to the emergency
Lock function
Now we will process the button “Add to emergency”
@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()
But again, now the bot will not do anything with the received ID. Let’s ban users)
@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('Ты вводишь буквы...nnВведи ID')
Now, after you send him a user ID, he will check it, and if he found this user in the Base not banned, then he will be banned! Otherwise, it returns to the main menu.
Now let’s remove users from the emergency
Unlock function
To begin with, according to the standard, we will process the button
@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()
And again the bot does nothing, now let’s fix it!
@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('Ты вводишь буквы...nnВведи ID')
Now let’s add statistics for our bot
Statistics
Unlike other functions, this one will be the simplest.
Here we will receive the number of users in the bot, not active, nor any others, just those who have entered the bot at least once
@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)}')
Now you also have statistics for the bot.
That’s all!
At the end of the file, we must add two lines
if __name__ == '__main__':
executor.start_polling(dp, skip_updates=True)
Now, just launch it and go check it out!
I understand the functionality is not great, not what the title says, but I accept suggestions for what else to add! In the future, finally, I will most likely implement proposals, and I will add them to this article, or to a new one!
All code is laid out on GITHUB
As usual, I am available at the TG: @derkown
Thanks for reading!