n8n-nodes-microsoft-teams-bot 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.
Files changed (127) hide show
  1. package/dist/credentials/TeamsBotApi.credentials.d.ts +7 -0
  2. package/dist/credentials/TeamsBotApi.credentials.js +107 -0
  3. package/dist/credentials/TeamsBotApi.credentials.js.map +1 -0
  4. package/dist/credentials/TeamsGraphApi.credentials.d.ts +7 -0
  5. package/dist/credentials/TeamsGraphApi.credentials.js +58 -0
  6. package/dist/credentials/TeamsGraphApi.credentials.js.map +1 -0
  7. package/dist/index.d.ts +4 -0
  8. package/dist/index.js +23 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/nodes/TeamsBot/TeamsBot.node.d.ts +21 -0
  11. package/dist/nodes/TeamsBot/TeamsBot.node.js +457 -0
  12. package/dist/nodes/TeamsBot/TeamsBot.node.js.map +1 -0
  13. package/dist/nodes/TeamsBot/TeamsBot.node.json +73 -0
  14. package/dist/nodes/TeamsBot/TeamsBotTrigger.node.d.ts +21 -0
  15. package/dist/nodes/TeamsBot/TeamsBotTrigger.node.js +506 -0
  16. package/dist/nodes/TeamsBot/TeamsBotTrigger.node.js.map +1 -0
  17. package/dist/nodes/TeamsBot/TeamsBotTrigger.node.json +57 -0
  18. package/dist/nodes/TeamsBot/actions/buildCard.d.ts +6 -0
  19. package/dist/nodes/TeamsBot/actions/buildCard.js +176 -0
  20. package/dist/nodes/TeamsBot/actions/buildCard.js.map +1 -0
  21. package/dist/nodes/TeamsBot/actions/cards.d.ts +34 -0
  22. package/dist/nodes/TeamsBot/actions/cards.js +731 -0
  23. package/dist/nodes/TeamsBot/actions/cards.js.map +1 -0
  24. package/dist/nodes/TeamsBot/actions/channels.d.ts +18 -0
  25. package/dist/nodes/TeamsBot/actions/channels.js +199 -0
  26. package/dist/nodes/TeamsBot/actions/channels.js.map +1 -0
  27. package/dist/nodes/TeamsBot/actions/messages.d.ts +86 -0
  28. package/dist/nodes/TeamsBot/actions/messages.js +1259 -0
  29. package/dist/nodes/TeamsBot/actions/messages.js.map +1 -0
  30. package/dist/nodes/TeamsBot/actions/router.d.ts +2 -0
  31. package/dist/nodes/TeamsBot/actions/router.js +186 -0
  32. package/dist/nodes/TeamsBot/actions/router.js.map +1 -0
  33. package/dist/nodes/TeamsBot/actions/teams.d.ts +18 -0
  34. package/dist/nodes/TeamsBot/actions/teams.js +227 -0
  35. package/dist/nodes/TeamsBot/actions/teams.js.map +1 -0
  36. package/dist/nodes/TeamsBot/actions/users.d.ts +13 -0
  37. package/dist/nodes/TeamsBot/actions/users.js +184 -0
  38. package/dist/nodes/TeamsBot/actions/users.js.map +1 -0
  39. package/dist/nodes/TeamsBot/descriptions/buildCard.description.d.ts +7 -0
  40. package/dist/nodes/TeamsBot/descriptions/buildCard.description.js +682 -0
  41. package/dist/nodes/TeamsBot/descriptions/buildCard.description.js.map +1 -0
  42. package/dist/nodes/TeamsBot/descriptions/card.description.d.ts +2 -0
  43. package/dist/nodes/TeamsBot/descriptions/card.description.js +564 -0
  44. package/dist/nodes/TeamsBot/descriptions/card.description.js.map +1 -0
  45. package/dist/nodes/TeamsBot/descriptions/index.d.ts +3 -0
  46. package/dist/nodes/TeamsBot/descriptions/index.js +20 -0
  47. package/dist/nodes/TeamsBot/descriptions/index.js.map +1 -0
  48. package/dist/nodes/TeamsBot/descriptions/message.description.d.ts +2 -0
  49. package/dist/nodes/TeamsBot/descriptions/message.description.js +964 -0
  50. package/dist/nodes/TeamsBot/descriptions/message.description.js.map +1 -0
  51. package/dist/nodes/TeamsBot/descriptions/node.description.d.ts +2 -0
  52. package/dist/nodes/TeamsBot/descriptions/node.description.js +567 -0
  53. package/dist/nodes/TeamsBot/descriptions/node.description.js.map +1 -0
  54. package/dist/nodes/TeamsBot/errors/authentication.d.ts +100 -0
  55. package/dist/nodes/TeamsBot/errors/authentication.js +110 -0
  56. package/dist/nodes/TeamsBot/errors/authentication.js.map +1 -0
  57. package/dist/nodes/TeamsBot/errors/graphApi.d.ts +44 -0
  58. package/dist/nodes/TeamsBot/errors/graphApi.js +84 -0
  59. package/dist/nodes/TeamsBot/errors/graphApi.js.map +1 -0
  60. package/dist/nodes/TeamsBot/errors/messages.d.ts +187 -0
  61. package/dist/nodes/TeamsBot/errors/messages.js +190 -0
  62. package/dist/nodes/TeamsBot/errors/messages.js.map +1 -0
  63. package/dist/nodes/TeamsBot/methods/listSearch.d.ts +4 -0
  64. package/dist/nodes/TeamsBot/methods/listSearch.js +78 -0
  65. package/dist/nodes/TeamsBot/methods/listSearch.js.map +1 -0
  66. package/dist/nodes/TeamsBot/teams.svg +11 -0
  67. package/dist/nodes/TeamsBot/transport/TeamsApiClient.d.ts +305 -0
  68. package/dist/nodes/TeamsBot/transport/TeamsApiClient.js +458 -0
  69. package/dist/nodes/TeamsBot/transport/TeamsApiClient.js.map +1 -0
  70. package/dist/nodes/TeamsBot/transport/api/BotFrameworkApi.d.ts +350 -0
  71. package/dist/nodes/TeamsBot/transport/api/BotFrameworkApi.js +1265 -0
  72. package/dist/nodes/TeamsBot/transport/api/BotFrameworkApi.js.map +1 -0
  73. package/dist/nodes/TeamsBot/transport/api/GraphApi.d.ts +158 -0
  74. package/dist/nodes/TeamsBot/transport/api/GraphApi.js +443 -0
  75. package/dist/nodes/TeamsBot/transport/api/GraphApi.js.map +1 -0
  76. package/dist/nodes/TeamsBot/transport/api/GraphApiClient.d.ts +160 -0
  77. package/dist/nodes/TeamsBot/transport/api/GraphApiClient.js +268 -0
  78. package/dist/nodes/TeamsBot/transport/api/GraphApiClient.js.map +1 -0
  79. package/dist/nodes/TeamsBot/transport/api/index.d.ts +7 -0
  80. package/dist/nodes/TeamsBot/transport/api/index.js +26 -0
  81. package/dist/nodes/TeamsBot/transport/api/index.js.map +1 -0
  82. package/dist/nodes/TeamsBot/transport/index.d.ts +12 -0
  83. package/dist/nodes/TeamsBot/transport/index.js +30 -0
  84. package/dist/nodes/TeamsBot/transport/index.js.map +1 -0
  85. package/dist/nodes/TeamsBot/types/api-types.d.ts +258 -0
  86. package/dist/nodes/TeamsBot/types/api-types.js +3 -0
  87. package/dist/nodes/TeamsBot/types/api-types.js.map +1 -0
  88. package/dist/nodes/TeamsBot/types/cards.d.ts +252 -0
  89. package/dist/nodes/TeamsBot/types/cards.js +3 -0
  90. package/dist/nodes/TeamsBot/types/cards.js.map +1 -0
  91. package/dist/nodes/TeamsBot/types/index.d.ts +5 -0
  92. package/dist/nodes/TeamsBot/types/index.js +24 -0
  93. package/dist/nodes/TeamsBot/types/index.js.map +1 -0
  94. package/dist/nodes/TeamsBot/utils/AdaptiveCardBuilder.d.ts +147 -0
  95. package/dist/nodes/TeamsBot/utils/AdaptiveCardBuilder.js +333 -0
  96. package/dist/nodes/TeamsBot/utils/AdaptiveCardBuilder.js.map +1 -0
  97. package/dist/nodes/TeamsBot/utils/AdaptiveCardTemplates.d.ts +122 -0
  98. package/dist/nodes/TeamsBot/utils/AdaptiveCardTemplates.js +467 -0
  99. package/dist/nodes/TeamsBot/utils/AdaptiveCardTemplates.js.map +1 -0
  100. package/dist/nodes/TeamsBot/utils/CardTemplates.d.ts +94 -0
  101. package/dist/nodes/TeamsBot/utils/CardTemplates.js +446 -0
  102. package/dist/nodes/TeamsBot/utils/CardTemplates.js.map +1 -0
  103. package/dist/nodes/TeamsBot/utils/apiHelpers.d.ts +30 -0
  104. package/dist/nodes/TeamsBot/utils/apiHelpers.js +95 -0
  105. package/dist/nodes/TeamsBot/utils/apiHelpers.js.map +1 -0
  106. package/dist/nodes/TeamsBot/utils/constants.d.ts +86 -0
  107. package/dist/nodes/TeamsBot/utils/constants.js +60 -0
  108. package/dist/nodes/TeamsBot/utils/constants.js.map +1 -0
  109. package/dist/nodes/TeamsBot/utils/fileProcessing.d.ts +66 -0
  110. package/dist/nodes/TeamsBot/utils/fileProcessing.js +276 -0
  111. package/dist/nodes/TeamsBot/utils/fileProcessing.js.map +1 -0
  112. package/dist/nodes/TeamsBot/utils/graphNotificationParser.d.ts +91 -0
  113. package/dist/nodes/TeamsBot/utils/graphNotificationParser.js +162 -0
  114. package/dist/nodes/TeamsBot/utils/graphNotificationParser.js.map +1 -0
  115. package/dist/nodes/TeamsBot/utils/index.d.ts +24 -0
  116. package/dist/nodes/TeamsBot/utils/index.js +90 -0
  117. package/dist/nodes/TeamsBot/utils/index.js.map +1 -0
  118. package/dist/nodes/TeamsBot/utils/installation.d.ts +15 -0
  119. package/dist/nodes/TeamsBot/utils/installation.js +41 -0
  120. package/dist/nodes/TeamsBot/utils/installation.js.map +1 -0
  121. package/dist/nodes/TeamsBot/utils/subscriptionManager.d.ts +63 -0
  122. package/dist/nodes/TeamsBot/utils/subscriptionManager.js +100 -0
  123. package/dist/nodes/TeamsBot/utils/subscriptionManager.js.map +1 -0
  124. package/dist/nodes/TeamsBot/utils/validation.d.ts +93 -0
  125. package/dist/nodes/TeamsBot/utils/validation.js +281 -0
  126. package/dist/nodes/TeamsBot/utils/validation.js.map +1 -0
  127. package/package.json +79 -0
