How to create a Telegram bot with Swift using Vapor

Dima Biserov
7 min readJun 17, 2021

--

В этой статье я расскажу как сделать Telegram бота на свифте + Vapor

Для кого?

Для iOS разработчиков, которые не хотят учить другой язык, что бы сделать элементарный back

Disclaimer: я не сеньор-помидор, пишу для себя и как умею/хочу, если что-то вам не нравится в коде/тексте, просто закройте вкладку плз

Стек:

  • Vapor — единственный веб фреймворк на свифте(SwiftNIO), который активно поддерживается комьюнити и постоянно развивается, с кучей готовых решений из коробки, типа сокетов, Sign with Apple, базами данных ит.п.
  • https://github.com/nerzh/telegram-vapor-bot — обертка над Telegram bot api, работает асинхронно, поддерживает лонгпол и вебхук, автор отвечает и прислушивается к юзерам, быстро фиксит баги, в общем поставьте звездочку
  • Digital Ocean — тут мы будем хостить нашего бота, подойдет и любой другой сервис, где можно установить Ubuntu, у меня все проекты на DO уже давно, мне удобно и привычно

Начнем:

Устанавливаем Vapor. Для этого пишем в терминале

brew install vapor

(Если у вас почему-то до сих пор не установлен brew — https://brew.sh/index_ru)

После чего так же в терминале в нужной нам директории пишем

vapor new tgbot

Вместо tgbot, естественно, можете написать что хотите

Fluent — удобный ORM фреймворк, т.к. в этой статье базу данных мы использовать не будем, поэтому пишем “n”
Leaf — фреймворк, который позволяет делать фронт (веб-страницы), так же пишем “n”
Должны увидеть следующее. Пишем cd tgbot && open . что бы открыть директорию проекта
Кликаем на Package.swift
После того как все зависимости загрузятся, запускаем проект

В браузере переходим на http://127.0.0.1:8080/

Если всё ок(а как иначе) должны увидеть:

It works!

Переходим в файл configure.swift и добавляем туда 2 строчки:

app.http.server.configuration.hostname = “0.0.0.0”app.http.server.configuration.port = 80

Меняем порт на 80, а так же адрес на 0.0.0.0 - это как 127.0.0.1

Кстати, если проект падает при старте с такой ошибкой:

Fatal error: Error raised at top level: bind(descriptor:ptr:bytes:): Address already in use (errno: 48)

Напишите в терминале:

killall Run

В браузере теперь можно перейти просто на http://127.0.0.1/

В Package.swift добавляем нашу библиотеку для Telegram Bot Api

.package(name: “telegram-vapor-bot”, url: “https://github.com/nerzh/telegram-vapor-bot", .upToNextMajor(from: “1.0.2”)) .product(name: "telegram-vapor-bot", package: "telegram-vapor-bot")

Далее создаем файл DefaultBotHandlers.swift, как предлагает автор библиотеки, и добавляем туда код, опять же из https://github.com/nerzh/telegram-vapor-bot

Что здесь происходит:

Мы добавляем 2 хендлера, то есть на что будет реагировать наш бот, и что будет отвечать. Первый хендлер дефолтный, то есть через него проходит абсолютно всё(текст, картинки, видео ит.д.), в ответ он пришлет Success. Так же мы видим строку

filters: (.all && !.command.names(["/ping"])

Это значит что есть исключение, в виде команды /ping

Как раз второй хендлер отвечает только на /ping, в ответ он пришлет pong

К хендлерам мы вернемся позже, сейчас настроим бота, переходим в файл configure.swift

let tgApi: String = "XXXXXXXXXX:YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY"let connection: TGConnectionPrtcl = TGLongPollingConnection()TGBot.configure(connection: connection, botId: tgApi, vaporClient: app.client)try TGBot.shared.start()TGBot.log.logLevel = .errorDefaultBotHandlers.addHandlers(app: app, bot: TGBot.shared)

Вместо ХХХХ… вписываем токен нашего бота, который получаем у BotFather, пишем ему /newbot, заполняем имя ит.д. После чего вставляем полученный токен

На этом настройка бота через longpoll окончена, можно подключить и через вебхук, но это чуть сложнее, возможно в следующей заметке покажу (про разницу можете почитать здесь)

Теперь запускаем проект и пишем нашему боту что угодно:

Если же мы напишем /ping, то сработает наш второй хендлер:

Вот и всё, просто же?) Дальше нужно углубляться — всё зависит от ваших нужд, я же покажу несколько простых примеров:

  1. Допустим нам нужно получить прямую ссылку на изображение, чтобы дальше ее залить на наш(или не наш)сервер и использовать в iOS приложении

Мы пытаемся получить путь до нашего изображения(Саня привет), после чего бот пришлет прямую ссылку на него в максимальном качестве(телеграм отдает массив с разными размерами, последний(last) самый большой, первый(first) маленький

Рекомендую почитать доки Telegram Bot API, что бы понимать что можно сделать в принципе, например, есть метод, который может переслать сообщение в нужный вам канал, как буд-то это вы запостили, пересыла видно не будет. Для этого нужно в нужный канал добавить админом нашего бота после чего воспользоваться методом

bot.forwardMessage

2. Получаем случайный факт о кошках через бесплатное Api, и отправляем его в ответ

Вместо привычной URLSession у вапора есть свой http client, кстати далеко не все библиотеки, которые вы используете для iOS будут работать в Linux, например Alomofire не работает, но они обещали сделать поддержку

Сценарии и логика могут быть любыми, дальше уже google в руки и вперед, решать именно ваши задачи

Теперь перейдем к процессу деплоя на DO

Для этого создадим репозиторий на гитхабе, как это сделать я писал ранее

Заходим на https://www.digitalocean.com/

Создаем новый проект
Создаем Droplet
Самый минимальный
Пароль сохраните)
Дроплет готов, копируем IP адрес

Заходим на наш дроплет через SSH

ssh root@ip_дроплета
далее пишем yes
и вводим пароль, который указали при создании

Теперь будем устанавливать на сервер необходимые пакеты:

sudo apt-get update
потом
sudo apt-get install clang libicu-dev libatomic1 build-essential pkg-config
потом
sudo apt-get install libssl-dev
Так это выглядит)

Далее качаем и устанавливаем Swift

wget https://swift.org/builds/swift-5.4.1-release/ubuntu1804/swift-5.4.1-RELEASE/swift-5.4.1-RELEASE-ubuntu18.04.tar.gz
потом
tar xzf - < swift-5.4.1-RELEASE-ubuntu18.04.tar.gz*
потом
sudo mkdir /swift
потом
sudo mv swift-5.4.1-RELEASE-ubuntu18.04 /swift/5.4.1
потом
sudo ln -s /swift/5.4.1/usr/bin/swift /usr/bin/swift
и пишем для проверки
swift --version
Качаем Swift 😼
Так должно быть в итоге

Теперь немного сахара для удобства — Vapor Toolbox

git clone https://github.com/vapor/toolbox.git
потом
cd toolbox
потом
swift build -c release --disable-sandbox --enable-test-discovery
потом
mv .build/release/vapor /usr/local/bin
Ждём
Должно быть так)

