Telegram боты для новичков


Краткий обзор 📖

Telegram имеет огромный интерфейс API, и разработка ботов в настоящее время растет очень быстро и пользуется большим спросом. Для новичков это хорошая возможность получить первую работу и хороший заработок. Возникает вопрос: как начать писать бота?

✔В этом посте вы найдете информацию о том:

  • какой язык выбрать;
  • какие фреймворки использовать;
  • как улучшить разработку бота;
  • что делать дальше.

Как выбрать язык? 🤔

Честно говоря, пишите на том языке, который вам ближе всего. Золотого стандарта не существует. Давайте разберемся, почему. Как вы знаете, чтобы получить данные из API, вам нужно написать скрипт, который делает HTTP-запросы. Например, получение данных из API GitHubбудет выглядеть следующим образом:

  • на Python (с пакетом requests)
>>> response = requests.get('https://api.github.com')
>>> response.content
b'{"current_user_url":"https://api.github.com/user","current_user_authorizations_html_url":"https://github.com/settings/connections/applications{/client_id}","authorizations_url":"https://api.github.com/authorizations","code_search_url":"https://api.github.com/search/code?q={query}{&page,per_page,sort,order}","commit_search_url":"https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}","emails_url":"https://api.github.com/user/emails","emojis_url":"https://api.github.com/emojis","events_url":"https://api.github.com/events","feeds_url":"https://api.github.com/feeds","followers_url":"https://api.github.com/user/followers","following_url":"https://api.github.com/user/following{/target}","gists_url":"https://api.github.com/gists{/gist_id}","hub_url":"https://api.github.com/hub","issue_search_url":"https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}","issues_url":"https://api.github.com/issues","keys_url":"https://api.github.com/user/keys","notifications_url":"https://api.github.com/notifications","organization_repositories_url":"https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}","organization_url":"https://api.github.com/orgs/{org}","public_gists_url":"https://api.github.com/gists/public","rate_limit_url":"https://api.github.com/rate_limit","repository_url":"https://api.github.com/repos/{owner}/{repo}","repository_search_url":"https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}","current_user_repositories_url":"https://api.github.com/user/repos{?type,page,per_page,sort}","starred_url":"https://api.github.com/user/starred{/owner}{/repo}","starred_gists_url":"https://api.github.com/gists/starred","team_url":"https://api.github.com/teams","user_url":"https://api.github.com/users/{user}","user_organizations_url":"https://api.github.com/user/orgs","user_repositories_url":"https://api.github.com/users/{user}/repos{?type,page,per_page,sort}","user_search_url":"https://api.github.com/search/users?q={query}{&page,per_page,sort,order}"}'
Войти в полноэкранный режим Выйти из полноэкранного режима
  • на JavaScript (с помощью метода fetch)
fetch('https://api.github.com')
  .then(response => response.json())
  .then(data => {
    console.log(data)
  })
  .catch(error => console.error(error))
// data from the response is:
{
  current_user_url: 'https://api.github.com/user',
  current_user_authorizations_html_url: 'https://github.com/settings/connections/applications{/client_id}',
  authorizations_url: 'https://api.github.com/authorizations',
  code_search_url: 'https://api.github.com/search/code?q={query}{&page,per_page,sort,order}',
  commit_search_url: 'https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}',
  emails_url: 'https://api.github.com/user/emails',
  emojis_url: 'https://api.github.com/emojis',
  events_url: 'https://api.github.com/events',
  feeds_url: 'https://api.github.com/feeds',
  followers_url: 'https://api.github.com/user/followers',
  following_url: 'https://api.github.com/user/following{/target}',
  gists_url: 'https://api.github.com/gists{/gist_id}',
  hub_url: 'https://api.github.com/hub',
  issue_search_url: 'https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}',
  issues_url: 'https://api.github.com/issues',
  keys_url: 'https://api.github.com/user/keys',
  label_search_url: 'https://api.github.com/search/labels?q={query}&repository_id={repository_id}{&page,per_page}',
  notifications_url: 'https://api.github.com/notifications',
  organization_url: 'https://api.github.com/orgs/{org}',
  organization_repositories_url: 'https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}',
  organization_teams_url: 'https://api.github.com/orgs/{org}/teams',
  public_gists_url: 'https://api.github.com/gists/public',
  rate_limit_url: 'https://api.github.com/rate_limit',
  repository_url: 'https://api.github.com/repos/{owner}/{repo}',
  repository_search_url: 'https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}',
  current_user_repositories_url: 'https://api.github.com/user/repos{?type,page,per_page,sort}',
  starred_url: 'https://api.github.com/user/starred{/owner}{/repo}',
  starred_gists_url: 'https://api.github.com/gists/starred',
  topic_search_url: 'https://api.github.com/search/topics?q={query}{&page,per_page}',
  user_url: 'https://api.github.com/users/{user}',
  user_organizations_url: 'https://api.github.com/user/orgs',
  user_repositories_url: 'https://api.github.com/users/{user}/repos{?type,page,per_page,sort}',
  user_search_url: 'https://api.github.com/search/users?q={query}{&page,per_page,sort,order}'
}
Войти в полноэкранный режим Выход из полноэкранного режима
  • в GoLang (с пакетом http)
