Merge branch 'development' of helene.linode:/mnt/repos/books.alexwlchan.net into...
[books.alexwlchan.net] / scripts / add_book.py
index df75786..aa2f7fa 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 import datetime
 import os
@@ -7,6 +7,7 @@ import subprocess
 from urllib.request import urlretrieve
 
 import frontmatter
+import hyperlink
 import inquirer
 from unidecode import unidecode
 
@@ -14,11 +15,11 @@ from unidecode import unidecode
 def slugify(u):
     """Convert Unicode string into blog slug."""
     # https://leancrew.com/all-this/2014/10/asciifying/
-    u = re.sub(u'[–—/:;,.]', '-', u)  # replace separating punctuation
-    a = unidecode(u).lower()          # best ASCII substitutions, lowercased
-    a = re.sub(r'[^a-z0-9 -]', '', a) # delete any other characters
-    a = a.replace(' ', '-')           # spaces to hyphens
-    a = re.sub(r'-+', '-', a)         # condense repeated hyphens
+    u = re.sub("[–—/:;,.]", "-", u)  # replace separating punctuation
+    a = unidecode(u).lower()  # best ASCII substitutions, lowercased
+    a = re.sub(r"[^a-z0-9 -]", "", a)  # delete any other characters
+    a = a.replace(" ", "-")  # spaces to hyphens
+    a = re.sub(r"-+", "-", a)  # condense repeated hyphens
     return a
 
 
@@ -58,7 +59,7 @@ def get_review_info():
         inquirer.List(
             "date_read",
             message="When did you finish reading it?",
-            choices=["today", "yesterday", "another day"]
+            choices=["today", "yesterday", "another day"],
         )
     ]
 
@@ -67,43 +68,91 @@ def get_review_info():
     today = datetime.datetime.now()
 
     if date_read == "today":
-        date_read = today.strftime("%Y-%m-%d")
+        date_read = today.date()
     elif date_read == "yesterday":
         yesterday = today - datetime.timedelta(days=1)
-        date_read = yesterday.strftime("%Y-%m-%d")
+        date_read = yesterday.date()
     else:
         date_read_question2 = [
-            inquirer.Text(
-                "date_read",
-                message="When did you finish reading it?"
-            )
+            inquirer.Text("date_read", message="When did you finish reading it?")
         ]
 
         date_read = inquirer.prompt(date_read_question2)["date_read"]
 
-    rating_question = [
+        if re.match(r"^\d{4}-\d{2}-\d{2}$", date_read.strip()):
+            date_read = datetime.datetime.strptime(date_read, "%Y-%m-%d").date()
+        elif re.match(r"^\d{1,2} [A-Z][a-z]+ \d{4}$", date_read.strip()):
+            date_read = datetime.datetime.strptime(date_read, "%d %B %Y").date()
+        else:
+            sys.exit("Unrecognised date: {date_read}")
+
+    other_questions = [
         inquirer.List(
             "rating",
             message="When’s your rating?",
-            choices=["★★★★★", "★★★★☆", "★★★☆☆", "★★☆☆☆", "★☆☆☆☆"]
-        )
+            choices=["★★★★★", "★★★★☆", "★★★☆☆", "★★☆☆☆", "★☆☆☆☆"],
+        ),
+        inquirer.Text("format", message="What format did you read it in?"),
     ]
 
-    rating = int(inquirer.prompt(rating_question)["rating"].count("★"))
+    answers = inquirer.prompt(other_questions)
+    format = answers["format"]
+
+    rating = int(answers["rating"].count("★"))
+    assert 1 <= rating <= 5
+
+    if rating > 3:
+        did_not_finish = False
+    else:
+        questions = [
+            inquirer.List(
+                "did_you_finish",
+                message="Did you finish the book?",
+                choices=["yes", "no"],
+            ),
+        ]
+
+        did_not_finish = inquirer.prompt(questions)["did_you_finish"] == "no"
+
+    return {
+        "date_read": date_read,
+        "rating": rating,
+        "format": format,
+        "did_not_finish": did_not_finish,
+    }
+
 
-    return {"date_read": date_read, "rating": rating}
+def save_cover(slug, cover_image_url):
+    filename, headers = urlretrieve(cover_image_url)
 
+    if headers["Content-Type"] == "image/jpeg":
+        extension = ".jpg"
+    elif headers["Content-Type"] == "image/png":
+        extension = ".png"
+    elif headers["Content-Type"] == "image/gif":
+        extension = ".gif"
+    else:
+        print(headers)
+        assert 0
+
+        url_path = hyperlink.URL.from_text(cover_image_url).path
+        extension = os.path.splitext(url_path[-1])[-1]
+
+    cover_name = f"{slug}{extension}"
+    dst_path = f"src/covers/{cover_name}"
+
+    if not os.path.exists(dst_path):
+        os.rename(filename, f"src/covers/{cover_name}")
+
+    return cover_name
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     book_info = get_book_info()
 
     slug = slugify(book_info["title"])
 
-    filename, _ = urlretrieve(book_info["cover_image_url"])
-    extension = os.path.splitext(book_info["cover_image_url"])[-1]
-    cover_name = f"{slug}{extension}"
-    os.rename(filename, f"src/covers/{cover_name}")
+    cover_name = save_cover(slug=slug, cover_image_url=book_info["cover_image_url"])
 
     new_entry = {
         "book": {
@@ -123,11 +172,20 @@ if __name__ == '__main__':
 
         new_entry["review"] = {
             "date_read": review_info["date_read"],
-            "rating": review_info["rating"]
+            "rating": review_info["rating"],
+            "format": review_info["format"],
         }
 
-        year = review_info["date_read"][:4]
+        if review_info["did_not_finish"]:
+            new_entry["review"]["did_not_finish"] = True
+
+        year = review_info["date_read"].year
         out_dir = f"reviews/{year}"
+    elif book_info["entry_type"] == "plans":
+        new_entry["plan"] = {
+            "date_added": datetime.datetime.now().date(),
+        }
+        out_dir = "plans"
     else:
         out_dir = book_info["entry_type"]
 
@@ -135,7 +193,11 @@ if __name__ == '__main__':
     os.makedirs(os.path.dirname(out_path), exist_ok=True)
 
     with open(out_path, "wb") as out_file:
-        frontmatter.dump(frontmatter.Post(content=u"", **new_entry), out_file)
+        frontmatter.dump(frontmatter.Post(content="", **new_entry), out_file)
         out_file.write(b"\n")
 
     subprocess.check_call(["open", out_path])
+
+    from render_html import main
+
+    main()