GoでNotion APIとGoogle ISBN APIを使って本棚管理をする

GoでNotion APIとGoogle ISBN APIを使って本棚管理をする

スポンサーリンク

待望のnotion apiがリリースされました、この機能ずっと欲しかったので楽しみでした。

https://developers.notion.com/

今回はNotion APIのお試しとして、isbnコードからGoogleISBN APIを使ってNotionのdatabaseに情報を自動で入れるスクリプトを作りました。

作り方

Notion APIの設定

このページにアクセスして Create new integration をします。

https://www.notion.so/my-integrations

Internal Integration Token を取得して置きます。

その後API連携したいページのShareボタンから今回作成したintegrationをinviteします

今回は連携するページをtableテンプレートを用いてこのように準備しておきます

これで設定は終了です。
試しにてきとうなAPIを叩いてみるといいと思います。

curl -X GET https://api.notion.com/v1/databases -H "Authorization: Bearer {Internal Integration Token}" -H "Content-Type: application/json" -H "Notion-Version: 2021-05-13 |
jq
https://api.notion.com/v1/databases

Google ISBN API

特に設定するものはないですが、以下のように叩けます。

curl https://www.googleapis.com/books/v1/volumes?q=isbn:{ISBN} | jq

Goで叩く

Google ISBN API

