Support formats; add a "currently reading" page
[books.alexwlchan.net] / scripts / add_book.py
1 #!/usr/bin/env python
2
3 import datetime
4 import os
5 import re
6 import subprocess
7 from urllib.request import urlretrieve
8
9 import frontmatter
10 import inquirer
11 from unidecode import unidecode
12
13
14 def slugify(u):
15     """Convert Unicode string into blog slug."""
16     # https://leancrew.com/all-this/2014/10/asciifying/
17     u = re.sub("[–—/:;,.]", "-", u)  # replace separating punctuation
18     a = unidecode(u).lower()  # best ASCII substitutions, lowercased
19     a = re.sub(r"[^a-z0-9 -]", "", a)  # delete any other characters
20     a = a.replace(" ", "-")  # spaces to hyphens
21     a = re.sub(r"-+", "-", a)  # condense repeated hyphens
22     return a
23
24
25 def get_book_info():
26     questions = [
27         inquirer.List(
28             "entry_type",
29             message="What type of book is this?",
30             choices=[
31                 "one I’ve read",
32                 "one I’m currently reading",
33                 "one I want to read",
34             ],
35         ),
36         inquirer.Text("title", message="What’s the title of the book?"),
37         inquirer.Text("author", message="Who’s the author?"),
38         inquirer.Text("publication_year", message="When was it published?"),
39         inquirer.Text("cover_image_url", message="What’s the cover URL?"),
40         inquirer.Text("cover_desc", message="What’s the cover?"),
41         inquirer.Text("isbn10", message="Do you know the ISBN-10?"),
42         inquirer.Text("isbn13", message="Do you know the ISBN-13?"),
43     ]
44
45     answers = inquirer.prompt(questions)
46
47     answers["entry_type"] = {
48         "one I’ve read": "reviews",
49         "one I’m currently reading": "currently_reading",
50         "one I want to read": "plans",
51     }[answers["entry_type"]]
52
53     return answers
54
55
56 def get_review_info():
57     date_read_question1 = [
58         inquirer.List(
59             "date_read",
60             message="When did you finish reading it?",
61             choices=["today", "yesterday", "another day"],
62         )
63     ]
64
65     date_read = inquirer.prompt(date_read_question1)["date_read"]
66
67     today = datetime.datetime.now()
68
69     if date_read == "today":
70         date_read = today.strftime("%Y-%m-%d")
71     elif date_read == "yesterday":
72         yesterday = today - datetime.timedelta(days=1)
73         date_read = yesterday.strftime("%Y-%m-%d")
74     else:
75         date_read_question2 = [
76             inquirer.Text("date_read", message="When did you finish reading it?")
77         ]
78
79         date_read = inquirer.prompt(date_read_question2)["date_read"]
80
81     other_questions = [
82         inquirer.List(
83             "rating",
84             message="When’s your rating?",
85             choices=["★★★★★", "★★★★☆", "★★★☆☆", "★★☆☆☆", "★☆☆☆☆"],
86         ),
87         inquirer.Text("format", message="What format did you read it in?"),
88     ]
89
90     answers = inquirer.prompt(other_questions)
91     rating = int(["rating"].count("★"))
92
93     return {"date_read": date_read, "rating": rating, "format": answers["format"]}
94
95
96 if __name__ == "__main__":
97     book_info = get_book_info()
98
99     slug = slugify(book_info["title"])
100
101     filename, _ = urlretrieve(book_info["cover_image_url"])
102     extension = os.path.splitext(book_info["cover_image_url"])[-1]
103     cover_name = f"{slug}{extension}"
104     os.rename(filename, f"src/covers/{cover_name}")
105
106     new_entry = {
107         "book": {
108             "title": book_info["title"],
109             "author": book_info["author"],
110             "publication_year": book_info["publication_year"],
111             "cover_image": cover_name,
112         }
113     }
114
115     for key in ("cover_desc", "isbn10", "isbn13"):
116         if book_info[key]:
117             new_entry["book"][key] = book_info[key]
118
119     if book_info["entry_type"] == "reviews":
120         review_info = get_review_info()
121
122         new_entry["review"] = {
123             "date_read": review_info["date_read"],
124             "rating": review_info["rating"],
125             "format": review_info["format"],
126         }
127
128         year = review_info["date_read"][:4]
129         out_dir = f"reviews/{year}"
130     else:
131         out_dir = book_info["entry_type"]
132
133     out_path = os.path.join("src", out_dir, f"{slug}.md")
134     os.makedirs(os.path.dirname(out_path), exist_ok=True)
135
136     with open(out_path, "wb") as out_file:
137         frontmatter.dump(frontmatter.Post(content="", **new_entry), out_file)
138         out_file.write(b"\n")
139
140     subprocess.check_call(["open", out_path])