files.ari-web.xyz/scripts/tree.py
Ari Archer 11ab8e6046
tree : add visitor count
Signed-off-by: Ari Archer <ari.web.xyz@gmail.com>
2023-05-23 19:22:07 +03:00

125 lines
3.8 KiB
Python

#!/usr/bin/env python3
"""Generate an HTML tree of all files
"""
import hashlib
import json
import os
import sys
import warnings
from subprocess import check_output as check_cmd_output
from typing import List, Tuple
warnings.filterwarnings("error", category=Warning)
IGNORE_FILES: Tuple[str] = ("netlify.toml",)
INDEX_TEMPLATE: str = f"""<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Ari-web file hosting index">
<meta name="keywords" content="website, webdev, linux, programming, ari, opensource, free, cdn, file, files, file-hosting, file_hosting, git, github">
<meta name="robots" content="follow, index, max-snippet:-1, max-video-preview:-1, max-image-preview:large, noimageindex"/>
<title>Ari::web -> Files</title>
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/hack-font@3/build/web/hack.min.css">
<link rel="manifest" href="/manifest.json" />
<meta name="color-scheme" content="dark">
<style>
:root {{ color-scheme: dark; }}
* {{ background-color: #262220; color: #f9f6e8; font-family: sans-serif; }}
body {{ padding: 2rem; max-width: 1100px; margin: auto; }}
h1 {{ text-align: center; margin: 1em; }}
li {{ margin: 0.5em; }}
a {{ text-decoration: none; color: #cdc4c4; font-style: italic; }}
a:focus, a:hover {{ text-decoration: underline; }}
</style>
</head>
<body>
<article>
<h1><a href='https://ari-web.xyz/'>Ari-web</a> file hosting index</h1>
<header>
<nav>
<p align='center'>
<i>Ignored files: {', '.join(IGNORE_FILES)} \
| Last built at {check_cmd_output('date').decode()} \
| <a href='/git'>source code</a> | <b>*download</b></i> | \
visitor <img src="https://server.ari-web.xyz/visit" alt="visitor count">
</p>
<hr/>
<nav>
</header>
<main>
%s
</main>
</article>
</body>
</html>"""
def generate_tree(path: str, html: str = "") -> Tuple[str, List[str]]:
"""Generate a tree in HTML of files in specified path
Parameters
----------
path (str): The path
html (str): Starting HTML
Returns
-------
html (str): The HTML tree
files l(ist[str]): List of all files
"""
files: List[str] = []
for file in os.listdir(path):
if file.startswith(".") or file in IGNORE_FILES:
continue
rel = path + "/" + file
if os.path.isdir(rel):
html += f"<li>{file}/</li><ul>"
_generated: Tuple[str, List[str]] = generate_tree(rel)
files.extend(_generated[1])
html += _generated[0]
html += "</ul>"
else:
files.append(rel.removeprefix("./"))
html += f'<li><a href="{rel}">{file}</a> [<a href="{rel}" download>*{file}</a>]</li>'
return html, files
def main() -> int:
"""Entry/main function"""
generated_tree: Tuple[str, List[str]] = generate_tree(".")
with open("index.html", "w", encoding="utf-8") as index:
index.write(INDEX_TEMPLATE % (generated_tree[0]))
with open("files.json", "w") as api_json:
json.dump(generated_tree[1], api_json)
with open("files.json", "rb") as api_json:
with open("files_json_hash.txt", "w") as api_hash:
api_hash.write(hashlib.sha256(api_json.read()).hexdigest())
return 0
if __name__ == "__main__":
assert main.__annotations__.get("return") is int, "main() should return an integer"
sys.exit(main())