Далее пишем

git clone https://github.com/dimabiserov/vaporTGBotExample.gitпуть до вашего репозитория, если он приватный то попросит логин и пароль от гитхаба, в моем случае он публичный
Переходим в папку с проектом
Пишем vapor build
Ждём минут 5 пока все зависимости загрузятся

после пишем

vapor run

Готово, бот работает!

Теперь что бы он работал всегда, даже когда мы закроем терминал, заходим на DO и нажимаем на console:

В открывшемся окне нужно залогиниться,

login: root, password: который выше сохраняли

Далее переходим в папку с проектом и пишем vapor run

Теперь бот будет работать всегда

Чтобы отключить нашего бота, зайдите снова в console DO и нажмите на клавиатуре control + c

Чтобы обновить код, нужно его закомитить в гит, после чего зайти в консоль DO-в папку проекта и написать:

 git pull && vapor build && vapor run

На этом всё, теперь ты фуллстак iOS Developer 🤡

Если наберем просмотров/лайков, напишу статью как сделать примитивный back на вапоре с базой данных, ендпоинтами, своим доменом ит.д.

Спасибо, что прочёл эту немаленькую статью, постарался расписать максимально подробно, чтобы и новички смогли)

Скачать проект c Github

Полезные ссылки:

Чат Server Side Swift Developer, где всегда помогут и подскажут по Вапору

Мой Telegram канал со Swift статьями

Чат Indie iOS Разработчиков

--

--

Dima Biserov
Dima Biserov

Written by Dima Biserov

Ни в коем случае не претендую на супер-пупер разработчика, здесь просто сборник полезной информации для меня и знакомых, если она была полезна и вам — its good

Responses (1)