LoginSignup
7
9

More than 5 years have passed since last update.

チャットワークへスケジュールをリマインドしてくれるBOT

Last updated at Posted at 2017-10-21
  • 2017/10/22追記
    • 終日のスケジュール入力に対応しました(Ver2.0.0へ変更)

前提

依頼されたタスクや参加する会議の日程、その他雑務など、仕事をしているとスケジュール管理が重要になってくる場面がたくさんでてくると思います。
自分のスケジュール管理ならできても、それだけではチームの状況は良くならないことも多いので(1人のミスは最終的には全員のミスになるので)、全員が幸せになれるようにリマインダーBOTを作ってみました。

できること

スケジュールを一括で簡単に登録でき、その時刻になったらチャットワークにTo付きで指定のメンバーにリマインドすることができます

メリット

  • Googleカレンダーでスケジュールのデータを管理しているので非エンジニアでも使いやすい
  • Googleカレンダーを使っているので定期スケジュールの登録、スケジュールの途中変更、削除などもしやすい
  • リマインドできるグループチャットや対象者をスケジュールごとに設定可能

環境

  • GoogleAppsScript(通称:GAS)
  • スプレッドシート
  • チャットワーク
  • Googleカレンダー

配布

使い方

  • ツール ⇒ スクリプトエディタを開き、定数部分を自分の環境にあったものに修正して下さい(SCRIPT_NAMEは変更不要です)
    • SPREADSHEET_URL:スプレッドシートのURL
    • CHATWORK_TOKEN:チャットワークのAPIトークン
    • CALENDAR_ID:GoogleカレンダーのID(基本的にはGmailアドレスと同じです)
    • ROOM_ID:一日一回送信される全体スケジュールの発言対象ルームID
  • ツール ⇒ スクリプトエディタを開き、スクリプトの実行タイマー(時計マーク)を下記に設定して下さい(以下は入力例です)
    • カレンダーとデータを連携する必要性があるため、設定時に承認を求められる場合があります
    • setTodaySchedule - 時間主導型 - 日タイマー - 午前4時~5時
      • この時間にその日のスケジュールを一括でスプレッドシートにコピペしてきます
    • sendSchedule - 時間主導型 - 分タイマー - 5分ごと
    • sendTodaySchedule - 時間主導型 - 日タイマー - 午前8時~9時
  • リマインドしたい内容を登録フォームに入力します。入力が終わったらツールバーの「スケジュールBOT」を実行して下さい
    • 終了日時は必要があれば手動で入力して下さい(終了日時を入力しておくとカレンダーが見やすいです)
    • スケジュールは複数同時登録可能です。複数登録する場合は、複数行入力して下さい
    • リマインドは開始日時に設定した時間に送られます
    • 発言対象、対象メンバーは適時VlookSheetを編集して追加して下さい
    • 行の追加は可能ですが、列を追加すると機能が正常に動かなくなります。列追加する場合はスクリプトも修正して下さい
    • 「登録リスト」「デイリー発言リスト」リートは編集しないで下さい
  • スケジュールの登録時に時間の部分を0:00で登録すると「終日」のスケジュールになります
  • 毎日1回だけ1日の全体スケジュールを特定のルームに送信することができます
  • スケジュール設定が「終日」の予定に関してはリマインドは行われません(全体スケジュールの時のみ予定に含まれます)
  • 定期的なスケジュール(リマインド)を登録したい場合は1つだけ登録した後、Googleカレンダーを開いて手動で定期登録に切り替えて下さい

プログラムの説明(エンジニア向け)

  • 「登録フォーム」シートに入力してある行を1行ずつ参照し、その内容をカレンダーに登録しています
  • GoogleAppsScriptのタイマー機能を使って、早朝に当日分の全スケジュールをデイリー発言リストにコピーしてきます
  • GoogleAppsScriptのタイマー機能を使って、一定時間ごとにスケジュールの時間が過ぎていないかどうか判定しています
  • スケジュールの時間になったらチャットワークの所定のグループへBOT発言します
  • リマインドは1回のみでいいので、発言したかどうかの判定を「デイリー発言リスト」のE列で行っています

ソースコード

// 定数指定
SPREADSHEET_URL = "";
CHATWORK_TOKEN = "";
CALENDAR_ID = "";
SCRIPT_NAME = "カレンダーへ登録";

// 本日の予定を送るチャットワークのルームID
ROOM_ID = 9999999999;

/**
 * スプレッドシート読み込み時に起動される
 */
function onOpen()
{
    var spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
    var menuFunction = [{
        name: SCRIPT_NAME,
        functionName: "createSchedule"
    }];

    spreadSheet.addMenu("スケジュールBOT", menuFunction);
}

/**
 * 登録リストの内容をカレンダーに登録する
 */
function createSchedule()
{
    // スプレッドシートを操作するための準備
    var url = SPREADSHEET_URL;
    var spreadsheet = SpreadsheetApp.openByUrl(url);
    var sheet = spreadsheet.getSheetByName("登録リスト");

    //シートの最終行番号、最終列番号を取得
    var startRow = 1;
    var startColumn = 1;
    var lastRow = sheet.getLastRow();
    var lastColumn = sheet.getLastColumn();

    // シートの縦横すべてを取得
    var sheetData = sheet.getSheetValues(startRow, startColumn, lastRow, lastColumn);

    // カレンダーへの登録
    for (var i = 1; i < lastRow; i++) {
        if (sheetData[i][0] != "") {
            createEvent(sheetData[i][0], sheetData[i][1], sheetData[i][2], sheetData[i][3], sheetData[i][4], sheetData[i][5]);
            // 連続して作成するとエラーを返すので1秒ウェイト
            Utilities.sleep(1000);
        }
    }
}

