Files
dingMCP/scripts/xft-open-api-readonly.mjs
T
gitea-admin 504145aec6
CI / Client installer (macos-latest) (push) Canceled after 0s
CI / Client installer (ubuntu-latest) (push) Canceled after 0s
CI / Client installer (windows-latest) (push) Canceled after 0s
CI / test (22) (push) Canceled after 0s
CI / test (24) (push) Canceled after 0s
CI / release-smoke (push) Canceled after 0s
feat: initial public release
2026-08-17 03:04:09 +00:00

75 lines
2.9 KiB
JavaScript

#!/usr/bin/env node
import { readFileSync } from "node:fs";
import { XftOpenApiClient } from "../dist/src/xft-open-api.js";
const [appId, secretFile, enterpriseId, dingTalkUserId, historyBillId] = process.argv.slice(2);
if (!appId || !secretFile || !enterpriseId || !dingTalkUserId) {
console.error("usage: node scripts/xft-open-api-readonly.mjs <appId> <secretFile> <enterpriseId> <dingTalkUserId>");
process.exit(2);
}
const config = {
clientId: "readonly-smoke-test",
clientSecret: "readonly-smoke-test",
apiBaseUrl: "https://api.dingtalk.com",
oapiBaseUrl: "https://oapi.dingtalk.com",
publicBaseUrl: "https://localhost",
port: 3000,
requestTimeoutMs: 15_000,
officialLookbackDays: 120,
officialScanConcurrency: 2,
officialClientOnlyProcessCodes: [],
batchLimit: 20,
xftOpenApi: {
appId,
authoritySecret: (() => {
const lines = readFileSync(secretFile, "utf8").split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
return lines.length >= 2 ? lines[1] : lines[0];
})(),
enterpriseId,
apiBaseUrl: "https://api.cmbchina.com",
encrypted: true,
dingTalkAppCode: "DDingTalk",
},
};
const client = new XftOpenApiClient(config);
if (historyBillId && historyBillId !== "--auth-only") {
try {
const history = await client.request(
`/itrip/xft-api/v1/bills/taskHistory/${encodeURIComponent(historyBillId)}`,
undefined,
"GET",
);
console.log(JSON.stringify({ historyProbe: "ok", responseType: Array.isArray(history) ? "array" : typeof history }));
} catch (error) {
console.log(JSON.stringify({ historyProbe: "failed", message: error instanceof Error ? error.message : String(error) }));
}
}
const user = { userId: dingTalkUserId };
const auth = await client.authStatus(user);
if (historyBillId === "--auth-only") {
console.log(JSON.stringify({ authenticated: auth.authenticated, identity: auth.identity }, null, 2));
process.exit(0);
}
const todos = await client.listMyTodos(user, 200);
const detailCandidates = ["COMMON_REIM", "TRAVEL_REIM"]
.map((eventType) => todos.items.find((item) => item.eventType === eventType))
.filter(Boolean);
const details = await Promise.all(detailCandidates.map((item) => client.getTodoDetail(user, item.billId)));
console.log(JSON.stringify({
authenticated: auth.authenticated,
identity: auth.identity,
todoCount: todos.totalCount,
sample: todos.items.slice(0, 3).map(({ billId, title, applicantName, amount, eventType }) => ({ billId, title, applicantName, amount, eventType })),
detailProbes: details.map((detail) => ({
billId: detail.todo.billId,
eventType: detail.todo.eventType,
formType: Array.isArray(detail.form) ? "array" : typeof detail.form,
formTopLevelKeys: detail.form && typeof detail.form === "object" && !Array.isArray(detail.form)
? Object.keys(detail.form).slice(0, 30)
: [],
})),
diagnostics: todos.diagnostics,
}, null, 2));