183 lines
6.6 KiB
Python
183 lines
6.6 KiB
Python
from sys import argv
|
|
from subprocess import Popen, PIPE, STDOUT, run, call
|
|
from PIL import Image
|
|
from jinja2 import Environment, FileSystemLoader
|
|
from markdown import markdown
|
|
from glob import glob
|
|
from json import dump, dumps, load
|
|
from os import path
|
|
import re
|
|
|
|
numbers = re.compile("[0-9]+")
|
|
name_from_url = re.compile(r"https:\/\/helixnebula.space/(.*)/")
|
|
out_dir = "/var/www/html/"
|
|
gemini_out_dir = "/var/gemini/"
|
|
base_url = "https://helixnebula.space/"
|
|
md_dir = "/var/stories/"
|
|
template_environment = Environment(
|
|
loader=FileSystemLoader("templates/"))
|
|
|
|
with open("metadata.json", "r") as f:
|
|
metadata = load(f)
|
|
|
|
for placename in metadata.keys():
|
|
read_path = f"{out_dir}{placename}/"
|
|
photos = [
|
|
path.basename(photo).split('/')[-1] for photo in
|
|
glob(read_path + "*")
|
|
]
|
|
try:
|
|
photos.remove("index.html")
|
|
except ValueError:
|
|
pass
|
|
metadata[placename]["count"] = len(photos)
|
|
metadata[placename]["photos"] = photos
|
|
metadata[placename]["photos"].sort(key=lambda path: int(numbers.search(path).group(0)))
|
|
|
|
with open(f"{out_dir}photos.json", "w") as f:
|
|
dump(metadata, f)
|
|
|
|
def covers(overwrite=False):
|
|
print("running covers")
|
|
for placename, info in metadata.items():
|
|
read_path = f"{out_dir}{placename}/{info['cover']}"
|
|
write_path = f"{out_dir}cover/cover_{info['cover']}"
|
|
if not overwrite and path.exists(write_path):
|
|
continue
|
|
command = ["convert", read_path, "-strip", "-interlace", "Plane", "-gaussian-blur", "0.05",
|
|
"-auto-orient", "-resize", "700x525>", "-quality", "80%", write_path]
|
|
run(command)
|
|
|
|
def thumbnails(overwrite=False):
|
|
print("running thumbnails")
|
|
for placename in metadata.keys():
|
|
for photo in metadata[placename]["photos"]:
|
|
read_path = f"{out_dir}{placename}/{photo}"
|
|
write_path = f"{out_dir}thumbnail/thumbnail_{photo}"
|
|
if not overwrite and path.exists(write_path):
|
|
continue
|
|
command = ["convert", read_path, "-strip", "-interlace", "Plane", "-gaussian-blur", "0.05",
|
|
"-auto-orient", "-resize", "300x200>", "-quality", "65%", write_path]
|
|
run(command)
|
|
|
|
def compressed(overwrite=False):
|
|
print("running compressed")
|
|
for placename in metadata.keys():
|
|
for photo in metadata[placename]["photos"]:
|
|
read_path = f"{out_dir}{placename}/{photo}"
|
|
write_path = f"{out_dir}compressed/compressed_{photo}"
|
|
if not overwrite and path.exists(write_path):
|
|
continue
|
|
command = ["convert", read_path, "-auto-orient", "-strip", "-resize", "1200>", "-quality", "90%", write_path]
|
|
run(command)
|
|
|
|
def render_index():
|
|
template = template_environment.get_template("main")
|
|
data = {key: value for key, value in sorted(metadata.items(), key=lambda item: item[1]['title'])}
|
|
photo_counts = {placename: metadata[placename]["count"] for placename in metadata.keys()}
|
|
total_count = 0
|
|
posts = [
|
|
path.basename(post).split('/')[-1][:-3] for post in
|
|
glob(md_dir + "*")
|
|
]
|
|
posts.sort()
|
|
for _, info in metadata.items():
|
|
total_count = info["count"] + total_count
|
|
with open(out_dir + "index.html", "w") as f:
|
|
f.write(template.render({
|
|
"metadata": data,
|
|
"album_count": len(metadata.keys()),
|
|
"photo_counts": photo_counts,
|
|
"total_count": total_count,
|
|
"posts": posts
|
|
}))
|
|
|
|
def render_places():
|
|
template = template_environment.get_template("place")
|
|
for placename, info in metadata.items():
|
|
working_path = out_dir + placename
|
|
photos = metadata[placename]["photos"]
|
|
photos_json = dumps(photos)
|
|
count = len(photos)
|
|
widths = []
|
|
heights = []
|
|
for photo in photos:
|
|
photo_path = out_dir + "thumbnail/thumbnail_" + photo
|
|
img = Image.open(photo_path)
|
|
width, height = img.size
|
|
widths.append(width)
|
|
heights.append(height)
|
|
photo_specs = zip(widths, heights, photos)
|
|
try:
|
|
with open(md_dir + placename + ".md", "r") as f:
|
|
md = markdown(f.read())
|
|
except FileNotFoundError:
|
|
md = "<h1>No story (yet)</h1>"
|
|
with open(working_path + "/index.html", "w") as f:
|
|
f.write(template.render({
|
|
"count": count,
|
|
"placename": placename,
|
|
"cover": info["cover"],
|
|
"info": info,
|
|
"markdown": md,
|
|
"photos": photo_specs,
|
|
"photos_json": photos_json
|
|
}))
|
|
|
|
def sub_http_local_urls(match):
|
|
name = match.group(1)
|
|
post_names = [
|
|
path.basename(post).split('/')[-1][:-3] for post in glob(md_dir + "*")
|
|
]
|
|
if name in post_names:
|
|
return name + ".gmi"
|
|
else:
|
|
return match.group(0)
|
|
|
|
def render_gemini_index():
|
|
template = template_environment.get_template("gemini_main")
|
|
post_names = [
|
|
path.basename(post).split('/')[-1][:-3] for post in glob(md_dir + "*")
|
|
]
|
|
post_names.sort()
|
|
with open(gemini_out_dir + "index.gmi", "w") as f:
|
|
f.write(template.render({
|
|
"post_info": {post_name: metadata[post_name]["title"] for post_name in post_names},
|
|
"post_states": {post_name: metadata[post_name]["state"] for post_name in post_names}
|
|
}))
|
|
|
|
def render_gemini_places():
|
|
post_paths = glob(md_dir + "*")
|
|
for post_path in post_paths:
|
|
post_name = path.basename(post_path).split('/')[-1][:-3]
|
|
with open(post_path, "r") as f:
|
|
content = f.read()
|
|
process = Popen(["gemgen"], stdout=PIPE, stdin=PIPE, stderr=PIPE, text=True)
|
|
with open(gemini_out_dir + post_name + ".gmi", "w") as f:
|
|
header = f"""=> / Index
|
|
## {metadata[post_name]["title"]}, {metadata[post_name]["state"]}
|
|
=> https://helixnebula.space/{post_name}/ Link to photography.
|
|
|
|
"""
|
|
gemtext = process.communicate(input=content)[0]
|
|
gemtext_with_local_urls = name_from_url.sub(sub_http_local_urls, gemtext)
|
|
f.write(header + gemtext_with_local_urls)
|
|
|
|
def copy_files():
|
|
call("cp js/* html/js/", shell=True)
|
|
call("cp style.css html/style.css", shell=True)
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
overwrite = "overwrite" in argv
|
|
covers(overwrite=overwrite)
|
|
thumbnails(overwrite=overwrite)
|
|
compressed(overwrite=overwrite)
|
|
except KeyboardInterrupt:
|
|
exit()
|
|
render_index()
|
|
render_places()
|
|
copy_files()
|
|
render_gemini_index()
|
|
render_gemini_places()
|