Перейти к содержимому
Socialift
Техническое руководство

Как опубликовать историю Telegram через API

История в Telegram публикуется только от имени аккаунта — методом MTProto stories.sendStory; в Bot API такого метода нет вовсе. Перед публикацией вызывается stories.canSendStory: от имени пользователя нужен Premium, от имени канала — право post_stories и достаточное число бустов. Медиа должно быть вертикальным фото или видео не больше 30 МБ.

Обновлено:

Как опубликовать историю через Telegram API?

Три шага. Сначала stories.canSendStory проверяет право — в ответе приходит число свободных «слотов» под истории. Затем stories.sendStory получает вертикальное фото или видео (до 30 МБ), правила приватности и необязательный period. В ответе внутри updateStoryID возвращается id новой истории — он нужен для редактирования и удаления.

Всё это живёт на уровне MTProto, то есть в сессии аккаунта. В Socialift это клиент TelegramAccount; он работает поверх Telethon и ставится через pip install "socialift[telegram]".

Историю можно опубликовать и от имени канала или супергруппы, но тогда вы должны быть админом с правом post_stories.

Bot API и MTProto: разница по историям

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

Bot API и MTProto: разница по историям — Таблица возможностей по платформам
ДействиеBot APIMTProto (аккаунт)
Публикация историинет — метода не существуетstories.sendStory
Увидеть входящую историюда — история приходит сообщениемда
Ответить на историюдада
Редактирование историинетstories.editStory
Удаление историинетstories.deleteStories
Список активных историйнетstories.getPeerStories

Бот только получает историю и может на неё ответить. Поэтому в Socialift методы историй не дублируются в клиенте Telegram (бот) — они есть только в TelegramAccount.

Почему бот не может публиковать истории

История — элемент профиля пользователя. Telegram сделал её для аккаунтов и каналов, а не для ботов: в документации Bot API нет метода отправки истории, есть только объект входящей истории и ответ на неё.

На практике это значит: если в контент-плане есть истории, проекту понадобится сессия аккаунта — с api_id и api_hash, по номеру телефона. Это более серьёзное решение, чем бот: файл сессии нужно хранить зашифрованным и соблюдать ограничения платформы.

Связка из двух клиентов в одном проекте — обычная практика: посты и сообщения через бота, истории — через аккаунт.

Сначала проверка: can_send_story

Документация Telegram требует именно этого: «Before posting a story, clients should invoke stories.canSendStory». Ошибку видно до загрузки файла, а не после.

can_send.py
import asyncio
from socialift import ApiError, TelegramAccount

async def main():
    async with TelegramAccount.from_env() as tg:
        targets = await tg.story_targets()
        print("можно от имени канала:", targets.chats)

        try:
            check = await tg.can_send_story("me")
        except ApiError as exc:
            print("сейчас опубликовать нельзя:", exc)
            return
        print("свободных слотов:", check.count)

asyncio.run(main())

При успехе can_send_story() возвращает stories.CanSendStoryCount: count — число свободных слотов, то есть лимит минус текущие активные истории.

story_targets() (stories.getChatsToSend) перечисляет каналы и супергруппы, от имени которых можно публиковать. Попадание в список ещё не значит «можно» — бусты и лимиты всё равно проверяются в can_send_story().

Проверка не даёт гарантии: если между can_send_story() и send_story() состояние изменится (например, история опубликована с другого устройства), та же ошибка вернётся уже из send_story().

Кто может публиковать и какие ошибки приходят

Если условия не выполнены, Telegram возвращает конкретный код ошибки — SDK переводит их в свои типы исключений.

Кто может публиковать и какие ошибки приходят — Таблица возможностей по платформам
СитуацияОшибка TelegramЧто делать
У пользователя нет PremiumPREMIUM_ACCOUNT_REQUIREDЛичные истории только с Premium; рассмотрите публикацию от имени канала
Нет права post_stories в каналеCHAT_ADMIN_REQUIREDВыдайте админку и именно это право (в SDK — PermissionError)
Каналу не хватает бустовBOOSTS_REQUIREDДождитесь нужного числа бустов
Лимит активных историйSTORIES_TOO_MUCHДождитесь истечения старых или удалите их
Недельный/месячный лимитSTORY_SEND_FLOOD_WEEKLY_%d или _MONTHLY_%dСекунды ожидания приходят в RateLimitError.retry_after

