Select Git revision
map_loader.cpp
codimd_export.py 2.73 KiB
#!/usr/bin/env python3
"""
Save all Markdown documents in your CodiMD history to a local directory.
"""
import json
from pathlib import Path
from urllib.error import HTTPError
from urllib.parse import quote
from urllib.request import Request, urlopen
import sys
from common import get_sessionid, check_accessibility, print_block_heading
def slurp(url, session_id):
"""Retrieve a (protected) CodiMD resource and return it as a bytes object."""
request = Request(url, headers={"Cookie": f"connect.sid={session_id}"})
with urlopen(request) as stream:
return stream.read()
def prepare_target_dir(pathname):
"""Create the directory to dump documents to, but refuse to override an existing one."""
target_dir = Path(pathname)
if target_dir.exists():
raise SystemExit(f"ERROR: the target directory {target_dir} already exists. Delete it, then re-execute this "
f"script")
target_dir.mkdir()
return target_dir
def export_from_codimd(instance_url, session_id, export_to):
check_accessibility(instance_url, session_id, "connect.sid")
"""Retrieve CodiMD document history and try to download each document."""
print_block_heading(f"Trying to fetch history ({instance_url})")
try:
data = json.loads(slurp(f"{instance_url}/history", session_id))
except OSError as error:
raise SystemExit(f"error: couldn't access the /history endpoint: {error}")
except json.JSONDecodeError as error:
raise SystemExit(f"error: received malformed JSON: {error}")
print_block_heading(f"Preparing target directory ({export_to})")
target_dir = prepare_target_dir(export_to)
num_ok = num_fail = 0
print_block_heading(f"Accessing history and trying to fetch each document")
print("Hold on, this may take a while...")
for row in data["history"]:
document_id = row["id"]
document_url = f"{instance_url}/{quote(document_id)}"
try:
contents = slurp(f"{document_url}/download", session_id)
with open(Path(target_dir, f"{document_id}.md"), mode="wb") as stream:
stream.write(contents)
with open(Path(target_dir, f"history.json"), mode="w") as stream:
json.dump(data, stream)
num_ok += 1
except HTTPError as error:
# history might reference deleted or otherwise inaccessible notes
error_msg = f"HTTP {error.code} {error.reason}"
print(f"{error_msg}: {document_url}", file=sys.stderr)
num_fail += 1
print(f"Done: {num_ok} notes successfully downloaded, {num_fail} not accessible.")
if __name__ == "__main__":
export_from_codimd("https://md.inf.tu-dresden.de", get_sessionid("CodiMD", "connect.sid"), "codimd-documents")