n8n-nodes-msteams-botframework 1.0.0 → 1.1.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
CHANGED
|
@@ -4,13 +4,22 @@ Custom n8n node để tương tác với Microsoft Teams thông qua Azure Bot Fr
|
|
|
4
4
|
|
|
5
5
|
## Tính năng
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
### MS Teams Bot (Action Node)
|
|
8
8
|
- ✉️ Gửi tin nhắn text đến channel hoặc user
|
|
9
9
|
- 🎴 Gửi Adaptive Cards
|
|
10
10
|
- 💬 Reply vào tin nhắn cụ thể
|
|
11
11
|
- ✏️ Cập nhật tin nhắn đã gửi
|
|
12
12
|
- 🗑️ Xóa tin nhắn
|
|
13
13
|
|
|
14
|
+
### MS Teams Bot Trigger (NEW in v1.1.0) 🎣
|
|
15
|
+
- 📥 Nhận tin nhắn từ Teams qua webhook
|
|
16
|
+
- 👥 Nhận thông báo khi có người join/leave
|
|
17
|
+
- 👍 Nhận reactions vào tin nhắn
|
|
18
|
+
- ✏️ Nhận thông báo khi message được edit
|
|
19
|
+
- 🗑️ Nhận thông báo khi message bị xóa
|
|
20
|
+
- 🤖 Tự động filter bot messages
|
|
21
|
+
- ⌨️ Tự động gửi typing indicator
|
|
22
|
+
|
|
14
23
|
## Yêu cầu
|
|
15
24
|
|
|
16
25
|
- n8n version 0.187.0 trở lên
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { IHookFunctions, IWebhookFunctions, INodeType, INodeTypeDescription, IWebhookResponseData } from 'n8n-workflow';
|
|
2
|
+
export declare class MsTeamsBotFrameworkTrigger implements INodeType {
|
|
3
|
+
description: INodeTypeDescription;
|
|
4
|
+
webhookMethods: {
|
|
5
|
+
default: {
|
|
6
|
+
checkExists(this: IHookFunctions): Promise<boolean>;
|
|
7
|
+
create(this: IHookFunctions): Promise<boolean>;
|
|
8
|
+
delete(this: IHookFunctions): Promise<boolean>;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
webhook(this: IWebhookFunctions): Promise<IWebhookResponseData>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MsTeamsBotFrameworkTrigger = void 0;
|
|
4
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
+
const botbuilder_1 = require("botbuilder");
|
|
6
|
+
class MsTeamsBotFrameworkTrigger {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.description = {
|
|
9
|
+
displayName: 'MS Teams Bot Trigger',
|
|
10
|
+
name: 'msTeamsBotFrameworkTrigger',
|
|
11
|
+
icon: 'file:msteams.svg',
|
|
12
|
+
group: ['trigger'],
|
|
13
|
+
version: 1,
|
|
14
|
+
subtitle: 'Receive MS Teams messages',
|
|
15
|
+
description: 'Receive messages and events from MS Teams via webhook',
|
|
16
|
+
defaults: {
|
|
17
|
+
name: 'MS Teams Bot Trigger',
|
|
18
|
+
},
|
|
19
|
+
inputs: [],
|
|
20
|
+
outputs: ['main'],
|
|
21
|
+
credentials: [
|
|
22
|
+
{
|
|
23
|
+
name: 'msTeamsBotFrameworkApi',
|
|
24
|
+
required: true,
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
webhooks: [
|
|
28
|
+
{
|
|
29
|
+
name: 'default',
|
|
30
|
+
httpMethod: 'POST',
|
|
31
|
+
responseMode: 'onReceived',
|
|
32
|
+
path: 'webhook',
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
properties: [
|
|
36
|
+
{
|
|
37
|
+
displayName: 'Events',
|
|
38
|
+
name: 'events',
|
|
39
|
+
type: 'multiOptions',
|
|
40
|
+
options: [
|
|
41
|
+
{
|
|
42
|
+
name: 'Message Received',
|
|
43
|
+
value: 'message',
|
|
44
|
+
description: 'Trigger when a message is received',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: 'Conversation Update',
|
|
48
|
+
value: 'conversationUpdate',
|
|
49
|
+
description: 'Trigger when someone joins/leaves conversation',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: 'Message Reaction',
|
|
53
|
+
value: 'messageReaction',
|
|
54
|
+
description: 'Trigger when someone reacts to a message',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'Message Update',
|
|
58
|
+
value: 'messageUpdate',
|
|
59
|
+
description: 'Trigger when a message is updated',
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: 'Message Delete',
|
|
63
|
+
value: 'messageDelete',
|
|
64
|
+
description: 'Trigger when a message is deleted',
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
default: ['message'],
|
|
68
|
+
required: true,
|
|
69
|
+
description: 'The events to listen to',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
displayName: 'Options',
|
|
73
|
+
name: 'options',
|
|
74
|
+
type: 'collection',
|
|
75
|
+
placeholder: 'Add Option',
|
|
76
|
+
default: {},
|
|
77
|
+
options: [
|
|
78
|
+
{
|
|
79
|
+
displayName: 'Ignore Bot Messages',
|
|
80
|
+
name: 'ignoreBotMessages',
|
|
81
|
+
type: 'boolean',
|
|
82
|
+
default: true,
|
|
83
|
+
description: 'Whether to ignore messages from bots',
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
displayName: 'Include Raw Activity',
|
|
87
|
+
name: 'includeRawActivity',
|
|
88
|
+
type: 'boolean',
|
|
89
|
+
default: false,
|
|
90
|
+
description: 'Whether to include the raw Bot Framework activity in output',
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
displayName: 'Auto Reply',
|
|
94
|
+
name: 'autoReply',
|
|
95
|
+
type: 'boolean',
|
|
96
|
+
default: false,
|
|
97
|
+
description: 'Whether to automatically send a typing indicator',
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
};
|
|
103
|
+
this.webhookMethods = {
|
|
104
|
+
default: {
|
|
105
|
+
async checkExists() {
|
|
106
|
+
return true;
|
|
107
|
+
},
|
|
108
|
+
async create() {
|
|
109
|
+
return true;
|
|
110
|
+
},
|
|
111
|
+
async delete() {
|
|
112
|
+
return true;
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
async webhook() {
|
|
118
|
+
const credentials = await this.getCredentials('msTeamsBotFrameworkApi');
|
|
119
|
+
const req = this.getRequestObject();
|
|
120
|
+
const events = this.getNodeParameter('events', []);
|
|
121
|
+
const options = this.getNodeParameter('options', {});
|
|
122
|
+
const appId = credentials.appId;
|
|
123
|
+
const appPassword = credentials.appPassword;
|
|
124
|
+
// Create Bot Framework Adapter
|
|
125
|
+
const adapter = new botbuilder_1.BotFrameworkAdapter({
|
|
126
|
+
appId,
|
|
127
|
+
appPassword,
|
|
128
|
+
});
|
|
129
|
+
// Process the incoming activity
|
|
130
|
+
let activityData = null;
|
|
131
|
+
let shouldTrigger = false;
|
|
132
|
+
try {
|
|
133
|
+
await adapter.processActivity(req, req.res, async (context) => {
|
|
134
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
135
|
+
const activity = context.activity;
|
|
136
|
+
// Check if we should process this activity type
|
|
137
|
+
if (!events.includes(activity.type)) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
// Ignore bot messages if configured
|
|
141
|
+
if (options.ignoreBotMessages && ((_a = activity.from) === null || _a === void 0 ? void 0 : _a.role) === 'bot') {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
shouldTrigger = true;
|
|
145
|
+
// Send typing indicator if auto reply is enabled
|
|
146
|
+
if (options.autoReply && activity.type === 'message') {
|
|
147
|
+
await context.sendActivity({ type: 'typing' });
|
|
148
|
+
}
|
|
149
|
+
// Extract useful data from activity
|
|
150
|
+
activityData = {
|
|
151
|
+
type: activity.type,
|
|
152
|
+
text: activity.text,
|
|
153
|
+
timestamp: activity.timestamp,
|
|
154
|
+
id: activity.id,
|
|
155
|
+
conversation: {
|
|
156
|
+
id: (_b = activity.conversation) === null || _b === void 0 ? void 0 : _b.id,
|
|
157
|
+
name: (_c = activity.conversation) === null || _c === void 0 ? void 0 : _c.name,
|
|
158
|
+
conversationType: (_d = activity.conversation) === null || _d === void 0 ? void 0 : _d.conversationType,
|
|
159
|
+
tenantId: (_e = activity.conversation) === null || _e === void 0 ? void 0 : _e.tenantId,
|
|
160
|
+
},
|
|
161
|
+
from: {
|
|
162
|
+
id: (_f = activity.from) === null || _f === void 0 ? void 0 : _f.id,
|
|
163
|
+
name: (_g = activity.from) === null || _g === void 0 ? void 0 : _g.name,
|
|
164
|
+
aadObjectId: (_h = activity.from) === null || _h === void 0 ? void 0 : _h.aadObjectId,
|
|
165
|
+
role: (_j = activity.from) === null || _j === void 0 ? void 0 : _j.role,
|
|
166
|
+
},
|
|
167
|
+
recipient: {
|
|
168
|
+
id: (_k = activity.recipient) === null || _k === void 0 ? void 0 : _k.id,
|
|
169
|
+
name: (_l = activity.recipient) === null || _l === void 0 ? void 0 : _l.name,
|
|
170
|
+
},
|
|
171
|
+
channelId: activity.channelId,
|
|
172
|
+
serviceUrl: activity.serviceUrl,
|
|
173
|
+
locale: activity.locale,
|
|
174
|
+
};
|
|
175
|
+
// Add type-specific data
|
|
176
|
+
switch (activity.type) {
|
|
177
|
+
case 'message':
|
|
178
|
+
activityData.message = {
|
|
179
|
+
text: activity.text,
|
|
180
|
+
textFormat: activity.textFormat,
|
|
181
|
+
attachments: activity.attachments,
|
|
182
|
+
mentions: (_m = activity.entities) === null || _m === void 0 ? void 0 : _m.filter((e) => e.type === 'mention'),
|
|
183
|
+
};
|
|
184
|
+
break;
|
|
185
|
+
case 'conversationUpdate':
|
|
186
|
+
activityData.conversationUpdate = {
|
|
187
|
+
membersAdded: activity.membersAdded,
|
|
188
|
+
membersRemoved: activity.membersRemoved,
|
|
189
|
+
};
|
|
190
|
+
break;
|
|
191
|
+
case 'messageReaction':
|
|
192
|
+
activityData.messageReaction = {
|
|
193
|
+
reactionsAdded: activity.reactionsAdded,
|
|
194
|
+
reactionsRemoved: activity.reactionsRemoved,
|
|
195
|
+
replyToId: activity.replyToId,
|
|
196
|
+
};
|
|
197
|
+
break;
|
|
198
|
+
case 'messageUpdate':
|
|
199
|
+
activityData.messageUpdate = {
|
|
200
|
+
text: activity.text,
|
|
201
|
+
updatedText: activity.text,
|
|
202
|
+
};
|
|
203
|
+
break;
|
|
204
|
+
case 'messageDelete':
|
|
205
|
+
activityData.messageDelete = {
|
|
206
|
+
deletedMessageId: activity.id,
|
|
207
|
+
};
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
// Include raw activity if requested
|
|
211
|
+
if (options.includeRawActivity) {
|
|
212
|
+
activityData.rawActivity = activity;
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
if (!shouldTrigger) {
|
|
216
|
+
// Return empty response if we shouldn't trigger
|
|
217
|
+
return {
|
|
218
|
+
workflowData: [],
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
// Return the activity data to the workflow
|
|
222
|
+
return {
|
|
223
|
+
workflowData: [
|
|
224
|
+
[
|
|
225
|
+
{
|
|
226
|
+
json: activityData,
|
|
227
|
+
},
|
|
228
|
+
],
|
|
229
|
+
],
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
catch (error) {
|
|
233
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to process Teams webhook: ${error.message}`, {
|
|
234
|
+
description: error.message,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
exports.MsTeamsBotFrameworkTrigger = MsTeamsBotFrameworkTrigger;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-msteams-botframework",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "n8n node for MS Teams Azure Bot Framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"n8n-community-node-package",
|
|
@@ -38,7 +38,8 @@
|
|
|
38
38
|
"dist/credentials/MsTeamsBotFrameworkApi.credentials.js"
|
|
39
39
|
],
|
|
40
40
|
"nodes": [
|
|
41
|
-
"dist/nodes/MsTeamsBotFramework/MsTeamsBotFramework.node.js"
|
|
41
|
+
"dist/nodes/MsTeamsBotFramework/MsTeamsBotFramework.node.js",
|
|
42
|
+
"dist/nodes/MsTeamsBotFramework/MsTeamsBotFrameworkTrigger.node.js"
|
|
42
43
|
]
|
|
43
44
|
},
|
|
44
45
|
"devDependencies": {
|