/**
 * カレンダー登録の本体
 */
function createEvent(title, startTime, endTime, location, menber, agenda)
{
    var calendar = CalendarApp.getCalendarById(CALENDAR_ID);

    if (HHmm(startTime) == "00:00") {
        calendar.createAllDayEvent(title,
            startTime,
            {
                description: menber + "\n" + agenda,
                location: location
            }
        );
    } else {
        calendar.createEvent(title,
            new Date(startTime),
            new Date(endTime),
            {
                description: menber + "\n" + agenda,
                location: location
            }
        );
    }
}

/**
 * 今日の予定をスプレッドシートにコピーする(毎日1度だけ呼ばれる)
 */
function setTodaySchedule()
{
    // スプレッドシートを操作するための準備
    var url = SPREADSHEET_URL;
    var spreadsheet = SpreadsheetApp.openByUrl(url);
    var sheet = spreadsheet.getSheetByName("デイリー発言リスト");

    //特定のIDのカレンダーを取得
    var calendar = CalendarApp.getCalendarById(CALENDAR_ID);

    //カレンダーの本日のイベントを取得
    var schedules = calendar.getEventsForDay(new Date());

    // 一旦、シートをクリアにする
    sheet.getRange("A2:E100").clearContent();

    // イベントの数だけ繰り返し
    for (var i = 0; i < schedules.length; i++) {
        var title = schedules[i].getTitle();
        var startTime = schedules[i].getStartTime();
        var location = schedules[i].getLocation();
        var agenda = schedules[i].getDescription();

        sheet.getRange(i + 2, 1).setValue(title);
        sheet.getRange(i + 2, 2).setValue(startTime);
        sheet.getRange(i + 2, 3).setValue(location);
        sheet.getRange(i + 2, 4).setValue(agenda);

        if (HHmm(startTime) == "00:00") {
            sheet.getRange(i + 2, 5).setValue("送信済");
        } else {
            sheet.getRange(i + 2, 5).setValue("未送信");
        }
    }
}

/**
 * 時間になったらチャットワークへ予定を発言する
 */
function sendSchedule()
{
    // スプレッドシートを操作するための準備
    var url = SPREADSHEET_URL;
    var spreadsheet = SpreadsheetApp.openByUrl(url);
    var sheet = spreadsheet.getSheetByName("デイリー発言リスト");

    //シートの最終行番号、最終列番号を取得
    var startRow = 1;
    var startColumn = 1;
    var lastRow = sheet.getLastRow();
    var lastColumn = sheet.getLastColumn();

    // シートの縦横すべてを取得
    var sheetData = sheet.getSheetValues(startRow, startColumn, lastRow, lastColumn);

    var nowTime = new Date();
    var honbun = "";

    for (var i = 1; i < lastRow; i++) {
        if (sheet.getRange(i + 1, 5).getValue() == "未送信" && sheet.getRange(i + 1, 2).getValue() <= nowTime) {
            honbun = "";
            honbun += "[info][title]" + sheetData[i][0] + " (roger)[/title]";
            honbun += sheetData[i][3];
            honbun += "[/info]";

            sheet.getRange(i + 1, 5).setValue("送信済");
            sendMessageToChatWork(sheetData[i][2], honbun);
        }
    }
}

/**
 * チャットワークへの発言プログラムの本体
 */
function sendMessageToChatWork(roomId, message)
{
    var token = CHATWORK_TOKEN;

    var parameter = {
        headers: {
            "X-ChatWorkToken": token
        },
        method: "post",
        payload: {
            body: message
        }
    };

    // 送信先情報
    var url = "https://api.chatwork.com/v2/rooms/" + roomId + "/messages";

    // メッセージ送信
    UrlFetchApp.fetch(url, parameter);
}

/**
 * 本日の予定をチャットワークに送る
 */
function sendTodaySchedule()
{
    // 本日の予定を送るチャットワークのルームID
    var roomId = ROOM_ID;

    //特定のIDのカレンダーを取得
    var calendar = CalendarApp.getCalendarById(CALENDAR_ID);

    //カレンダーの本日のイベントを取得
    var schedules = calendar.getEventsForDay(new Date());

    // チャットワークに送る文字列のヘッダー
    var honbun = "[info][title]本日の予定:" + Utilities.formatDate(new Date(), 'JST', 'yyyy/MM/dd') + " (roger)[/title]";

    // イベントの数だけ繰り返し
    for (var i = 0; i < schedules.length; i++) {
        var strTitle = schedules[i].getTitle();
        var strStart = HHmm(schedules[i].getStartTime());
        var strEnd = HHmm(schedules[i].getEndTime());
        honbun += strStart + ' - ' + strEnd + " " + strTitle + '\n';
    }

    honbun += '[/info]';

    sendMessageToChatWork(roomId, honbun)
}

/**
 * 時刻の表記をHH:mmに変更
 */
function HHmm(str)
{
    return Utilities.formatDate(str, 'JST', 'HH:mm');
}

参考

7
9
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
9