Ivan000 commited on
Commit
40d72d0
·
verified ·
1 Parent(s): 528d174

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +19 -34
main.py CHANGED
@@ -30,7 +30,7 @@ def html_to_fb2(title: str, body: str) -> str:
30
  <p>{clean_text}</p>
31
  </section>
32
  </body>
33
- </FictionBook>"""
34
 
35
  # ========== DuckDuckGo Search ==========
36
  def duckduckgo_search(query: str):
@@ -52,54 +52,39 @@ def duckduckgo_search(query: str):
52
  break
53
  return results
54
 
55
- # ========== OPDS Feed Generator ==========
56
- def generate_feed(entries):
57
  ns = "http://www.w3.org/2005/Atom"
58
  ET.register_namespace("", ns)
59
  feed = ET.Element("feed", xmlns=ns)
60
  ET.SubElement(feed, "id").text = "urn:uuid:duckopds-catalog"
61
  ET.SubElement(feed, "title").text = "DuckDuckGo OPDS Catalog"
62
  ET.SubElement(feed, "updated").text = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")
 
 
 
 
 
 
 
 
 
 
 
63
  for entry_info in entries:
64
  entry = ET.SubElement(feed, "entry")
65
  ET.SubElement(entry, "id").text = entry_info['id']
66
  ET.SubElement(entry, "title").text = entry_info['title']
67
  ET.SubElement(entry, "updated").text = entry_info['updated']
68
  ET.SubElement(entry, "link", entry_info['link'])
 
69
  return ET.tostring(feed, encoding="utf-8", xml_declaration=True)
70
 
71
  # ========== Routes ==========
72
  @app.get("/opds", include_in_schema=False)
73
- def root_opds() -> Response:
74
- # Only search section
75
- entries = [{
76
- 'id': 'urn:uuid:duckopds-search-section',
77
- 'title': 'Search',
78
- 'updated': datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ"),
79
- 'link': {
80
- 'rel': 'subsection',
81
- 'href': '/opds', # self endpoint handles search form if no q
82
- 'type': 'application/atom+xml;profile=opds-catalog;kind=search'
83
- }
84
- }]
85
- xml_data = generate_feed(entries)
86
- return Response(content=xml_data,
87
- media_type="application/atom+xml;profile=opds-catalog;kind=navigation")
88
-
89
- @app.get("/opds")
90
- def opds_search(q: Optional[str] = Query(None, description="Search query")) -> Response:
91
  entries = []
92
- # Always include search entry at top
93
- entries.append({
94
- 'id': 'urn:uuid:duckopds-search-section',
95
- 'title': 'Search',
96
- 'updated': datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ"),
97
- 'link': {
98
- 'rel': 'subsection',
99
- 'href': '/opds',
100
- 'type': 'application/atom+xml;profile=opds-catalog;kind=search'
101
- }
102
- })
103
  if q:
104
  results = duckduckgo_search(q)
105
  for title, url in results:
@@ -113,8 +98,8 @@ def opds_search(q: Optional[str] = Query(None, description="Search query")) -> R
113
  'type': 'application/fb2+xml'
114
  }
115
  })
116
- xml_data = generate_feed(entries)
117
- kind = 'acquisition' if q else 'search'
118
  return Response(content=xml_data,
119
  media_type=f"application/atom+xml;profile=opds-catalog;kind={kind}")
120
 
 
30
  <p>{clean_text}</p>
31
  </section>
32
  </body>
33
+ </FictionBook>"""
34
 
35
  # ========== DuckDuckGo Search ==========
36
  def duckduckgo_search(query: str):
 
52
  break
53
  return results
54
 
55
+ # ========== OPDS Feed Generation ==========
56
+ def create_feed(entries: list, templated: bool, q: Optional[str]) -> bytes:
57
  ns = "http://www.w3.org/2005/Atom"
58
  ET.register_namespace("", ns)
59
  feed = ET.Element("feed", xmlns=ns)
60
  ET.SubElement(feed, "id").text = "urn:uuid:duckopds-catalog"
61
  ET.SubElement(feed, "title").text = "DuckDuckGo OPDS Catalog"
62
  ET.SubElement(feed, "updated").text = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")
63
+
64
+ # OpenSearch templated search link
65
+ link_attrs = {
66
+ "rel": "search",
67
+ "type": "application/atom+xml;profile=opds-catalog;kind=search",
68
+ "href": "/opds?q={searchTerms}",
69
+ "templated": "true"
70
+ }
71
+ ET.SubElement(feed, "link", link_attrs)
72
+
73
+ # Add entries for search results
74
  for entry_info in entries:
75
  entry = ET.SubElement(feed, "entry")
76
  ET.SubElement(entry, "id").text = entry_info['id']
77
  ET.SubElement(entry, "title").text = entry_info['title']
78
  ET.SubElement(entry, "updated").text = entry_info['updated']
79
  ET.SubElement(entry, "link", entry_info['link'])
80
+
81
  return ET.tostring(feed, encoding="utf-8", xml_declaration=True)
82
 
83
  # ========== Routes ==========
84
  @app.get("/opds", include_in_schema=False)
85
+ def opds(q: Optional[str] = Query(None, alias="q", description="Search query")) -> Response:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  entries = []
87
+ kind = "search"
 
 
 
 
 
 
 
 
 
 
88
  if q:
89
  results = duckduckgo_search(q)
90
  for title, url in results:
 
98
  'type': 'application/fb2+xml'
99
  }
100
  })
101
+ kind = "acquisition"
102
+ xml_data = create_feed(entries, templated=True, q=q)
103
  return Response(content=xml_data,
104
  media_type=f"application/atom+xml;profile=opds-catalog;kind={kind}")
105