Pull to refresh

Comments 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, и вроде совсем бесплатно.
Минус в том что решение в облаках раз в пару лет обычно нужно чуть чуть переделывать. Потому что облачное окружение меняется. Могут исключить встроенную библиотеку например.

А еще можете посмотреть на 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 картинки всегда один, а содержимое отличается (веб камера) и телеграм запоминает первое содержимое и дальше всегда его отдает.
Всё хорошо, но хотелось бы быстрый, компилируемый язык. Идеально — Go, как у GCloud Functions.

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

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

Sign up to leave a comment.

Articles