@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/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") return;
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) return null;
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 || !this.state) {
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) return;
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 new Response(JSON.stringify({}), {
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 && !removedPayload) {
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 new Response(JSON.stringify({}), {
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 new Response(JSON.stringify({ success: true }), {
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 new Response(JSON.stringify({ success: true }), {
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 || !notification.message) {
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 || !notification.reaction) {
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[selectedMessages.length - 1];
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 || !msg.name) return true;
1847
+ if (!(msg.thread?.name && msg.name)) {
1848
+ return true;
1849
+ }
1846
1850
  const threadParts = msg.thread.name.split("/");
1847
- const threadId = threadParts[threadParts.length - 1];
1851
+ const threadId = threadParts.at(-1);
1848
1852
  const msgParts = msg.name.split("/");
1849
- const msgIdFull = msgParts[msgParts.length - 1] || "";
1853
+ const msgIdFull = msgParts.at(-1) || "";
1850
1854
  const dotIndex = msgIdFull.indexOf(".");
1851
- if (dotIndex === -1) return true;
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) break;
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) break;
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) startIndex = cursorIndex + 1;
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[selectedMessages.length - 1];
1933
- if (lastMsg?.name) nextCursor = 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) continue;
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) break;
1995
+ if (count >= limit) {
1996
+ break;
1997
+ }
1980
1998
  const threadId = this.encodeThreadId({
1981
1999
  spaceName,
1982
2000
  threadName