Формат интерфейса между справочными данными и пользователем в виде телеграм бота кажется очень привлекательным в современном мире. Допустим вы хотите обеспечить своих сотрудников справочными данными, которые будут всегда под рукой. При этом хорошо бы предусмотреть возможность добавления данных в зависимости от потребностей сотрудников. Как это сделать?
Именно такую задачу предлагаю сегодня рассмотреть.
Стандартно поставим Python и PyCharm. С использованием BotFather создадим бот и получим токен. Для обеспечения защиты токена я храню его в отдельном файле secrets.py и импортирую.
from secrets import secrets token = secrets.get('BOT_API_TOKEN') bot = telebot.TeleBot(token)
Создадим справочник (файл Dictionary.py), данные из которого будем по запросу выдавать пользователям. Я, для примера, сделал справочник по микросхемам памяти. Данные представляют собой набор данных: маркировка, аннотация, название файла с даташитом.
spisok=[["w25q128jv", "Последовательная Flash память на 128 Мбит с интерфейсом SPI.", "1.pdf"], ["w25q128fv", "Последовательная Flash память на 128 Мбит с интерфейсом SPI.", "2.pdf"], ["w25q128jw", "Последовательная Flash память на 128 Мбит с интерфейсом SPI.", "3.pdf"], ["w25q128bv", "Последовательная Flash память на 128 Мбит с интерфейсом SPI.", "4.pdf"], ["w25q128fw", "Последовательная Flash память на 128 Мбит с интерфейсом SPI.", "5.pdf"], ["w25q16jv", "Последовательная Flash память на 16 Мбит с интерфейсом SPI.", "6.pdf"], ["w25q32bv", "Последовательная Flash память на 32 Мбит с интерфейсом SPI.", "7.pdf"], ["w25q32fv", "Последовательная Flash память на 32 Мбит с интерфейсом SPI.", "8.pdf"], ["w25q32jv", "Последовательная Flash память на 32 Мбит с интерфейсом SPI.", "9.pdf"], ["w25q40ew", "Последовательная Flash память на 4 Мбит с интерфейсом SPI.", "10.pdf"], ["w25q64jv", "Последовательная Flash память на 64 Мбит с интерфейсом SPI.", "11.pdf"], ["w25x20cl", "Последовательная Flash память на 2 Мбит с интерфейсом SPI.", "12.pdf"], ["w9812g6kh", "Микросхема памяти SDRAM, 128 Мбит.", "14.pdf"], ["w25q64bv", "Последовательная Flash память на 64 Мбит с интерфейсом SPI.", "15.pdf"], ["w9825g6kh", "Микросхема памяти SDRAM, 256 Мбит.", "16.pdf"], ["w25q256jv", "Последовательная Flash память на 256 Мбит с интерфейсом SPI.", "17.pdf"], ["w25q80d", "Последовательная Flash память на 8 Мбит с интерфейсом SPI.", "18.pdf"], ["w25x40cl", "Последовательная Flash память на 4 Мбит с интерфейсом SPI.", "19.pdf"], ["w27c512", "Микросхема памяти EEPROM на 512 кбит.", "20.pdf"], ["w9864g6kh", "Микросхема памяти SDRAM, 64 Мбит.", "21.pdf"], ["w25q80ew", "Последовательная Flash память на 8 Мбит с интерфейсом SPI.", "22.pdf"], ["w25n01gv", "Последовательная Flash память на 1 Гбит с интерфейсом SPI.", "23.pdf"], ["w25q16jw", "Последовательная Flash память на 16 Мбит с интерфейсом SPI.", "24.pdf"], ["w25q20ew", "Последовательная Flash память на 2 Мбит с интерфейсом SPI.", "25.pdf"], ["w25q64fv", "Последовательная Flash память на 64 Мбит с интерфейсом SPI.", "26.pdf"], ["w25q80bv", "Последовательная Flash память на 8 Мбит с интерфейсом SPI.", "27.pdf"], ["w978h6kb", "Микросхема памяти SDRAM, 256 Мбит.", "28.pdf"], ["w978h2kb", "Микросхема памяти SDRAM, 256 Мбит.", "28.pdf"], ["w25q20cl", "Последовательная Flash память на 2 Мбит с интерфейсом SPI.", "29.pdf"], ["w25q40cl", "Последовательная Flash память на 4 Мбит с интерфейсом SPI.", "30.pdf"]]
Импортируем данный список в проект.
from Dictionary import spisok
Теперь можно приступить к разработке алгоритма работы справочной системы. Код обработки введенной строки представлен ниже.
@bot.message_handler(content_types=['text']) def get_text_messages(message): global file_name global stroka3 chec = 0 stroka1 = message.text.lower() if message.text == "/start": bot.send_message(message.from_user.id, "Справочник по электронике. Введите маркировку.") else: for i in range(len(spisok)): #все в нижний регистр stroka = spisok[i][0].lower() fin_stroka = [] if stroka.find(stroka1) >= 0 or stroka1.find(stroka) >= 0: chec += 1 # увеличиваем счетчик на 1 file_name = spisok[i][2] fin_stroka.append("___"+spisok[i][0]+"___") fin_stroka.append(spisok[i][1]) bot.send_message(message.chat.id, '\n'.join(fin_stroka)) if chec == 1 : keyboard = types.InlineKeyboardMarkup() key_yes = types.InlineKeyboardButton(text='Да', callback_data='yes') keyboard.add(key_yes) key_no = types.InlineKeyboardButton(text='Нет', callback_data='no') keyboard.add(key_no) question = 'Загрузить даташит?' bot.send_message(message.from_user.id, text=question, reply_markup=keyboard) elif chec == 0: f = open('zayavka.txt', 'a') if stroka3 != stroka1: stroka3 = stroka1 f.write(stroka1 + '\n') bot.send_message(message.from_user.id, "Данная позиция отсутствует в справочнике. Заявка на ее добавление принята.")
В ответ на стартовое сообщение пользователю выдается приглашение к вводу маркировки (строки 7,9).
В строках 10-19 осуществляется поиск введенной пользователем маркировки в импортированном списке. При этом очень важный момент заключается в том, что поиск осуществляется путем поиска введенной строки в строке из списка и наоборот (строка 14). Это позволяет найти микросхему при введении части маркировки, а также при введении избыточной для поиска маркировки (т.к. даташит рассматривает несколько вариантов по корпусам, то написанная на корпусе маркировка будет более полной).
Все найденные совпадения в виде отдельных сообщений выводятся пользователю. На основе данной информации пользователь может скорректировать свой запрос для получения конкретного даташита. В случае обнаружения одного совпадения предлагается скачать даташит (строки 20-27). Для определения необходимости скачивания пользователю выводятся кнопки «да» и «нет»
Обработка нажатий на данные кнопки в виде кода описана ниже.
@bot.callback_query_handler(func=lambda call: True) def callback_worker(call): global file_name if call.data == "yes": #call.data это callback_data, которую мы указали при объявлении кнопки file = open("./Baza/"+file_name, "rb") bot.send_document(call.message.chat.id, file) bot.send_message(call.message.chat.id, "Справочник по электронике. Введите маркировку.") elif call.data == "no": bot.send_message(call.message.chat.id, "Справочник по электронике. Введите маркировку.")
Если пользователь выбирает кнопку "да", то осуществляется выгрузка даташита из каталога Baza (строки 4-7).
При начале эксплуатации данной системы пользователи будут часто сталкиваться с отсутствием данных в нашей справочной системы. Для решения данной проблемы предусмотрено сохранение запроса пользователя в случае отсутствия в базе (файл zayavka.txt).
f = open('zayavka.txt', 'a') if stroka3 != stroka1: stroka3 = stroka1 f.write(stroka1 + '\n') bot.send_message(message.from_user.id, "Данная позиция отсутствует в справочнике. Заявка на ее добавление принята.")
Полный текст основного файла представлен ниже
import telebot # Импортируем telebot from secrets import secrets # Словарь с токеном из файла secrets.py from Dictionary import spisok # Импортируем словарь для Списка продуктов from telebot import types # для указания типов # передаём значение переменной с кодом экземпляру бота token = secrets.get('BOT_API_TOKEN') bot = telebot.TeleBot(token) global stroka3 stroka3 = "" @bot.callback_query_handler(func=lambda call: True) def callback_worker(call): global file_name if call.data == "yes": #call.data это callback_data, которую мы указали при объявлении кнопки file = open("./Baza/"+file_name, "rb") bot.send_document(call.message.chat.id, file) bot.send_message(call.message.chat.id, "Справочник по электронике. Введите маркировку.") elif call.data == "no": bot.send_message(call.message.chat.id, "Справочник по электронике. Введите маркировку.") @bot.message_handler(content_types=['text']) def get_text_messages(message): global file_name global stroka3 chec = 0 stroka1 = message.text.lower() if message.text == "/start": bot.send_message(message.from_user.id, "Справочник по электронике. Введите маркировку.") else: for i in range(len(spisok)): #все в нижний регистр stroka = spisok[i][0].lower() fin_stroka = [] if stroka.find(stroka1) >= 0 or stroka1.find(stroka) >= 0: chec += 1 # увеличиваем счетчик на 1 file_name = spisok[i][2] fin_stroka.append("___"+spisok[i][0]+"___") fin_stroka.append(spisok[i][1]) bot.send_message(message.chat.id, '\n'.join(fin_stroka)) #print(stroka.find(stroka1)) #print(stroka1.find(stroka)) if chec == 1 : keyboard = types.InlineKeyboardMarkup() key_yes = types.InlineKeyboardButton(text='Да', callback_data='yes') keyboard.add(key_yes) key_no = types.InlineKeyboardButton(text='Нет', callback_data='no') keyboard.add(key_no) question = 'Загрузить даташит?' bot.send_message(message.from_user.id, text=question, reply_markup=keyboard) elif chec == 0: f = open('zayavka.txt', 'a') if stroka3 != stroka1: stroka3 = stroka1 f.write(stroka1 + '\n') bot.send_message(message.from_user.id, "Данная позиция отсутствует в справочнике. Заявка на ее добавление принята.") # бесконечное выполнение кода while True: try: bot.polling(none_stop=True, interval=0) except: continue
В строках 60-64 предусмотрено постоянное выполнение кода с учетом исключения ошибок.
Протестируем наш бот. После старта бот предлагает ввести маркировку. Введем запрос "128". Бот выдает все микросхемы в маркировке которых есть "128" и аннотацию по ним.

Мы видим, что в базе есть микросхема w25q128bv. Скорректируем наш запрос "w25q128bv".

Соглашаемся со скачиванием даташита.

Попробуем ввести отсутствующую маркировку. Например "qwert123".

В файл zayavka.txt добавлена строка с отсутствующей маркировкой. Это позволяет администратору справочника при обновлении базы добавить в базу нужные элементы.

В статье рассмотрен вариант формирования справочной системы с использованием телеграм бота. Удобство данного подхода заключается в доступности актуальной информации с использованием мессенджера, который установлен почти на всех мобильных гаджетах.
