@chat-adapter/gchat 4.13.1 → 4.13.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -213
- package/dist/index.d.ts +103 -103
- package/dist/index.js +54 -39
- package/dist/index.js.map +1 -1
- package/package.json +7 -8
package/dist/index.js
CHANGED
|
@@ -309,16 +309,20 @@ function isDMThread(threadId) {
|
|
|
309
309
|
var USER_INFO_KEY_PREFIX = "gchat:user:";
|
|
310
310
|
var USER_INFO_CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
311
311
|
var UserInfoCache = class {
|
|
312
|
+
inMemoryCache = /* @__PURE__ */ new Map();
|
|
313
|
+
state;
|
|
314
|
+
logger;
|
|
312
315
|
constructor(state, logger) {
|
|
313
316
|
this.state = state;
|
|
314
317
|
this.logger = logger;
|
|
315
318
|
}
|
|
316
|
-
inMemoryCache = /* @__PURE__ */ new Map();
|
|
317
319
|
/**
|
|
318
320
|
* Cache user info for later lookup.
|
|
319
321
|
*/
|
|
320
322
|
async set(userId, displayName, email) {
|
|
321
|
-
if (!displayName || displayName === "unknown")
|
|
323
|
+
if (!displayName || displayName === "unknown") {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
322
326
|
const userInfo = { displayName, email };
|
|
323
327
|
this.inMemoryCache.set(userId, userInfo);
|
|
324
328
|
if (this.state) {
|
|
@@ -338,7 +342,9 @@ var UserInfoCache = class {
|
|
|
338
342
|
if (inMemory) {
|
|
339
343
|
return inMemory;
|
|
340
344
|
}
|
|
341
|
-
if (!this.state)
|
|
345
|
+
if (!this.state) {
|
|
346
|
+
return null;
|
|
347
|
+
}
|
|
342
348
|
const cacheKey = `${USER_INFO_KEY_PREFIX}${userId}`;
|
|
343
349
|
const fromState = await this.state.get(cacheKey);
|
|
344
350
|
if (fromState) {
|
|
@@ -517,6 +523,7 @@ function verifyPubSubRequest(request, _expectedAudience) {
|
|
|
517
523
|
var SUBSCRIPTION_REFRESH_BUFFER_MS = 60 * 60 * 1e3;
|
|
518
524
|
var SUBSCRIPTION_CACHE_TTL_MS = 25 * 60 * 60 * 1e3;
|
|
519
525
|
var SPACE_SUB_KEY_PREFIX = "gchat:space-sub:";
|
|
526
|
+
var REACTION_MESSAGE_NAME_PATTERN = /(spaces\/[^/]+\/messages\/[^/]+)/;
|
|
520
527
|
var GoogleChatAdapter = class {
|
|
521
528
|
name = "gchat";
|
|
522
529
|
userName;
|
|
@@ -661,7 +668,7 @@ var GoogleChatAdapter = class {
|
|
|
661
668
|
hasCredentials: !!this.credentials,
|
|
662
669
|
hasADC: this.useADC
|
|
663
670
|
});
|
|
664
|
-
if (!this.pubsubTopic
|
|
671
|
+
if (!(this.pubsubTopic && this.state)) {
|
|
665
672
|
this.logger.warn("ensureSpaceSubscription skipped - missing config", {
|
|
666
673
|
hasPubsubTopic: !!this.pubsubTopic,
|
|
667
674
|
hasState: !!this.state
|
|
@@ -720,7 +727,9 @@ var GoogleChatAdapter = class {
|
|
|
720
727
|
return;
|
|
721
728
|
}
|
|
722
729
|
const pubsubTopic = this.pubsubTopic;
|
|
723
|
-
if (!pubsubTopic)
|
|
730
|
+
if (!pubsubTopic) {
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
724
733
|
try {
|
|
725
734
|
const existing = await this.findExistingSubscription(
|
|
726
735
|
spaceName,
|
|
@@ -857,9 +866,7 @@ var GoogleChatAdapter = class {
|
|
|
857
866
|
const invokedFunction = event.commonEventObject?.invokedFunction;
|
|
858
867
|
if (buttonClickedPayload || invokedFunction) {
|
|
859
868
|
this.handleCardClick(event, options);
|
|
860
|
-
return
|
|
861
|
-
headers: { "Content-Type": "application/json" }
|
|
862
|
-
});
|
|
869
|
+
return Response.json({});
|
|
863
870
|
}
|
|
864
871
|
const messagePayload = event.chat?.messagePayload;
|
|
865
872
|
if (messagePayload) {
|
|
@@ -869,15 +876,13 @@ var GoogleChatAdapter = class {
|
|
|
869
876
|
text: messagePayload.message.text?.slice(0, 50)
|
|
870
877
|
});
|
|
871
878
|
this.handleMessageEvent(event, options);
|
|
872
|
-
} else if (!addedPayload
|
|
879
|
+
} else if (!(addedPayload || removedPayload)) {
|
|
873
880
|
this.logger.debug("Non-message event received", {
|
|
874
881
|
hasChat: !!event.chat,
|
|
875
882
|
hasCommonEventObject: !!event.commonEventObject
|
|
876
883
|
});
|
|
877
884
|
}
|
|
878
|
-
return
|
|
879
|
-
headers: { "Content-Type": "application/json" }
|
|
880
|
-
});
|
|
885
|
+
return Response.json({});
|
|
881
886
|
}
|
|
882
887
|
/**
|
|
883
888
|
* Handle Pub/Sub push messages from Workspace Events subscriptions.
|
|
@@ -892,9 +897,7 @@ var GoogleChatAdapter = class {
|
|
|
892
897
|
];
|
|
893
898
|
if (eventType && !allowedEventTypes.includes(eventType)) {
|
|
894
899
|
this.logger.debug("Skipping unsupported Pub/Sub event", { eventType });
|
|
895
|
-
return
|
|
896
|
-
headers: { "Content-Type": "application/json" }
|
|
897
|
-
});
|
|
900
|
+
return Response.json({ success: true });
|
|
898
901
|
}
|
|
899
902
|
try {
|
|
900
903
|
const notification = decodePubSubMessage(pushMessage);
|
|
@@ -909,9 +912,7 @@ var GoogleChatAdapter = class {
|
|
|
909
912
|
if (notification.reaction) {
|
|
910
913
|
this.handlePubSubReactionEvent(notification, options);
|
|
911
914
|
}
|
|
912
|
-
return
|
|
913
|
-
headers: { "Content-Type": "application/json" }
|
|
914
|
-
});
|
|
915
|
+
return Response.json({ success: true });
|
|
915
916
|
} catch (error) {
|
|
916
917
|
this.logger.error("Error processing Pub/Sub message", { error });
|
|
917
918
|
return new Response(JSON.stringify({ error: "Processing failed" }), {
|
|
@@ -924,7 +925,7 @@ var GoogleChatAdapter = class {
|
|
|
924
925
|
* Handle message events received via Pub/Sub (Workspace Events).
|
|
925
926
|
*/
|
|
926
927
|
handlePubSubMessageEvent(notification, options) {
|
|
927
|
-
if (!this.chat
|
|
928
|
+
if (!(this.chat && notification.message)) {
|
|
928
929
|
return;
|
|
929
930
|
}
|
|
930
931
|
const message = notification.message;
|
|
@@ -960,16 +961,14 @@ var GoogleChatAdapter = class {
|
|
|
960
961
|
* Fetches the message to get thread context for proper reply threading.
|
|
961
962
|
*/
|
|
962
963
|
handlePubSubReactionEvent(notification, options) {
|
|
963
|
-
if (!this.chat
|
|
964
|
+
if (!(this.chat && notification.reaction)) {
|
|
964
965
|
return;
|
|
965
966
|
}
|
|
966
967
|
const reaction = notification.reaction;
|
|
967
968
|
const rawEmoji = reaction.emoji?.unicode || "";
|
|
968
969
|
const normalizedEmoji = defaultEmojiResolver.fromGChat(rawEmoji);
|
|
969
970
|
const reactionName = reaction.name || "";
|
|
970
|
-
const messageNameMatch = reactionName.match(
|
|
971
|
-
/(spaces\/[^/]+\/messages\/[^/]+)/
|
|
972
|
-
);
|
|
971
|
+
const messageNameMatch = reactionName.match(REACTION_MESSAGE_NAME_PATTERN);
|
|
973
972
|
const messageName = messageNameMatch ? messageNameMatch[1] : "";
|
|
974
973
|
const spaceName = notification.targetResource?.replace(
|
|
975
974
|
"//chat.googleapis.com/",
|
|
@@ -1602,7 +1601,7 @@ var GoogleChatAdapter = class {
|
|
|
1602
1601
|
try {
|
|
1603
1602
|
const filter = threadName ? `thread.name = "${threadName}"` : void 0;
|
|
1604
1603
|
if (direction === "forward") {
|
|
1605
|
-
return this.fetchMessagesForward(
|
|
1604
|
+
return await this.fetchMessagesForward(
|
|
1606
1605
|
api,
|
|
1607
1606
|
spaceName,
|
|
1608
1607
|
threadId,
|
|
@@ -1611,7 +1610,7 @@ var GoogleChatAdapter = class {
|
|
|
1611
1610
|
options.cursor
|
|
1612
1611
|
);
|
|
1613
1612
|
}
|
|
1614
|
-
return this.fetchMessagesBackward(
|
|
1613
|
+
return await this.fetchMessagesBackward(
|
|
1615
1614
|
api,
|
|
1616
1615
|
spaceName,
|
|
1617
1616
|
threadId,
|
|
@@ -1718,7 +1717,7 @@ var GoogleChatAdapter = class {
|
|
|
1718
1717
|
);
|
|
1719
1718
|
let nextCursor;
|
|
1720
1719
|
if (startIndex + limit < allRawMessages.length && selectedMessages.length > 0) {
|
|
1721
|
-
const lastMsg = selectedMessages
|
|
1720
|
+
const lastMsg = selectedMessages.at(-1);
|
|
1722
1721
|
if (lastMsg?.name) {
|
|
1723
1722
|
nextCursor = lastMsg.name;
|
|
1724
1723
|
}
|
|
@@ -1816,7 +1815,7 @@ var GoogleChatAdapter = class {
|
|
|
1816
1815
|
const limit = options.limit || 100;
|
|
1817
1816
|
try {
|
|
1818
1817
|
if (direction === "backward") {
|
|
1819
|
-
return this.fetchChannelMessagesBackward(
|
|
1818
|
+
return await this.fetchChannelMessagesBackward(
|
|
1820
1819
|
api,
|
|
1821
1820
|
spaceName,
|
|
1822
1821
|
channelId,
|
|
@@ -1824,7 +1823,7 @@ var GoogleChatAdapter = class {
|
|
|
1824
1823
|
options.cursor
|
|
1825
1824
|
);
|
|
1826
1825
|
}
|
|
1827
|
-
return this.fetchChannelMessagesForward(
|
|
1826
|
+
return await this.fetchChannelMessagesForward(
|
|
1828
1827
|
api,
|
|
1829
1828
|
spaceName,
|
|
1830
1829
|
channelId,
|
|
@@ -1845,13 +1844,17 @@ var GoogleChatAdapter = class {
|
|
|
1845
1844
|
* Messages without a thread field (e.g., in non-threaded spaces) are always top-level.
|
|
1846
1845
|
*/
|
|
1847
1846
|
isThreadRoot(msg) {
|
|
1848
|
-
if (!msg.thread?.name
|
|
1847
|
+
if (!(msg.thread?.name && msg.name)) {
|
|
1848
|
+
return true;
|
|
1849
|
+
}
|
|
1849
1850
|
const threadParts = msg.thread.name.split("/");
|
|
1850
|
-
const threadId = threadParts
|
|
1851
|
+
const threadId = threadParts.at(-1);
|
|
1851
1852
|
const msgParts = msg.name.split("/");
|
|
1852
|
-
const msgIdFull = msgParts
|
|
1853
|
+
const msgIdFull = msgParts.at(-1) || "";
|
|
1853
1854
|
const dotIndex = msgIdFull.indexOf(".");
|
|
1854
|
-
if (dotIndex === -1)
|
|
1855
|
+
if (dotIndex === -1) {
|
|
1856
|
+
return true;
|
|
1857
|
+
}
|
|
1855
1858
|
const msgThreadPart = msgIdFull.slice(0, dotIndex);
|
|
1856
1859
|
const msgIdPart = msgIdFull.slice(dotIndex + 1);
|
|
1857
1860
|
return msgThreadPart === msgIdPart && msgThreadPart === threadId;
|
|
@@ -1877,14 +1880,18 @@ var GoogleChatAdapter = class {
|
|
|
1877
1880
|
orderBy: "createTime desc"
|
|
1878
1881
|
});
|
|
1879
1882
|
const pageMessages = response.data.messages || [];
|
|
1880
|
-
if (pageMessages.length === 0)
|
|
1883
|
+
if (pageMessages.length === 0) {
|
|
1884
|
+
break;
|
|
1885
|
+
}
|
|
1881
1886
|
for (const msg of pageMessages) {
|
|
1882
1887
|
if (this.isThreadRoot(msg)) {
|
|
1883
1888
|
topLevel.push(msg);
|
|
1884
1889
|
}
|
|
1885
1890
|
}
|
|
1886
1891
|
apiNextPageToken = response.data.nextPageToken ?? void 0;
|
|
1887
|
-
if (!apiNextPageToken)
|
|
1892
|
+
if (!apiNextPageToken) {
|
|
1893
|
+
break;
|
|
1894
|
+
}
|
|
1888
1895
|
pageToken = apiNextPageToken;
|
|
1889
1896
|
}
|
|
1890
1897
|
const selected = topLevel.slice(0, limit).reverse();
|
|
@@ -1922,7 +1929,9 @@ var GoogleChatAdapter = class {
|
|
|
1922
1929
|
let startIndex = 0;
|
|
1923
1930
|
if (cursor) {
|
|
1924
1931
|
const cursorIndex = topLevel.findIndex((msg) => msg.name === cursor);
|
|
1925
|
-
if (cursorIndex >= 0)
|
|
1932
|
+
if (cursorIndex >= 0) {
|
|
1933
|
+
startIndex = cursorIndex + 1;
|
|
1934
|
+
}
|
|
1926
1935
|
}
|
|
1927
1936
|
const selectedMessages = topLevel.slice(startIndex, startIndex + limit);
|
|
1928
1937
|
const messages = await Promise.all(
|
|
@@ -1932,8 +1941,10 @@ var GoogleChatAdapter = class {
|
|
|
1932
1941
|
);
|
|
1933
1942
|
let nextCursor;
|
|
1934
1943
|
if (startIndex + limit < topLevel.length && selectedMessages.length > 0) {
|
|
1935
|
-
const lastMsg = selectedMessages
|
|
1936
|
-
if (lastMsg?.name)
|
|
1944
|
+
const lastMsg = selectedMessages.at(-1);
|
|
1945
|
+
if (lastMsg?.name) {
|
|
1946
|
+
nextCursor = lastMsg.name;
|
|
1947
|
+
}
|
|
1937
1948
|
}
|
|
1938
1949
|
return { messages, nextCursor };
|
|
1939
1950
|
}
|
|
@@ -1968,7 +1979,9 @@ var GoogleChatAdapter = class {
|
|
|
1968
1979
|
const threadMap = /* @__PURE__ */ new Map();
|
|
1969
1980
|
for (const msg of rawMessages) {
|
|
1970
1981
|
const threadName = msg.thread?.name;
|
|
1971
|
-
if (!threadName)
|
|
1982
|
+
if (!threadName) {
|
|
1983
|
+
continue;
|
|
1984
|
+
}
|
|
1972
1985
|
const existing = threadMap.get(threadName);
|
|
1973
1986
|
if (existing) {
|
|
1974
1987
|
existing.count++;
|
|
@@ -1979,7 +1992,9 @@ var GoogleChatAdapter = class {
|
|
|
1979
1992
|
const threads = [];
|
|
1980
1993
|
let count = 0;
|
|
1981
1994
|
for (const [threadName, { rootMsg, count: replyCount }] of threadMap) {
|
|
1982
|
-
if (count >= limit)
|
|
1995
|
+
if (count >= limit) {
|
|
1996
|
+
break;
|
|
1997
|
+
}
|
|
1983
1998
|
const threadId = this.encodeThreadId({
|
|
1984
1999
|
spaceName,
|
|
1985
2000
|
threadName
|