From 5753de622ebb95540ccd83a945a89b75fe42757f Mon Sep 17 00:00:00 2001 From: Astakhov Peter Date: Thu, 8 Oct 2026 22:47:35 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20=D0=BA=D0=BE=D0=BD=D1=82=D0=B5=D0=BA=D1=81=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OPDS_LIBRARY_CONTEXT.md | 142 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 OPDS_LIBRARY_CONTEXT.md diff --git a/OPDS_LIBRARY_CONTEXT.md b/OPDS_LIBRARY_CONTEXT.md new file mode 100644 index 0000000..df16b30 --- /dev/null +++ b/OPDS_LIBRARY_CONTEXT.md @@ -0,0 +1,142 @@ +# Выжимка из контекста: Домашняя библиотека + +## Что построено + +**Локальный OPDS-каталог + веб-интерфейс** для копии библиотеки lib.rus.ec (~579 000 книг) на TV-приставке с Armbian. + +## Железо и окружение + +- **Устройство**: TV-приставка Vontar, Armbian, ARM +- **Диски**: `/mnt/hdd` — основной +- **Docker**: контейнеры Immich (фото), Home Assistant, qBittorrent, Adminer +- **PostgreSQL**: используется общий с Immich (`immich_postgres`), база `books` + - Пароль: `Karabas@Barabas`, пользователь: `postgres` + - **Фиксированный IP**: `172.20.0.4` (сеть `immich_immich_net`, подсеть `172.20.0.0/16`) +- **OPDS-сервер**: контейнер `opds_server` на порту **8085** (порт 8080 занят qBittorrent) +- **Адрес библиотеки**: `http://192.168.30.2:8085/` + +## Расположение файлов + +``` +/mnt/hdd/opds/ # проект OPDS +├── opds_server.py # главный Flask-сервер +├── db_utils.py # подключение к БД +├── author_utils.py # работа с авторами +├── book_utils.py # извлечение fb2, обложки, конвертация +├── parse_inpx.py # импорт книг +├── parse_genres.py # загрузка жанров +├── genres.xml # справочник жанров fb2 +├── Dockerfile +└── docker-compose.yml + +/mnt/hdd/share/Torrents/Downloaded/Libruks/ +├── Библиотека Либрусек для архивов 17-08-2026.inpx +├── Библиотека Либрусек для архивов 18-09-2026.inpx +├── Libruks1086.zip +└── Архивы Либрусек/ # 3726 zip-архивов с fb2 + ├── fb2-000065-005477.zip + ├── fb2-069327-070122.zip + └── ... (по диапазонам ID) + +/root/docker-compose.yml # Immich (с фиксированным IP postgres) +``` + +## Структура базы данных + +| Таблица | Назначение | +|---------|-----------| +| `authors` | Авторы (нормализованные: full_name, last_name, first_name, middle_name, name_hash, first_letter) | +| `series` | Серии (name, name_hash, first_letter) | +| `genres` | Жанры (code, title_ru, title_en, parent_code, root_code, is_root, is_custom, genre_alt[]) | +| `books` | Книги (title, internal_id, internal_id2, file_size, format, added_date, language, source, series_id, series_number, fts) | +| `book_authors` | Связь книг↔авторов (book_id, author_id, position) | +| `book_genres` | Связь книг↔жанров (book_id, genre_id) | + +**Особенности:** +- Полнотекстовый поиск через `fts tsvector` (русский язык) +- Хеши (MD5) для быстрого поиска +- Поле `source` для поддержки нескольких источников +- Нормализация: авторы/серии/жанры вынесены в отдельные таблицы + +## Формат inpx (lib.rus.ec) + +Текстовый файл с разделителем `\x04`: +``` +AUTHOR \x04 GENRE \x04 TITLE \x04 SERIES \x04 SERNO \x04 FILE \x04 SIZE \x04 LIBID \x04 DEL \x04 EXT \x04 DATE \x04 LANG \x04 KEYWORDS +``` + +- Авторы: `Фамилия,Имя,Отчество` через `:` для нескольких +- Жанры: коды fb2 через `:` (например, `sf_history:network_literature`) +- Особенность архивов: **fb2 внутри zip-архивов может быть вложенным zip** — нужно распаковывать дважды + +## Что реализовано в веб-интерфейсе + +- ✅ Главная с поиском и навигацией +- ✅ Поиск (полнотекстовый + по автору) +- ✅ Авторы с группировкой по алфавиту (умная навигация: Па → Пел → Пелевин) +- ✅ Страница автора (серии, книги, сборники с пометкой соавторов) +- ✅ Страница книги (обложка, аннотация, оглавление) +- ✅ Чтение глав (конвертация fb2→HTML на лету, встроенные картинки, навигация ← пред/оглавление↑/след →) +- ✅ Скачивание fb2 (с обработкой вложенных zip) +- ✅ OPDS 1.2 для читалок (FBReader) + +## Что НЕ реализовано / в планах + +- ❌ Страница серий (список + страница серии с книгами) +- ❌ Страница жанров (дерево + фильтрация) +- ❌ Обложки с ленивой загрузкой (обсуждали: заглушка → загрузка в фоне → кэш в `/mnt/hdd/opds/covers/`) +- ❌ OPDS 2.0 (обсуждали как второй эндпоинт `/opds2`) +- ❌ Редактирование жанров (кастомные жанры с `is_custom=TRUE` ждут ручного заполнения) +- ❌ Языковой фильтр (56 языков в базе, но основные — ru) + +## Ключевые решения + +- **Язык в скобках**: для не-русских книг показывать `(en)`, `(uk)` и т.д. +- **Сборники**: если авторов >1 — пометка `👥 соавторы: X, Y` (до 3) или `👥 N авторов` (больше) +- **Порядок книг автора**: от новых к старым (`added_date DESC NULLS LAST`) +- **Серии на странице автора**: все, где автор участвует, по алфавиту +- **Название**: "Домашняя библиотека" (не "Моя библиотека") +- **Модульная структура**: разбить на модули (db, author, book, series, genre utils) +- **Git**: хранить всю информацию в репозитории + +## Текущие проблемы / нюансы + +1. **IP PostgreSQL менялся** после перезагрузки → исправлено фиксированным IP `172.20.0.4` +2. **Сеть Immich** конфликтовала с adminer → adminer отключён, сеть пересоздана как `immich_immich_net` +3. **Вложенные zip в архивах** → `get_book_fb2` распаковывает дважды +4. **VACUUM** нельзя в транзакции → `autocommit=True` перед VACUUM +5. **Дубликаты авторов** (`Лукьяненко,Сергей,` и `Лукьяненко,Сергей`) → исправлено нормализацией при импорте +6. **string_agg(DISTINCT ... ORDER BY ...)** — ошибка в PostgreSQL → переписано на подзапросы + +## Полезные команды + +```bash +# Обновление библиотеки новым inpx +docker compose exec opds python parse_inpx.py \ + "/path/to/новый.inpx" \ + "dbname=books user=postgres password=Karabas@Barabas host=172.20.0.4" \ + "lib.rus.ec" + +# Проверка количества книг +docker exec -it immich_postgres psql -U postgres -d books -c "SELECT COUNT(*) FROM books;" + +# Кастомные жанры +docker exec -it immich_postgres psql -U postgres -d books -c " +SELECT g.code, COUNT(bg.book_id) as cnt +FROM genres g JOIN book_genres bg ON bg.genre_id = g.id +WHERE g.is_custom = TRUE GROUP BY g.code ORDER BY cnt DESC;" + +# Пересборка OPDS +cd /mnt/hdd/opds && docker compose up -d --build +``` + +## Следующий шаг + +Создание Git-репозитория `opds-library` со структурой: +- `sql/` — схема БД +- `scripts/` — парсеры +- `app/` — Flask-сервер (модули) +- `data/` — genres.xml +- `docker-compose.yml`, `Dockerfile`, `README.md` + +С этого места продолжаем. \ No newline at end of file