Documentation
¶
Overview ¶
Package opds provides a version-neutral domain model and helpers for building OPDS (Open Publication Distribution System) catalog services.
OPDS is a syndication format for electronic publications. Two wire formats are in wide use:
- OPDS 1.2, an Atom (XML) based format. Universally supported by readers such as Calibre, KOReader, Thorium, FBReader and many others.
- OPDS 2.0, a JSON format built on the Readium Web Publication Manifest.
Both express the same conceptual model, so this library models a catalog once, with version-neutral types, and lets pluggable encoders serialize to either format:
- Package opds the domain model, constants and builders (this package).
- Package opds/opds1 encodes the model to OPDS 1.2 (Atom XML).
- Package opds/opds2 encodes the model to OPDS 2.0 (JSON).
- Package opds/opensearch generates OpenSearch description documents (1.x search).
- Package opds/opdshttp an embeddable http.Handler tying it together.
To expose a catalog you implement the Source interface (and, optionally, Searcher) and hand it to opds/opdshttp, or drive the encoders directly.
Index ¶
- Constants
- Variables
- type Acquisition
- type AcquisitionRel
- type Author
- type Availability
- type Copies
- type Facet
- type Feed
- func (f *Feed) Add(pubs ...Publication) *Feed
- func (f *Feed) AddFacet(group, title, href, mediaType string, count int, active bool) *Feed
- func (f *Feed) AddGroup(g Group) *Feed
- func (f *Feed) AddNav(title, href, mediaType, rel string) *Feed
- func (f *Feed) AddNavEntry(e NavEntry) *Feed
- func (f *Feed) At(t time.Time) *Feed
- func (f *Feed) By(name string) *Feed
- func (f *Feed) IsAcquisition() bool
- func (f *Feed) Link(rel, href, mediaType string) *Feed
- func (f *Feed) Next(href, mediaType string) *Feed
- func (f *Feed) Page(total, perPage, start int) *Feed
- func (f *Feed) Prev(href, mediaType string) *Feed
- func (f *Feed) SearchLink(href, mediaType string, templated bool) *Feed
- func (f *Feed) Self(href, mediaType string) *Feed
- func (f *Feed) Start(href string) *Feed
- func (f *Feed) SubtitledBy(s string) *Feed
- func (f *Feed) Up(href, mediaType string) *Feed
- type FeedRequest
- type Group
- type Holds
- type Image
- type IndirectAcquisition
- type Link
- type NavEntry
- type Price
- type Publication
- func (p *Publication) About(name string) *Publication
- func (p *Publication) Acquire(a Acquisition) *Publication
- func (p *Publication) Author(a Author) *Publication
- func (p *Publication) Borrow(href, mediaType, state string) *Publication
- func (p *Publication) Buy(href, mediaType, currency string, value float64) *Publication
- func (p *Publication) By(name string) *Publication
- func (p *Publication) Categorize(name, code, scheme string) *Publication
- func (p *Publication) Cover(href, mediaType string) *Publication
- func (p *Publication) Describe(s string) *Publication
- func (p *Publication) From(publisher string) *Publication
- func (p *Publication) ISBN(isbn string) *Publication
- func (p *Publication) Identifier(id string) *Publication
- func (p *Publication) In(langs ...string) *Publication
- func (p *Publication) Link(rel, href, mediaType string) *Publication
- func (p *Publication) OpenAccess(href, mediaType string) *Publication
- func (p *Publication) PartOf(series string, position float64) *Publication
- func (p *Publication) PublishedAt(t time.Time) *Publication
- func (p *Publication) Sample(href, mediaType string) *Publication
- func (p *Publication) Summarize(s string) *Publication
- func (p *Publication) Thumbnail(href, mediaType string) *Publication
- func (p *Publication) UpdatedAt(t time.Time) *Publication
- type SearchDescription
- type SearchRequest
- type Searcher
- type Series
- type Source
- type Subject
- type Version
Constants ¶
const ( MediaTypeNavigation = "application/atom+xml;profile=opds-catalog;kind=navigation" // MediaTypeAcquisition is the media type of an OPDS 1.x acquisition feed. MediaTypeAcquisition = "application/atom+xml;profile=opds-catalog;kind=acquisition" // MediaTypeEntry is the media type of a standalone OPDS 1.x entry document. MediaTypeEntry = "application/atom+xml;type=entry;profile=opds-catalog" // MediaTypeFeed is the media type of an OPDS 2.0 feed. MediaTypeFeed = "application/opds+json" // MediaTypePublication is the media type of an OPDS 2.0 publication. MediaTypePublication = "application/opds-publication+json" // MediaTypeOpenSearch is the media type of an OpenSearch description document. MediaTypeOpenSearch = "application/opensearchdescription+xml" )
Media types used by OPDS catalogs.
const ( NSAtom = "http://www.w3.org/2005/Atom" NSOPDS = "http://opds-spec.org/2010/catalog" NSDCTerms = "http://purl.org/dc/terms/" NSOpenSearch = "http://a9.com/-/spec/opensearch/1.1/" NSThreading = "http://purl.org/syndication/thread/1.0" )
XML namespace URIs used by OPDS 1.x (Atom) feeds.
const ( RelSelf = "self" RelStart = "start" RelUp = "up" RelNext = "next" RelPrevious = "previous" RelFirst = "first" RelLast = "last" RelSearch = "search" RelAlternate = "alternate" RelRelated = "related" RelSubsection = "subsection" RelCollection = "collection" RelImage = "http://opds-spec.org/image" RelThumbnail = "http://opds-spec.org/image/thumbnail" RelFacet = "http://opds-spec.org/facet" RelGroup = "http://opds-spec.org/group" RelSortNew = "http://opds-spec.org/sort/new" RelSortPopular = "http://opds-spec.org/sort/popular" RelFeatured = "http://opds-spec.org/featured" RelRecommended = "http://opds-spec.org/recommended" RelShelf = "http://opds-spec.org/shelf" RelSubscriptions = "http://opds-spec.org/subscriptions" RelCrawlable = "http://opds-spec.org/crawlable" )
Standard (RFC 5988 / Atom) and OPDS-specific link relations.
The structural relations (RelSelf, RelStart, ...) are bare tokens shared by both OPDS versions. The relations carrying the "http://opds-spec.org/" prefix are OPDS-specific and identical across versions 1.2 and 2.0.
const ( // StateAvailable means the publication can be borrowed immediately. StateAvailable = "available" StateUnavailable = "unavailable" // StateReserved means the user holds a reservation in the queue. StateReserved = "reserved" // StateReady means a hold is ready to be borrowed by the user. StateReady = "ready" )
Availability states for library lending (used by AcquireBorrow links).
Variables ¶
var ErrNotFound = errors.New("opds: not found")
ErrNotFound is returned by a Source when a requested feed or publication does not exist. The HTTP layer maps it to 404 Not Found.
Functions ¶
This section is empty.
Types ¶
type Acquisition ¶
type Acquisition struct {
// Rel is the acquisition relation. Defaults to AcquireGeneric when empty.
Rel AcquisitionRel
// Href is the acquisition URL. Required.
Href string
// Type is the media type acquired. For indirect acquisition this is the
// media type of the intermediate resource (e.g. an HTML purchase page).
Type string
// Title is an optional label.
Title string
// Prices lists the cost(s) of acquisition. Required for AcquireBuy.
Prices []Price
// Indirect describes formats obtained after following the link
// (e.g. an LCP license that yields an EPUB).
Indirect []IndirectAcquisition
// Availability describes lending availability (AcquireBorrow).
Availability *Availability
// Holds describes the reservation queue (library lending).
Holds *Holds
// Copies describes copy counts (library lending).
Copies *Copies
}
Acquisition describes one way to obtain a publication.
type AcquisitionRel ¶
type AcquisitionRel string
AcquisitionRel identifies how a publication may be acquired. The values are the full relation URIs used (identically) in OPDS 1.2 and 2.0.
const ( // AcquireGeneric is a generic acquisition relation; the acquisition method // is unspecified. AcquireGeneric AcquisitionRel = "http://opds-spec.org/acquisition" // AcquireOpenAccess is freely accessible without payment or authentication. AcquireOpenAccess AcquisitionRel = "http://opds-spec.org/acquisition/open-access" // AcquireBuy must be purchased; carries at least one Price. AcquireBuy AcquisitionRel = "http://opds-spec.org/acquisition/buy" // AcquireBorrow is borrowed for a limited period (library lending). AcquireBorrow AcquisitionRel = "http://opds-spec.org/acquisition/borrow" // AcquireSample provides a sample or preview of the publication. AcquireSample AcquisitionRel = "http://opds-spec.org/acquisition/sample" // AcquireSubscribe is acquired through a subscription. AcquireSubscribe AcquisitionRel = "http://opds-spec.org/acquisition/subscribe" )
type Author ¶
type Author struct {
// Name is the display name. Required.
Name string
// URI optionally links to the author (a feed of their works, a homepage).
URI string
// SortAs is an optional collation key (2.0).
SortAs string
}
Author identifies a person or organization responsible for a feed or publication.
type Availability ¶
type Availability struct {
// State is one of StateAvailable, StateUnavailable, StateReserved, StateReady.
State string
// Since is when the current state began (e.g. loan start). Optional.
Since time.Time
// Until is when the current state ends (e.g. loan or hold expiry). Optional.
Until time.Time
}
Availability describes whether a borrowable publication can currently be obtained.
type Copies ¶
type Copies struct {
// Total is the number of copies owned.
Total int
// Available is the number of copies currently available to borrow.
Available int
}
Copies describes copy counts for a borrowable publication.
type Facet ¶
type Facet struct {
// Group names the facet group this facet belongs to (e.g. "Language").
Group string
// Title is the facet label (e.g. "French"). Required.
Title string
// Href is the URL of the filtered/sorted feed. Required.
Href string
// Type is the media type of the target feed.
Type string
// Count is an optional hint at the number of items behind the facet.
Count int
// Active marks the facet as the one currently applied.
Active bool
}
Facet is an alternate filtered or sorted view of a feed, grouped with other facets under a common Group label.
type Feed ¶
type Feed struct {
// ID is a stable, unique identifier for the feed (e.g. a URN or URL).
// Maps to atom:id in 1.2; used as metadata.identifier in 2.0.
ID string
// Title is the human-readable feed title. Required by both versions.
Title string
// Subtitle is an optional secondary title (atom:subtitle).
Subtitle string
// Updated is the last time the feed changed. Defaults to time.Now when zero.
Updated time.Time
// Icon is an optional URL to a feed icon (atom:icon).
Icon string
// Authors describe who is responsible for the feed.
Authors []Author
// Links are feed-level links (self, start, up, next, search, ...).
Links []Link
Navigation []NavEntry
// Publications holds the entries of an acquisition feed.
Publications []Publication
// Groups partition an acquisition feed into labelled sections (2.0 groups;
// emitted via opds:group links in 1.2).
Groups []Group
// Facets describe alternate filtered/sorted views of the same feed.
Facets []Facet
// Pagination. Zero values are treated as "unset" and omitted.
TotalResults int // total number of items across all pages
ItemsPerPage int // number of items per page
StartIndex int // 1-based index of the first item on this page (1.x)
CurrentPage int // 1-based page number (2.0)
}
Feed is a version-neutral OPDS feed (an Atom feed in 1.2, a collection in 2.0). A feed is either a navigation feed (Navigation populated) or an acquisition feed (Publications populated); both may be present but most clients expect one or the other.
func (*Feed) Add ¶
func (f *Feed) Add(pubs ...Publication) *Feed
Add appends one or more publications to the feed.
func (*Feed) AddNavEntry ¶
AddNavEntry appends a fully specified navigation entry.
func (*Feed) IsAcquisition ¶
IsAcquisition reports whether the feed is an acquisition feed (contains publications) as opposed to a navigation feed. It is used to select the correct OPDS 1.x media type.
func (*Feed) Page ¶
Page sets pagination links and counters. self/next/prev hrefs that are empty are skipped. total and perPage are recorded as counters; start is the 1-based index of the first item on this page.
func (*Feed) SearchLink ¶
SearchLink adds a search link. For 1.x mediaType should be MediaTypeOpenSearch; for 2.0 use MediaTypeFeed with a templated href.
func (*Feed) SubtitledBy ¶
SubtitledBy sets the feed subtitle.
type FeedRequest ¶
type FeedRequest struct {
// ID identifies the requested feed (empty for the root). For the HTTP layer
// this is the path segment after the feed prefix.
ID string
// Page is the requested 1-based page number (1 if unspecified).
Page int
// Version is the OPDS version the response will be encoded in, as
// negotiated by the caller. Implementations may use it to tailor hrefs.
Version Version
// BaseURL is the absolute base URL of the catalog (scheme://host), if known.
BaseURL string
// Query holds the raw query parameters of the request (facet selections,
// sort orders, and so on).
Query url.Values
}
FeedRequest carries the parameters of a request for a feed.
type Group ¶
type Group struct {
// Title is the section label.
Title string
// Href is an optional link to the full feed for this group.
Href string
// Type is the media type of the group's full feed.
Type string
// Rel is an optional relation for the group's link.
Rel string
Navigation []NavEntry
// Publications holds the group's publications.
Publications []Publication
}
Group is a labelled section of a feed (2.0 groups). A group typically links to a fuller feed via Href and shows a preview of its contents.
type Holds ¶
type Holds struct {
// Total is the number of holds placed.
Total int
// Position is the requesting user's position in the queue, if known.
Position *int
}
Holds describes a reservation queue for a borrowable publication.
type Image ¶
type Image struct {
// Href is the image URL. Required.
Href string
// Type is the image media type (e.g. "image/jpeg").
Type string
// Width and Height are optional pixel dimensions (2.0).
Width, Height int
// Thumbnail marks this as a reduced-size image. In 1.2 it selects the
// image/thumbnail relation; in 2.0 all images share the images collection.
Thumbnail bool
}
Image is a cover image or thumbnail.
type IndirectAcquisition ¶
type IndirectAcquisition struct {
// Type is the media type that will ultimately be acquired.
Type string
// Child holds further levels of indirection.
Child []IndirectAcquisition
}
IndirectAcquisition declares a media type obtainable after following an acquisition link. Entries may nest to express multiple levels of indirection.
type Link ¶
type Link struct {
// Rel is the link relation (see the Rel* constants).
Rel string
// Href is the target URL or, when Templated is true, a URI template.
Href string
// Type is the media type of the target.
Type string
// Title is an optional human-readable label.
Title string
// Templated indicates Href is an RFC 6570 URI template (2.0 only).
Templated bool
}
Link is a generic hypermedia link.
type NavEntry ¶
type NavEntry struct {
ID string
Title string
Updated time.Time
Content string
Href string
Type string
// RelSubsection, RelFeatured). Defaults to RelSubsection when empty.
Rel string
Images []Image
}
NavEntry is an entry in a navigation feed: a link to another feed or resource, with a title and optional description.
type Price ¶
type Price struct {
// Currency is an ISO 4217 currency code (e.g. "USD").
Currency string
// Value is the amount.
Value float64
}
Price is a monetary amount in a specific currency.
type Publication ¶
type Publication struct {
// ID is a stable, unique identifier (atom:id; metadata.identifier in 2.0).
ID string
// Title is the publication title. Required.
Title string
// SortAs is an optional collation key for the title (2.0 metadata.sortAs).
SortAs string
// Updated is when the entry last changed (atom:updated; metadata.modified).
Updated time.Time
// Published is the publication date (dcterms:issued; metadata.published).
Published time.Time
// Languages are ISO 639 language codes.
Languages []string
// Identifiers are external identifiers such as ISBN URNs (dcterms:identifier).
Identifiers []string
// Publisher is the publishing entity.
Publisher string
// Authors are the publication's authors.
Authors []Author
// Contributors are other contributors (editors, translators, ...).
Contributors []Author
// Subjects are categories/genres.
Subjects []Subject
// Summary is a short plain-text description (atom:summary).
Summary string
// Description is a longer description, may contain HTML (atom:content).
Description string
// Rights is a copyright/licensing statement (atom:rights).
Rights string
// Series places the publication within a series (2.0 belongsTo.series).
Series *Series
// Images are cover images. By convention the first is the primary cover.
Images []Image
// Acquisitions are the ways the publication can be acquired. An acquisition
// feed entry should have at least one.
Acquisitions []Acquisition
// Links are additional links (self, alternate to the full entry, related, ...).
Links []Link
}
Publication is a single catalog entry describing a publication and how to acquire it.
func NewPublication ¶
func NewPublication(id, title string) *Publication
NewPublication returns a publication with the given id and title and Updated set to now.
func (*Publication) About ¶
func (p *Publication) About(name string) *Publication
About adds a subject/category.
func (*Publication) Acquire ¶
func (p *Publication) Acquire(a Acquisition) *Publication
Acquire appends a fully specified acquisition.
func (*Publication) Author ¶
func (p *Publication) Author(a Author) *Publication
Author adds a fully specified author.
func (*Publication) Borrow ¶
func (p *Publication) Borrow(href, mediaType, state string) *Publication
Borrow adds a borrow acquisition with the given availability state.
func (*Publication) Buy ¶
func (p *Publication) Buy(href, mediaType, currency string, value float64) *Publication
Buy adds a buy acquisition with a single price.
func (*Publication) Categorize ¶
func (p *Publication) Categorize(name, code, scheme string) *Publication
Categorize adds a subject with a controlled-vocabulary code and scheme.
func (*Publication) Cover ¶
func (p *Publication) Cover(href, mediaType string) *Publication
Cover adds a primary cover image.
func (*Publication) Describe ¶
func (p *Publication) Describe(s string) *Publication
Describe sets the long description.
func (*Publication) From ¶
func (p *Publication) From(publisher string) *Publication
From sets the publisher.
func (*Publication) ISBN ¶
func (p *Publication) ISBN(isbn string) *Publication
ISBN adds an ISBN identifier as a URN.
func (*Publication) Identifier ¶
func (p *Publication) Identifier(id string) *Publication
Identifier adds a raw identifier.
func (*Publication) In ¶
func (p *Publication) In(langs ...string) *Publication
In sets one or more languages.
func (*Publication) Link ¶
func (p *Publication) Link(rel, href, mediaType string) *Publication
Link adds an arbitrary link to the publication.
func (*Publication) OpenAccess ¶
func (p *Publication) OpenAccess(href, mediaType string) *Publication
OpenAccess adds an open-access (free download) acquisition.
func (*Publication) PartOf ¶
func (p *Publication) PartOf(series string, position float64) *Publication
PartOf places the publication in a series at the given position.
func (*Publication) PublishedAt ¶
func (p *Publication) PublishedAt(t time.Time) *Publication
PublishedAt sets the publication date.
func (*Publication) Sample ¶
func (p *Publication) Sample(href, mediaType string) *Publication
Sample adds a sample/preview acquisition.
func (*Publication) Summarize ¶
func (p *Publication) Summarize(s string) *Publication
Summarize sets the short summary.
func (*Publication) Thumbnail ¶
func (p *Publication) Thumbnail(href, mediaType string) *Publication
Thumbnail adds a thumbnail image.
func (*Publication) UpdatedAt ¶
func (p *Publication) UpdatedAt(t time.Time) *Publication
UpdatedAt sets the entry's last-modified time.
type SearchDescription ¶
type SearchDescription struct {
// ShortName is a brief name for the search engine (OpenSearch ShortName).
ShortName string
// Description is a human-readable description of the search.
Description string
// Template is the search URL template using RFC 6570 / OpenSearch syntax,
// e.g. "/search?q={searchTerms}". If it contains no parameters the library
// appends "?q={searchTerms}". Extra params such as {author} and {title}
// are advertised when present.
Template string
}
SearchDescription describes a catalog's search interface. It drives the OpenSearch description document (1.x) and the templated search link (2.0).
type SearchRequest ¶
type SearchRequest struct {
// Terms is the free-text query (the OpenSearch {searchTerms}).
Terms string
// Author optionally narrows the search by author.
Author string
// Title optionally narrows the search by title.
Title string
// Page is the requested 1-based page number (1 if unspecified).
Page int
// Version is the negotiated OPDS version of the response.
Version Version
// BaseURL is the absolute base URL of the catalog, if known.
BaseURL string
// Query holds the raw query parameters of the request.
Query url.Values
}
SearchRequest carries the parameters of a search.
type Searcher ¶
type Searcher interface {
// Search returns a feed of results for the given request.
Search(ctx context.Context, req SearchRequest) (*Feed, error)
// SearchDescription returns metadata describing the search interface,
// used to generate the OpenSearch document and the 2.0 search link.
SearchDescription() SearchDescription
}
Searcher is an optional interface a Source may also implement to support search. When present, the HTTP layer advertises a search link and routes search requests to it.
type Series ¶
type Series struct {
// Name is the series title.
Name string
// Position is the publication's position in the series (0 if unknown).
Position float64
}
Series places a publication within a sequence.
type Source ¶
type Source interface {
// Root returns the catalog's root feed (usually a navigation feed).
Root(ctx context.Context, req FeedRequest) (*Feed, error)
// Feed returns the feed identified by req.ID. It should return ErrNotFound
// if no such feed exists.
Feed(ctx context.Context, req FeedRequest) (*Feed, error)
// Publication returns the full entry for a single publication. It should
// return ErrNotFound if no such publication exists. A Source that never
// serves standalone publication documents may return ErrNotFound always.
Publication(ctx context.Context, id string) (*Publication, error)
}
Source is the backend a catalog implements. It returns version-neutral Feed and Publication values; the library handles serialization to OPDS 1.2 or 2.0, content negotiation, and HTTP wiring.
Implementations are responsible for the URLs (hrefs) they place in feeds: the library does not rewrite them. Use FeedRequest.PageURL and the BaseURL to build consistent links, or construct them however suits the backend.
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
bookstore
command
Command bookstore is a runnable example OPDS catalog backed by an in-memory list of books.
|
Command bookstore is a runnable example OPDS catalog backed by an in-memory list of books. |
|
Package opds1 encodes the version-neutral opds model to OPDS 1.2 feeds and entry documents, serialized as Atom (XML) with the OPDS extension namespaces.
|
Package opds1 encodes the version-neutral opds model to OPDS 1.2 feeds and entry documents, serialized as Atom (XML) with the OPDS extension namespaces. |
|
Package opds2 encodes the version-neutral opds model to OPDS 2.0, the JSON format built on the Readium Web Publication Manifest.
|
Package opds2 encodes the version-neutral opds model to OPDS 2.0, the JSON format built on the Readium Web Publication Manifest. |
|
Package opdshttp provides an embeddable http.Handler that exposes an opds.Source as an OPDS catalog, handling routing, content negotiation between OPDS 1.2 and 2.0, pagination, and search.
|
Package opdshttp provides an embeddable http.Handler that exposes an opds.Source as an OPDS catalog, handling routing, content negotiation between OPDS 1.2 and 2.0, pagination, and search. |
|
Package opensearch generates OpenSearch description documents, the mechanism OPDS 1.x catalogs use to advertise their search interface.
|
Package opensearch generates OpenSearch description documents, the mechanism OPDS 1.x catalogs use to advertise their search interface. |