LoginSignup
2
0

More than 1 year has passed since last update.

HOMIKUJI(本×おみくじ)~本のAPIで遊んでみた

Last updated at Posted at 2023-05-06

『「技術書」の読書術』を読んで

ISBNをランダムに生成してヒットした本を読むという読書法があることと、本の情報を取得できるAPIがあることを知った。

さあ、遊びの時間だ!

:closed_book:HOMIKUJI:blue_book:

使ったもの

  • openBD API(書誌情報取得)
  • LINE Messaging API
  • Node-RED(Railwayでデプロイ)

実装

Node-REDフロー図

Node-REDはロジックが複雑になればなるほど、ローコードの視覚的にわかりやすいメリットが失われていくけど、とりあえずLINE Botを動かすには便利だから使っちゃう:thumbsup:
image.png

JSON
[{"id":"91315d34cf324824","type":"tab","label":"フロー 1","disabled":false,"info":"","env":[]},{"id":"9afbcf716abb1c19","type":"http request","z":"91315d34cf324824","name":"openBD APIにリクエスト","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://api.openbd.jp/v1/get?isbn={{payload}}","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":270,"y":180,"wires":[["3c255a4604136f26"]]},{"id":"103bde5d8b1c6a0b","type":"function","z":"91315d34cf324824","name":"ISBNをランダムで生成(※翔泳社の本限定)","func":"function generateRandomNumber() {\n    return Math.floor(Math.random() * 9999) + 1;\n};\n\nfunction calcCheckDigit(isbn) {\n    const digits = isbn.split(\"\").map((digit) => parseInt(digit));\n    const sum = digits.reduce((acc, digit, index) => {\n        return acc + (index % 2 === 0 ? digit * 1 : digit * 3);\n    }, 0);\n    return (10 - (sum % 10)) % 10;\n};\n\nfunction generateIsbn() {\n    const randomNumberAsStr = generateRandomNumber()\n        .toString()\n        .padStart(4, \"0\");\n    const isbn = `97847981${randomNumberAsStr}`;\n    return `${isbn}${calcCheckDigit(isbn)}`;\n};\n\nmsg.payload = generateIsbn();\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":230,"y":120,"wires":[["9afbcf716abb1c19"]]},{"id":"3c255a4604136f26","type":"switch","z":"91315d34cf324824","name":"本情報を取得できたかどうか判定","property":"payload[0]","propertyType":"jsonata","rules":[{"t":"null"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":540,"y":180,"wires":[["febbdb7b7c397598"],["a146a5bfcd9b4bf0"]]},{"id":"febbdb7b7c397598","type":"change","z":"91315d34cf324824","name":"本情報を取得できなかった","rules":[{"t":"set","p":"payload","pt":"msg","to":"ハズレ!残念!今日はスマホをいじって過ごそう!","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":780,"y":120,"wires":[["0e00e6e8a89fa1ee"]]},{"id":"a146a5bfcd9b4bf0","type":"change","z":"91315d34cf324824","name":"本情報を取得できた","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload[0].summary.title","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":240,"wires":[["43f73f7c25930fa6"]]},{"id":"e932759c5e2634b8","type":"Webhook","z":"91315d34cf324824","name":"","url":"/webhook","x":80,"y":360,"wires":[["2ef1373e0bc7a1c7"]]},{"id":"0e00e6e8a89fa1ee","type":"ReplyMessage","z":"91315d34cf324824","name":"","replyMessage":"","x":860,"y":240,"wires":[]},{"id":"43f73f7c25930fa6","type":"template","z":"91315d34cf324824","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"『{{payload}}』を読もう!最高の一日になるよ!","output":"str","x":660,"y":240,"wires":[["0e00e6e8a89fa1ee"]]},{"id":"2ef1373e0bc7a1c7","type":"switch","z":"91315d34cf324824","name":"「今日読むべき本は」と聞かれたかどうか判定","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"今日読むべき本は","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":340,"y":360,"wires":[["103bde5d8b1c6a0b"],["3a332d34744835b2"]]},{"id":"3a332d34744835b2","type":"change","z":"91315d34cf324824","name":"デフォルトのリプライ","rules":[{"t":"set","p":"payload","pt":"msg","to":"「今日読むべき本は?」と聞いてね!","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":660,"y":360,"wires":[["0e00e6e8a89fa1ee"]]}]

ランダムに生成したISBNを含んだリクエストをopenBD APIに投げています。
本の情報を取得できた場合には本のタイトルを、取得できなかった場合は「ハズレ」のメッセージをLINE Botに返します。

ISBNの生成

ISBNをランダムで生成(※翔泳社の本限定)するコード
JavaScript
function generateRandomNumber() {
    return Math.floor(Math.random() * 9999) + 1;
};

function calcCheckDigit(isbn) {
    const digits = isbn.split("").map((digit) => parseInt(digit));
    const sum = digits.reduce((acc, digit, index) => {
        return acc + (index % 2 === 0 ? digit * 1 : digit * 3);
    }, 0);
    return (10 - (sum % 10)) % 10;
};

function generateIsbn() {
    const randomNumberAsStr = generateRandomNumber()
        .toString()
        .padStart(4, "0");
    const isbn = `97847981${randomNumberAsStr}`;
    return `${isbn}${calcCheckDigit(isbn)}`;
};

msg.payload = generateIsbn();

return msg;

こちらの記事を参考にさせてもらいました!
完全なくじ引き読書法を実践するためのWebページを作った

ISBNって
978(固定) - 4(日本) - [出版社記号] - 書名記号(出版社ごと) - チェックデジット
というルールで採番されてるの知ってた?私は知らなかった。

このチェックデジットの計算方法が、
左から奇数桁の合計 + 左から偶数桁の合計 * 3 の下一桁を10から引いた値
という実装するのがちょいめんどくさい計算方法だったので、↑の記事が大変助かりました:pray:

翔泳社の本限定(出版社記号7981)にしているのは、ISBNを完全ランダムにすると全然ヒットしないからです。↑に載せているツイートの動画を見てもらえばお分かりかと思いますが、翔泳社限定にしてもヒット率2割以下です:sweat_smile:
それだけ世の中にはたくさんの本があるということですね:book:

今後やりたいこと

図書館APIと組み合わせたい!
ランダムに本をピックアップ

現在地近くでその本が読める図書館を提示
なーんてできたらおもしろそう:relaxed:

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0