@chat-adapter/gchat 4.13.0 → 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 +60 -42
- package/dist/index.js.map +1 -1
- package/package.json +7 -8
package/dist/index.js
CHANGED
|
@@ -85,8 +85,11 @@ function convertChildToWidgets(child, endpointUrl) {
|
|
|
85
85
|
return [];
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
|
+
function markdownToGChat(text) {
|
|
89
|
+
return text.replace(/\*\*(.+?)\*\*/g, "*$1*");
|
|
90
|
+
}
|
|
88
91
|
function convertTextToWidget(element) {
|
|
89
|
-
let text = convertEmoji(element.content);
|
|
92
|
+
let text = markdownToGChat(convertEmoji(element.content));
|
|
90
93
|
if (element.style === "bold") {
|
|
91
94
|
text = `*${text}*`;
|
|
92
95
|
} else if (element.style === "muted") {
|
|
@@ -169,8 +172,8 @@ function convertSectionToWidgets(element, endpointUrl) {
|
|
|
169
172
|
function convertFieldsToWidgets(element) {
|
|
170
173
|
return element.children.map((field) => ({
|
|
171
174
|
decoratedText: {
|
|
172
|
-
topLabel: convertEmoji(field.label),
|
|
173
|
-
text: convertEmoji(field.value)
|
|
175
|
+
topLabel: markdownToGChat(convertEmoji(field.label)),
|
|
176
|
+
text: markdownToGChat(convertEmoji(field.value))
|
|
174
177
|
}
|
|
175
178
|
}));
|
|
176
179
|
}
|
|
@@ -306,16 +309,20 @@ function isDMThread(threadId) {
|
|
|
306
309
|
var USER_INFO_KEY_PREFIX = "gchat:user:";
|
|
307
310
|
var USER_INFO_CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
308
311
|
var UserInfoCache = class {
|
|
312
|
+
inMemoryCache = /* @__PURE__ */ new Map();
|
|
313
|
+
state;
|
|
314
|
+
logger;
|
|
309
315
|
constructor(state, logger) {
|
|
310
316
|
this.state = state;
|
|
311
317
|
this.logger = logger;
|
|
312
318
|
}
|
|
313
|
-
inMemoryCache = /* @__PURE__ */ new Map();
|
|
314
319
|
/**
|
|
315
320
|
* Cache user info for later lookup.
|
|
316
321
|
*/
|
|
317
322
|
async set(userId, displayName, email) {
|
|
318
|
-
if (!displayName || displayName === "unknown")
|
|
323
|
+
if (!displayName || displayName === "unknown") {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
319
326
|
const userInfo = { displayName, email };
|
|
320
327
|
this.inMemoryCache.set(userId, userInfo);
|
|
321
328
|
if (this.state) {
|
|
@@ -335,7 +342,9 @@ var UserInfoCache = class {
|
|
|
335
342
|
if (inMemory) {
|
|
336
343
|
return inMemory;
|
|
337
344
|
}
|
|
338
|
-
if (!this.state)
|
|
345
|
+
if (!this.state) {
|
|
346
|
+
return null;
|
|
347
|
+
}
|
|
339
348
|
const cacheKey = `${USER_INFO_KEY_PREFIX}${userId}`;
|
|
340
349
|
const fromState = await this.state.get(cacheKey);
|
|
341
350
|
if (fromState) {
|
|
@@ -514,6 +523,7 @@ function verifyPubSubRequest(request, _expectedAudience) {
|
|
|
514
523
|
var SUBSCRIPTION_REFRESH_BUFFER_MS = 60 * 60 * 1e3;
|
|
515
524
|
var SUBSCRIPTION_CACHE_TTL_MS = 25 * 60 * 60 * 1e3;
|
|
516
525
|
var SPACE_SUB_KEY_PREFIX = "gchat:space-sub:";
|
|
526
|
+
var REACTION_MESSAGE_NAME_PATTERN = /(spaces\/[^/]+\/messages\/[^/]+)/;
|
|
517
527
|
var GoogleChatAdapter = class {
|
|
518
528
|
name = "gchat";
|
|
519
529
|
userName;
|
|
@@ -658,7 +668,7 @@ var GoogleChatAdapter = class {
|
|
|
658
668
|
hasCredentials: !!this.credentials,
|
|
659
669
|
hasADC: this.useADC
|
|
660
670
|
});
|
|
661
|
-
if (!this.pubsubTopic
|
|
671
|
+
if (!(this.pubsubTopic && this.state)) {
|
|
662
672
|
this.logger.warn("ensureSpaceSubscription skipped - missing config", {
|
|
663
673
|
hasPubsubTopic: !!this.pubsubTopic,
|
|
664
674
|
hasState: !!this.state
|
|
@@ -717,7 +727,9 @@ var GoogleChatAdapter = class {
|
|
|
717
727
|
return;
|
|
718
728
|
}
|
|
719
729
|
const pubsubTopic = this.pubsubTopic;
|
|
720
|
-
if (!pubsubTopic)
|
|
730
|
+
if (!pubsubTopic) {
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
721
733
|
try {
|
|
722
734
|
const existing = await this.findExistingSubscription(
|
|
723
735
|
spaceName,
|
|
@@ -854,9 +866,7 @@ var GoogleChatAdapter = class {
|
|
|
854
866
|
const invokedFunction = event.commonEventObject?.invokedFunction;
|
|
855
867
|
if (buttonClickedPayload || invokedFunction) {
|
|
856
868
|
this.handleCardClick(event, options);
|
|
857
|
-
return
|
|
858
|
-
headers: { "Content-Type": "application/json" }
|
|
859
|
-
});
|
|
869
|
+
return Response.json({});
|
|
860
870
|
}
|
|
861
871
|
const messagePayload = event.chat?.messagePayload;
|
|
862
872
|
if (messagePayload) {
|
|
@@ -866,15 +876,13 @@ var GoogleChatAdapter = class {
|
|
|
866
876
|
text: messagePayload.message.text?.slice(0, 50)
|
|
867
877
|
});
|
|
868
878
|
this.handleMessageEvent(event, options);
|
|
869
|
-
} else if (!addedPayload
|
|
879
|
+
} else if (!(addedPayload || removedPayload)) {
|
|
870
880
|
this.logger.debug("Non-message event received", {
|
|
871
881
|
hasChat: !!event.chat,
|
|
872
882
|
hasCommonEventObject: !!event.commonEventObject
|
|
873
883
|
});
|
|
874
884
|
}
|
|
875
|
-
return
|
|
876
|
-
headers: { "Content-Type": "application/json" }
|
|
877
|
-
});
|
|
885
|
+
return Response.json({});
|
|
878
886
|
}
|
|
879
887
|
/**
|
|
880
888
|
* Handle Pub/Sub push messages from Workspace Events subscriptions.
|
|
@@ -889,9 +897,7 @@ var GoogleChatAdapter = class {
|
|
|
889
897
|
];
|
|
890
898
|
if (eventType && !allowedEventTypes.includes(eventType)) {
|
|
891
899
|
this.logger.debug("Skipping unsupported Pub/Sub event", { eventType });
|
|
892
|
-
return
|
|
893
|
-
headers: { "Content-Type": "application/json" }
|
|
894
|
-
});
|
|
900
|
+
return Response.json({ success: true });
|
|
895
901
|
}
|
|
896
902
|
try {
|
|
897
903
|
const notification = decodePubSubMessage(pushMessage);
|
|
@@ -906,9 +912,7 @@ var GoogleChatAdapter = class {
|
|
|
906
912
|
if (notification.reaction) {
|
|
907
913
|
this.handlePubSubReactionEvent(notification, options);
|
|
908
914
|
}
|
|
909
|
-
return
|
|
910
|
-
headers: { "Content-Type": "application/json" }
|
|
911
|
-
});
|
|
915
|
+
return Response.json({ success: true });
|
|
912
916
|
} catch (error) {
|
|
913
917
|
this.logger.error("Error processing Pub/Sub message", { error });
|
|
914
918
|
return new Response(JSON.stringify({ error: "Processing failed" }), {
|
|
@@ -921,7 +925,7 @@ var GoogleChatAdapter = class {
|
|
|
921
925
|
* Handle message events received via Pub/Sub (Workspace Events).
|
|
922
926
|
*/
|
|
923
927
|
handlePubSubMessageEvent(notification, options) {
|
|
924
|
-
if (!this.chat
|
|
928
|
+
if (!(this.chat && notification.message)) {
|
|
925
929
|
return;
|
|
926
930
|
}
|
|
927
931
|
const message = notification.message;
|
|
@@ -957,16 +961,14 @@ var GoogleChatAdapter = class {
|
|
|
957
961
|
* Fetches the message to get thread context for proper reply threading.
|
|
958
962
|
*/
|
|
959
963
|
handlePubSubReactionEvent(notification, options) {
|
|
960
|
-
if (!this.chat
|
|
964
|
+
if (!(this.chat && notification.reaction)) {
|
|
961
965
|
return;
|
|
962
966
|
}
|
|
963
967
|
const reaction = notification.reaction;
|
|
964
968
|
const rawEmoji = reaction.emoji?.unicode || "";
|
|
965
969
|
const normalizedEmoji = defaultEmojiResolver.fromGChat(rawEmoji);
|
|
966
970
|
const reactionName = reaction.name || "";
|
|
967
|
-
const messageNameMatch = reactionName.match(
|
|
968
|
-
/(spaces\/[^/]+\/messages\/[^/]+)/
|
|
969
|
-
);
|
|
971
|
+
const messageNameMatch = reactionName.match(REACTION_MESSAGE_NAME_PATTERN);
|
|
970
972
|
const messageName = messageNameMatch ? messageNameMatch[1] : "";
|
|
971
973
|
const spaceName = notification.targetResource?.replace(
|
|
972
974
|
"//chat.googleapis.com/",
|
|
@@ -1599,7 +1601,7 @@ var GoogleChatAdapter = class {
|
|
|
1599
1601
|
try {
|
|
1600
1602
|
const filter = threadName ? `thread.name = "${threadName}"` : void 0;
|
|
1601
1603
|
if (direction === "forward") {
|
|
1602
|
-
return this.fetchMessagesForward(
|
|
1604
|
+
return await this.fetchMessagesForward(
|
|
1603
1605
|
api,
|
|
1604
1606
|
spaceName,
|
|
1605
1607
|
threadId,
|
|
@@ -1608,7 +1610,7 @@ var GoogleChatAdapter = class {
|
|
|
1608
1610
|
options.cursor
|
|
1609
1611
|
);
|
|
1610
1612
|
}
|
|
1611
|
-
return this.fetchMessagesBackward(
|
|
1613
|
+
return await this.fetchMessagesBackward(
|
|
1612
1614
|
api,
|
|
1613
1615
|
spaceName,
|
|
1614
1616
|
threadId,
|
|
@@ -1715,7 +1717,7 @@ var GoogleChatAdapter = class {
|
|
|
1715
1717
|
);
|
|
1716
1718
|
let nextCursor;
|
|
1717
1719
|
if (startIndex + limit < allRawMessages.length && selectedMessages.length > 0) {
|
|
1718
|
-
const lastMsg = selectedMessages
|
|
1720
|
+
const lastMsg = selectedMessages.at(-1);
|
|
1719
1721
|
if (lastMsg?.name) {
|
|
1720
1722
|
nextCursor = lastMsg.name;
|
|
1721
1723
|
}
|
|
@@ -1813,7 +1815,7 @@ var GoogleChatAdapter = class {
|
|
|
1813
1815
|
const limit = options.limit || 100;
|
|
1814
1816
|
try {
|
|
1815
1817
|
if (direction === "backward") {
|
|
1816
|
-
return this.fetchChannelMessagesBackward(
|
|
1818
|
+
return await this.fetchChannelMessagesBackward(
|
|
1817
1819
|
api,
|
|
1818
1820
|
spaceName,
|
|
1819
1821
|
channelId,
|
|
@@ -1821,7 +1823,7 @@ var GoogleChatAdapter = class {
|
|
|
1821
1823
|
options.cursor
|
|
1822
1824
|
);
|
|
1823
1825
|
}
|
|
1824
|
-
return this.fetchChannelMessagesForward(
|
|
1826
|
+
return await this.fetchChannelMessagesForward(
|
|
1825
1827
|
api,
|
|
1826
1828
|
spaceName,
|
|
1827
1829
|
channelId,
|
|
@@ -1842,13 +1844,17 @@ var GoogleChatAdapter = class {
|
|
|
1842
1844
|
* Messages without a thread field (e.g., in non-threaded spaces) are always top-level.
|
|
1843
1845
|
*/
|
|
1844
1846
|
isThreadRoot(msg) {
|
|
1845
|
-
if (!msg.thread?.name
|
|
1847
|
+
if (!(msg.thread?.name && msg.name)) {
|
|
1848
|
+
return true;
|
|
1849
|
+
}
|
|
1846
1850
|
const threadParts = msg.thread.name.split("/");
|
|
1847
|
-
const threadId = threadParts
|
|
1851
|
+
const threadId = threadParts.at(-1);
|
|
1848
1852
|
const msgParts = msg.name.split("/");
|
|
1849
|
-
const msgIdFull = msgParts
|
|
1853
|
+
const msgIdFull = msgParts.at(-1) || "";
|
|
1850
1854
|
const dotIndex = msgIdFull.indexOf(".");
|
|
1851
|
-
if (dotIndex === -1)
|
|
1855
|
+
if (dotIndex === -1) {
|
|
1856
|
+
return true;
|
|
1857
|
+
}
|
|
1852
1858
|
const msgThreadPart = msgIdFull.slice(0, dotIndex);
|
|
1853
1859
|
const msgIdPart = msgIdFull.slice(dotIndex + 1);
|
|
1854
1860
|
return msgThreadPart === msgIdPart && msgThreadPart === threadId;
|
|
@@ -1874,14 +1880,18 @@ var GoogleChatAdapter = class {
|
|
|
1874
1880
|
orderBy: "createTime desc"
|
|
1875
1881
|
});
|
|
1876
1882
|
const pageMessages = response.data.messages || [];
|
|
1877
|
-
if (pageMessages.length === 0)
|
|
1883
|
+
if (pageMessages.length === 0) {
|
|
1884
|
+
break;
|
|
1885
|
+
}
|
|
1878
1886
|
for (const msg of pageMessages) {
|
|
1879
1887
|
if (this.isThreadRoot(msg)) {
|
|
1880
1888
|
topLevel.push(msg);
|
|
1881
1889
|
}
|
|
1882
1890
|
}
|
|
1883
1891
|
apiNextPageToken = response.data.nextPageToken ?? void 0;
|
|
1884
|
-
if (!apiNextPageToken)
|
|
1892
|
+
if (!apiNextPageToken) {
|
|
1893
|
+
break;
|
|
1894
|
+
}
|
|
1885
1895
|
pageToken = apiNextPageToken;
|
|
1886
1896
|
}
|
|
1887
1897
|
const selected = topLevel.slice(0, limit).reverse();
|
|
@@ -1919,7 +1929,9 @@ var GoogleChatAdapter = class {
|
|
|
1919
1929
|
let startIndex = 0;
|
|
1920
1930
|
if (cursor) {
|
|
1921
1931
|
const cursorIndex = topLevel.findIndex((msg) => msg.name === cursor);
|
|
1922
|
-
if (cursorIndex >= 0)
|
|
1932
|
+
if (cursorIndex >= 0) {
|
|
1933
|
+
startIndex = cursorIndex + 1;
|
|
1934
|
+
}
|
|
1923
1935
|
}
|
|
1924
1936
|
const selectedMessages = topLevel.slice(startIndex, startIndex + limit);
|
|
1925
1937
|
const messages = await Promise.all(
|
|
@@ -1929,8 +1941,10 @@ var GoogleChatAdapter = class {
|
|
|
1929
1941
|
);
|
|
1930
1942
|
let nextCursor;
|
|
1931
1943
|
if (startIndex + limit < topLevel.length && selectedMessages.length > 0) {
|
|
1932
|
-
const lastMsg = selectedMessages
|
|
1933
|
-
if (lastMsg?.name)
|
|
1944
|
+
const lastMsg = selectedMessages.at(-1);
|
|
1945
|
+
if (lastMsg?.name) {
|
|
1946
|
+
nextCursor = lastMsg.name;
|
|
1947
|
+
}
|
|
1934
1948
|
}
|
|
1935
1949
|
return { messages, nextCursor };
|
|
1936
1950
|
}
|
|
@@ -1965,7 +1979,9 @@ var GoogleChatAdapter = class {
|
|
|
1965
1979
|
const threadMap = /* @__PURE__ */ new Map();
|
|
1966
1980
|
for (const msg of rawMessages) {
|
|
1967
1981
|
const threadName = msg.thread?.name;
|
|
1968
|
-
if (!threadName)
|
|
1982
|
+
if (!threadName) {
|
|
1983
|
+
continue;
|
|
1984
|
+
}
|
|
1969
1985
|
const existing = threadMap.get(threadName);
|
|
1970
1986
|
if (existing) {
|
|
1971
1987
|
existing.count++;
|
|
@@ -1976,7 +1992,9 @@ var GoogleChatAdapter = class {
|
|
|
1976
1992
|
const threads = [];
|
|
1977
1993
|
let count = 0;
|
|
1978
1994
|
for (const [threadName, { rootMsg, count: replyCount }] of threadMap) {
|
|
1979
|
-
if (count >= limit)
|
|
1995
|
+
if (count >= limit) {
|
|
1996
|
+
break;
|
|
1997
|
+
}
|
|
1980
1998
|
const threadId = this.encodeThreadId({
|
|
1981
1999
|
spaceName,
|
|
1982
2000
|
threadName
|