import os import sys from datetime import datetime, timezone from logging import Logger, getLogger from configparser import ConfigParser log: Logger = getLogger(__name__) class Page: def __init__(self, name: str, ctime: float, mtime: float, html: str, meta: dict, config: ConfigParser): log.debug('initializing the page object with name "%s"', name) # initial data self.name: str = name self.ctimestamp: float = ctime self.mtimestamp: float = mtime self.content: str = html self.meta: dict = meta self.config: ConfigParser = config # data from self.meta self.title: str = '' self.author: str = '' self.cdatetime: datetime self.mdatetime: datetime self.summary: str = '' self.lang: str = 'en' self.tags: list[tuple[str, str]] = [] # constructed self.url: str = '' self.image_url: str = '' self.cdate: str = '' self.cdate_list: str = '' self.cdate_list_sep: str = '' self.cdate_rss: str = '' self.cdate_sitemap: str = '' self.mdate: str self.mdate_list: str self.mdate_list_sep: str self.mdate_rss: str = '' self.mdate_sitemap: str = '' # later assigned references to next and previous pages # not always assigned (tail ends), and the None helps check it, ignoring self.next: Page = None # type: ignore self.previous: Page = None # type: ignore # also from self.meta, but for og metadata self.og: dict[str, str] = dict() def __lt__(self, other): return self.ctimestamp < other.ctimestamp def __get_mandatory_meta(self, meta: str) -> str: try: log.debug('parsing required metadata "%s"', meta) return self.meta[meta][0] except KeyError: log.error('failed to parse mandatory metadata "%s" from file "%s"', meta, os.path.join(self.config.get('path', 'src'), self.name)) sys.exit(1) # parses meta from self.meta, for og, it prioritizes, # the actual og meta def parse_metadata(self): log.debug('parsing metadata for file "%s"', self.name) self.title = self.__get_mandatory_meta('title') self.author = self.__get_mandatory_meta('author') self.summary = self.__get_mandatory_meta('summary') self.lang = self.__get_mandatory_meta('lang') log.debug('parsing timestamp') self.cdatetime = datetime.fromtimestamp(self.ctimestamp, tz=timezone.utc) self.cdate = self.cdatetime.strftime(self.config.get('fmt', 'date')) self.cdate_list = self.cdatetime.strftime(self.config.get('fmt', 'list_date')) self.cdate_list_sep = self.cdatetime.strftime(self.config.get('fmt', 'list_sep_date')) self.cdate_rss = self.cdatetime.strftime(self.config.get('fmt', 'rss_date')) self.cdate_sitemap = \ self.cdatetime.strftime(self.config.get('fmt', 'sitemap_date')) if self.mtimestamp != 0.0: log.debug('parsing modified timestamp') self.mdatetime = datetime.fromtimestamp(self.mtimestamp, tz=timezone.utc) self.mdate = self.mdatetime.strftime(self.config.get('fmt', 'date')) self.mdate_list = self.mdatetime.strftime(self.config.get('fmt', 'list_date')) self.mdate_list_sep = self.mdatetime.strftime(self.config.get('fmt', 'list_sep_date')) self.mdate_rss = self.mdatetime.strftime(self.config.get('fmt', 'rss_date')) self.mdate_sitemap = \ self.mdatetime.strftime(self.config.get('fmt', 'sitemap_date')) else: log.debug('not parsing modified timestamp, hasn\'t been modified') try: tags_only: list[str] = self.meta['tags'] log.debug('parsing tags') tags_only.sort() for t in tags_only: self.tags.append((t, f'{self.config.get("url", "main")}/tag/@{t}.html')) except KeyError: log.debug('not parsing tags, doesn\'t have any') log.debug('parsing url') self.url = f'{self.config.get("url", "main")}/{self.name.replace(".md", ".html")}' log.debug('final url "%s"', self.url) log.debug('parsing image url') try: self.image_url = \ f'{self.config.get("url", "static")}/{self.meta["image_url"][0]}' except KeyError: log.debug('using default image, no image_url metadata found') self.image_url = \ f'{self.config.get("url", "static")}/{self.config.get("url", "default_image")}' log.debug('final image url "%s"', self.image_url) # if contains open graph elements try: # og_e = object graph entry og_elements: list[str] = self.meta['og'] log.debug('parsing og metadata') for og_e in og_elements: kv: list[str] = og_e.split(',', 1) if len(kv) != 2: log.error('invalid og syntax for "%s", needs to be "k, v"', og_e) sys.exit(1) k: str = kv[0].strip() v: str = kv[1].strip() log.debug('og element: ("%s", "%s")', k, v) self.og[k] = v except KeyError: log.debug('no og metadata found')