BookfusionPluginsResearch/docs/api.md

35 KiB
Raw Blame History

BookFusion API

Документация восстановлена из исходников calibre-plugin/ и obsidian-plugin/.
# UNVERIFIED — поле или поведение не верифицированы живым трафиком.


Оглавление

  1. Обзор
  2. Аутентификация
  3. Calibre API
  4. Obsidian API
  5. Структуры данных
  6. Алгоритм calibre_metadata_digest
  7. Magic-комментарии Obsidian
  8. Поддерживаемые форматы файлов

1. Обзор

BookFusion предоставляет два независимых REST API с разными механизмами аутентификации:

API Базовый URL Назначение
Calibre API v1 https://www.bookfusion.com/calibre-api/v1 Загрузка книг из Calibre
Obsidian API https://www.bookfusion.com Синхронизация заметок и хайлайтов с Obsidian

2. Аутентификация

2.1 Calibre API — HTTP Basic Auth

Каждый запрос к Calibre API требует двух заголовков:

Заголовок Значение
Authorization Basic {base64("{api_key}:")}
User-Agent BookFusion Calibre Plugin {major}.{minor}.{patch}

{api_key} — API-ключ пользователя; используется как HTTP username, пароль — пустая строка.

Пример для ключа abc123 (плагин версии 1.4.0):

Authorization: Basic YWJjMTIzOg==
User-Agent: BookFusion Calibre Plugin 1.4.0

base64("abc123:") = YWJjMTIzOg==

API-ключ пользователь получает на странице (HTML, не API-эндпоинт):
https://www.bookfusion.com/calibre-api/v1/api-key

При неверном ключе сервер возвращает HTTP 401.


2.2 Obsidian API — Token

Каждый запрос к Obsidian API (кроме GET /obsidian-api/connect) требует заголовка:

X-Token: {token}

Получение токена — однократная операция через браузер:

  1. Открыть в браузере:
    GET https://www.bookfusion.com/obsidian-api/connect?_={unix_timestamp_ms}
  2. Пользователь входит в аккаунт BookFusion.
  3. BookFusion вызывает Obsidian protocol handler:
    obsidian://bookfusion-connect?token={token}
  4. Obsidian-плагин сохраняет token и использует его в последующих запросах.

3. Calibre API

Базовый URL: https://www.bookfusion.com/calibre-api/v1

Все запросы к Calibre API требуют заголовков Authorization и User-Agent из раздела 2.1.


GET /calibre-api/v1/limits

Возвращает лимиты аккаунта. Вызывается перед началом синхронизации.

Запрос

GET /calibre-api/v1/limits HTTP/1.1
Host: www.bookfusion.com
Authorization: Basic YWJjMTIzOg==
User-Agent: BookFusion Calibre Plugin 1.4.0

Query-параметры отсутствуют.

Ответ 200 OK

{
  "filesize": 52428800,
  "total_books": 100,
  "message": "You've reached the book limit for your plan. Upgrade to sync more books."
}
Поле Тип Описание
filesize integer Максимальный размер файла книги в байтах
total_books integer | null Максимальное количество книг. null — без ограничений
message string | null Сообщение для отображения пользователю при превышении лимита. null — нет сообщения

Ошибки

Код Описание
401 Неверный API-ключ

GET /calibre-api/v1/uploads/{id}

Проверяет, загружена ли книга в BookFusion. Возвращает объект с ID и дайджестом метаданных, если книга найдена.

Используется в двух сценариях:

Сценарий Значение {id}
У книги в Calibre есть идентификатор bookfusion BookFusion ID (целое число)
У книги нет ни bookfusion, ни isbn SHA-256 hex-дайджест содержимого файла

Path-параметры

Параметр Тип Описание
id string BookFusion ID книги (число) или SHA-256 hex-дайджест файла

Запрос (по BookFusion ID)

GET /calibre-api/v1/uploads/42 HTTP/1.1
Host: www.bookfusion.com
Authorization: Basic YWJjMTIzOg==
User-Agent: BookFusion Calibre Plugin 1.4.0

Запрос (по SHA-256 дайджесту)

GET /calibre-api/v1/uploads/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 HTTP/1.1
Host: www.bookfusion.com
Authorization: Basic YWJjMTIzOg==
User-Agent: BookFusion Calibre Plugin 1.4.0

