はじめに
子供が熱を出すと、小児科で「はい、これ書いてきてね」と渡される体温記録の紙。ネット上にもいろいろあります。HAL先生のこちらとか。
でも、これがよく忘れるんですよ。体温を測ったのにすぐに書かなかったら何度だったか忘れた、点をうつ位置を間違えた、はてはせっかく書いた体温表なのに医者に持っていくのを忘れた(我が家はこれがすごく多い)。
そういうわけで、もう少し楽をすることにしました。
もともと夫婦間で情報共有のため、slackに子供のことを書く専用channelがあります。そこに体温を投稿したら、Googleスプレッドシートに登録されるようにしました。
参考サイト
Slack BotをGASでいい感じで書くためのライブラリを作った
SlackとGASを使って会社のお弁当発注を自動化した話
コードの大半はお弁当発注のものを参考にさせていただきました。ありがとうございます!
作ったもの
仕様
slackのOutgoing WebHooksを設定したchannelで
taion: 36.8
とかつぶやくと、Googleスプレッドシートに記録されます。
正常に登録できると「ok」が返ってくる。
登録される値は
- 日時
- 体温
- 登録者
デフォルトではつぶやいた日時を「日時」として採用、体温のあとにスペース区切りで時刻を入れた場合は、その時刻の記録として登録されます。
taion: 36.9 6:30
→ つぶやいた当日の6:30の記録になる。
また、当日+つぶやいた時刻が、現在時刻よりも先の場合は、前日に補正して記録します。
(12/31 7:00に以下をつぶやく)
taion: 36.7 19:00
→ 12/30 19:00の記録になる。
実装と設定
ううむ、作ったのが半年くらい前だからもう記憶が怪しい
Googleスプレッドシート側の設定
- GASコード
Const = {
spreadSheetId: 'GoogleスプレッドシートID',
sheetName: '記録するスプレッドシートのシート名',
verifyToken: 'slackのverify Token'
}
function verifyToken(e) {
return Const.verifyToken == e.parameter.token;
}
function parseRequest(e) {
var request = {};
request.user = e.parameter.user_name;
var data = parseText(e.parameter.text);
if (! data){
request.raw = e.parameter.text;
} else {
request.temp = data[0];
request.dateTime = data[1];
}
return request;
}
function parseText(str){
var reg = /(^taion:|^体温:)\s*(\d{2}\.?\d?)[℃度]?\s*(\d{1,2})?\s*[:時]?\s*(\d{1,2})?/;
var matches = str.match(reg);
if (matches) {
var temp = matches[2];
var dt = new Date();
if(matches[3] != null){
var hour = parseInt(matches[3] ? matches[3] : '0');
var min = parseInt(matches[4] ? matches[4] : '0');
dt = new Date(dt.getFullYear(), dt.getMonth(), dt.getDate(), hour, min, 0);
if (dt > new Date()){
dt = new Date(dt.getFullYear(), dt.getMonth(), dt.getDate() - 1, hour, min, 0);
}
}
return [temp, dt];
}
return null;
}
function doPost(e) {
var prop = PropertiesService.getScriptProperties().getProperties();
if (! verifyToken(e)) {
throw new Error("invalid token.");
}
var result;
if (e.parameter == undefined) {
result = 'error';
}else{
var sheet = SpreadsheetApp.openById(Const.spreadSheetId).getSheetByName(Const.sheetName);
var request = parseRequest(e);
if (request){
var array = [request.dateTime, request.temp, request.user];
if (request.raw != null){
array.push(request.raw);
}
sheet.appendRow(array);
result = 'ok';
} else {
result = 'parseError:' + e.parameter.text;
}
}
var slackApp = SlackApp.create(prop.slackToken);
slackApp.chatPostMessage(e.parameter.channel_id, result, {
username : e.parameter.user_name});
return null;
}
-
コードの簡単な説明
- slackからpostされてきた値を、tokenのverifyして、値をparseして、体温と時間を取り出し、スプレッドシートの一番下に追加して、slackに「ok」って返してます。
- slackへの返却にはSlackAppを使わせていただいています(https://qiita.com/soundTricker/items/43267609a870fc9c7453)
- function
- doPost : post時処理。
- verifyToken : slack tokenのverify処理
- parseRequest: slackから来たrequest内容のパース。user名の取得と、テキスト内容の取得。
- parseText: テキスト内容のパース。コードが超イマイチなのは自覚している。
-
GAS公開
- https://qiita.com/soundTricker/items/a4878d7e3100082576e4 あたりを参考に、ウェブアプリケーションとして導入を行った。
- ウェブアプリケーションのURLを後でslackに設定するので保存しておく
- アプリケーションにアクセスできるユーザは「全員」
-
シート作成
- シート名はコードの Const.sheetName にいれる。
- シートのA, B, C列を使う。
- 必須ではないけれど、先頭行に日時、体温、登録者をいれておくほうがわかりやすい。
Slack側の設定
- Outgoing WebHooks追加
- App追加でOutgoing WebHooksを追加
- 設定項目
- Channel: 特定のchannelのみ連動するようにした
- Trigger Word(s): taion:.体温:
- URL(s): GASのウェブアプリケーションのURLをいれる
- Token: GASのコードのConst.verityTokenの値を入れるか、あるいは、ここの値を、GASのコードのConst.verityTokenに入れて、再度ウェブアプリケーションの公開を行う。
蛇足
我が家での使い方
我が家ではこれで記録された体温のシートにグラフを作って表示しています。
グラフの範囲とかは毎回手作業で修正。
時系列を逆に投稿しちゃったものなども手作業で修正。
なぜ作って半年近くたってから公開をしたかというと、またしても子供が熱をだしてこの機能のお世話になったからです。いつになったら熱を出さなくなるのか。。。