2 Commits

2 changed files with 47 additions and 45 deletions
+46 -44
View File
@@ -1240,6 +1240,52 @@ def opds_reading_list(slug: str, page: int = 1, _=Depends(require_basic)):
return Response(content=xml, media_type="application/atom+xml;profile=opds-catalog")
# ---- OpenSearch (descriptor) + Search results (OPDS 1.x) ----
# NOTE: These MUST be registered before the /opds/{path:path} catch-all below,
# otherwise the catch-all swallows /opds/search and /opds/search.xml.
@app.get("/opds/search.xml", response_class=Response)
def opensearch_description(_=Depends(require_basic)):
tpl = env.get_template("search-description.xml.j2")
xml = tpl.render(base=SERVER_BASE.rstrip("/"))
return Response(content=xml, media_type="application/opensearchdescription+xml")
@app.get("/opds/search", response_class=Response)
def opds_search(query: str | None = Query(None, alias="query"),
page: int | None = Query(None),
request: Request = None,
_=Depends(require_basic)):
term = (query or "").strip()
if not term:
return browse(path="", page=1)
items = PAGE_SIZE
pg = max(1, int(page or 1))
offset = (pg - 1) * items
conn = db.connect()
try:
rows = db.search_q(conn, term, items, offset)
total = db.search_count(conn, term)
finally:
conn.close()
entries_xml = [_entry_xml_from_row(r) for r in rows]
self_href = f"/opds/search?query={quote(term)}&page={pg}"
next_href = f"/opds/search?query={quote(term)}&page={pg+1}" if (offset + len(rows)) < total else None
xml = _feed(
entries_xml,
title=f"Search: {term}",
self_href=self_href,
next_href=next_href,
os_total=total,
os_start=offset + 1 if total > 0 else 0,
os_items=items,
search_href="/opds/search.xml",
start_href_override="/opds",
)
return Response(content=xml, media_type="application/atom+xml;profile=opds-catalog")
# Catch-all browse route - MUST come after specific /opds routes
@app.get("/opds/{path:path}", response_class=Response)
def browse(path: str, page: int = 1, _=Depends(require_basic)):
@@ -1286,50 +1332,6 @@ def browse(path: str, page: int = 1, _=Depends(require_basic)):
def root(_=Depends(require_basic)):
return browse(path="", page=1)
# ---- OpenSearch (descriptor) + Search results (OPDS 1.x) ----
@app.get("/opds/search.xml", response_class=Response)
def opensearch_description(_=Depends(require_basic)):
tpl = env.get_template("search-description.xml.j2")
xml = tpl.render(base=SERVER_BASE.rstrip("/"))
return Response(content=xml, media_type="application/opensearchdescription+xml")
@app.get("/opds/search", response_class=Response)
def opds_search(query: str | None = Query(None, alias="query"),
page: int | None = Query(None),
request: Request = None,
_=Depends(require_basic)):
term = (query or "").strip()
if not term:
return browse(path="", page=1)
items = PAGE_SIZE
pg = max(1, int(page or 1))
offset = (pg - 1) * items
conn = db.connect()
try:
rows = db.search_q(conn, term, items, offset)
total = db.search_count(conn, term)
finally:
conn.close()
entries_xml = [_entry_xml_from_row(r) for r in rows]
self_href = f"/opds/search?query={quote(term)}&page={pg}"
next_href = f"/opds/search?query={quote(term)}&page={pg+1}" if (offset + len(rows)) < total else None
xml = _feed(
entries_xml,
title=f"Search: {term}",
self_href=self_href,
next_href=next_href,
os_total=total,
os_start=offset + 1 if total > 0 else 0,
os_items=items,
search_href="/opds/search.xml",
start_href_override="/opds",
)
return Response(content=xml, media_type="application/atom+xml;profile=opds-catalog")
# -------------------- File endpoints --------------------
def _abspath(rel: str) -> Path:
"""
+1 -1
View File
@@ -2,7 +2,7 @@ services:
comicopds:
build: .
ports:
- "8080:8080"
- "8382:8080"
environment:
CONTENT_BASE_DIR: /library
PAGE_SIZE: "50"