itd-sdk-js 1.0.8 → 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/src/client.js CHANGED
@@ -16,6 +16,7 @@ import { HashtagsManager } from './hashtags.js';
16
16
  import { FilesManager } from './files.js';
17
17
  import { ReportsManager } from './reports.js';
18
18
  import { SearchManager } from './search.js';
19
+ import { VerificationManager } from './verification.js';
19
20
 
20
21
  dotenv.config();
21
22
 
@@ -199,7 +200,8 @@ export class ITDClient {
199
200
  this.hashtags = new HashtagsManager(this);
200
201
  this.files = new FilesManager(this);
201
202
  this.reports = new ReportsManager(this);
202
- this.search = new SearchManager(this);
203
+ this.searchManager = new SearchManager(this);
204
+ this.verification = new VerificationManager(this);
203
205
  }
204
206
 
205
207
  /**
@@ -343,6 +345,17 @@ export class ITDClient {
343
345
  async logout() {
344
346
  return await this.auth.logout();
345
347
  }
348
+
349
+ /**
350
+ * Смена пароля. POST /api/v1/auth/change-password. Требует cookies (refresh_token).
351
+ *
352
+ * @param {string} oldPassword - Текущий пароль
353
+ * @param {string} newPassword - Новый пароль
354
+ * @returns {Promise<Object|null>} Ответ API или null
355
+ */
356
+ async changePassword(oldPassword, newPassword) {
357
+ return await this.auth.changePassword(oldPassword, newPassword);
358
+ }
346
359
 
347
360
  /**
348
361
  * Создает пост (удобный метод)
@@ -383,7 +396,7 @@ export class ITDClient {
383
396
  *
384
397
  * @param {string|null} username - Имя пользователя (null = лента/свои посты)
385
398
  * @param {number} limit - Количество постов
386
- * @param {string} sort - Сортировка: "new", "old", "popular"
399
+ * @param {string} sort - Сортировка: "newest", "oldest", "popular"
387
400
  * @param {string|null} cursor - Курсор для пагинации
388
401
  * @param {string|null} tab - Тип ленты: "popular" (популярные), "following" (из подписок), null (обычная лента)
389
402
  * @returns {Promise<Object>} { posts: [], pagination: {} }
@@ -413,6 +426,19 @@ export class ITDClient {
413
426
  async getFeedFollowing(limit = 20, cursor = null) {
414
427
  return await this.posts.getFeedFollowing(limit, cursor);
415
428
  }
429
+
430
+ /**
431
+ * Получает лайкнутые посты пользователя.
432
+ * GET /api/posts/user/{username}/liked → { posts: [], pagination: {} }
433
+ *
434
+ * @param {string} username - Имя пользователя
435
+ * @param {number} limit - Количество постов
436
+ * @param {string|null} cursor - Курсор для пагинации
437
+ * @returns {Promise<Object>} { posts: [], pagination: {} }
438
+ */
439
+ async getLikedPosts(username, limit = 20, cursor = null) {
440
+ return await this.posts.getLikedPosts(username, limit, cursor);
441
+ }
416
442
 
417
443
  /**
418
444
  * Получает список постов (простой вариант - только массив)
@@ -435,6 +461,28 @@ export class ITDClient {
435
461
  async getPost(postId) {
436
462
  return await this.posts.getPost(postId);
437
463
  }
464
+
465
+ /**
466
+ * Отмечает пост как просмотренный. POST /api/posts/{id}/view
467
+ *
468
+ * @param {string} postId - ID поста
469
+ * @returns {Promise<boolean>} True если успешно
470
+ */
471
+ async viewPost(postId) {
472
+ return await this.posts.viewPost(postId);
473
+ }
474
+
475
+ /**
476
+ * Получает посты на стене пользователя. GET /api/posts/user/{username}/wall
477
+ *
478
+ * @param {string} username - Имя пользователя
479
+ * @param {number} limit - Количество
480
+ * @param {string|null} cursor - Курсор пагинации
481
+ * @returns {Promise<Object>} { posts: [], pagination: {} }
482
+ */
483
+ async getWallByUser(username, limit = 20, cursor = null) {
484
+ return await this.posts.getWallByUser(username, limit, cursor);
485
+ }
438
486
 
