見出し画像

【GAS×LINEMessagingAPI】大学のバスが残り何分で来るのか教えてくれるLINEBotを作ってみた!いつもやるめんどくさいことを自動化する!

はじめに

みなさんこんにちは!しげ(@EngineerShige)です!

この記事は、大学3年から未経験でプログラミングの学習を始め、アウトプットのポートフォリオとしてLINEBotを製作したお話です。Qiitaで読みたい方はこちらから!内容は同じです!

プログラミング学習を始めてから約3か月目で製作することのできる知識量をインプットすることができました。この記事を読み、より多くの人のプログラミング学習の糧になると幸いです。

コメント、アドバイス、感想などたくさんお待ちしております!

完成したものはこちらです☟

画像1

1.そもそもGASとは?

まず、この記事を読んでいる人の中にはGASとはなんのことなのか。まだわからない人がいるのではないかなと思います。そのような人にこそ、この記事を読んでいただき実際に作品を作ることの楽しさを経験して欲しいと思っています!

GASとは、Google Apps Scriptの頭文字を取ったもので、Googleが提供しているプログラミング言語です。少し難しく感じるかもしれませんが触れてみるとすごく簡単なのでぜひ触ってみることをお勧めします。

簡単に説明をしますと、GmailやGoogleドライブ、GoogleマップなどのGoogleが提供しているさまざまなサービスを連携して活用することができるものです。

詳しくは、私がこの開発をするにあたって大変お世話になったこちらの記事を参考にすることをお勧めします!
GASでできることや、GASとはなにかというのが詳しく書いていますのでとても参考になります。

2.背景

大学で毎日のように使っている通学バス。大学に行くとき、電車を降りるときにバスの時刻をチェック!大学から帰るとき、あと何分でバスが来るのか時刻表をチェック!
もーーーーうめんどくさいーーーーーーーーーーー!!!!!
超絶めんどくさがり屋な私だからこそ開発しようと思ったのかもしれません笑
ということで作ってこー!!!

3.基本機能

1.LINEBotを開くとリッチメニューが起動し、6パターンの行先を選択することができる。
2.選択すると、その行先を示した文字がワンタップで送信される。
3.送信された行先に対して、残り何分でバスが来るのかをBot側が返信してくれる。

4.開発環境

GoogleSpreadSheet,GoogleAppsScript,LINEMessagingAPI

5.製作工程

1.GoogleSpreadSheetに使うバス時刻を記入する
2.LINE Developersの登録
3.ひとまず、LINEBotを作成してみる。なにに対しても反応するBotを作ってみる!
4.バスが来る時刻と現在の時刻との差を返す関数を作る!
5.LINEで返信できるようにする
6.最後にリッチーメニューの導入!

6.実際に作ってみる

6-1.GoogleSpreadSheetに使うバス時刻を記入する
一番左のA列が時間を示している。時刻に対して行ごとに時刻が早い順番に時刻表を作成していく。

スクリーンショット 2020-07-05 12.03.38

6-2.LINE Developersの登録
こちらからLINE Developersを開いてください。
開きましたら、自身のLINEアカウントでログインを行います。
ログインできたら次のステップです!
※次のステップでかなり使うことになります。

6-3.ひとまず、LINEBotを作成してみる。なにに対しても反応するBotを作ってみる!
こちらは私が参考にさせて頂いた記事がすごくわかりやすいのでそちらを参考に製作してみてください!記事はこちら
記事内ではスプレッドシートを新たに作成していますが、先ほど作った時刻表のスプレッドシートを使います。注意としてはアクセストークンを間違えないことと、コードを書いたらWebアプリとして導入して、表示されたURLをLINE DevelopersのWebhookにしっかりと結びつけることです。

んごBotは作れたでしょうか?笑 んごBotで遊びすぎないように!笑
完成したら次のステップです!
なんとなくわかったと思いますが、このBotの返信を残り時刻にすればOKなんです!
よし!関数を作るぞ!

6-4.バスが来る時刻と現在の時刻との差を返す関数を作る!

画像3