package main

import (
    "net/http"
    "io/ioutil"
    "log"
)

func main() {
    res, err := http.Get("https://api.github.com")
    if err != nil {
      log.Fatal(err)
    }

    // read body
    body, err := ioutil.ReadAll(res.Body)
    res.Body.Close()
    if err != nil {
      log.Fatal(err)
    }

    if res.StatusCode != 200 {
      log.Fatal("Unexpected status code", res.StatusCode)
    }

    log.Printf("Body: %sn", body)
}
// body from the response is:
Body: {"current_user_url":"https://api.github.com/user","current_user_authorizations_html_url":"https://github.com/settings/connections/applications{/client_id}","authorizations_url":"https://api.github.com/authorizations","code_search_url":"https://api.github.com/search/code?q={query}{&page,per_page,sort,order}","commit_search_url":"https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}","emails_url":"https://api.github.com/user/emails","emojis_url":"https://api.github.com/emojis","events_url":"https://api.github.com/events","feeds_url":"https://api.github.com/feeds","followers_url":"https://api.github.com/user/followers","following_url":"https://api.github.com/user/following{/target}","gists_url":"https://api.github.com/gists{/gist_id}","hub_url":"https://api.github.com/hub","issue_search_url":"https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}","issues_url":"https://api.github.com/issues","keys_url":"https://api.github.com/user/keys","label_search_url":"https://api.github.com/search/labels?q={query}&repository_id={repository_id}{&page,per_page}","notifications_url":"https://api.github.com/notifications","organization_url":"https://api.github.com/orgs/{org}","organization_repositories_url":"https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}","organization_teams_url":"https://api.github.com/orgs/{org}/teams","public_gists_url":"https://api.github.com/gists/public","rate_limit_url":"https://api.github.com/rate_limit","repository_url":"https://api.github.com/repos/{owner}/{repo}","repository_search_url":"https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}","current_user_repositories_url":"https://api.github.com/user/repos{?type,page,per_page,sort}","starred_url":"https://api.github.com/user/starred{/owner}{/repo}","starred_gists_url":"https://api.github.com/gists/starred","topic_search_url":"https://api.github.com/search/topics?q={query}{&page,per_page}","user_url":"https://api.github.com/users/{user}","user_organizations_url":"https://api.github.com/user/orgs","user_repositories_url":"https://api.github.com/users/{user}/repos{?type,page,per_page,sort}","user_search_url":"https://api.github.com/search/users?q={query}{&page,per_page,sort,order}"}
Вход в полноэкранный режим Выход из полноэкранного режима

Как видно из результатов выполнения кода, разницы нет. Поэтому просто выбирайте язык, на котором вы пишете 😊.

Как выбрать фреймворк? 🏎️

Конечно, хорошо писать API-запросы самостоятельно. Это уменьшает зависимость от сторонних библиотек и позволяет больше контролировать поведение кода. Но когда таких методов больше двадцати, это уже увеличивает размер кода. Становится трудно управлять всей логикой. Именно здесь на помощь приходят сторонние библиотеки (фреймворки). После выбора языка вы можете рассмотреть варианты различных библиотек из списка здесь, на официальной странице Telegram. Для JavaScript я рекомендую использовать node-telegram-bot-api и telegraf. Для Python можно взять pyTelegramBotAPI и aiogram (настоятельно рекомендую).

Давайте начнем кодить первого бота 🐱💻.

