Сокращение кода при написании бота на pyTelegramBotAPI (решение)
За год я написал где-то 10 Telegram ботов на библиотеке pyTelegramBotAPI и все они вкратце выглядят так:
import logging
import time
import telebot
from telebot import types
from telebot.types import Message
logging.basicConfig(
filename='errors.txt',
level=logging.INFO,
format='\n%(asctime)s | %(message)s\n------------',
datefmt='%d.%m.%y %H:%M:%S'
)
while True:
try:
bot = telebot.TeleBot('token')
user_dict = {}
class User:
def __init__(self, text):
self.text = text
@bot.message_handler(content_types=['text'])
def text(message: Message):
try:
markup = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True, row_width=2)
bt1 = types.KeyboardButton('0')
bt2 = types.KeyboardButton('1')
bt3 = types.KeyboardButton('2')
bt4 = types.KeyboardButton('3')
bt5 = types.KeyboardButton('4')
bt6 = types.KeyboardButton('5')
bt7 = types.KeyboardButton('Отмена')
markup.add(bt1, bt2, bt3, bt4, bt5, bt6, bt7)
msg = bot.send_message(message.chat.id, '? Выберите *число*', parse_mode='Markdown',
reply_markup=markup)
bot.register_next_step_handler(msg, text_switch)
except:
logging.error('text', exc_info=True)
def text_switch(message: Message):
try:
chat_id = message.chat.id
user_dict[chat_id] = User(message.text)
user = user_dict[chat_id]
markup = types.ReplyKeyboardRemove(selective=False)
if message.text == '0':
bot.send_message(chat_id, '0️⃣ Ноль', reply_markup=markup)
elif message.text == '1':
bot.send_message(chat_id, '1️⃣ Один', reply_markup=markup)
elif message.text == '2':
bot.send_message(chat_id, '2️⃣ Два', reply_markup=markup)
elif message.text == '3':
bot.send_message(chat_id, '3️⃣ Три', reply_markup=markup)
elif message.text == '4':
bot.send_message(chat_id, '4️⃣ Четыре', reply_markup=markup)
elif message.text == '5':
bot.send_message(chat_id, '5️⃣ Пять', reply_markup=markup)
else:
bot.send_message(chat_id, '⛔ Отмена', reply_markup=markup)
except:
logging.error('text_switch', exc_info=True)
bot.send_message(chat_id, '❗ Какая-то *ошибка*!', parse_mode='Markdown', reply_markup=markup)
bot.enable_save_next_step_handlers(delay=2)
bot.load_next_step_handlers()
bot.polling()
except:
time.sleep(0.5)
Однако для создания клавиатуры нужно много строк кода - одну под создание клавиатуры, под каждую кнопку и одну под добавление кнопок. К тому же очень надоедает в функцию добавления прописывать каждую кнопку через запятую. До этого момента меня не особо тревожило, однако сейчас мне это надоело, поэтому я написал функцию создания клавиатуры. Она представлена в ответе ниже.
Ответы (1 шт):
На вход функция принимает список с названиями кнопок и количество кнопок в строке (по умолчанию 2)
Сама функция:
# Создание клавиатуры
def create_keyboard(keys: list, row_width: int = 2):
keyboard= []
for key in keys:
keyboard.append(types.KeyboardButton(key))
return types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True, row_width=row_width).add(
*keyboard)
Использование в примере:
import logging
import time
import telebot
from telebot import types
from telebot.types import Message
logging.basicConfig(
filename='errors.txt',
level=logging.INFO,
format='\n%(asctime)s | %(message)s\n------------',
datefmt='%d.%m.%y %H:%M:%S'
)
while True:
try:
bot = telebot.TeleBot('token')
user_dict = {}
class User:
def __init__(self, text):
self.text = text
@bot.message_handler(content_types=['text'])
def text(message: Message):
try:
markup = create_keyboard(['0', '1', '2', '3', '4', '5', 'Отмена'])
msg = bot.send_message(message.chat.id, '? Выберите *число*', parse_mode='Markdown',
reply_markup=markup)
bot.register_next_step_handler(msg, text_switch)
except:
logging.error('text', exc_info=True)
def text_switch(message: Message):
try:
chat_id = message.chat.id
user_dict[chat_id] = User(message.text)
user = user_dict[chat_id]
markup = types.ReplyKeyboardRemove(selective=False)
if message.text == '0':
bot.send_message(chat_id, '0️⃣ Ноль', reply_markup=markup)
elif message.text == '1':
bot.send_message(chat_id, '1️⃣ Один', reply_markup=markup)
elif message.text == '2':
bot.send_message(chat_id, '2️⃣ Два', reply_markup=markup)
elif message.text == '3':
bot.send_message(chat_id, '3️⃣ Три', reply_markup=markup)
elif message.text == '4':
bot.send_message(chat_id, '4️⃣ Четыре', reply_markup=markup)
elif message.text == '5':
bot.send_message(chat_id, '5️⃣ Пять', reply_markup=markup)
else:
bot.send_message(chat_id, '⛔ Отмена', reply_markup=markup)
except:
logging.error('text_switch', exc_info=True)
bot.send_message(chat_id, '❗ Какая-то *ошибка*!', parse_mode='Markdown', reply_markup=markup)
# Создание клавиатуры
def create_keyboard(keys: list, row_width: int = 2):
keyboard = []
for key in keys:
keyboard.append(types.KeyboardButton(key))
return types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True, row_width=row_width).add(
*keyboard)
bot.enable_save_next_step_handlers(delay=2)
bot.load_next_step_handlers()
bot.polling()
except:
time.sleep(0.5)
Благодаря этой функции для создания каждой клавиатуры нужно прописать всего лишь 1 строку кода (не считая перенос, если очень длинная)