439
487
  /**
440
488
  * Удаляет пост (удобный метод)
@@ -445,16 +493,36 @@ export class ITDClient {
445
493
  async deletePost(postId) {
446
494
  return await this.posts.deletePost(postId);
447
495
  }
496
+
497
+ /**
498
+ * Восстанавливает удалённый пост. POST /api/posts/{id}/restore
499
+ *
500
+ * @param {string} postId - ID поста
501
+ * @returns {Promise<boolean>} True если успешно
502
+ */
503
+ async restorePost(postId) {
504
+ return await this.posts.restorePost(postId);
505
+ }
448
506
 
449
507
  /**
450
- * Закрепляет пост (удобный метод)
451
- *
508
+ * Закрепляет пост. POST /api/posts/{id}/pin → { success: true, pinnedPostId }
509
+ *
452
510
  * @param {string} postId - ID поста
453
511
  * @returns {Promise<boolean>} True если успешно
454
512
  */
455
513
  async pinPost(postId) {
456
514
  return await this.posts.pinPost(postId);
457
515
  }
516
+
517
+ /**
518
+ * Открепляет пост. DELETE /api/posts/{id}/pin → { success: true, pinnedPostId: null }
519
+ *
520
+ * @param {string} postId - ID поста
521
+ * @returns {Promise<boolean>} True если успешно
522
+ */
523
+ async unpinPost(postId) {
524
+ return await this.posts.unpinPost(postId);
525
+ }
458
526
 
459
527
  /**
460
528
  * Делает репост (удобный метод)
@@ -537,12 +605,25 @@ export class ITDClient {
537
605
  * Добавляет комментарий к посту
538
606
  *
539
607
  * @param {string} postId - ID поста
540
- * @param {string} text - Текст комментария
608
+ * @param {string} text - Текст (пустая строка для голосового)
541
609
  * @param {string|null} replyToCommentId - ID комментария для ответа (опционально)
610
+ * @param {string[]|null} attachmentIds - ID загруженных файлов (audio/ogg для голосовых)
542
611
  * @returns {Promise<Object|null>} Данные комментария
543
612
  */
