itd-sdk-js 1.0.6 → 1.0.7

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 CHANGED
@@ -174,11 +174,24 @@ const post = await client.createPost('Текст поста', 'image.jpg');
174
174
 
175
175
  Получает дерево комментариев к посту.
176
176
 
177
- - **Параметры**: `postId`, `limit`, `sort` (`popular`, `new`, `old`).
177
+ - **Параметры**: `postId`, `limit` (по умолчанию 20, в запросе ограничивается 1–100), `sort` — в SDK можно передавать `"popular"`, `"new"`, `"old"`; в API уходит `popular`, `newest`, `oldest` соответственно.
178
+ - **Ответ API:** `{ data: { comments: [], total, hasMore, nextCursor } }`. Комментарии могут содержать вложенные `replies`, у ответов — поле `replyTo`.
178
179
 
179
180
  ### addComment(postId, text, replyToCommentId?)
180
181
 
181
- Добавляет новый комментарий или ответ на существующий.
182
+ Добавляет новый комментарий или ответ на существующий (POST к посту: `/api/posts/:postId/comments`).
183
+
184
+ ### replyToComment(commentId, content, replyToUserId)
185
+
186
+ Ответ на комментарий через отдельный эндпоинт **POST** `/api/comments/:commentId/replies`.
187
+
188
+ - **Параметры**:
189
+ - `commentId` — ID комментария, на который отвечаем.
190
+ - `content` — текст ответа.
191
+ - `replyToUserId` — ID пользователя-автора комментария (обязательно для API).
192
+ - **Возвращает:** объект созданного комментария-ответа или `null` при ошибке.
193
+
194
+ Пример: `client.replyToComment('80a775df-811a-4b60-b2fd-24651c1e546e', 'кака', '220e565c-45b9-4634-bdba-a6ebe6e8c5d1')`.
182
195
 
183
196
  ### Управление комментариями
184
197
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "itd-sdk-js",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "Unofficial SDK for итд.com - Node.js library for working with API. Automatic token refresh, session management, and convenient methods for posts, comments, users, and notifications.",
5
5
  "main": "src/client.js",
6
6
  "type": "module",
