@jimiford/channel-webex 1.0.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/LICENSE +21 -0
- package/README.md +314 -0
- package/dist/channel.d.ts +98 -0
- package/dist/channel.js +224 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +47 -0
- package/dist/send.d.ts +92 -0
- package/dist/send.js +304 -0
- package/dist/types.d.ts +223 -0
- package/dist/types.js +6 -0
- package/dist/webhook.d.ts +64 -0
- package/dist/webhook.js +297 -0
- package/openclaw.plugin.json +73 -0
- package/package.json +66 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Webex Channel Plugin Types
|
|
3
|
+
*/
|
|
4
|
+
export type DmPolicy = 'allow' | 'deny' | 'allowlisted';
|
|
5
|
+
export interface WebexChannelConfig {
|
|
6
|
+
/** Webex Bot access token */
|
|
7
|
+
token: string;
|
|
8
|
+
/** Public URL where webhooks will be received */
|
|
9
|
+
webhookUrl: string;
|
|
10
|
+
/** Policy for handling direct messages */
|
|
11
|
+
dmPolicy: DmPolicy;
|
|
12
|
+
/** List of allowed person IDs or emails (used when dmPolicy is 'allowlisted') */
|
|
13
|
+
allowFrom?: string[];
|
|
14
|
+
/** Webhook secret for payload verification */
|
|
15
|
+
webhookSecret?: string;
|
|
16
|
+
/** Base URL for Webex API (defaults to https://webexapis.com/v1) */
|
|
17
|
+
apiBaseUrl?: string;
|
|
18
|
+
/** Maximum retry attempts for failed requests */
|
|
19
|
+
maxRetries?: number;
|
|
20
|
+
/** Retry delay in milliseconds */
|
|
21
|
+
retryDelayMs?: number;
|
|
22
|
+
}
|
|
23
|
+
export interface WebexPerson {
|
|
24
|
+
id: string;
|
|
25
|
+
emails: string[];
|
|
26
|
+
displayName: string;
|
|
27
|
+
nickName?: string;
|
|
28
|
+
firstName?: string;
|
|
29
|
+
lastName?: string;
|
|
30
|
+
avatar?: string;
|
|
31
|
+
orgId: string;
|
|
32
|
+
created: string;
|
|
33
|
+
lastModified?: string;
|
|
34
|
+
type: 'person' | 'bot';
|
|
35
|
+
}
|
|
36
|
+
export interface WebexRoom {
|
|
37
|
+
id: string;
|
|
38
|
+
title: string;
|
|
39
|
+
type: 'direct' | 'group';
|
|
40
|
+
isLocked: boolean;
|
|
41
|
+
teamId?: string;
|
|
42
|
+
lastActivity: string;
|
|
43
|
+
creatorId: string;
|
|
44
|
+
created: string;
|
|
45
|
+
ownerId?: string;
|
|
46
|
+
}
|
|
47
|
+
export interface WebexMessage {
|
|
48
|
+
id: string;
|
|
49
|
+
roomId: string;
|
|
50
|
+
roomType: 'direct' | 'group';
|
|
51
|
+
toPersonId?: string;
|
|
52
|
+
toPersonEmail?: string;
|
|
53
|
+
text?: string;
|
|
54
|
+
markdown?: string;
|
|
55
|
+
html?: string;
|
|
56
|
+
files?: string[];
|
|
57
|
+
personId: string;
|
|
58
|
+
personEmail: string;
|
|
59
|
+
mentionedPeople?: string[];
|
|
60
|
+
mentionedGroups?: string[];
|
|
61
|
+
attachments?: WebexAttachment[];
|
|
62
|
+
created: string;
|
|
63
|
+
updated?: string;
|
|
64
|
+
parentId?: string;
|
|
65
|
+
}
|
|
66
|
+
export interface WebexAttachment {
|
|
67
|
+
contentType: 'application/vnd.microsoft.card.adaptive';
|
|
68
|
+
content: AdaptiveCard;
|
|
69
|
+
}
|
|
70
|
+
export interface AdaptiveCard {
|
|
71
|
+
type: 'AdaptiveCard';
|
|
72
|
+
version: string;
|
|
73
|
+
body: unknown[];
|
|
74
|
+
actions?: unknown[];
|
|
75
|
+
}
|
|
76
|
+
export interface WebexWebhook {
|
|
77
|
+
id: string;
|
|
78
|
+
name: string;
|
|
79
|
+
targetUrl: string;
|
|
80
|
+
resource: WebexWebhookResource;
|
|
81
|
+
event: WebexWebhookEvent;
|
|
82
|
+
filter?: string;
|
|
83
|
+
secret?: string;
|
|
84
|
+
status: 'active' | 'inactive';
|
|
85
|
+
created: string;
|
|
86
|
+
orgId: string;
|
|
87
|
+
createdBy: string;
|
|
88
|
+
appId: string;
|
|
89
|
+
ownedBy: 'creator' | 'org';
|
|
90
|
+
}
|
|
91
|
+
export type WebexWebhookResource = 'messages' | 'memberships' | 'rooms' | 'attachmentActions' | 'meetings' | 'recordings';
|
|
92
|
+
export type WebexWebhookEvent = 'created' | 'updated' | 'deleted' | 'started' | 'ended';
|
|
93
|
+
export interface WebexWebhookPayload {
|
|
94
|
+
id: string;
|
|
95
|
+
name: string;
|
|
96
|
+
targetUrl: string;
|
|
97
|
+
resource: WebexWebhookResource;
|
|
98
|
+
event: WebexWebhookEvent;
|
|
99
|
+
filter?: string;
|
|
100
|
+
orgId: string;
|
|
101
|
+
createdBy: string;
|
|
102
|
+
appId: string;
|
|
103
|
+
ownedBy: string;
|
|
104
|
+
status: string;
|
|
105
|
+
created: string;
|
|
106
|
+
actorId: string;
|
|
107
|
+
data: WebexWebhookData;
|
|
108
|
+
}
|
|
109
|
+
export interface WebexWebhookData {
|
|
110
|
+
id: string;
|
|
111
|
+
roomId: string;
|
|
112
|
+
roomType: 'direct' | 'group';
|
|
113
|
+
personId: string;
|
|
114
|
+
personEmail: string;
|
|
115
|
+
created: string;
|
|
116
|
+
mentionedPeople?: string[];
|
|
117
|
+
mentionedGroups?: string[];
|
|
118
|
+
files?: string[];
|
|
119
|
+
}
|
|
120
|
+
export interface CreateMessageRequest {
|
|
121
|
+
roomId?: string;
|
|
122
|
+
toPersonId?: string;
|
|
123
|
+
toPersonEmail?: string;
|
|
124
|
+
text?: string;
|
|
125
|
+
markdown?: string;
|
|
126
|
+
files?: string[];
|
|
127
|
+
attachments?: WebexAttachment[];
|
|
128
|
+
parentId?: string;
|
|
129
|
+
}
|
|
130
|
+
export interface CreateWebhookRequest {
|
|
131
|
+
name: string;
|
|
132
|
+
targetUrl: string;
|
|
133
|
+
resource: WebexWebhookResource;
|
|
134
|
+
event: WebexWebhookEvent;
|
|
135
|
+
filter?: string;
|
|
136
|
+
secret?: string;
|
|
137
|
+
}
|
|
138
|
+
export interface WebexApiError {
|
|
139
|
+
message: string;
|
|
140
|
+
errors?: Array<{
|
|
141
|
+
description: string;
|
|
142
|
+
}>;
|
|
143
|
+
trackingId: string;
|
|
144
|
+
}
|
|
145
|
+
export interface PaginatedResponse<T> {
|
|
146
|
+
items: T[];
|
|
147
|
+
}
|
|
148
|
+
export interface OpenClawEnvelope {
|
|
149
|
+
/** Unique message identifier */
|
|
150
|
+
id: string;
|
|
151
|
+
/** Channel identifier */
|
|
152
|
+
channel: 'webex';
|
|
153
|
+
/** Conversation/thread identifier */
|
|
154
|
+
conversationId: string;
|
|
155
|
+
/** Message author information */
|
|
156
|
+
author: {
|
|
157
|
+
id: string;
|
|
158
|
+
email?: string;
|
|
159
|
+
displayName?: string;
|
|
160
|
+
isBot: boolean;
|
|
161
|
+
};
|
|
162
|
+
/** Message content */
|
|
163
|
+
content: {
|
|
164
|
+
text?: string;
|
|
165
|
+
markdown?: string;
|
|
166
|
+
attachments?: OpenClawAttachment[];
|
|
167
|
+
};
|
|
168
|
+
/** Message metadata */
|
|
169
|
+
metadata: {
|
|
170
|
+
roomType: 'direct' | 'group';
|
|
171
|
+
roomId: string;
|
|
172
|
+
timestamp: string;
|
|
173
|
+
mentions?: string[];
|
|
174
|
+
parentId?: string;
|
|
175
|
+
raw: WebexMessage;
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
export interface OpenClawAttachment {
|
|
179
|
+
type: 'file' | 'card';
|
|
180
|
+
url?: string;
|
|
181
|
+
content?: unknown;
|
|
182
|
+
}
|
|
183
|
+
export interface OpenClawOutboundMessage {
|
|
184
|
+
/** Target conversation ID (roomId) or person ID/email for DMs */
|
|
185
|
+
to: string;
|
|
186
|
+
/** Message content */
|
|
187
|
+
content: {
|
|
188
|
+
text?: string;
|
|
189
|
+
markdown?: string;
|
|
190
|
+
files?: string[];
|
|
191
|
+
card?: AdaptiveCard;
|
|
192
|
+
};
|
|
193
|
+
/** Optional parent message ID for threading */
|
|
194
|
+
parentId?: string;
|
|
195
|
+
}
|
|
196
|
+
export interface WebexChannelPlugin {
|
|
197
|
+
name: string;
|
|
198
|
+
version: string;
|
|
199
|
+
/** Initialize the channel with configuration */
|
|
200
|
+
initialize(config: WebexChannelConfig): Promise<void>;
|
|
201
|
+
/** Send a message */
|
|
202
|
+
send(message: OpenClawOutboundMessage): Promise<WebexMessage>;
|
|
203
|
+
/** Handle incoming webhook */
|
|
204
|
+
handleWebhook(payload: WebexWebhookPayload, signature?: string): Promise<OpenClawEnvelope | null>;
|
|
205
|
+
/** Register webhooks with Webex */
|
|
206
|
+
registerWebhooks(): Promise<WebexWebhook[]>;
|
|
207
|
+
/** Cleanup and shutdown */
|
|
208
|
+
shutdown(): Promise<void>;
|
|
209
|
+
}
|
|
210
|
+
export interface WebhookHandler {
|
|
211
|
+
(envelope: OpenClawEnvelope): Promise<void> | void;
|
|
212
|
+
}
|
|
213
|
+
export interface RetryOptions {
|
|
214
|
+
maxRetries: number;
|
|
215
|
+
retryDelayMs: number;
|
|
216
|
+
shouldRetry?: (error: Error, attempt: number) => boolean;
|
|
217
|
+
}
|
|
218
|
+
export interface RequestOptions {
|
|
219
|
+
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
220
|
+
path: string;
|
|
221
|
+
body?: unknown;
|
|
222
|
+
headers?: Record<string, string>;
|
|
223
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Webex Channel Plugin Types
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOztHQUVHIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBXZWJleCBDaGFubmVsIFBsdWdpbiBUeXBlc1xuICovXG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIENvbmZpZ3VyYXRpb24gVHlwZXNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IHR5cGUgRG1Qb2xpY3kgPSAnYWxsb3cnIHwgJ2RlbnknIHwgJ2FsbG93bGlzdGVkJztcblxuZXhwb3J0IGludGVyZmFjZSBXZWJleENoYW5uZWxDb25maWcge1xuICAvKiogV2ViZXggQm90IGFjY2VzcyB0b2tlbiAqL1xuICB0b2tlbjogc3RyaW5nO1xuXG4gIC8qKiBQdWJsaWMgVVJMIHdoZXJlIHdlYmhvb2tzIHdpbGwgYmUgcmVjZWl2ZWQgKi9cbiAgd2ViaG9va1VybDogc3RyaW5nO1xuXG4gIC8qKiBQb2xpY3kgZm9yIGhhbmRsaW5nIGRpcmVjdCBtZXNzYWdlcyAqL1xuICBkbVBvbGljeTogRG1Qb2xpY3k7XG5cbiAgLyoqIExpc3Qgb2YgYWxsb3dlZCBwZXJzb24gSURzIG9yIGVtYWlscyAodXNlZCB3aGVuIGRtUG9saWN5IGlzICdhbGxvd2xpc3RlZCcpICovXG4gIGFsbG93RnJvbT86IHN0cmluZ1tdO1xuXG4gIC8qKiBXZWJob29rIHNlY3JldCBmb3IgcGF5bG9hZCB2ZXJpZmljYXRpb24gKi9cbiAgd2ViaG9va1NlY3JldD86IHN0cmluZztcblxuICAvKiogQmFzZSBVUkwgZm9yIFdlYmV4IEFQSSAoZGVmYXVsdHMgdG8gaHR0cHM6Ly93ZWJleGFwaXMuY29tL3YxKSAqL1xuICBhcGlCYXNlVXJsPzogc3RyaW5nO1xuXG4gIC8qKiBNYXhpbXVtIHJldHJ5IGF0dGVtcHRzIGZvciBmYWlsZWQgcmVxdWVzdHMgKi9cbiAgbWF4UmV0cmllcz86IG51bWJlcjtcblxuICAvKiogUmV0cnkgZGVsYXkgaW4gbWlsbGlzZWNvbmRzICovXG4gIHJldHJ5RGVsYXlNcz86IG51bWJlcjtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gV2ViZXggQVBJIFR5cGVzXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCBpbnRlcmZhY2UgV2ViZXhQZXJzb24ge1xuICBpZDogc3RyaW5nO1xuICBlbWFpbHM6IHN0cmluZ1tdO1xuICBkaXNwbGF5TmFtZTogc3RyaW5nO1xuICBuaWNrTmFtZT86IHN0cmluZztcbiAgZmlyc3ROYW1lPzogc3RyaW5nO1xuICBsYXN0TmFtZT86IHN0cmluZztcbiAgYXZhdGFyPzogc3RyaW5nO1xuICBvcmdJZDogc3RyaW5nO1xuICBjcmVhdGVkOiBzdHJpbmc7XG4gIGxhc3RNb2RpZmllZD86IHN0cmluZztcbiAgdHlwZTogJ3BlcnNvbicgfCAnYm90Jztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBXZWJleFJvb20ge1xuICBpZDogc3RyaW5nO1xuICB0aXRsZTogc3RyaW5nO1xuICB0eXBlOiAnZGlyZWN0JyB8ICdncm91cCc7XG4gIGlzTG9ja2VkOiBib29sZWFuO1xuICB0ZWFtSWQ/OiBzdHJpbmc7XG4gIGxhc3RBY3Rpdml0eTogc3RyaW5nO1xuICBjcmVhdG9ySWQ6IHN0cmluZztcbiAgY3JlYXRlZDogc3RyaW5nO1xuICBvd25lcklkPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFdlYmV4TWVzc2FnZSB7XG4gIGlkOiBzdHJpbmc7XG4gIHJvb21JZDogc3RyaW5nO1xuICByb29tVHlwZTogJ2RpcmVjdCcgfCAnZ3JvdXAnO1xuICB0b1BlcnNvbklkPzogc3RyaW5nO1xuICB0b1BlcnNvbkVtYWlsPzogc3RyaW5nO1xuICB0ZXh0Pzogc3RyaW5nO1xuICBtYXJrZG93bj86IHN0cmluZztcbiAgaHRtbD86IHN0cmluZztcbiAgZmlsZXM/OiBzdHJpbmdbXTtcbiAgcGVyc29uSWQ6IHN0cmluZztcbiAgcGVyc29uRW1haWw6IHN0cmluZztcbiAgbWVudGlvbmVkUGVvcGxlPzogc3RyaW5nW107XG4gIG1lbnRpb25lZEdyb3Vwcz86IHN0cmluZ1tdO1xuICBhdHRhY2htZW50cz86IFdlYmV4QXR0YWNobWVudFtdO1xuICBjcmVhdGVkOiBzdHJpbmc7XG4gIHVwZGF0ZWQ/OiBzdHJpbmc7XG4gIHBhcmVudElkPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFdlYmV4QXR0YWNobWVudCB7XG4gIGNvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vdm5kLm1pY3Jvc29mdC5jYXJkLmFkYXB0aXZlJztcbiAgY29udGVudDogQWRhcHRpdmVDYXJkO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEFkYXB0aXZlQ2FyZCB7XG4gIHR5cGU6ICdBZGFwdGl2ZUNhcmQnO1xuICB2ZXJzaW9uOiBzdHJpbmc7XG4gIGJvZHk6IHVua25vd25bXTtcbiAgYWN0aW9ucz86IHVua25vd25bXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBXZWJleFdlYmhvb2sge1xuICBpZDogc3RyaW5nO1xuICBuYW1lOiBzdHJpbmc7XG4gIHRhcmdldFVybDogc3RyaW5nO1xuICByZXNvdXJjZTogV2ViZXhXZWJob29rUmVzb3VyY2U7XG4gIGV2ZW50OiBXZWJleFdlYmhvb2tFdmVudDtcbiAgZmlsdGVyPzogc3RyaW5nO1xuICBzZWNyZXQ/OiBzdHJpbmc7XG4gIHN0YXR1czogJ2FjdGl2ZScgfCAnaW5hY3RpdmUnO1xuICBjcmVhdGVkOiBzdHJpbmc7XG4gIG9yZ0lkOiBzdHJpbmc7XG4gIGNyZWF0ZWRCeTogc3RyaW5nO1xuICBhcHBJZDogc3RyaW5nO1xuICBvd25lZEJ5OiAnY3JlYXRvcicgfCAnb3JnJztcbn1cblxuZXhwb3J0IHR5cGUgV2ViZXhXZWJob29rUmVzb3VyY2UgPVxuICB8ICdtZXNzYWdlcydcbiAgfCAnbWVtYmVyc2hpcHMnXG4gIHwgJ3Jvb21zJ1xuICB8ICdhdHRhY2htZW50QWN0aW9ucydcbiAgfCAnbWVldGluZ3MnXG4gIHwgJ3JlY29yZGluZ3MnO1xuXG5leHBvcnQgdHlwZSBXZWJleFdlYmhvb2tFdmVudCA9XG4gIHwgJ2NyZWF0ZWQnXG4gIHwgJ3VwZGF0ZWQnXG4gIHwgJ2RlbGV0ZWQnXG4gIHwgJ3N0YXJ0ZWQnXG4gIHwgJ2VuZGVkJztcblxuZXhwb3J0IGludGVyZmFjZSBXZWJleFdlYmhvb2tQYXlsb2FkIHtcbiAgaWQ6IHN0cmluZztcbiAgbmFtZTogc3RyaW5nO1xuICB0YXJnZXRVcmw6IHN0cmluZztcbiAgcmVzb3VyY2U6IFdlYmV4V2ViaG9va1Jlc291cmNlO1xuICBldmVudDogV2ViZXhXZWJob29rRXZlbnQ7XG4gIGZpbHRlcj86IHN0cmluZztcbiAgb3JnSWQ6IHN0cmluZztcbiAgY3JlYXRlZEJ5OiBzdHJpbmc7XG4gIGFwcElkOiBzdHJpbmc7XG4gIG93bmVkQnk6IHN0cmluZztcbiAgc3RhdHVzOiBzdHJpbmc7XG4gIGNyZWF0ZWQ6IHN0cmluZztcbiAgYWN0b3JJZDogc3RyaW5nO1xuICBkYXRhOiBXZWJleFdlYmhvb2tEYXRhO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFdlYmV4V2ViaG9va0RhdGEge1xuICBpZDogc3RyaW5nO1xuICByb29tSWQ6IHN0cmluZztcbiAgcm9vbVR5cGU6ICdkaXJlY3QnIHwgJ2dyb3VwJztcbiAgcGVyc29uSWQ6IHN0cmluZztcbiAgcGVyc29uRW1haWw6IHN0cmluZztcbiAgY3JlYXRlZDogc3RyaW5nO1xuICBtZW50aW9uZWRQZW9wbGU/OiBzdHJpbmdbXTtcbiAgbWVudGlvbmVkR3JvdXBzPzogc3RyaW5nW107XG4gIGZpbGVzPzogc3RyaW5nW107XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEFQSSBSZXF1ZXN0L1Jlc3BvbnNlIFR5cGVzXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ3JlYXRlTWVzc2FnZVJlcXVlc3Qge1xuICByb29tSWQ/OiBzdHJpbmc7XG4gIHRvUGVyc29uSWQ/OiBzdHJpbmc7XG4gIHRvUGVyc29uRW1haWw/OiBzdHJpbmc7XG4gIHRleHQ/OiBzdHJpbmc7XG4gIG1hcmtkb3duPzogc3RyaW5nO1xuICBmaWxlcz86IHN0cmluZ1tdO1xuICBhdHRhY2htZW50cz86IFdlYmV4QXR0YWNobWVudFtdO1xuICBwYXJlbnRJZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDcmVhdGVXZWJob29rUmVxdWVzdCB7XG4gIG5hbWU6IHN0cmluZztcbiAgdGFyZ2V0VXJsOiBzdHJpbmc7XG4gIHJlc291cmNlOiBXZWJleFdlYmhvb2tSZXNvdXJjZTtcbiAgZXZlbnQ6IFdlYmV4V2ViaG9va0V2ZW50O1xuICBmaWx0ZXI/OiBzdHJpbmc7XG4gIHNlY3JldD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBXZWJleEFwaUVycm9yIHtcbiAgbWVzc2FnZTogc3RyaW5nO1xuICBlcnJvcnM/OiBBcnJheTx7XG4gICAgZGVzY3JpcHRpb246IHN0cmluZztcbiAgfT47XG4gIHRyYWNraW5nSWQ6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQYWdpbmF0ZWRSZXNwb25zZTxUPiB7XG4gIGl0ZW1zOiBUW107XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIE9wZW5DbGF3IEVudmVsb3BlIFR5cGVzXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCBpbnRlcmZhY2UgT3BlbkNsYXdFbnZlbG9wZSB7XG4gIC8qKiBVbmlxdWUgbWVzc2FnZSBpZGVudGlmaWVyICovXG4gIGlkOiBzdHJpbmc7XG5cbiAgLyoqIENoYW5uZWwgaWRlbnRpZmllciAqL1xuICBjaGFubmVsOiAnd2ViZXgnO1xuXG4gIC8qKiBDb252ZXJzYXRpb24vdGhyZWFkIGlkZW50aWZpZXIgKi9cbiAgY29udmVyc2F0aW9uSWQ6IHN0cmluZztcblxuICAvKiogTWVzc2FnZSBhdXRob3IgaW5mb3JtYXRpb24gKi9cbiAgYXV0aG9yOiB7XG4gICAgaWQ6IHN0cmluZztcbiAgICBlbWFpbD86IHN0cmluZztcbiAgICBkaXNwbGF5TmFtZT86IHN0cmluZztcbiAgICBpc0JvdDogYm9vbGVhbjtcbiAgfTtcblxuICAvKiogTWVzc2FnZSBjb250ZW50ICovXG4gIGNvbnRlbnQ6IHtcbiAgICB0ZXh0Pzogc3RyaW5nO1xuICAgIG1hcmtkb3duPzogc3RyaW5nO1xuICAgIGF0dGFjaG1lbnRzPzogT3BlbkNsYXdBdHRhY2htZW50W107XG4gIH07XG5cbiAgLyoqIE1lc3NhZ2UgbWV0YWRhdGEgKi9cbiAgbWV0YWRhdGE6IHtcbiAgICByb29tVHlwZTogJ2RpcmVjdCcgfCAnZ3JvdXAnO1xuICAgIHJvb21JZDogc3RyaW5nO1xuICAgIHRpbWVzdGFtcDogc3RyaW5nO1xuICAgIG1lbnRpb25zPzogc3RyaW5nW107XG4gICAgcGFyZW50SWQ/OiBzdHJpbmc7XG4gICAgcmF3OiBXZWJleE1lc3NhZ2U7XG4gIH07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT3BlbkNsYXdBdHRhY2htZW50IHtcbiAgdHlwZTogJ2ZpbGUnIHwgJ2NhcmQnO1xuICB1cmw/OiBzdHJpbmc7XG4gIGNvbnRlbnQ/OiB1bmtub3duO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE9wZW5DbGF3T3V0Ym91bmRNZXNzYWdlIHtcbiAgLyoqIFRhcmdldCBjb252ZXJzYXRpb24gSUQgKHJvb21JZCkgb3IgcGVyc29uIElEL2VtYWlsIGZvciBETXMgKi9cbiAgdG86IHN0cmluZztcblxuICAvKiogTWVzc2FnZSBjb250ZW50ICovXG4gIGNvbnRlbnQ6IHtcbiAgICB0ZXh0Pzogc3RyaW5nO1xuICAgIG1hcmtkb3duPzogc3RyaW5nO1xuICAgIGZpbGVzPzogc3RyaW5nW107XG4gICAgY2FyZD86IEFkYXB0aXZlQ2FyZDtcbiAgfTtcblxuICAvKiogT3B0aW9uYWwgcGFyZW50IG1lc3NhZ2UgSUQgZm9yIHRocmVhZGluZyAqL1xuICBwYXJlbnRJZD86IHN0cmluZztcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gUGx1Z2luIFR5cGVzXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCBpbnRlcmZhY2UgV2ViZXhDaGFubmVsUGx1Z2luIHtcbiAgbmFtZTogc3RyaW5nO1xuICB2ZXJzaW9uOiBzdHJpbmc7XG5cbiAgLyoqIEluaXRpYWxpemUgdGhlIGNoYW5uZWwgd2l0aCBjb25maWd1cmF0aW9uICovXG4gIGluaXRpYWxpemUoY29uZmlnOiBXZWJleENoYW5uZWxDb25maWcpOiBQcm9taXNlPHZvaWQ+O1xuXG4gIC8qKiBTZW5kIGEgbWVzc2FnZSAqL1xuICBzZW5kKG1lc3NhZ2U6IE9wZW5DbGF3T3V0Ym91bmRNZXNzYWdlKTogUHJvbWlzZTxXZWJleE1lc3NhZ2U+O1xuXG4gIC8qKiBIYW5kbGUgaW5jb21pbmcgd2ViaG9vayAqL1xuICBoYW5kbGVXZWJob29rKHBheWxvYWQ6IFdlYmV4V2ViaG9va1BheWxvYWQsIHNpZ25hdHVyZT86IHN0cmluZyk6IFByb21pc2U8T3BlbkNsYXdFbnZlbG9wZSB8IG51bGw+O1xuXG4gIC8qKiBSZWdpc3RlciB3ZWJob29rcyB3aXRoIFdlYmV4ICovXG4gIHJlZ2lzdGVyV2ViaG9va3MoKTogUHJvbWlzZTxXZWJleFdlYmhvb2tbXT47XG5cbiAgLyoqIENsZWFudXAgYW5kIHNodXRkb3duICovXG4gIHNodXRkb3duKCk6IFByb21pc2U8dm9pZD47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgV2ViaG9va0hhbmRsZXIge1xuICAoZW52ZWxvcGU6IE9wZW5DbGF3RW52ZWxvcGUpOiBQcm9taXNlPHZvaWQ+IHwgdm9pZDtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gSW50ZXJuYWwgVHlwZXNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGludGVyZmFjZSBSZXRyeU9wdGlvbnMge1xuICBtYXhSZXRyaWVzOiBudW1iZXI7XG4gIHJldHJ5RGVsYXlNczogbnVtYmVyO1xuICBzaG91bGRSZXRyeT86IChlcnJvcjogRXJyb3IsIGF0dGVtcHQ6IG51bWJlcikgPT4gYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXF1ZXN0T3B0aW9ucyB7XG4gIG1ldGhvZDogJ0dFVCcgfCAnUE9TVCcgfCAnUFVUJyB8ICdERUxFVEUnO1xuICBwYXRoOiBzdHJpbmc7XG4gIGJvZHk/OiB1bmtub3duO1xuICBoZWFkZXJzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Webex Webhook Handler Module
|
|
3
|
+
*/
|
|
4
|
+
import type { WebexChannelConfig, WebexWebhookPayload, WebexWebhook, CreateWebhookRequest, OpenClawEnvelope } from './types';
|
|
5
|
+
export declare class WebexWebhookHandler {
|
|
6
|
+
private config;
|
|
7
|
+
private apiBaseUrl;
|
|
8
|
+
private botId;
|
|
9
|
+
constructor(config: WebexChannelConfig);
|
|
10
|
+
/**
|
|
11
|
+
* Initialize the webhook handler (fetch bot info)
|
|
12
|
+
*/
|
|
13
|
+
initialize(): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Handle an incoming webhook request
|
|
16
|
+
*/
|
|
17
|
+
handleWebhook(payload: WebexWebhookPayload, signature?: string): Promise<OpenClawEnvelope | null>;
|
|
18
|
+
/**
|
|
19
|
+
* Verify webhook signature using HMAC-SHA1
|
|
20
|
+
*/
|
|
21
|
+
verifySignature(payload: WebexWebhookPayload, signature: string): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Check if the sender is allowed based on DM policy
|
|
24
|
+
*/
|
|
25
|
+
private isAllowedSender;
|
|
26
|
+
/**
|
|
27
|
+
* Fetch full message details from Webex API
|
|
28
|
+
*/
|
|
29
|
+
private fetchMessage;
|
|
30
|
+
/**
|
|
31
|
+
* Normalize a Webex message to OpenClaw envelope format
|
|
32
|
+
*/
|
|
33
|
+
private normalizeMessage;
|
|
34
|
+
/**
|
|
35
|
+
* Register webhooks with Webex
|
|
36
|
+
*/
|
|
37
|
+
registerWebhooks(): Promise<WebexWebhook[]>;
|
|
38
|
+
/**
|
|
39
|
+
* List all webhooks
|
|
40
|
+
*/
|
|
41
|
+
listWebhooks(): Promise<WebexWebhook[]>;
|
|
42
|
+
/**
|
|
43
|
+
* Create a webhook
|
|
44
|
+
*/
|
|
45
|
+
createWebhook(request: CreateWebhookRequest): Promise<WebexWebhook>;
|
|
46
|
+
/**
|
|
47
|
+
* Delete a webhook
|
|
48
|
+
*/
|
|
49
|
+
deleteWebhook(webhookId: string): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Get bot information
|
|
52
|
+
*/
|
|
53
|
+
private getBotInfo;
|
|
54
|
+
/**
|
|
55
|
+
* Get the bot ID (after initialization)
|
|
56
|
+
*/
|
|
57
|
+
getBotId(): string | null;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Custom error for webhook validation failures
|
|
61
|
+
*/
|
|
62
|
+
export declare class WebhookValidationError extends Error {
|
|
63
|
+
constructor(message: string);
|
|
64
|
+
}
|
package/dist/webhook.js
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Webex Webhook Handler Module
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
|
+
};
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.WebhookValidationError = exports.WebexWebhookHandler = void 0;
|
|
43
|
+
const crypto = __importStar(require("crypto"));
|
|
44
|
+
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
45
|
+
const DEFAULT_API_BASE_URL = 'https://webexapis.com/v1';
|
|
46
|
+
class WebexWebhookHandler {
|
|
47
|
+
config;
|
|
48
|
+
apiBaseUrl;
|
|
49
|
+
botId = null;
|
|
50
|
+
constructor(config) {
|
|
51
|
+
this.config = config;
|
|
52
|
+
this.apiBaseUrl = config.apiBaseUrl || DEFAULT_API_BASE_URL;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Initialize the webhook handler (fetch bot info)
|
|
56
|
+
*/
|
|
57
|
+
async initialize() {
|
|
58
|
+
const botInfo = await this.getBotInfo();
|
|
59
|
+
this.botId = botInfo.id;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Handle an incoming webhook request
|
|
63
|
+
*/
|
|
64
|
+
async handleWebhook(payload, signature) {
|
|
65
|
+
// Verify webhook signature if secret is configured
|
|
66
|
+
if (this.config.webhookSecret && signature) {
|
|
67
|
+
if (!this.verifySignature(payload, signature)) {
|
|
68
|
+
throw new WebhookValidationError('Invalid webhook signature');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Only handle message created events
|
|
72
|
+
if (payload.resource !== 'messages' || payload.event !== 'created') {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
// Ignore messages from the bot itself
|
|
76
|
+
if (payload.data.personId === this.botId) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
// Check DM policy
|
|
80
|
+
if (payload.data.roomType === 'direct') {
|
|
81
|
+
if (!this.isAllowedSender(payload.data)) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Fetch full message details (webhook only contains IDs)
|
|
86
|
+
const message = await this.fetchMessage(payload.data.id);
|
|
87
|
+
// Normalize to OpenClaw envelope
|
|
88
|
+
return this.normalizeMessage(message);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Verify webhook signature using HMAC-SHA1
|
|
92
|
+
*/
|
|
93
|
+
verifySignature(payload, signature) {
|
|
94
|
+
if (!this.config.webhookSecret) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
const hmac = crypto.createHmac('sha1', this.config.webhookSecret);
|
|
98
|
+
hmac.update(JSON.stringify(payload));
|
|
99
|
+
const expectedSignature = hmac.digest('hex');
|
|
100
|
+
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSignature));
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Check if the sender is allowed based on DM policy
|
|
104
|
+
*/
|
|
105
|
+
isAllowedSender(data) {
|
|
106
|
+
switch (this.config.dmPolicy) {
|
|
107
|
+
case 'allow':
|
|
108
|
+
return true;
|
|
109
|
+
case 'deny':
|
|
110
|
+
return false;
|
|
111
|
+
case 'allowlisted':
|
|
112
|
+
if (!this.config.allowFrom || this.config.allowFrom.length === 0) {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
return this.config.allowFrom.includes(data.personId) ||
|
|
116
|
+
this.config.allowFrom.includes(data.personEmail);
|
|
117
|
+
default:
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Fetch full message details from Webex API
|
|
123
|
+
*/
|
|
124
|
+
async fetchMessage(messageId) {
|
|
125
|
+
const response = await (0, node_fetch_1.default)(`${this.apiBaseUrl}/messages/${messageId}`, {
|
|
126
|
+
method: 'GET',
|
|
127
|
+
headers: {
|
|
128
|
+
'Authorization': `Bearer ${this.config.token}`,
|
|
129
|
+
'Content-Type': 'application/json',
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
if (!response.ok) {
|
|
133
|
+
throw new Error(`Failed to fetch message: ${response.status} ${response.statusText}`);
|
|
134
|
+
}
|
|
135
|
+
return response.json();
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Normalize a Webex message to OpenClaw envelope format
|
|
139
|
+
*/
|
|
140
|
+
normalizeMessage(message) {
|
|
141
|
+
const attachments = [];
|
|
142
|
+
// Convert file attachments
|
|
143
|
+
if (message.files && message.files.length > 0) {
|
|
144
|
+
for (const fileUrl of message.files) {
|
|
145
|
+
attachments.push({
|
|
146
|
+
type: 'file',
|
|
147
|
+
url: fileUrl,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// Convert card attachments
|
|
152
|
+
if (message.attachments && message.attachments.length > 0) {
|
|
153
|
+
for (const attachment of message.attachments) {
|
|
154
|
+
attachments.push({
|
|
155
|
+
type: 'card',
|
|
156
|
+
content: attachment.content,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return {
|
|
161
|
+
id: message.id,
|
|
162
|
+
channel: 'webex',
|
|
163
|
+
conversationId: message.roomId,
|
|
164
|
+
author: {
|
|
165
|
+
id: message.personId,
|
|
166
|
+
email: message.personEmail,
|
|
167
|
+
displayName: undefined, // Would need additional API call to get
|
|
168
|
+
isBot: false, // Messages from bot are filtered out earlier
|
|
169
|
+
},
|
|
170
|
+
content: {
|
|
171
|
+
text: message.text,
|
|
172
|
+
markdown: message.markdown,
|
|
173
|
+
attachments: attachments.length > 0 ? attachments : undefined,
|
|
174
|
+
},
|
|
175
|
+
metadata: {
|
|
176
|
+
roomType: message.roomType,
|
|
177
|
+
roomId: message.roomId,
|
|
178
|
+
timestamp: message.created,
|
|
179
|
+
mentions: message.mentionedPeople,
|
|
180
|
+
parentId: message.parentId,
|
|
181
|
+
raw: message,
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Register webhooks with Webex
|
|
187
|
+
*/
|
|
188
|
+
async registerWebhooks() {
|
|
189
|
+
// First, list existing webhooks and remove duplicates
|
|
190
|
+
const existing = await this.listWebhooks();
|
|
191
|
+
const targetUrl = this.config.webhookUrl;
|
|
192
|
+
// Delete existing webhooks with the same target URL
|
|
193
|
+
for (const webhook of existing) {
|
|
194
|
+
if (webhook.targetUrl === targetUrl) {
|
|
195
|
+
await this.deleteWebhook(webhook.id);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// Create new webhooks for messages
|
|
199
|
+
const webhooks = [];
|
|
200
|
+
// Webhook for new messages
|
|
201
|
+
const messageCreatedWebhook = await this.createWebhook({
|
|
202
|
+
name: 'OpenClaw Message Handler',
|
|
203
|
+
targetUrl,
|
|
204
|
+
resource: 'messages',
|
|
205
|
+
event: 'created',
|
|
206
|
+
secret: this.config.webhookSecret,
|
|
207
|
+
});
|
|
208
|
+
webhooks.push(messageCreatedWebhook);
|
|
209
|
+
return webhooks;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* List all webhooks
|
|
213
|
+
*/
|
|
214
|
+
async listWebhooks() {
|
|
215
|
+
const response = await (0, node_fetch_1.default)(`${this.apiBaseUrl}/webhooks`, {
|
|
216
|
+
method: 'GET',
|
|
217
|
+
headers: {
|
|
218
|
+
'Authorization': `Bearer ${this.config.token}`,
|
|
219
|
+
'Content-Type': 'application/json',
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
if (!response.ok) {
|
|
223
|
+
throw new Error(`Failed to list webhooks: ${response.status} ${response.statusText}`);
|
|
224
|
+
}
|
|
225
|
+
const data = await response.json();
|
|
226
|
+
return data.items;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Create a webhook
|
|
230
|
+
*/
|
|
231
|
+
async createWebhook(request) {
|
|
232
|
+
const response = await (0, node_fetch_1.default)(`${this.apiBaseUrl}/webhooks`, {
|
|
233
|
+
method: 'POST',
|
|
234
|
+
headers: {
|
|
235
|
+
'Authorization': `Bearer ${this.config.token}`,
|
|
236
|
+
'Content-Type': 'application/json',
|
|
237
|
+
},
|
|
238
|
+
body: JSON.stringify(request),
|
|
239
|
+
});
|
|
240
|
+
if (!response.ok) {
|
|
241
|
+
const errorText = await response.text();
|
|
242
|
+
throw new Error(`Failed to create webhook: ${response.status} ${response.statusText} - ${errorText}`);
|
|
243
|
+
}
|
|
244
|
+
return response.json();
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Delete a webhook
|
|
248
|
+
*/
|
|
249
|
+
async deleteWebhook(webhookId) {
|
|
250
|
+
const response = await (0, node_fetch_1.default)(`${this.apiBaseUrl}/webhooks/${webhookId}`, {
|
|
251
|
+
method: 'DELETE',
|
|
252
|
+
headers: {
|
|
253
|
+
'Authorization': `Bearer ${this.config.token}`,
|
|
254
|
+
},
|
|
255
|
+
});
|
|
256
|
+
if (!response.ok && response.status !== 404) {
|
|
257
|
+
throw new Error(`Failed to delete webhook: ${response.status} ${response.statusText}`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Get bot information
|
|
262
|
+
*/
|
|
263
|
+
async getBotInfo() {
|
|
264
|
+
const response = await (0, node_fetch_1.default)(`${this.apiBaseUrl}/people/me`, {
|
|
265
|
+
method: 'GET',
|
|
266
|
+
headers: {
|
|
267
|
+
'Authorization': `Bearer ${this.config.token}`,
|
|
268
|
+
'Content-Type': 'application/json',
|
|
269
|
+
},
|
|
270
|
+
});
|
|
271
|
+
if (!response.ok) {
|
|
272
|
+
throw new Error(`Failed to get bot info: ${response.status} ${response.statusText}`);
|
|
273
|
+
}
|
|
274
|
+
return response.json();
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Get the bot ID (after initialization)
|
|
278
|
+
*/
|
|
279
|
+
getBotId() {
|
|
280
|
+
return this.botId;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
exports.WebexWebhookHandler = WebexWebhookHandler;
|
|
284
|
+
/**
|
|
285
|
+
* Custom error for webhook validation failures
|
|
286
|
+
*/
|
|
287
|
+
class WebhookValidationError extends Error {
|
|
288
|
+
constructor(message) {
|
|
289
|
+
super(message);
|
|
290
|
+
this.name = 'WebhookValidationError';
|
|
291
|
+
if (Error.captureStackTrace) {
|
|
292
|
+
Error.captureStackTrace(this, WebhookValidationError);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
exports.WebhookValidationError = WebhookValidationError;
|
|
297
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViaG9vay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy93ZWJob29rLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7R0FFRzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBRUgsK0NBQWlDO0FBQ2pDLDREQUErQjtBQWEvQixNQUFNLG9CQUFvQixHQUFHLDBCQUEwQixDQUFDO0FBRXhELE1BQWEsbUJBQW1CO0lBQ3RCLE1BQU0sQ0FBcUI7SUFDM0IsVUFBVSxDQUFTO0lBQ25CLEtBQUssR0FBa0IsSUFBSSxDQUFDO0lBRXBDLFlBQVksTUFBMEI7UUFDcEMsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDckIsSUFBSSxDQUFDLFVBQVUsR0FBRyxNQUFNLENBQUMsVUFBVSxJQUFJLG9CQUFvQixDQUFDO0lBQzlELENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssQ0FBQyxVQUFVO1FBQ2QsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDeEMsSUFBSSxDQUFDLEtBQUssR0FBRyxPQUFPLENBQUMsRUFBRSxDQUFDO0lBQzFCLENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssQ0FBQyxhQUFhLENBQ2pCLE9BQTRCLEVBQzVCLFNBQWtCO1FBRWxCLG1EQUFtRDtRQUNuRCxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxJQUFJLFNBQVMsRUFBRSxDQUFDO1lBQzNDLElBQUksQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sRUFBRSxTQUFTLENBQUMsRUFBRSxDQUFDO2dCQUM5QyxNQUFNLElBQUksc0JBQXNCLENBQUMsMkJBQTJCLENBQUMsQ0FBQztZQUNoRSxDQUFDO1FBQ0gsQ0FBQztRQUVELHFDQUFxQztRQUNyQyxJQUFJLE9BQU8sQ0FBQyxRQUFRLEtBQUssVUFBVSxJQUFJLE9BQU8sQ0FBQyxLQUFLLEtBQUssU0FBUyxFQUFFLENBQUM7WUFD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MkJBQTJCLFFBQVEsQ0FBQyxNQUFNLElBQUksUUFBUSxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUM7UUFDdkYsQ0FBQztRQUVELE9BQU8sUUFBUSxDQUFDLElBQUksRUFBb0UsQ0FBQztJQUMzRixDQUFDO0lBRUQ7O09BRUc7SUFDSCxRQUFRO1FBQ04sT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDO0lBQ3BCLENBQUM7Q0FDRjtBQXRSRCxrREFzUkM7QUFFRDs7R0FFRztBQUNILE1BQWEsc0JBQXVCLFNBQVEsS0FBSztJQUMvQyxZQUFZLE9BQWU7UUFDekIsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2YsSUFBSSxDQUFDLElBQUksR0FBRyx3QkFBd0IsQ0FBQztRQUVyQyxJQUFJLEtBQUssQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1lBQzVCLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLEVBQUUsc0JBQXNCLENBQUMsQ0FBQztRQUN4RCxDQUFDO0lBQ0gsQ0FBQztDQUNGO0FBVEQsd0RBU0MiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFdlYmV4IFdlYmhvb2sgSGFuZGxlciBNb2R1bGVcbiAqL1xuXG5pbXBvcnQgKiBhcyBjcnlwdG8gZnJvbSAnY3J5cHRvJztcbmltcG9ydCBmZXRjaCBmcm9tICdub2RlLWZldGNoJztcbmltcG9ydCB0eXBlIHtcbiAgV2ViZXhDaGFubmVsQ29uZmlnLFxuICBXZWJleFdlYmhvb2tQYXlsb2FkLFxuICBXZWJleFdlYmhvb2tEYXRhLFxuICBXZWJleE1lc3NhZ2UsXG4gIFdlYmV4V2ViaG9vayxcbiAgQ3JlYXRlV2ViaG9va1JlcXVlc3QsXG4gIE9wZW5DbGF3RW52ZWxvcGUsXG4gIE9wZW5DbGF3QXR0YWNobWVudCxcbiAgUGFnaW5hdGVkUmVzcG9uc2UsXG59IGZyb20gJy4vdHlwZXMnO1xuXG5jb25zdCBERUZBVUxUX0FQSV9CQVNFX1VSTCA9ICdodHRwczovL3dlYmV4YXBpcy5jb20vdjEnO1xuXG5leHBvcnQgY2xhc3MgV2ViZXhXZWJob29rSGFuZGxlciB7XG4gIHByaXZhdGUgY29uZmlnOiBXZWJleENoYW5uZWxDb25maWc7XG4gIHByaXZhdGUgYXBpQmFzZVVybDogc3RyaW5nO1xuICBwcml2YXRlIGJvdElkOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcblxuICBjb25zdHJ1Y3Rvcihjb25maWc6IFdlYmV4Q2hhbm5lbENvbmZpZykge1xuICAgIHRoaXMuY29uZmlnID0gY29uZmlnO1xuICAgIHRoaXMuYXBpQmFzZVVybCA9IGNvbmZpZy5hcGlCYXNlVXJsIHx8IERFRkFVTFRfQVBJX0JBU0VfVVJMO1xuICB9XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemUgdGhlIHdlYmhvb2sgaGFuZGxlciAoZmV0Y2ggYm90IGluZm8pXG4gICAqL1xuICBhc3luYyBpbml0aWFsaXplKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGJvdEluZm8gPSBhd2FpdCB0aGlzLmdldEJvdEluZm8oKTtcbiAgICB0aGlzLmJvdElkID0gYm90SW5mby5pZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGUgYW4gaW5jb21pbmcgd2ViaG9vayByZXF1ZXN0XG4gICAqL1xuICBhc3luYyBoYW5kbGVXZWJob29rKFxuICAgIHBheWxvYWQ6IFdlYmV4V2ViaG9va1BheWxvYWQsXG4gICAgc2lnbmF0dXJlPzogc3RyaW5nXG4gICk6IFByb21pc2U8T3BlbkNsYXdFbnZlbG9wZSB8IG51bGw+IHtcbiAgICAvLyBWZXJpZnkgd2ViaG9vayBzaWduYXR1cmUgaWYgc2VjcmV0IGlzIGNvbmZpZ3VyZWRcbiAgICBpZiAodGhpcy5jb25maWcud2ViaG9va1NlY3JldCAmJiBzaWduYXR1cmUpIHtcbiAgICAgIGlmICghdGhpcy52ZXJpZnlTaWduYXR1cmUocGF5bG9hZCwgc2lnbmF0dXJlKSkge1xuICAgICAgICB0aHJvdyBuZXcgV2ViaG9va1ZhbGlkYXRpb25FcnJvcignSW52YWxpZCB3ZWJob29rIHNpZ25hdHVyZScpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIE9ubHkgaGFuZGxlIG1lc3NhZ2UgY3JlYXRlZCBldmVudHNcbiAgICBpZiAocGF5bG9hZC5yZXNvdXJjZSAhPT0gJ21lc3NhZ2VzJyB8fCBwYXlsb2FkLmV2ZW50ICE9PSAnY3JlYXRlZCcpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIC8vIElnbm9yZSBtZXNzYWdlcyBmcm9tIHRoZSBib3QgaXRzZWxmXG4gICAgaWYgKHBheWxvYWQuZGF0YS5wZXJzb25JZCA9PT0gdGhpcy5ib3RJZCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgRE0gcG9saWN5XG4gICAgaWYgKHBheWxvYWQuZGF0YS5yb29tVHlwZSA9PT0gJ2RpcmVjdCcpIHtcbiAgICAgIGlmICghdGhpcy5pc0FsbG93ZWRTZW5kZXIocGF5bG9hZC5kYXRhKSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBGZXRjaCBmdWxsIG1lc3NhZ2UgZGV0YWlscyAod2ViaG9vayBvbmx5IGNvbnRhaW5zIElEcylcbiAgICBjb25zdCBtZXNzYWdlID0gYXdhaXQgdGhpcy5mZXRjaE1lc3NhZ2UocGF5bG9hZC5kYXRhLmlkKTtcblxuICAgIC8vIE5vcm1hbGl6ZSB0byBPcGVuQ2xhdyBlbnZlbG9wZVxuICAgIHJldHVybiB0aGlzLm5vcm1hbGl6ZU1lc3NhZ2UobWVzc2FnZSk7XG4gIH1cblxuICAvKipcbiAgICogVmVyaWZ5IHdlYmhvb2sgc2lnbmF0dXJlIHVzaW5nIEhNQUMtU0hBMVxuICAgKi9cbiAgdmVyaWZ5U2lnbmF0dXJlKHBheWxvYWQ6IFdlYmV4V2ViaG9va1BheWxvYWQsIHNpZ25hdHVyZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgaWYgKCF0aGlzLmNvbmZpZy53ZWJob29rU2VjcmV0KSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBjb25zdCBobWFjID0gY3J5cHRvLmNyZWF0ZUhtYWMoJ3NoYTEnLCB0aGlzLmNvbmZpZy53ZWJob29rU2VjcmV0KTtcbiAgICBobWFjLnVwZGF0ZShKU09OLnN0cmluZ2lmeShwYXlsb2FkKSk7XG4gICAgY29uc3QgZXhwZWN0ZWRTaWduYXR1cmUgPSBobWFjLmRpZ2VzdCgnaGV4Jyk7XG5cbiAgICByZXR1cm4gY3J5cHRvLnRpbWluZ1NhZmVFcXVhbChcbiAgICAgIEJ1ZmZlci5mcm9tKHNpZ25hdHVyZSksXG4gICAgICBCdWZmZXIuZnJvbShleHBlY3RlZFNpZ25hdHVyZSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIHRoZSBzZW5kZXIgaXMgYWxsb3dlZCBiYXNlZCBvbiBETSBwb2xpY3lcbiAgICovXG4gIHByaXZhdGUgaXNBbGxvd2VkU2VuZGVyKGRhdGE6IFdlYmV4V2ViaG9va0RhdGEpOiBib29sZWFuIHtcbiAgICBzd2l0Y2ggKHRoaXMuY29uZmlnLmRtUG9saWN5KSB7XG4gICAgICBjYXNlICdhbGxvdyc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnZGVueSc6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGNhc2UgJ2FsbG93bGlzdGVkJzpcbiAgICAgICAgaWYgKCF0aGlzLmNvbmZpZy5hbGxvd0Zyb20gfHwgdGhpcy5jb25maWcuYWxsb3dGcm9tLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5jb25maWcuYWxsb3dGcm9tLmluY2x1ZGVzKGRhdGEucGVyc29uSWQpIHx8XG4gICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5hbGxvd0Zyb20uaW5jbHVkZXMoZGF0YS5wZXJzb25FbWFpbCk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEZldGNoIGZ1bGwgbWVzc2FnZSBkZXRhaWxzIGZyb20gV2ViZXggQVBJXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGZldGNoTWVzc2FnZShtZXNzYWdlSWQ6IHN0cmluZyk6IFByb21pc2U8V2ViZXhNZXNzYWdlPiB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChgJHt0aGlzLmFwaUJhc2VVcmx9L21lc3NhZ2VzLyR7bWVzc2FnZUlkfWAsIHtcbiAgICAgIG1ldGhvZDogJ0dFVCcsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgICdBdXRob3JpemF0aW9uJzogYEJlYXJlciAke3RoaXMuY29uZmlnLnRva2VufWAsXG4gICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gZmV0Y2ggbWVzc2FnZTogJHtyZXNwb25zZS5zdGF0dXN9ICR7cmVzcG9uc2Uuc3RhdHVzVGV4dH1gKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpIGFzIFByb21pc2U8V2ViZXhNZXNzYWdlPjtcbiAgfVxuXG4gIC8qKlxuICAgKiBOb3JtYWxpemUgYSBXZWJleCBtZXNzYWdlIHRvIE9wZW5DbGF3IGVudmVsb3BlIGZvcm1hdFxuICAgKi9cbiAgcHJpdmF0ZSBub3JtYWxpemVNZXNzYWdlKG1lc3NhZ2U6IFdlYmV4TWVzc2FnZSk6IE9wZW5DbGF3RW52ZWxvcGUge1xuICAgIGNvbnN0IGF0dGFjaG1lbnRzOiBPcGVuQ2xhd0F0dGFjaG1lbnRbXSA9IFtdO1xuXG4gICAgLy8gQ29udmVydCBmaWxlIGF0dGFjaG1lbnRzXG4gICAgaWYgKG1lc3NhZ2UuZmlsZXMgJiYgbWVzc2FnZS5maWxlcy5sZW5ndGggPiAwKSB7XG4gICAgICBmb3IgKGNvbnN0IGZpbGVVcmwgb2YgbWVzc2FnZS5maWxlcykge1xuICAgICAgICBhdHRhY2htZW50cy5wdXNoKHtcbiAgICAgICAgICB0eXBlOiAnZmlsZScsXG4gICAgICAgICAgdXJsOiBmaWxlVXJsLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBDb252ZXJ0IGNhcmQgYXR0YWNobWVudHNcbiAgICBpZiAobWVzc2FnZS5hdHRhY2htZW50cyAmJiBtZXNzYWdlLmF0dGFjaG1lbnRzLmxlbmd0aCA+IDApIHtcbiAgICAgIGZvciAoY29uc3QgYXR0YWNobWVudCBvZiBtZXNzYWdlLmF0dGFjaG1lbnRzKSB7XG4gICAgICAgIGF0dGFjaG1lbnRzLnB1c2goe1xuICAgICAgICAgIHR5cGU6ICdjYXJkJyxcbiAgICAgICAgICBjb250ZW50OiBhdHRhY2htZW50LmNvbnRlbnQsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBpZDogbWVzc2FnZS5pZCxcbiAgICAgIGNoYW5uZWw6ICd3ZWJleCcsXG4gICAgICBjb252ZXJzYXRpb25JZDogbWVzc2FnZS5yb29tSWQsXG4gICAgICBhdXRob3I6IHtcbiAgICAgICAgaWQ6IG1lc3NhZ2UucGVyc29uSWQsXG4gICAgICAgIGVtYWlsOiBtZXNzYWdlLnBlcnNvbkVtYWlsLFxuICAgICAgICBkaXNwbGF5TmFtZTogdW5kZWZpbmVkLCAvLyBXb3VsZCBuZWVkIGFkZGl0aW9uYWwgQVBJIGNhbGwgdG8gZ2V0XG4gICAgICAgIGlzQm90OiBmYWxzZSwgLy8gTWVzc2FnZXMgZnJvbSBib3QgYXJlIGZpbHRlcmVkIG91dCBlYXJsaWVyXG4gICAgICB9LFxuICAgICAgY29udGVudDoge1xuICAgICAgICB0ZXh0OiBtZXNzYWdlLnRleHQsXG4gICAgICAgIG1hcmtkb3duOiBtZXNzYWdlLm1hcmtkb3duLFxuICAgICAgICBhdHRhY2htZW50czogYXR0YWNobWVudHMubGVuZ3RoID4gMCA/IGF0dGFjaG1lbnRzIDogdW5kZWZpbmVkLFxuICAgICAgfSxcbiAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgIHJvb21UeXBlOiBtZXNzYWdlLnJvb21UeXBlLFxuICAgICAgICByb29tSWQ6IG1lc3NhZ2Uucm9vbUlkLFxuICAgICAgICB0aW1lc3RhbXA6IG1lc3NhZ2UuY3JlYXRlZCxcbiAgICAgICAgbWVudGlvbnM6IG1lc3NhZ2UubWVudGlvbmVkUGVvcGxlLFxuICAgICAgICBwYXJlbnRJZDogbWVzc2FnZS5wYXJlbnRJZCxcbiAgICAgICAgcmF3OiBtZXNzYWdlLFxuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVyIHdlYmhvb2tzIHdpdGggV2ViZXhcbiAgICovXG4gIGFzeW5jIHJlZ2lzdGVyV2ViaG9va3MoKTogUHJvbWlzZTxXZWJleFdlYmhvb2tbXT4ge1xuICAgIC8vIEZpcnN0LCBsaXN0IGV4aXN0aW5nIHdlYmhvb2tzIGFuZCByZW1vdmUgZHVwbGljYXRlc1xuICAgIGNvbnN0IGV4aXN0aW5nID0gYXdhaXQgdGhpcy5saXN0V2ViaG9va3MoKTtcbiAgICBjb25zdCB0YXJnZXRVcmwgPSB0aGlzLmNvbmZpZy53ZWJob29rVXJsO1xuXG4gICAgLy8gRGVsZXRlIGV4aXN0aW5nIHdlYmhvb2tzIHdpdGggdGhlIHNhbWUgdGFyZ2V0IFVSTFxuICAgIGZvciAoY29uc3Qgd2ViaG9vayBvZiBleGlzdGluZykge1xuICAgICAgaWYgKHdlYmhvb2sudGFyZ2V0VXJsID09PSB0YXJnZXRVcmwpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5kZWxldGVXZWJob29rKHdlYmhvb2suaWQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIENyZWF0ZSBuZXcgd2ViaG9va3MgZm9yIG1lc3NhZ2VzXG4gICAgY29uc3Qgd2ViaG9va3M6IFdlYmV4V2ViaG9va1tdID0gW107XG5cbiAgICAvLyBXZWJob29rIGZvciBuZXcgbWVzc2FnZXNcbiAgICBjb25zdCBtZXNzYWdlQ3JlYXRlZFdlYmhvb2sgPSBhd2FpdCB0aGlzLmNyZWF0ZVdlYmhvb2soe1xuICAgICAgbmFtZTogJ09wZW5DbGF3IE1lc3NhZ2UgSGFuZGxlcicsXG4gICAgICB0YXJnZXRVcmwsXG4gICAgICByZXNvdXJjZTogJ21lc3NhZ2VzJyxcbiAgICAgIGV2ZW50OiAnY3JlYXRlZCcsXG4gICAgICBzZWNyZXQ6IHRoaXMuY29uZmlnLndlYmhvb2tTZWNyZXQsXG4gICAgfSk7XG4gICAgd2ViaG9va3MucHVzaChtZXNzYWdlQ3JlYXRlZFdlYmhvb2spO1xuXG4gICAgcmV0dXJuIHdlYmhvb2tzO1xuICB9XG5cbiAgLyoqXG4gICAqIExpc3QgYWxsIHdlYmhvb2tzXG4gICAqL1xuICBhc3luYyBsaXN0V2ViaG9va3MoKTogUHJvbWlzZTxXZWJleFdlYmhvb2tbXT4ge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goYCR7dGhpcy5hcGlCYXNlVXJsfS93ZWJob29rc2AsIHtcbiAgICAgIG1ldGhvZDogJ0dFVCcsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgICdBdXRob3JpemF0aW9uJzogYEJlYXJlciAke3RoaXMuY29uZmlnLnRva2VufWAsXG4gICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gbGlzdCB3ZWJob29rczogJHtyZXNwb25zZS5zdGF0dXN9ICR7cmVzcG9uc2Uuc3RhdHVzVGV4dH1gKTtcbiAgICB9XG5cbiAgICBjb25zdCBkYXRhID0gYXdhaXQgcmVzcG9uc2UuanNvbigpIGFzIFBhZ2luYXRlZFJlc3BvbnNlPFdlYmV4V2ViaG9vaz47XG4gICAgcmV0dXJuIGRhdGEuaXRlbXM7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgd2ViaG9va1xuICAgKi9cbiAgYXN5bmMgY3JlYXRlV2ViaG9vayhyZXF1ZXN0OiBDcmVhdGVXZWJob29rUmVxdWVzdCk6IFByb21pc2U8V2ViZXhXZWJob29rPiB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChgJHt0aGlzLmFwaUJhc2VVcmx9L3dlYmhvb2tzYCwge1xuICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgICdBdXRob3JpemF0aW9uJzogYEJlYXJlciAke3RoaXMuY29uZmlnLnRva2VufWAsXG4gICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICB9LFxuICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkocmVxdWVzdCksXG4gICAgfSk7XG5cbiAgICBpZiAoIXJlc3BvbnNlLm9rKSB7XG4gICAgICBjb25zdCBlcnJvclRleHQgPSBhd2FpdCByZXNwb25zZS50ZXh0KCk7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBjcmVhdGUgd2ViaG9vazogJHtyZXNwb25zZS5zdGF0dXN9ICR7cmVzcG9uc2Uuc3RhdHVzVGV4dH0gLSAke2Vycm9yVGV4dH1gKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpIGFzIFByb21pc2U8V2ViZXhXZWJob29rPjtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGUgYSB3ZWJob29rXG4gICAqL1xuICBhc3luYyBkZWxldGVXZWJob29rKHdlYmhvb2tJZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChgJHt0aGlzLmFwaUJhc2VVcmx9L3dlYmhvb2tzLyR7d2ViaG9va0lkfWAsIHtcbiAgICAgIG1ldGhvZDogJ0RFTEVURScsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgICdBdXRob3JpemF0aW9uJzogYEJlYXJlciAke3RoaXMuY29uZmlnLnRva2VufWAsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgaWYgKCFyZXNwb25zZS5vayAmJiByZXNwb25zZS5zdGF0dXMgIT09IDQwNCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gZGVsZXRlIHdlYmhvb2s6ICR7cmVzcG9uc2Uuc3RhdHVzfSAke3Jlc3BvbnNlLnN0YXR1c1RleHR9YCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldCBib3QgaW5mb3JtYXRpb25cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZ2V0Qm90SW5mbygpOiBQcm9taXNlPHsgaWQ6IHN0cmluZzsgZGlzcGxheU5hbWU6IHN0cmluZzsgZW1haWxzOiBzdHJpbmdbXSB9PiB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChgJHt0aGlzLmFwaUJhc2VVcmx9L3Blb3BsZS9tZWAsIHtcbiAgICAgIG1ldGhvZDogJ0dFVCcsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgICdBdXRob3JpemF0aW9uJzogYEJlYXJlciAke3RoaXMuY29uZmlnLnRva2VufWAsXG4gICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gZ2V0IGJvdCBpbmZvOiAke3Jlc3BvbnNlLnN0YXR1c30gJHtyZXNwb25zZS5zdGF0dXNUZXh0fWApO1xuICAgIH1cblxuICAgIHJldHVybiByZXNwb25zZS5qc29uKCkgYXMgUHJvbWlzZTx7IGlkOiBzdHJpbmc7IGRpc3BsYXlOYW1lOiBzdHJpbmc7IGVtYWlsczogc3RyaW5nW10gfT47XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBib3QgSUQgKGFmdGVyIGluaXRpYWxpemF0aW9uKVxuICAgKi9cbiAgZ2V0Qm90SWQoKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuYm90SWQ7XG4gIH1cbn1cblxuLyoqXG4gKiBDdXN0b20gZXJyb3IgZm9yIHdlYmhvb2sgdmFsaWRhdGlvbiBmYWlsdXJlc1xuICovXG5leHBvcnQgY2xhc3MgV2ViaG9va1ZhbGlkYXRpb25FcnJvciBleHRlbmRzIEVycm9yIHtcbiAgY29uc3RydWN0b3IobWVzc2FnZTogc3RyaW5nKSB7XG4gICAgc3VwZXIobWVzc2FnZSk7XG4gICAgdGhpcy5uYW1lID0gJ1dlYmhvb2tWYWxpZGF0aW9uRXJyb3InO1xuXG4gICAgaWYgKEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKSB7XG4gICAgICBFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSh0aGlzLCBXZWJob29rVmFsaWRhdGlvbkVycm9yKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==
|