# Read books from your plugin

> Find Books & Shelves from another plugin and read its book list, shelves and book files.

Other plugins read books through a small API, reached the way plugins reach Model Hub. Clusters uses it for collections of books.

## Before you start

- The API's types aren't published as a package yet. Until they are, copy [`books-and-shelves-api.d.ts`](https://insurgently.com/docs/books-and-shelves/api/books-and-shelves-api.d.ts) into your plugin: it is every public declaration in one file. `getBooks` and `onBooksReady` are a few lines each; copy them from [`api/index.ts`](https://github.com/Insurgent-Methods/books-and-shelves/blob/HEAD/api/index.ts).
- The full reference is generated from the code: the [API reference](https://insurgently.com/docs/books-and-shelves/api).

## Steps

1. **Find the plugin.** `getBooks` checks that Books & Shelves is installed and new enough. If not, it gives a plain message to show the user.

   ```ts
   const found = getBooks(this.app, '0.1.0');
   if (!found.books) return new Notice(found.message);
   const books = found.books;
   ```

2. **Read a shelf and its books.**

   ```ts
   const ids = await books.shelfMembers('field-guides');   // a shelf's Calibre ids
   const list = await books.listBooks(ids);                // id, title, authors, formats, notePath
   ```

3. **Read a book's file or text.**

   ```ts
   const epub = await books.bookFile(list[0].id, 'EPUB');  // bytes, through the Content Server
   const text = await books.pdfText(list[0].id);           // a PDF's text
   ```

4. **Offer a conversion.** A book that has only AZW3 or MOBI has no EPUB to read. With `convert: true` the user is asked; on yes, Calibre adds an EPUB. It resolves `null` if they decline.

   ```ts
   const epub = await books.bookFile(id, 'EPUB', { convert: true });
   ```

5. **Handle failures.** A failure rejects with an error whose `code` says why: `server-off`, `book-missing`, `format-missing` and others.

## If the plugin is reloaded

Books & Shelves fires `books-and-shelves:ready` with the API each time it loads. `onBooksReady` runs your callback now and on every reload.

## Related

- [Privacy and costs](../privacy-and-costs.md)
