我畀 Claude Code 起咗個 X 私訊同提及監聽器——完全冇掂過 X 嘅 API — UnifyPort
X 嘅 API 冇免費方案。讀取一條私訊收 $0.015,讀取一條帖文收 $0.005。如果你係一個兩人團隊,淨係想知有人喺 X 上面發咗私訊或者提及咗你,官方開發者平台會要求你先增值、建立專案、等審批、開計量收費——你一條訊息都未處理過。
我跳過晒呢啲。打開 Claude Code,將 UnifyPort 嘅 webhook 介面文件貼到上下文度,叫佢用 Node.js 起一個 X 私訊同提及監聽器。四十分鐘之後,我有咗一個 Express 伺服器,可以驗證每次交付嘅簽章、將事件寫入結構化日誌檔、同埋推送告警到 Discord 頻道。唔使 X 開發者帳號,唔使按次收費,唔使排隊審批。
你最後會得到咩
一個 Node.js Express 伺服器:
- 接收 UnifyPort 統一 webhook 嘅
message.received事件 - 用 HMAC-SHA256 同
signing_secret驗證每次交付嘅簽章 - 將每條 X 訊息寫入
messages.jsonl檔案 - 透過 webhook 向 Discord 頻道發送告警
時間:唔使一個鐘。你需要一個 UnifyPort 工作區,透過 UnifyPort Exporter 瀏覽器擴充功能連接 X 帳號——一鍵工作階段匯入,唔使開發者憑證——同埋一個 Discord webhook URL。
準備工作:將文件餵畀 Claude Code
喺提示之前,先將 API 文件送入代理嘅上下文。Claude Code 可以直接讀檔案,所以喺專案根目錄建立 unifyport-reference.md,包含:
message.received事件酬載結構x-unifyport-signature標頭同 HMAC-SHA256 簽章驗證說明POST /v1/webhook-endpoints建立呼叫
亦可以將呢啲內容直接貼到對話度。重點:真實嘅欄位名輸入,正確嘅程式碼輸出。冇文件嘅話,代理會自己發明一個 X 專用 SDK 或者根本唔存在嘅 dm.received 事件類型。
Cursor、Windsurf、Copilot 用法一樣——用 @Docs、文件面板或者直接貼文件到上下文。工具係次要嘅,文件先係核心。
建構過程:逐條提示
第一個提示——骨架:
讀取 unifyport-reference.md。用 Express 寫一個 server.js,包含 POST /webhook 路由。當 event 係 “message.received” 時,印出 provider、from 同 text 欄位。所有請求回傳 200。
Claude Code 輸出:
import express from "express";
const app = express();
app.use(express.json());
app.post("/webhook", (req, res) => {
const evt = req.body;
if (evt.event === "message.received") {
console.log(`[${evt.provider}] ${evt.from}: ${evt.text}`);
}
res.sendStatus(200);
});
app.listen(3000, () => console.log("listening on :3000"));
六行處理器。因為事件結構喺六個平台上完全一致,唔使任何 X 專用嘅解析——evt.provider 顯示 "x",但結構同 WhatsApp 或 Telegram 訊息完全一樣。
第二個提示——簽章驗證:
每次交付都包含 x-unifyport-signature 標頭。用環境變數入面嘅 signing_secret 做 HMAC-SHA256 驗證。HMAC 一定要對原始請求本體計算——唔可以對重新序列化嘅 JSON 計算。驗證失敗回傳 401。用時間安全比較。
Claude Code 加上驗證層:
import crypto from "crypto";
const SIGNING_SECRET = process.env.UNIFYPORT_SIGNING_SECRET;
app.use(express.json({
verify: (req, _res, buf) => { req.rawBody = buf; }
}));
function isValid(req) {
const sig = req.get("x-unifyport-signature") || "";
const expected = crypto
.createHmac("sha256", SIGNING_SECRET)
.update(req.rawBody)
.digest("hex");
return sig.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}
verify 回呼喺 Express 解析 JSON 之前捕獲原始 buffer——如果代理用咗 req.body 再序列化成 JSON,HMAC 永遠唔會匹配。因為提示講明咗「原始請求本體」,代理一次就寫啱。
第三個提示——日誌記錄同 Discord 告警:
加兩個功能:(1) 將每個 message.received 事件附加到 messages.jsonl——每行一個 JSON 物件,包含 timestamp、provider、from、text 同 message_id。(2) 向環境變數 DISCORD_WEBHOOK_URL 指定嘅 Discord webhook 發送一行告警。
完整嘅 server.js:
import express from "express";
import crypto from "crypto";
import { appendFileSync } from "fs";
const SIGNING_SECRET = process.env.UNIFYPORT_SIGNING_SECRET;
const DISCORD_WEBHOOK = process.env.DISCORD_WEBHOOK_URL;
const app = express();
app.use(express.json({
verify: (req, _res, buf) => { req.rawBody = buf; }
}));
function isValid(req) {
const sig = req.get("x-unifyport-signature") || "";
const expected = crypto
.createHmac("sha256", SIGNING_SECRET)
.update(req.rawBody)
.digest("hex");
return sig.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}
app.post("/webhook", async (req, res) => {
if (!isValid(req)) return res.sendStatus(401);
const evt = req.body;
if (evt.event === "message.received") {
const record = JSON.stringify({
timestamp: evt.timestamp,
provider: evt.provider,
from: evt.from,
text: evt.text,
message_id: evt.message_id,
});
appendFileSync("messages.jsonl", record + "\n");
if (DISCORD_WEBHOOK) {
await fetch(DISCORD_WEBHOOK, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
content: `**[${evt.provider}]** ${evt.from}: ${evt.text}`,
}),
});
}
}
res.sendStatus(200);
});
app.listen(3000, () => console.log("listening on :3000"));
唔使 50 行。簽章驗證、磁碟日誌、Discord 轉發全部搞掂。處理器唔會對 provider 做分支判斷——事件結構一樣,唔理訊息係嚟自 X、WhatsApp 定其他平台。
執行同睇到 X 訊息到達
喺 UnifyPort 控制台連接你嘅 X 帳號。X 用 UnifyPort Exporter 瀏覽器擴充功能做工作階段匯入——撳擴充功能圖示、授權,幾秒鐘帳號就連接好。唔使開發者後台,唔使申請 API 金鑰,唔使審批佇列。
註冊一個 webhook 端點指向你嘅伺服器,設定 subscribed_events: ["message.received"] 同 signing_secret。啟動伺服器,然後用另一個帳號畀你嘅 X 帳號發一條測試私訊。事件到達:
{
"event": "message.received",
"account_id": "acct_7Kp3mR",
"provider": "x",
"from": "user_9d4f2b",
"text": "Hey, are you still taking freelance projects?",
"timestamp": 1750521600,
"message_id": "x_msg_8c1e5a"
}
你嘅伺服器驗證簽章、將紀錄附加到 messages.jsonl、同埋將告警發送到 Discord。如果簽章驗證失敗——401——檢查 UNIFYPORT_SIGNING_SECRET 係咪同 webhook 端點上設定嘅值一致。
擴展:零程式碼改動加入 Telegram
喺同一個工作區連接 Telegram 帳號,訂閱同一個 webhook 端點。Telegram 訊息以完全相同嘅結構到達——唔同嘅 provider 欄位,結構一模一樣:
{
"event": "message.received",
"account_id": "acct_2Xn5wL",
"provider": "telegram",
"from": "user_4a7c8d",
"text": "Can you hop on a call tomorrow?",
"timestamp": 1750521660,
"message_id": "tg_msg_3b9f1e"
}
唔使新嘅處理器,唔使 Telegram 專用嘅解析邏輯。messages.jsonl 檔案而家同時包含 X 同 Telegram 事件,用相同嘅 schema,Discord 顯示兩個來源嘅告警。之後加 WhatsApp、LINE、Zalo 或 TikTok 都係同樣流程——連接帳號,現有嘅處理器自動處理一切。
呢個同直接對接 X API 嘅分別唔止係成本——而係準入門檻。X 要求通過審核嘅開發者帳號、增值嘅專案同按次計費嘅承諾。UnifyPort 嘅工作階段匯入路徑透過瀏覽器連接你嘅個人 X 帳號,將每條私訊同提及正規化為同其他五個平台完全相同嘅事件結構。將 Claude Code 指向呢個介面——一個事件 schema、一個簽章機制——你就可以喺食晏之前跑起一個帶驗證、日誌、告警嘅監聽器。然後加埋其他所有平台,程式碼一行都唔使改。