Comments 37
В сети куча мануалов для создания Telegram-бота
Но есть ли где пример создания (на python/java) telegram-клиента?
Есть необходимость создать бота(на самом деле программы, работающей на отдельном телефонном номере), который бы по запросу передавал временные пароли через секретный чат.
(Примечательно что приватные чаты могут создаваться только в мобильных версиях телеграм-клиентов)
Приветствую!
Хотел заняться созданием клиента, но не могу найти на это времени. Думаю, что обязательно напишу об этом статейку.
Наверное быстрее всего будет начать с этого: core.telegram.org/tdlib
Я как раз на днях собрал под Винду и запустил под c#, интерфейс общения json, наименования довольно говорящие и интуитивно понятные.
Если кому-то хочется увидеть статью про более сложного бота (с вебхуками, подключенной БД с настройками пользователей и т.д.) — пишите.

очень даже интересно.
Думал написать бота для тех. поддержки.
Проблем словил много:
1) как взаимодействовать с клиентом, т.е. отвечать кому-то конкретному, если пришел вопрос от двоих. Как сделать интерфейс админу (сделать кнопку с ответом разным пользователям).
2) как сделать кнопку запросить телефон, в тинькоф банке есть такое. При общении они спрашивают твой телефон, ты просто жмешь кнопку и они тебя проверили.
3) куда сохранять лучше историю? Я сделал в postgre. Сначала хотел писать sqllite, но столкнулся с проблемой доступа к файлу базы, видимо из-за параллельных потоков. А если вдруг бота в бой пускать, то с postgre сложнее разворачивать. Еще как вариант, думал писать просто в файл, в json формате или т.п.
4) историю сообщений думал сохранить в базе, чтоб оператор мог посмотреть всю переписку, но опять не придумал как ее выводить, может кнопку сделать прислать на почту, но почта не очень оперативно.ю когда в чате общаешься.
в общем у меня вроде и работает, но как-то криво. Если покажете пример (не обязательно все готовое и на блюдечке, можно озвученные темы) то будет супер.
да, я использовал telebot
1) Сам бот и бдует отвечать кому-то конкретному. Про интерфейс для админа немного не понял.
3) Историю, как по мне, лучше хранить в файле. Можно даже генерировать файл для каждого нового пользователя и хранить и х в отдельной папке, врядли это заёмёт слишком много места. Но надо покапаться если бот работает с фото и прочими документами, чтобы хранились их ID.
Пример сделаю, но время нужно найти, со всем чётко разобраться и написать статью. Постараюсь всё сделать как можно быстрее.
Спасибо за отклик!
Возможно и лучше. Честно, не так уж много работал с хранением данных, чтобы что-то однозначно утверждать.
мой вопрос был не в выборе базы MS Sql, PostGRE или MySQL а в возможности не использовать базу а писать в файл, т.к. данных вроде не очень много. И я хотел получить совет, как это сделать и стоит ли так делать или лучше СУБД нет ничего.
А почему нельзя в файл то? Это же питон.
По поводу стоит или нет. Всё зависит от проекта и данных, которые необходимо хранить. Но, всё же, это колхоз не очень рационально хранить всё в файле.
Про интерфейс для админа немного не понял.

клиент спросил вопрос, этот вопрос пришел двум сотрудникам тех.поддержки.
Один сотрудник отвечает через телеграмм нужному клиенту.
Я для этого сделал так: сотрудник получил сообщение: клиент 165313 сказал вопрос
Сотрудник пишет: например /ans а потом (uid клиента)(спец символ, например %)(ответ клиенту). Получается не очень удобно.
При этом остальные сотрудники тех.поддержки должны получить информацию, что с клиентом кто-то работает. А это еще лишняя информация, засоряющая чат.
В идеале сделать тех.поддержке кнопки, типа ответить клиенту 1, ответить клиенту 2. И если кто-то отвечает уже этому клиенту, то кнопка ответить клиенту 1 у других не активно. Но так у меня уже не получилось сделать.
Я бы даже отделное веб приложение для тех поддержки написал со списком вопров и автоудалением/заглушкой на них при крили какого-либо сотрудника. Ну и кончено проверка взял ли кто-то этот вопрос или нет при попытке его открыть…
это если крупная компания, а если контора на 5 человек, то все должны быть мобильные и готовы ответить с сотового в любой момент (и днем и ночью работа прежде всего). А веб приложение только с рабочего места — не очень оперативно.
Почему только с рабочего места? С телефона нельзя зайти в админку? Возможно я что-то ещё не знаю.
  1. Для разделения — проще всего с разными людьми взаимодействовать в разных чатах (разные chat_id).
  2. В кнопку добавляется параметр request_contact=True, потом забирать телефон из вернувшегося объекта contact https://core.telegram.org/bots/api/#contact
  3. А зачем на почту, когда можно файл с историей высылать в чат?
