Как стать автором
Обновить

Комментарии 46

Не совсем понимаю, почему такое ограничение на вызов лишь одного sendMessage. Разве нельзя вызвать sendPhoto, к примеру?

Да, вы правы, призывал читать документацию, и сам не дочитал.
Можно — @YandexServerless2Bot
Т.е. Яндекс не блокирует доступ к телеграм Api?

У моего VPS российский ip, api телеграма работает.

Да, не блокирует.
все эти реализации при получении запроса инициируют post до сервера api telegram, что в условиях крупного Российского хостера невыполнимо


Во-первых, провайдеры хостинга, датацентры и так далее не являются операторами связи. Они ничего не блокируют из списка РКН в своих сетях. В основном. Во всяком случае, если они что-то блокируют, это исключительно их инициатива, по закону они не обязаны. У меня есть прокси Telegram, поднятые на российских VPS, до сих пор работают.
Во-вторых, если webhook с серверов Telegram приходит, то очевидно, что и API так же доступно. Я еще не видел блокировок только в одну сторону.

Но за описанную возможность сразу отправить ответ, не дергая API телеги отдельным запросом спасибо, не знал.
Проверил, вы правы, добавил UPD в конце статьи. Мои хостеры в своё время блокировали telegram.org и всё что рядом, так что привык воспринимать это как данность.
Есть провайдеры хостинга, которые подключены к провайдерам интернета, причём последние блокируют доступ к Телеграм.

Без "Есть".


Пока нет ) Предполагаю что даже до стоимости проезда в метро не дойдёт.

Challenge accepted :D (нет)
Но думаю, могут найтись, "доброжелатели"..


При том, что можно написать просто бота, который будет дергать Вашего нное количество раз.
За статью спасибо.

Можно же добпвить простую проверку, чтоюы не отвечать юзеру более N раз в час. Тонда злоумышленнику нужно регистрировать много аккаунтов в телеграме уже.

Проверка будет в скрипте, соответственно вызываться он так или иначе будет.

Проверка будет занимать меньше времени чем работа самого скрипта.

Т.е. Вы считаете, что регистрация айди пользователя и времени/частоты его запросов, а также последующая проверка, будут работать быстрее чем ответ "Привет Хабр"?

Вот в этом случае уже действительно регистрация id не осмысленна.
А в случае если бот имеет какую-то полезную нагрузку — регистрация id пользователя и подсчет его активности уже будет иметь смысл.

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

да. Как вы в Serverless будете это помнить?
Так эта Лямбда же может без проблем обращаться, например, к вполне себе «serverfull» Redis'у автора. Помнить — не проблема, в общем.
и вишенкой на торте — SLA 99,9

Не такая уж это и вишенка.

Допустим простой 8ч 45м 57с в год.
Полный рабочий день включая обеденный перерыв, другими словами.

Вы можете гарантировать больше?

Вы можете гарантировать больше?


Несведующему человеку указанная 99,9% может показаться высокой, но это не так.

К примеру, при определенном масштабе деятельности, когда можно выделить круглосуточных админов с их дублированием (разумеется не под один этот сервер). И даже дешевле, без облака, но ручками — да. При нормальной организации репликации — сменить хостера при сбое дело нескольких минут.

Далее, для достижения уровня доступности 99,95% вам понадобится просто построить кластер active-passive.

Если вы хотите перешагнуть за 99,982% (уровень доступности в дата-центрах Tier III), вам нужно строить систему, распределенную по нескольким ЦОД.

Еще раз:

Цифры SLA намного более высокой доступности, чем 99,9% — вполне реальны в нашем мире.

При нормальной организации репликации

:-D

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

:-DD

просто построить кластер active-passive

:-DDD

Это запредельный уровень допущений. То есть наверняка есть люди, которые могут это сделать и есть конторы, которые могут дать на организацию всего этого время. Но это мизерная часть от всех людей и всех контор.

О чем мы спорим? Яндекс заявляет 99.9. ну, ок. Хорошо.
В принципе, с этим можно жить.
А дальше — как я пишу ниже — дьявол в деталях. Я просто внимталеьно смотрел договора (речь не про Яндекс как таковой — возможно, что там все ок ) И все там не так просто как "мы гарантируем". Ну, положим не выполнил поставщик / провайдер / облако свои гарантии — ну, заплатит он вам штраф. Или даст бесплатный бонус. И ЧТО? Репутацию и клиентов это вам не вернёт.