package/src/client.js CHANGED
@@ -481,6 +481,18 @@ export class ITDClient {
481
481
  async addComment(postId, text, replyToCommentId = null) {
482
482
  return await this.comments.addComment(postId, text, replyToCommentId);
483
483
  }
484
+
485
+ /**
486
+ * Ответ на комментарий (POST /api/comments/:id/replies).
487
+ *
488
+ * @param {string} commentId - ID комментария, на который отвечаем
489
+ * @param {string} content - Текст ответа
490
+ * @param {string} replyToUserId - ID пользователя-автора комментария (обязательно для API)
491
+ * @returns {Promise<Object|null>} Данные созданного комментария-ответа или null при ошибке
492
+ */
493
+ async replyToComment(commentId, content, replyToUserId) {
494
+ return await this.comments.replyToComment(commentId, content, replyToUserId);
495
+ }
484
496
 
485
497
  /**
486
498
  * Ставит лайк на комментарий
package/src/comments.js CHANGED
@@ -54,58 +54,107 @@ export class CommentsManager {
54
54
  return null;
55
55
  }
56
56
  }
57
+
58
+ /**
59
+ * Ответ на комментарий (отдельный эндпоинт /api/comments/:id/replies).
60
+ *
61
+ * @param {string} commentId - ID комментария, на который отвечаем
62
+ * @param {string} content - Текст ответа
63
+ * @param {string} replyToUserId - ID пользователя-автора комментария (обязательно для API)
64
+ * @returns {Promise<Object|null>} Данные созданного комментария-ответа или null при ошибке
65
+ */
66
+ async replyToComment(commentId, content, replyToUserId) {
67
+ if (!await this.client.auth.checkAuth()) {
68
+ console.error('Ошибка: необходимо войти в аккаунт');
69
+ return null;
70
+ }
71
+ if (!replyToUserId) {
72
+ console.error('Ошибка: replyToUserId обязателен для ответа на комментарий');
73
+ return null;
74
+ }
75
+ try {
76
+ const url = `${this.client.baseUrl}/api/comments/${commentId}/replies`;
77
+ const response = await this.axios.post(url, {
78
+ content,
79
+ replyToUserId,
80
+ });
81
+ if (response.status === 200 || response.status === 201) {
82
+ return response.data;
83
+ }
84
+ console.error(`Ошибка ответа на комментарий: ${response.status} - ${JSON.stringify(response.data)}`);
85
+ return null;
86
+ } catch (error) {
87
+ console.error('Исключение при ответе на комментарий:', error.message);
88
+ if (error.response) {
89
+ console.error('Response status:', error.response.status);
90
+ console.error('Response data:', error.response.data);
91
+ }
92
+ return null;
93
+ }
94
+ }
57
95
 
58
96
  /**
59
- * Получает комментарии к посту
60
- *
97
+ * Получает комментарии к посту.
98
+ * API ожидает sort: "newest" | "oldest" | "popular". SDK принимает "new"/"old"/"popular" и маппит в newest/oldest/popular.
99
+ *
61
100
  * @param {string} postId - ID поста
62
- * @param {number} limit - Количество комментариев
63
- * @param {string} sort - Сортировка: "popular", "new", "old" (по умолчанию "popular")
101
+ * @param {number} limit - Количество комментариев (по умолчанию 20)
102
+ * @param {string} sort - Сортировка: "popular", "new", "old" (в API уходит как popular, newest, oldest)
64
103
  * @returns {Promise<Object>} { comments: [], total, hasMore, nextCursor } или { comments: [] } при ошибке
65
- *
66
- * Примечание: Авторизация не требуется для просмотра комментариев
67
104
  */
68
105
  async getComments(postId, limit = 20, sort = 'popular') {
106
+ const commentsUrl = `${this.client.baseUrl}/api/posts/${postId}/comments`;
107
+ const reqLimit = Math.min(Math.max(1, Number(limit) || 20), 100);
108
+ const sortMap = { new: 'newest', old: 'oldest', popular: 'popular', newest: 'newest', oldest: 'oldest' };
109
+ const reqSort = sortMap[sort] || 'popular';
110
+
111
+ const parseResponse = (response) => {
112
+ const data = response.data?.data ?? response.data;
113
+ if (data?.comments) {
114
+ return {
115
+ comments: data.comments,
116
+ total: data.total ?? data.comments.length,
117
+ hasMore: data.hasMore ?? false,
118
+ nextCursor: data.nextCursor ?? null
119
+ };
120
+ }
121
+ if (Array.isArray(data)) {
122
+ return {
123
+ comments: data,
124
+ total: data.length,
125
+ hasMore: false,
126
+ nextCursor: null
127
+ };
128
+ }
129
+ return { comments: [], total: 0, hasMore: false, nextCursor: null };
130
+ };
131
+
69
132
  try {
70
- const commentsUrl = `${this.client.baseUrl}/api/posts/${postId}/comments`;
71
- const params = {
72
- limit: limit,
73
- sort: sort,
74
- };
75
-
76
- const response = await this.axios.get(commentsUrl, { params });
77
-
133
+ const response = await this.axios.get(commentsUrl, {
134
+ params: { limit: reqLimit, sort: reqSort },
135
+ });
136
+
78
137
  if (response.status === 200) {
79
- const data = response.data;
80
- // Структура: { data: { comments: [...], total, hasMore, nextCursor } }
81
- if (data.data && data.data.comments) {
82
- return {
83
- comments: data.data.comments,
84
- total: data.data.total || 0,
85
- hasMore: data.data.hasMore || false,
86
- nextCursor: data.data.nextCursor || null
87
- };
88
- } else if (data.comments) {
89
- return {
90
- comments: data.comments,
91
- total: data.total || 0,
92
- hasMore: data.hasMore || false,
93
- nextCursor: data.nextCursor || null
94
- };
95
- } else if (Array.isArray(data)) {
96
- return {
97
- comments: data,
98
- total: data.length,
99
- hasMore: false,
100
- nextCursor: null
101
- };
138
+ return parseResponse(response);
139
+ }
140
+ if (response.status === 422) {
141
+ const fallback = await this.axios.get(commentsUrl, { params: { limit: reqLimit, sort: 'popular' } });
142
+ if (fallback.status === 200) {
143
+ return parseResponse(fallback);
102
144
  }
103
- return { comments: [], total: 0, hasMore: false, nextCursor: null };
104
- } else {
105
- console.error(`Ошибка получения комментариев: ${response.status}`);
106
- return { comments: [], total: 0, hasMore: false, nextCursor: null };
145
+ console.warn('⚠️ GET /api/posts/:postId/comments: 422. API ожидает sort: newest | oldest | popular.');
107
146
  }
147
+ console.error(`Ошибка получения комментариев: ${response.status}`);
148
+ return { comments: [], total: 0, hasMore: false, nextCursor: null };
108
149
  } catch (error) {
150
+ if (error.response?.status === 422) {
151
+ try {
152
+ const retry = await this.axios.get(commentsUrl, { params: { limit: 20, sort: 'popular' } });
153
+ if (retry.status === 200) {
154
+ return parseResponse(retry);
155
+ }
156
+ } catch (_) {}
157
+ }
109
158
  console.error('Исключение при получении комментариев:', error.message);
110
159
  if (error.response) {
111
160
  console.error('Response status:', error.response.status);