[json-to-go](https://mholt.github.io/json-to-go/) を使ってJSONからStructを作ります

これを元にAPIを叩くコードを書きます。

const (
	BaseURL = "https://www.googleapis.com/books/v1/volumes?q=isbn:"
)

type GoogleISBN struct {
}

func New() *GoogleISBN {
	return &GoogleISBN{}
}

func (g *GoogleISBN) GetInfo(isbn string) (bookInfo *BookInfo, err error) {
	resp, err := http.Get(fmt.Sprintf("%s%s", BaseURL, isbn))
	if err != nil {
		return nil, err
	}
	resBytes, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	if err := json.Unmarshal(resBytes, &bookInfo); err != nil {
		return nil, err
	}

	return
}

type BookInfo struct {
	Kind       string `json:"kind"`
	Totalitems int    `json:"totalItems"`
	Items      []struct {
		Kind       string `json:"kind"`
		ID         string `json:"id"`
		Etag       string `json:"etag"`
		Selflink   string `json:"selfLink"`
		Volumeinfo struct {
			Title               string   `json:"title"`
			Subtitle            string   `json:"subtitle"`
			Authors             []string `json:"authors"`
			Publisheddate       string   `json:"publishedDate"`
			Description         string   `json:"description"`
			Industryidentifiers []struct {
				Type       string `json:"type"`
				Identifier string `json:"identifier"`
			} `json:"industryIdentifiers"`
			Readingmodes struct {
				Text  bool `json:"text"`
				Image bool `json:"image"`
			} `json:"readingModes"`
			Pagecount           int    `json:"pageCount"`
			Printtype           string `json:"printType"`
			Maturityrating      string `json:"maturityRating"`
			Allowanonlogging    bool   `json:"allowAnonLogging"`
			Contentversion      string `json:"contentVersion"`
			Panelizationsummary struct {
				Containsepubbubbles  bool `json:"containsEpubBubbles"`
				Containsimagebubbles bool `json:"containsImageBubbles"`
			} `json:"panelizationSummary"`
			Imagelinks struct {
				Smallthumbnail string `json:"smallThumbnail"`
				Thumbnail      string `json:"thumbnail"`
			} `json:"imageLinks"`
			Language            string `json:"language"`
			Previewlink         string `json:"previewLink"`
			Infolink            string `json:"infoLink"`
			Canonicalvolumelink string `json:"canonicalVolumeLink"`
		} `json:"volumeInfo"`
		Saleinfo struct {
			Country     string `json:"country"`
			Saleability string `json:"saleability"`
			Isebook     bool   `json:"isEbook"`
		} `json:"saleInfo"`
		Accessinfo struct {
			Country                string `json:"country"`
			Viewability            string `json:"viewability"`
			Embeddable             bool   `json:"embeddable"`
			Publicdomain           bool   `json:"publicDomain"`
			Texttospeechpermission string `json:"textToSpeechPermission"`
			Epub                   struct {
				Isavailable bool `json:"isAvailable"`
			} `json:"epub"`
			Pdf struct {
				Isavailable bool `json:"isAvailable"`
			} `json:"pdf"`
			Webreaderlink       string `json:"webReaderLink"`
			Accessviewstatus    string `json:"accessViewStatus"`
			Quotesharingallowed bool   `json:"quoteSharingAllowed"`
		} `json:"accessInfo"`
		Searchinfo struct {
			Textsnippet string `json:"textSnippet"`
		} `json:"searchInfo"`
	} `json:"items"`
}
https://github.com/nozo-moto/notion-library.go/blob/master/google_isbn/google_isbn.go

Notion API

同様にNotionのAPIを叩くコードも書きます。ドキュメントを参考に、jsonを組み立てるstructを作成します

https://developers.notion.com/reference/post-page
type Notion struct {
	accesstoken string
}

const (
	BASE_URL = "https://api.notion.com/v1/"
)

func New(accesstoken string) *Notion {
	return &Notion{
		accesstoken,
	}
}

func (n *Notion) NewBookShelf(databaseID, isbn, title, author, publishedDate string) *BookShelf {
	return &BookShelf{
		Parent: struct {
			DatabaseID string "json:\"database_id\""
		}{
			DatabaseID: databaseID,
		},
		Properties: struct {
			Title []struct {
				Text struct {
					Content string "json:\"content\""
				} "json:\"text\""
			} "json:\"Title\""
			Author []struct {
				Text struct {
					Content string "json:\"content\""
				} "json:\"text\""
			} "json:\"Author\""
			Publisheddate []struct {
				Text struct {
					Content string "json:\"content\""
				} "json:\"text\""
			} "json:\"PublishedDate\""
			ISBN []struct {
				Text struct {
					Content string "json:\"content\""
				} "json:\"text\""
			} "json:\"ISBN\""
		}{
			Title: []struct {
				Text struct {
					Content string "json:\"content\""
				} "json:\"text\""
			}{
				{
					Text: struct {
						Content string "json:\"content\""
					}{
						Content: title,
					},
				},
			},
			Author: []struct {
				Text struct {
					Content string "json:\"content\""
				} "json:\"text\""
			}{
				{
					Text: struct {
						Content string "json:\"content\""
					}{
						Content: author,
					},
				},
			},
			Publisheddate: []struct {
				Text struct {
					Content string "json:\"content\""
				} "json:\"text\""
			}{
				{
					Text: struct {
						Content string "json:\"content\""
					}{
						Content: publishedDate,
					},
				},
			},
			ISBN: []struct {
				Text struct {
					Content string "json:\"content\""
				} "json:\"text\""
			}{
				{
					Text: struct {
						Content string "json:\"content\""
					}{
						Content: isbn,
					},
				},
			},
		},
	}
}

type BookShelf struct {
	Parent struct {
		DatabaseID string `json:"database_id"`
	} `json:"parent"`
	Properties struct {
		Title []struct {
			Text struct {
				Content string `json:"content"`
			} `json:"text"`
		} `json:"Title"`
		Author []struct {
			Text struct {
				Content string `json:"content"`
			} `json:"text"`
		} `json:"Author"`
		Publisheddate []struct {
			Text struct {
				Content string `json:"content"`
			} `json:"text"`
		} `json:"PublishedDate"`
		ISBN []struct {
			Text struct {
				Content string `json:"content"`
			} `json:"text"`
		} `json:"ISBN"`
	} `json:"properties"`
}

func (n *Notion) PostToDB(bookShelfInfo *BookShelf) error {
	bookShelfBytes, err := json.Marshal(bookShelfInfo)
	if err != nil {
		return err
	}
	req, err := http.NewRequest(
		"POST",
		fmt.Sprintf("%s%s", BASE_URL, "pages"),
		bytes.NewBuffer([]byte(bookShelfBytes)),
	)
	if err != nil {
		return err
	}

	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Notion-Version", "2021-05-13")
	req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", n.accesstoken))

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	res, err := io.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	return nil
}
https://github.com/nozo-moto/notion-library.go

動かす

このようにして動かしてみます。

func main() {
	notionAccessToken := os.Getenv("NOTION_ACCESS_TOKEN")
	if notionAccessToken == "" {
		panic("set NOTION_ACCESS_TOKEN")
	}
	notionPageId := os.Getenv("NOTION_PAGE_ID")
	if notionPageId == "" {
		panic("set NOTION_PAGE_ID")
	}
	if len(os.Args) < 2 {
		panic("set isbn")
	}
	isbn := os.Args[1]
	googleISBN := google_isbn.New()
	notion := notion.New(notionAccessToken)

	bookInfo, err := googleISBN.GetInfo(isbn)
	if err != nil {
		panic(err)
	}

	bookInfoVolume := bookInfo.Items[0].Volumeinfo
	if err := notion.PostToDB(
		notion.NewBookShelf(
			notionPageId,
			isbn,
			bookInfoVolume.Title,
			fmt.Sprint(bookInfoVolume.Authors),
			bookInfoVolume.Publisheddate,
		),
	); err != nil {
		panic(err)
	}
}

このコードをgo run ./main.go ISBN のようにして動かすと

これで完成です。
この後バーコードリーダーと思っています。現在メルカリで注文中🚚

https://github.com/nozo-moto/notion-library.go