まず最初にやることは、時刻表と時刻の取得です!
んごBotの関数とは別に関数を作っていきます。
以下がコードです。(『//』はコメントアウトすることのできるコード。)

function myFunction1() {
 var today = new Date(); //Dateのデータを取得
 var hour = today.getHours(); //今の時刻を取得
 var minutes = today.getMinutes(); //今何分かを取得
 var dayofweek = today.getDay(); //曜日を取得(平日と休日でダイヤルが違うため。)

 const ss = SpreadsheetApp.getActiveSpreadsheet(); //シートの情報を取得
 const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('高坂から大学'); //使用するシートのデータを取得
 
 if(dayofweek != 6){ //土曜日かどうかの条件分岐
   var hour_data = sheet.getRange('A8:A19').getValues(); //バスデータ取得(時間)
   var minutes_data = sheet.getRange('B8:N19').getValues(); //バスデータ取得(分)

 }else{
   var hour_data = sheet.getRange('A22:A32').getValues(); //バスデータ取得(時間)
   var minutes_data = sheet.getRange('B22:F32').getValues(); //バスデータ取得(分)  
 }
}

※dayofweekが土曜日である6の時は休日ダイヤルを、それ以外の時は平日ダイヤルの範囲を選択しています。

これで情報が読み込めたので、ここから関数を作っていきます!(myFunction1()の中に追加していきます。)

let time_table = {}; //配列の変数を定義
 var i = 0;

 for(key of hour_data){ //[時間][分]となる、dataの2次元配列を作る。
   time_table[key] = minutes_data[i].filter(v => !!v); //すべての時刻と分を配列に変換する(filterでデータがあるところまでを変換している。)
   i++;
 }

 var length = time_table[hour].length; //時間ごとに何個データがあるかを計算

//以下は場合分けして、残り何分で来るのかを計算する関数。
 for(let j = 0; j < length; j++){
   if(minutes <= time_table[hour][j]){
     var time = time_table[hour][j] - minutes;
     var time ="あと" + time + "分です!";
     break;
   }
   else if(minutes > time_table[hour][j] && minutes < time_table[hour][j+1]){
     var time = time_table[hour][j+1] - minutes;
     var time ="あと" + time + "分です!";
     break;
   }
   else if(minutes === time_table[hour][0]){
     var time = "今到着しています。次の到着は" + (time_table[hour][j+2] - minutes) + "分です!";
     console.log(time);
     break;
   }
   else if(minutes > time_table[hour][j] && minutes === time_table[hour][j+1] && minutes < time_table[hour][length-1]){
     var time = "今到着しています。次の到着は" + (time_table[hour][j+2] - minutes) + "分です!";
     console.log(time);
     break;
   }
   else if(minutes === time_table[hour][length-1]){
     var time = "今到着しています。次の到着は" + (60 - minutes + time_table[hour+1][0]) + "分です!";
     console.log(time);
     break;
   }
   else if(minutes > time_table[hour][length-1] && time_table[hour][j] === time_table[hour][length-1]){
     var time = 60 - minutes + time_table[hour+1][0];
     var time ="あと" + time + "分です!";
   }
     }
   return time;

​これで残り何分なのかを出す関数が完成しました!!!
時刻がない時は反応しないなど、まだところどころうまくいっていないので修正していこうと思っています!
あとは、この関数と時刻表のスプレッドシートを複数パターン分用意してあげて、メインのLINE返信用の関数で条件分岐して適切な結果を返すようにすればOKです。

6-5.LINEで返信できるようにする
具体的には、以下の手順です。
送られてきたものを認識→条件に沿って関数を選択→返信が実行される
コードは以下の通りです!

//CHANNEL_ACCESS_TOKENを設定
//LINE developerで登録をした、自分のCHANNEL_ACCESS_TOKENを入れて下さい
var CHANNEL_ACCESS_TOKEN = '自分のCHANNEL_ACCESS_TOKEN'; 
var line_endpoint = 'https://api.line.me/v2/bot/message/reply';

//ポストで送られてくるので、ポストデータ取得
//JSONをパースする
function doPost(e) {
 var json = JSON.parse(e.postData.contents);

 //返信するためのトークン取得
 var reply_token= json.events[0].replyToken;
 if (typeof reply_token === 'undefined') {
   return;
 }

 //送られたLINEメッセージを取得
 var user_message = json.events[0].message.text;  

 //返信する内容を作成
 var reply_messages;
 if ('高坂→大学' == user_message) {
   reply_messages = [myFunction1()];

 } else if ('大学→高坂' == user_message) {
   reply_messages = [myFunction2()];

 } else if ('北坂戸→大学' == user_message) {
   reply_messages = [myFunction3()];

 }else if ('大学→北坂戸' == user_message) {
   reply_messages = [myFunction4()];

 }else if ('熊谷→大学' == user_message) {
   reply_messages = [myFunction5()];

 }else if ('大学→熊谷' == user_message) {
   reply_messages = [myFunction6()];
 }

 // メッセージを返信
 var messages = reply_messages.map(function (v) {
   return {'type': 'text', 'text': v};    
 });    
 UrlFetchApp.fetch(line_endpoint, {
   'headers': {
     'Content-Type': 'application/json; charset=UTF-8',
     'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN,
   },
   'method': 'post',
   'payload': JSON.stringify({
     'replyToken': reply_token,
     'messages': messages,
   }),
 });
 return ContentService.createTextOutput(JSON.stringify({'content': 'post ok'})).setMimeType(ContentService.MimeType.JSON);
}

6-6.最後にリッチーメニューの導入!
こちらからLINE Official Account Managerにアクセスしログインします。
作ったBotを選択して、左のサイドバーからリッチーメニューを選択します。

スクリーンショット 2020-07-15 16.44.55

作成をクリックし作成していきます!
表示期間なども決めることが可能です。今回は今年度までの期間にしています。
コンテンツ設定で、好きなリッチーメニューを作ります。GUIで作成可能なので超簡単です!

スクリーンショット 2020-07-15 16.52.19

保存を押せば完成です~!
リッチーメニューつけると公式感が出ていいです~~~!

画像6

7.最後に

最後までお読みいただきありがとうございます。
もしこのアカウントを使ってみたいという方がいらっしゃいましたら下記から登録可能ですので、実際に使ってみてください!
ID:@612vvufs

スクリーンショット 2020-07-15 16.56.36

今回実際に作ってみて最も感じたことはアウトプットと仲間の大切さです!
プログラミング学習を始めた当初は、inputだけであまり楽しくないし、わからないことだらけで挫折寸前でした。そんなときに出会ったのがinteeリアルカレッジでした。inteeリアルカレッジでは、現役のエンジニアさんから指導を受けながら未経験からポートフォリオ作品を作成するというものです。質問をできる環境と、そこで出会った仲間に教えてもらったり、横のつながりができたことが大きいかなと思います。また、自分が欲しいものを作りたい思いが一番の学習意欲になりました!

ここで、私がプログラミング学習をするうえで利用したサービスを紹介させていただきます。
今回このBotを作ることになった背景には、私がプログラミングを学習するために活用しているinteeというサービスがあります。inteeとは、スキルアップ型キャリア支援サービスで、就活をしている学生が使うことのできるサービスとなっています。理想のキャリア設計から必要なスキル(プログラミングなど)、ハイレベルな企業とのマッチングまで支援していただけるサービスとなっています。そのサービスの中で、GASなどを用いてポートフォリオ作品を作ることのできるサービスinteeリアルカレッジを私は利用させていただきました。始めた当初はほんとにHTML/CSSもままならないほどのレベルでした。。。すごく成長できますし、貴重な経験ができ、人脈も広がりとてもよかったです!

未経験だけど力をつけたい人、自分の力でサービスを作れるようになりたい人、チャレンジしてみたい人などにとてもおすすめです!気になった人はぜひ参加してみてください!

Twitterで活動や、学んだこと、おすすめの情報など投稿していますのでよろしければフォローをお願いします!!!Twitterアカウント

この記事がいいと思った方は、いいねやSNSでの共有そしてしげをフォローしていただけると大変喜びます!

最後の最後までお読みいただきありがとうございました!

この記事が気に入ったらサポートをしてみませんか?