itd-sdk-js 1.0.9 → 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/API_REFERENCE.md +132 -28
- package/examples/quick-start.js +2 -5
- package/package.json +1 -1
- package/src/auth.js +42 -5
- package/src/client.js +215 -31
- package/src/comments.js +48 -13
- package/src/files.js +41 -1
- package/src/notifications.js +50 -53
- package/src/posts.js +130 -24
- package/src/reports.js +8 -7
- package/src/users.js +68 -11
- package/src/verification.js +50 -0
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
|
|
|
@@ -200,6 +201,7 @@ export class ITDClient {
|
|
|
200
201
|
this.files = new FilesManager(this);
|
|
201
202
|
this.reports = new ReportsManager(this);
|
|
202
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
|
* Создает пост (удобный метод)
|
|
@@ -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
|
-
*
|
|
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 {
|
|
691
|
-
* @param {string|null} type - Фильтр по типу: 'reply', 'like', 'wall_post', 'follow', 'comment'
|
|
692
|
-
* @returns {Promise<Object|null>} { notifications: [],
|
|
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,
|
|
695
|
-
return await this.notifications.getNotifications(limit,
|
|
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 -
|
|
702
|
-
* @param {number} limit - Количество
|
|
703
|
-
* @param {
|
|
704
|
-
* @returns {Promise<Object|null>} { notifications: [],
|
|
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
|
|
707
|
-
return await this.notifications.
|
|
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
|
* Выполняет поиск пользователей и хэштегов
|
|
@@ -1030,12 +1214,12 @@ export class ITDClient {
|
|
|
1030
1214
|
|
|
1031
1215
|
/**
|
|
1032
1216
|
* Получает только непрочитанные уведомления (удобный метод)
|
|
1033
|
-
*
|
|
1034
|
-
* @param {number} limit - Количество
|
|
1035
|
-
* @param {
|
|
1036
|
-
* @returns {Promise<Object|null>} { notifications: [],
|
|
1217
|
+
*
|
|
1218
|
+
* @param {number} limit - Количество
|
|
1219
|
+
* @param {number} offset - Смещение
|
|
1220
|
+
* @returns {Promise<Object|null>} { notifications: [], hasMore } или null
|
|
1037
1221
|
*/
|
|
1038
|
-
async getUnreadNotifications(limit = 20,
|
|
1039
|
-
return await this.notifications.getUnreadNotifications(limit,
|
|
1222
|
+
async getUnreadNotifications(limit = 20, offset = 0) {
|
|
1223
|
+
return await this.notifications.getUnreadNotifications(limit, offset);
|
|
1040
1224
|
}
|
|
1041
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
|
-
|
|
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
|
}
|
package/src/notifications.js
CHANGED
|
@@ -8,14 +8,15 @@ export class NotificationsManager {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* Получает список
|
|
12
|
-
*
|
|
11
|
+
* Получает список уведомлений.
|
|
12
|
+
* GET /api/notifications/?offset=0&limit=20 → { notifications: [], hasMore }
|
|
13
|
+
*
|
|
13
14
|
* @param {number} limit - Количество уведомлений
|
|
14
|
-
* @param {
|
|
15
|
-
* @param {string|null} type - Фильтр по типу: 'reply', 'like', 'wall_post', 'follow', 'comment' (
|
|
16
|
-
* @returns {Promise<Object|null>} { notifications: [],
|
|
15
|
+
* @param {number} offset - Смещение для пагинации
|
|
16
|
+
* @param {string|null} type - Фильтр по типу: 'reply', 'like', 'wall_post', 'follow', 'comment' (на клиенте)
|
|
17
|
+
* @returns {Promise<Object|null>} { notifications: [], hasMore } или null при ошибке
|
|
17
18
|
*/
|
|
18
|
-
async getNotifications(limit = 20,
|
|
19
|
+
async getNotifications(limit = 20, offset = 0, type = null) {
|
|
19
20
|
if (!await this.client.auth.checkAuth()) {
|
|
20
21
|
console.error('Ошибка: необходимо войти в аккаунт');
|
|
21
22
|
return null;
|
|
@@ -23,42 +24,20 @@ export class NotificationsManager {
|
|
|
23
24
|
|
|
24
25
|
try {
|
|
25
26
|
const notificationsUrl = `${this.client.baseUrl}/api/notifications`;
|
|
26
|
-
const params = { limit };
|
|
27
|
-
if (cursor) {
|
|
28
|
-
params.cursor = cursor;
|
|
29
|
-
}
|
|
30
|
-
// Пробуем передать type в параметрах (если API поддерживает)
|
|
31
|
-
if (type) {
|
|
32
|
-
params.type = type;
|
|
33
|
-
}
|
|
27
|
+
const params = { limit, offset };
|
|
34
28
|
|
|
35
29
|
const response = await this.axios.get(notificationsUrl, { params });
|
|
36
30
|
|
|
37
31
|
if (response.status === 200) {
|
|
38
32
|
const data = response.data;
|
|
39
|
-
let notifications = [];
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
// Предполагаемая структура: { data: { notifications: [...], pagination: {...} } }
|
|
43
|
-
if (data.data && data.data.notifications) {
|
|
44
|
-
notifications = data.data.notifications;
|
|
45
|
-
pagination = data.data.pagination || {};
|
|
46
|
-
} else if (Array.isArray(data)) {
|
|
47
|
-
notifications = data;
|
|
48
|
-
} else if (data.notifications) {
|
|
49
|
-
notifications = data.notifications;
|
|
50
|
-
pagination = data.pagination || {};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Фильтруем по типу на клиенте (если API не поддерживает фильтрацию)
|
|
33
|
+
let notifications = Array.isArray(data?.notifications) ? data.notifications : [];
|
|
34
|
+
const hasMore = Boolean(data?.hasMore);
|
|
35
|
+
|
|
54
36
|
if (type && notifications.length > 0) {
|
|
55
37
|
notifications = notifications.filter(notif => notif.type === type);
|
|
56
38
|
}
|
|
57
|
-
|
|
58
|
-
return {
|
|
59
|
-
notifications: notifications,
|
|
60
|
-
pagination: pagination
|
|
61
|
-
};
|
|
39
|
+
|
|
40
|
+
return { notifications, hasMore };
|
|
62
41
|
} else {
|
|
63
42
|
console.error(`Ошибка получения уведомлений: ${response.status}`);
|
|
64
43
|
return null;
|
|
@@ -73,6 +52,34 @@ export class NotificationsManager {
|
|
|
73
52
|
}
|
|
74
53
|
}
|
|
75
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Отмечает несколько уведомлений как прочитанные.
|
|
57
|
+
* POST /api/notifications/read-batch → { success: true, count: number }
|
|
58
|
+
*
|
|
59
|
+
* @param {string[]} ids - Массив ID уведомлений
|
|
60
|
+
* @returns {Promise<Object|null>} { success: true, count } или null при ошибке
|
|
61
|
+
*/
|
|
62
|
+
async markAsReadBatch(ids) {
|
|
63
|
+
if (!await this.client.auth.checkAuth()) {
|
|
64
|
+
console.error('Ошибка: необходимо войти в аккаунт');
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
if (!Array.isArray(ids) || ids.length === 0) {
|
|
68
|
+
return { success: true, count: 0 };
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
const url = `${this.client.baseUrl}/api/notifications/read-batch`;
|
|
72
|
+
const response = await this.axios.post(url, { ids });
|
|
73
|
+
if (response.status === 200) {
|
|
74
|
+
return response.data;
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
} catch (error) {
|
|
78
|
+
console.error('Исключение при отметке уведомлений:', error.message);
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
76
83
|
/**
|
|
77
84
|
* Отмечает уведомление как прочитанное
|
|
78
85
|
*
|
|
@@ -144,8 +151,8 @@ export class NotificationsManager {
|
|
|
144
151
|
|
|
145
152
|
/**
|
|
146
153
|
* Отмечает все уведомления как прочитанные.
|
|
147
|
-
*
|
|
148
|
-
*
|
|
154
|
+
* POST /api/notifications/read-all → { success: true }
|
|
155
|
+
*
|
|
149
156
|
* @returns {Promise<boolean>} True если успешно
|
|
150
157
|
*/
|
|
151
158
|
async markAllAsRead() {
|
|
@@ -155,12 +162,11 @@ export class NotificationsManager {
|
|
|
155
162
|
}
|
|
156
163
|
|
|
157
164
|
try {
|
|
158
|
-
// Нужно найти реальный endpoint, пока используем предположительный
|
|
159
165
|
const readAllUrl = `${this.client.baseUrl}/api/notifications/read-all`;
|
|
160
166
|
const response = await this.axios.post(readAllUrl);
|
|
161
167
|
|
|
162
168
|
if (response.status === 200 || response.status === 204) {
|
|
163
|
-
return
|
|
169
|
+
return response.data?.success !== false;
|
|
164
170
|
} else {
|
|
165
171
|
console.error(`Ошибка отметки всех уведомлений: ${response.status}`);
|
|
166
172
|
if (response.data) {
|
|
@@ -173,10 +179,6 @@ export class NotificationsManager {
|
|
|
173
179
|
if (error.response) {
|
|
174
180
|
console.error('Response status:', error.response.status);
|
|
175
181
|
console.error('Response data:', error.response.data);
|
|
176
|
-
// Если 404 - значит endpoint неправильный, нужно найти реальный
|
|
177
|
-
if (error.response.status === 404) {
|
|
178
|
-
console.error('💡 Endpoint не найден. Найди реальный URL в DevTools');
|
|
179
|
-
}
|
|
180
182
|
}
|
|
181
183
|
return false;
|
|
182
184
|
}
|
|
@@ -196,21 +198,16 @@ export class NotificationsManager {
|
|
|
196
198
|
|
|
197
199
|
/**
|
|
198
200
|
* Получает только непрочитанные уведомления (удобный метод)
|
|
199
|
-
*
|
|
201
|
+
*
|
|
200
202
|
* @param {number} limit - Количество уведомлений
|
|
201
|
-
* @param {
|
|
202
|
-
* @returns {Promise<Object|null>} { notifications: [],
|
|
203
|
+
* @param {number} offset - Смещение для пагинации
|
|
204
|
+
* @returns {Promise<Object|null>} { notifications: [], hasMore } или null
|
|
203
205
|
*/
|
|
204
|
-
async getUnreadNotifications(limit = 20,
|
|
205
|
-
const all = await this.getNotifications(limit,
|
|
206
|
+
async getUnreadNotifications(limit = 20, offset = 0) {
|
|
207
|
+
const all = await this.getNotifications(limit, offset);
|
|
206
208
|
if (!all) return null;
|
|
207
|
-
|
|
208
|
-
// Фильтруем только непрочитанные
|
|
209
209
|
const unread = all.notifications.filter(n => !n.read);
|
|
210
|
-
return {
|
|
211
|
-
notifications: unread,
|
|
212
|
-
pagination: all.pagination
|
|
213
|
-
};
|
|
210
|
+
return { notifications: unread, hasMore: all.hasMore };
|
|
214
211
|
}
|
|
215
212
|
|
|
216
213
|
}
|