GoogleFormを毎日自動入力

現在編集中
# 利用するサービス
- Azure Functions
# 開発環境
- Windows11
- Azure Functions Core Tools (記事中で解説・インストール)
- VSCode +拡張機能
    - Azure Functions
- Node.js +npmパッケージ
    - Playwright-chromium
- Ubuntu (WSL2 (Windows Subsystem for Linux))
# AzureFunctionsの作成
## 関数アプリの作成
Azure Portalから、関数アプリを作成する。
主要な設定項目：
- 基本
    - ランタイムスタック：Node.js
    - バージョン：16 LTS
    - 地域：Japan East (Westだとうまくいかない？)
    -  __オペレーティングシステム__ : __Linux__
    - (プランの種類：消費量/サーバーレス)
- ホスティング
    - ストレージアカウント：(新規作成)
- 監視
    - Application Insights：(新規作成) 

以上の通り設定して、作成完了。
オペレーティングシステムはLinuxでないと動作しない。
## 関数の作成
VSCodeで作成するのが良い。
Azure Portal上「関数」タブ→「+作成」で、関数の作成からデプロイの仕方まで様々な説明が表示されるので、それを参照すべし。ここに、Azure Funcitons Core Toolsのインストール方法も載っている。
ただし、デプロイに関しては少々特殊な方法になるので、この後の説明をよく読むように。
(PCのOSがWindowsなのに対し、AzureFunctionsのOSがLinuxと異なるため)
### 関数アプリのフォルダ構成
browserフォルダを以下の通りに追加する。
```
/<関数アプリ名>
    - /.vscode
    - /browser (追加)
    - /node-modules
    - /<関数名>
        - function.json
        - index.js
        - sample.dat
    - .funcignore
    - host.json
    - local.setting.json
    - package.json
    - package-lock.json
```
# Playwrightのインストール
Ubuntu上で以下のコマンドを実行する。
```
npx playwright install
```
完了後、エクスプローラーからLinuxを開くと、
`\Ubuntu-20.04\home\<Ubuntuユーザー名>\.cache\ms-playwright`
ここにPlaywrightのブラウザがインストールされているはず。firefoxとかchromiumとか色々。とりあえずそれらを全部コピーして、`browser`フォルダ直下に貼り付ける。
# AzureFunctionsの構成
## Portal上
Azure Portal上の「構成」タブから、アプリケーション設定をいじる。
いずれも詳細は検索せよ。
- `AzureWebJobsStorage`：ストレージアカウントとの紐づけを行う。
- `PLAYWRIGHT_BROWSERS_PATH`：ここでは`./browser`を指定しておく。
## ローカル上
```local.setting.json
{
    "Values": {
        "AzureWebJobsStorage": "<ストレージアカウントとの紐づけ>",
        "PLAYWRIGHT_BROWSERS_PATH": "./browser"
    }
}
```
※ローカル上では、PLAYWRIGHT_BROWSERS_PATHは無くても良い。
# 関数のコーディング
AzureやPlaywrightに関係するところのみ掲載。
ちなみにこれは`Http Trigger`
```index.js
const { chromium } = require("playwright-chromium");

class MyClass {
    constructor(context) {
        //...
    }
    //...
}

module.exports = async function (context, req) {
    context.log('JavaScript HTTP trigger function processed a request.');

    const myClass = new MyClass(context);

    const options = (req.query.allData || (req.body && req.body.allData));
    context.log(options);//object
    const isTest = (req.query.isTest || (req.body && req.body.isTest));
    context.log(`"isTest" is ${isTest}`);

    for (let i = 0; i < options.length; i++) {

        const inputForm = new Promise(async (resolve, _) => {
            //...
            await page.locator(`//*[@id="mG61Hd"]/div[2]/div/div[3]/div[1]/div[1]/div`).click();
            await page.waitForSelector('//*[@id="mG61Hd"]/div[2]/div/div[3]/div[1]/div[1]/div[2]');
            await page.locator(`//*[@id="mG61Hd"]/div[2]/div/div[3]/div[1]/div[1]/div[2]`).click();
            await page.waitForSelector('//html/body/div[1]/div[2]/div[1]/div/div[3]');
            await page.close();
            await browser.close();
            resolve();
        });
        //...
    }

    await Promise.all(["Promiseの配列(inputForm)"]);

    const responseMessage = `This HTTP triggered function executed successfully.`

    context.res = {
        // status: 200, /* Defaults to 200 */
        body: responseMessage
    };
}
```
# 関数のデプロイ
関数の作成で述べた通り、PCのOSがWindowsなのに対してAzureFunctionsのOSがLinuxと異なるため、初期設定のままではデプロイできない。よってここでは「 __リモートビルド__ 」という手段を使う。
そのため、デプロイに2~3分ほど時間がかかる。