Power Automateとローカルスクリプトをプレミアムライセンスなしで連携する方法【Box連携＆Viber通知編】

# はじめに
業務自動化において、**Power Automateとローカルスクリプトの連携**は非常に強力な手段ですが、しばしば**プレミアムライセンスが必要なコネクター**に依存しています。これが、導入や運用の障壁となるケースも少なくありません。

本記事では、**プレミアムライセンスを使わずにPower Automateとローカルスクリプトを双方向で連携させる方法**を、実際のユースケースとともに紹介します。

# 目標
以下のような**プレミアムコネクターに依存しない構成**を目指しました：

- `Request`：外部からPower Automateへリクエストを送信  
- `Response`：Power Automateからのレスポンス返却  
- `HTTP`：外部APIへのアクセス

これらのコネクターを一切使わずに、**Power Automateとローカルスクリプトの双方向通信**を実現する方法を解説します。

# 想定環境
- Power Automate（クラウドフロー）
- SharePoint（無料枠）
- Microsoft Graph API（アプリ登録済み）
- Node.jsスクリプト（ロカール用）
- Box（ファイル共有、Box API未使用）
- Viber API（通知）

# スクリプトからPower Automateへの通信
Boxリンク取得：Boxに保存されたファイルの共有リンクを、Power Automateを使って取得し、スクリプトに返す仕組みを構築しました。

#### 1. スクリプト：フォーム送信（Playwright）
```typescript:playwright.ts
public async submitForm(url: string) {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();

  await page.goto(url); // 事前登録URLを使用、BoxパスとリクエストIDを送信
  await page.getByRole("button", { name: "送信" }).click();
  await browser.close();
}
```

#### 2. Power Automate：リンク生成
- フォーム送信をトリガーにクラウドフローを開始
- `Box Connector`（無料）を使い、パスからファイルID取得
- ファイルIDから共有🔗を生成
- `SharePointリスト`に、リクエストIDをキーにBoxリンクを格納

#### 3. スクリプト：定期的にポーリング（Graph API）
```typescript:Graph.ts
public async requestBoxLink(path: string) {
  const uuid = uuidv4();
  const url = [
    `https://forms.office.com/Pages/ResponsePage.aspx?`,
    `id=<フォームID>`,
    `&<パスのフィールドID>=${path}`,
    `&<リクエストIDのフィールドID>=${uuid}`,
  ].join("");

  await Playwright.submitForm(url);
  return uuid;
}

public async getSharedLinkResponse(requestId: string) {
  const siteId = "xxx"; // sharepointサイトのID
  const list = "xxx"; // リストID
  const url = "https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${listId}/items";
  const params = {
    $expand: "fields",
    $filter: `fields/requestId eq '${requestId}'`,
    $orderby: "createdDateTime desc",
    $top: 1,
  };

  const res = await Postman.getWithParams(url, params, this.accessToken); // axiosのラッパー
  const record = res.data.value.pop();
  record ? return record.files.data : return "";
}
```

#### 4. スクリプト：リンク取得完了まで待機
- Boxリンクが取得できたら処理を終了
- 取得できなければ数秒後に再試行（例：2秒ごとに最大30回）
```typescript:FileUtil.ts
public async getSharedLink(boxPath: string) {
  const requestId = await Graph.requestBoxLink(boxPath);
  let sharedLink = "";
  while (!sharedLink) {
    await CommonUtil.wait(2000);
    sharedLink = await Graph.getSharedLinkResponse(requestId);
  }

  return sharedLink;
}
```

# Power Automateからスクリプトへの通信
Power Automateから生成された通知情報を、スクリプトが定期的に取得し、Viberへ一括送信する仕組みです。

#### 1. Power Automate：通知をSharePointに格納
- 通知が発生したら、SharePointリストに1レコード追加
  - 通知内容（メッセージ、宛先、認証トークンなど）をSharePointリストに記録
  - タスク名：`send-viber`

#### 2. スクリプト：1時間ごとにリストをチェック
```typescript:Graph.ts
public async getViberTasks() {
  const siteId = "xxx"; // sharepointサイトのID
  const list = "xxx"; // リストID
  const url = "https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${listId}/items";
  const params = {
    $expand: "fields",
    $filter: `fields/taskName eq '$send-viber'`,
    $orderby: "createdDateTime desc",
  };

  type Record = {
    id: string;
    fields: {
      taskName: string;
      data: string;
      requestId: string;
      authToken: string;
      broadcaster: string;
    };
  };
  
  const res = await Postman.getWithParams(url, params, this.accessToken); // axiosのラッパー
  const records = res.data.value as Record[];
  
  if (records.lenght > 0) {
    const ids = records.map((record) => record.id);
    const tasks = records.map((record) => ({
      authToken: record.fields.authToken,
      broadcaster: record.fields.broadcaster,
      msg: record.fields.data,
    }));

    await Promise.all(ids.map((id: string) => this.deleteItem(id)));
    return tasks;
  } else {
    return [];
  }
}
```

#### 3. スクリプト：一括でViber送信
```Viber.ts
public async sendQueuedMessages() {
  const tasks = await Graph.getViberTasks();
  for (const task of tasks) {
    await this.postToChannel(task.authToken, task.broadcaster, task.msg);
  }
}
```
```TaskScheduler.ts
private taskConfig: TaskConfig[] = [
  {
    name: "sendQueuedMessages",
    cronExpression: "0 * * * *",
    command: async () => {
      await Viber.sendQueuedMessages();
    },
  }
];
```


## 🔐 注意点と補足

- SharePoint連携にはMicrosoft Graph APIの知識が必要です（アプリ登録とトークン取得）
- Viberは事前にチャンネルの作成・認証が必要です
- Power Automateの無料ライセンス範囲で完結するよう構成しています

## 🧩 まとめ

このように**SharePointを中継サーバーとして活用することで、Power Automateとローカルスクリプト間の双方向通信**を、**完全に無料ライセンスで実現**できます。

- スクリプト→Power Automate：SharePoint経由でBoxリンク取得
- Power Automate→スクリプト：SharePoint経由でViber通知

Power Automateの利用制限で困っている方は、ぜひ参考にしてみてください。