Spaces:
Sleeping
Sleeping
from fastapi import FastAPI, HTTPException | |
from fastapi.responses import FileResponse | |
from fastapi.middleware.cors import CORSMiddleware | |
import os, mimetypes, hashlib, re | |
from collections import defaultdict | |
VAULT = "vault" | |
app = FastAPI() | |
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"]) | |
def root(): | |
return { | |
"status": "vault-online", | |
"browse": "/vault", | |
"read": "/vault/{path}", | |
"raw": "/raw/{path}", | |
"tags": "/tags", | |
"graph": "/graph" | |
} | |
def vault(path: str = ""): | |
full = os.path.join(VAULT, path) | |
if not os.path.exists(full): | |
raise HTTPException(404) | |
if os.path.isdir(full): | |
return { | |
"path": path, | |
"entries": [{ | |
"name": f, | |
"type": "dir" if os.path.isdir(os.path.join(full, f)) else "file", | |
"size": os.path.getsize(os.path.join(full, f)) if os.path.isfile(os.path.join(full, f)) else None, | |
"modified": os.path.getmtime(os.path.join(full, f)), | |
"hash": hashlib.md5(f.encode()).hexdigest()[:8] | |
} for f in sorted(os.listdir(full))] | |
} | |
if os.path.isfile(full): | |
try: | |
with open(full, "r", encoding="utf-8") as f: | |
return {"path": path, "content": f.read()} | |
except: | |
raise HTTPException(500) | |
raise HTTPException(400) | |
def raw(path: str): | |
full = os.path.join(VAULT, path) | |
if not os.path.isfile(full): | |
raise HTTPException(404) | |
mt, _ = mimetypes.guess_type(full) | |
return FileResponse(full, media_type=mt or "application/octet-stream") | |
def extract_tags(): | |
tag_map = defaultdict(list) | |
for root, _, files in os.walk(VAULT): | |
for f in files: | |
if f.endswith(".md"): | |
path = os.path.join(root, f) | |
try: | |
with open(path, "r", encoding="utf-8") as file: | |
content = file.read() | |
tags = re.findall(r'(?<!\w)#([\w/-]+)', content) | |
for tag in tags: | |
tag_map[tag].append(os.path.relpath(path, VAULT)) | |
except: | |
continue | |
return dict(tag_map) | |
def link_graph(): | |
nodes = set() | |
edges = [] | |
for root, _, files in os.walk(VAULT): | |
for f in files: | |
if f.endswith(".md"): | |
src_path = os.path.relpath(os.path.join(root, f), VAULT) | |
nodes.add(src_path) | |
try: | |
with open(os.path.join(root, f), "r", encoding="utf-8") as file: | |
content = file.read() | |
links = re.findall(r'\[\[([^\]]+)\]\]', content) | |
for link in links: | |
target_file = link if link.endswith(".md") else f"{link}.md" | |
edges.append({"from": src_path, "to": target_file}) | |
nodes.add(target_file) | |
except: | |
continue | |
return { | |
"nodes": sorted(list(nodes)), | |
"edges": edges | |
} |