n8n-nodes-pragma-bitrix24 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 (51) hide show
  1. package/LICENSE +51 -0
  2. package/README.md +340 -0
  3. package/dist/credentials/Bitrix24Api.credentials.js +55 -0
  4. package/dist/nodes/Bitrix24/Bitrix24.node.js +1410 -0
  5. package/dist/nodes/Bitrix24/Company.js +17 -0
  6. package/dist/nodes/Bitrix24/Contact.js +31 -0
  7. package/dist/nodes/Bitrix24/Deal.js +17 -0
  8. package/dist/nodes/Bitrix24/Helpers.js +300 -0
  9. package/dist/nodes/Bitrix24/Lead.js +17 -0
  10. package/dist/nodes/Bitrix24/SmartProcess.js +1 -0
  11. package/dist/nodes/Bitrix24/bitrix24.svg +7 -0
  12. package/dist/nodes/Bitrix24/types.js +58 -0
  13. package/dist/nodes/Bitrix24AI/Bitrix24AI.node.js +205 -0
  14. package/dist/nodes/Bitrix24App/Bitrix24App.node.js +179 -0
  15. package/dist/nodes/Bitrix24Auxiliary/Bitrix24Auxiliary.node.js +566 -0
  16. package/dist/nodes/Bitrix24Booking/Bitrix24Booking.node.js +871 -0
  17. package/dist/nodes/Bitrix24Calendar/Bitrix24Calendar.node.js +471 -0
  18. package/dist/nodes/Bitrix24ChatBot/Bitrix24ChatBot.node.js +522 -0
  19. package/dist/nodes/Bitrix24Commerce/Bitrix24Commerce.node.js +431 -0
  20. package/dist/nodes/Bitrix24Department/Bitrix24Department.node.js +317 -0
  21. package/dist/nodes/Bitrix24Disk/Bitrix24Disk.node.js +334 -0
  22. package/dist/nodes/Bitrix24Document/Bitrix24Document.node.js +280 -0
  23. package/dist/nodes/Bitrix24Entity/Bitrix24Entity.node.js +263 -0
  24. package/dist/nodes/Bitrix24Group/Bitrix24Group.node.js +327 -0
  25. package/dist/nodes/Bitrix24Lists/Bitrix24Lists.node.js +406 -0
  26. package/dist/nodes/Bitrix24Log/Bitrix24Log.node.js +309 -0
  27. package/dist/nodes/Bitrix24Mail/Bitrix24Mail.node.js +109 -0
  28. package/dist/nodes/Bitrix24MessageService/Bitrix24MessageService.node.js +218 -0
  29. package/dist/nodes/Bitrix24OpenChannels/Bitrix24OpenChannels.node.js +379 -0
  30. package/dist/nodes/Bitrix24PaySystem/Bitrix24PaySystem.node.js +241 -0
  31. package/dist/nodes/Bitrix24Pipeline/Bitrix24Pipeline.node.js +553 -0
  32. package/dist/nodes/Bitrix24Pipeline/bitrix24.svg +7 -0
  33. package/dist/nodes/Bitrix24Sale/Bitrix24Sale.node.js +391 -0
  34. package/dist/nodes/Bitrix24Scrum/Bitrix24Scrum.node.js +555 -0
  35. package/dist/nodes/Bitrix24Scrum/bitrix24.svg +7 -0
  36. package/dist/nodes/Bitrix24Sign/Bitrix24Sign.node.js +132 -0
  37. package/dist/nodes/Bitrix24Social/Bitrix24Social.node.js +224 -0
  38. package/dist/nodes/Bitrix24Task/Bitrix24Task.node.js +444 -0
  39. package/dist/nodes/Bitrix24Telephony/Bitrix24Telephony.node.js +511 -0
  40. package/dist/nodes/Bitrix24Timeman/Bitrix24Timeman.node.js +196 -0
  41. package/dist/nodes/Bitrix24Tool/Bitrix24Tool.node.js +1035 -0
  42. package/dist/nodes/Bitrix24Tool/bitrix24.svg +7 -0
  43. package/dist/nodes/Bitrix24Trigger/Bitrix24Trigger.node.js +184 -0
  44. package/dist/nodes/Bitrix24User/Bitrix24User.node.js +351 -0
  45. package/dist/nodes/Bitrix24UserField/Bitrix24UserField.node.js +386 -0
  46. package/dist/nodes/Bitrix24UserField/bitrix24.svg +7 -0
  47. package/dist/nodes/shared/bitrix24.svg +7 -0
  48. package/dist/nodes/shared/localization.js +189 -0
  49. package/dist/nodes/shared/types.js +22 -0
  50. package/index.js +10 -0
  51. package/package.json +108 -0
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg width="32px" height="32px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg">
3
+ <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
4
+ <path d="M16,0 C24.8365,0 32,7.1635 32,16 C32,24.8365 24.8365,32 16,32 C7.1635,32 0,24.8365 0,16 C0,7.1635 7.1635,0 16,0" fill="#2FC7F7"/>
5
+ <path d="M13.3333,8 L18.6667,8 C21.6122,8 24,10.3878 24,13.3333 L24,18.6667 C24,21.6122 21.6122,24 18.6667,24 L13.3333,24 C10.3878,24 8,21.6122 8,18.6667 L8,13.3333 C8,10.3878 10.3878,8 13.3333,8" fill="#FFFFFF"/>
6
+ </g>
7
+ </svg>
@@ -0,0 +1,184 @@
1
+ "use strict";
2
+ /**
3
+ * Bitrix24 Trigger — Нода триггера событий
4
+ *
5
+ * Bitrix24 PRAGMA.by nodes for n8n
6
+ * Профессиональная интеграция с Битрикс24.
7
+ *
8
+ * @author PRAGMA & Азбука Решений
9
+ * @copyright 2026 PRAGMA (https://pragma.by/) & Азбука Решений (https://abc-solution.ru/)
10
+ *
11
+ * Контакты:
12
+ * 🇧🇾 PRAGMA: +375 (44) 702-70-90 | https://pragma.by/
13
+ * 🇷🇺 Азбука Решений: +7 (939) 555-19-60 | https://abc-solution.ru/
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.Bitrix24Trigger = void 0;
17
+ class Bitrix24Trigger {
18
+ constructor() {
19
+ this.description = {
20
+ displayName: 'Bitrix24 Триггер',
21
+ name: 'bitrix24Trigger',
22
+ icon: 'file:bitrix24.svg',
23
+ group: ['trigger'],
24
+ version: 1,
25
+ description: 'Получение событий из Битрикс24: CRM, задачи, диск и другие',
26
+ defaults: {
27
+ name: 'Bitrix24 Триггер',
28
+ },
29
+ inputs: [],
30
+ outputs: ['main'],
31
+ webhooks: [
32
+ {
33
+ name: 'default',
34
+ httpMethod: 'POST',
35
+ responseMode: 'onReceived',
36
+ path: 'webhook',
37
+ },
38
+ ],
39
+ properties: [
40
+ {
41
+ displayName: 'Events',
42
+ name: 'events',
43
+ type: 'multiOptions',
44
+ options: [
45
+ { name: 'On Bot Message Add', value: 'ONIMBOTMESSAGEADD' },
46
+ { name: 'On App Install', value: 'ONAPPINSTALL' },
47
+ { name: 'On Bot Join Chat', value: 'ONIMBOTJOINCHAT' },
48
+ { name: 'On Bot Delete', value: 'ONIMBOTDELETE' },
49
+ { name: 'On Bot Command Add', value: 'ONIMCOMMANDADD' },
50
+ { name: 'Custom (Advanced)', value: 'custom' },
51
+ ],
52
+ default: ['ONIMBOTMESSAGEADD', 'ONAPPINSTALL'],
53
+ required: true,
54
+ description: 'Select events to listen to',
55
+ },
56
+ {
57
+ displayName: 'Custom Event Name',
58
+ name: 'customEvent',
59
+ type: 'string',
60
+ default: '',
61
+ displayOptions: { show: { events: ['custom'] } },
62
+ description: 'Enter the exact Bitrix24 event name (e.g. ONCRMDEALADD, ONTASKADD). Case sensitive.',
63
+ },
64
+ {
65
+ displayName: 'Application Token (Verification)',
66
+ name: 'appToken',
67
+ type: 'string',
68
+ typeOptions: { password: true },
69
+ default: '',
70
+ description: 'Secret token from Bitrix24 App settings to verify request authenticity (Recommended)',
71
+ },
72
+ ],
73
+ };
74
+ }
75
+ async webhook() {
76
+ const req = this.getRequestObject();
77
+ const body = req.body;
78
+ // Security Check
79
+ const appToken = this.getNodeParameter('appToken', '');
80
+ if (appToken) {
81
+ const incomingToken = body.auth?.application_token || body.data?.application_token || body.application_token;
82
+ if (incomingToken !== appToken) {
83
+ // Invalid token
84
+ return {}; // Silent reject or throw error? Silent is better for security to not leak info.
85
+ }
86
+ }
87
+ // Extract event name (Bitrix sends it as 'event')
88
+ const event = body.event;
89
+ // Check if we care about this event
90
+ const events = this.getNodeParameter('events');
91
+ let isMatch = events.includes(event);
92
+ if (!isMatch && events.includes('custom')) {
93
+ const customEvent = this.getNodeParameter('customEvent', '');
94
+ if (customEvent && customEvent === event) {
95
+ isMatch = true;
96
+ }
97
+ }
98
+ if (!isMatch) {
99
+ return {}; // Ignore
100
+ }
101
+ // Helper to flatten/clean bitrix weird payload like "data[PARAMS][MESSAGE]"
102
+ const parseBitrixPayload = (raw) => {
103
+ const result = { raw };
104
+ // Extract Auth usually present in all events
105
+ if (raw.auth) {
106
+ result.auth = raw.auth; // access_token, expires, application_token, etc.
107
+ }
108
+ else {
109
+ // Try to find flat auth keys
110
+ result.auth = {};
111
+ Object.keys(raw).forEach(k => {
112
+ if (k.startsWith('auth[')) {
113
+ const subKey = k.match(/auth\[(.*?)\]/)?.[1];
114
+ if (subKey)
115
+ result.auth[subKey] = raw[k];
116
+ }
117
+ });
118
+ }
119
+ // Extract Data
120
+ if (raw.data) {
121
+ // If nested object
122
+ if (typeof raw.data === 'object') {
123
+ result.data = raw.data;
124
+ }
125
+ }
126
+ else {
127
+ // Flat data
128
+ result.data = {};
129
+ Object.keys(raw).forEach(k => {
130
+ if (k.startsWith('data[')) {
131
+ // Simple flattener logic could be complex due to nesting data[PARAMS][MESSAGE]
132
+ // For now, let's keep it somewhat raw or simple flat
133
+ result.data[k] = raw[k];
134
+ }
135
+ });
136
+ }
137
+ // Optimized Parsing for ONIMBOTMESSAGEADD
138
+ if (event === 'ONIMBOTMESSAGEADD') {
139
+ // Try to extract MESSAGE, DIALOG_ID, etc.
140
+ // Usually data[PARAMS][MESSAGE]
141
+ const getParam = (name) => {
142
+ return raw.data?.PARAMS?.[name] || raw[`data[PARAMS][${name}]`];
143
+ };
144
+ result.message = getParam('MESSAGE');
145
+ result.dialog_id = getParam('DIALOG_ID');
146
+ result.chat_id = getParam('CHAT_ID');
147
+ result.bot_id = raw.data?.BOT?.[Object.keys(raw.data?.BOT || {})[0]]?.BOT_ID
148
+ || Object.keys(raw).find(k => k.includes('[BOT_ID]')) ? raw[Object.keys(raw).find(k => k.includes('[BOT_ID]'))] : undefined;
149
+ // Files Parsing could be added here
150
+ }
151
+ else if (event === 'ONAPPINSTALL') {
152
+ result.auth_code = raw.auth?.code || result.auth.code;
153
+ }
154
+ else {
155
+ // Generic Parsing for Custom Events (CRM, Tasks, etc.)
156
+ // Usually data[FIELDS][ID] or data[ID]
157
+ if (result.data?.FIELDS) {
158
+ Object.assign(result, result.data.FIELDS);
159
+ }
160
+ // Flatten data[...] keys for generic access
161
+ Object.keys(raw).forEach(k => {
162
+ if (k.startsWith('data[')) {
163
+ const subKey = k.match(/data\[(.*?)\]/)?.[1];
164
+ if (subKey && !result[subKey])
165
+ result[subKey] = raw[k];
166
+ }
167
+ });
168
+ }
169
+ return result;
170
+ };
171
+ const returnData = parseBitrixPayload(body);
172
+ returnData.event = event;
173
+ return {
174
+ workflowData: [
175
+ [
176
+ {
177
+ json: returnData,
178
+ },
179
+ ],
180
+ ],
181
+ };
182
+ }
183
+ }
184
+ exports.Bitrix24Trigger = Bitrix24Trigger;
@@ -0,0 +1,351 @@
1
+ "use strict";
2
+ /**
3
+ * Bitrix24 User — Нода управления пользователями
4
+ *
5
+ * Bitrix24 PRAGMA.by nodes for n8n
6
+ * Профессиональная интеграция с Битрикс24.
7
+ *
8
+ * @author PRAGMA & Азбука Решений
9
+ * @copyright 2026 PRAGMA (https://pragma.by/) & Азбука Решений (https://abc-solution.ru/)
10
+ *
11
+ * Контакты:
12
+ * 🇧🇾 PRAGMA: +375 (44) 702-70-90 | https://pragma.by/
13
+ * 🇷🇺 Азбука Решений: +7 (939) 555-19-60 | https://abc-solution.ru/
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.Bitrix24User = void 0;
17
+ const n8n_workflow_1 = require("n8n-workflow");
18
+ const Helpers_1 = require("../Bitrix24/Helpers");
19
+ class Bitrix24User {
20
+ constructor() {
21
+ this.description = {
22
+ displayName: 'Bitrix24 Пользователи',
23
+ name: 'bitrix24User',
24
+ icon: 'file:bitrix24.svg',
25
+ group: ['transform'],
26
+ version: 1,
27
+ subtitle: '={{$parameter["resource"] + ": " + $parameter["operation"]}}',
28
+ description: 'Управление пользователями, группами и оргструктурой в Битрикс24',
29
+ defaults: {
30
+ name: 'Bitrix24 Пользователи',
31
+ },
32
+ inputs: ['main'],
33
+ outputs: ['main'],
34
+ credentials: [
35
+ {
36
+ name: 'bitrix24Api',
37
+ required: true,
38
+ },
39
+ ],
40
+ properties: [
41
+ {
42
+ displayName: 'Ресурс',
43
+ name: 'resource',
44
+ type: 'options',
45
+ noDataExpression: true,
46
+ options: [
47
+ {
48
+ name: 'Пользователь',
49
+ value: 'user',
50
+ description: 'Сотрудники компании: поиск, профили, фильтрация',
51
+ },
52
+ {
53
+ name: 'Рабочая группа',
54
+ value: 'sonet_group',
55
+ description: 'Социальные группы и проекты',
56
+ },
57
+ {
58
+ name: 'Отдел',
59
+ value: 'department',
60
+ description: 'Организационная структура компании',
61
+ },
62
+ {
63
+ name: 'График отсутствия',
64
+ value: 'absence',
65
+ description: 'Отпуска, больничные, командировки',
66
+ },
67
+ ],
68
+ default: 'user',
69
+ required: true,
70
+ },
71
+ {
72
+ displayName: 'Операция',
73
+ name: 'operation',
74
+ type: 'options',
75
+ noDataExpression: true,
76
+ options: [
77
+ {
78
+ name: 'Получить',
79
+ value: 'get',
80
+ action: 'Получить пользователя или группу',
81
+ description: 'Получить данные по ID',
82
+ displayOptions: {
83
+ show: {
84
+ resource: ['user', 'sonet_group'],
85
+ },
86
+ },
87
+ },
88
+ {
89
+ name: 'Создать',
90
+ value: 'create',
91
+ action: 'Create/Invite a user',
92
+ displayOptions: {
93
+ show: {
94
+ resource: ['user'],
95
+ },
96
+ },
97
+ },
98
+ {
99
+ name: 'Invite',
100
+ value: 'invite',
101
+ action: 'Invite a user',
102
+ description: 'Add user and send invitation',
103
+ displayOptions: {
104
+ show: {
105
+ resource: ['user'],
106
+ },
107
+ },
108
+ },
109
+ {
110
+ name: 'Get Current',
111
+ value: 'getCurrent',
112
+ action: 'Get current user',
113
+ displayOptions: {
114
+ show: {
115
+ resource: ['user'],
116
+ },
117
+ },
118
+ },
119
+ {
120
+ name: 'Update',
121
+ value: 'update',
122
+ action: 'Update a user',
123
+ displayOptions: {
124
+ show: {
125
+ resource: ['user'],
126
+ },
127
+ },
128
+ },
129
+ {
130
+ name: 'Delete',
131
+ value: 'delete',
132
+ action: 'Delete a user',
133
+ displayOptions: {
134
+ show: {
135
+ resource: ['user'],
136
+ },
137
+ },
138
+ },
139
+ {
140
+ name: 'Search',
141
+ value: 'search',
142
+ action: 'Search users or groups',
143
+ displayOptions: {
144
+ show: {
145
+ resource: ['user', 'sonet_group'],
146
+ },
147
+ },
148
+ },
149
+ {
150
+ name: 'Get All',
151
+ value: 'getAll',
152
+ action: 'Get all departments',
153
+ displayOptions: {
154
+ show: {
155
+ resource: ['department'],
156
+ },
157
+ },
158
+ },
159
+ ],
160
+ default: 'get',
161
+ required: true,
162
+ },
163
+ {
164
+ displayName: 'ID',
165
+ name: 'id',
166
+ type: 'string',
167
+ default: '',
168
+ required: true,
169
+ displayOptions: {
170
+ show: {
171
+ operation: ['get', 'update', 'delete'],
172
+ },
173
+ },
174
+ description: 'ID of the user or group',
175
+ },
176
+ // User Create/Update Fields
177
+ {
178
+ displayName: 'Email',
179
+ name: 'email',
180
+ type: 'string',
181
+ default: '',
182
+ displayOptions: { show: { resource: ['user'], operation: ['create', 'update'] } },
183
+ required: true, // Required for create usually
184
+ },
185
+ {
186
+ displayName: 'Extranet',
187
+ name: 'extranet',
188
+ type: 'boolean',
189
+ default: false,
190
+ displayOptions: { show: { resource: ['user'], operation: ['create'] } },
191
+ description: 'Is extranet user?',
192
+ },
193
+ {
194
+ displayName: 'First Name',
195
+ name: 'name',
196
+ type: 'string',
197
+ default: '',
198
+ displayOptions: { show: { resource: ['user'], operation: ['update'] } },
199
+ },
200
+ {
201
+ displayName: 'Last Name',
202
+ name: 'lastName',
203
+ type: 'string',
204
+ default: '',
205
+ displayOptions: { show: { resource: ['user'], operation: ['update'] } },
206
+ },
207
+ {
208
+ displayName: 'Departments',
209
+ name: 'userDepartments',
210
+ type: 'string',
211
+ default: '',
212
+ displayOptions: { show: { resource: ['user'], operation: ['update'] } },
213
+ description: 'Comma separated department IDs (e.g. 1,5)',
214
+ },
215
+ {
216
+ displayName: 'Start Date (Legacy)',
217
+ name: 'dateStart',
218
+ type: 'dateTime',
219
+ default: '',
220
+ displayOptions: {
221
+ show: {
222
+ resource: ['user'],
223
+ operation: ['search'],
224
+ },
225
+ },
226
+ description: 'Filter users by last update date (optional)',
227
+ },
228
+ {
229
+ displayName: 'Active Only',
230
+ name: 'active',
231
+ type: 'boolean',
232
+ default: true,
233
+ displayOptions: {
234
+ show: {
235
+ resource: ['user'],
236
+ operation: ['search'],
237
+ },
238
+ },
239
+ description: 'Whether to return only active users',
240
+ },
241
+ ],
242
+ };
243
+ }
244
+ async execute() {
245
+ const items = this.getInputData();
246
+ const returnData = [];
247
+ const resource = this.getNodeParameter('resource', 0);
248
+ const operation = this.getNodeParameter('operation', 0);
249
+ for (let i = 0; i < items.length; i++) {
250
+ try {
251
+ let endpoint = '';
252
+ let body = {};
253
+ if (resource === 'user') {
254
+ if (operation === 'get') {
255
+ endpoint = 'user.get';
256
+ const id = this.getNodeParameter('id', i);
257
+ body.ID = id;
258
+ }
259
+ else if (operation === 'getCurrent') {
260
+ endpoint = 'user.current';
261
+ }
262
+ else if (operation === 'create' || operation === 'invite') {
263
+ endpoint = 'user.add';
264
+ body.EMAIL = this.getNodeParameter('email', i);
265
+ body.EXTRANET = this.getNodeParameter('extranet', i) ? 'Y' : 'N';
266
+ }
267
+ else if (operation === 'update') {
268
+ endpoint = 'user.update';
269
+ body.ID = this.getNodeParameter('id', i);
270
+ const email = this.getNodeParameter('email', i);
271
+ if (email)
272
+ body.EMAIL = email;
273
+ const name = this.getNodeParameter('name', i);
274
+ if (name)
275
+ body.NAME = name;
276
+ const lastName = this.getNodeParameter('lastName', i);
277
+ if (lastName)
278
+ body.LAST_NAME = lastName;
279
+ const depts = this.getNodeParameter('userDepartments', i);
280
+ if (depts)
281
+ body.UF_DEPARTMENT = depts.split(',').map(d => parseInt(d.trim()));
282
+ }
283
+ else if (operation === 'delete') {
284
+ // user.delete checks rights. Often used just to fire (active=N)
285
+ // But here is explicit delete.
286
+ endpoint = 'user.delete';
287
+ body.ID = this.getNodeParameter('id', i);
288
+ }
289
+ else if (operation === 'search') {
290
+ endpoint = 'user.get'; // Best practice for search
291
+ const active = this.getNodeParameter('active', i);
292
+ if (active)
293
+ body.ACTIVE = 'Y';
294
+ }
295
+ }
296
+ else if (resource === 'sonet_group') {
297
+ if (operation === 'get') {
298
+ endpoint = 'sonet_group.get';
299
+ const id = this.getNodeParameter('id', i);
300
+ body = {
301
+ FILTER: { ID: id },
302
+ };
303
+ }
304
+ else if (operation === 'search') {
305
+ endpoint = 'sonet_group.get';
306
+ }
307
+ }
308
+ else if (resource === 'department') {
309
+ endpoint = 'department.get';
310
+ }
311
+ else if (resource === 'absence') {
312
+ endpoint = 'user.absence.get';
313
+ // Valid params: USER_ID, DATE_START, DATE_FINISH
314
+ // For now, simple list
315
+ }
316
+ if (!endpoint) {
317
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Operation ${operation} on ${resource} not implemented yet`);
318
+ }
319
+ const response = await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', endpoint + '.json', body);
320
+ let results = response.result;
321
+ if (Array.isArray(results)) {
322
+ for (const item of results) {
323
+ returnData.push({
324
+ json: item,
325
+ pairedItem: { item: i },
326
+ });
327
+ }
328
+ }
329
+ else {
330
+ returnData.push({
331
+ json: results,
332
+ pairedItem: { item: i },
333
+ });
334
+ }
335
+ }
336
+ catch (error) {
337
+ if (this.continueOnFail()) {
338
+ const err = error;
339
+ returnData.push({
340
+ json: { error: err.message },
341
+ pairedItem: { item: i },
342
+ });
343
+ continue;
344
+ }
345
+ throw error;
346
+ }
347
+ }
348
+ return [returnData];
349
+ }
350
+ }
351
+ exports.Bitrix24User = Bitrix24User;