Добавлен контекст

This commit is contained in:
astakhovp committed 2026-10-08 22:47:35 +03:00
1 parent f61fc0016c
commit 5753de622e
1 file changed
+142
+142
View File
@@ -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`
С этого места продолжаем.