mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 00:11:37 -06:00
3bb33b615c
Add configurable seed ratio and seed time goals to request indexers, supporting both static goals and tracker-advertised ratio/seed-time limits via torznab attributes. Enforce indexer-specific seed policy during request fulfillment and display active seed targets in the request seed panel. Closes #1360
216 lines
12 KiB
Markdown
216 lines
12 KiB
Markdown
# Book Requests
|
|
|
|
Book requests let readers ask for a book BookOrbit does not have. An approver decides on the
|
|
request, a release is picked from the sources you configured, a download client fetches it, and the
|
|
result is filed into a library.
|
|
|
|
Everything in this guide is operator configuration. Nothing here is on by default, and a fresh
|
|
install has no sources, no download clients and no automation.
|
|
|
|
## What BookOrbit ships
|
|
|
|
**BookOrbit ships no sources.** There is no bundled tracker, no default indexer, and no list of
|
|
sites to pick from. Two protocol adapters are compiled in: `torznab` for torrent indexers and
|
|
`newznab` for Usenet indexers. Both need an address and API key you supply. Everything else is an
|
|
indexer plugin you install yourself.
|
|
|
|
Which sources you point BookOrbit at, and what you search for and download through them, is your
|
|
decision and your responsibility. BookOrbit does not provide or endorse indexer sources. Its URL,
|
|
file, and path safety checks still apply to every configured source.
|
|
|
|
## Permissions
|
|
|
|
| Permission | What it allows |
|
|
| --------------------------- | ----------------------------------------------------------- |
|
|
| `book_request_access` | File a request, see your own, join somebody else's |
|
|
| `manage_book_requests` | Approve, reject, and drive fulfilment on every request |
|
|
| `book_request_auto_approve` | Your own requests skip the approval queue |
|
|
| `book_request_self_fulfill` | Pick the release and download it yourself, with no approver |
|
|
|
|
The last three each imply `book_request_access`; granting one on its own would produce an account
|
|
that can approve requests but has no page to see them on.
|
|
|
|
Configuring sources, download clients and automation is separate again, and needs
|
|
`manage_app_settings`. Installing an indexer plugin needs a superuser: a plugin runs inside the
|
|
server process with the server's reach.
|
|
|
|
## Before anything can be saved: the encryption key
|
|
|
|
Set `BOOK_REQUEST_ENCRYPTION_KEY` before configuring a download client or an indexer:
|
|
|
|
```bash
|
|
openssl rand -hex 32
|
|
```
|
|
|
|
It must be a 64-character hex string. Unlike `MIGRATION_ENCRYPTION_KEY` and the email key, this one
|
|
is not optional in practice: a tracker API key or seedbox password is **refused rather than stored
|
|
in the clear** when the key is missing, so the settings form will not save.
|
|
|
|
Rotating or removing the key leaves stored credentials unreadable. They are not silently dropped:
|
|
the affected source refuses to be used and says why, so you can re-enter the credential rather than
|
|
discover the loss during a download.
|
|
|
|
## Sources
|
|
|
|
Settings > System > Requests > Sources.
|
|
|
|
Three kinds of row, added two ways, identical once they exist:
|
|
|
|
- **Torznab**: an address plus an API key. This is how you attach a Prowlarr or Jackett instance,
|
|
and one such instance can expose many trackers behind one row per tracker.
|
|
- **Newznab**: an address plus an API key. BookOrbit uses generic searches, including an ISBN as
|
|
the query when enabled, and fetches the selected NZB without exposing the key to the download
|
|
client.
|
|
- **Plugins**: a single `.mjs` file installed through the page, loaded at boot from
|
|
`<APP_DATA_PATH>/plugins/indexers/<name>/index.mjs`. Plugins live in their own repositories and
|
|
are not distributed with BookOrbit.
|
|
|
|
A plugin may declare a signed update manifest. BookOrbit checks each declared channel at most once
|
|
every 12 hours, supports a review-before-install flow, and can install verified updates
|
|
automatically when a superuser enables that option for the plugin. The downloaded source must match
|
|
both the manifest's SHA-256 and its Ed25519 signature. Installs are atomic, activate without a
|
|
restart, and restore the previous plugin if activation fails.
|
|
|
|
Per source you can set the medium it is searched for, its categories, whether it is handed an ISBN
|
|
when the request has one, and a colour that marks its releases in the release picker.
|
|
|
|
Private network addresses are refused unless you opt the row in with **Allow private address**. A
|
|
self-hosted Prowlarr on the LAN is the common reason to; a public tracker resolving to a private
|
|
address is not.
|
|
|
|
Two health facts are shown per row, and they answer different questions:
|
|
|
|
- **Connected / Not reachable** is the last time you pressed **Test**, which makes a capabilities
|
|
call.
|
|
- **Searches failing** is how the last real searches went. A source can be reachable and still
|
|
refuse every search, and the badge counts consecutive failures so one blip reads differently
|
|
from a source that has been broken for a week.
|
|
|
|
### Per-indexer seed goals
|
|
|
|
Torrent sources can set a manual seed ratio and total seed time. Each manual field is independent.
|
|
Leaving one blank means inheritance; zero and negative values are not special modes. **Apply tracker
|
|
seed goals** controls only whether a valid goal reported by Torznab or a torrent plugin fills a
|
|
blank manual field. Turning it off does not disable manual values and does not request unlimited
|
|
seeding.
|
|
|
|
For ratio, BookOrbit uses the manual source value, then the tracker value when tracker fallback is
|
|
enabled, then omits the value so the download client uses its own default. Seed time follows the
|
|
same order: manual source value, tracker value when tracker fallback is enabled, then the download
|
|
client's default.
|
|
|
|
The policy is read when a new grab attempt starts, so a saved edit applies even when BookOrbit is
|
|
reusing recently inspected torrent bytes. It applies only to releases selected from that configured
|
|
source. A pasted magnet or uploaded torrent file has no indexer policy. Changes do not reconfigure
|
|
torrents already in a client.
|
|
|
|
## Download clients
|
|
|
|
Settings > System > Requests > Download clients. qBittorrent, Transmission and Deluge accept
|
|
torrents; NZBGet accepts NZBs. A Newznab source therefore needs an enabled NZBGet client, while a
|
|
Torznab source needs an enabled torrent client. Direct HTTP sources need no external client.
|
|
|
|
BookOrbit does not connect to an NNTP article server. Configure the article-server account in
|
|
NZBGet, then give BookOrbit a separate NZBGet API account. BookOrbit fetches the credentialed NZB,
|
|
sends its bytes to NZBGet, and monitors the item by a stable ownership key rather than a transient
|
|
NZBGet queue ID.
|
|
|
|
Each client needs at least one **path mapping**, including when BookOrbit and the client run on the
|
|
same host. A mapping translates the download directory the client reports into a path BookOrbit can
|
|
open, and it is also the root the import is allowed to read out of. On a single host that mapping
|
|
is an identity, `/downloads -> /downloads`; it still has to be stated, because "the same path" and
|
|
"no path stated" are different things and only one of them is safe to import from.
|
|
|
|
Hardlinking from the download directory into the library avoids storing the imported bytes twice
|
|
and keeps a torrent seeding after the book is filed. The mapping form can test whether a hardlink
|
|
actually works between the two paths, which is worth doing before the first grab: a mapping across
|
|
filesystems copies instead, silently doubling the space every book takes.
|
|
|
|
The same mount is necessary but is not sufficient. On Linux, `fs.protected_hardlinks=1` normally
|
|
requires the BookOrbit process user to own the completed source file or be able to write it. The
|
|
download client and BookOrbit commonly run with the same UID, or with a shared group that grants
|
|
BookOrbit write access to completed files. The mapping test creates its own BookOrbit-owned source
|
|
file, so it proves that the paths and mount permit hardlinks but cannot prove that a completed file
|
|
owned by a different user will be linkable. If the real file cannot be linked, BookOrbit falls back
|
|
to copying it and the book uses space twice while the original keeps seeding.
|
|
|
|
BookOrbit never stops a seed on its own. Removing a client-managed download is an explicit action
|
|
with its own confirmation, and removing one that is still working also fails the request.
|
|
|
|
qBittorrent accepts a per-torrent ratio and total seeding-time limit through fields documented
|
|
since Web API 2.8.1. When both exist, its own stop rules can act when either limit is reached; the
|
|
pair is not an AND condition and does not guarantee both tracker minimums. Deluge accepts the ratio
|
|
with stop-at-ratio enabled and removal disabled.
|
|
Transmission accepts the ratio in a best-effort call after adding the torrent; its idle-time option
|
|
is not used as total seed time. A failure in that Transmission policy update leaves the tracked
|
|
torrent in place and is logged as a warning.
|
|
|
|
Client-wide ratio, time, idle, and completion settings still apply. qBittorrent and Deluge can
|
|
adopt a duplicate torrent without replacing its existing limits; Transmission attempts to apply
|
|
an explicit ratio to an adopted torrent. BookOrbit does not delete and re-add an adopted torrent,
|
|
reconcile limits across clients, or run a background seed stopper.
|
|
|
|
## Automation
|
|
|
|
Settings > System > Requests > Automation. Everything here is off or unset by default.
|
|
|
|
- **Auto-grab** picks a release without an approver, but only above a minimum score. Below that the
|
|
request waits, and the approver still sees the full ranked list.
|
|
- **Auto-retry** falls back to the next-best release when an automatic grab fails, bounded by a
|
|
maximum number of attempts per request.
|
|
- **Auto-search** re-searches an approved request nothing was found for. Without it a request is
|
|
searched exactly once, and a book whose first release is posted next month waits forever. The
|
|
interval doubles for each week a request has been waiting, up to a cap, and stops entirely after
|
|
a configurable age.
|
|
- **Import checking** scores what landed against what was asked for. Below the threshold the file
|
|
waits in the Book Dock and the request reads "needs review", where a person either files it
|
|
anyway or discards it. Switching this off files whatever was downloaded straight into the target
|
|
library.
|
|
- **Import formats** decides what to keep when one release carries the same book several times
|
|
over: every format, or only the target library's preferred one. A multipart audiobook is never
|
|
affected, since its parts are one book rather than competing editions.
|
|
- **Default destinations** are per medium, and are the lowest rung of the ladder: a requester's own
|
|
pinned destination and an explicit choice at request or approval time both win over them. Without
|
|
one, a request that names no library can never be approved.
|
|
- **Release profiles** are an ordered tier list per medium describing the edition you want. Empty
|
|
is the ordinary state and disengages the tier axis entirely, leaving auto-grab decided by score.
|
|
|
|
## The lifecycle
|
|
|
|
```
|
|
pending -> approved -> searching -> grabbed -> downloading -> importing -> available
|
|
```
|
|
|
|
- **pending**: waiting on an approver. Auto-approval and self-serve both skip it.
|
|
- **needs_review**: the import scored below the threshold and is sitting in the Book Dock. Two ways
|
|
out: file it anyway, or discard it, which removes the dock entry and fails the request.
|
|
- **failed**: nothing could be downloaded, or a person discarded the import. Still grabbable, so a
|
|
different release can be tried.
|
|
- **rejected** / **cancelled**: settled by a person. A settled work can be requested again.
|
|
|
|
One live request per work. A second person asking for the same book is attached to the existing
|
|
request as a subscriber rather than opening a second one, and can leave it again from the request's
|
|
own menu.
|
|
|
|
## Troubleshooting
|
|
|
|
**"No sources are enabled"** on the requests page: either nothing is configured, or every row is
|
|
switched off. The notice says which.
|
|
|
|
**Requests sit at `approved` and nothing happens**: auto-grab is off, which is the default. Either
|
|
an approver opens the release picker, or auto-grab is switched on with a minimum score.
|
|
|
|
**A grab is refused with a path error**: the client has no path mapping, or the download directory
|
|
resolved outside the one it has. Add or widen the mapping under Settings > System > Requests.
|
|
|
|
**Credentials will not save**: `BOOK_REQUEST_ENCRYPTION_KEY` is unset or is not 64 hex characters.
|
|
|
|
**A source shows "Searches failing" but tests fine**: the address answers a capabilities call and
|
|
refuses searches. Usually a rate limit, an expired credential, or categories that do not exist on
|
|
that indexer.
|
|
|
|
## Related
|
|
|
|
- [Development guide](DEVELOPMENT.md)
|
|
- [Testing guide](TESTING.md)
|