【GAS】 LINE BOTでuserIdごとにキャッシュ管理をする

image

はじめに

 とある話しの流れで、GASとLINE BOTを使ったGoogleカレンダー予約システムを作ることになった。
こちらの記事を参考にさせてもらい作れたのですが、複数人が同時にアクセスすると、キャッシュ管理が重なって、うまく動かないことがわかったので、直すことにしました。
今回紹介するLINE BOT+GASコードは、userIdごとにキャッシュを発行することに焦点を当てたコードになります。

class EachCacheの作成

userIdを渡したらuserIdごとにキャッシュを発行して、消去するクラスを作成します。

class EachCache {
  constructor(userId) {
    this.userId = userId;
    this.keys = ["type", "tenki_today"];

    // キャッシュを消去するときに使う
    this.all_caches = this.keys.map((key, index, array) => {
      return this.userId + key;
    });

    this.cache = CacheService.getScriptCache();
  }

  get(key) {
    key = this.userId + key;
    return this.cache.get(key);
  }

  put(key, value) {
    key = this.userId + key;
    this.cache.put(key, value);
  }

  cacheClear() {
    this.cache.removeAll(this.all_caches);
  }

  // 確認ログ
  log() {
    return this.cache.getAll(this.all_caches);
  }

}

function reply(replyToken, message)の作成

LINEでの応答に使います。channelAccessTokenは、それぞれで発行したものを使ってください。

function reply(replyToken, message) {
  var url = "https://api.line.me/v2/bot/message/reply";
  UrlFetchApp.fetch(url, {
    "headers": {
      "Content-Type": "application/json; charset=UTF-8",
      "Authorization": "Bearer " + channelAccessToken, // <= それぞれ個別のトークン
    },
    "method": "post",
    "payload": JSON.stringify({
      "replyToken": replyToken,
      "messages": [{
        "type": "text",
        "text": message,
      }],
    }),
  });
  return ContentService.createTextOutput(JSON.stringify({ "content": "post ok" })).setMimeType(ContentService.MimeType.JSON);
}

function logToSheet()の作成

ログをスプレッドシートに記録します。

function logToSheet(sheetName,text_1, text_2, text_3, text_4) {
  // 対象のスプレッドシート を設定.
  const sheet = SpreadsheetApp.openById('*************************'); // それぞれ個別のスプレッドシートID
  const targetSheet = sheet.getSheetByName(sheetName);
  var lastRow = targetSheet.getLastRow();

  // 更新日時を取得
  var time = Utilities.formatDate(
    new Date(),
    'Asia/Tokyo', 'yyyy/MM/dd H:mm'
  );
  SpreadsheetApp.flush(); // スプレッドシートの再描画 
  targetSheet.getRange(lastRow + 1, 1).setValue(time.toLocaleString());
  targetSheet.getRange(lastRow + 1, 2).setValue(text_1);
  targetSheet.getRange(lastRow + 1, 3).setValue(text_2);
  targetSheet.getRange(lastRow + 1, 4).setValue(text_3);
  targetSheet.getRange(lastRow + 1, 5).setValue(text_4);
  SpreadsheetApp.flush(); // スプレッドシートの再描画 
}

doPost(e)の作成

上記のfunctionを使い、doPost(e)します。
節目ごとにログをシートに記録します。 全ての処理が終わったら、それぞれのuserIdに紐づいたcacheのみを消去します。

function doPost(e) {

  var data = JSON.parse(e.postData.contents);
  var lineType = data.events[0].type;
  var reply_token = data.events[0].replyToken;
  var uid = data.events[0].source.userId;
  var displayName = getDisplayName(uid);
  var message = data.events[0].message.text;

  if (typeof reply_token === undefined || lineType === 'follow' || lineType === 'unfollow') {
    return;
  }

  var eachCache = new EachCache(uid);
  logToSheet('log', message, 'eachCache.log()', eachCache.log());
  var type = eachCache.get("type");
  logToSheet('log', message, 'type == undefined', type == undefined);


  if (type == undefined && message !== 'キャンセル') {
    var text = displayName + 'さん、こんにちは\n今日の天気は?';
    var type = eachCache.put("type", 0);
    reply(reply_token, text);

    logToSheet('log', message, 'eachCache.log()', eachCache.log());

  } else {
    if (message === 'キャンセル') {
      var text = 'キャンセルしました';
      eachCache.cacheClear();
      reply(reply_token, text);

      logToSheet('log', message, 'eachCache.log()', eachCache.log());

    } else {
      switch (type) {
        case '0':
          eachCache.put('type', '1');
          eachCache.put('tenki_today', message);
          var text = '『' + message + '』' + 'ですね、' + '今の気分は?';
          reply(reply_token, text);

          logToSheet('log', message, 'eachCache.log()', eachCache.log());

          break;

        case '1':
          var tenki_today = eachCache.get('tenki_today');
          var text = '今日の天気は『' + tenki_today + '』' + 'で、\n気分は' + '『' + message + '』' + 'ですね!';
          text += '\nお疲れ様です!'
          reply(reply_token, text);
          eachCache.cacheClear(); // 処理が終了したので、userIdに紐づいたcacheを消去

          logToSheet('log', message, 'eachCache.log()', eachCache.log());

          break;

      }
    }
  }

}


