Телеграм-бот — это виртуальный пользователь Telegram, с которым можно общаться как с живым человеком. Перед нами – очень интересная задача. Мы должны создать “умного” бота, который умеет:
  • вести диалог
  • практиковаться в свиданиях
  • генерировать яркие и интересные описания для сайтов знакомств
  • помогать при переписке на сайте знакомств
Чтобы бот этому всему научился и выглядел умным, мы прикрутим к нему ChatGPT.

1. Предварительная подготовка к работе

Прежде чем начинать программировать, нам нужно подготовить рабочее место. Для этого нам понадобится:
  • cам Python SDK (Python Interpreter)
  • приложение для написания и запуска программ, PyCharm Community Edition
  • шаблон нашего проекта
  • Telegram: желательно для удобства загрузить десктопную версию, по крайней мере для первой лекции

2. Установка PyCharm и загрузка проекта

Загрузить бесплатную версию PyCharm Community Edition можно с сайта разработчика для Windows, MacOS или Linux. Шаблон проекта желательно разархивировать и запомнить, где лежит папка. Если уже загружали, найдите, где именно она хранится. Откройте PyCharm. Если это первый запуск, скорее всего, вы увидите окно с предложением создать проект, открыть его либо загрузить из системы контроля версий. Предварительная подготовка и конспект к занятию №1 - 1Если вы уже работали в PyCharm и у вас открыт другой проект, жмите на Windows/Linux File - Open, MacOS PyCharm – Open. Предварительная подготовка и конспект к занятию №1 - 2Далее в обоих случаях отыскиваем папку TinderBolt там, где вы её сохранили. И снова жмем Open. Предварительная подготовка и конспект к занятию №1 - 3Перед вами откроется шаблон проекта. Слева вы увидите дерево проекта, справа будет показан активный файл. Дерево проекта состоит из различных директорий и файлов. Нужные нам файлы с Python-кодом лежат по сразу в папке TinderBolt: Предварительная подготовка и конспект к занятию №1 - 4Теперь вам нужно указать интерпретатор Python для вашего проекта – просто кликните на ссылке сверху: Предварительная подготовка и конспект к занятию №1 - 5Если все прошло успешно, вы увидите, как первая строчка кода подчеркнута красным: Предварительная подготовка и конспект к занятию №1 - 6Если вы никогда не программировали, вероятно, структура проекта, да и сам код в файлах покажется вам чем-то непонятным и слишком сложным. На самом деле понимание всего этого просто требует практики. Пока что мы только собираемся учиться на Python Junior, а “джуны” обычно не создают структуру проекта, а лишь пишут отдельные его части. Так что в течение следующих занятий мы с вами сымитируем работу начинающего программиста на проекте, шаблон которого создал какой-то senior или архитектор.

3. Немного теории перед первой лекцией

Python-программа или Python-проект

В общем смысле программа – это последовательность команд, которые понимает и выполняет компьютер. Команды эти пишет программист, в нашем случае – на языке Python. Чтобы программистам было проще работать, у Python-проекта есть определенная структура. На физическом уровне это файлы и папки, расположенные в определенной иерархии, как вы могли видеть в открытом проекте TinderBolt. Основное количество файлов в типичном Python-проекте – это файлы с Python-кодом, но также есть файлы с ресурсами (например, текстовыми файлами или графическими аватарками), файлы с настройками и так далее. В простейшем случае программа может состоять из одного файла с Python-кодом. Python, установленный на компьютер, сможет перевести этот код на понятный компьютеру язык (откомпилировать), а затем и запустить программу.

Простейшая программа

Пример такой простейшей программы:

print("Это моя программа") 
Эта программы выведет на экран текст:

Это моя программа 
Тут все почти очевидно, но на всякий случай проговорю: чтобы вывести какой-то текст на экран нужно: а) обрамить его в двойные кавычки и b) написать команду print() – все как в примере выше. Переменные на Python создаются в момент присваивания им значений – специально объявлять переменные не нужно. Пример:

name = "Alexander" 
age = 35 
city = "Это моя программа" 

Условный оператор

Условие (if else) выглядит почти как во всех языках программирования:

if name == "Alexander": 
    print("Hi Alexander, The Great") 
