Files
rss-bridge-ntfy/README.md
T
dimon 3f9b108482 RSS/Atom -> ntfy bridge with web UI, OPML import/export and RU/EN localization
Web-managed fork of nurefexc/rss-bridge-ntfy: Flask UI + REST API, background
sync engine (SQLite dedup, quiet hours, filters, flood protection, images),
OPML import/export and switchable interface/notification language.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 19:34:53 +08:00

237 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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/<id>` | Изменить / удалить фид. |
| `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).