import json import os import time from glob import glob from itertools import batched import jinja2 from PIL import ImageFile from config import WILDCARD_LETTER, THUMBNAIL_CHUNK_SIZE, PROCS, GLOBALS from imgutils import create_thumbnail_sheet, convert_cover, \ convert_chapter ImageFile.LOAD_TRUNCATED_IMAGES = True from minify_html import minify from slugify import slugify from tqdm import tqdm from rcssmin import cssmin from multiprocessing.pool import ThreadPool env = jinja2.Environment( undefined=jinja2.StrictUndefined, ) env.filters["slug"] = slugify env.filters["minify_css"] = cssmin def render_index_pages(path, prefix, index_items, content_rating): with open("assets/index.html.jinja") as f: template = env.from_string(f.read()) index_parent_dir = f"{prefix}{('-' + content_rating.lower()) if content_rating else ''}" def _work(task): item, series = task index_loc = item.replace(WILDCARD_LETTER, "_") index_dir = str(os.path.join(path, index_parent_dir, index_loc)) os.makedirs(index_dir) if prefix == "t": series = sorted(series, key=lambda s: s["score"], reverse=True) else: series = sorted(series, key=lambda s: s["sort_name"]) thumbnails = [ { "cover": glob(os.path.join(path, s["location"], "cover.*"))[0], "name": s["name"], "loc": s["location"] } for s in series ] for i, chunk in enumerate(batched(thumbnails, THUMBNAIL_CHUNK_SIZE)): sheet_name = f"{int(time.time()):x}{i:x}" create_thumbnail_sheet(chunk, os.path.join(index_dir, sheet_name + ".webp")) sheet_img = os.path.join(index_parent_dir, index_loc, sheet_name + ".webp") for j, tn in enumerate(chunk): offset_class = f"o{j:x}" tn["offset"] = offset_class tn["img"] = sheet_img is_long_list = len(index_items) > 27 html = minify(template.render( name=item, thumbnails=thumbnails, parent_loc=index_parent_dir, loc=index_loc, prefix=prefix, index_pages=[ ( item.replace("-", " ") if is_long_list else item.upper(), item, os.path.join(index_parent_dir, item.replace(WILDCARD_LETTER, "_")), len(series) > 0 ) for item, series in index_items.items() ], tags=is_long_list, rating=content_rating, **GLOBALS )) with open(os.path.join(index_dir, "index.html"), "w") as f: f.write(html) with ThreadPool(processes=PROCS) as pool: tasks = list(index_items.items()) for _ in tqdm(pool.imap_unordered(_work, tasks), total=len(tasks)): pass def render_series_pages(path, index): with open("assets/series.html.jinja") as f: template = env.from_string(f.read()) def _work(series): series_dir = str(os.path.join(path, series["location"])) os.makedirs(series_dir) convert_cover(series["id"] + "_c", series["cover"], series_dir) html = minify(template.render( series_name = series["name"], loc = series["location"], chapters = series["chapters"], tags = list(filter(lambda t: t != "all", series["tags"])), rating = series["rating"], **GLOBALS )) with open(os.path.join(series_dir, "index.html"), "w") as f: #TODO: Debug # f.write(f"") f.write(html) with ThreadPool(processes=PROCS) as pool: for _ in tqdm(pool.imap_unordered(_work, index), total=len(index)): pass def render_chapter_pages(path, index): with open("assets/chapter.html.jinja") as f: template = env.from_string(f.read()) def _work(task): series, chapter = task chapter_dir = str(os.path.join(path, *chapter["location"].split("/"))) convert_chapter( cache_key=f"{series['id']}.{chapter['index']:03d}", images=chapter["images"], output_folder=chapter_dir ) images = [ os.path.basename(filename) for filename in sorted(glob(os.path.join(chapter_dir, "*.webp"))) ] html = minify(template.render( series_name = series["name"], series_loc = series["location"], chapter_name = chapter["name"], loc = chapter["location"], prev_loc = chapter.get("prev"), next_loc = chapter.get("next"), images = images, **GLOBALS )) with open(os.path.join(chapter_dir, "index.html"), "w") as f: f.write(html) tasks = [] for series in index: for chapter in series["chapters"]: tasks.append((series, chapter)) with ThreadPool(processes=PROCS) as pool: for _ in tqdm(pool.imap_unordered(_work, tasks), total=len(tasks)): pass def render_home(path): with open("assets/home.html.jinja") as f: template = env.from_string(f.read()) html = minify(template.render( **GLOBALS )) with open(os.path.join(path, "index.html"), "w") as f: f.write(html) with open("assets/manifest.json.jinja") as f: template = env.from_string(f.read()) data = json.loads(template.render( **GLOBALS )) with open(os.path.join(path, "manifest.json"), "w") as f: json.dump(data, f, sort_keys=True) def render_style(path): with open("assets/style.css.jinja") as f: template = env.from_string(f.read()) css = cssmin(template.render( **GLOBALS )) with open(os.path.join(path, GLOBALS["style"]), "w") as f: f.write(css)