Renamed feed to opds for better compatibility with some readers
added clickable links to feed (should hopefully solve #79) updated readme
This commit is contained in:
parent
e744ccc20e
commit
157a2e6e4a
|
@ -61,23 +61,25 @@
|
|||
{% for author in authors %}
|
||||
<entry>
|
||||
<title>{{author.name}}</title>
|
||||
<!--content type="text">{{author.name}}</content-->
|
||||
<id>{{ url_for('feed_author', name=author.name) }}</id>
|
||||
<link href="{{ url_for('feed_author', name=author.name)}}" type="application/atom+xml;profile=opds-catalog;kind=navigation" rel="subsection"/>
|
||||
<link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_author', name=author.name)}}" />
|
||||
<link type="application/atom+xml" href="{{url_for('feed_author', name=author.name)}}" rel="subsection"/>
|
||||
</entry>
|
||||
{% endfor %}
|
||||
{% for entry in categorys %}
|
||||
<entry>
|
||||
<title>{{entry.name}}</title>
|
||||
<id>{{ url_for('feed_category', name=entry.name) }}</id>
|
||||
<link href="{{ url_for('feed_category', name=entry.name)}}" type="application/atom+xml;profile=opds-catalog;kind=navigation" rel="subsection"/>
|
||||
<link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_category', name=entry.name)}}" />
|
||||
<link type="application/atom+xml" href="{{url_for('feed_category', name=entry.name)}}" rel="subsection"/>
|
||||
</entry>
|
||||
{% endfor %}
|
||||
{% for entry in series %}
|
||||
<entry>
|
||||
<title>{{entry.name}}</title>
|
||||
<id>{{ url_for('feed_series', name=entry.name) }}</id>
|
||||
<link href="{{ url_for('feed_series', name=entry.name)}}" type="application/atom+xml;profile=opds-catalog;kind=navigation" rel="subsection"/>
|
||||
<link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_series', name=entry.name)}}" />
|
||||
<link type="application/atom+xml" href="{{url_for('feed_series', name=entry.name)}}" rel="subsection"/>
|
||||
</entry>
|
||||
{% endfor %}
|
||||
</feed>
|
||||
|
|
|
@ -21,51 +21,55 @@
|
|||
|
||||
<entry>
|
||||
<title>{{_('Hot Books')}}</title>
|
||||
<link rel="http://opds-spec.org/sort/popular"
|
||||
href="{{url_for('feed_hot')}}"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
||||
<link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_hot')}}" />
|
||||
<link type="application/atom+xml" href="{{url_for('feed_hot')}}" rel="http://opds-spec.org/sort/popular"/>
|
||||
<id>{{url_for('feed_hot')}}</id>
|
||||
<content type="text">{{_('Popular publications from this catalog based on Rating.')}}</content>
|
||||
</entry>
|
||||
|
||||
<entry>
|
||||
<title>{{_('New Books')}}</title>
|
||||
<link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_new')}}" />
|
||||
<link rel="http://opds-spec.org/sort/new"
|
||||
href="{{url_for('feed_new')}}"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
||||
type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition"/>
|
||||
<id>{{url_for('feed_new')}}</id>
|
||||
<content type="text">{{_('The latest Books')}}</content>
|
||||
</entry>
|
||||
|
||||
<entry>
|
||||
<title>{{_('Random Books')}}</title>
|
||||
<link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_discover')}}" />
|
||||
<link rel="http://opds-spec.org/featured"
|
||||
href="{{url_for('feed_discover')}}"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
||||
type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition"/>
|
||||
<id>{{url_for('feed_discover')}}</id>
|
||||
<content type="text">{{_('Show Random Books')}}</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<title>{{_('Authors')}}</title>
|
||||
<link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_authorindex')}}" />
|
||||
<link rel="subsection"
|
||||
href="{{url_for('feed_authorindex')}}"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||
type="application/atom+xml;profile=opds-catalog;type=feed;kind=navigation"/>
|
||||
<id>{{url_for('feed_authorindex')}}</id>
|
||||
<content type="text">{{_('Books ordered by Author')}}</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<title>{{_('Category list')}}</title>
|
||||
<link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_categoryindex')}}" />
|
||||
<link rel="subsection"
|
||||
href="{{url_for('feed_categoryindex')}}"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||
type="application/atom+xml;profile=opds-catalog;type=feed;kind=navigation"/>
|
||||
<id>{{url_for('feed_categoryindex')}}</id>
|
||||
<content type="text">{{_('Books ordered by category')}}</content>
|
||||
</entry>
|
||||
<entry>
|
||||
<title>{{_('Series list')}}</title>
|
||||
<link type="application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition" href="{{url_for('feed_seriesindex')}}" />
|
||||
<link rel="subsection"
|
||||
href="{{url_for('feed_seriesindex')}}"
|
||||
type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||
type="application/atom+xml;profile=opds-catalog;type=feed;kind=navigation"/>
|
||||
<id>{{url_for('feed_seriesindex')}}</id>
|
||||
<content type="text">{{_('Books ordered by series')}}</content>
|
||||
</entry>
|
||||
|
|
|
@ -13,21 +13,6 @@
|
|||
<Url type="application/atom+xml"
|
||||
template="{{url_for('feed_search')}}?query={searchTerms}"/>
|
||||
|
||||
<Url type="application/x-suggestions+json"
|
||||
rel="suggestions"
|
||||
template="http://www.gutenberg.org/ebooks/suggest/?query={searchTerms}"/>
|
||||
<!--
|
||||
<Url type="application/rss+xml"
|
||||
template="http://example.com/?q={searchTerms}&pw={startPage?}&format=rss"/>
|
||||
<Image height="64" width="64" type="image/png">http://example.com/websearch.png</Image>
|
||||
<Image height="16" width="16" type="image/vnd.microsoft.icon">http://example.com/websearch.ico</Image>
|
||||
-->
|
||||
|
||||
<!--Query role="example" searchTerms="shakespeare hamlet" />
|
||||
<Query role="example" searchTerms="doyle detective" />
|
||||
<Query role="example" searchTerms="love stories" /-->
|
||||
|
||||
<Attribution>Search Data Copyright 1971-2012, Project Gutenberg, All Rights Reserved.</Attribution>
|
||||
<SyndicationRight>open</SyndicationRight>
|
||||
<Language>de-DE</Language>
|
||||
<OutputEncoding>UTF-8</OutputEncoding>
|
||||
|
|
|
@ -13,17 +13,6 @@
|
|||
<Url type="application/atom+xml"
|
||||
template="{{url_for('feed_search')}}?query={searchTerms}"/>
|
||||
|
||||
<!--
|
||||
<Url type="application/rss+xml"
|
||||
template="http://example.com/?q={searchTerms}&pw={startPage?}&format=rss"/>
|
||||
<Image height="64" width="64" type="image/png">http://example.com/websearch.png</Image>
|
||||
<Image height="16" width="16" type="image/vnd.microsoft.icon">http://example.com/websearch.ico</Image>
|
||||
-->
|
||||
|
||||
<Query role="example" searchTerms="shakespeare hamlet" />
|
||||
<Query role="example" searchTerms="doyle detective" />
|
||||
<Query role="example" searchTerms="love stories" />
|
||||
|
||||
<SyndicationRight>open</SyndicationRight>
|
||||
<Language>de-DE</Language>
|
||||
<OutputEncoding>UTF-8</OutputEncoding>
|
||||
|
|
46
cps/web.py
46
cps/web.py
|
@ -416,7 +416,7 @@ def before_request():
|
|||
g.allow_upload = config.UPLOADING
|
||||
|
||||
|
||||
@app.route("/feed")
|
||||
@app.route("/opds")
|
||||
@requires_basic_auth_if_no_ano
|
||||
def feed_index():
|
||||
if current_user.filter_language() != "all":
|
||||
|
@ -429,7 +429,7 @@ def feed_index():
|
|||
return response
|
||||
|
||||
|
||||
@app.route("/feed/osd")
|
||||
@app.route("/opds/osd")
|
||||
@requires_basic_auth_if_no_ano
|
||||
def feed_osd():
|
||||
xml = render_template('osd.xml')
|
||||
|
@ -438,7 +438,7 @@ def feed_osd():
|
|||
return response
|
||||
|
||||
|
||||
@app.route("/feed/search", methods=["GET"])
|
||||
@app.route("/opds/search", methods=["GET"])
|
||||
@requires_basic_auth_if_no_ano
|
||||
def feed_search():
|
||||
term = request.args.get("query").strip()
|
||||
|
@ -459,7 +459,7 @@ def feed_search():
|
|||
return response
|
||||
|
||||
|
||||
@app.route("/feed/new")
|
||||
@app.route("/opds/new")
|
||||
@requires_basic_auth_if_no_ano
|
||||
def feed_new():
|
||||
off = request.args.get("start_index")
|
||||
|
@ -472,13 +472,13 @@ def feed_new():
|
|||
entries = db.session.query(db.Books).filter(filter).order_by(db.Books.timestamp.desc()).offset(off).limit(
|
||||
config.NEWEST_BOOKS)
|
||||
xml = render_template('feed.xml', entries=entries,
|
||||
next_url="/feed/new?start_index=%d" % (int(config.NEWEST_BOOKS) + int(off)))
|
||||
next_url="/opds/new?start_index=%d" % (int(config.NEWEST_BOOKS) + int(off)))
|
||||
response = make_response(xml)
|
||||
response.headers["Content-Type"] = "application/xml"
|
||||
return response
|
||||
|
||||
|
||||
@app.route("/feed/discover")
|
||||
@app.route("/opds/discover")
|
||||
@requires_basic_auth_if_no_ano
|
||||
def feed_discover():
|
||||
off = request.args.get("start_index")
|
||||
|
@ -490,13 +490,13 @@ def feed_discover():
|
|||
off = 0
|
||||
entries = db.session.query(db.Books).filter(filter).order_by(func.random()).offset(off).limit(config.NEWEST_BOOKS)
|
||||
xml = render_template('feed.xml', entries=entries,
|
||||
next_url="/feed/discover?start_index=%d" % (int(config.NEWEST_BOOKS) + int(off)))
|
||||
next_url="/opds/discover?start_index=%d" % (int(config.NEWEST_BOOKS) + int(off)))
|
||||
response = make_response(xml)
|
||||
response.headers["Content-Type"] = "application/xml"
|
||||
return response
|
||||
|
||||
|
||||
@app.route("/feed/hot")
|
||||
@app.route("/opds/hot")
|
||||
@requires_basic_auth_if_no_ano
|
||||
def feed_hot():
|
||||
off = request.args.get("start_index")
|
||||
|
@ -510,13 +510,13 @@ def feed_hot():
|
|||
off).limit(config.NEWEST_BOOKS)
|
||||
|
||||
xml = render_template('feed.xml', entries=entries,
|
||||
next_url="/feed/hot?start_index=%d" % (int(config.NEWEST_BOOKS) + int(off)))
|
||||
next_url="/opds/hot?start_index=%d" % (int(config.NEWEST_BOOKS) + int(off)))
|
||||
response = make_response(xml)
|
||||
response.headers["Content-Type"] = "application/xml"
|
||||
return response
|
||||
|
||||
|
||||
@app.route("/feed/author")
|
||||
@app.route("/opds/author")
|
||||
@requires_basic_auth_if_no_ano
|
||||
def feed_authorindex():
|
||||
off = request.args.get("start_index")
|
||||
|
@ -528,13 +528,13 @@ def feed_authorindex():
|
|||
off = 0
|
||||
authors = db.session.query(db.Authors).order_by(db.Authors.sort).offset(off).limit(config.NEWEST_BOOKS)
|
||||
xml = render_template('feed.xml', authors=authors,
|
||||
next_url="/feed/author?start_index=%d" % (int(config.NEWEST_BOOKS) + int(off)))
|
||||
next_url="/opds/author?start_index=%d" % (int(config.NEWEST_BOOKS) + int(off)))
|
||||
response = make_response(xml)
|
||||
response.headers["Content-Type"] = "application/xml"
|
||||
return response
|
||||
|
||||
|
||||
@app.route("/feed/author/<name>")
|
||||
@app.route("/opds/author/<name>")
|
||||
@requires_basic_auth_if_no_ano
|
||||
def feed_author(name):
|
||||
off = request.args.get("start_index")
|
||||
|
@ -547,13 +547,13 @@ def feed_author(name):
|
|||
entries = db.session.query(db.Books).filter(db.Books.authors.any(db.Authors.name.like("%" + name + "%"))).filter(
|
||||
filter).offset(off).limit(config.NEWEST_BOOKS)
|
||||
xml = render_template('feed.xml', entries=entries,
|
||||
next_url="/feed/author?start_index=%d" % (int(config.NEWEST_BOOKS) + int(off)))
|
||||
next_url="/opds/author?start_index=%d" % (int(config.NEWEST_BOOKS) + int(off)))
|
||||
response = make_response(xml)
|
||||
response.headers["Content-Type"] = "application/xml"
|
||||
return response
|
||||
|
||||
|
||||
@app.route("/feed/category")
|
||||
@app.route("/opds/category")
|
||||
@requires_basic_auth_if_no_ano
|
||||
def feed_categoryindex():
|
||||
off = request.args.get("start_index")
|
||||
|
@ -561,13 +561,13 @@ def feed_categoryindex():
|
|||
off = 0
|
||||
entries = db.session.query(db.Tags).order_by(db.Tags.name).offset(off).limit(config.NEWEST_BOOKS)
|
||||
xml = render_template('feed.xml', categorys=entries,
|
||||
next_url="/feed/category?start_index=%d" % (int(config.NEWEST_BOOKS) + int(off)))
|
||||
next_url="/opds/category?start_index=%d" % (int(config.NEWEST_BOOKS) + int(off)))
|
||||
response = make_response(xml)
|
||||
response.headers["Content-Type"] = "application/xml"
|
||||
return response
|
||||
|
||||
|
||||
@app.route("/feed/category/<name>")
|
||||
@app.route("/opds/category/<name>")
|
||||
@requires_basic_auth_if_no_ano
|
||||
def feed_category(name):
|
||||
off = request.args.get("start_index")
|
||||
|
@ -580,13 +580,13 @@ def feed_category(name):
|
|||
entries = db.session.query(db.Books).filter(db.Books.tags.any(db.Tags.name.like("%" + name + "%"))).order_by(
|
||||
db.Books.timestamp.desc()).filter(filter).offset(off).limit(config.NEWEST_BOOKS)
|
||||
xml = render_template('feed.xml', entries=entries,
|
||||
next_url="/feed/category?start_index=%d" % (int(config.NEWEST_BOOKS) + int(off)))
|
||||
next_url="/opds/category?start_index=%d" % (int(config.NEWEST_BOOKS) + int(off)))
|
||||
response = make_response(xml)
|
||||
response.headers["Content-Type"] = "application/xml"
|
||||
return response
|
||||
|
||||
|
||||
@app.route("/feed/series")
|
||||
@app.route("/opds/series")
|
||||
@requires_basic_auth_if_no_ano
|
||||
def feed_seriesindex():
|
||||
off = request.args.get("start_index")
|
||||
|
@ -594,13 +594,13 @@ def feed_seriesindex():
|
|||
off = 0
|
||||
entries = db.session.query(db.Series).order_by(db.Series.name).offset(off).limit(config.NEWEST_BOOKS)
|
||||
xml = render_template('feed.xml', series=entries,
|
||||
next_url="/feed/series?start_index=%d" % (int(config.NEWEST_BOOKS) + int(off)))
|
||||
next_url="/opds/series?start_index=%d" % (int(config.NEWEST_BOOKS) + int(off)))
|
||||
response = make_response(xml)
|
||||
response.headers["Content-Type"] = "application/xml"
|
||||
return response
|
||||
|
||||
|
||||
@app.route("/feed/series/<name>")
|
||||
@app.route("/opds/series/<name>")
|
||||
@requires_basic_auth_if_no_ano
|
||||
def feed_series(name):
|
||||
off = request.args.get("start_index")
|
||||
|
@ -613,13 +613,13 @@ def feed_series(name):
|
|||
entries = db.session.query(db.Books).filter(db.Books.series.any(db.Series.name.like("%" + name + "%"))).order_by(
|
||||
db.Books.timestamp.desc()).filter(filter).offset(off).limit(config.NEWEST_BOOKS)
|
||||
xml = render_template('feed.xml', entries=entries,
|
||||
next_url="/feed/series?start_index=%d" % (int(config.NEWEST_BOOKS) + int(off)))
|
||||
next_url="/opds/series?start_index=%d" % (int(config.NEWEST_BOOKS) + int(off)))
|
||||
response = make_response(xml)
|
||||
response.headers["Content-Type"] = "application/xml"
|
||||
return response
|
||||
|
||||
|
||||
@app.route("/feed/download/<int:book_id>/<format>")
|
||||
@app.route("/opds/download/<int:book_id>/<format>")
|
||||
@requires_basic_auth_if_no_ano
|
||||
@download_required
|
||||
def get_opds_download_link(book_id, format):
|
||||
|
@ -1036,7 +1036,7 @@ def get_cover(cover_path):
|
|||
return send_from_directory(os.path.join(config.DB_ROOT, cover_path), "cover.jpg")
|
||||
|
||||
|
||||
@app.route("/feed/cover/<path:cover_path>")
|
||||
@app.route("/opds/cover/<path:cover_path>")
|
||||
@requires_basic_auth_if_no_ano
|
||||
def feed_get_cover(cover_path):
|
||||
return send_from_directory(os.path.join(config.DB_ROOT, cover_path), "cover.jpg")
|
||||
|
|
|
@ -10,6 +10,7 @@ Calibre Web is a web app providing a clean interface for browsing, reading and d
|
|||
- Bootstrap 3 HTML5 interface
|
||||
- User management
|
||||
- Admin interface
|
||||
- User Interface in english, german and french
|
||||
- OPDS feed for eBook reader apps
|
||||
- Filter and search by titles, authors, tags, series and language
|
||||
- Create custom book collection (shelves)
|
||||
|
@ -18,7 +19,7 @@ Calibre Web is a web app providing a clean interface for browsing, reading and d
|
|||
- Restrict eBook download to logged-in users
|
||||
- Support for public user registration
|
||||
- Send eBooks to Kindle devices with the click of a button
|
||||
- Support for reading eBooks directly in the browser
|
||||
- Support for reading eBooks directly in the browser (.txt, .epub, .pdf)
|
||||
- Upload new books in PDF format
|
||||
- Support for Calibre custom columns
|
||||
- Fine grained per-user permissions
|
||||
|
@ -27,7 +28,7 @@ Calibre Web is a web app providing a clean interface for browsing, reading and d
|
|||
|
||||
1. Rename `config.ini.example` to `config.ini` and set `DB_ROOT` to the path of the folder where your Calibre library (metadata.db) lives
|
||||
2. Execute the command: `python cps.py`
|
||||
3. Point your browser to `http://localhost:8083` or `http://localhost:8083/feed` for the OPDS catalog
|
||||
3. Point your browser to `http://localhost:8083` or `http://localhost:8083/opds` for the OPDS catalog
|
||||
|
||||
**Default admin login:**
|
||||
*Username:* admin
|
||||
|
|
Loading…
Reference in New Issue
Block a user