mirror of
https://github.com/chatmail/relay.git
synced 2026-05-12 00:54:37 +00:00
175 lines
5.1 KiB
Python
175 lines
5.1 KiB
Python
import hashlib
|
|
import importlib.resources
|
|
import re
|
|
import time
|
|
import traceback
|
|
import webbrowser
|
|
from pathlib import Path
|
|
|
|
import markdown
|
|
from chatmaild.config import read_config
|
|
from jinja2 import Template
|
|
|
|
from .genqr import gen_qr_png_data
|
|
|
|
_MERGE_CONFLICT_RE = re.compile(
|
|
r"^<<<<<<<.+^=======.+^>>>>>>>", re.DOTALL | re.MULTILINE
|
|
)
|
|
|
|
|
|
def snapshot_dir_stats(somedir):
|
|
d = {}
|
|
for path in somedir.iterdir():
|
|
if path.is_file() and path.name[0] != "." and path.suffix != ".swp":
|
|
mtime = path.stat().st_mtime
|
|
hash = hashlib.md5(path.read_bytes()).hexdigest()
|
|
d[path] = (mtime, hash)
|
|
return d
|
|
|
|
|
|
def prepare_template(source):
|
|
assert source.exists(), source
|
|
render_vars = {}
|
|
render_vars["pagename"] = "home" if source.stem == "index" else source.stem
|
|
render_vars["markdown_html"] = markdown.markdown(source.read_text())
|
|
page_layout = source.with_name("page-layout.html").read_text()
|
|
return render_vars, page_layout
|
|
|
|
|
|
def get_paths(config) -> (Path, Path, Path):
|
|
reporoot = importlib.resources.files(__package__).joinpath("../../../").resolve()
|
|
www_path = Path(config.www_folder)
|
|
# if www_folder was not set, use default directory
|
|
if config.www_folder == "":
|
|
www_path = reporoot.joinpath("www")
|
|
src_dir = www_path.joinpath("src")
|
|
# if www_folder is a hugo page, build it
|
|
if src_dir.joinpath("index.md").is_file():
|
|
build_dir = www_path.joinpath("build")
|
|
# if it is not a hugo page, upload it as is
|
|
else:
|
|
build_dir = None
|
|
return www_path, src_dir, build_dir
|
|
|
|
|
|
def build_webpages(src_dir, build_dir, config) -> Path:
|
|
try:
|
|
return _build_webpages(src_dir, build_dir, config)
|
|
except Exception:
|
|
print(traceback.format_exc())
|
|
|
|
|
|
def int_to_english(number):
|
|
if number >= 0 and number <= 12:
|
|
a = [
|
|
"zero",
|
|
"one",
|
|
"two",
|
|
"three",
|
|
"four",
|
|
"five",
|
|
"six",
|
|
"seven",
|
|
"eight",
|
|
"nine",
|
|
"ten",
|
|
"eleven",
|
|
"twelve",
|
|
]
|
|
return a[number]
|
|
elif number <= 50:
|
|
return str(number)
|
|
if number > 50:
|
|
return "more"
|
|
|
|
|
|
def _build_webpages(src_dir, build_dir, config):
|
|
mail_domain = config.mail_domain
|
|
assert src_dir.exists(), src_dir
|
|
if not build_dir.exists():
|
|
build_dir.mkdir()
|
|
|
|
qr_path = build_dir.joinpath(f"qr-chatmail-invite-{mail_domain}.png")
|
|
qr_path.write_bytes(gen_qr_png_data(mail_domain).read())
|
|
|
|
for path in src_dir.iterdir():
|
|
if path.suffix == ".md":
|
|
render_vars, content = prepare_template(path)
|
|
render_vars["username_min_length"] = int_to_english(
|
|
config.username_min_length
|
|
)
|
|
render_vars["username_max_length"] = int_to_english(
|
|
config.username_max_length
|
|
)
|
|
render_vars["password_min_length"] = int_to_english(
|
|
config.password_min_length
|
|
)
|
|
target = build_dir.joinpath(path.stem + ".html")
|
|
|
|
# recursive jinja2 rendering
|
|
while 1:
|
|
new = Template(content).render(config=config, **render_vars)
|
|
if new == content:
|
|
break
|
|
content = new
|
|
|
|
with target.open("w") as f:
|
|
f.write(content)
|
|
elif path.name != "page-layout.html":
|
|
target = build_dir.joinpath(path.name)
|
|
target.write_bytes(path.read_bytes())
|
|
return build_dir
|
|
|
|
|
|
def find_merge_conflict(src_dir) -> Path:
|
|
assert src_dir.exists(), src_dir
|
|
result = None
|
|
for path in src_dir.iterdir():
|
|
if path.suffix in [".css", ".html", ".md"]:
|
|
if _MERGE_CONFLICT_RE.search(path.read_text()):
|
|
result = path
|
|
break
|
|
return result
|
|
|
|
|
|
def main():
|
|
path = importlib.resources.files(__package__)
|
|
reporoot = path.joinpath("../../../").resolve()
|
|
inipath = reporoot.joinpath("chatmail.ini")
|
|
config = read_config(inipath)
|
|
config.webdev = True
|
|
assert config.mail_domain
|
|
|
|
www_path, src_path, build_dir = get_paths(config)
|
|
build_dir = build_webpages(src_path, build_dir, config)
|
|
index_path = build_dir.joinpath("index.html")
|
|
webbrowser.open(str(index_path))
|
|
|
|
print(f"\nOpened URL: file://{index_path.resolve()}\n")
|
|
print(f"Watching {src_path} directory for changes...")
|
|
|
|
stats = snapshot_dir_stats(src_path)
|
|
changenum = 0
|
|
debounce_time = 0.5 # wait 0.5s after detecting a change
|
|
|
|
while True:
|
|
time.sleep(1)
|
|
newstats = snapshot_dir_stats(src_path)
|
|
|
|
if newstats != stats:
|
|
changed_files = [f for f in newstats if stats.get(f) != newstats[f]]
|
|
for f in changed_files:
|
|
print(f"*** CHANGED: {f}")
|
|
|
|
stats = newstats
|
|
changenum += 1
|
|
build_webpages(src_path, build_dir, config)
|
|
print(f"[{changenum}] regenerated web pages at: {index_path}")
|
|
print(f"URL: file://{index_path.resolve()}\n\n")
|
|
|
|
time.sleep(debounce_time) # simple debounce
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|