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