夏が近づき暖かくなってきました。
食品も傷みやすい季節になってきましたね!
また、在宅ワークも進み家でのお昼ご飯などのレシピにも困っているのではないでしょうか?
ということで、今回は家庭内でのフードロスが減るよう、余っている食材をメッセージするとレシピのリンクを返してくれるボットを作って見ました。
1 材料に関連したレシピがある場合:
とりあえずできた。レシピを教えてくれる。#レシピpic.twitter.com/ZRWcB88FyA
— shima-07 (@y_kawashima_) May 5, 2020
2 材料に関連したレシピがない場合(ランダムで料理のカテゴリを提案します):
ゴメスを使ってレシピは知らない。
— shima-07 (@y_kawashima_) May 5, 2020
ラミレスも。#レシピpic.twitter.com/MR6EvBx9aP
※ カルーセルやボタンテンプレートのサムネはprotoout studioさんの可愛いアイコンをかりました。
では説明していきます。
前提
基本的なLINEbotの作り方はここではあまり詳しく書かないので、初めての方は下記ページを参考にしてみてください。
1時間でLINE BOTを作るハンズオン (資料+レポート) in Node学園祭2017 #nodefest
楽天レシピ系API
今回、レシピに関する情報は楽天レシピカテゴリーAPIや楽天レシピカテゴリ別ランキングAPIを利用しました。
これらのAPIはドキュメントにあるように、基本的に料理のカテゴリーや、特定のカテゴリーでの上位4位までにランクインされているレシピを返してくれます。
準備
楽天レシピ系のAPIを利用するにはアプリIDの発行が必要なので、まず発行します。
発行が完了すると、APIを使うときに必要なアプリID/デベロッパーID
などの情報が表示されるのでそれはメモしておきます。
ソースコード
早速ですが、ソースコードです。
'use strict';constexpress=require('express');constline=require('@line/bot-sdk');constPORT=process.env.PORT||3000;// 追加constaxios=require('axios');constconfig={channelSecret:'xxxxxx',channelAccessToken:'xxxxxx'};constapp=express();app.get('/',(req,res)=>res.send('Hello LINE BOT!(GET)'));//ブラウザ確認用(無くても問題ない)app.post('/webhook',line.middleware(config),(req,res)=>{// LINE上で入力されたconsole.log(req.body.events[0].message.text);//ここのif文はdeveloper consoleの"接続確認"用なので後で削除して問題ないです。if(req.body.events[0].replyToken==='00000000000000000000000000000000'&&req.body.events[1].replyToken==='ffffffffffffffffffffffffffffffff'){res.send('Hello LINE BOT!(POST)');console.log('疎通確認用');return;}Promise.all(req.body.events.map(handleEvent)).then((result)=>res.json(result));});constclient=newline.Client(config);//////////////// ここ以降が処理を書く場所 ///////////////asyncfunctionhandleEvent(event){if(event.type!=='message'||event.message.type!=='text'){returnPromise.resolve(null);}letmes=''varresult=event.message.text;mes=result+'を使ったレシピ';//wikiのurlの前の一言awaitclient.replyMessage(event.replyToken,{type:'text',// text: event.message.text //実際に返信の言葉を入れる箇所text:mes});returngetMenu(event.source.userId,result);}//handleevent constgetMenu=async(userId,food)=>{constres=awaitaxios.get('https://app.rakuten.co.jp/services/api/Recipe/CategoryList/20170426?format=json&formatVersion=2&categoryType=small&applicationId='+{楽天のアプリID/デベロッパーID});varname=[];varcatgid=[];varurl=[];varlen=res.data.result.small.length;vara=0;for(vari=0;i<len;i++){if(res.data.result.small[i].categoryName.indexOf(food)>-1){name[a]=res.data.result.small[i].categoryName;catgid[a]=res.data.result.small[i].parentCategoryId;url[a]=res.data.result.small[i].categoryUrl;a=a+1;}}console.log(name);console.log(catgid);console.log(url);letcol=[];// 何も引っかからなかった時の処理if(name.length<=0){// とりあえず返事するawaitclient.pushMessage(userId,{type:'text',text:'ごめん、その食材の使い方は知らない。代わりのおすすめメニュー↓↓',});// ランダムでこの中の物を返すためのリストletcategory=[{categoryName:"人気メニュー",categoryId:"30",categoryUrl:"https://recipe.rakuten.co.jp/category/30/"},{categoryName:"定番の肉料理",categoryId:"31",categoryUrl:"https://recipe.rakuten.co.jp/category/31/"},{categoryName:"定番の魚料理",categoryId:"32",categoryUrl:"https://recipe.rakuten.co.jp/category/32/"},{categoryName:"卵料理",categoryId:"33",categoryUrl:"https://recipe.rakuten.co.jp/category/33/"},{categoryName:"パスタ",categoryId:"15",categoryUrl:"https://recipe.rakuten.co.jp/category/15/"},{categoryName:"鍋料理",categoryId:"23",categoryUrl:"https://recipe.rakuten.co.jp/category/23/"},{categoryName:"簡単料理・時短",categoryId:"36",categoryUrl:"https://recipe.rakuten.co.jp/category/36/"},{categoryName:"節約料理",categoryId:"37",categoryUrl:"https://recipe.rakuten.co.jp/category/37/"},{categoryName:"今日の献立",categoryId:"38",categoryUrl:"https://recipe.rakuten.co.jp/category/38/"},{categoryName:"健康料理",categoryId:"39",categoryUrl:"https://recipe.rakuten.co.jp/category/39/"},]varlen=category.length;varrand=Math.floor(Math.random()*(len+1));// 毎度ランダムに変わるようにするvarcategoryName=category[rand].categoryName+'のレシピだよ!';varurl=category[rand].categoryUrl;// ボタンテンプレートreturnclient.pushMessage(userId,{"type":"template","altText":"This is a buttons template","template":{"type":"buttons","thumbnailImageUrl":"{サムネにしたい画像のURL}","imageAspectRatio":"rectangle","imageSize":"cover","imageBackgroundColor":"#FFFFFF","title":"おすすめMenu","text":categoryName,"defaultAction":{"type":"uri","label":"View detail","uri":url},"actions":[{"type":"uri","label":"レシピへGO","uri":url}]}});}else{varlen2=name.length;if(len2>10){len2=10;}// カルーセルの上限が10個なので10以上ある場合は10にする// "columns" の中身を作っておく for(vark=0;k<len2;k++){consttitle=name[k];consttext=name[k]+'のレシピを紹介するよ!';consturi=url[k];letcarousel={"thumbnailImageUrl":"{サムネにしたい画像のURL}","imageBackgroundColor":"#FFFFFF","title":title,"text":text,"defaultAction":{"type":"uri","label":"View detail","uri":uri},"actions":[{"type":"uri","label":"レシピへGO","uri":uri}]};col.push(carousel);}returnclient.pushMessage(userId,{"type":"template","altText":"this is a carousel template","template":{"type":"carousel","columns":col,"imageAspectRatio":"rectangle","imageSize":"cover"}});}}(process.env.NOW_REGION)?module.exports=app:app.listen(PORT);console.log(`Server running at ${PORT}`);
説明
本当は材料をメッセージしたらその材料を使った料理を返すようにしたかったのですが、それは楽天レシピAPIをそのまま使うだけではできなかったので、まず使ったAPIは/Recipe/CategoryList
のほうをcategoryType=small
で取ることで、入力した値をヒットしやすくなります。
入力値がAPIで返ってきた値とヒットした場合は、それを配列に入れてカルーセルで出すための準備をします。
もし、「ゴメス」のようなヒットしない値だった場合は、categoryType=large
の分類のボタンテンプレートでランダムに出すようにしています。
LINEのカルーセルやボタンテンプレートなどに関しては下記が参考になります。
■楽天のAPIを使ってマスクを買えるBotを作ってみた[LINEBotリッチメニュー]
■LINEの公式ドキュメント
作ってみて
厳密に食材に対してのレシピを返してくれるわけじゃないけど、まあまあ使えると思います。
ぜひお試しください!