diff --git a/extensions/googlechat/src/monitor.test.ts b/extensions/googlechat/src/monitor.test.ts index 5604671ad..c03831021 100644 --- a/extensions/googlechat/src/monitor.test.ts +++ b/extensions/googlechat/src/monitor.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from "vitest"; -import { isSenderAllowed } from "./monitor.js"; +import { isSenderAllowed, resolveSpaceType } from "./monitor.js"; describe("isSenderAllowed", () => { it("matches allowlist entries with users/", () => { @@ -25,3 +25,85 @@ describe("isSenderAllowed", () => { ); }); }); + +describe("resolveSpaceType", () => { + describe("modern spaceType field", () => { + it("detects DIRECT_MESSAGE as DM", () => { + const result = resolveSpaceType({ spaceType: "DIRECT_MESSAGE" }); + expect(result.spaceType).toBe("DIRECT_MESSAGE"); + expect(result.isGroup).toBe(false); + }); + + it("detects SPACE as group", () => { + const result = resolveSpaceType({ spaceType: "SPACE" }); + expect(result.spaceType).toBe("SPACE"); + expect(result.isGroup).toBe(true); + }); + + it("detects GROUP_CHAT as group", () => { + const result = resolveSpaceType({ spaceType: "GROUP_CHAT" }); + expect(result.spaceType).toBe("GROUP_CHAT"); + expect(result.isGroup).toBe(true); + }); + + it("handles lowercase spaceType", () => { + const result = resolveSpaceType({ spaceType: "direct_message" }); + expect(result.spaceType).toBe("DIRECT_MESSAGE"); + expect(result.isGroup).toBe(false); + }); + }); + + describe("deprecated type field fallback", () => { + it("maps legacy DM to DIRECT_MESSAGE", () => { + const result = resolveSpaceType({ type: "DM" }); + expect(result.spaceType).toBe("DIRECT_MESSAGE"); + expect(result.isGroup).toBe(false); + }); + + it("maps legacy ROOM to SPACE", () => { + const result = resolveSpaceType({ type: "ROOM" }); + expect(result.spaceType).toBe("SPACE"); + expect(result.isGroup).toBe(true); + }); + + it("handles lowercase legacy type", () => { + const result = resolveSpaceType({ type: "dm" }); + expect(result.spaceType).toBe("DIRECT_MESSAGE"); + expect(result.isGroup).toBe(false); + }); + }); + + describe("field priority", () => { + it("prefers modern spaceType over deprecated type", () => { + const result = resolveSpaceType({ spaceType: "SPACE", type: "DM" }); + expect(result.spaceType).toBe("SPACE"); + expect(result.isGroup).toBe(true); + }); + + it("falls back to type only when spaceType is missing", () => { + const result = resolveSpaceType({ type: "DM" }); + expect(result.spaceType).toBe("DIRECT_MESSAGE"); + expect(result.isGroup).toBe(false); + }); + + it("falls back to type when spaceType is empty string", () => { + const result = resolveSpaceType({ spaceType: "", type: "DM" }); + expect(result.spaceType).toBe("DIRECT_MESSAGE"); + expect(result.isGroup).toBe(false); + }); + }); + + describe("edge cases", () => { + it("treats empty space as group", () => { + const result = resolveSpaceType({}); + expect(result.spaceType).toBe(""); + expect(result.isGroup).toBe(true); + }); + + it("treats unknown spaceType as group", () => { + const result = resolveSpaceType({ spaceType: "UNKNOWN_TYPE" }); + expect(result.spaceType).toBe("UNKNOWN_TYPE"); + expect(result.isGroup).toBe(true); + }); + }); +}); diff --git a/extensions/googlechat/src/monitor.ts b/extensions/googlechat/src/monitor.ts index 74ea57d68..b87be5a59 100644 --- a/extensions/googlechat/src/monitor.ts +++ b/extensions/googlechat/src/monitor.ts @@ -297,6 +297,27 @@ function normalizeUserId(raw?: string | null): string { return trimmed.replace(/^users\//i, "").toLowerCase(); } +/** + * Resolves the space type from Google Chat space object. + * Normalizes to modern 'spaceType' format with fallback for deprecated 'type' field. + */ +export function resolveSpaceType(space: { type?: string; spaceType?: string }): { + spaceType: string; + isGroup: boolean; +} { + // Normalize to modern 'spaceType' format + let spaceType = (space.spaceType ?? "").toUpperCase(); + + // @deprecated fallback: map legacy 'type' to modern values + if (!spaceType && space.type) { + const legacyType = space.type.toUpperCase(); + spaceType = legacyType === "DM" ? "DIRECT_MESSAGE" : "SPACE"; + } + + const isGroup = spaceType !== "DIRECT_MESSAGE"; + return { spaceType, isGroup }; +} + export function isSenderAllowed( senderId: string, senderEmail: string | undefined, @@ -388,16 +409,7 @@ async function processMessageWithPipeline(params: { const spaceId = space.name ?? ""; if (!spaceId) return; - // Normalize to modern 'spaceType' format - let spaceType = (space.spaceType ?? "").toUpperCase(); - - // @deprecated fallback: map legacy 'type' to modern values - if (!spaceType && space.type) { - const legacyType = space.type.toUpperCase(); - spaceType = legacyType === "DM" ? "DIRECT_MESSAGE" : "SPACE"; - } - - const isGroup = spaceType !== "DIRECT_MESSAGE"; + const { isGroup } = resolveSpaceType(space); const sender = message.sender ?? event.user; const senderId = sender?.name ?? ""; const senderName = sender?.displayName ?? "";