【GAS】興味のあるイベント(connpass)がすでに終了していて悔しかったので解決した話

個人メモ+α

# 参加したかったイベント
　Tokyo GAS on GCPUG 2018 Spring
　https://gcpug-tokyo.connpass.com/event/81041/

# 原因
・connpassの利用を始めて2か月 気になるグループの洗い出しが終わっていない。
　※グループに参加していればメールで通知される。
・定期的に確認していなかった。
・人気のあるイベントだったため、気が付いたころには参加者があふれていた。

# 解決策
・connpassにイベント検索のAPIあるやんけ
　⇒これで監視できそう？？？
・GASのイベントだったし、GASで実装して二度と同じ失敗は繰り返さないようにしよう。
・携帯や職場PCで確認できるSlackに通知させよう

# 実装
ざっくりした実装の流れ
・SlackのToken取得しておく
・GASのSlackライブラリを導入しておく

### コード
```js:前準備.gs
//SlackのTokenを設定
//手動で実行しておく
function setSlackToken(){
  PropertiesService.getScriptProperties().setProperty("token ","your_token"); 
}
```

```js:main.gs

var apiUrl = "https://connpass.com/api/v1/event/?"
var query = ["keyword_or","series_id"]

//メインメソッド(毎日8～9時にトリガーを設定)
//更新がなかった時にはその旨を通知
function main(){
  var updateFlag = false;
  updateFlag = updateFlag || seminarCheck("GAS","GAS,GoogleAppsScript,Google Apps Script",0) ;
  updateFlag = updateFlag || seminarCheck("アイマス","アイマス,IDOLM@STER,アイドルマスター",0) ;
  updateFlag = updateFlag || seminarCheck("GCPUG","1898",1) ;
  
  Logger.log(updateFlag)
  if(!updateFlag){
    postMessage("本日の更新はありませんでした。")
  }
}

//セミナー更新確認メソッド
//propertyKey:検索キーの識別文字列(てきとうでもいい)
//keyword:実際に検索で使われる文字列「,」区切りで複数条件の検索が可能
//queryNum:query配列の何番目を使うか指定
//
function seminarCheck(propertyKey,keyword,queryNum) {
  //更新フラグ　更新されたらtrueになる
  var updateFlag = false;
  
  //プロパティから前回の実行結果を取得
  var properties = PropertiesService.getScriptProperties(); 
  var oldListStr = properties.getProperty(propertyKey);
  
  //APIをたたく
  var url = apiUrl + query[queryNum] + "=" + keyword;
  var response = UrlFetchApp.fetch(url);
  var json = JSON.parse(response.getContentText());
  
   //初回実行時は空リストと比較　⇒　新たに取得したものは全て通知される
  var oldList =[];
  if(oldListStr != null){
    oldList = oldListStr.split(',');
  }
  
  var eventIdList = [];
  var diffIdList =[];
  json["events"].forEach(function(event){
    var event_id = event["event_id"].toString();
    eventIdList.push(event_id);
    if(oldList.indexOf(event_id) <= -1){
      diffIdList.push(event_id);
    }
  });
  
  
  //前回の検索結果に含まれていないタイトルを通知(新規のタイトル)
  //Logger.log(diffIdList)
  if(diffIdList.length > 0){
    postMessage("種別："+propertyKey+"\r\n検索キーワード："+keyword+"\r\n")
    //イベントのjson取り出してloop 出力情報を取り出す。
    json["events"].forEach(function(val) {
      var id = val["event_id"].toString();
      if(diffIdList.indexOf(id) >= 0){
        sendSlack(val);
      }
    });
    
    postMessage("\r\n　　　\r\n")//インデント
    updateFlag = true;
  }
  
  
  
  /*
  * 今回の取得結果を保存
  */  
  properties.setProperty(propertyKey, eventIdList.toString()); //プロパティは文字列で保存されるため変換
  
  return updateFlag;
}
```
```js:slack.gs
//jsonの整形と送信
function sendSlack(json){
  //整形処理  
  var message = "";
  message = message + "title： "+json["title"]+"\r\n";
  message = message + "更新日： "+dateChange(json["updated_at"])+"\r\n";
  message = message + "url： "+json["event_url"]+"\r\n";
  
  postMessage(message)
}


//メッセージpostメソッド
function postMessage(message) {
  var prop = PropertiesService.getScriptProperties().getProperties();
  
  //slackApp インスタンスの取得
  var slackApp = SlackApp.create(prop.token);
  
  //投稿
  slackApp.postMessage(prop.channelId, message, {
    username : "connpass監視BOT"
  });
}

//日時返還
function dateChange(str){
  return Utilities.formatDate(new Date(str), 'Asia/Tokyo', 'yyyy/MM/dd hh:mm');
}
```
実行イメージ
![505d8c2a76f5863df8d8ff8df2b7e723.png](https://qiita-image-store.s3.amazonaws.com/0/188620/1f1bb2d7-7307-3304-c716-505cf8c2a2dd.png)



# まとめ
次はどんな犠牲を払ってでも参加する。

# 課題
　・純粋にキーワード検索を行っているので、物理的に参加が出来ないイベントも通知される。
　　⇒ 女性限定学生限定、九州で開催など
　　　⇒イベント会場の位置情報をもとに地方は除外できそう・・・
　　　⇒女性限定学生限定などは若干厳しそうなため、要検討
　・Slackに通知する際のフォーマットがめちゃくちゃダサい
　・検索キーワードがコード上にべた書きなのでスプレッドシートなどのから読み取るように変更させたい。
　　⇒難しくはないので、直近で修正予定。
　・Slackの通知がえげつないことになる場合あり。
　　⇒更新されたイベントの出力先をスプレッドシートに変更し、
　　　更新があった旨をSlackに通知させるとか？？？