@@ -0,0 +1,731 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.cardOperations = void 0;
27
+ const n8n_workflow_1 = require("n8n-workflow");
28
+ const index_1 = require("../transport/index");
29
+ const utils_1 = require("../utils");
30
+ const ACData = __importStar(require("adaptivecards-templating"));
31
+ /**
32
+ * Validates card operation parameters and card JSON format
33
+ * @param {CardOperationParams} params - Parameters to validate
34
+ * @param {string[]} requiredFields - List of required parameter fields
35
+ * @param {IExecuteFunctions} executeFunctions - n8n execution functions
36
+ * @param {number} itemIndex - Index of the current item being processed
37
+ * @throws {NodeOperationError} When validation fails
38
+ */
39
+ function validateCardParams(params, requiredFields, executeFunctions, itemIndex) {
40
+ // Validate required fields
41
+ for (const field of requiredFields) {
42
+ if (!params[field]) {
43
+ throw new n8n_workflow_1.NodeOperationError(executeFunctions.getNode(), `Required parameter "${field}" is missing`, { itemIndex });
44
+ }
45
+ }
46
+ // Validate recipient type and related fields
47
+ if (params.recipientType === 'channel') {
48
+ if (!params.teamId) {
49
+ throw new n8n_workflow_1.NodeOperationError(executeFunctions.getNode(), 'Required parameter "teamId" is missing for channel messages', { itemIndex });
50
+ }
51
+ if (!params.channelId) {
52
+ throw new n8n_workflow_1.NodeOperationError(executeFunctions.getNode(), 'Required parameter "channelId" is missing for channel messages', { itemIndex });
53
+ }
54
+ }
55
+ else if (params.recipientType === 'chat') {
56
+ if (!params.userId) {
57
+ throw new n8n_workflow_1.NodeOperationError(executeFunctions.getNode(), 'Required parameter "userId" is missing for chat messages', { itemIndex });
58
+ }
59
+ }
60
+ else {
61
+ throw new n8n_workflow_1.NodeOperationError(executeFunctions.getNode(), `Invalid recipient type: ${params.recipientType}`, { itemIndex });
62
+ }
63
+ }
64
+ /**
65
+ * Parses JSON card string into an object
66
+ * @param {string} card - JSON string of the card
67
+ * @param {IExecuteFunctions} executeFunctions - n8n execution functions
68
+ * @param {number} itemIndex - Index of the current item being processed
69
+ * @returns {AdaptiveCard} Parsed card object
70
+ * @throws {NodeOperationError} When card parsing fails
71
+ */
72
+ function parseCard(card, executeFunctions, itemIndex) {
73
+ try {
74
+ return typeof card === 'string' ? JSON.parse(card) : card;
75
+ }
76
+ catch (error) {
77
+ throw new n8n_workflow_1.NodeOperationError(executeFunctions.getNode(), `Invalid card format: ${error.message}`, { itemIndex });
78
+ }
79
+ }
80
+ /**
81
+ * Validates adaptive card structure with enhanced checks
82
+ * @param {AdaptiveCard} card - Card object to validate
83
+ * @param {IExecuteFunctions} executeFunctions - n8n execution functions
84
+ * @param {number} itemIndex - Index of the current item being processed
85
+ * @throws {NodeOperationError} When card validation fails
86
+ */
87
+ function validateCard(card, executeFunctions, itemIndex) {
88
+ try {
89
+ // Basic structure validation
90
+ if (!card.type || card.type !== 'AdaptiveCard') {
91
+ throw new Error('Card must have a valid type "AdaptiveCard"');
92
+ }
93
+ if (!card.version) {
94
+ throw new Error('Card must have a version property');
95
+ }
96
+ // Schema is required but might be missing in user-provided cards
97
+ if (!card.$schema) {
98
+ // Add it automatically rather than throwing an error
99
+ card.$schema = 'http://adaptivecards.io/schemas/adaptive-card.json';
100
+ }
101
+ // Check for body property
102
+ if (!card.body || !Array.isArray(card.body)) {
103
+ throw new Error('Card must have a body array');
104
+ }
105
+ // Enhanced validations
106
+ // Check schema version
107
+ const version = card.version;
108
+ // Validate card body components
109
+ validateCardComponents(card.body);
110
+ // Validate actions if present
111
+ if (card.actions && Array.isArray(card.actions)) {
112
+ validateCardActions(card.actions);
113
+ }
114
+ }
115
+ catch (error) {
116
+ throw new n8n_workflow_1.NodeOperationError(executeFunctions.getNode(), `Invalid card: ${error.message}`, { itemIndex });
117
+ }
118
+ }
119
+ /**
120
+ * Validates card body components
121
+ * @param {unknown[]} components - Array of card components to validate
122
+ * @throws {Error} When validation fails
123
+ */
124
+ function validateCardComponents(components) {
125
+ for (let i = 0; i < components.length; i++) {
126
+ const component = components[i];
127
+ // All components must have a type
128
+ if (!component.type) {
129
+ throw new Error(`Component at index ${i} is missing required 'type' property`);
130
+ }
131
+ // Validate specific component types
132
+ switch (component.type) {
133
+ case 'TextBlock':
134
+ if (component.text === undefined) {
135
+ throw new Error(`TextBlock at index ${i} is missing required 'text' property`);
136
+ }
137
+ break;
138
+ case 'Image':
139
+ if (!component.url) {
140
+ throw new Error(`Image at index ${i} is missing required 'url' property`);
141
+ }
142
+ break;
143
+ case 'Container':
144
+ if (!component.items || !Array.isArray(component.items)) {
145
+ throw new Error(`Container at index ${i} must have an 'items' array`);
146
+ }
147
+ validateCardComponents(component.items);
148
+ break;
149
+ case 'ColumnSet':
150
+ if (!component.columns || !Array.isArray(component.columns)) {
151
+ throw new Error(`ColumnSet at index ${i} must have a 'columns' array`);
152
+ }
153
+ // Validate each column in the column set
154
+ for (let j = 0; j < component.columns.length; j++) {
155
+ const column = component.columns[j];
156
+ if (!column.items || !Array.isArray(column.items)) {
157
+ throw new Error(`Column at index ${j} in ColumnSet ${i} must have an 'items' array`);
158
+ }
159
+ validateCardComponents(column.items);
160
+ }
161
+ break;
162
+ case 'FactSet':
163
+ if (!component.facts || !Array.isArray(component.facts)) {
164
+ throw new Error(`FactSet at index ${i} must have a 'facts' array`);
165
+ }
166
+ break;
167
+ }
168
+ }
169
+ }
170
+ /**
171
+ * Validates card actions
172
+ * @param {unknown[]} actions - Array of card actions to validate
173
+ * @throws {Error} When validation fails
174
+ */
175
+ function validateCardActions(actions) {
176
+ for (let i = 0; i < actions.length; i++) {
177
+ const action = actions[i];
178
+ // All actions must have a type
179
+ if (!action.type) {
180
+ throw new Error(`Action at index ${i} is missing required 'type' property`);
181
+ }
182
+ // Validate specific action types
183
+ switch (action.type) {
184
+ case 'Action.OpenUrl':
185
+ if (!action.url) {
186
+ throw new Error(`Action.OpenUrl at index ${i} is missing required 'url' property`);
187
+ }
188
+ if (!action.title) {
189
+ throw new Error(`Action.OpenUrl at index ${i} is missing required 'title' property`);
190
+ }
191
+ break;
192
+ case 'Action.Submit':
193
+ if (!action.title) {
194
+ throw new Error(`Action.Submit at index ${i} is missing required 'title' property`);
195
+ }
196
+ break;
197
+ case 'Action.ShowCard':
198
+ if (!action.title) {
199
+ throw new Error(`Action.ShowCard at index ${i} is missing required 'title' property`);
200
+ }
201
+ if (!action.card) {
202
+ throw new Error(`Action.ShowCard at index ${i} is missing required 'card' property`);
203
+ }
204
+ // Validate the nested card (but not recursively to avoid potential infinite loops)
205
+ {
206
+ const nestedCard = action.card;
207
+ if (!nestedCard.type || nestedCard.type !== 'AdaptiveCard') {
208
+ throw new Error(`Nested card in Action.ShowCard at index ${i} must have a valid type "AdaptiveCard"`);
209
+ }
210
+ if (!nestedCard.body || !Array.isArray(nestedCard.body)) {
211
+ throw new Error(`Nested card in Action.ShowCard at index ${i} must have a body array`);
212
+ }
213
+ }
214
+ break;
215
+ }
216
+ }
217
+ }
218
+ /**
219
+ * Card operations for the Teams Bot node
220
+ */
221
+ exports.cardOperations = {
222
+ /**
223
+ * Sends an adaptive card to a channel or chat
224
+ * @returns {Promise<INodeExecutionData[][]>} Promise resolving to output data
225
+ */
226
+ async send() {
227
+ const items = this.getInputData();
228
+ const returnData = [];
229
+ const api = new index_1.TeamsApiClient(this);
230
+ await api.initialize();
231
+ for (let i = 0; i < items.length; i++) {
232
+ try {
233
+ // Get operation parameters
234
+ const cardJson = this.getNodeParameter('card', i);
235
+ const recipientType = this.getNodeParameter('recipientType', i);
236
+ // Get options
237
+ const options = this.getNodeParameter('options', i, {});
238
+ // Get recipient-specific parameters
239
+ let teamId;
240
+ let channelId;
241
+ let userId;
242
+ if (recipientType === 'channel') {
243
+ teamId = this.getNodeParameter('teamId', i);
244
+ channelId = this.getNodeParameter('channelId', i);
245
+ }
246
+ else if (recipientType === 'chat') {
247
+ userId = this.getNodeParameter('userId', i);
248
+ }
249
+ // Prepare parameters for validation
250
+ const params = {
251
+ card: cardJson,
252
+ recipientType,
253
+ teamId,
254
+ channelId,
255
+ userId,
256
+ };
257
+ // Validate parameters
258
+ validateCardParams(params, ['card', 'recipientType'], this, i);
259
+ // Parse and validate card
260
+ const parsedCard = parseCard(cardJson, this, i);
261
+ validateCard(parsedCard, this, i);
262
+ // Convert to JSON string
263
+ const cardString = JSON.stringify(parsedCard);
264
+ // Send card based on recipient type
265
+ let response;
266
+ if (recipientType === 'channel') {
267
+ // Always handle auto-installation for channel
268
+ await (0, index_1.handleAutoInstall)(api, teamId, i, this);
269
+ // Send card to channel
270
+ response = await api.sendAdaptiveCardToChannel(teamId, channelId, cardString);
271
+ }
272
+ else {
273
+ // Always handle auto-installation for user
274
+ await (0, index_1.handleAutoInstall)(api, userId, i, this);
275
+ // Use the BotFrameworkApi directly to send the card in one operation
276
+ // This prevents sending an empty message followed by a card
277
+ response = await api.sendAdaptiveCardToUser(userId, cardString);
278
+ // Ensure we got a proper object response
279
+ response = (0, utils_1.ensureObjectResponse)(response);
280
+ }
281
+ // Ensure response is properly parsed before returning
282
+ returnData.push({
283
+ json: response,
284
+ pairedItem: { item: i },
285
+ });
286
+ }
287
+ catch (error) {
288
+ if (this.continueOnFail()) {
289
+ const errorMessage = error instanceof Error ? error.message : String(error);
290
+ returnData.push({
291
+ json: {
292
+ error: errorMessage,
293
+ },
294
+ pairedItem: { item: i },
295
+ });
296
+ continue;
297
+ }
298
+ throw error;
299
+ }
300
+ }
301
+ return [returnData];
302
+ },
303
+ /**
304
+ * Sends a notification card to a channel or chat
305
+ * @returns {Promise<INodeExecutionData[][]>} Promise resolving to output data
306
+ */
307
+ async sendNotification() {
308
+ const items = this.getInputData();
309
+ const returnData = [];
310
+ const api = new index_1.TeamsApiClient(this);
311
+ await api.initialize();
312
+ for (let i = 0; i < items.length; i++) {
313
+ try {
314
+ // Get operation parameters
315
+ const title = this.getNodeParameter('title', i);
316
+ const message = this.getNodeParameter('message', i);
317
+ const recipientType = this.getNodeParameter('recipientType', i);
318
+ // Get options
319
+ const options = this.getNodeParameter('options', i, {});
320
+ const notificationType = options.notificationType || 'default';
321
+ const imageUrl = options.imageUrl;
322
+ const actionUrl = options.actionUrl;
323
+ const actionLabel = options.actionLabel || 'View Details';
324
+ // Get recipient-specific parameters
325
+ let teamId;
326
+ let channelId;
327
+ let userId;
328
+ if (recipientType === 'channel') {
329
+ teamId = this.getNodeParameter('teamId', i);
330
+ channelId = this.getNodeParameter('channelId', i);
331
+ }
332
+ else if (recipientType === 'chat') {
333
+ userId = this.getNodeParameter('userId', i);
334
+ }
335
+ // Create notification card from template with data binding
336
+ const notificationTemplate = utils_1.CardTemplates.notification();
337
+ const templateEngine = new ACData.Template(notificationTemplate);
338
+ // Prepare data for template
339
+ const cardData = {
340
+ title,
341
+ message,
342
+ notificationType,
343
+ imageUrl: imageUrl || undefined,
344
+ actionUrl: actionUrl || undefined,
345
+ actionLabel,
346
+ };
347
+ // Apply data binding
348
+ const boundCard = templateEngine.expand({ $root: cardData });
349
+ const cardString = JSON.stringify(boundCard);
350
+ // Prepare parameters for validation
351
+ const params = {
352
+ card: cardString,
353
+ recipientType,
354
+ teamId,
355
+ channelId,
356
+ userId,
357
+ };
358
+ // Validate parameters
359
+ validateCardParams(params, ['recipientType'], this, i);
360
+ // Send card based on recipient type
361
+ let response;
362
+ if (recipientType === 'channel') {
363
+ // Always handle auto-installation for channel
364
+ await (0, index_1.handleAutoInstall)(api, teamId, i, this);
365
+ // Send card to channel
366
+ response = await api.sendAdaptiveCardToChannel(teamId, channelId, cardString);
367
+ }
368
+ else {
369
+ // Always handle auto-installation for user
370
+ await (0, index_1.handleAutoInstall)(api, userId, i, this);
371
+ // Use the BotFrameworkApi directly to send the card in one operation
372
+ // This prevents sending an empty message followed by a card
373
+ response = await api.sendAdaptiveCardToUser(userId, cardString);
374
+ // Ensure we got a proper object response
375
+ response = (0, utils_1.ensureObjectResponse)(response);
376
+ }
377
+ // Ensure response is properly parsed before returning
378
+ returnData.push({
379
+ json: response,
380
+ pairedItem: { item: i },
381
+ });
382
+ }
383
+ catch (error) {
384
+ if (this.continueOnFail()) {
385
+ const errorMessage = error instanceof Error ? error.message : String(error);
386
+ returnData.push({
387
+ json: {
388
+ error: errorMessage,
389
+ },
390
+ pairedItem: { item: i },
391
+ });
392
+ continue;
393
+ }
394
+ throw error;
395
+ }
396
+ }
397
+ return [returnData];
398
+ },
399
+ /**
400
+ * Sends an approval card to a channel or chat
401
+ * @returns {Promise<INodeExecutionData[][]>} Promise resolving to output data
402
+ */
403
+ async sendApproval() {
404
+ const items = this.getInputData();
405
+ const returnData = [];
406
+ const api = new index_1.TeamsApiClient(this);
407
+ await api.initialize();
408
+ for (let i = 0; i < items.length; i++) {
409
+ try {
410
+ // Get operation parameters
411
+ const title = this.getNodeParameter('title', i);
412
+ const description = this.getNodeParameter('description', i);
413
+ const requestId = this.getNodeParameter('requestId', i);
414
+ const recipientType = this.getNodeParameter('recipientType', i);
415
+ // Get options
416
+ const options = this.getNodeParameter('options', i, {});
417
+ const requestedBy = options.requestedBy;
418
+ const dueDate = options.dueDate;
419
+ const additionalInfo = options.additionalInfo;
420
+ const approveLabel = options.approveLabel || 'Approve';
421
+ const rejectLabel = options.rejectLabel || 'Reject';
422
+ // Get recipient-specific parameters
423
+ let teamId;
424
+ let channelId;
425
+ let userId;
426
+ if (recipientType === 'channel') {
427
+ teamId = this.getNodeParameter('teamId', i);
428
+ channelId = this.getNodeParameter('channelId', i);
429
+ }
430
+ else if (recipientType === 'chat') {
431
+ userId = this.getNodeParameter('userId', i);
432
+ }
433
+ // Create approval card from template with data binding
434
+ const approvalTemplate = utils_1.CardTemplates.approval();
435
+ const templateEngine = new ACData.Template(approvalTemplate);
436
+ // Prepare data for template
437
+ const cardData = {
438
+ title,
439
+ description,
440
+ requestId,
441
+ requestedBy: requestedBy || undefined,
442
+ dueDate: dueDate || undefined,
443
+ additionalInfo: additionalInfo || undefined,
444
+ approveLabel,
445
+ rejectLabel,
446
+ };
447
+ // Apply data binding
448
+ const boundCard = templateEngine.expand({ $root: cardData });
449
+ const cardString = JSON.stringify(boundCard);
450
+ // Prepare parameters for validation
451
+ const params = {
452
+ card: cardString,
453
+ recipientType,
454
+ teamId,
455
+ channelId,
456
+ userId,
457
+ };
458
+ // Validate parameters
459
+ validateCardParams(params, ['recipientType'], this, i);
460
+ // Send card based on recipient type
461
+ let response;
462
+ if (recipientType === 'channel') {
463
+ // Always handle auto-installation for channel
464
+ await (0, index_1.handleAutoInstall)(api, teamId, i, this);
465
+ // Send card to channel
466
+ response = await api.sendAdaptiveCardToChannel(teamId, channelId, cardString);
467
+ }
468
+ else {
469
+ // Always handle auto-installation for user
470
+ await (0, index_1.handleAutoInstall)(api, userId, i, this);
471
+ // Use the BotFrameworkApi directly to send the card in one operation
472
+ // This prevents sending an empty message followed by a card
473
+ response = await api.sendAdaptiveCardToUser(userId, cardString);
474
+ // Ensure we got a proper object response
475
+ response = (0, utils_1.ensureObjectResponse)(response);
476
+ }
477
+ // Ensure response is properly parsed before returning
478
+ returnData.push({
479
+ json: response,
480
+ pairedItem: { item: i },
481
+ });
482
+ }
483
+ catch (error) {
484
+ if (this.continueOnFail()) {
485
+ const errorMessage = error instanceof Error ? error.message : String(error);
486
+ returnData.push({
487
+ json: {
488
+ error: errorMessage,
489
+ },
490
+ pairedItem: { item: i },
491
+ });
492
+ continue;
493
+ }
494
+ throw error;
495
+ }
496
+ }
497
+ return [returnData];
498
+ },
499
+ /**
500
+ * Updates an existing adaptive card in a conversation
501
+ */
502
+ async update() {
503
+ const items = this.getInputData();
504
+ const returnData = [];
505
+ const api = new index_1.TeamsApiClient(this);
506
+ await api.initialize();
507
+ for (let i = 0; i < items.length; i++) {
508
+ try {
509
+ // Get operation parameters
510
+ const conversationId = this.getNodeParameter('conversationId', i);
511
+ const activityId = this.getNodeParameter('activityId', i);
512
+ const cardJson = this.getNodeParameter('card', i);
513
+ // Validate parameters
514
+ validateCardParams({ card: cardJson }, ['card'], this, i);
515
+ // Update the card
516
+ const response = await api.updateCard(conversationId, activityId, cardJson);
517
+ // Ensure response is properly parsed before returning
518
+ returnData.push({
519
+ json: (0, utils_1.ensureObjectResponse)(response),
520
+ pairedItem: { item: i },
521
+ });
522
+ }
523
+ catch (error) {
524
+ if (this.continueOnFail()) {
525
+ const errorMessage = error instanceof Error ? error.message : String(error);
526
+ returnData.push({
527
+ json: {
528
+ error: errorMessage,
529
+ },
530
+ pairedItem: { item: i },
531
+ });
532
+ continue;
533
+ }
534
+ throw error;
535
+ }
536
+ }
537
+ return [returnData];
538
+ },
539
+ /**
540
+ * Updates an existing adaptive card in a channel
541
+ */
542
+ async updateInChannel() {
543
+ const items = this.getInputData();
544
+ const returnData = [];
545
+ const api = new index_1.TeamsApiClient(this);
546
+ await api.initialize();
547
+ for (let i = 0; i < items.length; i++) {
548
+ try {
549
+ // Get operation parameters
550
+ const teamId = this.getNodeParameter('teamId', i);
551
+ const channelId = this.getNodeParameter('channelId', i);
552
+ const activityId = this.getNodeParameter('activityId', i);
553
+ const cardJson = this.getNodeParameter('card', i);
554
+ // Validate parameters
555
+ validateCardParams({ card: cardJson }, ['card'], this, i);
556
+ // Update the card in the channel
557
+ const response = await api.updateAdaptiveCardInChannel(teamId, channelId, activityId, cardJson);
558
+ // Ensure response is properly parsed before returning
559
+ returnData.push({
560
+ json: (0, utils_1.ensureObjectResponse)(response),
561
+ pairedItem: { item: i },
562
+ });
563
+ }
564
+ catch (error) {
565
+ if (this.continueOnFail()) {
566
+ const errorMessage = error instanceof Error ? error.message : String(error);
567
+ returnData.push({
568
+ json: {
569
+ error: errorMessage,
570
+ },
571
+ pairedItem: { item: i },
572
+ });
573
+ continue;
574
+ }
575
+ throw error;
576
+ }
577
+ }
578
+ return [returnData];
579
+ },
580
+ /**
581
+ * Processes card action data from user interactions
582
+ * Enhanced to extract user info, timestamp, and conversation context from trigger data
583
+ */
584
+ async processAction() {
585
+ const items = this.getInputData();
586
+ const returnData = [];
587
+ for (let i = 0; i < items.length; i++) {
588
+ try {
589
+ // Get action data from the trigger or input
590
+ const actionData = this.getNodeParameter('actionData', i, '');
591
+ if (!actionData) {
592
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No action data provided. This operation should be used with card action triggers.', { itemIndex: i });
593
+ }
594
+ let parsedActionData;
595
+ try {
596
+ parsedActionData = JSON.parse(actionData);
597
+ }
598
+ catch (error) {
599
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid action data JSON: ${error instanceof Error ? error.message : String(error)}`, { itemIndex: i });
600
+ }
601
+ // Get input item data (from trigger node) to extract additional metadata
602
+ const inputItem = items[i];
603
+ const inputJson = (inputItem === null || inputItem === void 0 ? void 0 : inputItem.json) || {};
604
+ // Type guard helper for IDataObject
605
+ const isDataObject = (value) => {
606
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
607
+ };
608
+ // Extract user information from trigger data
609
+ // Teams Bot Framework sends user info in resourceData.from or activity.from
610
+ const userInfo = {};
611
+ const resourceData = isDataObject(inputJson.resourceData) ? inputJson.resourceData : {};
612
+ const from = isDataObject(resourceData.from) ? resourceData.from :
613
+ isDataObject(inputJson.from) ? inputJson.from :
614
+ isDataObject(parsedActionData.from) ? parsedActionData.from : {};
615
+ if (from.user || from.id) {
616
+ // Extract from Teams message format
617
+ const user = isDataObject(from.user) ? from.user : {};
618
+ userInfo.id = user.id || from.id || user.userIdentity;
619
+ userInfo.name = user.displayName || from.name || user.name;
620
+ userInfo.email = user.userIdentity || user.email || from.email;
621
+ userInfo.userPrincipalName = user.userPrincipalName || from.userPrincipalName;
622
+ }
623
+ else if (from.id) {
624
+ // Extract from Bot Framework activity format
625
+ userInfo.id = from.id;
626
+ userInfo.name = from.name;
627
+ }
628
+ // Extract timestamp from trigger data
629
+ // Prefer timestamp from trigger (actual action time) over current time
630
+ let actionTimestamp;
631
+ if (typeof resourceData.lastModifiedDateTime === 'string') {
632
+ actionTimestamp = resourceData.lastModifiedDateTime;
633
+ }
634
+ else if (typeof resourceData.createdDateTime === 'string') {
635
+ actionTimestamp = resourceData.createdDateTime;
636
+ }
637
+ else if (typeof inputJson.timestamp === 'string') {
638
+ actionTimestamp = inputJson.timestamp;
639
+ }
640
+ else if (typeof resourceData.timestamp === 'string') {
641
+ actionTimestamp = resourceData.timestamp;
642
+ }
643
+ else if (typeof parsedActionData.timestamp === 'string') {
644
+ actionTimestamp = parsedActionData.timestamp;
645
+ }
646
+ else {
647
+ // Fallback to current time if no timestamp available
648
+ actionTimestamp = new Date().toISOString();
649
+ }
650
+ // Extract conversation context from trigger data
651
+ const conversationContext = {};
652
+ const conversation = isDataObject(resourceData.conversation) ? resourceData.conversation :
653
+ isDataObject(inputJson.conversation) ? inputJson.conversation :
654
+ isDataObject(parsedActionData.conversation) ? parsedActionData.conversation : {};
655
+ if (conversation.id) {
656
+ conversationContext.id = conversation.id;
657
+ conversationContext.name = conversation.name;
658
+ conversationContext.isGroup = conversation.isGroup;
659
+ conversationContext.conversationType = conversation.conversationType;
660
+ }
661
+ // Extract message/activity context
662
+ const messageContext = {};
663
+ if (inputJson.messageId || resourceData.id) {
664
+ messageContext.messageId = inputJson.messageId || resourceData.id;
665
+ }
666
+ if (inputJson.activityId || resourceData.id) {
667
+ messageContext.activityId = inputJson.activityId || resourceData.id;
668
+ }
669
+ if (resourceData.replyToId || inputJson.replyToId) {
670
+ messageContext.replyToId = resourceData.replyToId || inputJson.replyToId;
671
+ }
672
+ // Extract team/channel context if available
673
+ const contextInfo = {};
674
+ const channelIdentity = isDataObject(resourceData.channelIdentity) ? resourceData.channelIdentity : {};
675
+ if (inputJson.teamId || channelIdentity.teamId) {
676
+ contextInfo.teamId = inputJson.teamId || channelIdentity.teamId;
677
+ }
678
+ if (inputJson.channelId || channelIdentity.channelId) {
679
+ contextInfo.channelId = inputJson.channelId || channelIdentity.channelId;
680
+ }
681
+ if (inputJson.chatId || resourceData.chatId) {
682
+ contextInfo.chatId = inputJson.chatId || resourceData.chatId;
683
+ }
684
+ // Process the action data and return structured information with enhanced metadata
685
+ const processedAction = {
686
+ // Core action data
687
+ actionType: parsedActionData.type || 'submit',
688
+ actionId: parsedActionData.id || parsedActionData.actionId,
689
+ actionData: parsedActionData.data || parsedActionData.value || {},
690
+ // Enhanced metadata
691
+ timestamp: actionTimestamp,
692
+ // User information (if available from trigger)
693
+ user: Object.keys(userInfo).length > 0 ? userInfo : undefined,
694
+ // Conversation context (if available)
695
+ conversation: Object.keys(conversationContext).length > 0 ? conversationContext : undefined,
696
+ // Message context (if available)
697
+ message: Object.keys(messageContext).length > 0 ? messageContext : undefined,
698
+ // Team/channel context (if available)
699
+ context: Object.keys(contextInfo).length > 0 ? contextInfo : undefined,
700
+ // Original trigger event type (if available)
701
+ eventType: inputJson.eventType || resourceData.eventType || undefined,
702
+ };
703
+ // Remove undefined fields to keep output clean
704
+ Object.keys(processedAction).forEach(key => {
705
+ if (processedAction[key] === undefined) {
706
+ delete processedAction[key];
707
+ }
708
+ });
709
+ returnData.push({
710
+ json: processedAction,
711
+ pairedItem: { item: i },
712
+ });
713
+ }
714
+ catch (error) {
715
+ if (this.continueOnFail()) {
716
+ const errorMessage = error instanceof Error ? error.message : String(error);
717
+ returnData.push({
718
+ json: {
719
+ error: errorMessage,
720
+ },
721
+ pairedItem: { item: i },
722
+ });
723
+ continue;
724
+ }
725
+ throw error;
726
+ }
727
+ }
728
+ return [returnData];
729
+ },
730
+ };
731
+ //# sourceMappingURL=cards.js.map