Поскольку я в основном пишу код на Python, я предлагаю вам начать разработку ботов с помощью aiogram. Aiogram — это довольно простой и полностью асинхронный фреймворк для Telegram Bot API, написанный на Python 3.7 с использованием asyncio и aiohttp. Он поможет вам сделать ваших ботов быстрее и проще.

  1. Установите пакет. Это можно сделать с помощью pip. Также другие способы загрузки библиотеки перечислены здесь.

    pip install -U aiogram
    
  2. Давайте создадим структуру проекта. Нам нужны два python-файла: config.py и main.py. Это будет выглядеть следующим образом:

  3. Получение токена. Токен — это строка вида 110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw, которая необходима для авторизации бота и отправки запросов к Bot API. Держите свой токен в безопасности и храните его надежно, он может быть использован кем угодно для управления вашим ботом. Чтобы создать нового, вам нужно «поговорить» с @BotFather и получить токен там.

  4. Напишите начальный код. Прежде всего, скопируйте токен от БотФатера и вставьте его в config.py. Мы используем модуль os для работы с переменными окружения. Это хорошее решение, чтобы сохранить ваш токен в тайне. Пока вы находитесь на стадии разработки, токен может быть виден вам. Но на этапе производства удалите его.

    import os
    
    API_TOKEN = os.getenv('TOKEN', '5135575762:AAF9vytvlcuL-hruAHHMgZ3G2WvLpbZXMSI')
    

    В main.py нам нужно импортировать модуль logging, объекты aiogram и API_TOKEN из config.py.

    import logging
    
    from aiogram import Bot, Dispatcher, executor
    from aiogram.types import Message
    
    from config import API_TOKEN
    

    Теперь давайте инициализируем объекты бота и диспетчера:

    # Configure logging
    logging.basicConfig(level=logging.INFO)
    
    # Initialize bot and dispatcher
    bot = Bot(token=API_TOKEN)
    dp = Dispatcher(bot)
    

    Следующий шаг: взаимодействие с ботами начинается с одной команды. Мы можем обрабатывать команды от пользователей следующим образом:

    @dp.message_handler(commands=['start', 'help'])
    async def handle_start(message: Message) -> Message:
        return await message.reply("Hi!nI'm TestBot!")
    

    Также добавим еще один обработчик для перехвата всех текстовых сообщений:

    @dp.message_handler()
    async def echo(message: Message) -> Message:
        return await message.answer(message.text)
    

    Последний шаг: запуск длинного опроса. Эта команда запустит нашего бота для перехвата всех обновлений от Telegram API каждую секунду:

    if __name__ == '__main__':
        executor.start_polling(dp, skip_updates=True)
    
  5. В итоге у нас есть два файла:

import os

API_TOKEN = os.getenv('TOKEN', '5135575762:AAF9vytvlcuL-hruAHHMgZ3G2WvLpbZXMSI')
Войти в полноэкранный режим Выход из полноэкранного режима
import logging

from aiogram import Bot, Dispatcher, executor
from aiogram.types import Message

from config import API_TOKEN


# Configure logging
logging.basicConfig(level=logging.INFO)

# Initialize bot and dispatcher
bot = Bot(token=API_TOKEN)
dp = Dispatcher(bot)


@dp.message_handler(commands=['start', 'help'])
async def handle_start(message: Message) -> Message:
    return await message.reply("Hi!nI'm TestBot!")


@dp.message_handler()
async def echo(message: Message) -> Message:
    return await message.answer(message.text)


if __name__ == '__main__':
    executor.start_polling(dp, skip_updates=True)
Войти в полноэкранный режим Выход из полноэкранного режима

Что мы получили в итоге? 🤩

Запустим нашего бота с помощью команды в терминале:

python main.py
Enter fullscreen mode Выйти из полноэкранного режима

В консоли вы увидите что-то вроде этого:

INFO:aiogram:Bot: testbot [@testmezgoodlebot]
WARNING:aiogram:Updates were skipped successfully.
INFO:aiogram.dispatcher.dispatcher:Start polling.
Войти в полноэкранный режим Выйти из полноэкранного режима

Теперь давайте перейдем в Telegram и начнем общаться с ботом.

Чтобы начать чат с ботом, перейдите по ссылке, предоставленной BotFather.

Надеюсь, у вас будет такой же результат, как у меня 😺.

Поздравляю! Вы написали своего первого бота! ✨

Да, сейчас это простой эхо-бот, но в следующих постах мы рассмотрим все аспекты разработки ботов. Тогда вы уже сможете создавать ботов любой сложности. Так что ждите моих следующих новых постов.

Ссылки:

  • Код бота на GitHub

Спасибо за прочтение! ❤️ ❤️ ❤️

Оцените статью
devanswers.ru
Добавить комментарий