shikhalev.*

В посте о подключении телеграм-канала я уже предполагал, что напишу подробнее о технической стороне этого подключения. Вообще-то, я планировал этим заняться попозже, а пока переключиться на «Прак­ти­чес­кое руководство по dark­table»… Но внезапно обнаружил, что толком переключиться не могу, пока не доведу эту задачу с анонсером до какой-то логической точки.

Что ж, причесал Actions, отладил это хозяйство до более-менее стабильного со­сто­я­ния — хоть и далекого от завершения, но уже приемлемого для описания. Принципиальных изменений в ближайших версиях, скорее всего, не будет, а о плановых доделках я здесь еще скажу.

Задача

Собственно, основная задача стояла в следующем:

  • Отправлять анонсы (пока только в телеграм-канал) новых постов;

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

Уже по ходу дела решил добавить в Actions отправку уведомлений себе о выполненных операциях.

Текущее состояние

  • Анонсы в телеграм отправляются.

  • Специальный liquid-тег формирует ссылку на анонс (через t.me), которую затем JavaScript динамически заполняет дан­ны­ми и делает видимой.

  • Дополнительно я получаю уведомления об обновлениях сайта в личку от бота, как показано на КДПВ.

Чего точно нужно доделать:

  • Анонсирование в IndexNow;

  • Анонсирование в другие соцсети, желательно сделать какой-то удобный способ расширения;

  • Доработать вставляемую ссылку;

  • Доработать настройки, в т.ч. сделать раздельный флаг анонсирования в front-matter;

  • Документировать полноценно и зарелизить.

И в процессе еще вышел на пару задач, не связанных напрямую с анонсером:

Что и как работает

Общий принцип

Плагин при генерации сайта собирает список страниц с установленным флагом announce и загружает список уже анонсированных, хранящийся в каталоге _data jekyll-проекта. Сравнивает эти два списка и определяет новые анонсы, данные по которым записывает в отдельный файл .announces.json, вместе с некоторыми параметрами из конфига, чтобы в дальнейшем при отправке анонсов не требовалось дополнительно читать и парсить конфиг.

Чтобы передать эту информацию на этап отправки, приходится делать обратный пуш (с файлом .announces.json) в репозиторий. Собственно, почему этап отправки анонсов сделан отдельным? Дело в том, что телеграм получает информацию о странице при первом знакомстве с ней, и, соответственно, к этому моменту она должна быть опубликована.

Затем отдельный ruby-скрипт (входящий в тот же гем, что и плагин) читает этот файл с анонсами и файл с уже проанонсированными (тот тоже в формате JSON), отправляет анонсы и добавляет информацию в файл с проанонсированными. Его, соответственно, тоже нужно запушить обратно в репозиторий.

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

Кроме того, файл с данными по уже анонсированным копируется также на сайт, откуда его и берет в дальнейшем JavaScript.

Исходники

jekyll-is-announcer

Собственно, гем с анонсером. Ключевые файлы:

Пример использования

Репозиторий с исходниками данного сайта, а конкретней — его каталог .github/workflows.

  • build.yml — сборка Jekyll с обратным пушем и деплоем GitHub Pages. Срабатывает на пуш в ветку main.

  • announce.yml — отправка анонсов, с обратным пушем и опять же деплоем с обновленным списком анонсированных. Запускается вручную или раз в сутки по расписанию (на случай, если забуду сам запустить).

  • Пример использования liquid-тега можно увидеть лэйауте для постов — post.html.

  • И что важно: конфигурация в _config.yml.

Вспомогательное

Как можно видеть workflows репозитория сайта ссылаются также на некоторые нестандартные actions:

  • action-jekyll-is-backpush — обратный пуш с уведомлением. Проверяет, есть ли чего пушить, если нечего — то ничего не делает (и не уведомляет, ибо не о чем). Обратный пуш отправляется с «[skip ci]» в сообщении коммита, соответственно, триггеры на него не срабатывают.

  • action-jekyll-is-publish — публикация, то есть отправка в ветку gh-pages. Опять же пушит и уведомляет только если есть изменения.

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

Вместо итого

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