let there be light

This commit is contained in:
Jurgis Sakalauskas
2026-04-28 11:48:29 +03:00
commit beb1294d86
15 changed files with 966 additions and 0 deletions
+77
View File
@@ -0,0 +1,77 @@
import json
import shutil
from datetime import datetime, timezone
from pathlib import Path
from typing import Optional
class Storage:
def __init__(self, data_dir: Path):
self.data_dir = Path(data_dir)
self.articles_dir = self.data_dir / "articles"
self.index_file = self.data_dir / "index.json"
self.articles_dir.mkdir(parents=True, exist_ok=True)
if not self.index_file.exists():
self._write_index({"articles": []})
def _read_index(self) -> dict:
with open(self.index_file) as f:
return json.load(f)
def _write_index(self, data: dict) -> None:
tmp = self.index_file.with_suffix(".json.tmp")
with open(tmp, "w") as f:
json.dump(data, f, indent=2)
tmp.replace(self.index_file)
def list_articles(self) -> list[dict]:
return self._read_index()["articles"]
def get_article(self, article_id: str) -> Optional[dict]:
for a in self.list_articles():
if a["id"] == article_id:
return a
return None
def add_article(
self,
article_id: str,
title: str,
url: str,
markdown: str,
epub_bytes: bytes,
) -> None:
folder = self.articles_dir / article_id
folder.mkdir(parents=True, exist_ok=False)
(folder / "source.md").write_text(markdown, encoding="utf-8")
(folder / "article.epub").write_bytes(epub_bytes)
meta = {
"id": article_id,
"url": url,
"title": title,
"fetched_at": _now(),
}
(folder / "meta.json").write_text(json.dumps(meta, indent=2))
index = self._read_index()
index["articles"].insert(0, meta)
self._write_index(index)
def delete_article(self, article_id: str) -> bool:
index = self._read_index()
before = len(index["articles"])
index["articles"] = [a for a in index["articles"] if a["id"] != article_id]
if len(index["articles"]) == before:
return False
self._write_index(index)
folder = self.articles_dir / article_id
if folder.exists():
shutil.rmtree(folder)
return True
def epub_path(self, article_id: str) -> Path:
return self.articles_dir / article_id / "article.epub"
def _now() -> str:
return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")