やりたいこと
chatworkのタスクのリマインド。
というのも、chatworkはタスクが設定できて便利なのですがリマインドがないのでタスク漏れのリスクがありますよね。Googleカレンダーなどにもタスクを登録してリマインドをしている方もいるのではと思います。
リマインドまでchatworkで完結したら便利!ということでやってみました。
実装
①chatworkのAPIトークンを取得
▼こちらのサイトでAPIを取得したいアカウントのパスワードを入力すると取得できます。
https://www.chatwork.com/service/packages/chatwork/subpackages/api/token.php
②Google Apps Scriptの設定
GoogleDriveでスプレッドシートを新規作成します。スプレッドシートを開いてスクリプトエディタを使用します。
スクリプトエディタに下記のコードをまるっとコピペしてみてください。
/*---- 初期設定ここから ----*/
// チャットワークAPIトークンを設定
var ChatWorkToken = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
// 設定用シートのシート名(シートの名前を変更している場合はここは変わってきます)
var SHEETNAME = 'シート1';
/*---- 初期設定ここまで ----*/
// 管理用メニューを追加
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('管理用')
.addItem('最新のルーム一覧を読込む', 'getRooms')
.addItem('いますぐリマインド実行', 'myFunction')
.addToUi();
}
// リマインド実行のメインのファンクション
function remind(){
// スプレッドシート読み込み
// spreadsheet読込->json取得
var sheet = getSheet();
var json = convertSheet2Json(sheet);
if( json == false ){
Browser.msgBox( "シートに何もありません" );
return false;
}
// ルーム毎にリマインド
for(var i=0; i<json.length; i++) {
var obj = json[i];
if( obj.num_of_days !== '' ){
// ルーム毎にリマインド
//Logger.log( obj.room_id + ", " + obj.num_of_days );
sendRemind( obj.room_id, obj.num_of_days);
}
}
}
// 最新のルーム一覧を読込む
function getRooms(){
// シートを読込み
var sheet = getSheet();
var previousValues = readSheet(sheet);
// 既存の設定をルームIDをキーにした連想配列に残す
var array = [];
if( previousValues != false ){
for(var i=0; i<previousValues.length; i++) {
var key = previousValues[i][0];
var value = previousValues[i][1];
array[key] = value;
}
}
// ルーム一覧を読み込み
// ChatWork apiに投げるパラメータを設定
var params = {
headers : {"X-ChatWorkToken" : ChatWorkToken},
method : "get"
};
//ルーム一覧を取得するURL
var url = "https://api.chatwork.com/v2/rooms";
//チャットワークAPIエンドポイントからレスポンスを取得
var strRespons = UrlFetchApp.fetch(url, params);
// 中身がなかったら終了 (2018/6/11修正)
if( strRespons.getContentText() == '' ){ return false; }
// シートをクリア
sheet.clearContents();
// レスポンス文字列をJSON形式として解析しJSONオブジェクトとして返す
var json = JSON.parse(strRespons.getContentText());
// 二次元配列を作成し、シートに貼り付ける
// 配列を定義
var values = [];
// 1行目はフィールド名を挿入
values[0] = [ 'ルームID', 'リマインド日数', 'ルーム名' ];
// jsonの内容を2行目以降に追加
var i = 1;
for each(var obj in json){
var num_of_days = ( array[obj.room_id] )? array[obj.room_id] : '';
var line = [ obj.room_id, num_of_days, obj.name ];
values.push( line );
}
// シートに貼付け
sheet.getRange(1,1,values.length,values[0].length).setValues( values );
}
function sendRemind(room_id, num_of_days){
// ルームのタスクを読込み
// ChatWork apiに投げるパラメータを設定
var params = {
headers : {"X-ChatWorkToken" : ChatWorkToken},
method : "get"
};
// 未完了のタスクを取得するURL
var url = "https://api.chatwork.com/v2/rooms/" + room_id + "/tasks?status=open";
//チャットワークAPIエンドポイントからレスポンスを取得
var strRespons = UrlFetchApp.fetch(url, params);
// 中身がなかったら終了 (2018/6/11修正)
if( strRespons.getContentText() == '' ){ return false; }
// レスポンス文字列をJSON形式として解析しJSONオブジェクトとして返す
var json = JSON.parse(strRespons.getContentText());
// 昇順で並べ替え
json.sort(function(a,b){
if(a.limit_time < b.limit_time) return -1; if(a.limit_time > b.limit_time) return 1;
return 0;
});
// 現在の日付取得
var nowDate = new Date();
// リマインドする最大の日付の23:59:59をセットする
var refDate = new Date();
refDate.setDate( nowDate.getDate() + num_of_days );
refDate.setHours(23);
refDate.setMinutes(59);
refDate.setSeconds(59);
/* チャットワークに送る文字列のヘッダー */
var strBody = "[info][title]期限が近づいているタスクをお知らせします。[/title]";
// 前回の日付を代入して比較する変数
var lastLimitDate = '';
// タスク毎に予定を作成
for each(var obj in json){
// 期限なしタスクなら何もせず次へ (2018/6/11追加)
if( obj.limit_time == 0 ) continue;
// タスクの期限を取得
var date = new Date( obj.limit_time * 1000 );
// リマインド必要な日付でなければループを抜ける
if( date > refDate ) break;
// タイトルを設定
var title = obj.body;
title = title.split(String.fromCharCode(10)).join(' '); // 改行をスペースに置換
title = title.replace(/\[/g, "<"); // chatworkのタグを "[" → "<" に変換 title = title.replace(/\]/g, ">"); // chatworkのタグを "]" → ">" に変換
title = title.replace(/<("[^"]*"|'[^']*'|[^'">])*>/g, ""); // タグを削除
title = title.substring(0,50); // タイトルは50文字で切る
// 日付を文字列に変換
var strDate = date.getMonth()+1 +"月" + date.getDate() + "日";
//
var limit = '';
if( nowDate > date ){
limit = '期限切れ';
title += " ( " + strDate + "まで )"
} else {
limit = ( date.getFullYear() === nowDate.getFullYear() && date.getMonth() === nowDate.getMonth() && date.getDate() === nowDate.getDate() )?'本日 '+ strDate + 'まで' : strDate + 'まで'+":"+title;
}
// 日付が異なる場合は水平線挿入
var hr = ( lastLimitDate == '' || lastLimitDate == limit )? '' : '[hr]';
if( lastLimitDate == '' || lastLimitDate != limit ) hr = hr + limit + ':\n' + ' ';
strBody = strBody + hr + '[picon:' + obj.account.account_id + '] '
lastLimitDate = limit;
}
// リマインド不要なら終了
if( lastLimitDate == '' ) return false;
// インフォタグを閉じる
strBody = strBody + '[/info]';
// ルームにメッセージ送信
sendMessage(room_id, strBody);
return true;
}
function getSheet(){
var book = SpreadsheetApp.getActiveSpreadsheet();
return book.getSheetByName(SHEETNAME);
}
// シートを読み込んでjson形式で返す
function convertSheet2Json(sheet) {
// シートを読み込んで二次元配列を返す
var values = readSheet(sheet);
if( values == false ) return false;
// create json
var jsonArray = [];
for(var i=0; i<values.length; i++) {
var json = new Object();
json['room_id'] = values[i][0];
json['num_of_days'] = values[i][1];
jsonArray.push(json);
}
return jsonArray;
}
// シートを読み込んで二次元配列を返す
function readSheet(sheet){
var lastRow = sheet.getLastRow();
if( lastRow <= 1 ) return false;
var rowIndex = 2;
var colStartIndex = 1;
var colNum = 2;
var range = sheet.getRange(rowIndex, colStartIndex, lastRow, colNum);
var values = range.getValues();
return values;
}
// メッセージ送信
function sendMessage(room_id, strBody){
var params = {
headers : {"X-ChatWorkToken" : ChatWorkToken},
method : "post",
payload : {
body : strBody
}
};
var url = "https://api.chatwork.com/v2/rooms/" + room_id + "/messages";
UrlFetchApp.fetch(url, params);
}
次にシートにリマインドを送ってほしいチャットルームIDと期限何日前のタスクをリマインドするかを記入します。
③実行
試しに実行してみましょう。
remind関数を選択して三角の実行ボタンを押してみてください。
※初回のみ承認と許可が必要なので許可してあげましょう。
どうですか?正常に実行されましたでしょうか?
最後に毎日決まった時間にリマインドが送られてくるようにしましょう。
左上の時計マークをクリックして下記のように設定しましょう。いつリマインドを送るかの設定はそれぞれ都合が良いように調整してください。
まとめ
いかがだったでしょうか?チャットワークの便利機能であるタスク追加機能がより便利になったのではないでしょうか。
今回のコードでは下の写真のようなフォーマットでリマインドが送られてくるようにしましたがここは調整が効くところですのでそれぞれ確認しやすいように改良してみてください!