Google Apps Script로 작업을 잊지 않는 메커니즘을 만들어 봅시다.

안녕하세요 tsuttie입니다(*'▽')
이번에는 GAS를 사용하여 chatwork에 작업 잊음을 통보하고 싶습니다.

1. 무엇을 했는가



이번에는 무엇을 했는가 하면 kintone의 레코드 정보를 참조하여 레코드가 없으면 chatwork에 통지하는 구조를 여러 가지 조합하여 구축해 보았습니다.
정기적으로 실행할 수 있도록 스크립트를 실행하려면 GAS(Google Apps Script)를 사용합니다. 정확히 사내의 공부회(참가자 2명···)에서 GAS의 공부를 하고 있었으므로 모처럼이므로 사용해 보았다. 같은 느낌입니다.

2. GAS를 사용해 보자



GAS의 사용법에 대해서는 이하의 사이트를 참고로 실시했습니다.
【저장판】초보자용 실무로 사용할 수 있는 Google Apps Script 완전 매뉴얼

정말로 상세하게 기재해 주시고 있으므로 앞으로 GAS를 사용해 보는 분은 꼭 참고해 주세요.
기본적인 실행을 할 수 있으면 문제 없을까 생각합니다. 물론 모두 파악할 수 있으면 좋겠습니다만, 나머지는 방법을 조사 조사라고 하는 느낌으로 나는 사용하고 있습니다・・・

3. 실제로 써 보자



그런 이렇게 아래의 흐름으로 스크립트를 짜 보았습니다.

GAS 자동 실행 (시간별 설정)

평일인지 여부 (휴일의 경우 종료)

kintone 정보 얻기

당일 레코드가 존재하는지 (있는 경우 종료)

chatwork에 레코드를 추가하라는 알림

이런 느낌입니다.
누군가가 해야 한다.
하지만 실시자가 일에 따라 바뀌는 탓에 조금 잊기 쉽다.
그런 작업이 있었기 때문에 이런 방법을 취했습니다.
function myFunction() {

 // 平日かどうかを判定する
 // 日曜と土曜を省く
  var currentDate = new Date();
  var weekday = currentDate.getDay();
  if (weekday == 0 || weekday == 6) {
    return;
  }
 // 祝日も省く
  var calendar = CalendarApp.getCalendarById('ja.japanese#[email protected]');
  if (calendar.getEventsForDay(currentDate, {max: 1}).length > 0) {
    return;
  }

 // kintoneAPIを使用するために初期化
  var subdomain = "{サイボウズのサブドメイン}";
  var apps = {
    YOUR_APPLICATION1: { appid: {アプリケーションのID}, name: "{アプリケーション名}", token: "{APIトークンキー}" },
  };
  var kintone_manager = new KintoneManager(subdomain, apps);

 // 登録日のフィールドコードが当日のものを取得
  var date = Utilities.formatDate(new Date(), 'Asia/Tokyo', "yyyy-MM-dd");
  var query = '{登録日のフィールドコード} = "' + date + '"';
  var response = kintone_manager.search("YOUR_APPLICATION1", query);
  // ステータスコード
  // 成功すれば200になる
  var code = response.getResponseCode();
  var content = JSON.parse(response.getContentText());
  // レコードの配列が取得できる。
  var records = content.records;

 // 当日のものがあるかどうかを調べる
  if (records[0] == null){
  // ない場合にはchatworkに通知を実施
    var client = ChatWorkClient.factory({token: '{chatworkトークンキー}'}); //チャットワークAPI
    client.sendMessage({
      room_id:{ルームID}, 
      body: '{メッセージ内容}'});
  }
}


