itd-api 0.1.0 → 0.2.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.
Files changed (80) hide show
  1. package/README.md +114 -489
  2. package/dist/index.cjs +8781 -415
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +4990 -1
  5. package/dist/index.d.ts +4990 -1
  6. package/dist/index.js +8688 -2
  7. package/dist/index.js.map +1 -1
  8. package/dist/multi-storage-BhcA2Izn.d.ts +198 -0
  9. package/dist/multi-storage-CyMe404l.js +805 -0
  10. package/dist/multi-storage-CyMe404l.js.map +1 -0
  11. package/dist/multi-storage-D1keK2Op.cjs +930 -0
  12. package/dist/multi-storage-D1keK2Op.cjs.map +1 -0
  13. package/dist/multi-storage-NDqzRQcD.d.cts +198 -0
  14. package/dist/node.cjs +225 -548
  15. package/dist/node.cjs.map +1 -1
  16. package/dist/node.d.cts +46 -59
  17. package/dist/node.d.ts +46 -59
  18. package/dist/node.js +223 -126
  19. package/dist/node.js.map +1 -1
  20. package/dist/runtime-CFEsf-jD.cjs +185 -0
  21. package/dist/runtime-CFEsf-jD.cjs.map +1 -0
  22. package/dist/runtime-DHxDn8gf.js +126 -0
  23. package/dist/runtime-DHxDn8gf.js.map +1 -0
  24. package/dist/storage-BjNRlkbE.d.cts +82 -0
  25. package/dist/storage-BjNRlkbE.d.ts +82 -0
  26. package/dist/storage-D9tfHx7Z.js +424 -0
  27. package/dist/storage-D9tfHx7Z.js.map +1 -0
  28. package/dist/storage-ycBqLBRB.cjs +615 -0
  29. package/dist/storage-ycBqLBRB.cjs.map +1 -0
  30. package/dist/web.cjs +87 -0
  31. package/dist/web.cjs.map +1 -0
  32. package/dist/web.d.cts +27 -0
  33. package/dist/web.d.ts +27 -0
  34. package/dist/web.js +86 -0
  35. package/dist/web.js.map +1 -0
  36. package/package.json +34 -14
  37. package/dist/chunk-6FB4HTKH.js +0 -7763
  38. package/dist/chunk-6FB4HTKH.js.map +0 -1
  39. package/dist/chunk-73CISRBG.cjs +0 -7873
  40. package/dist/chunk-73CISRBG.cjs.map +0 -1
  41. package/dist/index-BZF4K90s.d.cts +0 -4961
  42. package/dist/index-BZF4K90s.d.ts +0 -4961
  43. package/guides/README.md +0 -24
  44. package/guides/authentication/README.md +0 -176
  45. package/guides/authentication/examples/bot-with-session.mjs +0 -98
  46. package/guides/authentication/examples/turnstile-login.mjs +0 -56
  47. package/guides/integrations/README.md +0 -62
  48. package/guides/integrations/examples/proxy.mjs +0 -26
  49. package/guides/multi-accounts/README.md +0 -143
  50. package/guides/multi-accounts/examples/multi-accounts.mjs +0 -71
  51. package/guides/plugins/README.md +0 -253
  52. package/guides/plugins/examples/cache.mjs +0 -33
  53. package/guides/plugins/examples/crypto.mjs +0 -54
  54. package/guides/quickstart/README.md +0 -124
  55. package/guides/quickstart/examples/quick-start.mjs +0 -44
  56. package/guides/quickstart/examples/typescript.ts +0 -90
  57. package/guides/realtime/README.md +0 -109
  58. package/guides/realtime/examples/notifications.mjs +0 -62
  59. package/guides/reference/README.md +0 -67
  60. package/guides/reference/accounts.md +0 -101
  61. package/guides/reference/auth.md +0 -141
  62. package/guides/reference/builders.md +0 -135
  63. package/guides/reference/client.md +0 -184
  64. package/guides/reference/comments.md +0 -58
  65. package/guides/reference/discovery.md +0 -81
  66. package/guides/reference/enums.md +0 -103
  67. package/guides/reference/errors.md +0 -107
  68. package/guides/reference/files.md +0 -73
  69. package/guides/reference/models.md +0 -448
  70. package/guides/reference/notifications.md +0 -77
  71. package/guides/reference/pagination.md +0 -82
  72. package/guides/reference/platform.md +0 -47
  73. package/guides/reference/posts.md +0 -157
  74. package/guides/reference/realtime.md +0 -78
  75. package/guides/reference/reports.md +0 -28
  76. package/guides/reference/subscription.md +0 -41
  77. package/guides/reference/users.md +0 -146
  78. package/guides/reference/verification.md +0 -24
  79. package/guides/text-markup/README.md +0 -214
  80. package/guides/text-markup/examples/create-post.mjs +0 -64
