自動で議事録を準備する

# 概要
手動で議事録の準備をするのが面倒で、自動でやりたかったので[新人でも、楽がしたい！ ~議事録の準備~](https://qiita.com/RuyPKG/items/abf72dde739e52364bcf)を参考にして作ったが、要件が若干違っていた。
# 要件
- カレンダーから予定を見て、会議が始まる前に議事録の準備ができている
- SLACKにて通知する
- 会議がない場合は作成をしない
- 議事録ファイルは毎回作ってはいけない
- **議事録のファイルは同じファイルを利用する**
- そのファイルの「**以下議事録**」の下からテンプレートを挿入する

最後の要件が意外と難しく、全て出来なかった。
議事録ファイルから「以下、議事録」を探して位置を見つけて、そこからテンプレートを挿入する。

![以下議事録.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/2aff5f5d-7f7e-d11f-f492-8db4dd202a21.png)


# ロジック
ほとんどが[新人でも、楽がしたい！ ~議事録の準備~](https://qiita.com/RuyPKG/items/abf72dde739e52364bcf)と同じ。

- １時間毎にGASバッチが起動
- カレンダーを見る。
- 朝会の予定が入っている場合
 - 議事録ドキュメントの「以下、議事録」を見つける
 - その位置にテンプレートから挿入する。
 - SLACKに通知する

# 各ファイルの役割
- 朝会議事録テンプレートファイル
 - GASスクリプト本体
 - 挿入するテンプレート
- 議事録ファイルID
 - 議事録のファイルID
 - 議事録が変わる場合、こちらも変更する
 - ![議事録ID.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/311665cd-e0f8-8291-c382-1b1b9f155c34.png)


- 自動議事録作成会議名
 - カレンダーに登録している会議名
 - カレンダーに登録している会議名が変わったら、こちらも合わせて変更する
![会議名.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/df10e1bf-307f-cd8c-5e04-975e4ef417af.png)

# Webhookを発行
[slack api](https://api.slack.com/)からwebhookを発行する。

# GAS
８割が[新人でも、楽がしたい！ ~議事録の準備~](https://qiita.com/RuyPKG/items/abf72dde739e52364bcf)です。本当にありがとうございます。


```javascript:コード.gs
// Googleカレンダーに登録された「直近１時間分」のイベントの配列を返す
function getCalendarEventList() {

  var now = new Date();
  var oneHourFromNow = new Date(now.getTime() + (1 * 60 * 60 * 1000));
  var events = CalendarApp.getDefaultCalendar().getEvents(now, oneHourFromNow);

  var eventList = [];
  for (i = 0; i < events.length; i++) {
    eventList.push(events[i]);
  }

  return eventList;  
}
// スプレッドシートに記載された文字の配列を返す
function getEventTitleFromSpredsheet(spredsheetpath) {

  var ss = SpreadsheetApp.openById(spredsheetpath);
  var sheet = ss.getSheets()[0];
  var range = sheet.getRange(1, 1, ss.getLastRow());
  var values = range.getValues();

  var meetingList = [];
  for (i = 0; i < values.length; i++) {
    value = values[i];
    meetingList.push(value[0]);
  }

  // スプレッドシートに記載された文字の配列を返す
  return meetingList;
}
function start(){

  // 議事録自動準備プログラムで、最初に起動する関数
  // 「直近のイベント一覧」と「議事録を作成するMTG名」を取得し、一致する名前があれば議事録を準備する
  var SPREDSHEETPATH = "[自動議事録作成会議名のID]"
  var meethingList = getEventTitleFromSpredsheet(SPREDSHEETPATH);
  var eventList = getCalendarEventList();

  var createFlag = false;
  var meethingName = '';

  for (var i = 0; i < meethingList.length; i++) {
    for (var j = 0; j < eventList.length; j++) {
      if (meethingList[i] == eventList[j].getTitle()) {

        var functionTriggeredTime = new Date();
        var meethingStartTime = eventList[j].getStartTime();

        // 会議の開始時間が、プログラム起動時間より後ならば、createFlag=trueにする。
        // 会議中にプログラムが起動した場合には、議事録は作成されない。
        if (functionTriggeredTime < meethingStartTime){
          createFlag = true;
          meethingName = eventList[j].getTitle();
        }
      }
    }
  }

  if (createFlag) {
    prepareMinutes(meethingName);
    Logger.log('議事録を準備しました。');
    Logger.log('MTG名：' + meethingName);
  } else {
    Logger.log('議事録は準備されませんでした。');
  }
}
//議事録を作成し、slackに通知する
function prepareMinutes(meethingName){

  // slack Incoming Webhook
  var POSTURL = '[WebhookのURL]';

  var fileUrl = insertTemplate();
  
  // slackに議事録へのurlを投稿する
  var message = '議事録を準備しました。' + '\n\n' + '会議名：' + meethingName + '\n' + 'URL : ' + fileUrl;
  var jsonData = {
    'text':message
  };
  var payload = JSON.stringify(jsonData);
  var options = {
    'method':'post',
    'contentType':'application/json',
    'payload':payload
  };
  
  UrlFetchApp.fetch(POSTURL, options);
}

// 「以下議事録」の文字を探す
function getHorizontal(mininutes_doc) {
  var LIMIT = 50; // もしも見つからなかった場合用
  var listItems = mininutes_doc.getBody().getParagraphs();
  for (var i = 0; i < LIMIT; i++) {
    var value = listItems[i].getText();
    if (value.indexOf("以下、議事録") != -1) {
      return i + 1;
    }
  }
  return i;
}

// 議事録ファイルにテンプレートを入れる
function insertTemplate() {
  // 議事録ファイルのIDが入っているスプレッドシートから取得
  var MININUTES_DOC_ID = '[議事録ファイルのID]'
  var mininute_ids = getEventTitleFromSpredsheet(MININUTES_DOC_ID);
  var mininute_id = mininute_ids[0]
  var template_doc = DocumentApp.getActiveDocument();
  var mininutes_doc = DocumentApp.openById(mininute_id);

  var horizontal = getHorizontal(mininutes_doc);
  mininutes_doc.getBody().insertHorizontalRule(horizontal);
  horizontal++;
  template_doc.getBody().getParagraphs().forEach(function(value, i) {
    if (value.getType() == DocumentApp.ElementType.LIST_ITEM) {  // 箇条書きの場合
      mininutes_doc.getBody().insertListItem(horizontal + i, value.getText()).setGlyphType(DocumentApp.GlyphType.BULLET);
    } else {
      mininutes_doc.getBody().insertParagraph(horizontal + i, value.getText());
      mininutes_doc.getBody().getParagraphs()[horizontal + i].setAttributes(value.getAttributes()); // 見出しなどの属性を設定
    }
  })
  return mininutes_doc.getUrl();
}
```

出来たら動かして、動くことを確認する。

# トリガを設定する

１時間毎に動かすトリガを設定します。時計のアイコンから設定が出来ます。

![トリガ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/a892a7d9-5e16-a4b3-20b9-960c0f80c388.png)

１時間毎に動くように設定します。

![1時間毎にトリガ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/0964f671-8315-ea18-b334-1f65a4549eb4.png)

一応、これで完成です。

# 参考サイト
[Google Apps Scriptで議事録テンプレ作成を楽にした](https://qiita.com/wiroha/items/5ce99d7bfc56e3270be6)
[GASを利用した定例議事録作成の自動化](https://qiita.com/takeyoshi-k/items/3c914dfdd509ecc20a7c#gas%E3%81%AE%E5%AE%9F%E8%A1%8C%E3%82%92%E3%82%B9%E3%82%B1%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E5%8C%96)
[新人でも、楽がしたい！ ~議事録の準備~](https://qiita.com/RuyPKG/items/abf72dde739e52364bcf)
ありがとうございます。

# 課題
- テンプレートからコピーする際、以下が出来ない
 - 箇条書きがネストしている場合
 - 水平線がコピーできない
 - 他にもたくさんコピーできないパターンはある
- 担当者が離れてこのスクリプトを止めなかった場合、延々とスクリプトが動いてしまい、ドキュメントが肥大化してしまう
 - 自動的の止まる仕組みを入れたいよね〜
- GASの場合、設定ファイル的なものってどこに配置するのが適切なんだろう？
 - 「以下、議事録」の設定も、外出にするべきなんだろうか。