[SSG][Fix] Fix %M to %m. Add -v for logging.

This commit is contained in:
Ceda EI 2020-03-10 12:41:54 +05:30
parent f7582b1b2b
commit 401e1b64f0
1 changed files with 61 additions and 9 deletions

70
nova.py
View File

@ -1,4 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# pylint: disable=logging-format-interpolation
"Creates a static site for redacted.life" "Creates a static site for redacted.life"
import argparse import argparse
@ -7,6 +8,7 @@ from datetime import datetime
import json import json
import os import os
import os.path as path import os.path as path
import logging
import re import re
import subprocess import subprocess
import shutil import shutil
@ -36,6 +38,7 @@ class EpisodeList(UserList):
self.output = output self.output = output
self.template = template self.template = template
self.archives = archives self.archives = archives
logging.info(f"New EpisodeList: {url=} {output=} {template=} {archives=}")
def sort(self, *_args, **_kwargs): def sort(self, *_args, **_kwargs):
"Sorts the EpisodeList" "Sorts the EpisodeList"
@ -43,6 +46,7 @@ class EpisodeList(UserList):
def generate_thumbnails(self): def generate_thumbnails(self):
"Generates thumbnails for all the videos" "Generates thumbnails for all the videos"
logging.info(f"Creating missing directories")
if not path.isdir(self.output + "assets"): if not path.isdir(self.output + "assets"):
os.mkdir(self.output + "assets") os.mkdir(self.output + "assets")
if not path.isdir(self.output + "assets/thumbnails"): if not path.isdir(self.output + "assets/thumbnails"):
@ -50,6 +54,7 @@ class EpisodeList(UserList):
for episode in self.data: for episode in self.data:
location = (self.output + "assets/thumbnails/" + location = (self.output + "assets/thumbnails/" +
gen_name(episode.date, episode.slug) + ".jpg") gen_name(episode.date, episode.slug) + ".jpg")
logging.info(f"Creating thumbnail for {episode=} at {location}")
episode.store_thumbnail(location) episode.store_thumbnail(location)
def generate_rss(self, header): def generate_rss(self, header):
@ -58,8 +63,10 @@ class EpisodeList(UserList):
open(self.output + "feed_ogg.rss", "w") as ogg: open(self.output + "feed_ogg.rss", "w") as ogg:
# pylint: disable = invalid-name # pylint: disable = invalid-name
for s, ext in ((mp3, "mp3"), (ogg, "ogg")): for s, ext in ((mp3, "mp3"), (ogg, "ogg")):
logging.info(f"Writing header for {ext}")
s.write(header) s.write(header)
for ep in self.data: for ep in self.data:
logging.info(f"Writing item for episode {ep} with {ext=}")
s.write("<item>") s.write("<item>")
s.write("\n") s.write("\n")
# Title # Title
@ -123,6 +130,7 @@ class EpisodeList(UserList):
s.write("\n") s.write("\n")
s.write("</item>") s.write("</item>")
s.write("\n") s.write("\n")
logging.info(f"Writing end for {ext}")
s.write("</channel>") s.write("</channel>")
s.write("\n") s.write("\n")
s.write("</rss>") s.write("</rss>")
@ -139,24 +147,27 @@ class EpisodeList(UserList):
def generate_site(self, root): def generate_site(self, root):
"Generates the entire site" "Generates the entire site"
# Generate CSS from SCSS logging.info("Generating CSS from SCSS")
subprocess.run(["sass", "--update", f"{root}scss:{root}assets/css"], subprocess.run(["sass", "--update", f"{root}scss:{root}assets/css"],
check=True) check=True)
# Copy the existing assets logging.info("Copy the existing assets")
shutil.copytree(root + "assets", self.output + "assets", shutil.copytree(root + "assets", self.output + "assets",
dirs_exist_ok=True) dirs_exist_ok=True)
# Create the required directories logging.info("Create the required directories")
paths = [ paths = [
"assets", "assets",
"assets/audio", "assets/audio",
"assets/videos", "assets/videos",
] ]
logging.info("Creating missing directories")
for directory in paths: for directory in paths:
if not path.isdir(self.output + directory): if not path.isdir(self.output + directory):
logging.info(f"Creating directory {directory}")
os.mkdir(self.output + directory) os.mkdir(self.output + directory)
# Render episodes and copy data logging.info("Render episodes and copy data")
for episode in self.data: for episode in self.data:
logging.info(f"Rendering episode {episode}")
html = f"{self.output}{gen_name(episode.date, episode.slug)}.html" html = f"{self.output}{gen_name(episode.date, episode.slug)}.html"
thumbnail = ("assets/thumbnails/" + thumbnail = ("assets/thumbnails/" +
gen_name(episode.date, episode.slug) + ".jpg") gen_name(episode.date, episode.slug) + ".jpg")
@ -164,14 +175,19 @@ class EpisodeList(UserList):
gen_name(episode.date, episode.slug) + ".mp4") gen_name(episode.date, episode.slug) + ".mp4")
audio = (self.output + "assets/audio/" + audio = (self.output + "assets/audio/" +
gen_name(episode.date, episode.slug) + ".mp3") gen_name(episode.date, episode.slug) + ".mp3")
logging.info(f"Copying {episode.video} to {video}")
shutil.copy2(episode.video, video) shutil.copy2(episode.video, video)
logging.info(f"Copying {episode.audio}.mp3 to {audio}")
shutil.copy2(episode.audio + ".mp3", audio) shutil.copy2(episode.audio + ".mp3", audio)
logging.info(f"Copying {episode.audio}.ogg to {audio}")
shutil.copy2(episode.audio + ".ogg", audio) shutil.copy2(episode.audio + ".ogg", audio)
logging.info(f"Writing to {html}")
with open(html, "w") as file: with open(html, "w") as file:
file.write(episode.render(self.template, thumbnail)) file.write(episode.render(self.template, thumbnail))
last = self.data[-1] last = self.data[-1]
last_name = f"{self.output}{gen_name(last.date, last.slug)}.html" last_name = f"{self.output}{gen_name(last.date, last.slug)}.html"
logging.info(f"Copying last one ({last}) to index.html")
shutil.copy2(last_name, self.output + "index.html") shutil.copy2(last_name, self.output + "index.html")
@ -186,6 +202,8 @@ class Episode:
self.audio = audio_src self.audio = audio_src
self.config = config self.config = config
self.length = MP3(audio_src + ".mp3").info.length self.length = MP3(audio_src + ".mp3").info.length
logging.info(f"New episode: {date=} {slug=} {title=} {self.video=} "
f"{self.audio=} {config=} {self.length=} {self.show_notes=}")
def render(self, template, thumbnail_src): def render(self, template, thumbnail_src):
"Renders the Episode with the given template" "Renders the Episode with the given template"
@ -200,11 +218,17 @@ class Episode:
"Stores the thumbnail for given image at path" "Stores the thumbnail for given image at path"
args = ["ffmpeg", "-i", self.video, "-ss", "00:00:01.000", "-vframes", args = ["ffmpeg", "-i", self.video, "-ss", "00:00:01.000", "-vframes",
"1", location] "1", location]
logging.info(f"Running {' '.join(args)}")
subprocess.run(args, check=False) subprocess.run(args, check=False)
def __len__(self): def __len__(self):
return int(self.length) return int(self.length)
def __str__(self):
return f"{self.slug}: {self.title}"
def __repr__(self):
return str(self)
def parse_args(): def parse_args():
"Parses arguments" "Parses arguments"
@ -212,9 +236,14 @@ def parse_args():
parser.add_argument("input_dir", help="Input directory") parser.add_argument("input_dir", help="Input directory")
parser.add_argument("output_dir", help="Output directory") parser.add_argument("output_dir", help="Output directory")
parser.add_argument("url", help="Base URL of website") parser.add_argument("url", help="Base URL of website")
parser.add_argument("--verbose", "-v", action="store_true", help="Verbose Logging")
args = parser.parse_args() args = parser.parse_args()
input_dir = path.abspath(args.input_dir.rstrip("/")) + "/" input_dir = path.abspath(args.input_dir.rstrip("/")) + "/"
output_dir = path.abspath(args.output_dir.rstrip("/")) + "/" output_dir = path.abspath(args.output_dir.rstrip("/")) + "/"
if args.verbose:
logging.basicConfig(level=logging.DEBUG)
else:
logging.basicConfig()
url = args.url.rstrip("/") + "/" url = args.url.rstrip("/") + "/"
return input_dir, output_dir, url return input_dir, output_dir, url
@ -248,6 +277,9 @@ def main(args):
"Main method" "Main method"
root = path.dirname(sys.argv[0]).rstrip("/") + "/" root = path.dirname(sys.argv[0]).rstrip("/") + "/"
input_dir, output_dir, url = args input_dir, output_dir, url = args
logging.info(f"Input directory: {input_dir}")
logging.info(f"Output directory: {output_dir}")
logging.info(f"URL: {url}")
# Input validation # Input validation
paths = [ paths = [
@ -256,10 +288,12 @@ def main(args):
input_dir + "videos", input_dir + "videos",
input_dir + "audio", input_dir + "audio",
] ]
logging.info("Checking if all paths exist.")
if not all(path.isdir((fail := i)) for i in paths): if not all(path.isdir((fail := i)) for i in paths):
print(f"Invalid Input. {fail} is not a directory.", file=sys.stderr) logging.error(f"Invalid Input. {fail} is not a directory.")
return 1 return 1
logging.info("Creating output directory if it doesn't exist")
if not path.isdir(output_dir): if not path.isdir(output_dir):
os.mkdir(output_dir) os.mkdir(output_dir)
@ -268,6 +302,7 @@ def main(args):
autoescape=jinja2.select_autoescape("html") autoescape=jinja2.select_autoescape("html")
) )
logging.info("Creating EpisodeList")
podcast = EpisodeList( podcast = EpisodeList(
url, url,
[], [],
@ -277,20 +312,28 @@ def main(args):
) )
split = re.compile(r"((?P<date>\d{4}-[01]?\d-[0123]?\d)-(?P<slug>.*).md)") split = re.compile(r"((?P<date>\d{4}-[01]?\d-[0123]?\d)-(?P<slug>.*).md)")
logging.info(f"Parsing all files in {input_dir}md")
for file in os.listdir(input_dir + "md"): for file in os.listdir(input_dir + "md"):
logging.info(f"File: {file}")
match = split.match(file) match = split.match(file)
logging.info(f"Match: {match}")
if not match: if not match:
print(f"Invalid filename: {file}", file=sys.stderr) logging.error(f"Invalid filename: {file}")
continue continue
date = datetime.strptime(match.group("date"), "%Y-%M-%d") date = datetime.strptime(match.group("date"), "%Y-%m-%d")
logging.info(f"Date: {date}")
slug = match.group("slug") slug = match.group("slug")
logging.info(f"Slug: {slug}")
with open(input_dir + "md/" + file) as episode: with open(input_dir + "md/" + file) as episode:
try: try:
config, show_notes = parse_file(episode) config, show_notes = parse_file(episode)
logging.info(f"Config: {config}")
logging.info(f"Show Notes: {show_notes}")
except ParseError as err: except ParseError as err:
print(f"Error while parsing file: {file}") logging.error(f"Error while parsing file: {file}")
print(err) logging.error(err)
return 2 return 2
logging.info("Appending to EpisodeList")
podcast.append( podcast.append(
Episode( Episode(
date, date,
@ -303,25 +346,34 @@ def main(args):
) )
) )
logging.info("Generating subscribe page")
with open(input_dir + "subscribe.json") as subscribe, \ with open(input_dir + "subscribe.json") as subscribe, \
open(output_dir + "subscribe.html", "w") as html: open(output_dir + "subscribe.html", "w") as html:
html.write(env.get_template("subscribe.html").render( html.write(env.get_template("subscribe.html").render(
subscribtions=json.load(subscribe) subscribtions=json.load(subscribe)
)) ))
logging.info("Generating donate page")
with open(input_dir + "donate.json") as donate, \ with open(input_dir + "donate.json") as donate, \
open(output_dir + "donate.html", "w") as html: open(output_dir + "donate.html", "w") as html:
html.write(env.get_template("donate.html").render( html.write(env.get_template("donate.html").render(
donations=json.load(donate) donations=json.load(donate)
)) ))
logging.info("Sorting podcasts")
podcast.sort() podcast.sort()
logging.info("Generating thumbnails")
podcast.generate_thumbnails() podcast.generate_thumbnails()
logging.info("Generating archives pages")
podcast.generate_archives() podcast.generate_archives()
logging.info("Generating RSS feeds")
with open(input_dir + "header.rss") as header: with open(input_dir + "header.rss") as header:
podcast.generate_rss(header.read()) podcast.generate_rss(header.read())
logging.info("Generating Site")
podcast.generate_site(root) podcast.generate_site(root)
logging.info("Copying Overrides")
shutil.copytree(input_dir + "overrides", output_dir, dirs_exist_ok=True) shutil.copytree(input_dir + "overrides", output_dir, dirs_exist_ok=True)
logging.info("Done")
return 0 return 0