DiscourseクエリをGoogle Sheetsと同期する

<div data-theme-toc="true"> </div>

# Discourse Data ExplorerクエリをGoogleスプレッドシートに同期する

> :bookmark: このハウツーガイドでは、Google Apps Scriptを使用して、Discourse Data Explorerクエリの結果をGoogleスプレッドシートに自動的にインポートする方法を説明します。
>
> :person_raising_hand: 必要なユーザーレベル: 管理者

## 概要

GoogleスプレッドシートをDiscourseサイトのData Explorerプラグインに接続することで、スケジュールに基づいてクエリ結果を自動的に取得できます。これは、ダッシュボードの作成、メトリクスの追跡、またはDiscourse管理者アクセス権を持たないチームメンバーとのレポート共有に役立ちます。

## 前提条件

始める前に、以下が揃っていることを確認してください。

*   Discourseサイトで[Data Explorer](https://meta.discourse.org/t/32566)プラグインが有効になっていること
*   同期したい保存済みのData Explorerクエリがあること
*   Discourseサイトへの管理者アクセス権
*   Googleスプレッドシートへのアクセス権を持つGoogleアカウント

## ステップ 1: Discourseの準備

### クエリIDの取得

1.  Discourseサイトの管理者パネルに移動します。
2.  **Plugins** → Data Explorer に移動します。
3.  同期したいクエリを開きます。
4.  ブラウザのアドレスバーのURLを確認します。`.../queries/123` のようになります。末尾の数字が**クエリID**です。

### APIキーの生成

1.  **Admin → Advanced → API Keys** に移動します。

2.  **New API Key** をクリックします。

3.  キーを設定します。

    *   **Description:** 「Google Sheets Sync」など、わかりやすい説明を入力します。
    *   **User Level:** 「Single User」を選択し管理者ユーザーを選ぶか、「All Users」を選択します。
    *   **Scope:** 「Granular」を選択し、Data Explorerセクションの下の **run queries** にチェックを入れます。

    > :information_source: 段階的な「run queries」スコープを使用すると、このAPIキーはData Explorerクエリの実行のみに制限され、グローバルキーを使用するよりも安全です。

4.  **Save** をクリックし、**APIキーをすぐにコピー**します。これ以降、キーを見ることはできません。

APIキーの詳細については、[Create and configure an API key](https://meta.discourse.org/t/create-and-configure-an-api-key/230124)を参照してください。

## ステップ 2: Google Apps Scriptの設定

Google Apps Scriptには `UrlFetchApp` が組み込みサービスとして含まれているため、何もインストールする必要はありません。コードエディタに入力するだけで、スクリプトエンジンが自動的に認識します。

1.  Googleスプレッドシートを開きます。
2.  **Extensions** → **Apps Script** に移動します。
3.  `Code.gs` 内の既存のコードをすべて削除し、以下を貼り付けます。

```javascript
function syncDiscourseData() {
  // ============ CONFIGURATION ============
  const DISCOURSE_URL = "https://your-forum.com"; // あなたのDiscourse URL (末尾のスラッシュなし)
  const QUERY_ID = "123";                         // あなたのData ExplorerクエリID
  const API_KEY = "your_api_key_here";            // あなたのAPIキー
  const API_USERNAME = "system";                  // APIリクエスト用のユーザー名
  // =======================================
  
  const url = `${DISCOURSE_URL}/admin/plugins/explorer/queries/${QUERY_ID}/run.csv`;
  
  const options = {
    "method": "post",
    "headers": {
      "Api-Key": API_KEY,
      "Api-Username": API_USERNAME
    }
  };

  try {
    const response = UrlFetchApp.fetch(url, options);
    const csvData = response.getContentText();
    const data = Utilities.parseCsv(csvData);
    
    const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
    
    // 既存のデータをクリアして新しいデータを書き込む
    sheet.clear(); 
    sheet.getRange(1, 1, data.length, data[0].length).setValues(data);
    
    // データの2列後に「最終更新日時」タイムスタンプを追加
    const timestampCell = sheet.getRange(1, data[0].length + 2);
    const now = new Date();
    timestampCell.setValue("Last Updated: " + Utilities.formatDate(now, Session.getScriptTimeZone(), "yyyy-MM-dd HH:mm:ss"));
    timestampCell.setFontWeight("bold");
    
    Logger.log("Successfully synced " + (data.length - 1) + " rows");
    
  } catch (e) {
    Logger.log("Error: " + e.toString());
  }
}
  1. スクリプト上部の設定値を更新します。
    • https://your-forum.com をあなたのDiscourse URLに置き換えます。
    • 123 をあなたのクエリIDに置き換えます。
    • your_api_key_here をあなたのAPIキーに置き換えます。

ステップ 3: スクリプトの実行と承認

  1. 保存アイコン (:floppy_disk:) をクリックし、プロジェクトに名前を付けます(例: 「Discourse Sync」)。

  2. 実行ボタン (:play_button:) をクリックします。

  3. 承認を求めるポップアップが表示されます。

    • Review Permissions をクリックします。
    • Googleアカウントを選択します。
    • 「Googleがこのアプリを確認していません」と表示された場合は、AdvancedGo to [Project Name] (unsafe) をクリックします。
    • Allow をクリックします。
  4. Googleスプレッドシートを確認します。データが表示されているはずです。

:bulb: エラーが発生した場合は、Apps Scriptエディタで ViewLogs をクリックすると、詳細なエラーメッセージを確認できます。

ステップ 4: 自動同期の設定(オプション)

スケジュールに基づいて同期を自動的に実行するには:

  1. Apps Scriptエディタで、左側のサイドバーにあるTriggersアイコン (:one_o_clock:) をクリックします。

  2. 右下隅の + Add Trigger をクリックします。

  3. トリガーを設定します。

    • Function to run: syncDiscourseData
    • Event source: Time-driven
    • Type of time based trigger: 希望の頻度を選択します(例: Day timer, Hour timer)。
    • Time of day/interval: 同期を実行したい時間を選択します。
  4. Save をクリックします。

パラメータ付きクエリの処理

Data Explorerクエリでパラメータを使用している場合は、リクエストペイロードにそれらを追加します。

const options = {
  "method": "post",
  "headers": {
    "Api-Key": API_KEY,
    "Api-Username": API_USERNAME
  },
  "payload": {
    "params": JSON.stringify({
      "start_date": "2024-01-01",
      "category_id": "5"
    })
  }
};

:warning: すべてのパラメータ値は、数値パラメータであっても文字列である必要があります。

パラメータ付きクエリの実行に関する詳細については、Run Data Explorer queries with the Discourse APIを参照してください。

大規模データセットの処理

CSVエクスポートはデフォルトで最大10,000行に制限されています。より大きなデータセットの場合は、LIMIT および OFFSET パラメータを使用してクエリでページネーションを実装します。

--[params]
-- integer :limit = 1000
-- integer :page = 0

SELECT *
FROM your_table
OFFSET :page * :limit
LIMIT :limit

その後、スクリプトを変更して、結果が返されなくなるまでページをループ処理するようにします。

トラブルシューティング

問題 解決策
403 Forbidden エラー APIキーに「run queries」スコープがあり、ユーザー名に管理者アクセス権があることを確認してください
404 Not Found エラー クエリIDが正しいこと、およびクエリが存在することを確認してください
結果が空になる Data Explorerで直接実行したときにクエリがデータを返すことを確認してください
レート制限エラー DiscourseはデフォルトでData Explorer APIリクエストを10秒間に2回に制限しています。必要に応じてリクエスト間に遅延を追加してください

追加リソース

「いいね!」 2