#作りたいもの
筆者の所属団体で、鍵の借用時と返却時にボタンを押すことでログが残り、任意のタイミングで利用状況を確認できるシステム
##今まで
鍵の管理用のLINEグループでいちいち借用返却報告をしてた
→通知うざいっす
#使ったもの
プラットフォームは今まで通りLINEで
→MessagingAPIとGASでLINE bot
#概要
LINE botにキーワードを送信するとGASを動かしてspreadsheetに入力
確認用のキーワードを送信するとspreadsheetを参照して利用状況を返信してくれる
##MessagingAPIの登録
たくさん投稿があると思うので割愛
LINE Developers
RichMenuを使うことでユーザーにキーワードをミスなく入力させる事ができる。
アクセストークンを控えておく。
##GAS
新しいGASのファイルとlog用のspreadsheetを作る。
作ったGASファイルのリンクをLINE Developersの方でwebhookに貼り付ける。
var CHANNEL_ACCESS_TOKEN = '***LINE ACCESS TOKEN***';
var url = "***SHEET URL***";
var spreadsheet = SpreadsheetApp.openByUrl(url);
var sheets = spreadsheet.getSheets(); //log用のシート
function getUserName(UID){//Userの表示名取得
var url = 'https://api.line.me/v2/bot/profile/' + UID;
try {//エラー処理
var response = UrlFetchApp.fetch(url,{
'headers': {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN,
}
})
}catch(e){//表示名を取得できなかったら
return 0;
}
var json = JSON.parse(response.getContentText());
return json["displayName"]
}
function makeMsg(array){//返信用メッセージを作るやつ
var result=[];
for(var i=0;i<array.length;i++){
if (array[i] !== "closed"){
var temp = array[i].split(',');
result[i]=temp[1]+"\n"+temp[0];
} else {
result[i]=array[i];
}
}
var msg = "利用状況\n"+
"*************\n"+
"ボックス:" + result[0] + "\n"+
"会議室 : " + result[1] +"\n"+
"2北 : " + result[2];
return msg;
}
function sendMsg(reply_token,message){ //メッセージ送信
var url = 'https://api.line.me/v2/bot/message/reply';
UrlFetchApp.fetch(url, {
'headers': {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN,
},
'method': 'post',
'payload': JSON.stringify({
'replyToken': reply_token,
'messages': [{
'type': 'text',
'text': message,
}],
}),
});
}
function deleteRows(sheets){ //行削除(なくてもいい)
for(var i in sheets){
var LastRow = sheets[i].getLastRow()
if(LastRow > 6) {
sheets[i].deleteRow(2)
}
}
}
function updateSheet(room,key,value){ //sheetの操作
if (key == 'take'){
var data = sheets[room].getDataRange().getValues();
var lastrow = data.length;
if(data[lastrow-1][1]==""){
lastrow = lastrow - 1;
}
sheets[room].getRange(lastrow + 1, 1).setValue(value);
} else if (key == 'return'){
var lastrow = sheets[room].getDataRange().getLastRow();
sheets[room].getRange(lastrow, 2).setValue(value);
}
}
function doPost(e) { //イベントがあったら動く関数
var date = new Date();
var event_data = JSON.parse(e.postData.contents).events[0]
var reply_token= event_data.replyToken;
if (typeof reply_token === 'undefined') {
return;
}
var message = JSON.parse(e.postData.contents).events[0].message.text.split('-');
var user_id = JSON.parse(e.postData.contents).events[0].source.userId;
var user_name = getUserName(user_id);
var value = Utilities.formatDate( date, 'Asia/Tokyo', 'yyyy/MM/dd HH:mm') + "," + user_name + "," + user_id;
var msg = "OK!";
if (message[0] == "box"){
updateSheet(0,message[1],value)
} else if (message[0] == "meeting"){
updateSheet(1,message[1],value)
} else if (message[0] == "warehouse"){
updateSheet(2,message[1],value)
} else if (message[0]=='ログ'){
msg = url;
} else if (message[0]=='id'){
msg = user_id;
} else if (message[0]=='かぎ'){
var data_list = [];
for(var i in sheets){
var sheet_data = sheets[i].getDataRange().getValues();
var lastrow = sheet_data.length;
if(sheet_data[lastrow-1][1]==""){
data_list[i] = sheet_data[lastrow-1][0];
} else{
data_list[i] = "closed";
}
}
msg=makeMsg(data_list);
} else if(message[0] == 'ヘルプ'){
msg = "";
} else {
msg = "I'm sorry. I can't reply.";
}
deleteRows(sheets);
sendMsg(reply_token,msg);
return ContentService.createTextOutput(JSON.stringify({'content': 'post ok'})).setMimeType(ContentService.MimeType.JSON);
}
function remind(){//リマインド関数
var status_dict = {box:"", meeting:"", warehouse:""};
var key = Object.keys(status_dict);
for(var i in sheets){
var sheet_data = sheets[i].getDataRange().getValues();
var lastrow = sheet_data.length;
if(sheet_data[lastrow-1][1]==""){
status_dict[key[i]] = sheet_data[lastrow-1][0].split(',')[2];
} else{
status_dict[key[i]] = "";
}
}
for(var key in status_dict){
var text = remindMsg(key);
if(!(text =="")){
push(status_dict[key],text);
}
}
}
function remindMsg(key){//セリフ作成
var text = "";
if(key =="box"){
text = "ボックス";
} else if(key =="meeting") {
text = "会議室";
} else if(key =="warehouse") {
text = "2北";
}
return text + "の鍵は返却しましたか?返却済でしたら返却ボタンを押下してください。";
}
function push(user,text){//PUSHメッセージ送信
var url = "https://api.line.me/v2/bot/message/push";
var headers = {
"Content-Type" : "application/json; charset=UTF-8",
'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN,
};
var postData = {
"to" : user,
"messages" : [
{
'type':'text',
'text':text,
}
]
};
var options = {
"method" : "post",
"headers" : headers,
"payload" : JSON.stringify(postData),
"muteHttpExceptions": true
};
//return UrlFetchApp.fetch(url, options);
var response = UrlFetchApp.fetch(url, options);
}
参考:
LINE Botをサーバーレスで開発!Google Apps ScriptとLINE Messaging APIを使ってチャットボットを作ってみた
GASでSpreadsheetを操作する自分的ベストプラクティス
transpose 2-dimensional Javascript array in one line
#所感
今まで自己満というか遊びというかでプログラミングしてて、初めて人のためにモノを作ったんですが悪くないですね。通知から解放された友人に褒められました。
GAS(JavaScript)を触った事がなかったので(これでいいのか…???)感は否めないですが、突貫工事の割にちゃんとしたものができてよかったです。
ここをこうしたら速くなるよ!とか、こう書いた方がわかりやすい/JSではこういう作法!とかコメントいただけましたら幸いです。
おしまい
2019/06/07 GASのコードを更新しました