package/README.md CHANGED
@@ -1,533 +1,158 @@
1
- # itd-api
2
-
3
- Клиент REST и realtime API социальной сети **итд.com** для JavaScript и TypeScript.
4
-
5
- - **Ноль зависимостей** у установленного пакета
6
- - **Работает везде**: Node 18+, браузер, Bun, Deno, React Native — только web-стандарты
7
- - **ESM и CommonJS**, полные `.d.ts` с описаниями на русском
8
- - Авторизация, продление токена, повторы и очередь запросов — **сами**
9
- - Три схемы пагинации спрятаны за одним `for await`
10
- - Уведомления из REST и из потока приведены к **одной форме**
11
-
12
- ```bash
13
- npm install itd-api
14
- ```
15
-
16
- ---
17
-
18
- ## Быстрый старт
19
-
20
- ```ts
21
- import { ItdClient, FeedTab } from 'itd-api';
22
-
23
- const itd = new ItdClient({ auth: process.env.ITD_TOKEN });
24
-
25
- const me = await itd.users.me();
26
- console.log(`@${me.username}, подписчиков: ${me.followersCount}`);
27
-
28
- for await (const post of itd.posts.iterate({ tab: FeedTab.Following })) {
29
- if (!post.isLiked) await itd.posts.like(post.id);
30
- }
31
- ```
32
-
33
- В Node, Bun и Deno импортируйте `itd-api/node` — оттуда доступны загрузка файлов по пути
34
- и хранение сессии в файле:
35
-
36
- ```ts
37
- import { ItdClient, FileTokenStorage } from 'itd-api/node';
38
-
39
- // Сессия из файла: продлевается сама, `auth` не нужен. Как её туда положить —
40
- // в разделе «Авторизация»: вход требует капчи, поэтому делается один раз.
41
- const itd = new ItdClient({ storage: new FileTokenStorage('./.itd-session.json') });
42
-
43
- await itd.posts.create((p) => p.content('привет').attach('./photo.jpg'));
44
- ```
45
-
46
- Продолжение с запускаемыми примерами — в [руководстве по быстрому старту](./guides/quickstart/README.md).
47
- Все тематические материалы собраны в [`guides/`](./guides/README.md), а технический справочник
48
- методов и типов по категориям — в [`reference/`](./guides/reference/README.md).
49
-
50
- ---
51
-
52
- ## Авторизация
53
-
54
- Клиент может взять доступ из `auth`, сохранённой сессии или явного вызова `itd.auth`:
55
-
56
- ```ts
57
- new ItdClient({ auth: '<accessToken>' });
58
- new ItdClient({ auth: { accessToken, refreshToken } });
59
- new ItdClient({ auth: { email, password, getTurnstileToken } });
60
- new ItdClient({ storage: new FileTokenStorage('./.itd-session.json') });
61
- ```
62
-
63
- При `401` сессия продлевается, исходный запрос повторяется, а новое состояние сохраняется.
64
- Параллельные запросы ждут одного refresh. Потерю сессии можно отследить:
65
-
66
- ```ts
67
- itd.on('authError', ({ error }) => {
68
- if (isItdApiError(error)) console.error('Сессия потеряна:', error.code);
69
- });
70
- ```
71
-
72
- Вход, регистрация и восстановление пароля требуют одноразовый Turnstile token. Подробности
73
- о cookie, `deviceId`, OTP, собственном storage и автоматическом решателе:
74
- [руководство по авторизации](./guides/authentication/README.md).
75
-
76
- ---
77
-
78
- ## Несколько аккаунтов
79
-
80
- `ItdAccounts` хранит именованные клиенты с отдельными tokens, cookie и `deviceId`, но одним
81
- `MultiTokenStorage`:
82
-
83
- ```ts
84
- import { ItdAccounts, FileMultiTokenStorage } from 'itd-api/node';
85
-
86
- const accounts = new ItdAccounts({
87
- storage: new FileMultiTokenStorage('./.itd-sessions.json'),
88
- rateLimit: { concurrency: 4 },
89
- });
90
-
91
- // Поднимаем тех, кто уже входил раньше: ни auth, ни капча не нужны.
92
- await accounts.restore();
93
-
94
- if (!accounts.has('kiow')) {
95
- accounts.addAccount('kiow', { auth: { email, password, getTurnstileToken } });
96
- }
97
-
98
- const itd = accounts.account('kiow'); // обычный ItdClient со всеми разделами
99
- await itd.posts.create({ content: 'привет' });
100
- await accounts.close();
101
- ```
102
-
103
- Личные прокси, общая или раздельные очереди, собственное хранилище и события контейнера
104
- описаны в [руководстве по нескольким аккаунтам](./guides/multi-accounts/README.md).
105
-
106
- ---
107
-
108
- ## Пагинация
109
-
110
- Три разные схемы API (курсор, страницы, смещение) выглядят одинаково:
111
-
112
- ```ts
113
- // по элементам
114
- for await (const post of itd.posts.iterate({ tab: 'popular' })) { … }
115
-
116
- // по страницам — когда нужны сведения о самой странице
117
- for await (const page of itd.posts.iterateComments(postId).pages()) {
118
- console.log(page.items.length, 'из', page.total);
119
- }
120
-
121
- // набрать нужное количество и остановиться
122
- const posts = await itd.posts.iterate({ tab: 'popular' }).collect(100);
123
- ```
124
-
125
- Отдельные страницы тоже доступны:
126
-
127
- ```ts
128
- const page = await itd.posts.list({ tab: 'popular', limit: 20 });
129
- const next = await itd.posts.list({ tab: 'popular', cursor: page.nextCursor ?? undefined });
130
- ```
131
-
132
- Курсор непрозрачен: у вкладки `popular` это номер страницы, у `following` — отметка времени.
133
- Передавайте его обратно как есть.
134
-
135
- Перебор одноразовый: позиция хранится внутри, поэтому второй `for await` по тому же объекту
136
- ничего не выдаст. Нужен ещё проход — возьмите новый перебор у того же метода.
137
-
138
- ### Чего API не умеет
139
-
140
- **Подписчики, подписки и заблокированные не листаются.** Сервер отдаёт первые 20 записей
141
- и на этом всё: `page` он игнорирует, `limit` больше 20 молча уменьшает, а `hasMore` всегда
142
- `false`. Числу `total` там тоже верить нельзя: оно расходится с `followersCount` из профиля.
143
-
144
- ```ts
145
- // вернёт 20 записей и остановится — это предел API, а не библиотеки
146
- const all = await itd.users.iterateFollowers('durov').collect();
147
- ```
148
-
149
- **`posts.byUser()` — это стена, а не авторские посты.** В неё входят и записи, которые
150
- другие оставили на странице пользователя, поэтому записей обычно больше, чем `postsCount`
151
- в профиле. Нужны только свои — отфильтруйте по `post.author.id`.
152
-
153
- ---
154
-
155
- ## Публикация
156
-
157
- Три равноправные формы, проверки одинаковы для каждой:
158
-
159
- ```ts
160
- // обычный объект
161
- await itd.posts.create({ content: 'привет' });
162
-
163
- // функция-настройщик — импорты не нужны
164
- await itd.posts.create((p) =>
165
- p.content('привет')
166
- .attach('./photo.jpg')
167
- .poll((q) => q.question('нравится?').options('да', 'нет')),
168
- );
169
-
170
- // билдер — когда объект готовится заранее
171
- import { post, poll } from 'itd-api';
172
-
173
- const draft = post().onWall(userId);
174
- await itd.posts.create(draft.content('первый'));
175
- await itd.posts.create(draft.content('второй')); // заготовка не испорчена
176
- ```
177
-
178
- Файлы из `attach()` загружаются автоматически, порядок вложений сохраняется, MIME-тип
179
- проверяется до отправки.
180
-
181
- ### Разметка текста
182
-
183
- Билдер собирает текст и сам считает смещения:
184
-
185
- ```ts
186
- import { post, renderSpans } from 'itd-api';
187
-
188
- const created = await itd.posts.create(
189
- post().markup((m) =>
190
- m
191
- .text('смотрите ')
192
- .hashtag('котики')
193
- .text(' от ')
194
- .mention('durov')
195
- .text(': ')
196
- .bold('важно'),
197
- ),
198
- );
199
-
200
- renderSpans(created.content, created.spans); // безопасный HTML по умолчанию
201
- ```
202
-
203
- Доступны `bold`, `italic`, `underline`, `strike`, `spoiler`, `monospace`, `quote`, `link`,
204
- `hashtag`, `mention`, `span()` и несколько стилей сразу через `styled()`. Вложенные и
205
- пересекающиеся spans поддерживаются. Смещения измеряются в единицах UTF-16, как индексы
206
- строк и DOM Selection в JavaScript.
207
-
208
- Для обычного текста есть автоматическое обнаружение ссылок, хэштегов и упоминаний:
1
+ <p align="center">
2
+ <picture>
3
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/KiowDev/itd-api/main/guides/web/public/logos/itd-api-logo-horizontal-dark.svg">
4
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/KiowDev/itd-api/main/guides/web/public/logos/itd-api-logo-horizontal.svg">
5
+ <img alt="itd-api" src="https://raw.githubusercontent.com/KiowDev/itd-api/main/guides/web/public/logos/itd-api-logo-horizontal.svg" width="560">
6
+ </picture>
7
+ </p>
209
8
 