На самом деле даже 99.9 никто не гарантирует. Если подумать.
Читайте договор мелким шрифтом. И скорее всего там будет, что доступность платформы (т.е. веб-панкели и АПИ), а сами сервисы… Ну, не летит трафик в вашу лямбду. И что? Это у вас провайдер фиговый — к нему и идите )

Но база то все равно должна где то лежать, что бы к ней дотянуться из этой функции? Это уже контейнер, проще на одном контейнере все поднять, если он все равно нужен. Тем более для пет-проекта
Это уже зависит от архитектуры приложения. Одному из моих ботов хватит json файлика лежащего рядом, который будет раз в пол года меняться. Другому — папки с иногда добавляющимися файлами. Третий ходит по внешним api.
Если понадобится база — я скорее буду смотреть на cloud managed решения, тот же MySQL в Яндексе будет стоить 508₽ в месяц, и обслуживать несколько проектов. С бэкапами, администрированием и тем-же SLA. В Амазоне, кстати, примерно столько же RDS стоит.
Но да, безусловно облако не панацея и есть множество случаев когда или надо переделывать под него архитектуру чтобы не разориться, или сразу завести всё на бюджетной vds за 1,5$ в месяц.
Странно что бесплатного лимита нет. У меня давно крутится пара домашних ботов в Google App Engine, и вроде совсем бесплатно.
Минус в том что решение в облаках раз в пару лет обычно нужно чуть чуть переделывать. Потому что облачное окружение меняется. Могут исключить встроенную библиотеку например.
Лимита нет, но есть бесплатный тестовый период cloud.yandex.ru/docs/free-trial

А еще можете посмотреть на azure functions. Там есть большое кол-во триггеров и бесплатные первые 4 млн вызовов в месяц)

Я так понимаю, что дьявол в деталях. И хоть сами вызовы ничего не стоят, но их роутинг через api gateway или что там у ажура может влететь в копеечку. Как прокомментируете ?

В отличии от aws там api routing бесплатен. :) в копеечку вам может влететь работа с бд. Или очень долгое выполнение функции.

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

Вместо того, чтобы следить за обновлением пакетов на настоящей ОС в Виртуальной машине, заниматься настройкой политик безопасности и файрволла — вы загружаете программу на сервер, и она работает.

Звучит очень двояко. А если я не хочу использовать последнюю версию? А если я вообще питонщик и у меня завязка на конкретные версии модулей?
И фраза, что загружаешь и оно работает слишком… Пафосная. Скажем так. Есть два подхода к написанию лямбд. Первый — поднять локальное окружение или эмулятор лямбды. Среды. Амазон, кстати, такой предоставляет. И в нем полностью написать и прогнать свой код. Ну, либо можете наживую отлаживать в облаке (не очень хорошо). Ну, либо — писать будто никакой лямбды нет, потом просто обернуть свой код и запушить в облако. Но могут быть сюрпризы.


Ещё лямбда (=серверлесс) имеет кучу минусов. Это и мониторинг. И отладка. И в целом перенос сложности с одного уровня проекта на другой. Отдельный вопрос — как будут сосуществовать разные версии кода в одном облаке. Бр. В общем — когда нужно написать что-то маленькое, что-то быстрое — serverless прекрасен, но как только нужно написать полноценный сервис, то стоит подумать и об экономике (в промышленных масштабах лямбда дорога), об ограничениях (лимиты памяти, времени выполнения) и удобстве поддержки

Очевидное ограничение самого serverless подхода, не зависимо от платформы — пользоваться приходится ровно тем, что дают. Написать код на неподдерживаемых языках программирования или использовать нестандартные параметры компилятора/интерпретатора вы не сможете. Также возможны дополнительные ограничения призванные защитить всех участников процесса разработки.

Да, всё так. Возможно перебрал пафоса с «последней версией», выбирается конкретный мажорный релиз, с nodejs10 на nodejs12 вас автоматически без предупреждений не переведут.
А подскажите как отправить «multipart/form-data», хочу отправить sendPhoto, но ничего не выходит
import json
import base64
import urllib.request

def handler(event, context):
    img  = urllib.request.urlopen("https://habr.com/images/habr.png").read()

    parsed_string = json.loads(event["body"])
    chat_id = parsed_string['message']['chat']['id']

    answerM = {
        "method": "sendMessage",
        "chat_id": chat_id,
        "text": "привет"
    }

    answerP = {
        "method": "sendPhoto",
        "chat_id": chat_id
        #"photo": base64.b64encode(img).decode()
    }

    return {
        'statusCode': 200,
        'headers': {"Content-Type": "multipart/form-data"},
        'body': json.dumps(answerP),
        'isBased64Encoded': 'true',
        'files': {'photo': base64.b64encode(img).decode()}
    }