else: 
    print("Hi ", name) 
После условия и после else нужно ставить двоеточие. Круглые скобки для условия не нужны.

Блок кода

Важно! Несколько команд объединяются в блок кода не с помощью фигурных скобок {}, с просто сдвигом на 4 пробела вправо. Это позволяет коду на Python быть очень компактным, но обязывает вас следить за пробелами – лишние пробелы где попало ставить нельзя.

Комментарии

Комментарии начинаются с символа # и идут до конца строки. Примеры:

# образец условия if else  
if name == "Alexander":  #проверяем, что переменная равна  Alexander 
    print("Hi Alexander, The Great") 
else: 
    print("Hi ", name) 
Комментарии можно оставлять для коллег, которые будут читать ваш код или же для вас, чтобы не забыть чего. Суть в том, что в программе комментарии не выполняются: они здесь только чтобы что-то пояснить и в них можно писать что угодно. Но желательно, чтобы они несли какой-то смысл.

Функции

Функции объявляются с помощью ключевого слова def. Пример:

def sum (a, b): 
    return a+b 

Сравнение

Оператор = это не равенство, а присвоение.

name = "Alexander" 
age = 35 
city = "Это моя программа" 
Если вы хотите сравнить переменные, то нужно использовать двойной символ равно – «==».

4. Дополнение и краткий конспект к занятию №1

Любой Python-проект состоит из каких-то файлов и папок. Это могут быть файлы с Python-кодом, файлы с настройками, ресурсы для работы нашей программы. Например, картинки, которые она будет загружать или текстовые файлы, информацию из которых она будет тем или иным образом считывать. Давайте поговорим о структуре нашего проекта, а точнее – о самых главных его файлах. Файлы с кодом лежат прямо в папке TinderBolt: Предварительная подготовка и конспект к занятию №1 - 7В папке resources лежат картинки, текстовые сообщения и промпты для chatGPT. Предварительная подготовка и конспект к занятию №1 - 8Мы будем писать весь код в файле bot.py. Прямо на месте комментария «тут будем писать наш код» Предварительная подготовка и конспект к занятию №1 - 9Описание файлов:
  • bot.py — содержит всю логику нашего бота, присылает сообщения пользователю, получат сообщения от пользователя и обрабатывает введенные им команды и нажатия кнопок.
  • gpt.py – содержит служебный класс ChatGPTService, который позволяет упростить работу нашего бота с ChatGPT и сделать обращение к нему более простым и понятным.
  • util.py – содержит несколько служебных функций, которые позволяют не писать слишком длинную логику во время марафона там, где это не нужно.
Весь код в данных файлах снабжён комментариями, так что вы можете разобраться, как он работает, если у вас будет желание. Это полезно. API — это аббревиатура от "Application Programming Interface", что переводится как "интерфейс программирования приложений". Это набор функций для общения программ между собой. То есть API позволяет программам общаться друг с другом, а программистам – использовать возможности других программ в своих.

Шаг 1. Установка библиотек

Если вверху файла bot.py у вас импорт библиотек подсвечивается красным, значит у вас все хорошо. Но библиотеки все-таки придется скачать. Для этого вам нужно открыть Терминал: Предварительная подготовка и конспект к занятию №1 - 10И выполнить в нем две команды:

pip install python-telegram-bot 
И

pip install openai 
Если все прошло хорошо, то первая строчка файла bot.py перестанет светиться красным, и вы можете использовать ваши библиотеки.

Шаг 2. Регистрация бота и получение токена

На 9-й строчке нашего файла bot.py есть такой код:

app = ApplicationBuilder().token("telegram-token").build() 
Вот этот telegram-token нам нужно заменить на реальный Telegram Token. Чтобы нам получить значение токена, нам нужно зарегистрировать нашего бота на сервере Telegram:
  1. Заходим в Telegram.
  2. В поиске ищем бота по имени BotFather (этакий папа всех ботов).
  3. Пишем команду /start
  4. Жмем на /newbot Предварительная подготовка и конспект к занятию №1 - 11
  5. Выбираем имя для нашего бота.
  6. Теперь выбираем имя пользователя (username) для своего бота. Имя должно быть уникальным и заканчиваться на «bot».
  7. Если все ок, бот нам напишет приветственное сообщение, в котором будет наше имя пользователя, а в качестве токена можно использовать выданный ботом токен для HTTP API, а также ссылка на нашего бота. Предварительная подготовка и конспект к занятию №1 - 12
  8. Теперь возвращаемся в PyCharm, в файл bot.py ввставляем наш токен между двойных кавычек:
    
    app = ApplicationBuilder().token("809898698769:jafafdlkdjkjjfkdjd77yh").build() 
    

