@andrey4emk/npm-app-back-b24 3.9.0 → 4.0.1

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.
@@ -27,6 +27,15 @@ interface SmsMessageData {
27
27
  */
28
28
  const DEFAULT_UPLOAD_FOLDER_ID = 2792881;
29
29
 
30
+ /**
31
+ * Файл, загруженный на диск Bitrix24 — то, что классу нужно от ответа
32
+ * `disk.folder.uploadfile`. Идентификатор портал отдаёт то строкой, то числом,
33
+ * и класс лишь передаёт его дальше в `disk.file.getExternalLink`
34
+ */
35
+ interface UploadedFile {
36
+ ID: string | number;
37
+ }
38
+
30
39
  /** Результат отправки SMS */
31
40
  interface SmsResult {
32
41
  error: boolean;
@@ -175,7 +184,7 @@ export class Smsgold {
175
184
  }
176
185
 
177
186
  /** Загружает файл в папку Битрикс24 через метод disk.folder.uploadfile */
178
- private async uploadFileInFolderB24(fileBuffer: Buffer, fileName: string): Promise<{ error: boolean; message?: string; data?: any }> {
187
+ private async uploadFileInFolderB24(fileBuffer: Buffer, fileName: string): Promise<{ error: boolean; message?: string; data?: UploadedFile }> {
179
188
  try {
180
189
  const base64File = fileBuffer.toString("base64");
181
190
 
@@ -185,7 +194,7 @@ export class Smsgold {
185
194
  data: { NAME: fileName },
186
195
  fileContent: [fileName, base64File],
187
196
  });
188
- const data = getResultData(res, "disk.folder.uploadfile");
197
+ const data = getResultData<UploadedFile>(res, "disk.folder.uploadfile");
189
198
  return { error: false, data };
190
199
  } catch (error: unknown) {
191
200
  const errMsg = error instanceof Error ? error.message : String(error);
@@ -25,11 +25,31 @@ interface WappiFileMessageData extends WappiMessageData {
25
25
  fileName: string;
26
26
  }
27
27
 
28
+ /**
29
+ * Ответ Wappi в той части, которую разбирает класс.
30
+ *
31
+ * Описан по фактически читаемым полям, а не по всему API. Поля `check` и `haveContact`
32
+ * в ответе Wappi отсутствуют — их дописывает сам класс в объект ответа, поэтому
33
+ * в интерфейсе они обязаны быть, иначе присваивание не пройдёт тайпчек
34
+ */
35
+ interface WappiResponse {
36
+ status?: string;
37
+ detail?: string;
38
+ on_max?: boolean;
39
+ on_whatsapp?: boolean;
40
+ contact?: unknown;
41
+ /** Дописывается классом: номер пригоден для отправки */
42
+ check?: boolean;
43
+ /** Дописывается классом: контакт найден или создан */
44
+ haveContact?: boolean;
45
+ }
46
+
28
47
  /** Стандартный результат операции */
29
48
  interface WappiResult {
30
49
  error: boolean;
31
50
  message: string;
32
- data: any;
51
+ /** Ответ Wappi как есть — форму задаёт сервис, потребитель приводит сам */
52
+ data: unknown;
33
53
  /**
34
54
  * Ответа не дождались. Отличает «проверка сказала нет» от «проверки не было»:
35
55
  * без этого признака вызывающий код принимает таймаут за отрицательный ответ.
@@ -93,7 +113,7 @@ export class Wappi {
93
113
  url = `https://wappi.pro/maxapi/sync/message/send?${sendOpenLine}profile_id=${profile_id}`;
94
114
  }
95
115
 
96
- let data: any;
116
+ let data: WappiResponse;
97
117
  try {
98
118
  const res = await fetchWithTimeout(
99
119
  url!,
@@ -110,7 +130,7 @@ export class Wappi {
110
130
  },
111
131
  FETCH_TIMEOUTS.send
112
132
  );
113
- data = await res.json();
133
+ data = (await res.json()) as WappiResponse;
114
134
  } catch (error: unknown) {
115
135
  // Метод исторически без try/catch — перехватываем только таймаут, который сами
116
136
  // и вводим, чтобы не появился новый путь исключений там, где его сегодня нет.
@@ -202,7 +222,7 @@ export class Wappi {
202
222
  url = `https://wappi.pro/maxapi/async/message/file/url/send?${sendOpenLine}profile_id=${profile_id}`;
203
223
  }
204
224
 
205
- let data: any;
225
+ let data: WappiResponse;
206
226
  try {
207
227
  // В теле уходит base64 файла — бюджет transfer, а не send
208
228
  const res = await fetchWithTimeout(
@@ -223,7 +243,7 @@ export class Wappi {
223
243
  },
224
244
  FETCH_TIMEOUTS.transfer
225
245
  );
226
- data = await res.json();
246
+ data = (await res.json()) as WappiResponse;
227
247
  } catch (error: unknown) {
228
248
  // Перехватываем только таймаут, остальные ошибки ведут себя как раньше
229
249
  if (!isTimeoutError(error)) throw error;
@@ -265,9 +285,14 @@ export class Wappi {
265
285
  const contactCheck = await this.getContactTelegramWappi(phone);
266
286
 
267
287
  // 2 Если существует, то номер в телеге есть, можем отправлять сообщение
268
- if (!contactCheck.error && contactCheck.data.haveContact) {
269
- contactCheck.data.check = true;
270
- return { error: false, message: `Номер ${phone} проверен для мессенджера ${messangerType}`, data: contactCheck.data };
288
+ // Приведение, а не проверка: `data` объявлен unknown только в публичном типе,
289
+ // внутри класса это всегда разобранный ответ Wappi. На ошибке там null,
290
+ // но до чтения поля не доходит — первым проверяется `!contactCheck.error`,
291
+ // порядок вычисления тот же, что и до 4.0.0
292
+ const contactData = contactCheck.data as WappiResponse;
293
+ if (!contactCheck.error && contactData.haveContact) {
294
+ contactData.check = true;
295
+ return { error: false, message: `Номер ${phone} проверен для мессенджера ${messangerType}`, data: contactData };
271
296
  }
272
297
 
273
298
  // Ответа не дождались — это не «контакта нет». Создавать контакт вслепую нельзя:
@@ -280,14 +305,15 @@ export class Wappi {
280
305
 
281
306
  // 3 Если не существует, то номера в телеге нет, пробуем создать
282
307
  const addContactResult = await this.addContactTelegramWappi(phone);
308
+ const addedData = addContactResult.data as WappiResponse;
283
309
 
284
310
  if (!addContactResult.error) {
285
311
  // Если получается создать, отправляем информацию
286
- addContactResult.data.check = true;
287
- return { error: false, message: `Номер ${phone} успешно добавлен и проверен для мессенджера ${messangerType}`, data: addContactResult.data };
312
+ addedData.check = true;
313
+ return { error: false, message: `Номер ${phone} успешно добавлен и проверен для мессенджера ${messangerType}`, data: addedData };
288
314
  }
289
315
  // Если не получается, то отправляем информацию об ошибке
290
- return { error: true, message: `Не удалось проверить и добавить номер ${phone} в Telegram: ${addContactResult.message}`, data: addContactResult.data };
316
+ return { error: true, message: `Не удалось проверить и добавить номер ${phone} в Telegram: ${addContactResult.message}`, data: addedData };
291
317
  }
292
318
  if (messangerType === "max") {
293
319
  token = this.maxAuth.token;
@@ -295,7 +321,7 @@ export class Wappi {
295
321
  url = `https://wappi.pro/maxapi/sync/contact/check?profile_id=${profile_id}&phone=${phone}`;
296
322
  }
297
323
 
298
- let data: any;
324
+ let data: WappiResponse;
299
325
  try {
300
326
  const res = await fetchWithTimeout(
301
327
  url!,
@@ -308,7 +334,7 @@ export class Wappi {
308
334
  },
309
335
  FETCH_TIMEOUTS.api
310
336
  );
311
- data = await res.json();
337
+ data = (await res.json()) as WappiResponse;
312
338
  } catch (error: unknown) {
313
339
  // Перехватываем только таймаут, остальные ошибки ведут себя как раньше
314
340
  if (!isTimeoutError(error)) throw error;
@@ -353,7 +379,7 @@ export class Wappi {
353
379
  FETCH_TIMEOUTS.api
354
380
  );
355
381
 
356
- const data: any = await res.json();
382
+ const data = (await res.json()) as WappiResponse;
357
383
 
358
384
  if (data.status !== "done") {
359
385
  return { error: true, message: `Ошибка получения контакта ${phone} из Telegram`, data };
@@ -405,7 +431,7 @@ export class Wappi {
405
431
  FETCH_TIMEOUTS.send
406
432
  );
407
433
 
408
- const data: any = await res.json();
434
+ const data = (await res.json()) as WappiResponse;
409
435
  if (data.status !== "done") {
410
436
  return { error: true, message: `Ошибка создания контакта ${phone} в Telegram`, data };
411
437
  }