Я не вижу в документации возможности отдельно прикладывать файлы в поле files, думаю что надо самостоятельно объявить delimiter в заголовке и подготовить данные с ним в body

Добавил Content-Disposition
import json
import base64
import urllib.request

def handler(event, context):
    img  = urllib.request.urlopen("https://habr.com/images/habr.png").read()

    parsed_string = json.loads(event["body"])
    chat_id = parsed_string['message']['chat']['id']

    boundary = 'Asrf456BGe4h'
    parts = []
    parts.append('--' + boundary)
    parts.append('Content-Disposition: form-data; name="method"')
    parts.append('')
    parts.append('sendPhoto')
    parts.append('--' + boundary)
    parts.append('Content-Disposition: form-data; name="chat_id"')
    parts.append('')
    parts.append(str(chat_id))
    parts.append('--' + boundary)
    parts.append('Content-Disposition: form-data; name="photo"; filename="%s"' % 'img.jpg')
    parts.append('Content-Type: image/jpeg')
    parts.append('')
    parts.append(base64.b64encode(img).decode())
    parts.append('--' + boundary + '--')
    parts.append('')

    body = '\r\n'.join(parts)

    return {
        'statusCode': 200,
        'headers': {
            'content-type': 'multipart/form-data; boundary=' + boundary
        },
        'body': body,
        'isBased64Encoded': 'true'
    }

И добился формирования следующего ответа, но не понимаю, что из этого не нравится телеграму:
HTTP/1.1 200 OK
Server: nginx
Date: Sun, 06 Oct 2019 14:26:32 GMT
Content-Type: multipart/form-data; boundary=Asrf456BGe4h
Transfer-Encoding: chunked
Connection: keep-alive
X-Content-Type-Options: nosniff
X-Function-Id: ...
X-Function-Version-Id: ...
X-Request-Id: ...
Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
X-Frame-Options: SAMEORIGIN

--Asrf456BGe4h
Content-Disposition: form-data; name="method"

sendPhoto
--Asrf456BGe4h
Content-Disposition: form-data; name="chat_id"

1111111
--Asrf456BGe4h
Content-Disposition: form-data; name="photo"; filename="img.jpg"
Content-Type: image/jpeg

iVBORw0KGgoAAAANSUhEUgAABLAAAAJ2CAYAAABPQHtcAAAABGdBTUEAALGPC/
.../A0wmf2FFW4KcAAAAAElFTkSuQmCC
--Asrf456BGe4h--

Явного упоминания такой готовности в доках уже телеграма нет, я пробовал sendPhoto в таком виде:


exports.input = function (data){
    let body = JSON.parse(data.body);
    let answer = {
        "method":"sendPhoto",
        "photo": "https://habrastorage.org/webt/hr/f7/nl/hrf7nll2xn4c9leojqsc95uv7ji.png",
        "chat_id": body.message.chat.id, 
        "reply_to_message_id" : body.message.message_id, 
        "text" : "Привет, Habr!"
    };

    return {
        "statusCode": 200,
        "headers": {
            'Content-Type': 'application/json'
        },
        "body": JSON.stringify(answer),
        "isBase64Encoded": false
    }

}

Как подсказали ниже/выше, для небольших картинок (меньше 5 Мб) можно указать просто URL.
Если набор изображений более-менее стабильный и отбирается вручную, можно заранее отправить их своему боту в Telegram, через метод getUpdates посмотреть на fileID этих картинок и дальше вызывать sendPhoto с этими fileID, тогда отправка будет вообще мгновенной, ведь файл уже лежит на серверах Telegram.

Да, такой вариант работает, но не в моем случае.
У меня URL картинки всегда один, а содержимое отличается (веб камера) и телеграм запоминает первое содержимое и дальше всегда его отдает.

Может быть, костыль, но что если добавлять к URL картинки какой-нибудь невзрачный параметр? Типа https://example.com/pic.jpg?yourvalue=abcxyz

Да, спасибо, работает
Всё хорошо, но хотелось бы быстрый, компилируемый язык. Идеально — Go, как у GCloud Functions.

Обещали выкатить в недалёком будущем, именно Go.

Кстати, не обязательно цена serverless функции на Go будет ниже чем цена аналогичной функции на nodejs, надо дождаться релиза.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории