Как я за полчаса собрала личный RSS-ридер в Telegram с помощью Make и AI

У меня уже есть Telegram-канал о фронтенд-разработке, где я делюсь с подписчиками новостями, интересными находками и собственными наблюдениями. Чтобы было о чём рассказывать, приходится регулярно заглядывать в блоги React, TypeScript, Chrome, WebKit и других проектов. В какой-то момент я поняла, что хочу читать всё это в одном месте, а не вспоминать каждый раз, куда давно не заходила и что могла пропустить. Конечно, можно подписаться на несколько новостных каналов, но тогда кто-то другой будет решать, какие новости мне показывать - а мне хотелось получать информацию напрямую из официальных источников, желательно сразу на русском и в формате, который можно быстро пролистать за кофе.

Так у меня появился отдельный Telegram-канал со свежими новостями из технических блогов, которые AI кратко пересказывает их на русском, а я уже выбираю, что хочется прочитать подробнее. Если тема действительно интересная, открываю первоисточник, разбираюсь в деталях и, возможно, потом пишу об этом в своём основном канале - уже со своими выводами и опытом.

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

RSS, Make и немного автоматизации

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

Например, одна запись может выглядеть так:

<item> <title>What's New in Chrome</title> <link>https://example.com/article</link> <description>New features for web developers...</description> <pubDate>...</pubDate> </item>

Для моей задачи это оказалось идеальным вариантом: не нужно писать парсер, разбирать HTML или следить за изменениями вёрстки сайтов. Достаточно знать адрес RSS-ленты и периодически получать из неё новые записи.

Я решила начать с официальных источников, которые и так читаю или периодически проверяю:

У V8 используется Atom (формат типа rss), но в его основе также лежит xml, и для моего сценария разница несущественна.

А кто будет регулярно проверять эти адреса, отправлять статьи на перевод и публиковать результат в Telegram? Можно было написать небольшой скрипт на Node.js, но мне совершенно не хотелось поднимать сервер и поддерживать отдельный проект ради личной новостной ленты, плюс я платформы автоматизации сейчас на жестком хайпе - а тут такой повод попробовать!) Я выбирала из Make и n8n. Оба позволяют собирать процессы из отдельных блоков: получить данные, обработать, передать дальше. При этом n8n даёт больше свободы для собственного кода и самостоятельного развёртывания, а Make предлагает готовую облачную среду с визуальным редактором и большим набором интеграций.

Для моего случая Make оказался проще: RSS, HTTP-запросы, Telegram и небольшое хранилище данных там уже есть. Не пришлось ничего разворачивать, настраивать окружение или думать, где всё это будет работать.

В итоге схема получилась довольно короткой:

RSS → OpenRouter → Telegram

RSS отдаёт статью, OpenRouter помогает перевести и кратко пересказать её, а Telegram становится интерфейсом, в котором я читаю результат.

Собираем первую рабочую версию

Сначала я создала отдельный Telegram-канал, а затем через @BotFather — бота, который будет отправлять туда сообщения. Для этого достаточно выполнить /newbot, придумать имя и username, получить токен и добавить бота в администраторы канала с правом публикации.

После этого открыла Make, создала новый сценарий и добавила модуль RSS → Watch RSS feed items. В качестве первого источника выбрала блог Chrome:

Для каждого источника достаточно указать адрес RSS-ленты и количество получаемых записей.
Для каждого источника достаточно указать адрес RSS-ленты и количество получаемых записей.

На этапе тестирования ограничила количество элементов, чтобы случайно не отправить в канал пачку старых статей.

Следующим шагом нужно было как-то превращать английские заголовки и описания в нормальный русский текст. Я остановилась на OpenRouter — сервис, через который можно обращаться к разным языковым моделям через единый API, тем более там ест тариф openrouter/free, то есть маршрутизация на доступные бесплатные модели. У такого варианта есть лимиты и нет гарантии постоянной доступности, но для небольшого личного проекта этого пока хватает.

В Make добавила модуль HTTP → Make a request со следующими настройками:

Authentication type: No authentication URL: <a href="https://openrouter.ai/api/v1/chat/completions" target="_blank">https://openrouter.ai/api/v1/chat/completions</a> Method: POST И двумя заголовками: Authorization: Bearer ВАШ_API_КЛЮЧ Content-Type: application/json

API-ключ нужно предварительно создать в OpenRouter. Само собой, публиковать его где-либо не стоит.

Дальше началась небольшая борьба с JSON. Изначально я попробовала собрать тело запроса вручную, подставляя туда описание статьи из RSS. Это работало ровно до момента, пока в описании не встретились переносы строк и специальные символы. Make сообщил:

Source is not valid JSON Bad control character in string literal

Вместо того чтобы вручную экранировать всё, что может прийти из RSS, я переключила настройки HTTP-модуля:

Body content type: application/json Body input method: Data structure
Перешла на Data structure, чтобы не собирать JSON вручную и не ловить ошибки экранирования.
Перешла на Data structure, чтобы не собирать JSON вручную и не ловить ошибки экранирования.

Затем создала структуру с текстовым полем model и массивом messages, в котором каждый элемент содержит role и content. Make стал самостоятельно формировать корректный JSON, и проблема исчезла.

В поле model указала openrouter/free, а в messages добавила два элемента: system с инструкциями для модели и user с содержимым конкретной новости.

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

Поэтому инструкция получилась такой:

Ты — помощник для чтения технических новостей. Кратко пересказывай на русском языке новости о frontend-разработке из официальных источников. Это личная новостная лента, а не авторский блог. Пиши естественно, понятно и без лишних вступлений. Не используй рекламный стиль, кликбейт и эмоциональные оценки. Не пиши от первого лица и не изображай автора. Не добавляй собственное мнение. Сначала объясни, что произошло, затем передай основные технические детали. Если в исходном тексте есть информация о практическом применении или ограничениях, упомяни её. Не придумывай факты и не делай выводов, которых нет в источнике. Названия технологий, библиотек и API сохраняй на языке оригинала. Не делай буквальный перевод. Передавай смысл кратко и точно. Верни готовое сообщение в HTML для Telegram. Заголовок заключи в <b>...</b>. После него напиши 1–3 коротких абзаца. В конце добавь: <a href="URL_ИЗ_НОВОСТИ">Источник</a> Используй только URL из входных данных. Не добавляй Markdown, хэштеги и подпись автора.

Во второй элемент messages, с ролью user, передаю данные из RSS:

Заголовок: [RSS → Title] Текст: [RSS → Description] URL_ИЗ_НОВОСТИ: [RSS → URL]

Здесь записи в квадратных скобках обозначают поля, которые нужно выбрать в интерфейсе Make, а не текст, который следует вставить буквально.

В HTTP-модуле включила Parse response: Yes, чтобы результат API можно было использовать в следующих шагах.

Оставалось отправить готовый текст в Telegram. Для этого добавила модуль Telegram Bot → Send a Text Message or a Reply, подключила созданного бота и указала в Chat ID username канала. В поле Text выбрала результат HTTP-запроса:

Data → choices[] → message → content

А в Parse Mode поставила HTML, чтобы Telegram отображал жирные заголовки и ссылки на первоисточники.

Здесь я тоже успела поймать ошибку:

[400] Bad Request: chat not found

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

Нажала Run once, Make получил статью из RSS, отправил её в OpenRouter, получил русский пересказ и опубликовал сообщение в Telegram. На этом первую версию можно было считать готовой.

Когда одного источника стало мало

С Chrome всё работало, поэтому следующим логичным шагом было подключить MDN, WebKit, React, TypeScript и остальные блоги.

Я попробовала просто добавить ещё одну RSS-цепочку рядом с первой, но Make предупредил, что она не подключена к основному потоку и выполняться не будет. Пришлось немного переделать сценарий.

В начале я поставила Tools/Basic trigger, за ним - Router, а уже от Router сделала отдельные ветки для каждого источника. Внутри каждой ветки использовала RSS → Retrieve RSS feed items, который получает элементы ленты при выполнении сценария.

В результате схема стала такой
В результате схема стала такой

Итоговый сценарий: один запуск, несколько RSS-источников и публикация в Telegram

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

При копировании модулей обнаружилась ещё одна мелочь: Make сохраняет сопоставления полей. Поэтому после создания новой ветки нужно проверить, что заголовок, описание и URL берутся из её собственного RSS-модуля, а не из предыдущего. Иначе можно получить довольно странную ситуацию, когда ветка MDN публикует новости Chrome.

Но появилась проблема посерьёзнее: Retrieve RSS feed items может возвращать одни и те же статьи при каждом запуске. Если ничего с этим не делать, канал будет регулярно публиковать уже прочитанные новости.

Избавляемся от дублей

Для этого пригодился Data Store — встроенное хранилище Make. Я создала хранилище published_news и решила сохранять в нём URL каждой опубликованной статьи.

Логика простая: перед публикацией проверяем, встречался ли такой URL раньше. Если да — пропускаем. Если нет — отправляем новость в Telegram и только после успешной отправки запоминаем ссылку. Реализуем это через фильтр с условием:

Как я за полчаса собрала личный RSS-ридер в Telegram с помощью Make и AI

Если URL уже есть в Data Store, новость не идёт дальше по сценарию

После Telegram добавила Data Store → Add/replace a record и снова использовала URL статьи в качестве ключа.

Здесь важно именно такое расположение модулей: если сохранить URL до отправки сообщения, то при ошибке Telegram статья уже будет считаться обработанной и может потеряться. В моей схеме запись создаётся после успешной публикации. Конечно, абсолютной гарантии это не даёт: например, если Telegram отправит сообщение, а Data Store не сможет сохранить URL, при следующем запуске возможен дубль. Для личной ленты меня такой риск пока устраивает.

Заодно стоит учитывать, что проверка по URL не распознаёт одинаковые новости из разных источников. Если Chrome и MDN напишут об одном событии, для Data Store это будут две разные статьи. Пока это даже полезно: иногда интересно сравнить первоисточники.

Расписание и пара нюансов

Изначально я запускала сценарий каждые 15 минут, но довольно быстро поняла, что мне такая оперативность ни к чему. Я не новостное агентство и не пытаюсь опубликовать релиз быстрее остальных. Мне достаточно раз в несколько часов открыть Telegram и посмотреть, что появилось, поэтому частоту запуска можно спокойно уменьшить — заодно это экономит операции Make и запросы к OpenRouter.

Есть нюанс с настройкой Maximum number of returned items. Во время тестирования у меня стояло значение 1, чтобы не получить сразу много публикаций. Но для постоянной работы этого может быть недостаточно: если между запусками источник выпустит несколько статей, часть из них можно пропустить. После настройки Data Store разумнее увеличить лимит, например до пяти элементов, и позволить фильтру отсекать уже опубликованные URL. Я пока остановила на 2.

Ещё один момент связан с содержимым RSS. Не все сайты отдают в ленту полный текст статьи. Иногда там только заголовок и несколько предложений описания, поэтому AI пересказывает именно их. Для быстрого знакомства с новостью этого обычно достаточно, но если тема меня заинтересовала, я всё равно открываю оригинал. И, конечно, модель может ошибаться. Поэтому использовать такой пересказ как единственный источник информации для авторской публикации я бы не стала.

Отдельно стоит следить за HTML: модель иногда может сгенерировать некорректный тег, а Telegram поддерживает не всю HTML-разметку. Если это станет регулярной проблемой, проще будет просить AI возвращать отдельно заголовок и текст, а форматирование собирать уже в Make.

Что в итоге получилось

Сейчас у меня есть два независимых Telegram-канала: в основном канале я общаюсь с подписчиками, делюсь опытом и пишу о том, что мне самой интересно. Новостной канал существует отдельно и выполняет более скучную, но полезную работу: собирает новости из официальных блогов и показывает их мне на русском языке.

В дальнейшем хочется добавить фильтрацию по темам и, возможно, ежедневный дайджест вместо отдельных сообщений. Ещё было бы удобно сохранять заинтересовавшие статьи в отдельный список, чтобы потом возвращаться к ним при подготовке публикаций. Но пока я решила не усложнять систему - она уже закрывает мою основную потребность: мне больше не нужно вручную обходить десяток технических блогов, чтобы узнать, что в них появилось..

Надеюсь, что эта инструкция поможет и вам создать свою читалку или автоматизировать другой простой процесс! :)