210
- ```ts
211
- await itd.posts.create(post('#котики от @durov: https://example.com').autoSpans());
212
- ```
213
-
214
- `renderSpans()` также выводит Markdown и ANSI и позволяет настроить маршруты упоминаний,
215
- хэштегов и префикс CSS-классов. Вызов `postBuilder.content(newText)` сбрасывает прежние
216
- spans, поскольку они рассчитаны для другого текста. `posts.update()` принимает тот же билдер,
217
- но требует явно заданный `content`.
218
-
219
- Авторазметка, пересекающиеся стили, обновление и настройка рендера подробно разобраны
220
- в [руководстве по разметке](./guides/text-markup/README.md).
221
-
222
- Билдеры есть у разметки, поста, комментария, опроса и жалобы. Все они неизменяемые, а `build()`
223
- проверяет данные и бросает `ItdConfigError` **до** обращения к сети:
224
-
225
- ```ts
226
- post('привет').onWall('durov');
227
- // ItdConfigError: wallRecipientId должен быть UUID, а не именем пользователя
228
- // (получено: «durov»). Идентификатор можно взять из профиля:
229
- // (await itd.users.get(username)).id
230
- ```
231
-
232
- ---
233
-
234
- ## Уведомления и realtime
235
-
236
- ```ts
237
- import { formatNotificationText, resolveNotificationUrl } from 'itd-api';
238
-
239
- const stream = itd.realtime();
240
-
241
- stream.on('notification', ({ notification }) => {
242
- console.log(formatNotificationText(notification)); // «Аня и ещё 2 оценили ваш пост»
243
- console.log(resolveNotificationUrl(notification)); // '/@anya/post/9f1c…'
244
- });
245
-
246
- await stream.connect();
247
- ```
248
-
249
- REST и поток используют одну форму уведомления. Переподключение, refresh token, keep-alive
250
- и fallback на polling обрабатываются внутри. Эксплуатационные настройки и счётчик
251
- непрочитанных разобраны в [руководстве по realtime](./guides/realtime/README.md).
252
-
253
- ---
254
-
255
- ## Статус сервисов
256
-
257
- `itd.platform.status()` отдаёт состояние платформы и историю доступности за 90 суток.
258
- Авторизация не нужна, ответ кэшируется сервером на минуту.
9
+ # itd-api
259
10
 
