vomebook commited on
Commit
06776eb
·
verified ·
1 Parent(s): 9e90535

feat: add progressive EPUB chapter reader

Browse files
Files changed (1) hide show
  1. app.py +12 -4
app.py CHANGED
@@ -120,7 +120,13 @@ def decode_reader_assets(raw: bytes) -> dict:
120
  mode = entry.get("m")
121
  if mode not in ("p", "e", "d", "h", "a", "v") or not isinstance(path, str) or not re.fullmatch(r"objects/[0-9a-f]{2}/[0-9a-f]{64}/(?:[a-z0-9-]+/)?(?:document\.pdf|book\.epub|document\.docx|document\.html|audio\.mp3|video\.mp4)", path):
122
  continue
123
- clean[key] = {"s": 2, "m": mode, "p": path}
 
 
 
 
 
 
124
  else:
125
  clean[key] = {"s": 4}
126
  return {"v": 1, "f": clean}
@@ -391,7 +397,7 @@ def validate_voiceofml_source_url(url: str) -> str:
391
 
392
 
393
  READER_ASSET_SOURCE_RE = re.compile(
394
- r"^/datasets/vomebook/Reader-Assets/resolve/main/objects/[0-9a-f]{2}/[0-9a-f]{64}/(?:[a-z0-9-]+/)?(?:document\.pdf|book\.epub|document\.docx|document\.html|audio\.mp3|video\.mp4)$"
395
  )
396
  VOICEOFML_READER_SOURCE_RE = re.compile(r"^/datasets/VoiceOfML/[A-Za-z0-9._-]+/(?:resolve|raw)/main/.+$")
397
 
@@ -1418,8 +1424,10 @@ async def api_random_reader(repo: Optional[str] = Query(default=None)):
1418
  rec["Path"] = rec.get("Path") or build_record_path_url(rec)
1419
  asset = converted.get(index)
1420
  if asset:
1421
- rec["ReaderLink"] = f"https://huggingface.co/datasets/vomebook/Reader-Assets/resolve/main/{asset['p']}"
1422
- rec["ReaderExtension"] = {"p": "pdf", "e": "epub", "d": "docx", "h": "html", "a": "audio", "v": "video"}[asset["m"]]
 
 
1423
  rec["DownloadLink"] = rec["Link"]
1424
  return JSONResponse(rec)
1425
 
 
120
  mode = entry.get("m")
121
  if mode not in ("p", "e", "d", "h", "a", "v") or not isinstance(path, str) or not re.fullmatch(r"objects/[0-9a-f]{2}/[0-9a-f]{64}/(?:[a-z0-9-]+/)?(?:document\.pdf|book\.epub|document\.docx|document\.html|audio\.mp3|video\.mp4)", path):
122
  continue
123
+ chapter_manifest = entry.get("c")
124
+ fallback = entry.get("f")
125
+ if chapter_manifest is not None and (mode != "e" or not isinstance(chapter_manifest, str) or not re.fullmatch(r"objects/[0-9a-f]{2}/[0-9a-f]{64}/[a-z0-9-]+/chapter-manifest\.json", chapter_manifest)):
126
+ continue
127
+ if fallback is not None and (not isinstance(fallback, str) or not re.fullmatch(r"objects/[0-9a-f]{2}/[0-9a-f]{64}/[a-z0-9-]+/document\.pdf", fallback)):
128
+ continue
129
+ clean[key] = {"s": 2, "m": mode, "p": path, **({"c": chapter_manifest} if chapter_manifest else {}), **({"f": fallback} if fallback else {})}
130
  else:
131
  clean[key] = {"s": 4}
132
  return {"v": 1, "f": clean}
 
397
 
398
 
399
  READER_ASSET_SOURCE_RE = re.compile(
400
+ r"^/datasets/vomebook/Reader-Assets/resolve/main/objects/[0-9a-f]{2}/[0-9a-f]{64}/(?:[a-z0-9-]+/)?(?:chapter-manifest\.json|document\.pdf|book\.epub|document\.docx|document\.html|audio\.mp3|video\.mp4)$"
401
  )
402
  VOICEOFML_READER_SOURCE_RE = re.compile(r"^/datasets/VoiceOfML/[A-Za-z0-9._-]+/(?:resolve|raw)/main/.+$")
403
 
 
1424
  rec["Path"] = rec.get("Path") or build_record_path_url(rec)
1425
  asset = converted.get(index)
1426
  if asset:
1427
+ rec["ReaderLink"] = f"https://huggingface.co/datasets/vomebook/Reader-Assets/resolve/main/{asset.get('c') or asset['p']}"
1428
+ rec["ReaderExtension"] = "epub-chapters" if asset.get("c") else {"p": "pdf", "e": "epub", "d": "docx", "h": "html", "a": "audio", "v": "video"}[asset["m"]]
1429
+ if asset.get("f"):
1430
+ rec["ReaderFallback"] = f"https://huggingface.co/datasets/vomebook/Reader-Assets/resolve/main/{asset['f']}"
1431
  rec["DownloadLink"] = rec["Link"]
1432
  return JSONResponse(rec)
1433