bookshelf-generator/main.py

193 lines
6.8 KiB
Python

import requests
import argparse
import os
import jinja2
import yaml
PROJECT_PATH = os.path.abspath(os.path.dirname(__file__))
def build_site(output_dir, images_dir, relative_template_path, template_vars):
# copy over static files
input_static_dir = images_dir
if not os.path.exists(output_dir):
os.makedirs(output_dir)
output_static_dir = os.path.join(output_dir, 'static')
if os.path.exists(output_static_dir):
os.system('rm -r {}'.format(output_static_dir))
print('copying static to {}'.format(output_static_dir))
os.system('cp -r {} {}'.format(input_static_dir, output_static_dir))
# render html
template_loader = jinja2.FileSystemLoader(searchpath=PROJECT_PATH)
template_env = jinja2.Environment(loader=template_loader)
page_template = template_env.get_template(relative_template_path)
page_text = page_template.render(template_vars)
output_page_path = os.path.join(output_dir, "bookshelf.html")
with open(output_page_path, 'w') as output_file:
output_file.write(page_text)
def fetch_list_page(list_url, page):
headers = {"accept": "application/ld+json"}
url = list_url + "?page={}".format(page)
result = requests.get(url, headers=headers)
return result.json()
def get_apub_object(object_url):
headers = {"accept": "application/ld+json"}
url = object_url
result = requests.get(url, headers=headers)
return result.json()
def fetch_list(list_url):
more_results = True
page = 1
all_items = []
while more_results:
try:
results = fetch_list_page(list_url=list_url, page=page)
items = results.get("orderedItems")
if items:
all_items += items
next = results.get("next")
if next:
# TODO: alternatively, this could perhaps be re-written more generally
# to use this next field to direct the pagination instead of an increment
page += 1
if not next:
more_results = False
else:
more_results = False
except:
more_results = False
return all_items
def process_list(list_url):
list_items = fetch_list(list_url)
processed_items = []
for index, book in enumerate(list_items):
base_title = book.get("title")
subtitle = book.get("subtitle")
if subtitle:
title = "{}: {}".format(base_title, subtitle)
else:
title = base_title
authors = book.get("authors")
first_author = authors[0]
author = get_apub_object(first_author)
published_date = book.get("publishedDate")
cover_url = book.get("cover").get("url")
if published_date:
published_year = published_date.split("-")[0]
else:
published_year = None
# print
to_print = "{}. {} by {}".format(index, title, author.get("name"))
if published_year:
to_print += " ({})".format(published_year)
print(to_print)
print("cover: {}".format(cover_url))
image_title = book.get("title")
image_title = ''.join(c for c in image_title if (c.isalnum() or c == " "))
image_title = image_title.replace(" ", "-")
image_title = image_title.replace(":", "")
image_path = "{}.jpg".format(image_title)
# return item
item = {
"title": title,
"author": author.get("name"),
"published_year": published_year,
"cover_url": cover_url,
"cover_image_path": image_path
}
processed_items.append(item)
return processed_items
def download_images(processed_items, output_dir):
for item in processed_items:
image_url = item.get("cover_url")
image_path = os.path.join(output_dir, item.get("cover_image_path"))
if image_url:
print("++ downloading {}".format(image_url))
os.system('wget {} -O "{}"'.format(image_url, image_path))
def write_yaml(items, output_dir):
yaml_path = os.path.join(output_dir, "books.yaml")
output = yaml.dump(items, Dumper=yaml.Dumper)
with open(yaml_path, 'w') as f:
f.write(output)
def load_yaml(yaml_path):
with open(yaml_path) as f:
contents = f.read()
books = yaml.load(contents, Loader=yaml.Loader)
return {
"books": books
}
if __name__ == '__main__':
# create parser
parser = argparse.ArgumentParser(
prog='bookshelf-generator',
description='generates HTML for a web-page to display a bookshelf using bookwyrm or a yaml as input',
epilog='<3')
# subparser for building website
subparsers = parser.add_subparsers(dest="subparser")
build_parser = subparsers.add_parser('generate-html')
bookwyrm_parser = subparsers.add_parser('bookwyrm-download')
# bookwyrm-download subparser
required_bookwyrm_args = bookwyrm_parser.add_argument_group('required named arguments')
required_bookwyrm_args.add_argument('-l', '--list-url', help="bookwyrm list url to use as a source input",
required=True)
required_bookwyrm_args.add_argument('-o', '--output-dir',
help="path where images should be downloaded and yaml should be written",
required=True)
# generate-html subparser
required_build_args = build_parser.add_argument_group('required named arguments')
required_build_args.add_argument('-i', '--images-dir', help="path to folder containing cover images", required=True)
required_build_args.add_argument('-y', '--yaml-path', help="yaml path to use as input", required=True)
required_build_args.add_argument('-t', '--template', help="path to jinja file to use as a template for the html",
required=True)
required_build_args.add_argument('-o', '--output-path', help="path to generate html inside of", required=True)
# parse args
args = parser.parse_args()
if args.subparser == "bookwyrm-download":
if not os.path.exists(args.output_dir):
os.makedirs(args.output_dir)
processed_items = process_list(args.list_url)
download_images(processed_items, output_dir=args.output_dir)
write_yaml(processed_items, output_dir=args.output_dir)
elif args.subparser == "generate-html":
yaml_path = args.yaml_path
images_dir = args.images_dir
output_path = args.output_path
template_vars = load_yaml(yaml_path)
build_site(output_dir=output_path, images_dir=images_dir, relative_template_path=args.template, template_vars=template_vars)
else:
raise Exception("invalid subcommand. must be either bookwyrm-download or generate-html")