Ответ 200 OK

Единственный объект (не массив).

{
  "id": 42,
  "calibre_metadata_digest": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
}
Поле Тип Описание
id integer BookFusion внутренний ID книги # UNVERIFIED
calibre_metadata_digest string SHA-256 hex-дайджест метаданных предыдущей загрузки (алгоритм — раздел 6)

Ошибки

Код Описание
401 Неверный API-ключ
404 Книга не найдена
500 Внутренняя ошибка сервера

GET /calibre-api/v1/uploads

Ищет загруженную книгу по ISBN. Используется если у книги в Calibre есть идентификатор isbn, но нет bookfusion.

Query-параметры

Параметр Тип Обязательный Описание
isbn string да ISBN книги

Запрос

GET /calibre-api/v1/uploads?isbn=9780743273565 HTTP/1.1
Host: www.bookfusion.com
Authorization: Basic YWJjMTIzOg==
User-Agent: BookFusion Calibre Plugin 1.4.0

Ответ 200 OK

Массив объектов. При отсутствии совпадений — пустой массив [].
Клиент использует только первый элемент массива.

[
  {
    "id": 42,
    "calibre_metadata_digest": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
  }
]

Поля элемента:

Поле Тип Описание
id integer BookFusion внутренний ID книги # UNVERIFIED
calibre_metadata_digest string SHA-256 hex-дайджест метаданных предыдущей загрузки

Ошибки

Код Описание
401 Неверный API-ключ
500 Внутренняя ошибка сервера

POST /calibre-api/v1/uploads/init

Инициализирует загрузку новой книги. Возвращает presigned URL и параметры для загрузки файла напрямую во внешнее хранилище (S3 или аналогичное).

Вызывается только для книг, не найденных через GET /uploads/{id} или GET /uploads?isbn=.

Запрос

Content-Type: multipart/form-data

POST /calibre-api/v1/uploads/init HTTP/1.1
Host: www.bookfusion.com
Authorization: Basic YWJjMTIzOg==
User-Agent: BookFusion Calibre Plugin 1.4.0
Content-Type: multipart/form-data; boundary=----Boundary

------Boundary
Content-Disposition: form-data; name="filename"

the-great-gatsby.epub
------Boundary
Content-Disposition: form-data; name="digest"

e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
------Boundary--
Поле Тип Обязательный Описание
filename string да Имя файла книги (basename), например book.epub
digest string да SHA-256 hex-дайджест содержимого файла

Ответ 200 OK

{
  "url": "https://<storage-host>/<bucket>",
  "params": {
    "key": "uploads/abc123def456/the-great-gatsby.epub",
    "<param2>": "<value2>",
    "<param3>": "<value3>"
  }
}

Конкретные ключи params зависят от провайдера хранилища и не зафиксированы в исходниках плагина. Гарантированно присутствует только ключ key. # UNVERIFIED

Поле Тип Описание
url string URL внешнего хранилища для загрузки файла
params object<string, string> Поля для multipart-запроса к url. Конкретные ключи зависят от провайдера хранилища. Гарантированно содержит ключ key (используется при финализации). Остальные ключи не зафиксированы. # UNVERIFIED

Ошибки

Код Тело ответа Описание
401 Неверный API-ключ
422 {"error": "..."} Ошибка валидации

POST {upload_url} — внешнее хранилище

Загружает файл книги во внешнее хранилище. URL и параметры получены из ответа POST /uploads/init.

Это не BookFusion API — запрос отправляется на url из ответа предыдущего шага (S3 или аналогичный сервис). Заголовки аутентификации BookFusion не передаются.

Запрос

Content-Type: multipart/form-data

Сначала все поля из объекта params ответа /uploads/init, последним — поле file:

POST https://s3.amazonaws.com/bookfusion-uploads HTTP/1.1
Content-Type: multipart/form-data; boundary=----Boundary

------Boundary
Content-Disposition: form-data; name="key"

uploads/abc123def456/the-great-gatsby.epub
------Boundary
Content-Disposition: form-data; name="AWSAccessKeyId"

AKIAIOSFODNN7EXAMPLE
------Boundary
Content-Disposition: form-data; name="policy"

eyJleHBpcmF0aW9uIjoiMjAyNi0wNC0yN1QxMjowMDowMFoifQ==
------Boundary
Content-Disposition: form-data; name="signature"

