Перейти к содержанию

Лента

POST /v1/feed

Объединяет последние посты до 100 каналов в один список, отсортированный по оценке, которая учитывает вовлечённость, насыщенность контента и свежесть.

По умолчанию выключено

Лента — самый тяжёлый эндпоинт: ей нужна страница каждого запрошенного канала. Пока она не включена через ENABLE_FEED=true, она отвечает 503. Если у вас больше одного воркера или сервера, запускайте её с Redis (REDIS_URL), чтобы все они делили кэш страниц и рейтинг популярности.

Запрос

{"channels": ["durov", "telegram", "stranaua"]}

От 1 до 100 корректных имён пользователей. Дубликаты игнорируются. Некорректный ввод получает 422, даже пока лента выключена.

Ответ

{
  "result": [
    {
      "id": 552,
      "content": { … },
      "footer": { … },
      "view": "…",
      "channel": {
        "username": "durov",
        "title": {"string": "Pavel Durov", "html": "Pavel Durov"},
        "description": { … },
        "avatar": "https://…",
        "counters": {"subscribers": "10.3M", "photos": "102", "videos": "47", "links": "200"},
        "labels": ["verified"]
      },
      "_score": 0.1688
    }
  ]
}

Каждый элемент — пост в сыром разобранном виде (поля, которые Telegram не предоставил, опускаются, а не равны null), плюс:

  • channel — профиль канала, которому принадлежит пост;
  • _score — оценка ранжирования в диапазоне [0, 10];
  • _duplicates (необязательно) — та же новость, опубликованная другими каналами и свёрнутая в этот пост: [{"channel": "…", "id": 123}, …];
  • _topic (необязательно) — тема, общая для этого поста и других постов ленты: {"id": 3, "keywords": ["starlink", "ограничения", …]}.

Порядок элементов — это порядок ленты. В основном, но не строго, он следует _score: ранжировщик перемешивает каналы и темы (см. «Ранжирование» ниже). Каналы, которые не удалось загрузить (неизвестные, ошибки t.me), пропускаются.

Свежесть данных

Лента кэширует каждую страницу канала по схеме stale-while-revalidate:

Возраст страницы в кэше Что происходит
< FEED_FRESH_TTL (60 с) используется как есть
< FEED_STALE_TTL (15 мин) используется сразу; фоновое обновление заменяет её
старше / нет в кэше загружается сейчас — все недостающие каналы параллельно

Фоновый рефрешер поддерживает актуальность каналов, которые действительно запрашивают: чем чаще канал встречается в запросах ленты, тем чаще он обновляется (каждые 30 с для самых популярных и вплоть до раза в 10 мин). Поэтому большинство запросов ленты вообще не ждут t.me. Подробности: Внутреннее устройство → Лента.

Ранжирование

Ранжирование выполняется нативно на Rust и учитывает:

  • вовлечённость относительно канала — просмотры с поправкой на возраст поста в сравнении с другими постами канала, так что выдающиеся посты небольших каналов конкурируют с крупными каналами;
  • реакции, насыщенность контента и размер аудитории;
  • свежесть с периодом полураспада FEED_HALF_LIFE_HOURS (24 ч);
  • свёртку дубликатов между каналами;
  • разнообразие: меньше подряд идущих постов одного канала или одной темы (FEED_DIVERSITY);
  • темы, выведенные из текстов.

Полный алгоритм описан в разделе Внутреннее устройство → Лента. При PARSER_MODE=simplified реакции не разбираются и не учитываются.

Изменено в 2.1

Ранжирование переехало на Rust и изменилось: значения _score и порядок отличаются от 2.0, добавлены _duplicates / _topic.