Длительность: значения period

Telegram принимает ровно четыре значения period, остальные отклоняет сервер. Socialift SDK проверяет это до загрузки файла.

Длительность: значения period — Таблица возможностей по платформам
Длительностьperiod (секунды)Для кого
6 часов21600только Premium
12 часов43200только Premium
24 часа86400по умолчанию, для всех
48 часов172800только Premium

Если period не передан, поле не отправляется и Telegram ставит 24 часа. По истечении срока история уходит в архив; при pinned=True она остаётся и в профиле.

Приватность: кто увидит историю

В MTProto это Vector<InputPrivacyRule>. SDK сводит его к четырём сокращениям, а для сложных случаев принимает готовый список правил.

everyone
Значение по умолчанию, как в приложении — InputPrivacyValueAllowAll. Историю видят все.
contacts
Только контакты — InputPrivacyValueAllowContacts.
close_friends
Только «близкие друзья» — InputPrivacyValueAllowCloseFriends. Сам список управляется через contacts.editCloseFriends.
selected
Только выбранные пользователи — InputPrivacyValueAllowUsers. При этом значении список allow обязателен.
deny
Исключения — InputPrivacyValueDisallowUsers. Правила применяются в переданном порядке, поэтому deny добавляется последним: «контакты, но не вот эти».

Медиа и текст: вертикаль, 30 МБ и ловушка подписи

Документация Telegram описывает медиа коротко: вертикальное фото или вертикальное видео, максимум 30 МБ. Цифр по соотношению сторон и длительности в документации нет, поэтому SDK их и не проверяет — невертикальное медиа обрежется в приложениях неправильно, но без ошибки.

Ограничение по размеру SDK проверяет локально: если передан путь к файлу или байты, файл больше 30 МБ не поедет на сервер впустую — сразу поднимается ConfigurationError.

caption — текст под историей. Его предельная длина приходит из серверной конфигурации (story_caption_length_limit_*) и цифрой в документации не зафиксирована. Форматирование (entities) зависит от конфигурации stories_entities: то есть не у всех аккаунтов в тексте истории работают жирный шрифт и ссылки. Без parse_mode текст уходит без разметки.

noforwards=True запрещает пересылку и сохранение истории — на случай, когда контент не должен расходиться дальше.

Публикация истории через Socialift SDK

send_story загружает файл, собирает правила приватности и вызывает stories.sendStory. Ответ — Updates, внутри id новой истории.

send_story.py
import asyncio
from socialift import RateLimitError, TelegramAccount

async def main():
    async with TelegramAccount.from_env() as tg:
        check = await tg.can_send_story("me")
        if not check.count:
            print("лимит активных историй исчерпан")
            return
        try:
            result = await tg.send_story(
                "me",
                "story.mp4",
                caption="Новая коллекция",
                period=43200,
                privacy="close_friends",
                deny=["@konkurent"],
                pinned=True,
                noforwards=True,
            )
        except RateLimitError as exc:
            print("недельный или месячный лимит, ждать:", exc.retry_after)
            return
        print(result)

asyncio.run(main())

TelegramAccount.from_env() читает TELEGRAM_API_ID, TELEGRAM_API_HASH и TELEGRAM_SESSION. Токен бота здесь не подойдёт.

file — путь, байты, файловый объект или готовый InputFile. Тип определяется по расширению (.jpg и .png — фото, остальное — видео); принудительно — photo=True или photo=False.

Чтобы опубликовать от имени канала, передайте его первым аргументом: send_story("@my_channel", ...). Тогда проверяется не Premium, а право post_stories и бусты.

