# RSS → ntfy Bridge (с веб-интерфейсом) Мост, который следит за RSS/Atom-лентами и отправляет новые записи как push-уведомления в [ntfy](https://ntfy.sh). В отличие от [оригинального проекта](https://github.com/nurefexc/rss-bridge-ntfy), где ленты настраивались через JSON-файлы и переменные окружения, **здесь всё управление происходит через веб-интерфейс** — добавление лент, топиков, расписаний и глобальных настроек, запуск синхронизации, просмотр журнала и отправка тестовых уведомлений. Проект упакован в Docker и запускается одной командой. --- ## Возможности - 🌐 **Полное управление через браузер** — фиды, топики, настройки, без правки файлов. - 🔔 **Отправка в ntfy** с заголовком, ссылкой (Click), Markdown, иконкой и картинкой (Attach). - 🧠 **Дедупликация** через SQLite (WAL) — одна запись не приходит дважды. - 🌙 **Тихие часы** — пониженный приоритет в заданном интервале (напр. `22-7`). - 🧹 **Фильтры** include/exclude по регулярным выражениям. - 🌊 **Флуд-защита** — ступенчатая задержка доставки для записей с низким приоритетом. - 🖼️ **Картинки и описание** автоматически извлекаются из HTML записи. - 📜 **Живой журнал** и дашборд со статусом прямо в интерфейсе. - ▶️ **Кнопки** «Синхронизировать сейчас», «Пауза/Возобновить», «Тестовое уведомление». - 📥 **Импорт/экспорт OPML** — перенос списка лент между ридерами (с сохранением ntfy-параметров). - 🌍 **Локализация интерфейса** — переключение языка (RU/EN) прямо в шапке; влияет и на текст уведомлений. - 💾 **Все данные в одном томе** `./data` (настройки, фиды, история, логи). --- ## Быстрый старт (Docker Compose) — рекомендуется Требуется установленный **Docker** и **Docker Compose**. ```bash # 1. Перейти в каталог проекта cd rss-bridge-ntfy # 2. Собрать образ и запустить контейнер docker compose up -d --build # 3. Открыть веб-интерфейс # http://localhost:8080 ``` Готово. Откройте **http://localhost:8080**, перейдите на вкладку **«Фиды»** и добавьте первую ленту. Полезные команды: ```bash docker compose logs -f # смотреть логи docker compose restart # перезапустить docker compose down # остановить и удалить контейнер (данные в ./data сохранятся) ``` ### Настройка перед запуском (необязательно) В файле `docker-compose.yml` можно поменять: - **Порт.** `"8080:8080"` → например `"9000:8080"`, тогда интерфейс будет на `:9000`. - **Часовой пояс.** `TZ: "Europe/Moscow"` — влияет на тихие часы и время в логах. > Адрес ntfy-сервера и токен задаются **не здесь, а в самом интерфейсе** > (вкладка «Настройки»). По умолчанию используется публичный `https://ntfy.sh`. --- ## Запуск через `docker run` (без Compose) ```bash docker build -t rss-bridge-ntfy-web . docker run -d \ --name rss-bridge-ntfy \ -p 8080:8080 \ -e TZ=Europe/Moscow \ -v "$(pwd)/data:/data" \ --restart unless-stopped \ rss-bridge-ntfy-web ``` --- ## Запуск без Docker (для разработки) Требуется **Python 3.11+**. ```bash pip install -r requirements.txt python main.py # Интерфейс: http://localhost:8080 ``` Переменные окружения (необязательно): `PORT` (по умолчанию `8080`), `HOST` (`0.0.0.0`), `DATA_DIR` (`data`), `TZ` (`UTC`). --- ## Как пользоваться интерфейсом Интерфейс состоит из трёх вкладок. ### 1. Дашборд - Карточки со статистикой: число фидов, топиков, отправленных уведомлений, записей в истории. - Состояние движка, время последней и следующей синхронизации. - **Тестовое уведомление** — введите топик и текст, проверьте доставку в ntfy. - **Журнал** работы в реальном времени и кнопка очистки истории дедупликации. - В шапке: **«Синхронизировать»** (запустить цикл немедленно) и **«Пауза/Возобновить»**. ### 2. Фиды Кнопка **«+ Добавить фид»** открывает форму. Поля: | Поле | Описание | |------|----------| | **Название** | Подпись источника в уведомлении. | | **URL фида*** | Ссылка на RSS/Atom. | | **Топик ntfy*** | Топик, в который уйдут уведомления (напр. `news`). | | **Приоритет** | 1–5 (базовый приоритет уведомления). | | **Иконка (URL)** | Картинка-иконка уведомления (заголовок `Icon`). | | **Тихие часы** | Интервал вида `22-7`; в это время используется приоритет ниже. | | **Приоритет в тихие часы** | Какой приоритет применять в тихие часы (по умолчанию 1). | | **Include regex** | Показывать только записи, совпадающие с выражением. | | **Exclude regex** | Отбрасывать записи, совпадающие с выражением. | | **Включён** | Переключатель активности фида. | Кнопка **«Проверить фид»** в форме загружает ленту и показывает несколько свежих заголовков — удобно убедиться, что URL рабочий, ещё до сохранения. Каждую ленту в списке можно включить/выключить тумблером, отредактировать (✎) или удалить (🗑). **Импорт/экспорт OPML.** В шапке вкладки «Фиды» есть кнопки: - **Экспорт OPML** — скачивает файл `feeds.opml` со всеми лентами (ntfy-параметры — топик, приоритет, тихие часы, фильтры — сохраняются в кастомных атрибутах `ntfy*`). - **Импорт OPML** — загружает `.opml`-файл и добавляет ленты. Дубликаты (совпадение по URL и топику) пропускаются. У стандартных OPML-файлов из других ридеров топик берётся из родительской группы (или `rss`, если её нет), затем его можно поправить. ### Локализация Язык интерфейса переключается выпадающим списком **RU/EN** в правом верхнем углу. Выбор сохраняется в настройках на сервере и влияет также на язык ссылки «Читать на сайте» / «Read on website» в самих уведомлениях. ### 3. Настройки (глобальные) | Настройка | Описание | |-----------|----------| | **ntfy сервер (URL)** | Адрес сервера ntfy (по умолчанию `https://ntfy.sh`; можно указать свой self-hosted). | | **ntfy токен** | Токен доступа (`Bearer`) для приватных серверов/топиков. Необязательно. | | **Интервал синхронизации** | Как часто опрашивать ленты, в секундах (по умолчанию 600). | | **Часовой пояс (IANA)** | Напр. `Europe/Moscow`. Используется для тихих часов. | | **Лимит новых записей за цикл** | Максимум новых уведомлений на ленту за один проход (по умолчанию 3). | | **Макс. длина описания** | До скольких символов обрезать текст уведомления. | | **User-Agent** | Заголовок User-Agent при запросе лент. | | **Флуд-защита** | Ступенчатые задержки доставки для записей с приоритетом < 4. | | **Язык (RU/EN)** | Переключается в шапке; влияет на интерфейс и текст уведомлений. | После сохранения настроек запускается синхронизация. --- ## Получение уведомлений на телефоне 1. Установите приложение **ntfy** ([Android](https://play.google.com/store/apps/details?id=io.heckel.ntfy) / [iOS](https://apps.apple.com/app/ntfy/id1625396347)) или откройте веб-клиент https://ntfy.sh/app. 2. Подпишитесь на топик, который вы указали у фида (например `news`). 3. Новые записи из ленты будут приходить push-уведомлениями. > Топик в ntfy.sh — это, по сути, публичный канал. Используйте длинное, > труднодоступное имя топика или собственный сервер ntfy с токеном для приватности. --- ## Где хранятся данные Всё лежит в каталоге `./data` (примонтирован как том `/data` в контейнере): | Файл | Назначение | |------|------------| | `settings.json` | Глобальные настройки. | | `feeds.json` | Список лент и их параметры. | | `history.db` | SQLite-база отправленных записей (дедупликация). | | `bridge.log` | Файл журнала. | Резервная копия = копия каталога `data/`. Удаление `history.db` приведёт к повторной отправке последних записей. --- ## Структура проекта ``` rss-bridge-ntfy/ ├── main.py # точка входа: поднимает движок и веб-сервер (waitress) ├── engine.py # ядро: парсинг лент, дедуп, фильтры, отправка в ntfy ├── store.py # потокобезопасное хранилище настроек и фидов (JSON) ├── webapp.py # Flask: REST API + отдача интерфейса ├── opml.py # импорт/экспорт OPML ├── templates/index.html ├── static/css/style.css ├── static/js/app.js ├── static/js/i18n.js # словарь локализации (RU/EN) ├── requirements.txt ├── Dockerfile ├── docker-compose.yml └── data/ # создаётся при запуске (том с данными) ``` --- ## REST API Интерфейс работает поверх простого API — им можно пользоваться и напрямую: | Метод | Путь | Назначение | |-------|------|------------| | `GET` | `/api/status` | Статус движка и статистика. | | `POST` | `/api/sync` | Запустить синхронизацию немедленно. | | `POST` | `/api/engine` | `{"action":"pause"|"resume"}` — пауза/возобновление. | | `GET` | `/api/logs` | Последние строки журнала. | | `POST` | `/api/history/clear` | Очистить историю дедупликации. | | `GET`/`PUT` | `/api/settings` | Получить/обновить глобальные настройки. | | `GET`/`POST` | `/api/feeds` | Список фидов / создать фид. | | `PUT`/`DELETE` | `/api/feeds/` | Изменить / удалить фид. | | `POST` | `/api/feeds/preview` | `{"url":"..."}` — проверить ленту. | | `GET` | `/api/export/opml` | Скачать все ленты в формате OPML. | | `POST` | `/api/import/opml` | Загрузить OPML (multipart `file` или тело запроса). | | `POST` | `/api/test-notify` | `{"topic":"...","message":"..."}` — тест. | --- ## Лицензия MIT. Основано на идее проекта [nurefexc/rss-bridge-ntfy](https://github.com/nurefexc/rss-bridge-ntfy).