#!/usr/bin/env python3 # -*- coding: utf-8 -*- """blog manager""" from __future__ import annotations import asyncio import datetime import hashlib import json import os import re import shutil import string import subprocess import sys import tempfile import time import typing import xml.etree.ElementTree as etree from glob import iglob from html import escape as html_escape from threading import Thread from timeit import default_timer as code_timer from warnings import filterwarnings as filter_warnings import html_minifier.minify # type: ignore import mistune import mistune.core import mistune.inline_parser import mistune.plugins import rcssmin # type: ignore import unidecode from readtime import of_markdown as read_time_of_markdown # type: ignore __version__: typing.Final[int] = 2 OK: typing.Final[int] = 0 ER: typing.Final[int] = 1 CONFIG_FILE: typing.Final[str] = "blog.json" DEFAULT_CONFIG: dict[str, typing.Any] = { "title": "blog", "header": "blog", "description": "my blog page", "posts-dir": "b", "assets-dir": "content", "rss-file": "rss.xml", "blog-keywords": [ "blog", "blog page", "blog post", "personal", "website", ], "default-keywords": [ "blog", "blog page", "blog post", "personal", "website", ], "website": "https://example.com", "blog": "https://blog.example.com", "source": "/git", "visitor-count": "/visit", "comment": "/c", "theme": { "primary": "#000", "secondary": "#fff", "type": "dark", }, "manifest": { "icons": [ { "src": "/favicon.ico", "sizes": "128x128", "type": "image/png", }, ], }, "author": "John Doe", "locale": "en_GB", "recents": 14, "indent": 4, "markdown-plugins": [ # good defaults "speedup", "strikethrough", "insert", "superscript", "subscript", "footnotes", "abbr", ], "editor": ["vim", "--", "%s"], "context-words": [ "the", "a", "about", "etc", "on", "at", "in", "by", "its", "i", "to", "my", "of", "between", "because", "of", "or", "how", "to", "begin", "is", "this", "person", "important", "homework", "and", "cause", "how", "what", "for", "with", "without", "using", "im", ], "wslug-limit": 10, "slug-limit": 96, "proxy-api": "https://gimmeproxy.com/api/getProxy?post=true&get=true&user-agent=true&supportsHttps=true&protocol=http&minSpeed=20&curl=true", "test-proxy": "https://example.com/", "test-proxy-timeout": 15, "license": "GPL-3.0-or-later", "recent-title-trunc": 32, "server-host": "127.0.0.1", "server-port": 8080, "post-preview-size": 196, "read-wpm": 150, "posts": {}, } NCI: bool = "CI" not in os.environ NOCLR: bool = "NOCLR" in os.environ LOG_CLR: str = "\033[90m" ERR_CLR: str = "\033[1m\033[31m" NEW_CLR: str = "\033[1m\033[32m" IMP_CLR: str = "\033[1m\033[35m" HTML_BEGIN: typing.Final[ str ] = """
""" POST_TEMPLATE: typing.Final[str] = ( HTML_BEGIN + """