#!/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 mistune import mistune.core import mistune.inline_parser import mistune.plugins import unidecode import web_mini 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 + """