260
- ```ts
261
- import { statusDays } from 'itd-api';
11
+ [![npm version](https://img.shields.io/npm/v/itd-api.svg)](https://www.npmjs.com/package/itd-api)
12
+ [![npm downloads](https://img.shields.io/npm/dm/itd-api.svg)](https://www.npmjs.com/package/itd-api)
13
+ [![CI](https://github.com/KiowDev/itd-api/actions/workflows/ci.yml/badge.svg)](https://github.com/KiowDev/itd-api/actions/workflows/ci.yml)
14
+ [![Node.js](https://img.shields.io/node/v/itd-api.svg)](https://www.npmjs.com/package/itd-api)
15
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0%2B-3178c6.svg)](./tsconfig.json)
16
+ [![license](https://img.shields.io/npm/l/itd-api.svg)](./LICENSE)
262
17
 
263
- const status = await itd.platform.status();
18
+ Независимый TypeScript-клиент REST и realtime API социальной сети **итд.com**.
19
+ Проект не является официальным SDK и не аффилирован с итд.com.
264
20
 
265
- status.overall_status; // 'operational' | 'degraded' | 'downtime'
266
- status.services.map((s) => s.current_status);
21
+ [Документация](https://kiowdev.github.io/itd-api/) ·
22
+ [Быстрый старт](https://kiowdev.github.io/itd-api/quickstart/) ·
23
+ [Руководства](https://kiowdev.github.io/itd-api/guides/) ·
24
+ [Справочник API](https://kiowdev.github.io/itd-api/reference/) ·
25
+ [Совместимость](#совместимость) ·
26
+ [Сеть и доверие](#сеть-и-доверие) ·
27
+ [Пакеты проекта](#пакеты-проекта)
267
28
 
268
- const auth = status.services.find((s) => s.id === 'auth');
269
- auth?.uptime_90d; // 97.92
270
- auth?.last_checked; // '2026-07-23T23:14:25Z'
29
+ ## Установка
271
30
 
272
- const days = auth ? statusDays(auth) : []; // 90 элементов, [0] — сегодня
273
- days[0]?.uptime; // 100
274
- days[0]?.lines; // [{ t: 'down', text: 'недоступен 6 мин (12:00–12:06)' }]
31
+ ```bash
32
+ npm install itd-api
275
33
  ```
276
34
 
277
- Поле `days` приходит объектом с числовыми ключами, и сутки без данных сервер пропускает —
278
- `statusDays()` разворачивает его в массив, где пропуски равны `null`. Строки в `lines`
279
- готовы к показу как есть: длительность и границы интервала отдельными полями не приходят,
280
- время в них московское, тогда как `date_key` суток нарезан по UTC.
281
-
282
- ### Сервисы платформы
283
-
284
- Статус живёт на отдельном домене — `статус.итд.com`. Такие домены описываются как сервисы:
285
- у каждого своё имя, хост, заголовки и признак публичности. Запрос выбирает сервис
286
- полем `service`.
35
+ Передайте access token и запросите посты со стены пользователя:
287
36
 
288
37
  ```ts
