@andrey4emk/npm-app-back-b24 3.3.1 → 3.4.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 +24 -3
- package/bitrix24/b24.ts +78 -29
- package/bitrix24/errTaskB24.ts +5 -7
- package/bitrix24/eventB24.ts +16 -14
- package/package.json +5 -6
- package/sendMessage/smsgold.ts +4 -3
package/README.md
CHANGED
|
@@ -35,6 +35,7 @@ import {
|
|
|
35
35
|
refreshAndSaveTokens,
|
|
36
36
|
reinitializeB24,
|
|
37
37
|
stopProactiveRefresh,
|
|
38
|
+
getResultData,
|
|
38
39
|
errorB24,
|
|
39
40
|
event,
|
|
40
41
|
Event,
|
|
@@ -118,14 +119,20 @@ const response = await fetchRetry("https://api.example.com/data", { method: "GET
|
|
|
118
119
|
|
|
119
120
|
**Retry при сетевых ошибках:**
|
|
120
121
|
|
|
121
|
-
Экземпляр `$b24` обёрнут Proxy, который автоматически повторяет запросы при сетевых ошибках. Повторные попытки применяются к методам `callMethod`, `callListMethod`, `callBatch
|
|
122
|
+
Экземпляр `$b24` обёрнут Proxy, который автоматически повторяет запросы при сетевых ошибках. Повторные попытки применяются к методам `callMethod`, `callListMethod`, `callBatch`, а также к обновлению токена (`refreshAuth`). Метод `fetchListMethod` из ретраев исключён — это async-генератор, оборачивать его в async-функцию нельзя; постраничные запросы SDK ретраит сам.
|
|
122
123
|
|
|
123
124
|
| Параметр | Значение |
|
|
124
125
|
| -------------- | ----------------------------------------- |
|
|
125
126
|
| Попыток | 5 |
|
|
126
|
-
| Задержка | 500 мс (
|
|
127
|
+
| Задержка | 500 мс (линейно растущая для refreshAuth) |
|
|
127
128
|
|
|
128
|
-
Retry срабатывает только при сетевых проблемах (`ECONNRESET`, `ETIMEDOUT`, `ERR_NETWORK` и т.д.). HTTP-ошибки (400, 500) и ошибки бизнес-логики Bitrix24 **не** вызывают повторных попыток. Каждая неудачная попытка логируется через `logs.add()` с уровнем `error
|
|
129
|
+
Retry срабатывает только при сетевых проблемах (`ECONNRESET`, `ETIMEDOUT`, `ERR_NETWORK` и т.д.). HTTP-ошибки (400, 500) и ошибки бизнес-логики Bitrix24 **не** вызывают повторных попыток. Каждая неудачная попытка логируется через `logs.add()` с уровнем `error` — в сообщение попадает код ошибки SDK.
|
|
130
|
+
|
|
131
|
+
У самого SDK есть собственный слой ретраев (`maxRetries: 3`), но он работает только при rate limit (HTTP 429, 503) и при распознанных `NETWORK_ERROR` / `REQUEST_TIMEOUT`. Замаскированные транспортные сбои приходят с кодом `JSSDK_UNKNOWN_ERROR`, который входит в `BUILT_IN_HARD_ERROR_CODES` — на таких ошибках SDK делает одну попытку, и повторяет только Proxy.
|
|
132
|
+
|
|
133
|
+
**«Мягкие» ошибки Bitrix24:**
|
|
134
|
+
|
|
135
|
+
Часть ошибок (`ERROR_ENTITY_NOT_FOUND`, `BITRIX_REST_V3_EXCEPTION_*`) SDK не бросает исключением, а возвращает как `AjaxResult` с ошибкой: `isSuccess === false`, и тогда `response.getData()` вернёт `undefined`. Отдельный случай — успешный ответ, у которого сам `result` пустой (`null`/`undefined`). Чтобы не падать на `undefined`, разбирайте ответы через `getResultData()` — он покрывает обе ситуации и бросает понятную ошибку с именем метода.
|
|
129
136
|
|
|
130
137
|
**Проактивное обновление токена:**
|
|
131
138
|
|
|
@@ -193,6 +200,20 @@ const response = await fetchRetry("https://api.example.com/data", { method: "GET
|
|
|
193
200
|
});
|
|
194
201
|
```
|
|
195
202
|
|
|
203
|
+
- **`getResultData(response, methodName)`** — достаёт `result` из ответа SDK. Если Bitrix24 вернул «мягкую» ошибку (`AjaxResult` с ошибкой вместо исключения) или пустой ответ, бросает `Error` с понятным текстом вместо падения на `undefined`.
|
|
204
|
+
|
|
205
|
+
- **Параметры:**
|
|
206
|
+
- `response` (AjaxResult) — результат `$b24.callMethod()`.
|
|
207
|
+
- `methodName` (string) — имя метода B24, попадёт в текст ошибки.
|
|
208
|
+
- **Возвращает:** содержимое `result`. Тип задаётся дженериком.
|
|
209
|
+
|
|
210
|
+
```js
|
|
211
|
+
import { $b24, getResultData } from "@andrey4emk/npm-app-back-b24";
|
|
212
|
+
|
|
213
|
+
const response = await $b24.callMethod("crm.deal.get", { id: 123 });
|
|
214
|
+
const deal = getResultData(response, "crm.deal.get");
|
|
215
|
+
```
|
|
216
|
+
|
|
196
217
|
### Задачи ошибок
|
|
197
218
|
|
|
198
219
|
- **`errorB24(dataTask)`** — создаёт служебную задачу в Bitrix24 при ошибках/событиях. Использует глобальный `$b24`.
|
package/bitrix24/b24.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { B24OAuth, AjaxError } from "@bitrix24/b24jssdk";
|
|
2
|
-
import type { B24OAuthParams, B24OAuthSecret, AuthData } from "@bitrix24/b24jssdk";
|
|
1
|
+
import { B24OAuth, AjaxError, SdkError, Logger } from "@bitrix24/b24jssdk";
|
|
2
|
+
import type { B24OAuthParams, B24OAuthSecret, AuthData, AjaxResult } from "@bitrix24/b24jssdk";
|
|
3
3
|
import { logs } from "../logs/logs.ts";
|
|
4
4
|
import { isNetworkError } from "../utils/fetchRetry.ts";
|
|
5
5
|
import Conf from "conf";
|
|
@@ -34,12 +34,15 @@ const RETRY_COUNT = 5;
|
|
|
34
34
|
/** Задержка между попытками (мс) */
|
|
35
35
|
const RETRY_DELAY_MS = 500;
|
|
36
36
|
|
|
37
|
-
/** Методы B24OAuth, оборачиваемые retry-логикой */
|
|
38
|
-
const RETRYABLE_METHODS = new Set(["callMethod", "callListMethod", "callBatch"
|
|
37
|
+
/** Методы B24OAuth, оборачиваемые retry-логикой (fetchListMethod — async-генератор, его оборачивать нельзя) */
|
|
38
|
+
const RETRYABLE_METHODS = new Set(["callMethod", "callListMethod", "callBatch"]);
|
|
39
39
|
|
|
40
40
|
/** Коды AxiosError, означающие проблему с сетью */
|
|
41
41
|
const AXIOS_NETWORK_CODES = new Set(["ERR_NETWORK", "ECONNABORTED"]);
|
|
42
42
|
|
|
43
|
+
/** Коды ошибок SDK (AjaxError / RefreshTokenError), означающие транспортный сбой */
|
|
44
|
+
const SDK_NETWORK_CODES = new Set(["NETWORK_ERROR", "REQUEST_TIMEOUT", "ERR_NETWORK", "ECONNABORTED"]);
|
|
45
|
+
|
|
43
46
|
const confAuthB24 = new Conf({
|
|
44
47
|
cwd: path.resolve(CONFIG_DIR),
|
|
45
48
|
configName: "authB24",
|
|
@@ -55,6 +58,31 @@ function cleanDomain(domain: string): string {
|
|
|
55
58
|
/** Задержка на указанное количество миллисекунд */
|
|
56
59
|
const delay = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));
|
|
57
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Достаёт result из ответа SDK.
|
|
63
|
+
*
|
|
64
|
+
* SDK при «мягких» ошибках (ERROR_ENTITY_NOT_FOUND, BITRIX_REST_V3_EXCEPTION_*)
|
|
65
|
+
* не бросает исключение, а возвращает AjaxResult с ошибкой.
|
|
66
|
+
* Функция превращает такой ответ в понятную ошибку вместо падения на undefined.
|
|
67
|
+
* Также отсекает случай, когда запрос успешен, но result пустой (null/undefined).
|
|
68
|
+
*
|
|
69
|
+
* @param response — результат $b24.callMethod()
|
|
70
|
+
* @param methodName — имя метода B24, попадёт в текст ошибки
|
|
71
|
+
*/
|
|
72
|
+
export function getResultData<T = any>(response: AjaxResult, methodName: string): T {
|
|
73
|
+
if (!response.isSuccess) {
|
|
74
|
+
const messages = response.getErrorMessages().join("; ") || "неизвестная ошибка";
|
|
75
|
+
throw new Error(`${methodName}: Bitrix24 вернул ошибку — ${messages}`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const data = response.getData();
|
|
79
|
+
if (data?.result == null) {
|
|
80
|
+
throw new Error(`${methodName}: Bitrix24 вернул пустой ответ`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return data.result as T;
|
|
84
|
+
}
|
|
85
|
+
|
|
58
86
|
// ==================== Создание экземпляра B24OAuth ====================
|
|
59
87
|
|
|
60
88
|
function createB24Instance(): B24OAuth | null {
|
|
@@ -91,7 +119,14 @@ function createB24Instance(): B24OAuth | null {
|
|
|
91
119
|
|
|
92
120
|
const secret: B24OAuthSecret = { clientId: CLIENT_ID, clientSecret: CLIENT_SECRET };
|
|
93
121
|
|
|
94
|
-
|
|
122
|
+
const b24 = new B24OAuth(authParams, secret);
|
|
123
|
+
|
|
124
|
+
// Логгер без хендлеров: SDK 2.x на каждый вызов callMethod/callBatch пишет
|
|
125
|
+
// предупреждение об устаревании напрямую в console.warn, если логгер — NullLogger.
|
|
126
|
+
// Любой другой логгер получает запись через свой интерфейс, поэтому консоль остаётся чистой.
|
|
127
|
+
b24.setLogger(Logger.create("npm-app-back-b24"));
|
|
128
|
+
|
|
129
|
+
return b24;
|
|
95
130
|
}
|
|
96
131
|
|
|
97
132
|
// ==================== Работа с токенами ====================
|
|
@@ -188,8 +223,9 @@ async function refreshAuthWithMutex(): Promise<AuthData> {
|
|
|
188
223
|
lastError = error;
|
|
189
224
|
if (!isB24NetworkError(error) || attempt === RETRY_COUNT) throw error;
|
|
190
225
|
const msg = error instanceof Error ? error.message : String(error);
|
|
226
|
+
const code = error instanceof SdkError ? ` [${error.code}]` : "";
|
|
191
227
|
const delayMs = RETRY_DELAY_MS * attempt;
|
|
192
|
-
logs.add(`refreshAuth: попытка ${attempt}/${RETRY_COUNT} не удалась (${msg}), повтор через ${delayMs}мс`, "error");
|
|
228
|
+
logs.add(`refreshAuth${code}: попытка ${attempt}/${RETRY_COUNT} не удалась (${msg}), повтор через ${delayMs}мс`, "error");
|
|
193
229
|
await delay(delayMs);
|
|
194
230
|
}
|
|
195
231
|
}
|
|
@@ -261,15 +297,23 @@ export function stopProactiveRefresh(): void {
|
|
|
261
297
|
|
|
262
298
|
/**
|
|
263
299
|
* Проверяет, является ли ошибка из SDK сетевой.
|
|
264
|
-
*
|
|
300
|
+
*
|
|
301
|
+
* SDK 2.x маскирует транспортные сбои: в логирующей ветке падает собственный
|
|
302
|
+
* TypeError, и наружу приходит AjaxError с кодом JSSDK_UNKNOWN_ERROR и status 0.
|
|
303
|
+
* Поэтому проверяем и код, и originalError, и status.
|
|
304
|
+
* RefreshTokenError приходит как SdkError с кодом вроде ENOTFOUND и без originalError.
|
|
265
305
|
*/
|
|
266
306
|
function isB24NetworkError(error: unknown): boolean {
|
|
267
307
|
if (error instanceof AjaxError) {
|
|
268
|
-
//
|
|
308
|
+
// Практически недостижимо (SDK бросает реальную ошибку раньше),
|
|
309
|
+
// но если код всё же пришёл — SDK уже исчерпал свои попытки
|
|
269
310
|
if (error.code === "JSSDK_CALL_ALL_ATTEMPTS_EXHAUSTED") return false;
|
|
311
|
+
}
|
|
270
312
|
|
|
271
|
-
|
|
313
|
+
if (error instanceof SdkError) {
|
|
314
|
+
const { code, originalError, status } = error;
|
|
272
315
|
|
|
316
|
+
if (SDK_NETWORK_CODES.has(code)) return true;
|
|
273
317
|
if (originalError && isNetworkError(originalError)) return true;
|
|
274
318
|
if (AXIOS_NETWORK_CODES.has((originalError as any)?.code)) return true;
|
|
275
319
|
if (status === 0) return true;
|
|
@@ -294,7 +338,8 @@ function withRetry<T extends (...args: any[]) => Promise<any>>(fn: T, context: a
|
|
|
294
338
|
}
|
|
295
339
|
|
|
296
340
|
const msg = error instanceof Error ? error.message : String(error);
|
|
297
|
-
|
|
341
|
+
const code = error instanceof SdkError ? ` [${error.code}]` : "";
|
|
342
|
+
logs.add(`$b24.${methodName}${code}: попытка ${attempt}/${RETRY_COUNT} не удалась (${msg}), повтор через ${RETRY_DELAY_MS}мс`, "error");
|
|
298
343
|
|
|
299
344
|
await delay(RETRY_DELAY_MS);
|
|
300
345
|
}
|
|
@@ -306,32 +351,36 @@ function withRetry<T extends (...args: any[]) => Promise<any>>(fn: T, context: a
|
|
|
306
351
|
}
|
|
307
352
|
|
|
308
353
|
/**
|
|
309
|
-
* Proxy-обёртка вокруг B24OAuth
|
|
310
|
-
*
|
|
311
|
-
*
|
|
354
|
+
* Proxy-обёртка вокруг B24OAuth.
|
|
355
|
+
*
|
|
356
|
+
* Методы из RETRYABLE_METHODS оборачиваются retry-логикой, все остальные
|
|
357
|
+
* привязываются к оригинальному объекту через bind: класс B24OAuth использует
|
|
358
|
+
* приватные поля (#authOAuthManager), и при вызове метода с this === Proxy
|
|
359
|
+
* движок бросает "Cannot read private member".
|
|
360
|
+
*
|
|
361
|
+
* Обёртки кешируются — по одной на метод, чтобы не ломать сравнение по ссылке.
|
|
312
362
|
*/
|
|
313
363
|
function wrapB24WithRetry(b24: B24OAuth): B24OAuth {
|
|
314
364
|
const methodCache = new Map<string, Function>();
|
|
315
365
|
|
|
316
366
|
return new Proxy(b24, {
|
|
317
|
-
get(target, prop
|
|
318
|
-
// Передаём target
|
|
319
|
-
//
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
367
|
+
get(target, prop) {
|
|
368
|
+
// Передаём target третьим аргументом: геттеры (например, auth)
|
|
369
|
+
// тоже должны исполняться с this === target
|
|
370
|
+
const value = Reflect.get(target, prop, target);
|
|
371
|
+
|
|
372
|
+
if (typeof prop !== "string" || typeof value !== "function") {
|
|
373
|
+
return value;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
if (!methodCache.has(prop)) {
|
|
377
|
+
const wrapped = RETRYABLE_METHODS.has(prop)
|
|
378
|
+
? withRetry(value as (...args: any[]) => Promise<any>, target, prop)
|
|
379
|
+
: value.bind(target);
|
|
380
|
+
methodCache.set(prop, wrapped);
|
|
331
381
|
}
|
|
332
382
|
|
|
333
|
-
|
|
334
|
-
return Reflect.get(target, prop, target);
|
|
383
|
+
return methodCache.get(prop);
|
|
335
384
|
},
|
|
336
385
|
});
|
|
337
386
|
}
|
package/bitrix24/errTaskB24.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DateTime } from "luxon";
|
|
2
|
-
import { $b24 } from "./b24.ts";
|
|
2
|
+
import { $b24, getResultData } from "./b24.ts";
|
|
3
3
|
import { logs } from "../logs/logs.ts";
|
|
4
4
|
import dotEnv from "dotenv";
|
|
5
5
|
|
|
@@ -54,8 +54,7 @@ export async function checkB24Scope(): Promise<void> {
|
|
|
54
54
|
|
|
55
55
|
try {
|
|
56
56
|
const scopeResponse = await $b24.callMethod("scope");
|
|
57
|
-
const
|
|
58
|
-
const scopes: string[] = scopeData.result ?? [];
|
|
57
|
+
const scopes = getResultData<string[]>(scopeResponse, "scope") ?? [];
|
|
59
58
|
|
|
60
59
|
logs.add(`Права приложения Bitrix24: ${scopes.join(", ")}`, "info");
|
|
61
60
|
|
|
@@ -104,8 +103,7 @@ export async function errorB24(dataTask: ErrorTaskData): Promise<ErrorB24Result>
|
|
|
104
103
|
select: ["ID", "STATUS"],
|
|
105
104
|
});
|
|
106
105
|
|
|
107
|
-
const
|
|
108
|
-
const tasks: TaskItem[] = data.result?.tasks ?? [];
|
|
106
|
+
const tasks: TaskItem[] = getResultData<{ tasks?: TaskItem[] }>(response, "tasks.task.list").tasks ?? [];
|
|
109
107
|
|
|
110
108
|
if (tasks.length >= maxTasks) {
|
|
111
109
|
return {
|
|
@@ -128,12 +126,12 @@ export async function errorB24(dataTask: ErrorTaskData): Promise<ErrorB24Result>
|
|
|
128
126
|
},
|
|
129
127
|
});
|
|
130
128
|
|
|
131
|
-
const
|
|
129
|
+
const createdTask = getResultData(createResponse, "tasks.task.add");
|
|
132
130
|
|
|
133
131
|
return {
|
|
134
132
|
error: false,
|
|
135
133
|
message: "Задача создана в Битрикс24.",
|
|
136
|
-
data:
|
|
134
|
+
data: createdTask,
|
|
137
135
|
};
|
|
138
136
|
} catch (error: any) {
|
|
139
137
|
return {
|
package/bitrix24/eventB24.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { B24OAuth } from "@bitrix24/b24jssdk";
|
|
2
|
-
import { $b24 } from "./b24.ts";
|
|
2
|
+
import { $b24, getResultData } from "./b24.ts";
|
|
3
3
|
|
|
4
4
|
// ==================== Типы ====================
|
|
5
5
|
|
|
@@ -141,7 +141,9 @@ export class Event {
|
|
|
141
141
|
filter: { EVENT_NAME: eventName },
|
|
142
142
|
});
|
|
143
143
|
|
|
144
|
-
const arrOfflineEvents = response.
|
|
144
|
+
const arrOfflineEvents = getResultData<OfflineEventsResponse["result"]>(response, "event.offline.get");
|
|
145
|
+
// B24 для пустой коллекции может вернуть result: [] — тогда events отсутствует
|
|
146
|
+
const allEvents = arrOfflineEvents?.events ?? [];
|
|
145
147
|
|
|
146
148
|
// Обработка событий коннектора
|
|
147
149
|
if (eventName === "ONIMCONNECTORMESSAGEADD") {
|
|
@@ -150,9 +152,9 @@ export class Event {
|
|
|
150
152
|
message: [],
|
|
151
153
|
};
|
|
152
154
|
|
|
153
|
-
if (
|
|
154
|
-
data.processId = arrOfflineEvents.
|
|
155
|
-
data.message =
|
|
155
|
+
if (allEvents.length > 0) {
|
|
156
|
+
data.processId = arrOfflineEvents.process_id;
|
|
157
|
+
data.message = allEvents.map((event) => {
|
|
156
158
|
const messageData = event.EVENT_DATA.MESSAGES[0];
|
|
157
159
|
|
|
158
160
|
return {
|
|
@@ -178,23 +180,23 @@ export class Event {
|
|
|
178
180
|
};
|
|
179
181
|
|
|
180
182
|
// Очищаем события от системного пользователя
|
|
181
|
-
const arrEventsToClear =
|
|
183
|
+
const arrEventsToClear = allEvents.filter((event) => event.EVENT_ADDITIONAL.user_id === SYSTEM_USER_ID);
|
|
182
184
|
|
|
183
185
|
if (arrEventsToClear.length > 0) {
|
|
184
186
|
const arrMessageIdToClear = arrEventsToClear.map((event) => event.MESSAGE_ID);
|
|
185
187
|
await this.b24.callMethod("event.offline.clear", {
|
|
186
|
-
process_id: arrOfflineEvents.
|
|
188
|
+
process_id: arrOfflineEvents.process_id,
|
|
187
189
|
message_id: arrMessageIdToClear,
|
|
188
190
|
});
|
|
189
|
-
|
|
190
|
-
// Удаляем эти события из основного массива
|
|
191
|
-
arrOfflineEvents.result.events = arrOfflineEvents.result.events.filter((event) => event.EVENT_ADDITIONAL.user_id !== SYSTEM_USER_ID);
|
|
192
191
|
}
|
|
193
192
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
193
|
+
// Работаем только с событиями, не относящимися к системному пользователю
|
|
194
|
+
const activeEvents = allEvents.filter((event) => event.EVENT_ADDITIONAL.user_id !== SYSTEM_USER_ID);
|
|
195
|
+
|
|
196
|
+
if (activeEvents.length > 0) {
|
|
197
|
+
data.processId = arrOfflineEvents.process_id;
|
|
198
|
+
data.entitysId = activeEvents.map((event) => event.EVENT_DATA.FIELDS.ID);
|
|
199
|
+
data.arrMessageIdAndEntityId = activeEvents.map((event) => ({
|
|
198
200
|
messageId: event.MESSAGE_ID,
|
|
199
201
|
entityId: event.EVENT_DATA.FIELDS.ID,
|
|
200
202
|
}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@andrey4emk/npm-app-back-b24",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"description": "Bitrix24 OAuth helpers for Node.js projects",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -35,15 +35,14 @@
|
|
|
35
35
|
"utils/fetchRetry.ts"
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@bitrix24/b24jssdk": "
|
|
38
|
+
"@bitrix24/b24jssdk": "2.0.0",
|
|
39
39
|
"@types/express": "5.0.6",
|
|
40
40
|
"@types/luxon": "3.7.1",
|
|
41
41
|
"@types/node": "25.0.10",
|
|
42
|
+
"@types/nodemailer": "7.0.9",
|
|
42
43
|
"conf": "15.0.2",
|
|
43
44
|
"dotenv": "17.2.3",
|
|
44
45
|
"luxon": "3.4.4",
|
|
45
|
-
"nodemailer": "7.0.6"
|
|
46
|
-
|
|
47
|
-
},
|
|
48
|
-
"devDependencies": {}
|
|
46
|
+
"nodemailer": "7.0.6"
|
|
47
|
+
}
|
|
49
48
|
}
|
package/sendMessage/smsgold.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { B24OAuth } from "@bitrix24/b24jssdk";
|
|
2
|
+
import { getResultData } from "../bitrix24/b24.ts";
|
|
2
3
|
|
|
3
4
|
// ==================== Типы ====================
|
|
4
5
|
|
|
@@ -74,10 +75,10 @@ export class Smsgold {
|
|
|
74
75
|
|
|
75
76
|
// Получаем публичную ссылку на файл для вставки в сообщение
|
|
76
77
|
try {
|
|
77
|
-
|
|
78
|
+
const resLink = await this.b24!.callMethod("disk.file.getExternalLink", {
|
|
78
79
|
id: idFileContract,
|
|
79
80
|
});
|
|
80
|
-
publicLink = (resLink
|
|
81
|
+
publicLink = getResultData<string>(resLink, "disk.file.getExternalLink");
|
|
81
82
|
} catch (error: unknown) {
|
|
82
83
|
const errMsg = error instanceof Error ? error.message : String(error);
|
|
83
84
|
return { error: true, message: `Ошибка при получении публичной ссылки на файл: ${errMsg}` };
|
|
@@ -139,7 +140,7 @@ export class Smsgold {
|
|
|
139
140
|
data: { NAME: fileName },
|
|
140
141
|
fileContent: [fileName, base64File],
|
|
141
142
|
});
|
|
142
|
-
const data = (res
|
|
143
|
+
const data = getResultData(res, "disk.folder.uploadfile");
|
|
143
144
|
return { error: false, data };
|
|
144
145
|
} catch (error: unknown) {
|
|
145
146
|
const errMsg = error instanceof Error ? error.message : String(error);
|