将 Discourse 查询同步到 Google Sheets 的自动化操作

将 Discourse Data Explorer 查询同步到 Google 表格

:bookmark: 本操作指南说明如何使用 Google Apps Script 自动将 Discourse Data Explorer 查询结果导入 Google 表格。

:person_raising_hand: 所需用户级别:管理员

概述

通过将 Google 表格连接到 Discourse 站点的 Data Explorer 插件,您可以按计划自动提取查询结果。这对于创建仪表板、跟踪指标或与没有 Discourse 管理员访问权限的团队成员共享报告非常有用。

先决条件

在开始之前,请确保您拥有:

  • Discourse 站点上启用了 Data Explorer 插件
  • 您想要同步的已保存的 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 密钥 (API Keys)

  2. 点击 新建 API 密钥 (New API Key)

  3. 配置密钥:

    • 描述 (Description): 输入描述性的内容,例如“Google 表格同步 (Google Sheets Sync)”
    • 用户级别 (User Level): 选择“单个用户 (Single User)”并选择一个管理员用户,或选择“所有用户 (All Users)”
    • 范围 (Scope): 选择“细粒度 (Granular)”,然后在 Data Explorer 部分勾选 运行查询 (run queries)

    :information_source: 使用细粒度的“运行查询”范围将此 API 密钥限制为仅运行 Data Explorer 查询,这比使用全局密钥更安全。

  4. 点击 保存 (Save)立即复制 API 密钥——您将无法再次看到它

有关 API 密钥的更多详细信息,请参阅:创建和配置 API 密钥

步骤 2:设置 Google Apps Script

Google Apps Script 包含 UrlFetchApp 作为内置服务——您无需安装任何内容。只需将其键入代码编辑器中,脚本引擎就会自动识别它。

  1. 打开您的 Google 表格
  2. 前往 扩展程序 (Extensions)Apps Script
  3. 删除 Code.gs 中任何现有代码并粘贴以下内容:
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/discourse-data-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);
    
    // 在数据后两列添加“最后更新”时间戳
    const timestampCell = sheet.getRange(1, data[0].length + 2);
    const now = new Date();
    timestampCell.setValue("最后更新: " + Utilities.formatDate(now, Session.getScriptTimeZone(), "yyyy-MM-dd HH:mm:ss"));
    timestampCell.setFontWeight("bold");
    
    Logger.log("成功同步 " + (data.length - 1) + " 行");
    
  } catch (e) {
    Logger.log("错误: " + e.toString());
  }
}
  1. 更新脚本顶部的配置值:
    • https://your-forum.com 替换为您的 Discourse URL
    • 123 替换为您的查询 ID
    • your_api_key_here 替换为您的 API 密钥

步骤 3:运行并授权脚本

  1. 点击保存图标 (:floppy_disk:) 并命名您的项目(例如:“Discourse 同步 (Discourse Sync)”)

  2. 点击运行按钮 (:play_button:)

  3. 将出现一个弹出窗口,要求授权:

    • 点击查看权限 (Review Permissions)
    • 选择您的 Google 帐户
    • 如果您看到“Google 尚未验证此应用”,请点击高级 (Advanced)转到 [项目名称] (不安全) (Go to [Project Name] (unsafe))
    • 点击允许 (Allow)
  4. 检查您的 Google 表格——数据现在应该会出现

:bulb: 如果遇到错误,请在 Apps Script 编辑器中点击查看 (View)日志 (Logs) 以查看详细的错误消息。

步骤 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): 选择您首选的频率(例如:每日计时器、每小时计时器)
    • 一天中的时间/间隔 (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: 所有参数值都必须是字符串,即使是数字参数也是如此。

有关运行带参数查询的更多详细信息,请参阅:使用 Discourse API 运行 Data Explorer 查询

处理大型数据集

CSV 导出默认最多包含 10,000 行。对于更大的数据集,请在查询中使用 LIMITOFFSET 参数来实现分页:

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

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

然后修改您的脚本以循环遍历页面,直到没有更多结果返回为止。

故障排除

问题 解决方案
403 禁止访问错误 验证您的 API 密钥是否具有“运行查询”范围,并且用户名是否具有管理员访问权限
404 未找到错误 检查查询 ID 是否正确以及查询是否存在
结果为空 验证在 Data Explorer 中直接运行时查询是否返回数据
速率限制错误 默认情况下,Discourse 将 Data Explorer API 请求限制为每 10 秒 2 次。如有需要,请在请求之间添加延迟

附加资源

4 个赞