Шаг 3. Запуск бота

Наш бот пока ничего не умеет, но он уже работает. Чтобы запустить программу в PyCharm, нужно щелкнуть по зеленой стрелочке справа сверху окна ▶ (при этом в самом окне желательно открыть файл bot.py). Предварительная подготовка и конспект к занятию №1 - 13Либо же кликните по имени файла bot.py в дереве проектов правой кнопкой мыши и найдите там такую же стрелочку с надписью Run “bot”. Предварительная подготовка и конспект к занятию №1 - 14Так запускается любая программа на Python. Мы же запускаем на исполнение все команды файла bot.py. Теперь, когда программа запущена, мы можем возвращаться в Telegram: наш бот работает. Кликаем по ссылке, полученной в приветственном сообщении, и мы у бота в гостях. Мы можем нажать на кнопку Start или написать /start (это кнопка начала общения с ботом). Правда, общаться он пока еще не умеет, поэтому ничего не произойдет. Поэтому просто остановим программу и перейдем к написанию кода. Как мы общаемся с ботом или живым человеком? Мы получаем его сообщения и пишем свои. Чаще всего это текстовые сообщения, но также это могут быть картинки, а в случае бота — еще и команды. Как мы уже писали выше, для общения программ между собой есть специальные пакеты API. Разумеется, программисты уже написали API для Телеграм-ботов на Python, и наш ментор их использовал, чтобы создать методы для общения именно с нашим ботом. В принципе, это могли сделать и мы, но тогда наша работа усложнилась бы в разы, а мы только начинаем учиться, нам и так сложно.

Шаг 4. Учим бота отвечать

Сделать так, чтобы бот нам что-то написал несложно. Для начала нам нужно будет написать асинхронную функцию hello. Именно в том месте, где был комментарий «тут будем писать наш код». Выглядеть ее первая версия может примерно так:

async def hello(update, context): 
    await send_text(update, context, "Привет!") 
Эта функция на любое сообщение пользователя будет писать ему «Привет!» Но теперь эту функцию нужно еще связать с приложением нашего бота. Для этого после строчки с токеном нужно написать:

app.add_handler(MessageHandler(filters.TEXT, hello)) 
С помощью этой команды мы указываем приложению нашего бота (app), что ему нужно добавить в свою логику еще один обработчик сообщений от пользователя add_handler(MessageHandler(filters.TEXT, hello)) Итоговый код будет выглядеть вот так:

async def hello(update, context): 
    await send_text(update, context, "Привет!") 

app = ApplicationBuilder().token("0980989809:fjkdfjlsdjfisdm").build() 
app.add_handler(MessageHandler(filters.TEXT, hello)) 
app.run_polling() 

Шаг 5. Учим бота получать сообщения от пользователя

Чтобы в функции hello получить сообщение, которое пользователь написал боту, нужно написать использовать объект update и написать код типа:

user_message = update.message.text 
Новый вариант функции hello() может выглядеть так:

async def hello(update, context): 
    await send_text(update, context, "Привет!") 
    await send_text(update, context, "Ты написал " + update.message.text) 
Важно! Слова async и await обязательно использовать, т.к. библиотека python-telegram-bot полностью асинхронная. Поэтому мы должны тоже писать асинхронные функции – и использовать ключевое слово async перед объявлением наших функций. Перед вызовом же асинхронной функции нужно обязательно писать ключевое слово await.

Шаг 6. Отправляем сообщение с кнопками

Чтобы отправить пользователю сообщение с кнопками, можно использовать функцию send_text_buttons. В нее нужно передать:
  • обязательные параметры update, context,
  • текст, который вы хотите вывести пользователю
  • список кнопок в фигурных скобках.