まとめ

上記のコードを参考にすれば、googleカレンダーを共有して予約することのできるLINE BOTが作れると思います。
LINE BOTの作り方やMessagingAPIの利用の仕方など省略してしまいましたが、それぞれ検索してもらえればわかりやすいサイトがありますので、そちらを参考にしてください。

お知らせ

可茂IT塾ではFlutterインターンを募集しています!

可茂IT塾ではFlutterインターンを募集しています!

可茂IT塾ではFlutterインターンを募集しています!可茂IT塾のエンジニアの判断で、一定以上のスキルをを習得した方には有給でのインターンも受け入れています。

Read More
U30可茂ITインターンハッカソン

U30可茂ITインターンハッカソン

12月28,29日開催。2日間でアプリ開発の企画から完成までを目指す!U30可茂ITインターンハッカソンを開催します。

Read More

タグ

Flutter (112)初心者向け (28)イベント (18)Google Apps Script (15)Nextjs (12)可茂IT塾 (9)Firebase (7)riverpod (6)React (6)ChatGPT (5)vscode (5)デザイン (5)新卒 (4)就活 (4)Figma (4)Dart (4)JavaScript (4)お知らせ (4)FlutterWeb (3)Prisma (3)NestJS (3)Slack (3)TypeScript (3)ワーケーション (3)インターン (3)設計 (2)線型計画法 (2)事例 (2)Git (2)Image (2)File (2)Material Design (2)画像 (2)iOS (2)アプリ開発 (2)React Hooks (2)tailwindcss (2)社会人 (2)大学生 (2)RSS (1)Google (1)Web (1)CodeRunner (1)個人開発 (1)Android (1)Unity (1)WebView (1)Twitter (1)フルリモート (1)TextScaler (1)textScaleFactor (1)学生向け (1)supabase (1)Java (1)Spring Boot (1)shell script (1)正規表現 (1)パワーポイント (1)趣味 (1)モンスターボール (1)CSS (1)SCSS (1)Cupertino (1)ListView (1)就活浪人 (1)既卒 (1)保守性 (1)iPad (1)シェアハウス (1)スクレイピング (1)PageView (1)画面遷移 (1)flutter_hooks (1)Gmail (1)GoogleWorkspace (1)ShaderMask (1)google map (1)Google Places API (1)GCPコンソール (1)Google_ML_Kit (1)Vercel (1)Google Domains (1)DeepLeaning (1)深層学習 (1)Google Colab (1)コード生成 (1)GitHub Copilot (1)オンラインオフィス (1)オブジェクト指向 (1)クラスの継承 (1)ポリモーフィズム (1)LINE (1)Bitcoin (1)bitFlyer (1)コミュニティー (1)文系エンジニア (1)Freezed (1)ヒーター (1)作業効率 (1) (1)permission_handler (1)flutter_local_notifications (1)markdown (1)GlobalKey (1)ValueKey (1)Key (1)アイコン (1)go_router (1)debug (1)datetime_picker (1)Apple Store Connect (1)FlutterGen (1)デバッグ (1)Widget Inspector (1)VRChat (1)API (1)検索機能 (1)Shader (1)Navigator (1)メール送信 (1)FlutterFlow (1)Firebase App Distribution (1)Fastlane (1)Dio (1)CustomClipper (1)ClipPath (1)カスタム認証 (1)アニメーション (1)Arduino (1)ESP32 (1)経験談 (1)フリーランス (1)mac (1)csv (1)docker (1)GithubActions (1)Dialog (1)BI (1)LifeHack (1)ショートカット (1)Chrome (1)高校生 (1)キャリア教育 (1)非同期処理 (1)生体認証 (1)BackdropFilter (1)レビュー (1)getAuth (1)Algolia (1)コンサルティング (1)Symbol (1)

お知らせ

可茂IT塾ではFlutterインターンを募集しています!

可茂IT塾ではFlutterインターンを募集しています!

可茂IT塾ではFlutterインターンを募集しています!可茂IT塾のエンジニアの判断で、一定以上のスキルをを習得した方には有給でのインターンも受け入れています。

Read More
U30可茂ITインターンハッカソン

U30可茂ITインターンハッカソン

12月28,29日開催。2日間でアプリ開発の企画から完成までを目指す!U30可茂ITインターンハッカソンを開催します。

Read More