gmailからLINE WORKSのグループに通知

#問題

```bash
web=サービス
dev=開発運用担当
ops=インフラ担当

while(web.障害==true){
  ops.iyaiya=0

  dev.障害通知先がメールだけだったので対応に遅れた()

  if(dev.怖い人に怒られた == true){

    :shitsukoi
    dev.監視改善依頼()->ops

    ops.過去繰返し返事した内容から回答(){
      すでにzabbixのアクションでLINE WORKSの通知を運用中
      新規アイテムで叩く監視用API（URL）が必要
    }->dev

    dev.(){
      監視用APIは無理|時間がない|APIってなに？|そっちでなんとかしてくれ
    }->ops

    ops.iyaiya++
    
    if(ops.iyaiya == 3){
      goto(:syouganaine)
      break
    }

    ops.sleep(3days)

    if(dev.怖い人にまた怒られた == true){
      dev.alert(マジか)
      goto(:shitsukoi) 
    }
  } else {
    dev.reset(怒られてないので障害はなかった)
  }
}
```

#:syouganaine
障害トリガーはメールしかないのでGoogle Action Script(GAS)で行きますか。

#GAS
  * 監視したいメールに自動振り分けでタグ「gmail-tag」をつける。
  * GASで処理後は重複読取れないようにタグを外す。

```javascript
function sendEmail() {
  var messages = [];
  var threads;

  var label = GmailApp.getUserLabelByName('gmail-tag'); //指定タグ付きメールのみ読取る
  threads = label.getThreads();

  //threads = GmailApp.search('label:gmail-tag is:unread');

  for (var i = 0; i < threads.length; i++) {
    messages = threads[i].getMessages();
    
    //threads[i].markRead();
    //threads[i].moveToTrash();
  
    var message = messages[messages.length-1];
    message.markRead();
    
    var subject = message.getSubject();
    var body = message.getPlainBody();
    var msgdate = message.getDate();
    
    var output = '*■' + subject + '*';
    //output += '\n*from:* ' + message.getFrom();
    //output += '\n*to:* ' + message.getTo();
    //output += '\n*cc:* ' + message.getCc();
    output += '\n _' + msgdate + '_';
    output += '\n```' + body + '```';
    //Logger.log(output);

    //通知したいメールをタイトルでフィルタリング
    if(subject.indexOf('障害発生') > -1){
      var roomId = "257xxxxx";
      sendLW(roomId, output);
    }
   }

  // remove the label from these threads so we don't send them to again next time the script is run
  label.removeFromThreads(threads);
}

function sendLW(roomId, message){
  var ops = setLwOptions();
 
  var jwttoken = getJwtToken(ops.serverId, ops.privateKey);
  var newtoken = getServerToken(ops.apiId, jwttoken);
  
  sendMessage(newtoken, ops.apiId, ops.consumerKey, ops.botNo, roomId, message) 
}

function getJwtToken(serverId, privateKey){
  var header = Utilities.base64Encode(JSON.stringify({"alg":"RS256","typ":"JWT"}), Utilities.Charset.UTF_8);
  var claimSet = JSON.stringify({
    "iss": serverId,
    "iat": Math.floor(Date.now() / 1000),
    "exp": Math.floor(Date.now() / 1000 + 2000)
  });
  var encodeText = header + "." + Utilities.base64Encode(claimSet, Utilities.Charset.UTF_8).slice(0, -2);
  var signature = Utilities.computeRsaSha256Signature(encodeText, privateKey);
  var jwtToken = encodeText + "." + Utilities.base64Encode(signature).slice(0, -2);
  return jwtToken;
}

function getServerToken(apiId, jwtToken) {
  var uri = 'https://authapi.worksmobile.com/b/' + apiId + '/server/token';
  
  var payload = {
    "grant_type" : encodeURIComponent("urn:ietf:params:oauth:grant-type:jwt-bearer"),
    "assertion" : jwtToken
  };  
  var options = {
    'method': 'post',
    'headers': {'Content-Type' : 'application/x-www-form-urlencoded'},
    'payload': payload
  };
  
  var body = UrlFetchApp.fetch(uri, options);
  return JSON.parse(body).access_token;
}

function sendMessage(token, apiId, ckey, botNo, roomId, message){
  var uri = 'https://apis.worksmobile.com/' + apiId + '/message/sendMessage/v2';
  var payload = {
    "botNo" : botNo, <- 本番ではgo言語型変換エラーのため、数字を直入れている
    "accountId": null,
    "roomId": roomId,
    "content" : {
      "type" : "text",
      "text" : message
    }
  };

  var res = UrlFetchApp.fetch(uri, {
    'method'  : 'post',
    'headers' : {
      'Content-Type' : 'application/json',
      'consumerKey' : ckey,
      'Authorization' : 'Bearer ' + token
    },
    'payload' : JSON.stringify(payload),
    muteHttpExceptions: true
  });


  /*
　//debug
  var responseCode = res.getResponseCode();
  var responseBody = res.getContentText();
  if (responseCode === 200) {
    var responseJson = JSON.parse(responseBody);
    // ...
  } else {
    Logger.log(Utilities.formatString("Request failed. Expected 200, got %d: %s", responseCode, responseBody));
    // ...
  }
  */
}

function setLwOptions(){
  return {
    "apiId" : "jp1kxxxxxxxxxxx",
    "consumerKey" : "obeVEPwHxxxxxxxxxxxxxx",
    "serverId" : "bbe3e59e2c3c4c7xxxxxxxxxxxxxx",
    "privateKey" : "-----BEGIN PRIVATE KEY-----\nxxx\nxxx\n-----END PRIVATE KEY-----",
    "botNo" : "9999"
  };
}

```

#参考
getJwtToken()助かりました！
https://qiita.com/kunihiros/items/a94221ad7c9f4de84cf8

debug
https://www.monotalk.xyz/blog/google-app-script-%E3%81%AE-urlfetchapp-%E3%81%AE-%E4%BE%8B%E5%A4%96%E3%83%8F%E3%83%B3%E3%83%89%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/

gas reference
https://developers.google.com/apps-script/reference/gmail/gmail-label

#追記
下記がより先進と気付く・・・
SES->SNS->Lambda->Chat