Telegram бот без явного использования сервера

Всем привет!

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

Для этого можно воспользоваться так называемыми бессерверными вычислениями, например

https://cloud.google.com/functions или https://cloud.yandex.ru/services/functions.

Я буду использовать сервис от яндекса.


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


Делать я буду бота который озвучивает сообщения  при помощи сервиса от того же яндекса: https://cloud.yandex.ru/services/speechkit и бота который делает цветные фотографии из Ч/Б при помощи сервиса от mail.ru https://mcs.mail.ru/vision/, несмотря на то что основная цель данного сервиса - распознавание образов, этот сервис имеет функцию улучшения изображений https://mcs.mail.ru/help/ru_RU/manage-vision/vision-image-ap....


В первую очередь нам необходимо создать аккаунт в Yandex Cloud (или Google Cloud, если вдруг кто-то захочет повторить процесс там), подробно данную процедуру я описывать не буду, там ничего сложного.

После создания аккаунта заходим в консоль: https://console.cloud.yandex.ru и в левом меню переходим в пункт Cloud Functions, создаем функцию и придумываем ей имя.

После этого нам предлагают выбрать язык

Telegram бот без явного использования сервера Telegram, Бот, Программирование, Командная оболочка bash, Синтез речи, Колоризация, Видео, Длиннопост

Как видите, выбор большой. Я же не буду искать лёгкий путей и выберу Bash.


После этого мы попадаем в редактор.

Telegram бот без явного использования сервера Telegram, Бот, Программирование, Командная оболочка bash, Синтез речи, Колоризация, Видео, Длиннопост

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

Важно: После каждого изменения необходимо в правой части экрана нажимать на кнопку "Создать версию". В документации https://cloud.yandex.ru/docs/functions/ может почитать детальную информацию по каждому языку и посмотреть примеры.

Telegram бот без явного использования сервера Telegram, Бот, Программирование, Командная оболочка bash, Синтез речи, Колоризация, Видео, Длиннопост

Так выглядит моё окно редактора с полностью готовой функцией.

Код функции:

#!/bin/bash
# Ответ со статусом 200, оставляем из примера
echo '{
"statusCode": 200,
"body": {}
}'
# Запросы в функцию попадают через stdin, чтобы его получить достаточно вызвать команду `cat`
# Сервис, помимо тела запроса, присылает много дополнительной информации, а сам запрос лежит по ключу body
REQUEST=$(cat | jq -r '.body') # В переменную REQUEST достаём весь запрос от telegram
MESSAGE=$(echo $REQUEST | jq -r '.message') # Достаем структуру message
CHAT_ID=$(echo $MESSAGE | jq -r '.chat.id') # Внутри находим id чата для того чтобы отправить туда сообщение
TEXT=$(echo $MESSAGE | jq -r '.text') # Берём текст сообщения который будем озвучивать
# Cоздаём токен яндекса
# Для этого обязательно в настройках внизу должен быть подключен сервисный аккаунт
IAM_TOKEN=$(yc iam create-token)
FILE="/tmp/$(date +%s).ogg" # Названия временного файла, в виде текущей даты в секундах
# Отправляем текст на синтез и результат записываем во временный файл
curl -s -X POST -H "Authorization: Bearer ${IAM_TOKEN}" \
--data-urlencode "text=${TEXT}" \
-d "voice=alena&lang=ru-RU&folderId=${FOLDER_ID}" \
"https://tts.api.cloud.yandex.net/speech/v1/tts:synthesize" > $FILE
# Полученный файл отправляем в telegram
curl -s https://api.telegram.org/bot${BOT_API_KEY}/sendVoice -F "voice=@${FILE}" -F "chat_id=${CHAT_ID}" > /dev/null
# Удаляем файл
rm $FILE > /dev/null

В переменных окружения указан API ключ от бота который выдаётся при его создании.

И указан FOLDER_ID необходимый для работы синтеза речи, подробнее тут: https://cloud.yandex.ru/docs/speechkit/quickstart


Теперь осталось перейти в обзор функции сделать её публичной и скопировать ссылку для вебхука. Ссылку для вебхука я устанавливал командой:

