# jabnews Jabber-бот для трансляции RSS-новостей в конференции (MUC). Бот подписывается на RSS-ленты и автоматически публикует новые записи в указанные jabber-комнаты. ## Возможности - Управление через личные сообщения и команды в конференции - Подписка на несколько RSS-лент с индивидуальным интервалом опроса - Дедупликация: каждый RSS-источник опрашивается один раз, даже если подписан в нескольких комнатах - Персональные командные символы для каждой комнаты - Разграничение прав: владелец бота, администратор комнаты, участник ## Команды ### Личные сообщения | Команда | Описание | |---------|----------| | `join ` | Добавить бота в конференцию | | `exit ` | Вывести бота из конференции | | `list` | Список моих комнат | | `list-all` | Все комнаты бота — только для владельца | | `help` | Справка | ### Команды в конференции По умолчанию командные символы — `!`. Их можно изменить командой `cmd`. | Команда | Описание | |---------|----------| | `! subscribe [интервал]` | Подписаться на RSS (интервал в минутах, default 15, min 5) | | `! unsubscribe ` | Отписаться от RSS | | `! list` | Список подписок комнаты | | `! cmd <символы>` | Сменить командные символы | | `! help` | Справка по командам комнаты | Обращение к боту по нику (`jabnews, help`) эквивалентно команде `! help`. ## Архитектура Проект реализован по паттерну **Ports and Adapters (Hexagonal Architecture)**. ``` src/ domain/ subscriptions/ — shared kernel: Subscription, SubscriptionRepository news/ — NewsItem, NewsFetcher, NewsPublisher, FetchAndPublishNews admin/ — Room, Admin, все usecases управления adapters/ jabber/ — XMPP-соединение, публикация новостей, обработка команд sources/rss/ — получение новостей через feedparser db/ — SQLite реализации репозиториев scheduled/ — таймер проверки новостей (каждые 5 мин) main.py — composition root ``` ### Направления зависимостей ``` domain/admin → domain/subscriptions domain/news → domain/subscriptions adapters/* → domain/* main.py → adapters/* + domain/* domain/admin ↛ domain/news domain/news ↛ domain/admin ``` Доменный слой не зависит ни от slixmpp, ни от feedparser, ни от aiosqlite. ## Запуск ### Требования - Docker + Docker Compose ### Настройка ```bash cp env.example .env ``` Заполните `.env`: ```env BOT_JID=bot@your-jabber-server.com BOT_PASSWORD=secret JID_OWNER=owner@your-jabber-server.com BOT_NICK=jabnews DB_PATH=/data/jabnews.db LOG_LEVEL=INFO ``` ### Запуск через Docker Compose ```bash docker compose up -d ``` База данных хранится в `./data/jabnews.db` на хосте. ### Запуск локально (для разработки) ```bash uv sync cp env.example .env # заполнить .env uv run python src/main.py ``` ## Стек - Python 3.12+ - [slixmpp](https://pypi.org/project/slixmpp/) — XMPP-клиент - [feedparser](https://pypi.org/project/feedparser/) — парсинг RSS - [aiosqlite](https://pypi.org/project/aiosqlite/) — асинхронная работа с SQLite - [uv](https://github.com/astral-sh/uv) — сборка и управление зависимостями