bWq2s1WEIj+Ydj0vQ685zfW47oA=
------Boundary
Content-Disposition: form-data; name="file"; filename="the-great-gatsby.epub"

(binary file content)
------Boundary--
Поле Тип Описание
(все ключи из params) string Поля из объекта params ответа /uploads/init
file binary Содержимое файла книги. Передаётся последним полем.

Ответ

Тело ответа не используется. Успех — HTTP 2xx.

При сетевых ошибках (connection refused, remote host closed, host not found, timeout, temporary network failure) клиент выполняет до двух повторных попыток.


POST /calibre-api/v1/uploads/finalize

Завершает загрузку: регистрирует книгу в BookFusion и привязывает загруженный файл к метаданным.

Вызывается после успешной загрузки файла во внешнее хранилище.

Запрос

Content-Type: multipart/form-data

POST /calibre-api/v1/uploads/finalize HTTP/1.1
Host: www.bookfusion.com
Authorization: Basic YWJjMTIzOg==
User-Agent: BookFusion Calibre Plugin 1.4.0
Content-Type: multipart/form-data; boundary=----Boundary

------Boundary
Content-Disposition: form-data; name="key"

uploads/abc123def456/the-great-gatsby.epub
------Boundary
Content-Disposition: form-data; name="digest"

e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
------Boundary
Content-Disposition: form-data; name="metadata[calibre_metadata_digest]"

9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
------Boundary
Content-Disposition: form-data; name="metadata[title]"

The Great Gatsby
------Boundary
Content-Disposition: form-data; name="metadata[summary]"

A story of the fabulously wealthy Jay Gatsby and his love for Daisy Buchanan.
------Boundary
Content-Disposition: form-data; name="metadata[language]"

eng
------Boundary
Content-Disposition: form-data; name="metadata[isbn]"

9780743273565
------Boundary
Content-Disposition: form-data; name="metadata[issued_on]"

1925-04-10
------Boundary
Content-Disposition: form-data; name="metadata[series][][title]"

The Jazz Age Collection
------Boundary
Content-Disposition: form-data; name="metadata[series][][index]"

1.0
------Boundary
Content-Disposition: form-data; name="metadata[author_list][]"

F. Scott Fitzgerald
------Boundary
Content-Disposition: form-data; name="metadata[tag_list][]"

fiction
------Boundary
Content-Disposition: form-data; name="metadata[tag_list][]"

classic
------Boundary
Content-Disposition: form-data; name="metadata[bookshelves][]"


------Boundary
Content-Disposition: form-data; name="metadata[bookshelves][]"

American Literature
------Boundary
Content-Disposition: form-data; name="metadata[cover]"; filename="cover.jpg"

(binary image data)
------Boundary--
Поле Тип Обязательный Описание
key string да Значение params.key из ответа /uploads/init
digest string да SHA-256 hex-дайджест содержимого файла книги
metadata[calibre_metadata_digest] string да SHA-256 hex-дайджест метаданных (алгоритм — раздел 6)
metadata[title] string да Название книги
metadata[summary] string нет Аннотация
metadata[language] string нет Язык книги (первый элемент из списка языков Calibre)
metadata[isbn] string нет ISBN
metadata[issued_on] string нет Дата публикации, формат YYYY-MM-DD. Не передаётся если значение равно 0101-01-01
metadata[series][][title] string нет Название серии. Повторяется для каждой серии отдельной строкой.
metadata[series][][index] string нет Порядковый номер в серии. Передаётся вместе с series[][title]; отсутствует если index равен None.
metadata[author_list][] string нет Автор. Повторяется для каждого автора.
metadata[tag_list][] string нет Тег. Повторяется для каждого тега.
metadata[bookshelves][] string нет Полка. Первый элемент — обязательно пустая строка (Rails-паттерн для гарантированной передачи массива); затем — названия полок. Поле передаётся только если в настройках Calibre-плагина задана bookshelves_custom_column.
metadata[cover] binary нет Файл обложки книги

Ответ 200 OK

{
  "id": 42
}
Поле Тип Описание
id integer BookFusion внутренний ID созданной книги

Ошибки

Код Тело ответа Описание
401 Неверный API-ключ
422 {"error": "..."} Ошибка валидации