curl https://api.telegram.org/bot<API_KEY>/setWebhook -F "url=https://functions.yandexcloud.net/d..."

<API_KEY> - заменить на токен бота, а в url= соответсвенно ваша ссылка.

Telegram бот без явного использования сервера Telegram, Бот, Программирование, Командная оболочка bash, Синтез речи, Колоризация, Видео, Длиннопост

На этом всё, бот должен работать. Проверяем:

Для создание второго бота проделываем всю ту же процедуру, но на этот раз, для использования сервиса обработки фотографий, нам необходимо зарегестрироваться ещё и на сайте https://mcs.mail.ru, и получить там токен для использования его в API.

Готовая функция  выглядит так:

Telegram бот без явного использования сервера Telegram, Бот, Программирование, Командная оболочка bash, Синтез речи, Колоризация, Видео, Длиннопост

Не обращайте внимания на подсветку кода, из-за сложного синтаксиса в 11 строке всё ломается. В переменных окружения как и в прошлый раз указан API ключ бота и API ключ от mail.ru.


Код целиком:

#!/bin/bash
echo '{
"statusCode": 200,
"body": {}
}'
REQUEST=$(cat | jq -r '.body')
MESSAGE=$(echo $REQUEST | jq -r '.message')
CHAT_ID=$(echo $MESSAGE | jq -r '.chat.id')
PHOTO=$(echo $MESSAGE | jq -r '(.photo | .[-1]) // (select(.document) | .document | select(.mime_type | contains("image"))) // false')
if [[ "$PHOTO" == "false" ]]; then
exit
fi
FILE_ID=$(echo $PHOTO | jq -r '.file_id')
FILE_PATH=$(curl -s https://api.telegram.org/bot${BOT_API_KEY}/getFile -F "file_id=${FILE_ID}" | jq -r '.result.file_path')
FILE="/tmp/$(date +%s)"
curl -s https://api.telegram.org/file/bot${BOT_API_KEY}/${FILE_PATH} > $FILE
COLORIZED_FILE="/tmp/$(date +%s)-colorized.jpg"
curl -s "https://smarty.mail.ru/api/v1/photo/improve?oauth_provider=m...{MCS_OAUTH_TOKEN}" \
-F file_0=@${FILE} -F meta='{"images":[{"name":"file_0"}], "mode":["improve"]}' |\
jq -r '.body.improve[0] | .colorized_improved // .colorized' | base64 --decode > $COLORIZED_FILE
curl -s \
https://api.telegram.org/bot${BOT_API_KEY}/sendPhoto \
-F "photo=@${COLORIZED_FILE}" \
-F "chat_id=${CHAT_ID}" > /dev/null
rm $FILE > /dev/null
rm $COLORIZED_FILE > /dev/null

Результат работы: 
Telegram бот без явного использования сервера Telegram, Бот, Программирование, Командная оболочка bash, Синтез речи, Колоризация, Видео, Длиннопост

Ещё пример колоризации:

Telegram бот без явного использования сервера Telegram, Бот, Программирование, Командная оболочка bash, Синтез речи, Колоризация, Видео, Длиннопост
Telegram бот без явного использования сервера Telegram, Бот, Программирование, Командная оболочка bash, Синтез речи, Колоризация, Видео, Длиннопост

Фотографии взяты из последних постов на пикабу по тегу черно-белое фото


P.S. Приведённый мной код хоть и работает, но представляет из себя определенную субстанция, так как в нём нет абсолютно никаких обработок ошибок и т.п. Единственное что есть - это проверка того что присланный файл это фотография, во втором боте.


P.S №2. Ссылки на ботов не оставляю так как использованные сервисы по синтезу речи и колоризации фотографий платные,  хоть и очень дешёвые. С тарифами можно ознакомится на соответствующих сайтах.  Кому любопытно попробовать синтез речи, на сайте https://cloud.yandex.ru/services/speechkit есть такая возможность.  А колоризация доступна на сайте: https://9may.mail.ru/restoration/ , но не уверен что используются одни и те же алогритмы.