Book reviews

This commit is contained in:
JP Hastings-Spital 2023-07-26 21:00:28 +01:00
parent cfb50a5961
commit 9efc6b93db
27 changed files with 516 additions and 14 deletions

View file

@ -1,4 +1,3 @@
relativeURLs = true
languageCode = "en-gb"
theme = "hello-friend-ng"
@ -9,6 +8,7 @@ PygmentsStyle = "monokai"
# disqusShortname = ""
canonifyURLs = true
relativeURLs = true
enableRobotsTXT = true
enableGitInfo = false

View file

@ -1,11 +1,10 @@
---
title: Einstein's Dream
title: Einstein's Dreams
subtitle: A book by Alan Lightman
type: review
date: 2013-05-08
emoji: 📖
date: "2013-05-10T00:00:00Z"
emoji: "\U0001F4D6"
draft: false
images:
tags:
- imported
- from-goodreads
@ -13,7 +12,7 @@ syndications:
- https://www.goodreads.com/review/show/610034736
---
{{< book "9781400077809" >}}
{{< openlibrary "9781400077809" >}}
A wonderful series of glimpses of strange worlds where time is fundamentally different - an insight into the weird and wonderful worlds Einstein must have dreamt through in his Annus Mirabilis.

View file

@ -0,0 +1,17 @@
---
title: Accelerando (Singularity)
subtitle: A book by Charles Stross
type: review
date: "2013-05-01T00:00:00Z"
emoji: "\U0001F4D6"
draft: false
tags:
- imported
- from-goodreads
syndications:
- https://www.goodreads.com/review/show/604252422
---
{{< openlibrary "9780441014156" >}}
An interesting and gripping book with food for much deep thought on the nature of morality, but the "story over many generations" format has always left me feeling as though I've read a group of short stories, each with an unsatisfactory end.

View file

@ -0,0 +1,17 @@
---
title: Incidences
subtitle: A book by Daniil Kharms
type: review
date: "2011-10-16T00:00:00Z"
emoji: "\U0001F4D6"
draft: false
tags:
- imported
- from-goodreads
syndications:
- https://www.goodreads.com/review/show/111896935
---
{{< openlibrary "9781852424800" >}}
I really love the style of his almost ridiculously brief short stories — they contain a lot for so few lines!

View file

@ -0,0 +1,17 @@
---
title: Ready Player One
subtitle: A book by Ernest Cline
type: review
date: "2011-08-25T00:00:00Z"
emoji: "\U0001F4D6"
draft: false
tags:
- imported
- from-goodreads
syndications:
- https://www.goodreads.com/review/show/202287308
---
{{< openlibrary "9780307887436" >}}
I absolutely demolished this book - it's a completely engrossing tale, well worth a read!

View file

@ -0,0 +1,17 @@
---
title: Consider Phlebas
subtitle: A book by Iain M. Banks
type: review
date: "2012-04-21T00:00:00Z"
emoji: "\U0001F4D6"
draft: false
tags:
- imported
- from-goodreads
syndications:
- https://www.goodreads.com/review/show/316204375
---
{{< openlibrary "9781857231380" >}}
Great story, satisfying if saddening end.

View file

@ -0,0 +1,17 @@
---
title: Lost in a Good Book
subtitle: A book by Jasper Fforde
type: review
date: "2013-08-18T00:00:00Z"
emoji: "\U0001F4D6"
draft: false
tags:
- imported
- from-goodreads
syndications:
- https://www.goodreads.com/review/show/695460156
---
{{< openlibrary "9780142004036" >}}
Very enjoyable, though a little indistinct from the Jane Eyre affair, I think it stands as part of the series but not so much on its own.

View file

@ -0,0 +1,17 @@
---
title: The Eyre Affair
subtitle: A book by Jasper Fforde
type: review
date: "2013-08-10T00:00:00Z"
emoji: "\U0001F4D6"
draft: false
tags:
- imported
- from-goodreads
syndications:
- https://www.goodreads.com/review/show/687343966
---
{{< openlibrary "9780142001806" >}}
Charmingly written, with an interesting plot, deep characters and a very interesting precepts - well worth a read!

View file