period=43200 (12 часов) на аккаунте без Premium будет отклонён — если не уверены, не передавайте period, и Telegram поставит 24 часа.

Чтение, редактирование и удаление

При редактировании отправляются только переданные поля, остальные не меняются — поэтому в edit_story у privacy значение по умолчанию None.

edit_story.py
import asyncio
from socialift import TelegramAccount

async def main():
    async with TelegramAccount.from_env() as tg:
        peer = await tg.stories("me")
        for story in peer.stories:
            print(story.id, story.expire_date)

        await tg.edit_story("me", 42, caption="Исправленный текст")
        await tg.edit_story("me", 42, privacy="contacts", deny=["@konkurent"])
        await tg.delete_story("me", [42, 43])

asyncio.run(main())

stories(entity) отдаёт только СЕЙЧАС активные истории (stories.getPeerStories). Иногда в ответе приходят одни id — их запрашивают отдельно: stories(entity, ids=[...]).

Истёкших историй в этом списке нет: они в архиве (stories.getStoriesArchive) или в профиле (stories.getPinnedStories) — для них используйте raw().

Если в edit_story не передать ничего, будет ConfigurationError: пустое редактирование — бессмысленный запрос. При замене file медиа перезаливается целиком, потому что по документации DocumentAttribute намертво привязаны к медиа.

delete_story необратимо: удаляются и активная, и закреплённая в профиле, и архивная история.

Чек-лист перед запуском

  • Не пытаетесь ли вы публиковать историю токеном бота — такого метода в Bot API нет.
  • Перед каждой публикацией вызывайте can_send_story() и проверяйте count.
  • Медиа вертикальное и меньше 30 МБ; соотношение сторон контролируйте сами — Telegram его не зафиксировал.
  • В period передавайте только 21600, 43200, 86400 или 172800; без Premium — только 86400.
  • При privacy="selected" список allow обязателен.
  • Ошибки STORY_SEND_FLOOD_WEEKLY и MONTHLY ловите как RateLimitError и ждите retry_after.
  • Для публикации от имени канала заранее проверяйте право post_stories и бусты.
  • Файл сессии храните зашифрованным — он даёт полный доступ к аккаунту.
  • Форматирование в тексте истории зависит от серверной настройки stories_entities и работает не у всех.

← Назад в блог

Частые вопросы

Может ли Telegram-бот публиковать истории?

Нет. В Bot API нет метода публикации истории — бот только видит входящую историю и может на неё ответить. Для публикации нужны MTProto и сессия аккаунта: в Socialift это клиент TelegramAccount.

Нужен ли Telegram Premium для публикации истории?

От имени пользователя — да, иначе придёт PREMIUM_ACCOUNT_REQUIRED. От имени канала или супергруппы Premium не нужен, но требуются админское право post_stories и достаточное число бустов у канала.

Сколько живёт история и можно ли это изменить?

Параметр period принимает четыре значения: 21600 (6 часов), 43200 (12), 86400 (24) и 172800 (48). На аккаунте без Premium работает только 86400. Если не передать, Telegram поставит 24 часа; после этого история уходит в архив, а при pinned=True остаётся и в профиле.

Какие ограничения у медиа для истории?

Вертикальное фото или вертикальное видео, максимум 30 МБ. Точных цифр по соотношению сторон и длительности в документации Telegram нет, поэтому невертикальное медиа опубликуется без ошибки, но обрежется неправильно.

Можно ли отредактировать опубликованную историю?

Да, через stories.editStory: текст, приватность, медиа и media_areas. Меняются только переданные поля. При замене медиа файл загружается заново, так как по документации DocumentAttribute привязаны к самому медиа.

Как ограничить круг зрителей истории?

Значения privacy: everyone, contacts, close_friends и selected (в последнем случае список allow обязателен). Чтобы исключить отдельных людей, используйте deny — он добавляется последним правилом.

Источники

  1. Telegram: Stories (MTProto)
  2. Telegram: stories.sendStory
  3. Telegram: stories.canSendStory
  4. Telegram Bot API

Связанные страницы