544
- async addComment(postId, text, replyToCommentId = null) {
545
- return await this.comments.addComment(postId, text, replyToCommentId);
613
+ async addComment(postId, text, replyToCommentId = null, attachmentIds = null) {
614
+ return await this.comments.addComment(postId, text, replyToCommentId, attachmentIds);
615
+ }
616
+
617
+ /**
618
+ * Добавляет голосовое сообщение в комментарий. Загружает audio/ogg и создаёт комментарий.
619
+ *
620
+ * @param {string} postId - ID поста
621
+ * @param {string} audioPath - Путь к аудиофайлу (audio/ogg)
622
+ * @param {string|null} replyToCommentId - ID комментария для ответа (опционально)
623
+ * @returns {Promise<Object|null>} Данные созданного комментария или null
624
+ */
625
+ async addVoiceComment(postId, audioPath, replyToCommentId = null) {
626
+ return await this.comments.addVoiceComment(postId, audioPath, replyToCommentId);
546
627
  }
547
628
 
548
629
  /**
@@ -586,6 +667,16 @@ export class ITDClient {
586
667
  async deleteComment(commentId) {
587
668
  return await this.comments.deleteComment(commentId);
588
669
  }
670
+
671
+ /**
672
+ * Восстанавливает удалённый комментарий. POST /api/comments/{id}/restore
673
+ *
674
+ * @param {string} commentId - ID комментария
675
+ * @returns {Promise<boolean>} True если успешно
676
+ */
677
+ async restoreComment(commentId) {
678
+ return await this.comments.restoreComment(commentId);
679
+ }
589
680
 
590
681
  /**
591
682
  * Получает комментарии к посту
@@ -600,14 +691,38 @@ export class ITDClient {
600
691
  }
601
692
 
602
693
  /**
603
- * Обновляет описание профиля текущего пользователя
604
- *
605
- * @param {string} bio - Новое описание профиля
694
+ * Обновляет профиль текущего пользователя.
695
+ * PUT /api/users/me → { id, username, displayName, bio, updatedAt }
696
+ *
697
+ * @param {string|null} bio - Новое описание профиля (опционально)
606
698
  * @param {string|null} displayName - Новое отображаемое имя (опционально)
699
+ * @param {string|null} username - Новый username (опционально)
700
+ * @param {string|null} bannerId - ID загруженного баннера (опционально)
607
701
  * @returns {Promise<Object|null>} Обновленные данные профиля или null при ошибке
608
702
  */
609
- async updateProfile(bio, displayName = null) {
610
- return await this.users.updateProfile(bio, displayName);
703
+ async updateProfile(bio = null, displayName = null, username = null, bannerId = null) {
704
+ return await this.users.updateProfile(bio, displayName, username, bannerId);
705
+ }
706
+
707
+ /**
708
+ * Получает настройки приватности.
709
+ * GET /api/users/me/privacy → { isPrivate, wallClosed }
710
+ *
711
+ * @returns {Promise<Object|null>} { isPrivate, wallClosed } или null
712
+ */
713
+ async getPrivacy() {
714
+ return await this.users.getPrivacy();
715
+ }
716
+
717
+ /**
718
+ * Обновляет настройки приватности.
719
+ * PUT /api/users/me/privacy → { isPrivate, wallClosed }
720
+ *
721
+ * @param {Object} options - { isPrivate?: boolean, wallClosed?: boolean }
722
+ * @returns {Promise<Object|null>} { isPrivate, wallClosed } или null
723
+ */
724
+ async updatePrivacy(options = {}) {
725
+ return await this.users.updatePrivacy(options);
611
726
  }
612
727
 
613
728
  /**
@@ -684,27 +799,39 @@ export class ITDClient {
684
799
  }
685
800
 
686
801
  /**
687
- * Получает список уведомлений
688
- *
802
+ * Получает список уведомлений.
803
+ * GET /api/notifications/?offset=0&limit=20 → { notifications: [], hasMore }
804
+ *
689
805
  * @param {number} limit - Количество уведомлений
690
- * @param {string|null} cursor - Курсор для пагинации
691
- * @param {string|null} type - Фильтр по типу: 'reply', 'like', 'wall_post', 'follow', 'comment' (опционально)
692
- * @returns {Promise<Object|null>} { notifications: [], pagination: {} } или null
806
+ * @param {number} offset - Смещение для пагинации
807
+ * @param {string|null} type - Фильтр по типу: 'reply', 'like', 'wall_post', 'follow', 'comment'
808
+ * @returns {Promise<Object|null>} { notifications: [], hasMore } или null
693
809
  */
694
- async getNotifications(limit = 20, cursor = null, type = null) {
695
- return await this.notifications.getNotifications(limit, cursor, type);
810
+ async getNotifications(limit = 20, offset = 0, type = null) {
811
+ return await this.notifications.getNotifications(limit, offset, type);
696
812
  }
697
-
813
+
698
814
  /**
699
815
  * Получает уведомления определенного типа
700
- *
701
- * @param {string} type - Тип уведомления: 'reply', 'like', 'wall_post', 'follow', 'comment'
702
- * @param {number} limit - Количество уведомлений (по умолчанию 20)
703
- * @param {string|null} cursor - Курсор для пагинации
704
- * @returns {Promise<Object|null>} { notifications: [], pagination: {} } или null
816
+ *
817
+ * @param {string} type - Тип: 'reply', 'like', 'wall_post', 'follow', 'comment'
818
+ * @param {number} limit - Количество
819
+ * @param {number} offset - Смещение
820
+ * @returns {Promise<Object|null>} { notifications: [], hasMore } или null
821
+ */
822
+ async getNotificationsByType(type, limit = 20, offset = 0) {
823
+ return await this.notifications.getNotifications(limit, offset, type);
824
+ }
825
+
826
+ /**
827
+ * Отмечает несколько уведомлений как прочитанные.
828
+ * POST /api/notifications/read-batch → { success: true, count }
829
+ *
830
+ * @param {string[]} ids - Массив ID уведомлений
831
+ * @returns {Promise<Object|null>} { success: true, count } или null
705
832
  */
706
- async getNotificationsByType(type, limit = 20, cursor = null) {
707
- return await this.notifications.getNotifications(limit, cursor, type);
833
+ async markNotificationsAsReadBatch(ids) {
834
+ return await this.notifications.markAsReadBatch(ids);
708
835
  }
709
836
 
710
837
  /**
@@ -784,6 +911,26 @@ export class ITDClient {
784
911
  async uploadFile(filePath) {
785
912
  return await this.files.uploadFile(filePath);
786
913
  }
914
+
915
+ /**
916
+ * Получает информацию о файле. GET /api/files/{id}
917
+ *
918
+ * @param {string} fileId - ID файла
919
+ * @returns {Promise<Object|null>} { id, url, filename, mimeType, size } или null
920
+ */
921
+ async getFile(fileId) {
922
+ return await this.files.getFile(fileId);
923
+ }
924
+
925
+ /**
926
+ * Удаляет файл. DELETE /api/files/{id}
927
+ *
928
+ * @param {string} fileId - ID файла
929
+ * @returns {Promise<boolean>} True если успешно
930
+ */
931
+ async deleteFile(fileId) {
932
+ return await this.files.deleteFile(fileId);
933
+ }
787
934
 
788
935
  /**
789
936
  * Отправляет репорт на пост, комментарий или пользователя
@@ -833,6 +980,43 @@ export class ITDClient {
833
980
  async reportUser(userId, reason = 'other', description = '') {
834
981
  return await this.reports.reportUser(userId, reason, description);
835
982
  }
983
+
984
+ /**
985
+ * Получает статус верификации. GET /api/verification/status
986
+ *
987
+ * @returns {Promise<Object|null>} Статус верификации или null
988
+ */
989
+ async getVerificationStatus() {
990
+ return await this.verification.getStatus();
991
+ }
992
+
993
+ /**
994
+ * Подаёт заявку на верификацию. POST /api/verification/submit
995
+ *
996
+ * @param {string} videoUrl - URL загруженного видео (из uploadFile)
997
+ * @returns {Promise<Object|null>} { success, request } или null
998
+ */
999
+ async submitVerification(videoUrl) {
1000
+ return await this.verification.submit(videoUrl);
1001
+ }
1002
+
1003
+ /**
1004
+ * Получает статус платформы. GET /api/platform/status
1005
+ *
1006
+ * @returns {Promise<Object|null>} Статус платформы или null
1007
+ */
1008
+ async getPlatformStatus() {
1009
+ try {
1010
+ const response = await this.axios.get('/api/platform/status');
1011
+ if (response.status === 200) {
1012
+ return response.data?.data ?? response.data;
1013
+ }
1014
+ return null;
1015
+ } catch (error) {
1016
+ console.error('Ошибка получения статуса платформы:', error.message);
1017
+ return null;
1018
+ }
1019
+ }
836
1020
 
837
1021
  /**
838
1022
  * Выполняет поиск пользователей и хэштегов
@@ -843,7 +1027,7 @@ export class ITDClient {
843
1027
  * @returns {Promise<Object|null>} { users: [], hashtags: [] } или null при ошибке
844
1028
  */
845
1029
  async search(query, userLimit = 5, hashtagLimit = 5) {
846
- return await this.search.search(query, userLimit, hashtagLimit);
1030
+ return await this.searchManager.search(query, userLimit, hashtagLimit);
847
1031
  }
848
1032
 
849
1033
  /**
@@ -854,7 +1038,7 @@ export class ITDClient {
854
1038
  * @returns {Promise<Array|null>} Массив пользователей или null при ошибке
855
1039
  */
856
1040
  async searchUsers(query, limit = 5) {
857
- return await this.search.searchUsers(query, limit);
1041
+ return await this.searchManager.searchUsers(query, limit);
858
1042
  }
859
1043
 
860
1044
  /**
@@ -865,7 +1049,7 @@ export class ITDClient {
865
1049
  * @returns {Promise<Array|null>} Массив хэштегов или null при ошибке
866
1050
  */
867
1051
  async searchHashtags(query, limit = 5) {
868
- return await this.search.searchHashtags(query, limit);
1052
+ return await this.searchManager.searchHashtags(query, limit);
869
1053
  }
870
1054
 
871
1055
  // ========== USER-FRIENDLY МЕТОДЫ ==========
@@ -995,16 +1179,6 @@ export class ITDClient {
995
1179
  return await this.users.getMyClan();
996
1180
  }
997
1181
 
998
- /**
999
- * Получает клан пользователя (эмодзи аватара) (удобный метод)
1000
- *
1001
- * @param {string} username - Имя пользователя
1002
- * @returns {Promise<string|null>} Эмодзи клана или null
1003
- */
1004
- async getUserClan(username) {
1005
- return await this.users.getUserClan(username);
1006
- }
1007
-
1008
1182
  // === Комментарии ===
1009
1183
 
1010
1184
  /**
@@ -1040,12 +1214,12 @@ export class ITDClient {
1040
1214
 
1041
1215
  /**
1042
1216
  * Получает только непрочитанные уведомления (удобный метод)
1043
- *
1044
- * @param {number} limit - Количество уведомлений
1045
- * @param {string|null} cursor - Курсор для пагинации
1046
- * @returns {Promise<Object|null>} { notifications: [], pagination: {} } или null
1217
+ *
1218
+ * @param {number} limit - Количество
1219
+ * @param {number} offset - Смещение
1220
+ * @returns {Promise<Object|null>} { notifications: [], hasMore } или null
1047
1221
  */
1048
- async getUnreadNotifications(limit = 20, cursor = null) {
1049
- return await this.notifications.getUnreadNotifications(limit, cursor);
1222
+ async getUnreadNotifications(limit = 20, offset = 0) {
1223
+ return await this.notifications.getUnreadNotifications(limit, offset);
1050
1224
  }
1051
1225
  }
package/src/comments.js CHANGED
@@ -13,30 +13,28 @@ export class CommentsManager {
13
13
  }
14
14
 
15
15
  /**
16
- * Добавляет комментарий к посту
17
- *
16
+ * Добавляет комментарий к посту.
17
+ * POST /api/posts/{postId}/comments → { id, content, author, attachments, ... }
18
+ * Поддерживает текст, голосовые (attachmentIds с audio/ogg) и ответы (replyTo).
19
+ *
18
20
  * @param {string} postId - ID поста
19
- * @param {string} text - Текст комментария
21
+ * @param {string} text - Текст комментария (пустая строка для голосового)
20
22
  * @param {string|null} replyToCommentId - ID комментария для ответа (опционально)
23
+ * @param {string[]|null} attachmentIds - ID загруженных файлов (audio/ogg для голосовых)
21
24
  * @returns {Promise<Object|null>} Данные созданного комментария или null
22
25
  */
23
- async addComment(postId, text, replyToCommentId = null) {
26
+ async addComment(postId, text, replyToCommentId = null, attachmentIds = null) {
24
27
  if (!await this.client.auth.checkAuth()) {
25
28
  console.error('Ошибка: необходимо войти в аккаунт');
26
29
  return null;
27
30
  }
28
-
29
31
  try {
30
32
  const commentUrl = `${this.client.baseUrl}/api/posts/${postId}/comments`;
31
- const commentData = {
32
- content: text, // Реальное поле - content
33
- };
34
-
35
- // Если это ответ на комментарий
36
- if (replyToCommentId) {
37
- commentData.replyTo = replyToCommentId;
33
+ const commentData = { content: text ?? '' };
34
+ if (replyToCommentId) commentData.replyTo = replyToCommentId;
35
+ if (Array.isArray(attachmentIds) && attachmentIds.length > 0) {
36
+ commentData.attachmentIds = attachmentIds;
38
37
  }
39
-
40
38
  const response = await this.axios.post(commentUrl, commentData);
41
39
 
42
40
  if (response.status === 200 || response.status === 201) {
@@ -55,6 +53,25 @@ export class CommentsManager {
55
53
  }
56
54
  }
57
55
 
56
+ /**
57
+ * Добавляет голосовое сообщение в комментарий.
58
+ * Загружает audio/ogg через /api/files/upload и создаёт комментарий с attachmentIds.
59
+ *
60
+ * @param {string} postId - ID поста
61
+ * @param {string} audioPath - Путь к аудиофайлу (audio/ogg)
62
+ * @param {string|null} replyToCommentId - ID комментария для ответа (опционально)
63
+ * @returns {Promise<Object|null>} Данные созданного комментария или null
64
+ */
65
+ async addVoiceComment(postId, audioPath, replyToCommentId = null) {
66
+ if (!await this.client.auth.checkAuth()) {
67
+ console.error('Ошибка: необходимо войти в аккаунт');
68
+ return null;
69
+ }
70
+ const uploaded = await this.client.files.uploadFile(audioPath);
71
+ if (!uploaded) return null;
72
+ return await this.addComment(postId, '', replyToCommentId, [uploaded.id]);
73
+ }
74
+
58
75
  /**
59
76
  * Ответ на комментарий (отдельный эндпоинт /api/comments/:id/replies).
60
77
  *
@@ -257,6 +274,24 @@ export class CommentsManager {
257
274
  return false;
258
275
  }
259
276
  }
277
+
278
+ /**
279
+ * Восстанавливает удалённый комментарий. POST /api/comments/{id}/restore
280
+ *
281
+ * @param {string} commentId - ID комментария
282
+ * @returns {Promise<boolean>} True если успешно
283
+ */
284
+ async restoreComment(commentId) {
285
+ if (!await this.client.auth.checkAuth()) return false;
286
+ try {
287
+ const url = `${this.client.baseUrl}/api/comments/${commentId}/restore`;
288
+ const response = await this.axios.post(url);
289
+ return response.status === 200 || response.status === 201 || response.status === 204;
290
+ } catch (error) {
291
+ console.error('Исключение при восстановлении комментария:', error.message);
292
+ return false;
293
+ }
294
+ }
260
295
 
261
296
  // ========== USER-FRIENDLY МЕТОДЫ ==========
262
297
 
package/src/files.js CHANGED
@@ -11,7 +11,8 @@ export class FilesManager {
11
11
  }
12
12
 
13
13
  /**
14
- * Загружает файл (изображение) на сервер.
14
+ * Загружает файл на сервер. POST /api/files/upload.
15
+ * Поддерживает изображения и аудио (audio/ogg для голосовых в комментариях).
15
16
  * Таймаут — client.uploadTimeout (по умолчанию 120 с). При ошибке возвращает null.
16
17
  *
17
18
  * @param {string} filePath - Путь к файлу
@@ -58,4 +59,43 @@ export class FilesManager {
58
59
  return null;
59
60
  }
60
61
  }
62
+
63
+ /**
64
+ * Получает информацию о файле. GET /api/files/{id}
65
+ *
66
+ * @param {string} fileId - ID файла
67
+ * @returns {Promise<Object|null>} { id, url, filename, mimeType, size, ... } или null
68
+ */
69
+ async getFile(fileId) {
70
+ if (!await this.client.auth.checkAuth()) return null;
71
+ try {
72
+ const url = `${this.client.baseUrl}/api/files/${fileId}`;
73
+ const response = await this.axios.get(url);
74
+ if (response.status === 200) {
75
+ return response.data?.data ?? response.data;
76
+ }
77
+ return null;
78
+ } catch (error) {
79
+ console.error('Ошибка получения файла:', error.message);
80
+ return null;
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Удаляет файл. DELETE /api/files/{id}
86
+ *
87
+ * @param {string} fileId - ID файла
88
+ * @returns {Promise<boolean>} True если успешно
89
+ */
90
+ async deleteFile(fileId) {
91
+ if (!await this.client.auth.checkAuth()) return false;
92
+ try {
93
+ const url = `${this.client.baseUrl}/api/files/${fileId}`;
94
+ const response = await this.axios.delete(url);
95
+ return response.status === 200 || response.status === 204;
96
+ } catch (error) {
97
+ console.error('Ошибка удаления файла:', error.message);
98
+ return false;
99
+ }
100
+ }
61
101
  }