289
- const itd = new ItdClient({
290
- services: {
291
- pb: {
292
- baseUrl: 'https://pbapi.xn--d1ah4a.com',
293
- headers: { Referer: 'https://pixel.xn--d1ah4a.com/' },
294
- },
295
- },
296
- });
297
-
298
- await itd.request({ method: 'GET', service: 'pb', path: '/api/pixel-info', query: { x: 1, y: 2 } });
299
- ```
300
-
301
- То же самое после создания клиента — `itd.defineService({ name, baseUrl, headers, auth })`;
302
- базовый URL сервиса отдаёт `itd.serviceBaseUrl(name)`.
303
-
304
- Bearer-токен по умолчанию отправляется только основному хосту и его поддоменам.
305
- Публичный или сторонний сервис его не получает. То же правило действует для разового
306
- `itd.request({ baseUrl })`; если внешнему хосту действительно нужна авторизация,
307
- разрешите её явно через `skipAuth: false`.
308
-
309
- У каждого сервиса своя очередь `rateLimit`: лимит частоты сервер считает по хосту, поэтому
310
- `429` от статуса не тормозит основной API и наоборот.
311
-
312
- ---
313
-
314
- ## Ошибки
38
+ import { ItdClient } from 'itd-api';
315
39
 
316
- Обе формы ошибок API сведены к одному классу:
40
+ const itd = new ItdClient({ auth: '<accessToken>' });
41
+ const page = await itd.posts.byUser('nowkie', { limit: 10 });
317
42
 
318
- ```ts
319
- import { ItdValidationError, ItdRateLimitError, isItdApiError } from 'itd-api';
320
-
321
- try {
322
- await itd.users.updateMe({ username: 'занятое_имя' });
323
- } catch (error) {
324
- if (error instanceof ItdValidationError) {
325
- console.log(error.fieldErrors.username); // ['Имя уже занято']
326
- } else if (error instanceof ItdRateLimitError) {
327
- console.log(error.retryAfter); // мс
328
- } else if (isItdApiError(error)) {
329
- console.log(error.status, error.code, error.message);
330
- }
43
+ for (const post of page.items) {
44
+ console.log(post.author.username, post.content);
331
45
  }
332
46
  ```
333
47
 
334
- `ItdApiError` `ItdValidationError`, `ItdAuthError`, `ItdForbiddenError`, `ItdNotFoundError`,
335
- `ItdConflictError`, `ItdRateLimitError`, `ItdPhoneVerificationError`, `ItdServerError`.
336
- Отдельно: `ItdNetworkError`, `ItdTimeoutError`, `ItdAbortError`, `ItdConfigError`.
337
-
338
- ---
339
-
340
- ## Настройка
341
-
342
- ```ts
343
- const itd = new ItdClient({
344
- baseUrl: 'https://xn--d1ah4a.com', // свой прокси, если работаете из браузера
345
- auth: { email, password, getTurnstileToken },
346
- storage: new FileTokenStorage('./.itd-session.json'),
347
- timeout: 30_000,
348
- retry: { attempts: 3, retryWrites: false },
349
- rateLimit: { concurrency: 4, rps: 8 },
350
- // Заголовки латиницей: кириллица в них запрещена самим HTTP.
351
- userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36', // по умолчанию itd-api/<версия>; false — не слать
352
- deviceId: '3f2a…-uuid', // по умолчанию заводится сам и живёт в сессии
353
- services: { pb: 'https://pbapi.xn--d1ah4a.com' }, // домены сервисов платформы, см. ниже
354
- logger: true, // токены и пароли в логах маскируются
355
- hooks: {
356
- onRequest: (ctx) => console.log(ctx.method, ctx.path),
357
- onRetry: (ctx) => console.log('повтор через', ctx.delay),
358
- },
359
- });
360
- ```
361
-
362
- **Повторы.** Обрыв сети и `5xx` не гарантируют, что запрос не был обработан, поэтому запись
363
- по умолчанию не повторяется (`retryWrites: false`): повтор мог бы создать дубль поста.
364
- Чтения повторяются с экспоненциальным откатом.
48
+ Для долгоживущего приложения восстановите сохранённую сессию или настройте вход по
49
+ [руководству по авторизации](https://kiowdev.github.io/itd-api/authentication/).
365
50
 
366
- **Очередь: `concurrency` и `rps` решают разные задачи.** Все запросы идут через одну очередь
367
- клиента, поэтому достаточно **одного экземпляра `ItdClient` на приложение** — разложите его
368
- по модулям, и темп будет общим.
51
+ ## Возможности
369
52
 
370
- `concurrency` (по умолчанию 6) ограничивает только одновременность. От ограничения частоты
371
- он почти не спасает: десять запросов подряд при `concurrency: 1` уходят за ~150 мс,
372
- а окно сервера измеряется десятками секунд. Темп задаёт `rps`:
373
-
374
- ```ts
375
- rateLimit: { concurrency: 2, rps: 0.5 } // не чаще одного запроса в 2 секунды
376
- ```
377
-
378
- Ставить `concurrency: 1` без нужды не стоит: загрузка видео с таймаутом в 300 секунд
379
- заблокирует на это время вообще всё остальное.
380
-
381
- **Ограничение частоты — отдельный механизм.** Лимит у каждого эндпоинта свой: замеры по
382
- `x-ratelimit-limit` дали 90 у `/api/posts`, 40 у `/api/users/me` и `/api/notifications/`,
383
- 25 у `/api/v1/auth/refresh` и всего 15 у `/api/files/upload`. Сервер
384
- не присылает `Retry-After` и не сообщает, когда окно сбросится: есть только заголовки
385
- `x-ratelimit-limit` и `x-ratelimit-remaining` (доступны на `ItdRateLimitError` как
386
- `rateLimit` и `rateLimitRemaining`).
387
-
388
- Экспоненциальный откат в сотни миллисекунд при окне около минуты бесполезен, поэтому
389
- для `429` используется лестница пауз:
390
-
391
- ```ts
392
- rateLimit: { retryDelays: [1000, 5000, 30_000, 60_000, 90_000] } // по умолчанию
393
- ```
394
-
395
- Первый шаг короткий — вдруг окно уже истекло, тогда работа продолжится почти сразу.
396
- Дальше паузы выходят на масштаб окна. Когда лестница кончилась, `ItdRateLimitError`
397
- пробрасывается вам. Список не зависит от `retry.attempts` и переопределяется одной строкой.
398
-
399
- Дополнительно очередь **тормозит заранее**: как только `x-ratelimit-remaining` доходит
400
- до нуля, запросы придерживаются, не дожидаясь отказа. Отключается через
401
- `rateLimit: { respectHeaders: false }`.
402
-
403
- ### Про CORS
404
-
405
- **Напрямую из браузера запросы работать не будут.** Проверено запросами к боевому API:
406
- на preflight сервер отвечает `204` с `Access-Control-Allow-Methods` и
407
- `Access-Control-Allow-Credentials`, но **без `Access-Control-Allow-Origin`** — браузер
408
- такой ответ отвергает.
409
-
410
- Поэтому в браузерном приложении укажите в `baseUrl` адрес своего прокси. В Node, Bun,
411
- Deno и React Native ограничение не действует.
412
-
413
- Исключение — `itd.platform.status()`: страница статуса отдаёт
414
- `Access-Control-Allow-Origin: *`, и этот метод работает из браузера напрямую.
415
-
416
- ### Прокси (HTTP/SOCKS5)
53
+ | Область | Что поддерживается |
54
+ |---|---|
55
+ | REST API | пользователи, посты, комментарии, файлы, уведомления, поиск, жалобы, верификация и подписка |
56
+ | Авторизация | access/refresh token, автоматическое обновление, OTP, хранение сессии и несколько аккаунтов |
57
+ | Realtime | SSE с переподключением и fallback на polling |
58
+ | Пагинация | разные серверные схемы через единый `for await` |
59
+ | Публикация | билдеры постов, комментариев, опросов, разметки текста и загрузки файлов |
60
+ | Надёжность | таймауты, отмена, очередь, rate limiting, безопасные повторы, хуки и типизированные ошибки |
61
+ | Расширение | плагины, собственный `fetch`, сервисы и произвольные запросы |
62
+ | Платформа | версии приложений, changelog, анонсы, портал и состояние сервисов |
417
63
 
418
- Чтобы направить запросы клиента через прокси, возьмите `fetch` из пакета
419
- [`@itd-api/proxy`](./proxy/README.md):
64
+ У основного пакета нет runtime-зависимостей. Он поставляется как ESM и CommonJS с
65
+ полными TypeScript-типами.
420
66
 
421
- ```sh
422
- npm i @itd-api/proxy
423
- ```
67
+ ## Пакеты проекта
424
68
 
425
- ```ts
426
- import { ItdClient } from 'itd-api';
427
- import { proxyFetch } from '@itd-api/proxy';
69
+ Все пакеты в таблице поддерживаются проектом itd-api.
428
70
 
429
- const fetch = proxyFetch('socks5://127.0.0.1:1080');
430
- // http://…, https://…, socks5://… — можно с user:pass@
431
- const itd = new ItdClient({ fetch });
71
+ | Пакет | Назначение | Среда | npm | Документация |
72
+ |---|---|---|---|---|
73
+ | `itd-api` | REST/realtime-клиент | Node.js 18+, браузер, Bun, Deno, React Native | [npm](https://www.npmjs.com/package/itd-api) | [быстрый старт](https://kiowdev.github.io/itd-api/quickstart/) |
74
+ | `@itd-api/cache` | TTL/LRU-кэш и дедупликация запросов | среды основного клиента | [npm](https://www.npmjs.com/package/@itd-api/cache) | [документация](https://kiowdev.github.io/itd-api/packages/cache) |
75
+ | `@itd-api/crypto` | скрытые сообщения в постах, комментариях и профилях | среды основного клиента | [npm](https://www.npmjs.com/package/@itd-api/crypto) | [документация](https://kiowdev.github.io/itd-api/packages/crypto) |
76
+ | `@itd-api/proxy` | HTTP/HTTPS- и SOCKS5-транспорт | Node.js 18+, Bun, Deno | [npm](https://www.npmjs.com/package/@itd-api/proxy) | [документация](https://kiowdev.github.io/itd-api/packages/proxy) |
77
+ | `@itd-api/turnstile` | получение Turnstile-токена в локальном браузере | Node.js 18+, Bun, Deno + Playwright | [npm](https://www.npmjs.com/package/@itd-api/turnstile) | [документация](https://kiowdev.github.io/itd-api/packages/turnstile) |
432
78
 
433
- // …работа…
79
+ ## Документация
434
80
 
435
- await itd.close();
436
- await fetch.close(); // закрывает пул соединений
437
- ```
81
+ | Раздел | Содержание |
82
+ |---|---|
83
+ | [Быстрый старт](https://kiowdev.github.io/itd-api/quickstart/) | создание клиента, чтение и публикация, пагинация, ошибки |
84
+ | [Авторизация](https://kiowdev.github.io/itd-api/authentication/) | токены, Turnstile, OTP, refresh и хранение сессии |
85
+ | [Конфигурация](https://kiowdev.github.io/itd-api/configuration/) | таймауты, повторы, очереди, сервисы, hooks и lifecycle |
86
+ | [Несколько аккаунтов](https://kiowdev.github.io/itd-api/multi-accounts/) | `ItdAccounts`, общее хранилище и отдельные сессии |
87
+ | [Разметка текста](https://kiowdev.github.io/itd-api/text-markup/) | spans, автоматическая разметка и отображение |
88
+ | [Realtime](https://kiowdev.github.io/itd-api/realtime/) | события, SSE, polling и переподключение |
89
+ | [Интеграции](https://kiowdev.github.io/itd-api/integrations/) | browser proxy и Turnstile |
90
+ | [Плагины](https://kiowdev.github.io/itd-api/plugins/) | cache, crypto и создание плагина |
91
+ | [Справочник API](https://kiowdev.github.io/itd-api/reference/) | ресурсы, методы, типы, ошибки и билдеры |
438
92
 
439
- Через тот же `fetch` пойдут авторизация, cookie, очередь, повторы и поток уведомлений.
440
- Только для Node/Bun/Deno. Подключение proxy и Turnstile разобрано в
441
- [руководстве по интеграциям](./guides/integrations/README.md), параметры транспорта — в
442
- [README пакета](./proxy/README.md).
93
+ ## Совместимость
443
94
 
444
- ---
95
+ | Среда | Поддержка |
96
+ |---|---|
97
+ | Node.js 18+ | полная, включая файловую точку входа `itd-api/node` |
98
+ | Bun, Deno | полная |
99
+ | Браузер | кроме файловой системы; хранилище сессии — `itd-api/web`; для основного API нужен server-side proxy из-за CORS |
100
+ | React Native | полная; realtime переключается на polling без потокового чтения |
445
101
 
446
- ## Плагины
102
+ TypeScript 5.0+. Пакет проверяется в Node.js 18, 20, 22, 24 и 26, а корректность
103
+ публикации — через `publint` и `@arethetypeswrong/cli`.
447
104
 
448
- Плагин оборачивает запросы и ответы сразу всех ресурсов:
105
+ ## Сеть и доверие
449
106
 
450
- ```ts
451
- import { ItdClient } from 'itd-api';
452
- import { cache } from '@itd-api/cache';
453
-
454
- const itd = new ItdClient({ auth: token });
455
- itd.use(
456
- cache({
457
- ttl: 60_000,
458
- routes: ['users.get', 'posts.get', 'posts.list'],
459
- }),
460
- );
461
- ```
107
+ По умолчанию основной пакет обращается ровно к двум хостам:
462
108
 
463
- Плагины поддерживают зависимости и декларативный порядок, хуки каждой сетевой попытки,
464
- отключение через `unuse()` и асинхронный teardown через `dispose()`. Официальные плагины
465
- Cache и Crypto, полный контракт `ItdPlugin`, собственные опции и структура пакета описаны в
466
- [руководстве по плагинам](./guides/plugins/README.md).
109
+ | Хост | Назначение | Автоматическая передача Bearer-токена |
110
+ |---|---|---|
111
+ | `https://xn--d1ah4a.com` (`итд.com`) | REST API, авторизация и realtime | да, для защищённых REST-методов и realtime |
112
+ | `https://xn--80a7abcbg.xn--d1ah4a.com` (`статус.итд.com`) | публичное состояние сервисов | нет |
467
113
 
468
- ---
114
+ Опциональный `@itd-api/turnstile` дополнительно загружает виджет с
115
+ `https://challenges.cloudflare.com`; пакет не передаёт пароль странице браузера.
116
+ `@itd-api/cache` и `@itd-api/crypto` сами не создают сетевые запросы, а
117
+ `@itd-api/proxy` использует только адрес proxy, заданный пользователем.
469
118
 
470
- ## Что доступно
119
+ Пользовательские настройки меняют границу доверия:
471
120
 
472
- | Раздел | Методы |
121
+ | Настройка | Последствие |
473
122
  |---|---|
474
- | `itd.auth` | вход, регистрация, OTP, пароли, сессии, OAuth-ссылки |
475
- | `itd.users` | профили, подписки, блокировки, приватность, значки |
476
- | `itd.posts` | лента, публикация, реакции, репосты, опросы, комментарии к постам |
477
- | `itd.comments` | ответы, редактирование, реакции |
478
- | `itd.notifications` | список, счётчик, отметки о прочтении, настройки |
479
- | `itd.files` | загрузка медиа |
480
- | `itd.hashtags` · `itd.search` | хэштеги, трендовые, глобальный поиск |
481
- | `itd.reports` · `itd.verification` | жалобы, заявка на верификацию |
482
- | `itd.subscription` · `itd.platform` | подписка, способы оплаты, анонсы, статус сервисов |
483
- | `itd.realtime()` | поток уведомлений |
484
- | `itd.use()` · `itd.unuse()` | управляемые плагины: обёртки, hooks и teardown |
485
- | `itd.request()` | произвольный запрос, если метода ещё нет |
486
- | `ItdAccounts` | несколько аккаунтов с общим хранилищем сессий |
487
-
488
- Все методы и типы каждого раздела с сигнатурами — в [справочнике](./guides/reference/README.md).
489
-
490
- Метода не хватает или ответ разошёлся с документацией — есть запасной путь:
491
-
492
- ```ts
493
- const raw = await itd.request({ method: 'GET', path: '/api/что-то', raw: true });
494
- ```
123
+ | `baseUrl` | становится основным API-хостом; на него идут авторизация, сессия, защищённые запросы и realtime |
124
+ | `fetch` | получает URL, заголовки и body всех запросов клиента; передавайте только доверенную реализацию |
125
+ | `proxyFetch(...)` | направляет запросы через указанный вами proxy, которому будут доступны соединения с API |
126
+ | `defineService({ auth: true })` | явно разрешает отправлять Bearer-токен на хост этого сервиса |
127
+ | `request({ baseUrl })` | внешний хост не получает Bearer автоматически; `skipAuth: false` явно разрешает его передачу |
495
128
 
496
- ---
129
+ Уязвимости следует отправлять приватно по
130
+ [политике безопасности](./.github/SECURITY.md).
497
131
 
498
- ## Совместимость
132
+ ## Известные ограничения платформы
499
133
 
500
- | Среда | Поддержка |
134
+ | Ограничение | Что учитывать |
501
135
  |---|---|
502
- | Node.js 18+ | полная, включая `itd-api/node` |
503
- | Bun, Deno | полная |
504
- | Браузер | всё, кроме файловой системы; нужен прокси из-за CORS |
505
- | React Native | полная; realtime автоматически переключается на опрос, если нет потокового чтения |
136
+ | CORS основного API | браузерному приложению нужен собственный серверный proxy; [подробнее](https://kiowdev.github.io/itd-api/integrations/#браузер-и-cors) |
137
+ | Подписчики, подписки и блокировки | сервер возвращает только первые 20 записей; [подробнее](https://kiowdev.github.io/itd-api/reference/users) |
138
+ | Посты пользователя | `posts.byUser()` возвращает стену, включая чужие публикации на ней; [подробнее](https://kiowdev.github.io/itd-api/reference/posts) |
139
+ | Rate limiting | лимиты различаются по endpoint, а сервер не сообщает время сброса окна; [настройка очереди](https://kiowdev.github.io/itd-api/configuration/#очередь-и-rate-limiting) |
506
140
 
507
- TypeScript 5.0+. Пакет собран в ESM и CommonJS, типы корректны во всех режимах
508
- резолвинга (проверено `publint` и `@arethetypeswrong/cli`).
141
+ Матрица известных маршрутов, wire-контрактов и статуса поддержки находится в
142
+ [справочнике endpoint](https://kiowdev.github.io/itd-api/reference/endpoints).
509
143
 
510
- ---
144
+ ## Проект
511
145
 
512
- ## Разработка
146
+ - [CI](https://github.com/KiowDev/itd-api/actions/workflows/ci.yml)
147
+ - [История релизов](https://github.com/KiowDev/itd-api/releases)
148
+ - [Как внести вклад](./.github/CONTRIBUTING.md)
149
+ - [Политика безопасности](./.github/SECURITY.md)
150
+ - [MIT License](./LICENSE) и [NOTICE](./NOTICE)
513
151
 
514
- ```bash
515
- npm install
516
- npm test # 611 тестов
517
- npm run test:all # вместе с пакетами workspace
518
- npm run typecheck
519
- npm run lint
520
- npm run build
521
- npm run check:pack # publint + attw
522
- npm run docs # сайт документации из TSDoc
523
- ```
524
-
525
- Тесты не обращаются к сети: `fetch` подменяется через опцию конфигурации.
526
-
527
- ---
152
+ Публикация `itd-api@0.1.0` содержит проверяемое
153
+ [npm provenance](https://registry.npmjs.org/-/npm/v1/attestations/itd-api@0.1.0).
528
154
 
529
155
  ## Лицензия
530
156
 
531
- MIT. Библиотека не связана с итд.com и разработана независимо.
532
-
533
- Сторонний код, включённый в сборку, перечислен в [NOTICE](./NOTICE).
157
+ MIT © Kiow. Проект использует независимо восстановленные сведения о публичном
158
+ интерфейсе платформы; товарные знаки и сама платформа принадлежат их владельцам.