@chat-adapter/gchat 4.2.0 → 4.3.0
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 +174 -22
- package/dist/index.d.ts +16 -31
- package/dist/index.js +294 -278
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -40,37 +40,155 @@ chat.onNewMention(async (thread, message) => {
|
|
|
40
40
|
|
|
41
41
|
*Either `credentials` or `useADC: true` is required.
|
|
42
42
|
|
|
43
|
-
##
|
|
43
|
+
## Environment Variables
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
```bash
|
|
46
|
+
GOOGLE_CHAT_CREDENTIALS={"type":"service_account",...}
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
# Optional: for receiving ALL messages, not just @mentions
|
|
49
|
+
GOOGLE_CHAT_PUBSUB_TOPIC=projects/your-project/topics/chat-events
|
|
50
|
+
GOOGLE_CHAT_IMPERSONATE_USER=admin@yourdomain.com
|
|
51
|
+
```
|
|
50
52
|
|
|
51
|
-
|
|
53
|
+
## Google Chat Setup
|
|
52
54
|
|
|
53
|
-
1.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
### 1. Create a GCP Project
|
|
56
|
+
|
|
57
|
+
1. Go to [console.cloud.google.com](https://console.cloud.google.com)
|
|
58
|
+
2. Click the project dropdown → **New Project**
|
|
59
|
+
3. Enter project name and click **Create**
|
|
60
|
+
|
|
61
|
+
### 2. Enable Required APIs
|
|
57
62
|
|
|
58
|
-
|
|
63
|
+
1. Go to **APIs & Services** → **Library**
|
|
64
|
+
2. Search and enable:
|
|
65
|
+
- **Google Chat API**
|
|
66
|
+
- **Google Workspace Events API** (for receiving all messages)
|
|
67
|
+
- **Cloud Pub/Sub API** (for receiving all messages)
|
|
59
68
|
|
|
60
|
-
|
|
61
|
-
2. Configure your app:
|
|
62
|
-
- App name and avatar
|
|
63
|
-
- HTTP endpoint URL for webhooks
|
|
64
|
-
- Enable interactive features
|
|
69
|
+
### 3. Create a Service Account
|
|
65
70
|
|
|
66
|
-
|
|
71
|
+
1. Go to **IAM & Admin** → **Service Accounts**
|
|
72
|
+
2. Click **Create Service Account**
|
|
73
|
+
3. Enter name and description
|
|
74
|
+
4. Click **Create and Continue**
|
|
75
|
+
5. Skip the optional steps, click **Done**
|
|
67
76
|
|
|
68
|
-
|
|
77
|
+
### 4. Create Service Account Key
|
|
69
78
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
79
|
+
> **Note**: If your organization has the `iam.disableServiceAccountKeyCreation` constraint enabled, you'll need to:
|
|
80
|
+
> 1. Go to **IAM & Admin** → **Organization Policies**
|
|
81
|
+
> 2. Find `iam.disableServiceAccountKeyCreation`
|
|
82
|
+
> 3. Click **Manage Policy** → **Override parent's policy**
|
|
83
|
+
> 4. Set to **Not enforced** (or add an exception for your project)
|
|
84
|
+
|
|
85
|
+
1. Click on your service account
|
|
86
|
+
2. Go to **Keys** tab
|
|
87
|
+
3. Click **Add Key** → **Create new key**
|
|
88
|
+
4. Select **JSON** and click **Create**
|
|
89
|
+
5. Save the downloaded file
|
|
90
|
+
6. Copy the entire JSON content → `GOOGLE_CHAT_CREDENTIALS` (as a single line)
|
|
91
|
+
|
|
92
|
+
### 5. Configure Google Chat App
|
|
93
|
+
|
|
94
|
+
1. Go to [console.cloud.google.com/apis/api/chat.googleapis.com/hangouts-chat](https://console.cloud.google.com/apis/api/chat.googleapis.com/hangouts-chat)
|
|
95
|
+
2. Click **Configuration**
|
|
96
|
+
3. Fill in:
|
|
97
|
+
- **App name**: Your bot's display name
|
|
98
|
+
- **Avatar URL**: URL to your bot's avatar image
|
|
99
|
+
- **Description**: What your bot does
|
|
100
|
+
- **Interactive features**:
|
|
101
|
+
- Enable **Receive 1:1 messages**
|
|
102
|
+
- Enable **Join spaces and group conversations**
|
|
103
|
+
- **Connection settings**: Select **App URL**
|
|
104
|
+
- **App URL**: `https://your-domain.com/api/webhooks/gchat`
|
|
105
|
+
- **Visibility**: Choose who can discover and install your app
|
|
106
|
+
4. Click **Save**
|
|
107
|
+
|
|
108
|
+
**Important for button clicks**: The same App URL receives both message events and interactive events (card button clicks). Google Chat sends CARD_CLICKED events to this URL when users click buttons in cards.
|
|
109
|
+
|
|
110
|
+
### 6. Add Bot to a Space
|
|
111
|
+
|
|
112
|
+
1. Open Google Chat
|
|
113
|
+
2. Create or open a Space
|
|
114
|
+
3. Click the space name → **Manage apps & integrations** (or **Apps & integrations**)
|
|
115
|
+
4. Click **Add apps**
|
|
116
|
+
5. Search for your app name
|
|
117
|
+
6. Click **Add**
|
|
118
|
+
|
|
119
|
+
## (Optional) Pub/Sub for All Messages
|
|
120
|
+
|
|
121
|
+
By default, Google Chat only sends webhooks for @mentions. To receive ALL messages in a space (for conversation context), you need to set up Workspace Events with Pub/Sub.
|
|
122
|
+
|
|
123
|
+
### 1. Create Pub/Sub Topic
|
|
124
|
+
|
|
125
|
+
1. Go to **Pub/Sub** → **Topics**
|
|
126
|
+
2. Click **Create Topic**
|
|
127
|
+
3. Enter topic ID (e.g., `chat-events`)
|
|
128
|
+
4. Uncheck **Add a default subscription**
|
|
129
|
+
5. Click **Create**
|
|
130
|
+
6. Copy the full topic name → `GOOGLE_CHAT_PUBSUB_TOPIC`
|
|
131
|
+
- Format: `projects/your-project-id/topics/chat-events`
|
|
132
|
+
|
|
133
|
+
### 2. Grant Chat Service Account Access
|
|
134
|
+
|
|
135
|
+
> **Note**: If your organization has the `iam.allowedPolicyMemberDomains` constraint, you may need to temporarily relax it or use the console workaround below.
|
|
136
|
+
|
|
137
|
+
1. Go to your Pub/Sub topic
|
|
138
|
+
2. Click **Permissions** tab (or **Show Info Panel** → **Permissions**)
|
|
139
|
+
3. Click **Add Principal**
|
|
140
|
+
4. Enter: `chat-api-push@system.gserviceaccount.com`
|
|
141
|
+
5. Select role: **Pub/Sub Publisher**
|
|
142
|
+
6. Click **Save**
|
|
143
|
+
|
|
144
|
+
**If you get a policy error**, try via Cloud Console:
|
|
145
|
+
1. Go to **Pub/Sub** → **Topics**
|
|
146
|
+
2. Check the box next to your topic
|
|
147
|
+
3. Click **Permissions** in the info panel
|
|
148
|
+
4. Click **Add Principal**
|
|
149
|
+
5. Add `chat-api-push@system.gserviceaccount.com` with **Pub/Sub Publisher** role
|
|
150
|
+
|
|
151
|
+
### 3. Create Push Subscription
|
|
152
|
+
|
|
153
|
+
1. Go to **Pub/Sub** → **Subscriptions**
|
|
154
|
+
2. Click **Create Subscription**
|
|
155
|
+
3. Enter subscription ID (e.g., `chat-messages-push`)
|
|
156
|
+
4. Select your topic
|
|
157
|
+
5. **Delivery type**: Push
|
|
158
|
+
6. **Endpoint URL**: `https://your-domain.com/api/webhooks/gchat`
|
|
159
|
+
7. Click **Create**
|
|
160
|
+
|
|
161
|
+
### 4. Enable Domain-Wide Delegation
|
|
162
|
+
|
|
163
|
+
To create Workspace Events subscriptions and initiate DMs, you need domain-wide delegation:
|
|
164
|
+
|
|
165
|
+
**Step 1: Enable delegation on the Service Account (GCP Console)**
|
|
166
|
+
|
|
167
|
+
1. Go to [IAM & Admin → Service Accounts](https://console.cloud.google.com/iam-admin/serviceaccounts)
|
|
168
|
+
2. Click on your service account
|
|
169
|
+
3. Go to **Details** tab
|
|
170
|
+
4. Check **Enable Google Workspace Domain-wide Delegation**
|
|
171
|
+
5. Click **Save**
|
|
172
|
+
6. Go to **Advanced settings** (or click on the service account again)
|
|
173
|
+
7. Copy the **Client ID** - this is a **numeric ID** (e.g., `123456789012345678901`), NOT the email address
|
|
174
|
+
|
|
175
|
+
**Step 2: Authorize the Client ID (Google Admin Console)**
|
|
176
|
+
|
|
177
|
+
1. Go to [Google Admin Console](https://admin.google.com)
|
|
178
|
+
2. Go to **Security** → **Access and data control** → **API controls**
|
|
179
|
+
3. Click **Manage Domain Wide Delegation**
|
|
180
|
+
4. Click **Add new**
|
|
181
|
+
5. Enter:
|
|
182
|
+
- **Client ID**: The numeric ID from Step 1 (e.g., `123456789012345678901`)
|
|
183
|
+
- **OAuth Scopes** (all on one line, comma-separated):
|
|
184
|
+
```
|
|
185
|
+
https://www.googleapis.com/auth/chat.spaces.readonly,https://www.googleapis.com/auth/chat.messages.readonly,https://www.googleapis.com/auth/chat.spaces,https://www.googleapis.com/auth/chat.spaces.create
|
|
186
|
+
```
|
|
187
|
+
6. Click **Authorize**
|
|
188
|
+
|
|
189
|
+
**Step 3: Set environment variable**
|
|
190
|
+
|
|
191
|
+
Set `GOOGLE_CHAT_IMPERSONATE_USER` to an admin user email in your domain (e.g., `admin@yourdomain.com`). This user will be impersonated when creating DM spaces and Workspace Events subscriptions.
|
|
74
192
|
|
|
75
193
|
## Features
|
|
76
194
|
|
|
@@ -88,6 +206,40 @@ For reaction events, you need Workspace Events via Pub/Sub:
|
|
|
88
206
|
- **Typing indicators**: Not supported by Google Chat API
|
|
89
207
|
- **Adding reactions**: Requires domain-wide delegation (appears from impersonated user, not bot)
|
|
90
208
|
|
|
209
|
+
## Troubleshooting
|
|
210
|
+
|
|
211
|
+
### No webhook received
|
|
212
|
+
- Verify the App URL is correct in Google Chat configuration
|
|
213
|
+
- Check that the Chat API is enabled
|
|
214
|
+
- Ensure the service account has the necessary permissions
|
|
215
|
+
|
|
216
|
+
### Pub/Sub not working
|
|
217
|
+
- Verify `chat-api-push@system.gserviceaccount.com` has Pub/Sub Publisher role
|
|
218
|
+
- Check that the push subscription URL is correct
|
|
219
|
+
- Verify domain-wide delegation is configured with correct scopes
|
|
220
|
+
- Check `GOOGLE_CHAT_IMPERSONATE_USER` is a valid admin email
|
|
221
|
+
|
|
222
|
+
### "Permission denied" for Workspace Events
|
|
223
|
+
- Ensure domain-wide delegation is configured
|
|
224
|
+
- Verify the OAuth scopes are exactly as specified
|
|
225
|
+
- Check that the impersonated user has access to the spaces
|
|
226
|
+
|
|
227
|
+
### "Insufficient Permission" for DMs (openDM)
|
|
228
|
+
- DMs require domain-wide delegation with `chat.spaces` and `chat.spaces.create` scopes
|
|
229
|
+
- Add these scopes to your domain-wide delegation configuration in Google Admin Console
|
|
230
|
+
- Set `GOOGLE_CHAT_IMPERSONATE_USER` to an admin email in your domain
|
|
231
|
+
- Scope changes can take up to 24 hours to propagate
|
|
232
|
+
|
|
233
|
+
### "unauthorized_client" error
|
|
234
|
+
- The Client ID is not registered in Google Admin Console
|
|
235
|
+
- Or domain-wide delegation is not enabled on the service account
|
|
236
|
+
|
|
237
|
+
### Button clicks (CARD_CLICKED) not received
|
|
238
|
+
- Verify "Interactive features" is enabled in the Google Chat app configuration
|
|
239
|
+
- Check that the App URL is correctly set and accessible
|
|
240
|
+
- Button clicks go to the same webhook URL as messages
|
|
241
|
+
- Ensure your button elements have valid `id` attributes (these become the `actionId`)
|
|
242
|
+
|
|
91
243
|
## License
|
|
92
244
|
|
|
93
245
|
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
|
-
import { CardElement, BaseFormatConverter, Root, Adapter, ChatInstance, WebhookOptions, AdapterPostableMessage, RawMessage, EmojiValue, FetchOptions, FetchResult, ThreadInfo, Message, FormattedContent } from 'chat';
|
|
1
|
+
import { CardElement, BaseFormatConverter, Root, Logger, Adapter, ChatInstance, WebhookOptions, AdapterPostableMessage, RawMessage, EmojiValue, FetchOptions, FetchResult, ThreadInfo, Message, FormattedContent } from 'chat';
|
|
2
2
|
import { google } from 'googleapis';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Thread ID encoding/decoding utilities for Google Chat adapter.
|
|
6
|
+
*/
|
|
7
|
+
/** Google Chat-specific thread ID data */
|
|
8
|
+
interface GoogleChatThreadId {
|
|
9
|
+
spaceName: string;
|
|
10
|
+
threadName?: string;
|
|
11
|
+
/** Whether this is a DM space */
|
|
12
|
+
isDM?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
4
15
|
/**
|
|
5
16
|
* Google Chat Card converter for cross-platform cards.
|
|
6
17
|
*
|
|
@@ -273,6 +284,8 @@ interface ServiceAccountCredentials {
|
|
|
273
284
|
}
|
|
274
285
|
/** Base config options shared by all auth methods */
|
|
275
286
|
interface GoogleChatAdapterBaseConfig {
|
|
287
|
+
/** Logger instance for error reporting */
|
|
288
|
+
logger: Logger;
|
|
276
289
|
/** Override bot username (optional) */
|
|
277
290
|
userName?: string;
|
|
278
291
|
/**
|
|
@@ -323,13 +336,7 @@ interface GoogleChatAdapterCustomAuthConfig extends GoogleChatAdapterBaseConfig
|
|
|
323
336
|
useApplicationDefaultCredentials?: never;
|
|
324
337
|
}
|
|
325
338
|
type GoogleChatAdapterConfig = GoogleChatAdapterServiceAccountConfig | GoogleChatAdapterADCConfig | GoogleChatAdapterCustomAuthConfig;
|
|
326
|
-
|
|
327
|
-
interface GoogleChatThreadId {
|
|
328
|
-
spaceName: string;
|
|
329
|
-
threadName?: string;
|
|
330
|
-
/** Whether this is a DM space */
|
|
331
|
-
isDM?: boolean;
|
|
332
|
-
}
|
|
339
|
+
|
|
333
340
|
/** Google Chat message structure */
|
|
334
341
|
interface GoogleChatMessage {
|
|
335
342
|
name: string;
|
|
@@ -451,7 +458,7 @@ declare class GoogleChatAdapter implements Adapter<GoogleChatThreadId, unknown>
|
|
|
451
458
|
private impersonatedChatApi?;
|
|
452
459
|
/** HTTP endpoint URL for button click actions */
|
|
453
460
|
private endpointUrl?;
|
|
454
|
-
/**
|
|
461
|
+
/** User info cache for display name lookups - initialized later in initialize() */
|
|
455
462
|
private userInfoCache;
|
|
456
463
|
constructor(config: GoogleChatAdapterConfig);
|
|
457
464
|
initialize(chat: ChatInstance): Promise<void>;
|
|
@@ -513,14 +520,6 @@ declare class GoogleChatAdapter implements Adapter<GoogleChatThreadId, unknown>
|
|
|
513
520
|
private handleMessageEvent;
|
|
514
521
|
private parseGoogleChatMessage;
|
|
515
522
|
postMessage(threadId: string, message: AdapterPostableMessage): Promise<RawMessage<unknown>>;
|
|
516
|
-
/**
|
|
517
|
-
* Extract card element from a message if present.
|
|
518
|
-
*/
|
|
519
|
-
private extractCard;
|
|
520
|
-
/**
|
|
521
|
-
* Extract files from a message if present.
|
|
522
|
-
*/
|
|
523
|
-
private extractFiles;
|
|
524
523
|
/**
|
|
525
524
|
* Create an Attachment object from a Google Chat attachment.
|
|
526
525
|
*/
|
|
@@ -568,8 +567,6 @@ declare class GoogleChatAdapter implements Adapter<GoogleChatThreadId, unknown>
|
|
|
568
567
|
encodeThreadId(platformData: GoogleChatThreadId): string;
|
|
569
568
|
/**
|
|
570
569
|
* Check if a thread is a direct message conversation.
|
|
571
|
-
* Checks for the :dm marker in the thread ID which is set when
|
|
572
|
-
* processing DM messages or opening DMs.
|
|
573
570
|
*/
|
|
574
571
|
isDM(threadId: string): boolean;
|
|
575
572
|
decodeThreadId(threadId: string): GoogleChatThreadId;
|
|
@@ -594,18 +591,6 @@ declare class GoogleChatAdapter implements Adapter<GoogleChatThreadId, unknown>
|
|
|
594
591
|
* multi-bot spaces (especially via Pub/Sub).
|
|
595
592
|
*/
|
|
596
593
|
private isMessageFromSelf;
|
|
597
|
-
/**
|
|
598
|
-
* Cache user info for later lookup (e.g., when processing Pub/Sub messages).
|
|
599
|
-
*/
|
|
600
|
-
private cacheUserInfo;
|
|
601
|
-
/**
|
|
602
|
-
* Get cached user info. Checks in-memory cache first, then falls back to state adapter.
|
|
603
|
-
*/
|
|
604
|
-
private getCachedUserInfo;
|
|
605
|
-
/**
|
|
606
|
-
* Resolve user display name, using cache if available.
|
|
607
|
-
*/
|
|
608
|
-
private resolveUserDisplayName;
|
|
609
594
|
private handleGoogleChatError;
|
|
610
595
|
}
|
|
611
596
|
declare function createGoogleChatAdapter(config: GoogleChatAdapterConfig): GoogleChatAdapter;
|