Всем привет! Проше прощения, не заметил как опубликовали!!! Я нашёл пару неточностей, например про взаимодействие с токенами! Сейчас всё отброшу и напишу как и что правильно делать!
Если кому-то хочется увидеть статью про более сложного бота (с вебхуками, подключенной БД с настройками пользователей и т.д.) — пишите.

тоже очень интересно, взаимодествие с юзерами, хранение их данных в базе, и т.п
Постараюсь сделать, но время нужно найти, со всем чётко разобраться и написать статью. Постараюсь всё сделать как можно быстрее.
Спасибо!
так же интересно, почему выбрали telebot, а не python-telegram-bot? в ней (telebot) больше возможностей?
и почему PyTelegramBotAPI==2.2.3? я так понимаю версия 3.6 последняя? какие то проблемы будут на Heroku? какие?
Спасибо.
1) Как по мне telebot удобнее и лучше задокументирован, возможно это вкусовщина.
2) Каюсь, раньше хероку выдавала море ошибок с новыми версиями PyTelegramBotAPI, сейчас же (только что протестил) всё нормально.
В примере я так понимаю вы используете Long Polling, а не вебхуки?
Было бы еще интересно если бы Вы в процессе показали как настраивать Apache или Nginx для работы питона с вебхуками. И потом деплой всего этого хотя бы на Heroku.
Если это не сильно много. Спасибо.
Да, long polling. Постараюсь написать по возможности статьи про более сложного бота с вебхуками и настройками пользователя. К сожалени не могу даже приблизительно сказать о сроказ написания, т.к. море работы.
И, не забываем зайти на гитхаб и удалить TOKEN из нашего bot.py. Ведь нам не нужно, чтобы кто-то им пользовался.

Серьезно? Ну, Семен Семёныч!
image
Рекомендую вынести токены в отдельный файл tokens.py, и добавить этот файл ручками в .gitignore (тогда файл не будет заливаться на гитхаб).

Вообще, за статью спасибо! Сам тут недавно написал бота для чтения книг, тоже на telebot. Правда теперь хочу причесать код в нормальный ООП-стайл.
И, кстати, polling пришлось обернуть бесконечным циклом, так как часто там какие-то ошибки подключения. И он просто падает.
while True:
        try:
            tb.polling(none_stop=True)
        except Exception as e:
            logger.error(e)
            time.sleep(15)
Про удаление токена это да, я наколхозил выбрал не самый рациональный вариант. Никогда серьёзно не пользовался гитом, т.к. программирование было хобби.

Про падение бота я бы поговорил, как по мне, бот падать не должен, нужно все такие сценарии обрабатывать.

Ну а про ООП стайл… Тут от сложности бота зависит. Есть ли смысл парсер-бот в него оборачивать?)
Криво вставил ссылку на изображение в первом комменте:
image

Про падения — но вот он, тем не менее, падает по таймауту. Это уже некая особенность реализации telebot, как я понимаю. Так по сути и обрабатываю сценарий перезапуском. Примеры ошибок
File "/usr/local/lib/python3.5/dist-packages/telebot/__init__.py", line 129, in get_updates
    json_updates = apihelper.get_updates(self.token, offset, limit, timeout, allowed_updates)
  File "/usr/local/lib/python3.5/dist-packages/telebot/apihelper.py", line 175, in get_updates
    return _make_request(token, method_url, params=payload)
  File "/usr/local/lib/python3.5/dist-packages/telebot/apihelper.py", line 54, in _make_request
    timeout=(connect_timeout, read_timeout), proxies=proxy)
  File "/usr/local/lib/python3.5/dist-packages/requests/sessions.py", line 465, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python3.5/dist-packages/requests/sessions.py", line 573, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/requests/adapters.py", line 433, in send
    raise ReadTimeout(e, request=request)
