diff --git a/.gitignore b/.gitignore index 485dee6..c26f7aa 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ .idea +static +dist diff --git a/bookshelf.html b/bookshelf.html new file mode 100644 index 0000000..6b71d43 --- /dev/null +++ b/bookshelf.html @@ -0,0 +1,37 @@ + + + + + +
+ bookshelf +
+ +
+{% for book in books %} + +
+
+ +
+
+ {{ book.title }} by {{ book.author }} {% if book.published_year %} ({{book.published_year}}) {% endif %} +
+
+ +{% endfor %} +
+ + + \ No newline at end of file diff --git a/main.py b/main.py index 4805761..0ee17b4 100644 --- a/main.py +++ b/main.py @@ -1,17 +1,154 @@ import requests +import argparse +import os +import jinja2 -def fetch_list(list_url, page): +# LIST_URL = "https://bookwyrm.social/list/2458/s/notplants-2023" +# LIST_URL = "https://bookwyrm.social/list/2404/s/2024" + +PROJECT_PATH = os.path.abspath(os.path.dirname(__file__)) + +# output dirs +OUTPUT_DIR = os.path.join(PROJECT_PATH, 'dist') +if not os.path.exists(OUTPUT_DIR): + os.makedirs(OUTPUT_DIR) + +# input static folder +STATIC_DIR = os.path.join(PROJECT_PATH, 'static') +if not os.path.exists(STATIC_DIR): + os.makedirs(STATIC_DIR) + + +def build_site(output_dir, relative_template_path, template_vars): + + # copy over static files + input_static_dir = os.path.join(STATIC_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 + 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").replace(" ", "-") + image_title = image_title.replace(":", "") + image_path = "static/{}.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): + for item in processed_items: + image_url = item.get("cover_url") + image_path = item.get("cover_image_path") + if image_url: + print("++ downloading {}".format(image_url)) + os.system('wget {} -O "{}"'.format(image_url, image_path)) if __name__ == '__main__': - list_url = "https://wyrms.de/user/j12i/books/reading" - list = fetch_list(list_url, page=1) - list_dict = list.json() - for key, val in list_dict.items(): - print("{}: {}".format(key, val)) + parser = argparse.ArgumentParser( + prog='bookshelf-generator', + description='generates HTML for a web-page to display a bookshelf using bookwyrm or a csv as input', + epilog='<3') + + parser.add_argument('list_url') # bookwyrm list url to use as a source input + parser.add_argument('-t', '--template') # path to jinja file to use as a template for the html + + args = parser.parse_args() + print(args.list_url, args.template) + + processed_items = process_list(args.list_url) + template_vars = { + "books": processed_items + } + # download_images(processed_items) + build_site(output_dir=OUTPUT_DIR, relative_template_path=args.template, template_vars=template_vars) + + + diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..a6c7ee6 --- /dev/null +++ b/run.sh @@ -0,0 +1 @@ +python3 main.py "https://bookwyrm.social/list/2458/s/notplants-2023" --template="bookshelf.html" \ No newline at end of file