// (1) ライブラリ直接追加部分(ハマりポイントに記載)
var KintoneManager = (function() {
    "use strict";
    // user, passが指定されれば、パスワード認証
    // 指定されなければ、APIトークン認証
    // appsは以下の形式
    // {
    //    // アプリケーション名はkintoneのデータに依存せず、GAS内のコードで取り扱う専用
    //    YOUR_APP_NAME1: {
    //       appid: 1,
    //       guestid: 2,
    //       name: "日報",
    //       token: "XXXXXXXXXXXXXX_YOUR_TOKEN_XXXXXXXXXXXXXX" // パスワード認証する場合は省略化
    //    },
    //    YOUR_APP_NAME2: {
    //       ...
    //    }
    // }
    function KintoneManager(subdomain, apps, user, pass){
        this.subdomain = subdomain;
        this.authorization = null;
        this.apps = apps;

        if (arguments.length > 3) {
            this.authorization = Utilities.base64Encode(user + ":" + pass);
        } else if (arguments.length > 2) {
            // 引数が3つの場合はエンコード済みの認証情報として処理
            this.authorization = user;
        }
    }
    // レコードの作成
    KintoneManager.prototype.create = function(app_name, records) {
        var app = this.apps[app_name];
        var payload = {
          app: app.appid,
          records: records
        };
        var response = UrlFetchApp.fetch(
            "@1/records.json".replace(/@1/g,this._getEndpoint(app.guestid)),
           this._postOption(app, payload)
        );
        return response;
    };
    // レコードの検索
    KintoneManager.prototype.search = function(app_name, query){
       var q = encodeURIComponent(query);
       var app = this.apps[app_name];
       var response = UrlFetchApp.fetch(
         "@1/records.json?app=@2&query=@3"
            .replace(/@1/g, this._getEndpoint(app.guestid))
            .replace(/@2/g, app.appid)
            .replace(/@3/g, q),
         this._getOption(app)
       );
       return response;
    };
    // レコードの更新
    KintoneManager.prototype.update = function(app_name, records) {
        var app = this.apps[app_name];
        var payload = {
          app: app.appid,
          records: records
        };
        var response = UrlFetchApp.fetch(
            "@1/records.json".replace(/@1/g, this._getEndpoint(app.guestid)),
           this._putOption(app, payload)
        );
        return response;
    };
    // レコードの削除
    KintoneManager.prototype.destroy = function(app_name, record_ids){
       var app = this.apps[app_name];
       var query = "app=" + app.appid;
       for(var i=0; i<record_ids.length;i++){
           query += "&ids[@1]=@2".replace(/@1/g,i).replace(/@2/g,record_ids[i]);
       }
       var response = UrlFetchApp.fetch(
         "@1/records.json?@2"
            .replace(/@1/g, this._getEndpoint(app.guestid))
            .replace(/@2/g, query),
         this._deleteOption(app)
       );
       return response;
    };
    // GETメソッドの時のオプション情報
    KintoneManager.prototype._getOption = function(app) {
       var option = {
          method: "get",
          headers: this._authorizationHeader(app),
          muteHttpExceptions: true
       };
       return option;
    };
    // POSTメソッドの時のオプション情報
    KintoneManager.prototype._postOption = function(app,payload) {
       var option = {
               method: "post",
               contentType: "application/json",
               headers: this._authorizationHeader(app),
               muteHttpExceptions: true,
               payload: JSON.stringify(payload)
       };
       return option;
    };
    // PUTメソッドの時のオプション情報
    KintoneManager.prototype._putOption = function(app,payload) {
       var option = {
               method: "put",
               contentType: "application/json",
               headers: this._authorizationHeader(app),
               muteHttpExceptions: true,
               payload: JSON.stringify(payload)
       };
       return option;
    };
    // DELETEメソッドの時のオプション情報
    KintoneManager.prototype._deleteOption = function(app) {
       var option = {
          method: "delete",
          headers: this._authorizationHeader(app),
          muteHttpExceptions: true
       };
       return option;
    };
    // エンドポイントの取得
    KintoneManager.prototype._getEndpoint = function(guest_id) {
      var endpoint = "https://@1.cybozu.com".replace(/@1/g,this.subdomain);
      if (guest_id == null) {
        return endpoint + "/k/v1";
      } else {
        return endpoint + "/k/guest/@1/v1".replace(/@1/g, guest_id);
      }
    };
    // ヘッダーの認証情報
    KintoneManager.prototype._authorizationHeader = function(app) {
      if (this.authorization) {
         // パスワード認証
         return { "X-Cybozu-Authorization": this.authorization };
      } else if (app.token) {
         // APIトークン認証
         return { "X-Cybozu-API-Token": app.token };
      } else {
        throw new Error("kintone APIを呼ぶための認証情報がありません。");
      }
    };
    return KintoneManager;
})();

그리고는 위의 스크립트를 정기 실행으로 설정해 주면 완성입니다. (하마리 포인트에 기재)
감상은・・・

쉽게 할 수있다 (전율)

이었다.

4. 빠진 포인트



· 라이브러리 추가
chatwork, kintone의 API를 두드리는 부분은 라이브러리를 사용했습니다.

■ChatWorkClient 라이브러리 추가
추가의 방법은↓를 참고로 했습니다.
참고 : Google Apps Script에서 ChatWork API를 사용하여 게시

■ kintone API 실행
kintone의 API를 사용하기 위해서 이하를 사용했습니다만, 「라이브러리의 추가」로부터에서는 왠지 잘 되지 않고・・・
참고 : kintone과 Google Apps Script 협력
상기 코드내(1)에 직접 추가했는데, 잘 되어 버렸으므로 그쪽에서 대응했습니다.

· 스크립트 정기 실행
스크립트의 정기 실행에 대해서는 처음에 소개했습니다 사이트보다 ↓ 부분을 참고로 설정을 실시했습니다.
Google Apps Script에서 매일 정해진 시간에 스크립트를 실행하는 트리거 설정
아침에 끝에 확인하고 싶었기 때문에 다음과 같이 설정하고 있습니다.
부하 분산을 위해인지 1시간 단위로의 설정이 되므로 세세한 통지에는 적합하지 않을지도 모릅니다・・・


5. 정리



이번에는 GAS를 사용하여 chatwork에 작업 잊음을 통지를 해 보았습니다.
여러가지 조합해 구조를 만들어 보았습니다만, 의외로 여러 곳에 사용할 수 있을 것 같네. 라는 인상이었습니다.
앞으로도 뭔가 장면이 있으면 사용하고 싶습니다.

뭔가 지적 등 있으면 댓글 주시면 감사하겠습니다.
잘 부탁드립니다. ('◇')ゞ

좋은 웹페이지 즐겨찾기