@ -0,0 +1,21 @@
---
title: The Consuming Fire
subtitle: A book by John Scalzi
type: review
date: "2018-10-20T00:00:00Z"
emoji: "\U0001F4D6"
draft: false
tags:
- imported
- from-goodreads
syndications:
- https://www.goodreads.com/review/show/2569740480
---
{{< openlibrary "9781509835171" >}}
Completely engaging, I breezed through this book like I do all Scalzi's work — great fun!
## Quotes
> Confidence isnt about knowing youre right. Confidence is about knowing you can make it right.

View file

@ -0,0 +1,19 @@
---
title: The Human Division
subtitle: A book by John Scalzi
type: review
date: "2013-05-01T00:00:00Z"
emoji: "\U0001F4D6"
draft: false
tags:
- imported
- from-goodreads
syndications:
- https://www.goodreads.com/review/show/604255023
---
{{< openlibrary "9780765333513" >}}
Wonderful! The serialisation of this book was perfect for the story and I was always looking forward to Tuesday mornings when my Kindle would update with the latest edition.
I find myself looking for a sequel.

View file

@ -2,10 +2,9 @@
title: Intrusion
subtitle: A book by Ken MacLeod
type: review
date: 2013-04-20
emoji: 📖
date: "2013-04-20T00:00:00Z"
emoji: "\U0001F4D6"
draft: false
images:
tags:
- imported
- from-goodreads
@ -13,6 +12,6 @@ syndications:
- https://www.goodreads.com/review/show/566131190
---
{{< book "9781841499390" >}}
{{< openlibrary "9781841499390" >}}
A very well written book with a good combination of mystery, politics, scientific fact and deep characters. Occasionally the technical talk may be overwhelming (for me it was with the politics, but there's some chemistry, technology and a little law) but it's skilfully placed to not hand-hold those with technical knowledge while allowing those without the specific knowledge enough to follow the story.

View file

@ -1,9 +1,9 @@
---
title: 2312
title: "2312"
subtitle: A book by Kim Stanley Robinson
type: review
date: 2013-05-01
emoji: 📖
date: "2013-04-01T00:00:00Z"
emoji: "\U0001F4D6"
draft: false
tags:
- imported
@ -12,7 +12,7 @@ syndications:
- https://www.goodreads.com/review/show/604253366
---
{{< book "9780316098120" >}}
{{< openlibrary "9780316098120" >}}
Tough reading at times, I often got the nagging feeling that the author was trying to impress me with his (obviously deep and detailed) knowledge of a wide variety of topics above telling a story. This did lend to the feel of the book as a kind of fictional historical text (which I think was the intention), but I did put the book down once without the intention of picking it up again.

View file

@ -0,0 +1,17 @@
---
title: Make Good Art
subtitle: A book by Neil Gaiman
type: review
date: "2014-01-02T00:00:00Z"
emoji: "\U0001F4D6"
draft: false
tags:
- imported
- from-goodreads
syndications:
- https://www.goodreads.com/review/show/808658340
---
{{< openlibrary "9780062266767" >}}
A lovely little speech with printed in an interesting and expressive way (if occasionally slightly irritating on the first read!). Well worth reading if you ever have or ever will make things.

View file

@ -0,0 +1,17 @@
---
title: The Unlikely Pilgrimage of Harold Fry
subtitle: A book by Rachel Joyce
type: review
date: "2013-08-03T00:00:00Z"
emoji: "\U0001F4D6"
draft: false
tags:
- imported
- from-goodreads
syndications:
- https://www.goodreads.com/review/show/687343274
---
{{< openlibrary "9780812993295" >}}
A wonderfully simple story about a man who ends up doing something he believes in. Easy to breeze through, it's a wholly satisfying read.

View file

@ -0,0 +1,17 @@
---
title: 'QED: The Strange Theory of Light and Matter'
subtitle: A book by Richard P. Feynman
type: review
date: "2011-10-15T00:00:00Z"
emoji: "\U0001F4D6"
draft: false
tags:
- imported
- from-goodreads
syndications:
- https://www.goodreads.com/review/show/224218792
---
{{< openlibrary "9780140125054" >}}
Always a pleasure to read. Even having covered the content during my Physics degree his style is a pleasure to get into and his analogies work as well for a physicist as I'm sure they would have done for Alix.

View file

@ -0,0 +1,17 @@
---
title: Mr. Penumbra's 24-Hour Bookstore
subtitle: A book by Robin Sloan
type: review
date: "2013-08-23T00:00:00Z"
emoji: "\U0001F4D6"
draft: false
tags:
- imported
- from-goodreads
syndications:
- https://www.goodreads.com/review/show/698555776
---
{{< openlibrary "9781782391210" >}}
This is a superb book. Inspiring, permanently thrilling, believable but without trying to be, witty and laugh-out-loud funny in places I can't recommend it enough.

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

View file

@ -0,0 +1,17 @@
---
title: Poor Yorick
subtitle: A book by Ryan North
type: review
date: "2014-01-01T00:00:00Z"
emoji: "\U0001F4D6"
draft: false
tags:
- imported
- from-goodreads
syndications:
- https://www.goodreads.com/review/show/808640102
---
{{< openlibrary "OL49208407M" >}}
Ridiculous and fun - a short, choose-your-own-journey story with much nifty reference to Hamlet.

View file

@ -0,0 +1,17 @@
---
title: The Raw Shark Texts
subtitle: A book by Steven Hall
type: review
date: "2014-04-02T00:00:00Z"
emoji: "\U0001F4D6"
draft: false
tags:
- imported
- from-goodreads
syndications:
- https://www.goodreads.com/review/show/879236135
---
{{< openlibrary "9781847670243" >}}
Took me a while to get into it, but the concept is excellent and Hall doesn't assume the reader is an idiot - I get the feeling I'm going to need to read it again and hunt down the unchapters though…

View file

@ -0,0 +1,17 @@
---
title: Sourcery
subtitle: A book by Terry Pratchett
type: review
date: "2010-07-09T00:00:00Z"
emoji: "\U0001F4D6"
draft: false
tags:
- imported
- from-goodreads
syndications:
- https://www.goodreads.com/review/show/111897239
---
{{< openlibrary "9780061367779" >}}
As always, a joy to read, but I sometimes felt a little overwhelmed by the lengthy passages of metaphor.

View file

@ -0,0 +1,18 @@
<div class="book">
{{ with .cover }}
<img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="The cover of this book">
{{ end }}
<strong><a href="{{ .url }}" target="_blank">{{ .title }}</a></strong>
<ol>
{{ range .authors }}
<li><a href="{{ .url }}" target="_blank">{{ .name }}</a></li>
{{ end }}
</ol>
<ul>
{{ range .subjects }}
<li>{{ . }}</li>
{{ end }}
</ul>
</div>

View file

@ -0,0 +1,32 @@
{{ $isbn := .Get 0 }}
{{ $path := .Page.Path }}
{{ $query := (dict "type" "/type/edition" "isbn_13" $isbn) | jsonify }}
{{ $thing := getJSON (printf "https://openlibrary.org/api/things?query=%s" ($query)) }}
{{ if and (eq $thing.status "ok") (ge (len $thing.result) 1) }}
{{ $key := index $thing.result 0 }}
{{ $bookObj := getJSON (printf "https://openlibrary.org/api/get?key=%s" $key) }}
{{ if eq $bookObj.status "ok" }}
{{ $authors := slice }}
{{ range $bookObj.result.authors }}
{{ $authorObj := getJSON (printf "https://openlibrary.org/api/get?key=%s" .key) }}
{{ if eq $authorObj.status "ok" }}
{{ $authors = $authors | append (dict "name" $authorObj.result.name "url" (printf "https://openlibrary.org%s" $authorObj.result.key)) }}
{{ end }}
{{ end }}
{{/* TODO: Perhaps I nede to parse this a bit */}}
{{ $subjects := $bookObj.result.subjects }}
{{ $cover := "" }}
{{ with resources.GetRemote (printf "https://covers.openlibrary.org/b/isbn/%s-M.jpg" $isbn) }}
{{ with .Err }}
{{ else }}
{{ $cover = .Content | resources.FromString (replaceRE `\.md$` ".jpg" $path) }}
{{ end }}
{{ end }}
{{ $book := dict "title" $bookObj.result.title "authors" $authors "url" (printf "https://openlibrary.org%s" $key) "cover" $cover "subjects" $subjects }}
{{ partial "book.html" $book }}
{{ end }}
{{ end }}

View file

@ -0,0 +1,5 @@
module github.com/jphastings/www.byjp.me/tools/archive/goodreads
go 1.20
require gopkg.in/yaml.v2 v2.4.0

View file

@ -0,0 +1,4 @@
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=

View file

@ -0,0 +1,181 @@
package main
import (
"encoding/csv"
"fmt"
"io"
"os"
"path"
"regexp"
"strings"
"time"
yaml "gopkg.in/yaml.v2"
)
func check(err error, msg string) {
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n %v", msg, err)
os.Exit(1)
}
}
type closer interface {
Close() error
}
func doClose(c closer, msg string) {
check(c.Close(), msg)
}
type postInfo struct {
Title string
Subtitle string
Type string
Date string
Emoji string
Draft bool
Tags []string
Syndications []string
path string
content string
}
func main() {
if len(os.Args) != 3 {
fmt.Fprintf(os.Stderr, "Usage: %s <path/to/goodreads_library_export.csv> <path/to/hugo>\n", os.Args[0])
}
csvPath := os.Args[1]
hugo := os.Args[2]
outputDir := path.Join(hugo, "content", "posts", "reviews", "books")
f, err := os.Open(csvPath)
check(err, "Unable to open csv file")
defer doClose(f, "Unable to close csv file")
postCount, err := createPosts(csv.NewReader(f), outputDir)
check(err, "Unable to create hugo posts for your goodreads data")
fmt.Printf("Success! %d Goodreads reviews were added to your hugo blog.\n", postCount)
}
var requiredFields = []string{
"ISBN13",
"Title",
"Author",
"Date Read",
"Date Added",
"My Review",
}
func createPosts(c *csv.Reader, outputDir string) (int, error) {
added := 0
headers := make(map[string]int)
for {
record, err := c.Read()
if err == io.EOF {
break
}
if err != nil {
return added, err
}
if len(headers) == 0 {
for i, h := range record {
headers[h] = i
}
for _, f := range requiredFields {
if _, ok := headers[f]; !ok {
return added, fmt.Errorf("given CSV doesn't have a %s column", f)
}
}
continue
}
m := make(map[string]string)
for _, f := range requiredFields {
m[f] = record[headers[f]]
}
if m["My Review"] == "" {
continue
}
post, err := postFromRow(m)
if err != nil {
return added, err
}
postPath := path.Join(outputDir, post.path)
if err := os.MkdirAll(path.Dir(postPath), 0755); err != nil {
return added, err
}
hugoPost, err := os.Create(postPath)
if err != nil {
return added, err
}
fmt.Fprintln(hugoPost, "---")
if err := yaml.NewEncoder(hugoPost).Encode(post); err != nil {
return added, err
}
fmt.Fprintln(hugoPost, "---")
fmt.Fprintln(hugoPost, post.content)
hugoPost.Close()
added += 1
}
return added, nil
}
func postFromRow(row map[string]string) (postInfo, error) {
reviewDate, err := time.Parse("2006/01/02", row["Date Read"])
if err != nil {
reviewDate, err = time.Parse("2006/01/02", row["Date Added"])
}
if err != nil {
return postInfo{}, err
}
isbn := row["ISBN13"][2 : len(row["ISBN13"])-1]
content := escapeMarkdown(row["My Review"])
post := postInfo{
Type: "review",
Draft: false,
Emoji: "📖",
Title: row["Title"],
Subtitle: "A book by " + row["Author"],
Tags: []string{"imported", "from-goodreads"},
Date: reviewDate.Format(time.RFC3339),
Syndications: []string{"https://www.goodreads.com/review/show/"},
content: fmt.Sprintf("\n{{< book \"%s\" >}}\n\n%s", isbn, content),
path: path.Join(kebab(row["Author"]), kebab(row["Title"])+".md"),
}
return post, nil
}
var markdownEscapable = regexp.MustCompile(`([!\[\]])`)
func escapeMarkdown(str string) string {
text := strings.ReplaceAll(str, "<br/>", "\n")
return markdownEscapable.ReplaceAllString(text, `\$1`)
}
var kebabRE = regexp.MustCompile(`[^a-z0-9-]+`)
func kebab(str string) string {
return kebabRE.ReplaceAllString(
strings.ToLower(
strings.ReplaceAll(str, "'", "")),
"-",
)
}

View file

@ -1,5 +1,8 @@
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=