PUT /calibre-api/v1/uploads/{id}

Обновляет метаданные существующей книги. Опционально — перезагружает файл книги.

Path-параметры

Параметр Тип Описание
id string BookFusion ID книги

Запрос

Content-Type: multipart/form-data

Минимальный пример (обновление метаданных без перезагрузки файла):

PUT /calibre-api/v1/uploads/42 HTTP/1.1
Host: www.bookfusion.com
Authorization: Basic YWJjMTIzOg==
User-Agent: BookFusion Calibre Plugin 1.4.0
Content-Type: multipart/form-data; boundary=----Boundary

------Boundary
Content-Disposition: form-data; name="metadata[calibre_metadata_digest]"

a4e624d686e03ed2767c0abd85c46f3d32c3f784a9d4c851d30de5dd9a26bade
------Boundary
Content-Disposition: form-data; name="metadata[title]"

The Great Gatsby (Updated Edition)
------Boundary
Content-Disposition: form-data; name="metadata[author_list][]"

F. Scott Fitzgerald
------Boundary--
Поле Тип Обязательный Описание
file binary нет Файл книги. Передаётся только при явной перезагрузке.
metadata[calibre_metadata_digest] string да SHA-256 hex-дайджест метаданных
metadata[title] string да Название книги
metadata[summary] string нет Аннотация
metadata[language] string нет Язык
metadata[isbn] string нет ISBN
metadata[issued_on] string нет Дата публикации YYYY-MM-DD
metadata[series][][title] string нет Название серии (повторяется)
metadata[series][][index] string нет Номер в серии (повторяется; отсутствует если index равен None)
metadata[author_list][] string нет Автор (повторяется)
metadata[tag_list][] string нет Тег (повторяется)
metadata[bookshelves][] string нет Полка (первый элемент — пустая строка, затем значения)
metadata[cover] binary нет Файл обложки книги

Ответ 200 OK

Тело ответа не определено. # UNVERIFIED

Ошибки

Код Тело ответа Описание
401 Неверный API-ключ
422 {"error": "..."} Ошибка валидации

4. Obsidian API

Базовый URL: https://www.bookfusion.com

Все запросы к Obsidian API (кроме GET /obsidian-api/connect) требуют заголовка X-Token из раздела 2.2.


GET /obsidian-api/connect

Страница аутентификации в браузере. Используется для получения токена.

Возвращает HTML-страницу, не JSON.

Query-параметры

В каждом запросе передаётся ровно один из двух параметров:

Параметр Тип Сценарий Описание
_ string Новое подключение Unix timestamp в миллисекундах. Служит cache buster.
token string Повторное открытие страницы настроек Существующий токен пользователя.

Запрос — новое подключение

GET /obsidian-api/connect?_=1745658000000 HTTP/1.1
Host: www.bookfusion.com

Запрос — открытие страницы настроек

GET /obsidian-api/connect?token=tok_abc123def456 HTTP/1.1
Host: www.bookfusion.com

Ответ

HTML-страница. После успешной аутентификации BookFusion открывает Obsidian через protocol handler:

obsidian://bookfusion-connect?token={token}
Параметр Тип Описание
token string Токен для заголовка X-Token в последующих API-запросах

POST /obsidian-api/sync

Возвращает страницы книг и индексные файлы для синхронизации с Obsidian vault.

Поддерживает пагинацию через курсор: запросы повторяются с cursor из предыдущего ответа, пока cursor не станет null.

Запрос

POST /obsidian-api/sync HTTP/1.1
Host: www.bookfusion.com
Content-Type: application/json
X-Token: tok_abc123def456
API-Version: 1

{
  "cursor": null
}

Заголовки:

Заголовок Значение Описание
Content-Type application/json
X-Token {token} Токен аутентификации
API-Version 1 Версия API. Строковое значение "1".

Тело запроса:

Поле Тип Обязательный Описание
cursor string | null да Курсор пагинации. null — начало синхронизации; строка — продолжение.

Ответ 200 OK

Пример — первая страница с одной книгой:

{
  "pages": [
    {
      "id": "bf-book-123",
      "type": "book",
      "content": "# The Great Gatsby\n\nA story of wealth and loss in the 1920s.",
      "directory": "BookFusion",
      "filename": "The Great Gatsby.md",
      "update_strategy": "magic",
      "frontmatter": "title: The Great Gatsby\nauthor: F. Scott Fitzgerald\nrating: 5",
      "highlights": [
        {
          "id": "hl-456",
          "content": "So we beat on, boats against the current, borne back ceaselessly into the past.",
          "chapter_heading": "## Chapter 9",
          "previous": "hl-455",
          "next": null
        }
      ],
      "atomic_highlights": false
    }
  ],
  "cursor": "eyJpZCI6MTAwfQ==",
  "next_sync_cursor": null
}

Поля ответа:

Поле Тип Описание
pages Page[] Массив страниц для создания или обновления. Может быть пустым [].
cursor string | null Курсор для следующего запроса текущей сессии. null — сессия пагинации завершена.
next_sync_cursor string | null Курсор для следующей сессии синхронизации. Сохранить и передать как cursor в первом запросе следующего запуска. null — нет нового курсора для сохранения. # UNVERIFIED

Пагинация

Сессия 1:
  POST {cursor: null}  → {cursor: "A", next_sync_cursor: null,  pages: [...]}
  POST {cursor: "A"}   → {cursor: "B", next_sync_cursor: null,  pages: [...]}
  POST {cursor: "B"}   → {cursor: null, next_sync_cursor: "Z",  pages: [...]}
  → сессия завершена, сохранить next_sync_cursor = "Z"

Сессия 2:
  POST {cursor: "Z"}   → {cursor: null, next_sync_cursor: "W",  pages: [...]}
  → сессия завершена, сохранить next_sync_cursor = "W"

Ошибки

Код Тело ответа Описание
не 2xx {"message": "..."} Ошибка сервера

5. Структуры данных

Все структуры используются в ответе POST /obsidian-api/sync.

5.1 Page

Базовый тип. Конкретный тип страницы определяется полем type.

Поле Тип Описание
type "book" | "index" Тип страницы
content string | null Содержимое Markdown-файла
directory string Путь к папке в Obsidian vault
filename string Имя файла
update_strategy "append" | "replace" | "magic" | "insert" Стратегия обновления существующего файла

Значения update_strategy:

Значение Описание
append Новые хайлайты добавляются в конец файла
replace Файл перезаписывается целиком
magic Позиционное обновление по magic-комментариям; использует поля previous / next хайлайтов
insert Позиционное обновление без magic-комментариев

5.2 BookPage

Страница книги. Содержит все поля Page, плюс:

Поле Тип Описание
type "book" Всегда "book"
id string ID книги. Используется в magic-комментариях файла (раздел 7).
frontmatter string | null YAML-строка без разделителей ---. При создании файла вставляется между ---. null — frontmatter отсутствует.
highlights HighlightBlock[] | AtomicHighlightPage[] Массив хайлайтов. Тип элементов определяется полем atomic_highlights.
atomic_highlights boolean true — каждый хайлайт создаётся в отдельном файле (тип AtomicHighlightPage). false — хайлайты встраиваются в файл книги (тип HighlightBlock).

Полный набор полей BookPage:

Поле Тип
type "book"
content string | null
directory string
filename string
update_strategy "append" | "replace" | "magic" | "insert"
id string
frontmatter string | null
highlights HighlightBlock[] | AtomicHighlightPage[]
atomic_highlights boolean

5.3 IndexPage

Индексный файл. Содержит все поля Page без дополнительных.

Поле Тип
type "index"
content string | null
directory string
filename string
update_strategy "append" | "replace" | "magic" | "insert"

5.4 HighlightBlock

Хайлайт, встраиваемый в файл книги. Используется когда BookPage.atomic_highlights = false.

Поле Тип Описание
id string ID хайлайта. Используется в magic-комментариях (раздел 7).
content string Текст хайлайта
chapter_heading string | null Заголовок главы, перед которым отображается хайлайт
previous string | null ID предыдущего хайлайта в документе. Используется стратегиями magic и insert.
next string | null ID следующего хайлайта в документе. Используется стратегиями magic и insert.

5.5 AtomicHighlightPage

Хайлайт в отдельном файле. Используется когда BookPage.atomic_highlights = true. Содержит все поля HighlightBlock, плюс:

Поле Тип Описание
directory string Путь к папке в vault для файла хайлайта
filename string Имя файла хайлайта
link string Obsidian-ссылка на файл хайлайта (встраивается в файл книги)

Полный набор полей AtomicHighlightPage:

Поле Тип
id string
content string
chapter_heading string | null
previous string | null
next string | null
directory string
filename string
link string

6. Алгоритм calibre_metadata_digest

SHA-256 дайджест метаданных книги, вычисляемый Calibre-плагином. Сервер сохраняет его и возвращает в ответе GET /uploads/{id}, чтобы плагин мог определить — изменились ли метаданные с момента последней загрузки.

Источник: calibre-plugin/upload_worker.py:275322

Алгоритм — последовательная запись полей в SHA-256 хэш в UTF-8. Поля пропускаются если равны None или пустой строке:

  1. title — всегда
  2. summary (поле comments в Calibre) — если не пустой
  3. Первый элемент metadata.languages — если список не пустой
  4. isbn — если не пустой
  5. pubdate.date().isoformat() — если значение не равно "0101-01-01"
  6. Для каждой серии из metadata.series и кастомных полей типа series:
    • series.title (UTF-8)
    • str(series.index) (UTF-8) — если series.index is not None
  7. Для каждого автора из metadata.authors: author (UTF-8)
  8. Для каждого тега из metadata.tags: tag (UTF-8)
  9. Для каждой полки из bookshelves_custom_column (если настроена): bookshelf (UTF-8)
  10. Если обложка существует:
    • bytes(os.path.getsize(cover_path)) — размер файла как Python bytes-объект
    • b'\0'
    • Содержимое файла обложки блоками по 65536 байт
from hashlib import sha256
import os

h = sha256()
h.update(title.encode('utf-8'))
if summary:
    h.update(summary.encode('utf-8'))
if language:
    h.update(language.encode('utf-8'))
if isbn:
    h.update(isbn.encode('utf-8'))
if issued_on and issued_on != '0101-01-01':
    h.update(issued_on.encode('utf-8'))
for s in series_list:
    h.update(s['title'].encode('utf-8'))
    if s['index'] is not None:
        h.update(str(s['index']).encode('utf-8'))
for author in authors:
    h.update(author.encode('utf-8'))
for tag in tags:
    h.update(tag.encode('utf-8'))
for shelf in bookshelves:
    h.update(shelf.encode('utf-8'))
if cover_path:
    h.update(bytes(os.path.getsize(cover_path)))
    h.update(b'\0')
    with open(cover_path, 'rb') as f:
        while chunk := f.read(65536):
            h.update(chunk)
digest = h.hexdigest()

7. Magic-комментарии Obsidian

Obsidian-плагин размечает блоки контента специальными комментариями. Это позволяет обновлять отдельные хайлайты без перезаписи всего файла.

Источник: obsidian-plugin/src/utils.ts:3

Формат блока:

%%begin-{id}%%
{content}
%%end-{id}%%
  • {id} — значение поля id из BookPage или HighlightBlock / AtomicHighlightPage
  • При обновлении плагин ищет блок с совпадающим id и заменяет его целиком
  • Стратегии magic и insert используют поля previous / next хайлайтов для определения позиции вставки нового блока

Пример файла с хайлайтами:

---
title: The Great Gatsby
author: F. Scott Fitzgerald
---

%%begin-bf-book-123%%
# The Great Gatsby

A story of wealth and loss in the 1920s.
%%end-bf-book-123%%

%%begin-hl-456%%
## Chapter 9
So we beat on, boats against the current, borne back ceaselessly into the past.
%%end-hl-456%%

8. Поддерживаемые форматы файлов

Источник: calibre-plugin/book_format.py:78

Calibre-плагин выбирает формат файла для загрузки в следующем порядке:

  1. Предпочтительные форматы (проверяются первыми): EPUB, MOBI
  2. Если предпочтительного нет — первый поддерживаемый формат из списка:

AZW, AZW3, AZW4, CBZ, CBR, CBC, CHM, DJVU, DOCX, EPUB, FB2, FBZ, HTML, HTMLZ, LIT, LRF, MOBI, ODT, PDF, PRC, PDB, PML, RB, RTF, SNB, TCR, TXT, TXTZ

Если у книги нет файла ни в одном поддерживаемом формате, книга пропускается без загрузки.