142 lines
5.9 KiB
Diff
142 lines
5.9 KiB
Diff
diff --git a/dist/index.js b/dist/index.js
|
|
index b0383953a27e4426ce544128a26bf3c8d8964b06..9ae852cba707495c3e72b0e07523cb6fca2e197a 100644
|
|
--- a/dist/index.js
|
|
+++ b/dist/index.js
|
|
@@ -163,7 +163,6 @@ var BridgeHttpAdapter = class {
|
|
}
|
|
async dispatch(request, options) {
|
|
const body = await request.text();
|
|
- this.logger.debug("Teams webhook raw body", { body });
|
|
let parsedBody;
|
|
try {
|
|
parsedBody = JSON.parse(body);
|
|
@@ -504,6 +503,52 @@ import {
|
|
NetworkError as NetworkError2,
|
|
PermissionError
|
|
} from "@chat-adapter/shared";
|
|
+function teamsErrorRecord(value) {
|
|
+ return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
+}
|
|
+function teamsErrorBody(value) {
|
|
+ if (typeof value === "string") {
|
|
+ if (value.length > 16384) return void 0;
|
|
+ try {
|
|
+ return teamsErrorRecord(JSON.parse(value));
|
|
+ } catch {
|
|
+ return void 0;
|
|
+ }
|
|
+ }
|
|
+ return teamsErrorRecord(value);
|
|
+}
|
|
+function teamsErrorCode(value) {
|
|
+ return typeof value === "string" && /^[A-Za-z][A-Za-z0-9_.-]{0,127}$/.test(value) ? value : void 0;
|
|
+}
|
|
+function teamsErrorCodes(value, depth = 0, seen = /* @__PURE__ */ new Set()) {
|
|
+ if (depth > 4) return [];
|
|
+ const record = teamsErrorBody(value);
|
|
+ if (!record || seen.has(record)) return [];
|
|
+ seen.add(record);
|
|
+ const codes = [teamsErrorCode(record.code), teamsErrorCode(record.subCode), teamsErrorCode(record.subcode)].filter(Boolean);
|
|
+ for (const key of ["error", "innerError", "details", "body", "data"]) {
|
|
+ codes.push(...teamsErrorCodes(record[key], depth + 1, seen));
|
|
+ }
|
|
+ return [...new Set(codes)].slice(0, 8);
|
|
+}
|
|
+function teamsPermissionError(error, operation, statusCode) {
|
|
+ const err = teamsErrorRecord(error) || {};
|
|
+ const innerError = teamsErrorRecord(err.innerHttpError);
|
|
+ const response = teamsErrorRecord(innerError?.response) || teamsErrorRecord(err.response);
|
|
+ const bodies = [innerError, response, err];
|
|
+ const providerCodes = [...new Set(bodies.flatMap((body) => teamsErrorCodes(body)))].slice(0, 8);
|
|
+ const permissionError = new PermissionError("teams", operation);
|
|
+ permissionError.status = statusCode;
|
|
+ permissionError.statusCode = statusCode;
|
|
+ permissionError.providerCodes = providerCodes;
|
|
+ permissionError.subCode = providerCodes.find((code) => code === "MessageWritesBlocked" || code === "ForbiddenOperationException");
|
|
+ permissionError.details = {
|
|
+ providerStatus: statusCode,
|
|
+ providerCodes,
|
|
+ ...permissionError.subCode ? { providerSubCode: permissionError.subCode } : {}
|
|
+ };
|
|
+ return permissionError;
|
|
+}
|
|
function handleTeamsError(error, operation) {
|
|
if (error && typeof error === "object") {
|
|
const err = error;
|
|
@@ -516,7 +561,7 @@ function handleTeamsError(error, operation) {
|
|
);
|
|
}
|
|
if (statusCode === 403 || err.message && typeof err.message === "string" && err.message.toLowerCase().includes("permission")) {
|
|
- throw new PermissionError("teams", operation);
|
|
+ throw teamsPermissionError(error, operation, statusCode);
|
|
}
|
|
if (statusCode === 404) {
|
|
throw new NetworkError2(
|
|
@@ -560,18 +605,15 @@ function encodeThreadId(platformData) {
|
|
const encodedConversationId = Buffer.from(
|
|
platformData.conversationId
|
|
).toString("base64url");
|
|
- const encodedServiceUrl = Buffer.from(platformData.serviceUrl).toString(
|
|
- "base64url"
|
|
- );
|
|
const conversationType = platformData.conversationType;
|
|
const legacyIsDM = !platformData.conversationId.startsWith("19:");
|
|
const explicitIsDM = conversationType === "personal";
|
|
const needsConversationType = conversationType !== void 0 && explicitIsDM !== legacyIsDM;
|
|
- return needsConversationType ? `teams:${encodedConversationId}:${encodedServiceUrl}:${conversationType}` : `teams:${encodedConversationId}:${encodedServiceUrl}`;
|
|
+ return needsConversationType ? `teams:${encodedConversationId}:${conversationType}` : `teams:${encodedConversationId}`;
|
|
}
|
|
function decodeThreadId(threadId) {
|
|
const parts = threadId.split(":");
|
|
- const hasValidPartCount = parts.length === 3 || parts.length === 4;
|
|
+ const hasValidPartCount = parts.length >= 2 && parts.length <= 4;
|
|
if (!hasValidPartCount || parts[0] !== "teams") {
|
|
throw new ValidationError("teams", `Invalid Teams thread ID: ${threadId}`);
|
|
}
|
|
@@ -578,13 +620,16 @@ function decodeThreadId(threadId) {
|
|
const conversationId = Buffer.from(parts[1], "base64url").toString(
|
|
"utf-8"
|
|
);
|
|
- const serviceUrl = Buffer.from(parts[2], "base64url").toString(
|
|
- "utf-8"
|
|
- );
|
|
- const rawConversationType = parts[3];
|
|
- if (!rawConversationType) {
|
|
- return { conversationId, serviceUrl };
|
|
+ if (!parts[2]) {
|
|
+ return { conversationId };
|
|
+ }
|
|
+ const canonicalConversationType = parseConversationType(parts[2]);
|
|
+ if (parts.length === 3 && canonicalConversationType) {
|
|
+ return { conversationId, conversationType: canonicalConversationType };
|
|
}
|
|
+ const serviceUrl = Buffer.from(parts[2], "base64url").toString("utf-8");
|
|
+ const rawConversationType = parts[3];
|
|
+ if (!rawConversationType) return { conversationId, serviceUrl };
|
|
const conversationType = parseConversationType(rawConversationType);
|
|
if (!conversationType) {
|
|
throw new ValidationError(
|
|
@@ -1668,7 +1713,8 @@ var TeamsAdapter = class {
|
|
this.app = new App({
|
|
...toAppOptions(config),
|
|
client: {
|
|
- headers: { "User-Agent": "Vercel.ChatSDK" }
|
|
+ headers: { "User-Agent": "Vercel.ChatSDK" },
|
|
+ timeout: 45e3
|
|
},
|
|
httpServerAdapter: this.bridgeAdapter
|
|
});
|
|
diff --git a/dist/index.d.ts b/dist/index.d.ts
|
|
index 3f516b01355b28baaebc3d3540f85f22521bd4e4..a40328baaf4ee95a9db394001f4865fc662b6794 100644
|
|
--- a/dist/index.d.ts
|
|
+++ b/dist/index.d.ts
|
|
@@ -125,7 +125,7 @@ interface TeamsThreadId {
|
|
conversationId: string;
|
|
conversationType?: "channel" | "groupChat" | "personal";
|
|
replyToId?: string;
|
|
- serviceUrl: string;
|
|
+ serviceUrl?: string;
|
|
}
|
|
/** Teams channel context extracted from activity.channelData */
|
|
interface TeamsChannelContext {
|