claspでgas(google app script)アプリをいい感じに改修した

thumbnail

mofmofでは毎日オンライン朝会をしていて、2チームに別れてzoomの部屋に入りそれぞれの部屋で1人ずつ最近の出来事をしゃべるってことを15分程やっています。
ちょっと雑談しましょう的なノリです。

以前からgas(google app script)で朝会を管理していたのですが、

- コード管理とデプロイが面倒
- 環境変数にすべき値(スプレッドシートIDとかslackのhookURLなど)をハードコーディングする必要がある
- gs≒はjsなので型が無い

claspを使うとtypescriptで開発できたり、githubと連携してデプロイできそうだったり(※未検証)するので良さそうだなと思ってclaspで作り直しました。

## やること
- スプレッドシートからメンバーリストを取得
- メンバーをシャッフルする
- シャッフルしたメンバーを2チームに分ける
- スプレッドシートからランダムでお題(話すことが思いつかない人用にお題を出す)を1つ取得
- 特別コンテンツ(おしゃべりじゃないことをする日、オンラインゲーム・瞑想・ヨガとか)をやるかどうか抽選する
- ↑情報をテキスト化する
- テキストをslackに通知する

## セットアップ
セットアップ等はこちらの記事を参考にしました。
https://dev.classmethod.jp/articles/ts2gas/

clasp自身がtypescriptを変換してくれるので特に何も考えることもなくtsがgsに変換された上でgasにデプロイされます。

## ファイル分割

typescriptが使えるので、てっきりモジュール化(ESM)・ファイル分割もいけるんだろうと思っていたのですができませんでした。
デプロイしたら単純にimport文がコメントアウトされてるだけでした。

### webpack
サードパーティのプラグイン等を使えばモジュール化もできそうな感じではあったのですが、webpackでローカルビルドしてjsに変換した上でアップする方式にしました。

こちらの記事を参考にしました。
https://zenn.dev/tacck/articles/20211218_gas#webpack-%E8%A8%AD%E5%AE%9A

やってることは

- webpackにgas-webpack-pluginを追加している
- gasが呼び出す関数をトップレベルに設定する
- globalに設定した関数がgas上で選択可能になる
- https://github.com/fossamagna/gas-webpack-plugin
- 例:

```
$index.ts

import { main, timerMain } from "./modules/main";

declare const global: {
 [x: string]: unknown;
};

global.main = main; // 処理の本体。本来はトップレベルにする必要ない(timeMainの中で呼び出される)が、デバッグ用に直接叩くこともあるので追加
global.timerMain = timerMain; // gasのタイマーから呼び出す関数
```

ビルドしてclasp deployするとglobalに設定した関数がgas上で実行可能関数として選択できます。


参考記事のように、package.jsonで以下のようにしとくと便利でした

```
 "scripts": {
  "build": "webpack",
  "push": "npm run build && clasp push" 
 },
```

## テスト

ここまででアプリ自体はできました。
ついでなのでテストもしておこうと思いました。
と言っても最低限のところだけ、作成したメッセージが期待された文言が入っているかをテストしてみました。

### gas特有の関数
spread操作とか環境変数操作等、gas特有の関数に依存しているのでテストするにあたってはスタブを作成する必要があります。
自前で作ると面倒で何かいい感じのものは無いかと調べたらありました。
https://github.com/dan-kushnaryov/gas-mock-globals
一通りのスタブが揃ってるっぽいのでこれをテストコードでimportしてあげればOK

## 完成

こんな感じでslackに通知されます。


- Around: zoomみたいなオンライン会議用チャットツールです。ゲームなどもできます。リアクション機能多め。
- `アンゴラ`・`ウール` はオンライン会議室の名前です。羊からの連想です。
- マスクしている箇所にメンバーの名前がリスト表示されます。

リポジトリはこちらです。
https://github.com/sugiii8/asakai-clasp