From f981b7a338a3282b18683dd45fd1fd5868f6abf8 Mon Sep 17 00:00:00 2001 From: zPlus Date: Sat, 16 Sep 2023 07:47:59 +0200 Subject: [PATCH] Add support for OPDS. --- app.py | 29 ++++++++++ pages/templates/library/opds/books.tpl | 76 ++++++++++++++++++++++++ pages/templates/library/opds/others.tpl | 77 +++++++++++++++++++++++++ pages/templates/library/opds/root.tpl | 28 +++++++++ 4 files changed, 210 insertions(+) create mode 100644 pages/templates/library/opds/books.tpl create mode 100644 pages/templates/library/opds/others.tpl create mode 100644 pages/templates/library/opds/root.tpl diff --git a/app.py b/app.py index dad8177..d896fb6 100755 --- a/app.py +++ b/app.py @@ -87,6 +87,35 @@ def static(filename): return bottle.static_file(filename, root='./static/') +@bottle.get('/library/opds.xml', name='library_opds') +def library_opds(): + """ + Serve OPDS Atom RSS feeds + """ + + #response.content_type = 'text/xml; charset=utf-8' + return template('templates/library/opds/root.tpl') + +@bottle.get('/library/opds/books.xml', name='library_opds_books') +def library_opds_books(): + """ + Serve OPDS Atom RSS feeds. + Items of type "books" only + """ + + #response.content_type = 'text/xml; charset=utf-8' + return template('templates/library/opds/books.tpl') + +@bottle.get('/library/opds/others.xml', name='library_opds_others') +def library_opds_others(): + """ + Serve OPDS Atom RSS feeds. + Uncategorized items only + """ + + #response.content_type = 'text/xml; charset=utf-8' + return template('templates/library/opds/others.tpl') + @bottle.get('/library/', name='library_item') def library_item(item_id): """ diff --git a/pages/templates/library/opds/books.tpl b/pages/templates/library/opds/books.tpl new file mode 100644 index 0000000..ca6f780 --- /dev/null +++ b/pages/templates/library/opds/books.tpl @@ -0,0 +1,76 @@ + + +{% set data = query(""" + PREFIX library: + PREFIX license: + + CONSTRUCT { + ?item library:title ?title; + library:author ?author ; + library:license ?license . + ?license license:id ?license_id ; + license:name ?license_name . + } + WHERE { + ?item library:type 'book' ; + library:title ?title ; + library:author ?author ; + library:license ?license . + + OPTIONAL { + ?license license:id ?license_id_optional ; + license:name ?license_name_optional . + } + + BIND(COALESCE(?license_id_optional, SUBSTR(STR(?license), 14)) AS ?license_id) + BIND(COALESCE(?license_name_optional, SUBSTR(STR(?license), 14)) AS ?license_name) + } + """, + { + '@context': { + 'library': 'dokk:library:', + 'license': 'dokk:license:', + 'library:author': { '@container': '@set' }, + 'library:license': { '@container': '@set' } + }, + 'library:title': {} + }) +%} + + + + + + + urn:uuid:1ad42a21-f98f-44a9-b37a-7c4496ab661d + DOKK Library Books + {{ now() }} + + DOKK + https://dokk.org + + + {% for item in data["@graph"]|sort(attribute="library:title") %} + + {{ item['library:title'] }} + + {% for author in item["library:author"]|sort() %} + + {{ author }} + + {% endfor%} + + {% for license in item["library:license"]|sort(attribute="license:id") %} + {{ license['license:id'] }} + {% endfor%} + + + + + + + + {% endfor %} + diff --git a/pages/templates/library/opds/others.tpl b/pages/templates/library/opds/others.tpl new file mode 100644 index 0000000..d9429d2 --- /dev/null +++ b/pages/templates/library/opds/others.tpl @@ -0,0 +1,77 @@ + + +{% set data = query(""" + PREFIX library: + PREFIX license: + + CONSTRUCT { + ?item library:title ?title; + library:author ?author ; + library:license ?license . + ?license license:id ?license_id ; + license:name ?license_name . + } + WHERE { + ?item library:title ?title ; + library:author ?author ; + library:license ?license . + + FILTER(NOT EXISTS { ?item library:type ?item_type }) + + OPTIONAL { + ?license license:id ?license_id_optional ; + license:name ?license_name_optional . + } + + BIND(COALESCE(?license_id_optional, SUBSTR(STR(?license), 14)) AS ?license_id) + BIND(COALESCE(?license_name_optional, SUBSTR(STR(?license), 14)) AS ?license_name) + } + """, + { + '@context': { + 'library': 'dokk:library:', + 'license': 'dokk:license:', + 'library:author': { '@container': '@set' }, + 'library:license': { '@container': '@set' } + }, + 'library:title': {} + }) +%} + + + + + + + urn:uuid:98d6aff1-0df9-4229-8c6e-2ab0ebece9e1 + DOKK Library Other Materials + {{ now() }} + + DOKK + https://dokk.org + + + {% for item in data["@graph"]|sort(attribute="library:title") %} + + {{ item['library:title'] }} + + {% for author in item["library:author"]|sort() %} + + {{ author }} + + {% endfor%} + + {% for license in item["library:license"]|sort(attribute="license:id") %} + {{ license['license:id'] }} + {% endfor%} + + + + + + + + {% endfor %} + diff --git a/pages/templates/library/opds/root.tpl b/pages/templates/library/opds/root.tpl new file mode 100644 index 0000000..e4314a4 --- /dev/null +++ b/pages/templates/library/opds/root.tpl @@ -0,0 +1,28 @@ + + + + urn:uuid:37a3bc53-cce9-47a2-b557-2c2d5b73d915 + DOKK Library + {{ now() }} + + DOKK + https://dokk.org + + + + + + Books + + {{ now() }} + urn:uuid:1ad42a21-f98f-44a9-b37a-7c4496ab661d + + + Other Materials + + {{ now() }} + urn:uuid:98d6aff1-0df9-4229-8c6e-2ab0ebece9e1 + +