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>
This commit is contained in:
@@ -0,0 +1,236 @@
|
||||
# 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).
|
||||
Reference in New Issue
Block a user