Каждая кнопка задается двумя словами через двоеточие:
  • уникальное имя кнопки
  • текст на кнопке
Пример:

async def hello(update, context): 
    await send_text(update, context, "Привет!") 
    await send_text_buttons(update, context, "Выберите режим работы", {  # Текст перед кнопкой 
        "btn_start": " Старт ", # Текст и команда кнопки "Старт" 
        "btn_stop": " Стоп "  # Текст и команда кнопки "Стоп" 
    }) 
Теперь, если мы запустим бота, у нас отобразится две кнопки: Предварительная подготовка и конспект к занятию №1 - 15Если вы хотите, чтобы ваша программа что-то делала при нажатии на кнопки, то вам нужно создать еще одну асинхронную функцию и связать ее с ботом. Пример:

async def hello_button(update, context): 
    query = update.callback_query.data   #код кнопки 
    await update.callback_query.answer() #помечаем что обработали нажатие на кнопку 
    await send_text(update, context, "Вы нажали на кнопку " + query) 
Связать функцию с ботом можно добавив еще один обработчик:

app = ApplicationBuilder().token("0980989809:fjkdfjlsdjfisdm").build() 
app.add_handler(MessageHandler(filters.TEXT, hello)) 
app.add_handler(CallbackQueryHandler(hello_button)) 
app.run_polling() 

Шаг 7. Учим бота отправлять картинки

Наконец, отправлять в чат картинки можно с помощью метода send_photo(). Пример:

async def hello(update, context): 
    await send_photo(update, context, "main") 
Ему можно отправлять картинки по имени(ключу), а сами картинки лежат в папке resources\images в нашем проекте.

Шаг 8. Работа с командами Telegram

Команды в Telegram начинаются с / косой черты. Собственно, с одной из них мы уже работали, это команда /start. Давайте попробуем заставить нашу программу отреагировать на команду /start. Например, если пользователь прислал команду старт, то ему в ответ прислать картинку. Для этого нам нужно создать асинхронную функцию start(), выглядеть ее код может примерно так:

async def start(update, context): 
    await send_photo(update, context, "main") 
Но теперь и эту функцию нужно связать с нашим ботом, чтобы она вызвалась, когда пользователь введет команду start. Сделать это довольно просто: нужно добавить еще один handler:

app.add_handler(CommandHandler("start", start)) 
Важно! Каждая команда является в первую очередь просто сообщением, а потом уже командой: команда – это сообщение, которое начинается с символа /. Если вы не хотите, чтобы функция hello обрабатывала ваши команды как сообщения, то нужно отключить ей обработку команд. Сделать это можно кодом типа такого:

app = ApplicationBuilder().token("0980989809:fjkdfjlsdjfisdm").build() 
app.add_handler(CommandHandler("start", start)) 

app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, hello)) # отключаем команды 

app.add_handler(CallbackQueryHandler(hello_button)) 
app.run_polling() 
Что нужно сделать перед и во время первой лекции
  1. Установить все необходимое для работы.
  2. Послушать лекцию и повторить все за ментором.
По итогу у нас должен быть бот, который:
  1. имеет имя, название и ссылку на себя
  2. запускается
  3. считывает сообщение пользователя
  4. отсылает картинку и описание своей работы, если пользователь послал ему команду /start
  5. отсылает простое текстовое сообщение
Не все может быть понятно, но важно не запутаться и все сделать, повторить за ментором. Некоторые моменты станут понятны позднее.

Подсказки к выполнению задания №1

Проверка корректности кода и обновление изменений в проекте

Чтобы увидеть изменения, которые ты вносишь непосредственно в работе Телеграм-бота, не забудь после написания своего кода применить все изменения (перезапустить программу) в PyCharm. Для этого нужно в нижней горизонтальной панели нажать на зеленую круглую стрелку: Предварительная подготовка и конспект к занятию №1 - 16Помни о том, что твои названия переменных, функций и кнопок должны быть читабельными: по названию должно быть понятно, что они делают или для чего предназначены.

Форматирование текста

Чтобы выделить в боте текст курсивом, нужно в начале и в конце необходимого фрагмента добавить нижние подчеркивания: _текст_ Чтобы выделить текст жирным, нужно в начале и в конце необходимого фрагмента добавить звездочки: *текст*