調べて、学ぶ

検索したり実験したことを覚えとくブログ

googleAPIを駆使するLINEbotサービスを作った #3

前回の続き

2.分解した内容をgoogleカレンダーに登録する

gMailのテキスト取得がうまくいったので、取得した文章をgoogleカレンダーのパラメータとするよう分解していく。

メール例文

予約通知です

施設名: aaaaaaaaa

スタート: 2020年 7月 1日, 水曜日

エンド: 2020年 7月 5日, 日曜日

予約ID: nnnnnnnnnn


受信するメールは定型文(以下)なので、「:」ごとに分解していけば良い。

こんな感じ。(ソースから引用&若干編集)

//メールの文章を分解してパラメータに格納する
//引数 pText:メールのテキスト内容

exports.sliceText = function(pText){
    let textlines = pText.replace(/\r/g,'') //改行ごとに配列化
    let params;
    let cnt;
    let YMD;
    let dt;
    let job = {'dtFrom':'','dtTo':'','youbi':''}; 
    let reserveID;

    //改行ごとにメール文章を
    for(cnt in textlines){
    
      params = textlines[cnt].split(':')
      switch(params[0]){
        case '施設名':
          room = params[1].replace(/ /g,'');
          break;
        case 'スタート':
          dt = params[1].replace('/ /g','').replace('年','-').replace('月','-').replace('日','');// y-m-d, ◯曜日
          YMD = dt.split(',')[0].split('-');
          stay.dtFrom = new Date(YMD[0], Number(YMD[1]) -1 , YMD[2] ,12,00,00);
          break;
          
        case 'エンド':
          dt = params[1].replace('/ /g','').replace('年','-').replace('月','-').replace('日','');// y-m-d, ◯曜日
          YMD = dt.split(',')[0].split('-');
          
          stay.dtTo = new Date(YMD[0], Number(YMD[1]) -1 , YMD[2] ,10,00,00);
          
          //清掃予定(時間は任意で固定)
          jpb.youbi = params[1].split(',')[1].replace(/ /g,'').substr(0,1);
          job.dtFrom = new Date(YMD[0], Number(YMD[1]) -1 , YMD[2] ,10,00,00);
          job.dtTo = new Date(YMD[0], Number(YMD[1]) -1 , YMD[2] ,11,00,00);
          
          
          break;


        case '予約ID':
          console.log(params[1])
          reserveID = params[1].split('ref')[0];
          break;
      }
    }

    //googleカレンダー用のパラメータを返す
    return {'room':room,'job':clean,'reserveID':beds24ID};
};

googleカレンダーについて。 先のsliceText()をよしなに加工して、以下のinsertEents()の引数として渡すとイベントが作成できる。(認証周りはgMailと同じ)

//◆◆GCal予定書き込み◆◆
//◆◆insertEvents()に使用するパラメータ
/* {
  start:{dateTime:'',timeZone:'Asia/Tokyo'}
  ,end:{dateTime:'',timeZone:'Asia/Tokyo'} 
  ,summary:'カレンダーのタイトル'
  ,description:'カレンダーのメモ'
  ,location :'カレンダーの場所'
} */
exports.insertEvents = function(pGcalParam){
  return new Promise((resolve)=>{
    // Authorize a client with credentials, then call the Google Calendar API.
    resolve(authorize(JSON.parse(credDat)))
  }).then((res)=>{
    const oauth = res

    return new Promise((resolve)=>{
      const calendar = google.calendar({version: 'v3', auth:oauth});
      calendar.events.insert({
        calendarId: 'primary',
        resource:pGcalParam,
      }, (err, res) => {
        if (err) return console.log('The API returned an error: ' + err);
        
        //console.log(res.data.id);
        resolve(res);
      });
    })
  })
};

(後々で必要になる)カレンダー内容の更新について。

このLINEbotは「仕事が来たぞ」というお知らせについて「やります」と返事した時にカレンダーの更新(担当者名を書き換える)を行うので、googleカレンダーの更新が必須になる。 APIのリファレンスをぱっと見た感じだとupdate()を使えばいいじゃないの? と思いがちですが、部分的な編集の場合はpatch()を使うらしい。 渡すパラーメータも上のinsertEvents()で使っているものと同じなので、上記の「calendar.events.insert」の部分を「calendar.events.patch」と書き換えるだけでOK。

※一意のイベントに絞り込まなければならないので、カレンダーのIDは必須。 処理のフローとしては、

1.予定の一覧(ID)を取得

2.1をループし、LINEbotから与えられたカレンダーと同じIDが見つかったら内容更新

となる

(ソース抜粋)
//現在の予定一覧を取得(gCalendar.listEvents())し、対象のイベントが未登録であればreplyユーザ名で更新する。
gCalendar.listEvents().then((ev)=>{
    if(ev.length){
        ev.map((ev)=>{
        
        if(ev.id == [LINEbotで募集しているID]){
            //カレンダーのサマリー(担当者を格納している)内容を確認
            if(ev.summary == '未登録'){
            
                //登録
                const gCalParam = {
                    summary: 【LINEのユーザ名】
                    ,id:e.id
                }
            
                entryEvents(gCalParam).then((res)=>{
                    //略
                });

            }else{
                //誰かが登録済み
                let echo='';

                if(ev.summary == 【LINEのユーザ名】){
                    //自分が予約済み
                    //略
                }else{
                    //自分以外が予約済み
                    //略
                }
            }
          }
      });

  }else{
      console.log('no events')
  }
});

function entryEvents(gCalParam){
  return new Promise((resolve)=>{
    // Authorize a client with credentials, then call the Google Calendar API.
    resolve(authorize(JSON.parse(credDat)))
  }).then((res)=>{
    const oauth = res

    return new Promise((resolve)=>{
      const calendar = google.calendar({version: 'v3', auth:oauth});
      
      //patch()で更新。eventIdにカレンダーのIDを指定するのがキモ
      calendar.events.patch({
        calendarId: 'primary',
        eventId:pGcalParam.id,  
        resource:{summary:pGcalParam.summary}
      },(err,res)=>{
        if (err) return console.log('The API returned an error: ' + err);
        
        //console.log(res.data.id);
        resolve(res);      
      })
    })
  })
}

これで「メールを受信」して「カレンダーに登録する(更新する)」ことができた。

#4.LINEの配信・メールの処理へ続く ...続かせるのやめました。

(追記)2020/11/18 気力が持たないし、これからやることもそんなに面白くないのでここで打ち切ることにします。