Флибуста большая, но не бесконечная: своя рукопись, книга, которой там нет, файл в лучшем качестве — всё это можно положить в собственную библиотеку через раздел «Добавить». В статье об административных разделах форма описана коротко; здесь — подробно, с тем, что происходит «под капотом», потому что от этого зависит, переживёт ли книга следующее обновление базы.
Чем это отличается от «Добавить книги из торрента»
В «Сервисе» есть блок для торрентов — он добавляет архивы Флибусты
целиком, то есть файлы вида f.fb2-…zip, и книги из них уже есть в дампе
базы. Раздел «Добавить» — про одну книгу, которой в базе нет: для неё
создаётся запись с названием, авторами и жанрами, и упаковывается файл.
Форма шаг за шагом
1. Название. До 254 символов. Когда вы уходите из поля, библиотека ищет похожие названия (с допуском на опечатки) и показывает список со ссылками на страницы книг — посмотрите, не та ли это книга. При точном совпадении названия форма не примет книгу без галочки «Всё равно добавить (это другая книга с таким же названием)». Одноимённых книг у разных авторов много, так что галочка — норма, а не исключение.
2. Авторы. Поле поиска с подсказками начиная с двух символов. Ищет по всем авторам базы, включая тех, у кого сейчас нет ни одной книги (в обычном поиске библиотеки такие авторы скрыты), с допуском на опечатки; в подсказке показано число книг и пометка «локальный» для авторов, добавленных через этот же раздел. Если автора нет — «+ Новый автор»: фамилия, имя, отчество, псевдоним; обязательна фамилия или псевдоним. Авторов от одного до десяти, порядок сохраняется.
3. Файл. Плюс язык (две-три латинские буквы, по умолчанию ru), год и
до десяти жанров из дерева Флибусты.
Размер загрузки — до 500 МБ на стороне PHP; reverse proxy может ограничивать сильнее.
Как распознаётся формат
Расширение файла библиотеке почти безразлично — она смотрит на содержимое:
| Формат | По чему определяется |
|---|---|
сигнатура %PDF- |
|
| djvu | сигнатура AT&TFORM + DJVU |
| mobi | метка BOOKMOBI или TEXtREAd в заголовке |
| rtf | {\rtf |
| fb2 | тег <FictionBook в начале файла |
| html | <html или <!DOCTYPE html |
| txt | расширение .txt и отсутствие нулевых байтов |
| epub | zip с записью mimetype = application/epub+zip |
| docx | zip с [Content_Types].xml и word/document.xml |
| zip-обёртка | любой другой zip, содержащий ровно один файл одного из форматов выше |
Zip-обёртка распаковывается, и в библиотеку попадает то, что внутри; zip с
двумя книгами или с вложенной папкой будет отвергнут. Файл, который не
подошёл ни под одно правило, не принимается — например, fb2 в кодировке, где
<FictionBook не встречается в первых 8 КБ, или «txt» с бинарным мусором.
Дубликаты
Два уровня проверки:
- Жёсткий — по md5 файла. Если точно такой же файл уже есть в библиотеке (в дампе или среди локальных), добавление отклоняется с указанием, какая это книга. Обойти нельзя, и не нужно.
- Мягкий — по названию, описан выше: требует подтверждения галочкой.
Проверка по авторам не делается: библиотека не пытается решить, что «Война и мир» Толстого и «Война и мир» другого автора — разные книги; это решаете вы галочкой.
Что происходит при сохранении
Всё в одной транзакции:
- Книге выдаётся идентификатор из последовательности, начинающейся с
10 000 000. Идентификаторы Флибусты до этого значения не доходят,
поэтому по
id ≥ 10 000 000библиотека везде отличает локальные книги от книг дампа. Новые авторы получают id из такой же последовательности. - Запись сохраняется в таблицы
local_books,local_authors,local_book_authors,local_book_genres— это постоянное хранилище локальных книг. - Те же данные вставляются в обычные таблицы библиотеки (
libbook,libavtor,libavtorname,libgenre) и в индекс полнотекстового поиска — поэтому книга видна и находится сразу, без пересканирования. - Файл упаковывается в одно-книжный zip в
/cache/local:f.fb2.<id>-<id>.zipдля fb2 илиf.usr-<id>-<id>.zipдля остальных, с записью<id>.<расширение>внутри — ровно по соглашению Флибусты. В таблицу индекса архивов добавляется строка с диапазоном из одного id.
Благодаря последнему пункту для чтения, скачивания, конвертации и OPDS локальная книга ничем не отличается от книги из дампа. Обложка для fb2 извлекается из самого файла, как и у обычных книг.
Что происходит при следующем импорте дампа
Кнопка «Обновить базу данных» очищает обычные таблицы и заливает их
заново из дампа Флибусты. Локальные книги при этом пропали бы — если бы не
шаг «Восстановление локально добавленных книг» (merge_local_books.php),
который импорт выполняет автоматически после заливки дампа:
- Для каждой книги из
local_booksищется двойник в новом дампе: сильное совпадение по md5 или слабое — одинаковое название плюс общий автор (по фамилии и имени). - Если двойник найден, дальнейшее решает переменная
FLIBUSTA_LOCAL_DUPLICATE_POLICY:keep_both(по умолчанию) — обе книги остаются, в лог пишется заметка;prefer_dump— локальная копия удаляется вместе с её zip, а избранное и позиции чтения переносятся на книгу из дампа (там, где не конфликтуют с уже существующими записями).
- Книга без двойника вставляется обратно в обычные таблицы. Дата
добавления берётся из
local_books, поэтому книга не всплывает наверх списка новинок при каждом импорте. - Если автор книги из дампа исчез (на Флибусте объединили или удалили автора), создаётся запись-заглушка «(автор удалён из дампа)», чтобы книга не осталась без автора.
- Локальные авторы, у которых в новом дампе появился полный тёзка, только перечисляются в логе — автоматически они не объединяются.
Отчёт восстановления попадает в /cache/log/dbupdate.log и в вывод операции
на странице «Сервис»: сколько восстановлено, сколько удалено как дубликаты,
были ли ошибки. Если zip какой-то книги не найден в /cache/local, в логе
будет предупреждение: книга останется в каталоге, но открыть её будет нельзя.
Как удалить локальную книгу
Кнопки удаления в интерфейсе пока нет. Удалить можно через psql (как
подключиться — в статье о скриптах),
причём достаточно убрать книгу из постоянного хранилища и из текущих таблиц:
-- id книги виден в адресе её страницы: /book/view/10000005
DELETE FROM local_books WHERE bookid = 10000005; -- связи с авторами и жанрами удалятся каскадно
DELETE FROM libbook WHERE bookid = 10000005;
DELETE FROM libbook_ts WHERE bookid = 10000005;
DELETE FROM libavtor WHERE bookid = 10000005;
DELETE FROM libgenre WHERE bookid = 10000005;
DELETE FROM book_zip WHERE start_id = 10000005 AND end_id = 10000005;
и удалить файл /cache/local/f.fb2.10000005-10000005.zip (или f.usr-…).
Если лень вычищать обычные таблицы — можно удалить только из local_books и
файл, а потом запустить «Обновить базу данных»: обычные таблицы пересоздадутся
без этой книги. Локальный автор без книг останется в базе как кандидат для
будущих добавлений; это безвредно.
Бэкап и переезд
Локальные книги — единственное содержимое библиотеки, которое нельзя скачать заново. Их два компонента:
- таблицы
local_books,local_authors,local_book_authors,local_book_genresи последовательностиlocal_book_id_seq,local_author_id_seqв Postgres; - файлы
f.fb2.<id>-<id>.zipиf.usr-<id>-<id>.zipв/cache/local.
Достаточно сохранить эти таблицы и файлы; всё остальное восстанавливается импортом дампа. Как именно снимать и восстанавливать дамп — в статье о бэкапе и обновлении.