requests.exceptions.ReadTimeout: HTTPSConnectionPool(host='api.telegram.org', port=443): Read timed out. (read timeout=30)


ООП стайл — это я так, на правах заметок на полях, не более. Я сам еще далеко «не настоящий сварщик».
Про падения

я ниже написал, повторюсь, попробуйте бота запускать с такими ключами

bot.polling(none_stop=False, interval=0, timeout=20)
Не помогло. Более того, процесс завершился сам. А с while он хотя бы перезапуститься.
During handling of the above exception, another exception occurred:

...

    r = adapter.send(request, **kwargs)
  File "/home/user/.local/lib/python3.6/site-packages/requests/adapters.py", line 521, in send
    raise ReadTimeout(e, request=request)
requests.exceptions.ReadTimeout: HTTPSConnectionPool(host='api.telegram.org', port=443): Read timed out. (read timeout=30)

Process finished with exit code 1
Страно. У меня боты не падают. Нужно выяснить что крашит бота.
После добавления в код переменной (global isRunning) для проверки состояния выполнения скрипта, на исполнении появляется ошибка «NameError: name 'isRunning' is not defined». Для чистоты эксперимента в итоге взял код целиком из статьи, но ошибка все равно возникает.
Что я упускаю?
Код в иделае бы получить. Но возможно что-то в этом роде.
isRunning = 0

def JustAFunction(arg):
    global isRunning
    isRunning = True
    #some code...
Код из примера в статье, цитирую ниже.
После «global isRunning» пробовал добавить «isRunning = 0» и «isRunning = False», ошибка ушла, но в работе бота остался бардак при повторном вызове команды /start
@bot.message_handler(commands=['start', 'go'])
def start_handler(message):
    global isRunning
    if not isRunning:
        chat_id = message.chat.id
        text = message.text
        msg = bot.send_message(chat_id, 'Сколько вам лет?')
        bot.register_next_step_handler(msg, askAge) #askSource
        isRunning = True
Странно. Возможно опечатался, и не перенёс isRunning вверх. Но, как по мне, удобней с добавлением ООП это всё делать.

Сам не могу сейчас проверить (чистая система, настраиваю), посмотрите мои доводы, может что-то поможет.
Нужно смотреть меняется ли сама переменная, сделайте вывод в этой же функции и глобальный.
@bot.message_handler(commands=['start', 'go'])
def start_handler(message):
    global isRunning
    if not isRunning:
        chat_id = message.chat.id
        text = message.text
        msg = bot.send_message(chat_id, 'Сколько вам лет?')
        bot.register_next_step_handler(msg, askAge) #askSource
        isRunning = True
        print(isRunning)
print(isRunning)

Но, как мне кажется, стоит перенести присвоение в верх функции, т.к., если я не ошибаюсь bot.register_next_step_handler заканчивает выполнение функции. Честно, не лазил по коде telebot-а, не могу быть уверен на 100%
P.S. Попробуй:
@bot.message_handler(commands=['start', 'go'])
def start_handler(message):
    global isRunning
    if not isRunning:
        isRunning = True
        chat_id = message.chat.id
        text = message.text
        msg = bot.send_message(chat_id, 'Сколько вам лет?')
        bot.register_next_step_handler(msg, askAge) #askSource
использую тоже вариант
bot.polling(none_stop=True, interval=0, timeout=10
но все равно происходит такая вот проблема
requests.exceptions.ReadTimeout: HTTPSConnectionPool(host='api.telegram.org', port=443): Read timed out. (read timeout=40)
Разработчики pytelegrambotapi рекомендуют использовать infinity_polling при таких проблемах.
if __name__ == '__main__':
     bot.infinity_polling()
Only those users with full accounts are able to leave comments. Log in, please.