Все значимые изменения в проекте документируются в этом файле.
Формат основан на Keep a Changelog.
- Docker: пустой сайт Hugo —
run-docker.shбольше не создаёт симлинкsite/content, а готовит обычный каталог-точку монтирования. Hugo не заходит вcontent, если это симлинк за пределы корня проекта, и молча собирал сайт без статей. Ранее поломка была незаметна, так как устаревшийsite/publicне удалялся между сборками. - Docker: пропуск дедупликации assets — цикл копирования CSS в compose-командах больше не завершает контейнер с ненулевым кодом, когда каталог одной из платформ отсутствует. Из-за этого
run-docker.shпрерывался до шага дедупликации. - Локальная сборка: пустой сайт Hugo —
backup.pyдобавляет вhugo.tomlсекцию[[module.mounts]]с путём до каталога бэкапа. Ранее локальная сборка иhugo serverопирались только на симлинкsite/content, который Hugo игнорирует. Симлинк сохраняется для совместимости и используетсяsite/build.shпри дедупликации assets.
- Hugo: конфигурация языка — генерация
hugo.tomlтеперь явно задаётdefaultContentLanguageи[languages.ru].locale, устраняя deprecated-предупреждение.Language.LanguageCodeв новых версиях Hugo.
- Скачивание assets: устойчивость к сбоям CDN — скачивание assets теперь повторяет весь цикл
GET+ streaming + запись файла до 10 раз, удаляет partial-файлы после сбоя и использует задержки3, 5, 7, 10, 15, 15, 15, 15, 15секунд между попытками.
- Boosty: вложенные файлы — добавлена обработка блоков
file: файлы скачиваются как assets и выводятся в Markdown как ссылки на локальные файлы.
- Boosty: подписанные медиа — для
audio_fileиfileURL теперь используются параметрыsignedQueryиз API-ответа поста. Это устраняет некорректные запросы к CDN без подписи, которые могли приводить к403 Access denied.
- Документация для LLM/агента — уточнены правила работы с пользователем, git-коммитами, release notes и generated artifacts.
- Синхронизация: политика обработки ошибок — добавлена настройка
sync.on_error(stopпо умолчанию,continueдля пропуска проблемных источников). Перед скачиванием выполняется preflight-проверка авторизации всех источников, чтобы приstopне создавать частичный архив.
- Sponsr: двойные пробелы в Markdown — устранены лишние пробелы вокруг inline-разметки, возникавшие при замене внутренних spacer-маркеров после конвертации HTML.
- Hugo: deprecated-предупреждения — генерация
hugo.tomlтеперь используетlocaleвместо устаревшегоlanguageCode, а RSS-шаблон читает.Language.Localeвместо.Language.LanguageCode.
- Boosty: превью-картинка для видео — для блоков
ok_videoпревью-картинка (preview/previewUrl) теперь скачивается всегда, независимо от настройкиasset_types. В Markdown вставляется кликабельная картинка-превью[](video_link)вместо текстовой ссылки. Если превью недоступно — fallback на текстовую ссылку как раньше. - Hugo: кликабельное имя автора — имя автора в метаданных статьи теперь является ссылкой на список постов автора.
- Скачивание assets: поддержка force-флага — assets с
force=Trueскачиваются в обход фильтраasset_types(используется для превью видео).
- Boosty:
ok_videoв Markdown — для блоковok_videoссылка теперь строится из реальныхplayerUrlsс приоритетом качества (full_hd → ... → lowest, затемhls/dash), а не изvideoembed/{id}.
- Boosty: недоступные ссылки OK.ru — исправлен кейс, когда
idвok_videoбыл UUID и ссылкаhttps://ok.ru/videoembed/{id}вела на 404. - Boosty: скачивание встроенного видео —
ok_videoтеперь добавляется в список ассетов как видеофайл (лучшийplayerUrl), поэтому при успешной загрузке Markdown ссылается на локальный файлassets/<video>.mp4. - Boosty: fallback для
ok_video— при отсутствииplayerUrlsиспользуетсяhttps://ok.ru/video/{vid}, и только потом legacyhttps://ok.ru/videoembed/{id}.
- Sponsr: тире в прямой речи — исправлена регрессия конвертации, из-за которой строка вида
- <em>текст</em>в абзаце могла превращаться в markdown-список. Теперь standalone тире в начале абзаца корректно сохраняется как обычный текст (\- ...) и Hugo не рендерит буллет.
- Документация релизов — зафиксировано соглашение: сообщения git-коммитов, аннотации git-тегов и release notes ведутся на русском языке (обновлены
CONTEXT.mdиREADME.md).
- Sponsr: консистентность single/full sync — при синхронизации новых постов теперь используется загрузка полного поста по ID (как в режиме скачивания одного поста), а не урезанный HTML из списка
/more-posts. Это устраняет расхождение в Markdown-разметке между./run-docker.sh <url>и полной синхронизацией./run-docker.sh.
- Docker: публикация образов в GHCR — настроен GitHub Actions workflow для автоматической сборки и публикации Docker-образов в GitHub Container Registry при создании релиза. Теперь пользователи могут использовать готовый образ
ghcr.io/strannick-ru/article-backup:latestвместо локальной сборки. - Docker: разделение конфигурации —
docker-compose.ymlтеперь по умолчанию использует готовый образ для удобства пользователей. Для разработчиков и сборки из исходников добавлен отдельный файлdocker-compose-dev.yml.
- Sponsr: экранирование спецсимволов — символы
_,*,[и]в обычном тексте теперь корректно экранируются и не превращаются в ошибочную разметку (курсив, жирный, ссылки). Это исправляет проблему с "поплывшей" вёрсткой в статьях, содержащих много нижних подчеркиваний или математических знаков. - Sponsr: пробелы вокруг жирного текста — исправлено "склеивание" жирного текста с окружающими словами (например,
слово**жирное**→слово **жирное**). Использован надежный метод вставки маркеров в DOM, так какhtml2textигнорировал обычные пробелы. - Sponsr: пунктуация после ссылок — устранены лишние пробелы между ссылкой и знаками препинания (точка, запятая), даже если они были выделены курсивом.
- Python 3.12: SyntaxWarning — исправлены предупреждения
invalid escape sequenceв регулярных выражениях.
- Безопасность данных: коллизии имен — предотвращена перезапись постов с одинаковой датой и заголовком. Для новых записей к имени папки (slug) добавляется короткий хеш ID. Для существующих постов сохраняется обратная совместимость (пути не меняются).
- CLI: обработка ошибок — скрипт теперь возвращает код возврата
1(ошибка), если синхронизация хотя бы одного источника не удалась. В конце выводится сводка по ошибкам. Ранее скрипт мог завершаться успешно, скрывая сбои. - Сетевая стабильность — добавлены retry (повторные попытки) для всех API-запросов (списки постов, получение метаданных) в Sponsr и Boosty. Ранее retry использовался только для скачивания медиафайлов. Тайм-аут чтения увеличен до 60 секунд.
- Ресурсы — исправлена потенциальная утечка соединений при скачивании файлов (гарантированное закрытие response).
- Конфигурация — исправлено падение с
AttributeErrorпри пустом файлеconfig.yaml. Добавлено безопасное экранирование спецсимволов при генерацииhugo.toml(исправляет ошибки с кавычками в названии сайта). - Sponsr: форматирование в ссылках — устранены артефакты вида
[ _текст_ ], возникавшие при конвертации ссылок, начинающихся или заканчивающихся курсивом. Теперь пробелы внутри скобок ссылок удаляются корректно.
- Boosty — добавлено логирование предупреждений при обнаружении неизвестных типов блоков контента, чтобы избежать "молчаливой" потери данных.
- Видео: встроенные плееры вместо текстовых ссылок — встроенные видео (iframe/embed в Sponsr, ok_video в Boosty) теперь сохраняются в Markdown как обычные ссылки
[📹 Видео](embed_url)вместо текста📹 Видео: url. Hugo render hook (render-link.html) автоматически распознаёт embed URL известных видеохостингов (Rutube, YouTube, Vimeo, OK.ru, VK) и отображает полноценный адаптивный плеер (<iframe>в.video-container). Markdown-файлы остаются чистыми — без HTML-вставок. - Boosty: фильтрация пустых ссылок — исправлено появление артефактов вида
<url>в Markdown. Это происходило, когда редактор Boosty оставлял блоки ссылок с пустым текстом. Теперь такие блоки игнорируются при конвертации.
- Sponsr: фрагментация курсива — исправлена проблема, когда сплошной курсивный текст с вложенным жирным (например,
<em>текст <b>жирный</b> текст</em>) разбивался на отдельные фрагменты (_текст_ **жирный** _текст_) при конвертации. Теперь соседние теги<em>объединяются в один блок перед конвертацией, что даёт корректный результат:_текст **жирный** текст_. - Hugo: форматирование в ссылках — исправлен рендеринг ссылок, содержащих Markdown-форматирование (жирный, курсив). Ранее Hugo экранировал HTML-теги внутри ссылок (
<em>...), теперь они выводятся корректно благодаряsafeHTMLв render hook.
- Sponsr: пробелы и курсив — исправлена проблема, когда пробелы внутри тегов форматирования (например,
<em>текст </em>) приводили к невалидному Markdown (_текст _). Теперь пробелы выносятся наружу тегов перед конвертацией. - Sponsr: вложенное форматирование — устранены артефакты
****(четыре звёздочки), возникавшие при конвертации конструкций вида<b><em>text</em></b>внутри ссылок. Добавлено слияние вложенных одинаковых тегов (<em><em>→<em>) и улучшен regex-постпроцессинг. - Sponsr: пробелы в ссылках — исправлено появление пробелов внутри Markdown-ссылок (
[текст ](url)), которые возникали из-за пробелов в конце тега<a>.
- Sponsr: потеря пробелов при конвертации — исправлена проблема, когда пробел между ссылкой и следующим текстом терялся, если в HTML он находился внутри пустого тега форматирования (
<em> </em>). Такие теги теперь заменяются на своё текстовое содержимое вместо полного удаления. - Boosty: конвертация параграфов и стилей — исправлена проблема, когда inline-блоки (текст + ссылка + текст) внутри одного параграфа разбивались на отдельные строки вместо склейки. Исправлено применение стилей (italic/bold) в блоках со ссылками, где API использует глобальные позиции. Пробелы на границах стилизованных фрагментов теперь выносятся наружу маркеров.
- Markdown: дублирование заголовка — заголовок статьи больше не добавляется в body Markdown при конвертации. Hugo берёт заголовок из frontmatter, поэтому исчезает повторяющийся H1 на странице поста.
- Hugo RSS: метаданные и язык — RSS на уровне
/{platform}/{author}/posts/index.xmlтеперь используетdescriptionиз параметров секции (берётся изdisplay_nameв конфиге), а язык берётся изlanguageCode(по умолчаниюru), вместоen.
- Инкрементальная синхронизация — после первой полной синхронизации автора скрипт загружает только начало индекса (чанками по 20 постов) до тех пор, пока не встретит посты, которые уже есть в локальной базе. Это значительно сокращает время повторных запусков для авторов с большим количеством статей (с 2156 запросов до ~40-60). Добавлена таблица
sync_stateв БД для отслеживания статуса синхронизации. Обратная совместимость: старые базы автоматически обновляются при первом запуске. Производительность: автор с 2000+ постами — первый запуск ~30 мин, повторные ~30 сек (⚡ 98% быстрее).
- Sponsr: форматирование в ссылках — исправлена проблема, когда bold+italic форматирование внутри ссылок конвертировалось с лишними звёздочками снаружи (
******[***текст***](url)вместо[***текст***](url)). Теперь используется предобработка HTML перед конвертацией html2text: удаляются пустые теги форматирования, а вложенные<b><em>корректно схлопываются в***текст***внутри ссылок. - Sponsr: парсинг тегов — исправлена ошибка Hugo "unable to cast map[string]interface{} to string" при обработке тегов. API Sponsr вернул теги как массив объектов (с полями
tag_name,id,project_id), а не как массив строк. Теперь корректно извлекаются только имена тегов из объектов, поддерживается обратная совместимость с форматом строк.
- Sponsr: пробелы вокруг bold — восстановлены пробелы, которые пропадали рядом с
**...**при конвертации.
- Конвертация Sponsr Markdown — исправлена проблема, из-за которой конвертер
html2textдобавлял лишние пробелы вокруг Unicode-кавычек (например,« *текст* »вместо«*текст*»). - Sponsr: вложенные em/strong — нормализовано преобразование вложенного курсива/жирного, устранены лишние пробелы и bidi-маркеры, из-за которых ломалась разметка и заголовки.
- Assets: коллизии имён — исправлена дедупликация имён файлов при параллельной загрузке: ссылки в Markdown больше не указывают на несуществующие файлы.
- Внутренние ссылки — исправление ссылок между статьями теперь ограничено одной платформой и одним автором (не затрагивает внешние/чужие ссылки).
- Hugo: ссылки в списках — восстановлена генерация ссылок через
path.Base .RelPermalinkдля корректной работы при раздаче автора через субдомен. - Тесты — добавлены unit-тесты на дедупликацию ассетов.
- Скрипт
run-docker.sh— удобная обертка для запуска Docker. Автоматически считываетoutput_dirизconfig.yamlи монтирует правильный volume, решая проблему потери данных при смене пути бэкапа. - Улучшенный дизайн и типографика — полный редизайн шаблонов Hugo:
- Добавлены новые темы: Light, Sepia, Dark, Gruvbox, Everforest.
- Переключатель тем прямо в интерфейсе (выбор сохраняется в браузере).
- Улучшенная типографика: шрифт
PT Serifдля текста иPT Serif Captionдля заголовков. - Дизайн "лист на столе" с комфортными отступами и тенью.
- Поддержка настройки
default_themeв конфиге (по умолчанию "light").
- Фильтрация типов ассетов — в
config.yamlтеперь можно указатьasset_typesдля каждого источника. Пример:asset_types: ["image", "document"]. Поддерживаемые типы:image,video,audio,document(только PDF). Если параметр не указан, скачиваются все поддерживаемые типы. - Docker: поддержка
BACKUP_OUTPUT_DIR— добавлена переменная окружения для принудительного указания пути сохранения внутри контейнера. Это решает проблему потери данных, если пользователь изменитoutput_dirвconfig.yaml, но забудет обновить volume mapping в Docker.
- Генерация
_index.md— исправлена проблема, когда при скачивании одного поста (single mode) не создавался индексный файл раздела, из-за чего Hugo отображал "Boosties" вместо "Boosty". Теперь индекс создается всегда. - Ссылки в списках — исправлены "битые" ссылки (404) в списках постов. Заменен механизм генерации путей с
path.Baseна стандартныйRelPermalink. - Симлинки в Docker — исправлено создание некорректных симлинков внутри контейнера. Теперь скрипт
run-docker.shавтоматически обновляет симлинкsite/contentна хосте, указывая на правильную директорию с данными. - Загрузка картинок с Boosty — исправлена ошибка, когда картинки без расширения в URL (формат
/image/uuid) не скачивались при включенной фильтрацииasset_types. Теперь предварительная проверка пропускает такие файлы для анализа заголовков Content-Type. - Sponsr Parser — исправлена ошибка получения
post_id(API платформы изменилось). - Boosty Parser — исправлено получение превью для видео с OK.ru (изменилось имя поля в API).
- Рефакторинг шаблонов Hugo — внедрен базовый шаблон
baseof.htmlдля унификации структуры страниц.
Первый публичный релиз. Пакет доступен на PyPI.
-
Публикация на PyPI — пакет можно установить через
pip install article-backup. Команда для запуска:article-backup. -
Hugo: конфигурация из config.yaml —
hugo.tomlтеперь генерируется автоматически при запускеbackup.pyиз секцииhugo:в конфиге. Поддерживаемые параметры:base_url,title,language_code. Это позволяет управлять настройками Hugo из единого файла конфигурации. -
Hugo: поддержка субдоменов для авторов — добавлен скрипт
site/build.shдля сборки сайта с автономными папками авторов. Каждый автор получает свою копию CSS, что позволяет раздавать их через отдельные субдомены nginx (pushkin.example.site,lermontov.example.site). Включены относительные URL (relativeURLs = true). -
Hugo: RSS-ленты для каждого автора — теперь для каждого автора генерируется отдельный RSS-фид (
/sponsr/pushkin/index.xml). На странице списка постов автора отображается ссылка 📡 на RSS. -
Sponsr: сохранение ссылок на встроенные видео — при скачивании статей встроенные видео (iframe/embed) преобразуются в markdown-ссылки вида
📹 Видео: URL. Поддерживаемые платформы:- Rutube
- YouTube
- Vimeo
- OK.ru (Одноклассники)
- VK Video
-
Docker Compose — добавлена конфигурация для запуска на серверах с устаревшим Python. Включает:
backup— сервис с Python 3.12 для скрипта бэкапаhugo— сервис с официальным образом Hugo для сборки сайта- Подходит для автоматизации через cron:
docker compose run --rm backup && docker compose run --rm hugo
- Docker: Hugo автоматически копирует CSS — сервис
hugoпосле сборки автоматически копирует CSS в папки авторов (public/sponsr/*/css/,public/boosty/*/css/). Это позволяет раздавать авторов через субдомены без ручного запускаbuild.sh.
-
SQLite: "database is locked" — исправлена ошибка при синхронизации нескольких источников подряд. Добавлен timeout 30 секунд и включён режим WAL (Write-Ahead Logging) для лучшей конкурентной работы с базой данных.
-
Hugo: 404 на ссылках при субдоменной раздаче — исправлены относительные пути в шаблоне
list.html. Ранее ссылки генерировались как../../../sponsr/author/posts/slug/, что приводило к 404 при раздаче автора через субдомен. Теперь используются прямые пути:slug/для постов иindex.xmlдля RSS.