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

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

スポンサーリンク

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

Connect Notion pages and databases to the tools you use every day, creating powe…
developers.notion.com

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

作り方

Notion APIの設定

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

A new tool that blends your everyday work apps into one. It
www.notion.so

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

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"`
}
Contribute to nozo-moto/notion-library.go development by creating an account on …
github.com

Notion API

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

Connect Notion pages and databases to the tools you use every day, creating powe…
developers.notion.com
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
}
Contribute to nozo-moto/notion-library.go development by creating an account on …
github.com

動かす

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

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 のようにして動かすと

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

Contribute to nozo-moto/notion-library.go development by creating an account on …
github.com